Skip to content

Commit ac525de

Browse files
committed
feat: 离线激活移植
1 parent b889e98 commit ac525de

8 files changed

Lines changed: 106 additions & 12 deletions

File tree

MaiChartManager/Controllers/App/AppLicenseController.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,16 @@ public async Task<RequestPurchaseResult> RequestPurchase()
2020

2121
return new RequestPurchaseResult(null, res.Status);
2222
}
23+
24+
[HttpPost]
25+
public async Task<bool> VerifyOfflineKey([FromBody] string key)
26+
{
27+
var result = await OfflineReg.VerifyAsync(key);
28+
if (!result.IsValid) return false;
29+
30+
StaticSettings.Config.OfflineKey = key;
31+
StaticSettings.Config.Save();
32+
IapManager.SetOfflineLicenseActive();
33+
return true;
34+
}
2335
}

MaiChartManager/Front/src/client/apiGen.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,23 @@ export class Api<
765765
...params,
766766
}),
767767

768+
/**
769+
* No description
770+
*
771+
* @tags AppLicense
772+
* @name VerifyOfflineKey
773+
* @request POST:/MaiChartManagerServlet/VerifyOfflineKeyApi
774+
*/
775+
VerifyOfflineKey: (data: string, params: RequestParams = {}) =>
776+
this.request<boolean, any>({
777+
path: `/MaiChartManagerServlet/VerifyOfflineKeyApi`,
778+
method: "POST",
779+
body: data,
780+
type: ContentType.Json,
781+
format: "json",
782+
...params,
783+
}),
784+
768785
/**
769786
* No description
770787
*

MaiChartManager/Front/src/components/VersionInfo/index.tsx

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,52 @@ import { computed, defineComponent, ref } from "vue";
22
import { Popover, Qrcode } from "@munet/ui";
33
import AppIcon from '@/components/AppIcon';
44
import '@fontsource/nerko-one'
5-
import { version } from "@/store/refs";
5+
import { updateVersion, version } from "@/store/refs";
66
import StorePurchaseButton from "@/components/StorePurchaseButton";
77
import AfdianIcon from "@/icons/afdian.svg";
88
import { HardwareAccelerationStatus, LicenseStatus } from "@/client/apiGen";
99
import { 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

1213
export 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
})

MaiChartManager/Front/src/locales/en.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ about:
528528
h264Encoder: H264 Encoder
529529
premiumActive: Thank you for your support, premium features activated!
530530
continueSupport: Click here to continue supporting
531+
offlineActivation: Offline Activation
532+
enterActivationCode: Please enter activation code
533+
activationCodeInvalid: Invalid activation code
534+
activationSuccess: Premium features activated, thank you!
531535
jacket:
532536
upload: Upload Jacket
533537
select: Select Jacket

MaiChartManager/Front/src/locales/zh-TW.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ about:
487487
h264Encoder: H264 編碼器
488488
premiumActive: 感謝你的支援,贊助版功能已啟用!
489489
continueSupport: 如果還想繼續贊助請點擊
490+
offlineActivation: 離線啟用
491+
enterActivationCode: 請輸入啟用碼
492+
activationCodeInvalid: 啟用碼無效
493+
activationSuccess: 贊助版功能已啟用,謝謝你!
490494
jacket:
491495
upload: 上傳封面
492496
select: 選擇封面

MaiChartManager/Front/src/locales/zh.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ about:
493493
h264Encoder: H264 编码器
494494
premiumActive: 感谢你的支持,赞助版功能已启用!
495495
continueSupport: 如果还想继续赞助请点击
496+
offlineActivation: 离线激活
497+
enterActivationCode: 请输入激活码
498+
activationCodeInvalid: 激活码无效
499+
activationSuccess: 赞助版功能已启用,谢谢你!
496500
jacket:
497501
upload: 上传封面
498502
select: 选择封面

MaiChartManager/IapManager.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public static void BindToForm(Form form)
6161
WinRT.Interop.InitializeWithWindow.Initialize(StoreContext, form.Handle);
6262
}
6363

64+
public static void SetOfflineLicenseActive()
65+
{
66+
License = LicenseStatus.Active;
67+
}
68+
6469
public static async Task<StorePurchaseResult> Purchase()
6570
{
6671
if (_form.WindowState == FormWindowState.Minimized)

MaiChartManager/MaiChartManager.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
</PropertyGroup>
2929
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
3030
<IsPublishable>False</IsPublishable>
31-
<DefineConstants>TRACE;CRACK</DefineConstants>
31+
<DefineConstants>TRACE</DefineConstants>
3232
<OutputType>Exe</OutputType>
3333
</PropertyGroup>
3434
<PropertyGroup Condition="'$(Configuration)'=='Release'">

0 commit comments

Comments
 (0)