@@ -2,20 +2,52 @@ import { computed, defineComponent, ref } from "vue";
22import { Popover , Qrcode } from "@munet/ui" ;
33import AppIcon from '@/components/AppIcon' ;
44import '@fontsource/nerko-one'
5- import { version } from "@/store/refs" ;
5+ import { updateVersion , version } from "@/store/refs" ;
66import StorePurchaseButton from "@/components/StorePurchaseButton" ;
77import AfdianIcon from "@/icons/afdian.svg" ;
88import { HardwareAccelerationStatus , LicenseStatus } from "@/client/apiGen" ;
99import { useI18n } from 'vue-i18n' ;
10- import { Modal , theme } from "@munet/ui" ;
10+ import { Modal , TextInput , Button , addToast , theme } from "@munet/ui" ;
11+ import api from "@/client/api" ;
1112
1213export default defineComponent ( {
1314 setup ( props ) {
1415 const show = ref ( false ) ;
16+ const showOfflineActivation = ref ( false ) ;
17+ const activationCode = ref ( '' ) ;
18+ const activating = ref ( false ) ;
1519 const displayVersion = computed ( ( ) => version . value ?. version ?. split ( '+' ) [ 0 ] ) ;
1620 const { t } = useI18n ( ) ;
1721
18- return ( ) => version . value && < div class = { 'w-15 py-1 flex items-center justify-center rounded-md cursor-pointer transition-all duration-200 bg-avatarMenuButton text-3.5 shrink-0' } onClick = { ( ) => show . value = true } >
22+ const onVersionClick = ( e : MouseEvent ) => {
23+ if ( e . shiftKey && version . value ?. license !== LicenseStatus . Active ) {
24+ showOfflineActivation . value = true ;
25+ activationCode . value = '' ;
26+ return ;
27+ }
28+ show . value = true ;
29+ } ;
30+
31+ const submitOfflineKey = async ( ) => {
32+ if ( ! activationCode . value . trim ( ) || activating . value ) return ;
33+ activating . value = true ;
34+ try {
35+ const { data : result } = await api . VerifyOfflineKey ( activationCode . value . trim ( ) ) ;
36+ if ( result ) {
37+ addToast ( { message : t ( 'about.activationSuccess' ) , type : 'success' } ) ;
38+ showOfflineActivation . value = false ;
39+ await updateVersion ( ) ;
40+ } else {
41+ addToast ( { message : t ( 'about.activationCodeInvalid' ) , type : 'error' } ) ;
42+ }
43+ } catch {
44+ addToast ( { message : t ( 'about.activationCodeInvalid' ) , type : 'error' } ) ;
45+ } finally {
46+ activating . value = false ;
47+ }
48+ } ;
49+
50+ return ( ) => version . value && < div class = { 'w-15 py-1 flex items-center justify-center rounded-md cursor-pointer transition-all duration-200 bg-avatarMenuButton text-3.5 shrink-0' } onClick = { onVersionClick } >
1951 v{ displayVersion . value }
2052
2153 < Modal
@@ -26,14 +58,8 @@ export default defineComponent({
2658 < div class = "flex flex-col gap-2" style = { { containerType : 'inline-size' } } >
2759 < AppIcon class = "mb-10 max-[540px]:scale-75" />
2860 < div class = "flex justify-center gap-1 text-10 c-gray-4" >
29- < a class = "i-mdi-github hover:c-#1f2328 transition-300" href = "https://github.com/clansty/MaiChartManager" target = "_blank" />
30- < a class = "i-ic-baseline-telegram hover:c-#39a6e6 transition-300" href = "https://t.me/MaiChartManager" target = "_blank" />
31- < Popover trigger = "hover" >
32- { {
33- trigger : ( ) => < div class = "i-ri-qq-fill hover:c-#e31b25 transition-300" /> ,
34- default : ( ) => < div > < Qrcode value = "https://qm.qq.com/q/U3gT7CDuy6" /> </ div >
35- } }
36- </ Popover >
61+ < a class = "i-mdi-github hover:c-[var(--text-color)] transition-300" href = "https://github.com/clansty/MaiChartManager" target = "_blank" />
62+ < a class = "i-ri-qq-fill hover:c-[var(--text-color)] transition-300" href = "https://qm.qq.com/q/U3gT7CDuy6" target = "_blank" />
3763 </ div >
3864 < div >
3965 { t ( 'about.version' ) } : v{ version . value . version }
@@ -77,6 +103,28 @@ export default defineComponent({
77103 </ div >
78104 </ div >
79105 </ Modal >
106+
107+ < Modal
108+ width = "30em"
109+ title = { t ( 'about.offlineActivation' ) }
110+ v-model :show = { showOfflineActivation . value }
111+ > { {
112+ default : ( ) => < div class = "flex flex-col gap-4" >
113+ < div > { t ( 'about.enterActivationCode' ) } </ div >
114+ < TextInput
115+ v-model :value = { activationCode . value }
116+ onEnterPressed = { submitOfflineKey }
117+ disabled = { activating . value }
118+ />
119+ </ div > ,
120+ actions : ( ) => < Button
121+ onClick = { submitOfflineKey }
122+ disabled = { ! activationCode . value . trim ( ) || activating . value }
123+ ing = { activating . value }
124+ >
125+ { t ( 'common.confirm' ) }
126+ </ Button > ,
127+ } } </ Modal >
80128 </ div > ;
81129 }
82130} )
0 commit comments