Compare commits

..

147 Commits

Author SHA1 Message Date
qhy040404
a2586b0ef2 fix different theme between window and dialog 2024-03-15 20:32:16 +08:00
DismissedLight
eee84a338e significantly reduce uniformstaggeredlayout resize lag 2024-03-15 20:24:32 +08:00
Lightczx
be30362b52 uniformstaggeredlayout optimization 2024-03-15 17:18:25 +08:00
Lightczx
38f36bbb82 fix gachalog page closing crash 2024-03-15 14:21:38 +08:00
Lightczx
704866b16a update dependency 2024-03-15 13:43:55 +08:00
Lightczx
ca9783bc1b corner radius on auto suggest tokenbox 2024-03-15 10:54:06 +08:00
DismissedLight
6e8e151fff fix unlocking fps 2024-03-14 20:32:06 +08:00
DismissedLight
b98dc9f5d3 fix unlocking fps 2024-03-14 19:58:01 +08:00
Masterain
206100d8ef New Crowdin updates (#1477) 2024-03-14 14:41:52 +08:00
Lightczx
1a74c7ca96 fix #1476 2024-03-14 11:24:55 +08:00
DismissedLight
88528fa28d hide zero count section 2024-03-13 21:18:11 +08:00
DismissedLight
263cea9225 Merge pull request #1475 from DGP-Studio/fix/token_ui 2024-03-13 21:09:13 +08:00
Lightczx
2879bd653a add chronicled wish cloud statistics 2024-03-13 17:25:42 +08:00
qhy040404
3d061e3bdb adjust ui 2024-03-13 16:52:46 +08:00
qhy040404
022527829e refine wiki token ui 2 2024-03-13 16:39:16 +08:00
qhy040404
0fcf10dfa7 refine wiki token ui 2024-03-13 16:16:44 +08:00
Lightczx
7fc6ecc3c3 fix gachalog overview scrollbar margin 2024-03-13 15:17:40 +08:00
DismissedLight
fad5f8ada3 Merge pull request #1473 from DGP-Studio/develop 2024-03-13 14:15:42 +08:00
Lightczx
238c2036f6 bump version 2024-03-13 14:03:49 +08:00
DismissedLight
e48f740e46 Merge pull request #1472 from DGP-Studio/l10n_develop 2024-03-13 13:57:16 +08:00
Masterain
8574a3d825 New translations sh.resx (English) 2024-03-12 22:56:21 -07:00
DismissedLight
08f27e8ee7 Merge pull request #1463 from DGP-Studio/l10n_develop 2024-03-13 13:55:23 +08:00
Lightczx
c8b3779d97 compat UIGF v3.0 2024-03-13 11:43:39 +08:00
Lightczx
54cbd9dfb9 fix web cache query provider 2024-03-13 10:45:34 +08:00
DismissedLight
65517abcb4 Merge pull request #1469 from DGP-Studio/fix/titlebar_darkmode 2024-03-13 09:04:26 +08:00
qhy040404
87c3043fd9 fix wrong titlebar color when manually manually setting the color theme 2024-03-12 22:34:32 +08:00
DismissedLight
762bc14b88 adjust ui for city banner 2024-03-12 21:35:06 +08:00
DismissedLight
51dfc7020f Merge pull request #1466 from DGP-Studio/dependabot/nuget/src/Snap.Hutao/develop/packages-ba3ce57765 2024-03-12 09:37:41 +08:00
dependabot[bot]
47dda1bebc Bump the packages group in /src/Snap.Hutao with 1 update
Bumps the packages group in /src/Snap.Hutao with 1 update: [MSTest.TestAdapter](https://github.com/microsoft/testfx).


Updates `MSTest.TestAdapter` from 3.2.1 to 3.2.2
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.2.1...v3.2.2)

---
updated-dependencies:
- dependency-name: MSTest.TestAdapter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: packages
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 07:12:02 +00:00
Lightczx
1a300e8b9c fix predownload latest path and name 2024-03-11 11:47:43 +08:00
Lightczx
16e8a17614 disable launchoptions by default 2024-03-11 11:24:41 +08:00
Lightczx
a5c75f9465 revert BGI process waitforinputidle 2024-03-11 11:16:23 +08:00
Lightczx
0cb59808a1 refactor unlocking fps 2024-03-11 11:01:57 +08:00
Masterain
80439ed673 New translations sh.resx (Chinese Traditional) 2024-03-10 18:37:38 -07:00
Lightczx
d632002e4b Sync Scighost/Starward#692 2024-03-11 09:33:21 +08:00
DismissedLight
cf6a972d55 Update FeedbackPage.xaml 2024-03-10 22:39:11 +08:00
DismissedLight
e1a976f02d fix theme switch dropping shadow 2024-03-10 22:28:03 +08:00
DismissedLight
dbedc2a00d fix equal panel spacing 2024-03-10 22:23:10 +08:00
DismissedLight
03312f1d52 Merge pull request #1464 from DGP-Studio/fix/horizontal_equal_panel 2024-03-10 21:37:03 +08:00
qhy040404
47f29de9c6 fix measure 2024-03-10 21:30:15 +08:00
Masterain
708da5769a New translations sh.resx (Indonesian) 2024-03-10 01:31:59 -08:00
Masterain
8bce2d3b28 New translations sh.resx (English) 2024-03-10 01:31:58 -08:00
Masterain
5252e7b451 New translations sh.resx (Chinese Traditional) 2024-03-10 01:31:56 -08:00
Masterain
2f5d884425 New translations sh.resx (Russian) 2024-03-10 01:31:55 -08:00
Masterain
5aea3695b9 New translations sh.resx (Portuguese) 2024-03-10 01:31:54 -08:00
Masterain
462e570bc1 New translations sh.resx (Korean) 2024-03-10 01:31:53 -08:00
Masterain
511d113c65 New translations sh.resx (Japanese) 2024-03-10 01:31:52 -08:00
Lightczx
2a5e7e0136 temp progress 2024-03-10 17:30:57 +08:00
Lightczx
177e7a6233 fix #1459 2024-03-10 14:29:57 +08:00
DismissedLight
bd09b303ab Merge pull request #1456 from DGP-Studio/fix/darkmode
fix #1434
2024-03-10 14:13:10 +08:00
qhy040404
5538b74939 remove WindowOptions.UseSystemBackdrop 2024-03-10 12:16:30 +08:00
qhy040404
fda289421b code style 2024-03-10 12:16:30 +08:00
qhy040404
c0abe7f7c5 fix #1434 2024-03-10 12:16:30 +08:00
DismissedLight
e95732d448 Merge pull request #1454 from DGP-Studio/fix/navigate_crash 2024-03-10 12:10:13 +08:00
DismissedLight
9e52a87d11 Merge pull request #1457 from DGP-Studio/fix/composition_image_delay 2024-03-10 12:03:29 +08:00
qhy040404
66bce570cc Update build.cake 2024-03-10 10:46:46 +08:00
qhy040404
a5091134b0 fix typo 2024-03-10 10:46:46 +08:00
qhy040404
59c9845ad0 fix navigation crash 2024-03-10 10:46:46 +08:00
qhy040404
2db829e1e2 add delay to fix blink again 2024-03-10 10:46:37 +08:00
DismissedLight
1a64328270 Update GachaTypeComparer.cs 2024-03-09 16:48:37 +08:00
DismissedLight
1c847626c7 Merge pull request #1453 from Mikachu2333/develop 2024-03-08 16:12:08 +08:00
LinkChou
062a09c632 correct 2024-03-08 12:16:55 +08:00
LinkChou
7433c1832a add tips about 'test binary package' 2024-03-07 19:41:42 +08:00
Lightczx
252649f28c fix #1429 2024-03-07 16:56:18 +08:00
Lightczx
75dda65c55 impl #1432 2024-03-07 16:53:25 +08:00
Lightczx
a9b165882f fix #1433 2024-03-07 16:49:15 +08:00
Lightczx
e41e913558 code style 2024-03-07 16:44:06 +08:00
Lightczx
2d9125d369 fix #1443 2024-03-07 16:37:26 +08:00
DismissedLight
2c7a6d152c Merge pull request #1445 from DGP-Studio/feat/1434 2024-03-07 16:27:54 +08:00
Lightczx
0c4c509fd6 code style 2024-03-07 16:27:01 +08:00
DismissedLight
7dba08451c Merge branch 'develop' into feat/1434 2024-03-07 16:20:48 +08:00
DismissedLight
a55cb89fe8 Merge pull request #1452 from DGP-Studio/fix/layoutcycle_2 2024-03-07 16:20:17 +08:00
Lightczx
4aa9557526 code style 2024-03-07 16:20:10 +08:00
qhy040404
38577f9813 apply suggestion 2024-03-07 13:37:22 +08:00
qhy040404
91361ddab5 resolve review 2024-03-07 13:26:35 +08:00
qhy040404
5ced8f6c71 impl #1434 2024-03-07 13:26:35 +08:00
qhy040404
55706e68f0 use self impl EqualPanel to fix layout cycle 2024-03-07 13:25:03 +08:00
qhy040404
63c4bb6a23 fix command bar blink 2024-03-07 13:00:52 +08:00
Lightczx
baa4b88622 refine spiralabyss team ui 2024-03-06 17:11:23 +08:00
DismissedLight
de2ce0db63 Merge pull request #1444 from DGP-Studio/feat/refresh_ui_for_team_appearence 2024-03-06 15:47:45 +08:00
Lightczx
6cbf8ca918 code style 2024-03-06 15:43:46 +08:00
DismissedLight
df125904a6 Merge branch 'develop' into feat/refresh_ui_for_team_appearence 2024-03-06 14:20:36 +08:00
Lightczx
1bad9d0928 fix #1449 2024-03-06 14:19:04 +08:00
DismissedLight
a762166db4 Merge branch 'develop' into feat/refresh_ui_for_team_appearence 2024-03-06 14:09:23 +08:00
DismissedLight
f432e5ba42 Merge pull request #1437 from DGP-Studio/activity-city-banner-compat 2024-03-06 14:07:47 +08:00
Lightczx
46dd4db25c fixup endid indexer setter 2024-03-06 14:04:04 +08:00
Lightczx
2e685182e6 fixup endid indexer getter 2024-03-06 14:01:53 +08:00
Lightczx
4f1bbd2e89 typo fix 2024-03-06 13:58:34 +08:00
qhy040404
0f5b6dda16 refresh ui for team appearance 2024-03-06 12:02:56 +08:00
Lightczx
4c38bb528f basic support 2024-03-06 11:57:37 +08:00
Lightczx
44e7f7482c minor adjustment 2024-03-06 11:55:37 +08:00
Lightczx
8a2fa3c701 factory completed 2024-03-06 11:55:37 +08:00
DismissedLight
6e10819609 Merge pull request #1441 from DGP-Studio/dependabot/nuget/src/Snap.Hutao/develop/packages-15667d2017 2024-03-06 09:16:27 +08:00
dependabot[bot]
c1b838bd97 Bump the packages group in /src/Snap.Hutao with 2 updates
Bumps the packages group in /src/Snap.Hutao with 2 updates: [MSTest.TestAdapter](https://github.com/microsoft/testfx) and [MSTest.TestFramework](https://github.com/microsoft/testfx).


Updates `MSTest.TestAdapter` from 3.2.1 to 3.2.2
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.2.1...v3.2.2)

Updates `MSTest.TestFramework` from 3.2.1 to 3.2.2
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.2.1...v3.2.2)

---
updated-dependencies:
- dependency-name: MSTest.TestAdapter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: packages
- dependency-name: MSTest.TestFramework
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: packages
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-05 16:03:28 +00:00
DismissedLight
268c4c6c71 Merge pull request #1421 from DGP-Studio/feat/wikisuggestbox 2024-03-05 23:59:39 +08:00
DismissedLight
59dabaa5be code style 2024-03-05 23:59:23 +08:00
DismissedLight
dcac7ac792 Merge pull request #1431 from DGP-Studio/fix/minor 2024-03-05 21:45:00 +08:00
qhy040404
2ad6dad282 minor fix 2024-03-05 17:28:01 +08:00
qhy040404
4185336556 minor ui adjustment 2024-03-05 17:10:31 +08:00
qhy040404
15a627e50a init all tokens first 2024-03-05 16:55:28 +08:00
qhy040404
2ea53fd39d Frozen Dictionaries 2024-03-04 18:02:00 +08:00
qhy040404
6de3cba550 remove unused code 2024-03-04 00:09:38 +08:00
qhy040404
03c1bacfe9 maybe code style 2024-03-04 00:01:52 +08:00
qhy040404
d157476a9a minor fix 2024-03-03 21:37:44 +08:00
qhy040404
e35c03ac90 support or in wiki search 2024-03-03 21:03:28 +08:00
qhy040404
9619835cc2 migrate to TokenizingTextBox 2024-03-03 16:23:25 +08:00
qhy040404
6936a30a74 finish suggestion methods 2024-03-03 16:23:19 +08:00
Lightczx
506d198167 update to was 1.5 2024-03-01 09:30:43 +08:00
DismissedLight
9c2131cb9d Merge pull request #1426 from DGP-Studio/dependabot/nuget/src/Snap.Hutao/develop/packages-dcc47c4d6c 2024-02-27 09:21:58 +08:00
DismissedLight
896e3d49f2 Merge branch 'develop' into dependabot/nuget/src/Snap.Hutao/develop/packages-dcc47c4d6c 2024-02-27 09:21:30 +08:00
DismissedLight
7da24790c4 Merge pull request #1423 from Masterain98/main 2024-02-26 17:02:25 +08:00
DismissedLight
ebf163f200 Merge branch 'develop' into dependabot/nuget/src/Snap.Hutao/develop/packages-dcc47c4d6c 2024-02-26 16:59:23 +08:00
Lightczx
26043a6a73 Add furniture data struct 2024-02-26 16:35:36 +08:00
Masterain
ad67001556 Update LaunchGame.png 2024-02-26 15:28:25 +08:00
dependabot[bot]
428cd35a7f Bump the packages group in /src/Snap.Hutao with 3 updates
Bumps the packages group in /src/Snap.Hutao with 3 updates: [MSTest.TestAdapter](https://github.com/microsoft/testfx), [MSTest.TestFramework](https://github.com/microsoft/testfx) and [coverlet.collector](https://github.com/coverlet-coverage/coverlet).


Updates `MSTest.TestAdapter` from 3.2.1 to 3.2.2
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.2.1...v3.2.2)

Updates `MSTest.TestFramework` from 3.2.1 to 3.2.2
- [Release notes](https://github.com/microsoft/testfx/releases)
- [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md)
- [Commits](https://github.com/microsoft/testfx/compare/v3.2.1...v3.2.2)

Updates `coverlet.collector` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v6.0.0...v6.0.1)

---
updated-dependencies:
- dependency-name: MSTest.TestAdapter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: packages
- dependency-name: MSTest.TestFramework
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: packages
- dependency-name: coverlet.collector
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: packages
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 07:16:52 +00:00
qhy040404
1cf3450264 fix static resource download 2024-02-25 23:29:45 +08:00
DismissedLight
1849ac16da adjust regex 2024-02-25 16:23:45 +08:00
DismissedLight
4e9d87af50 fix ja-jp announcement 2024-02-25 15:53:09 +08:00
DismissedLight
eb125e547f add mask when no backdrop 2024-02-24 20:24:46 +08:00
Lightczx
c17798a8c9 code style 2024-02-23 10:22:24 +08:00
DismissedLight
fa9b39d134 Merge pull request #1412 from DGP-Studio/fix/hotkey_notify 2024-02-23 09:42:10 +08:00
qhy040404
8dc85c7a25 prompt if hotkey not registered 2024-02-23 09:39:50 +08:00
DismissedLight
5845c718e1 Merge pull request #1419 from DGP-Studio/feat/real_time_bg 2024-02-23 09:36:25 +08:00
Lightczx
0c093851ed code style 2024-02-23 09:33:55 +08:00
qhy040404
04c187aa16 real time refresh background 2024-02-22 22:34:12 +08:00
Lightczx
25cf9f5356 code style 2024-02-22 10:26:43 +08:00
DismissedLight
c30c8b114a re-enable backdrop 2024-02-21 23:38:57 +08:00
DismissedLight
7a572631e9 Merge pull request #1415 from DGP-Studio/develop 2024-02-21 20:35:56 +08:00
DismissedLight
41f5a04e5a Merge branch 'main' into develop 2024-02-21 20:35:38 +08:00
DismissedLight
4f26d6efc2 update package version 2024-02-21 20:33:18 +08:00
Masterain
0d6b5e595e New Crowdin updates (#1413) 2024-02-21 20:29:41 +08:00
DismissedLight
e30bebd1a3 Update StatisticsCard.xaml 2024-02-21 20:25:56 +08:00
Masterain
ffb34c0e93 New Crowdin updates (#1411) 2024-02-21 20:25:12 +08:00
Lightczx
35b35ab649 minor fix 5 2024-02-21 16:29:30 +08:00
Lightczx
f067350cd8 minor fix 2024-02-21 15:28:05 +08:00
Lightczx
14648dafe8 adjust language order 2024-02-21 14:04:24 +08:00
Lightczx
7a7d81cfee add static resource hint for more situation 2024-02-21 13:55:07 +08:00
Lightczx
30c055e7ba impl #1373 #1389 2024-02-21 11:57:41 +08:00
qhy040404
6a922d9db6 更新 alpha.yml 2024-02-21 09:52:20 +08:00
DismissedLight
02a6e64a8c Merge pull request #1408 from DGP-Studio/fix/launch 2024-02-20 14:40:57 +08:00
qhy040404
85bcf37b1b Update alpha.yml 2024-02-20 10:43:27 +08:00
qhy040404
465c7035c0 Update alpha.yml 2024-02-20 10:31:23 +08:00
qhy040404
6241bbc997 Setup dependabot for actions 2024-02-19 17:57:17 +08:00
qhy040404
afbd8ec6ad Revert "Update alpha.yml"
This reverts commit 288cc841ac.
2024-02-19 17:41:32 +08:00
qhy040404
288cc841ac Update alpha.yml 2024-02-19 17:26:00 +08:00
qhy040404
e1784e2078 Update issue templates 2024-02-18 21:16:44 +08:00
qhy040404
635b52980b Update .gitlab-ci.yml 2024-02-07 21:13:59 +08:00
212 changed files with 4094 additions and 2075 deletions

View File

@@ -18,7 +18,7 @@ body:
options:
- label: 我已阅读 Snap Hutao 文档中的[常见问题](https://hut.ao/advanced/FAQ.html)和[常见程序异常](https://hut.ao/advanced/exceptions.html),我的问题没有在文档中得到解答
required: true
- label: 我知道文档站的导航栏中有**搜索功能**,且已经搜索过相关关键词
required: true
@@ -29,12 +29,12 @@ body:
id: winver
attributes:
label: Windows 版本
description: |
description: |
`Win+R` 输入 `winver` 回车后在打开的窗口第二行可以找到
placeholder: 22000.556
validations:
required: true
- type: input
id: shver
attributes:
@@ -48,10 +48,10 @@ body:
id: deviceid
attributes:
label: 设备 ID
description: |
description: |
在胡桃工具箱的反馈中心界面,你可以找到并复制你的设备 ID
如果你的问题涉及程序崩溃,请填写该项,这将有助于我们定位问题
如果你的程序已经无法启动,请下载并运行[诊断工具](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.DiagTools.exe),它将显示你的设备 ID
如果你的程序已经无法启动,请下载并运行[诊断工具](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.Diagnostic.Tooling.exe),它将显示你的设备 ID
validations:
required: false
@@ -79,7 +79,7 @@ body:
- 公告
- 其它
validations:
required: true
required: true
- type: textarea
id: what-happened
@@ -107,4 +107,3 @@ body:
options:
- label: 我认为上述的描述已经足以详细,以允许开发人员能复现该问题
required: true

View File

@@ -18,7 +18,7 @@ body:
options:
- label: I have read [FAQ page](https://hut.ao/advanced/FAQ.html) and [Exception page](https://hut.ao/advanced/exceptions.html) in Snap Hutao document, and my issue is not answered
required: true
- label: I and tried **search feature** in Snap Hutao document site, and no associated article
required: true
@@ -29,12 +29,12 @@ body:
id: winver
attributes:
label: Windows Version
description: |
description: |
Use `Win+R` and input `winver`, Windows build version is usually at the second line
placeholder: e.g. 22000.556
validations:
required: true
- type: input
id: shver
attributes:
@@ -48,10 +48,10 @@ body:
id: deviceid
attributes:
label: Device ID
description: |
description: |
In Snap Hutao's Feedback Center, you can find and copy your device ID
If your issue is about program crash, please fill this so we can dump the log and locate the source easier
If your program cannot startup, please download and run [Diagnosis Tool](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.DiagTools.exe), it will shows your device ID.
If your program cannot startup, please download and run [Diagnostic Tooling](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.Diagnostic.Tooling.exe), it will shows your device ID.
validations:
required: false
@@ -74,12 +74,12 @@ body:
- User Interface
- Snap Hutao Cloud
- Snap Hutao Account
- Checkin
- Checkin
- Wiki
- Announcement
- Other
validations:
required: true
required: true
- type: textarea
id: what-happened
@@ -107,4 +107,3 @@ body:
options:
- label: I believe the description above is detail enough to allow developers to reproduce the issue
required: true

View File

@@ -13,4 +13,8 @@ updates:
groups:
packages:
patterns:
- "*"
- "*"
- package-ecosystem: "github-actions"
directory: "/.github/workflows" # GitHub Workflows
schedule:
interval: "weekly"

View File

@@ -14,6 +14,8 @@ on:
- 'LICENSE'
- '**.yml'
pull_request:
branches:
- develop
paths-ignore:
- '.gitattributes'
- '.github/**'
@@ -22,16 +24,17 @@ on:
- '**.md'
- 'LICENSE'
- '**.yml'
- '**.resx'
jobs:
build:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4.0.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0

View File

@@ -74,3 +74,4 @@ Refresh:
script:
- apt-get install -y curl
- curl -X PATCH "$PURGE_URL"
- curl -X POST -o /dev/null "$UPLOAD_OSS_URL"

View File

@@ -35,7 +35,8 @@ Install with Snap Hutao MSIX package, can be installed with Windows built-in App
* [向我们提交 PR / Make Pull Requests](https://github.com/DGP-Studio/Snap.Hutao/pulls)
* [在 Crowdin 上进行本地化 / Translate Project on Crowdin](https://translate.hut.ao/)
* [为我们更新文档 / Enhance our Document ](https://github.com/DGP-Studio/Snap.Hutao.Docs)
* [为我们更新文档 / Enhance our Document](https://github.com/DGP-Studio/Snap.Hutao.Docs)
* [帮助我们测试程序 / Test Binary Package](https://hut.ao/development/contribute.html)
## 特别感谢 / Special Thanks

View File

@@ -69,6 +69,15 @@ else if (AppVeyor.IsRunningOnAppVeyor)
})[..^2];
Information($"Version: {version}");
}
else // Local
{
repoDir = System.Environment.CurrentDirectory;
outputPath = System.IO.Path.Combine(repoDir, "src", "output");
version = System.DateTime.Now.ToString("yyyy.M.d.") + ((int)((System.DateTime.Now - System.DateTime.Today).TotalSeconds / 86400 * 65535)).ToString();
Information($"Version: {version}");
}
Task("Build")
.IsDependentOn("Build binary package")
@@ -112,6 +121,17 @@ Task("Generate AppxManifest")
Information("Using Release configuration");
content = System.Text.RegularExpressions.Regex.Replace(content, " Publisher=\"([^\"]*)\"", " Publisher=\"CN=SignPath Foundation, O=SignPath Foundation, L=Lewes, S=Delaware, C=US\"");
}
else
{
Information("Using Local configuration.");
content = content
.Replace("Snap Hutao", "Snap Hutao Local")
.Replace("胡桃", "胡桃 Local")
.Replace("DGP Studio", "DGP Studio CI");
content = System.Text.RegularExpressions.Regex.Replace(content, " Name=\"([^\"]*)\"", " Name=\"E8B6E2B3-D2A0-4435-A81D-2A16AAF405C7\"");
content = System.Text.RegularExpressions.Regex.Replace(content, " Publisher=\"([^\"]*)\"", " Publisher=\"E=admin@dgp-studio.cn, CN=DGP Studio CI, OU=CI, O=DGP-Studio, L=San Jose, S=CA, C=US\"");
content = System.Text.RegularExpressions.Regex.Replace(content, " Version=\"([0-9\\.]+)\"", $" Version=\"{version}\"");
}
System.IO.File.WriteAllText(manifest, content);
@@ -173,6 +193,10 @@ Task("Build MSIX")
{
arguments = "pack /d " + binPath + " /p " + System.IO.Path.Combine(outputPath, $"Snap.Hutao-{version}.msix");
}
else
{
arguments = "pack /d " + binPath + " /p " + System.IO.Path.Combine(outputPath, $"Snap.Hutao.Local-{version}.msix");
}
var p = StartProcess(
"makeappx.exe",
new ProcessSettings

View File

@@ -13,9 +13,9 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.2.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.2.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
<PackageReference Include="coverlet.collector" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -6,6 +6,7 @@
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources/>
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.TokenizingTextBox/TokenizingTextBox.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Loading.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Image/CachedImage.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/Card.xaml"/>
@@ -22,11 +23,13 @@
<ResourceDictionary Source="ms-appx:///Control/Theme/PageOverride.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/PivotOverride.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/ScrollViewer.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/SegmentedOverride.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/SettingsStyle.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/Thickness.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/TransitionCollection.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/Uri.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/WindowOverride.xaml"/>
<ResourceDictionary Source="ms-appx:///View/Card/Primitive/CardProgressBar.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style

View File

@@ -23,10 +23,12 @@ internal static class ControlAnimationConstants
/// <summary>
/// 图像淡入
/// </summary>
public static readonly TimeSpan ImageFadeIn = TimeSpan.FromSeconds(0.3);
public static readonly TimeSpan ImageScaleFadeIn = TimeSpan.FromSeconds(0.3);
/// <summary>
/// 图像淡出
/// </summary>
public static readonly TimeSpan ImageFadeOut = TimeSpan.FromSeconds(0.2);
public static readonly TimeSpan ImageScaleFadeOut = TimeSpan.FromSeconds(0.2);
public static readonly TimeSpan ImageOpacityFadeInOut = TimeSpan.FromSeconds(1);
}

View File

@@ -0,0 +1,79 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.Control.AutoSuggestBox;
[DependencyProperty("FilterCommand", typeof(ICommand))]
[DependencyProperty("FilterCommandParameter", typeof(object))]
[DependencyProperty("AvailableTokens", typeof(IReadOnlyDictionary<string, SearchToken>))]
internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox
{
public AutoSuggestTokenBox()
{
DefaultStyleKey = typeof(TokenizingTextBox);
TextChanged += OnFilterSuggestionRequested;
QuerySubmitted += OnQuerySubmitted;
TokenItemAdding += OnTokenItemAdding;
TokenItemAdded += OnTokenItemModified;
TokenItemRemoved += OnTokenItemModified;
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (this.FindDescendant("SuggestionsPopup") is Popup { Child: Border { Child: ListView listView } border })
{
IAppResourceProvider appResourceProvider = Ioc.Default.GetRequiredService<IAppResourceProvider>();
listView.Background = null;
listView.Margin = appResourceProvider.GetResource<Thickness>("AutoSuggestListPadding");
border.Background = appResourceProvider.GetResource<Microsoft.UI.Xaml.Media.Brush>("AutoSuggestBoxSuggestionsListBackground");
border.CornerRadius = new(0, 0, 8, 8);
}
}
private void OnFilterSuggestionRequested(Microsoft.UI.Xaml.Controls.AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (string.IsNullOrWhiteSpace(Text))
{
return;
}
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
sender.ItemsSource = AvailableTokens.Values.Where(q => q.Value.Contains(Text, StringComparison.OrdinalIgnoreCase));
}
}
private void OnQuerySubmitted(Microsoft.UI.Xaml.Controls.AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (args.ChosenSuggestion is not null)
{
return;
}
CommandInvocation.TryExecute(FilterCommand, FilterCommandParameter);
}
private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args)
{
if (string.IsNullOrWhiteSpace(args.TokenText))
{
return;
}
args.Item = AvailableTokens.GetValueOrDefault(args.TokenText) ?? new SearchToken(SearchTokenKind.None, args.TokenText);
}
private void OnTokenItemModified(TokenizingTextBox sender, object args)
{
CommandInvocation.TryExecute(FilterCommand, FilterCommandParameter);
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Windows.UI;
namespace Snap.Hutao.Control.AutoSuggestBox;
internal sealed class SearchToken
{
public SearchToken(SearchTokenKind kind, string value, Uri? iconUri = null, Uri? sideIconUri = null, Color? quality = null)
{
Value = value;
Kind = kind;
IconUri = iconUri;
SideIconUri = sideIconUri;
Quality = quality;
}
public SearchTokenKind Kind { get; }
public string Value { get; set; } = default!;
public Uri? IconUri { get; }
public Uri? SideIconUri { get; }
public Color? Quality { get; }
public override string ToString()
{
return Value;
}
}

View File

@@ -0,0 +1,17 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Control.AutoSuggestBox;
internal enum SearchTokenKind
{
None,
AssociationType,
Avatar,
BodyType,
ElementName,
FightProperty,
ItemQuality,
Weapon,
WeaponType,
}

View File

@@ -3,6 +3,7 @@
using CommunityToolkit.WinUI.Behaviors;
using Microsoft.UI.Xaml;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.Control.Behavior;
@@ -45,10 +46,6 @@ internal sealed partial class InvokeCommandOnLoadedBehavior : BehaviorBase<UIEle
return;
}
if (Command is not null && Command.CanExecute(CommandParameter))
{
Command.Execute(CommandParameter);
executed = true;
}
executed = Command.TryExecute(CommandParameter);
}
}

View File

@@ -0,0 +1,87 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.Behaviors;
using Microsoft.UI.Xaml;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.Control.Behavior;
[DependencyProperty("Period", typeof(TimeSpan))]
[DependencyProperty("Command", typeof(ICommand))]
[DependencyProperty("CommandParameter", typeof(object))]
internal sealed partial class PeriodicInvokeCommandOrOnActualThemeChangedBehavior : BehaviorBase<FrameworkElement>, IDisposable
{
private TaskCompletionSource acutalThemeChangedTaskCompletionSource = new();
private CancellationTokenSource periodicTimerCancellationTokenSource = new();
public void Dispose()
{
periodicTimerCancellationTokenSource.Dispose();
}
protected override bool Initialize()
{
AssociatedObject.ActualThemeChanged += OnActualThemeChanged;
return true;
}
protected override void OnAssociatedObjectLoaded()
{
RunCoreAsync().SafeForget();
}
protected override bool Uninitialize()
{
AssociatedObject.ActualThemeChanged -= OnActualThemeChanged;
return true;
}
private void OnActualThemeChanged(FrameworkElement sender, object args)
{
acutalThemeChangedTaskCompletionSource.TrySetResult();
periodicTimerCancellationTokenSource.Cancel();
}
private void TryExecuteCommand()
{
if (AssociatedObject is null)
{
return;
}
Command.TryExecute(CommandParameter);
}
private async ValueTask RunCoreAsync()
{
using (PeriodicTimer timer = new(Period))
{
do
{
if (!IsAttached)
{
break;
}
ITaskContext taskContext = Ioc.Default.GetRequiredService<ITaskContext>();
await taskContext.SwitchToMainThreadAsync();
TryExecuteCommand();
await taskContext.SwitchToBackgroundAsync();
try
{
Task nextTickTask = timer.WaitForNextTickAsync(periodicTimerCancellationTokenSource.Token).AsTask();
await Task.WhenAny(nextTickTask, acutalThemeChangedTaskCompletionSource.Task).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
}
acutalThemeChangedTaskCompletionSource = new();
periodicTimerCancellationTokenSource = new();
}
while (true);
}
}
}

View File

@@ -5,7 +5,6 @@ using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Shapes;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
namespace Snap.Hutao.Control.Brush;

View File

@@ -4,7 +4,6 @@
using CommunityToolkit.WinUI.Collections;
using CommunityToolkit.WinUI.Helpers;
using Microsoft.UI.Xaml.Data;
using Snap.Hutao.Core.ExceptionService;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
@@ -208,13 +207,11 @@ internal sealed class AdvancedCollectionView<T> : IAdvancedCollectionView<T>, IN
public void Add(T item)
{
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
source.Add(item);
}
public void Clear()
{
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
source.Clear();
}
@@ -230,7 +227,6 @@ internal sealed class AdvancedCollectionView<T> : IAdvancedCollectionView<T>, IN
public bool Remove(T item)
{
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
source.Remove(item);
return true;
}
@@ -243,7 +239,6 @@ internal sealed class AdvancedCollectionView<T> : IAdvancedCollectionView<T>, IN
public void Insert(int index, T item)
{
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
source.Insert(index, item);
}

View File

@@ -0,0 +1,18 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Control.Extension;
internal static class CommandInvocation
{
public static bool TryExecute(this ICommand? command, object? parameter = null)
{
if (command is not null && command.CanExecute(parameter))
{
command.Execute(parameter);
return true;
}
return false;
}
}

View File

@@ -2,11 +2,13 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using System.Runtime.CompilerServices;
namespace Snap.Hutao.Control.Extension;
internal static class DependencyObjectExtension
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IServiceProvider ServiceProvider(this DependencyObject obj)
{
return Ioc.Default;

View File

@@ -0,0 +1,24 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
namespace Snap.Hutao.Control.Helper;
[SuppressMessage("", "SH001")]
[DependencyProperty("VisibilityObject", typeof(object), null, nameof(OnVisibilityObjectChanged), IsAttached = true, AttachedType = typeof(UIElement))]
[DependencyProperty("OpacityObject", typeof(object), null, nameof(OnOpacityObjectChanged), IsAttached = true, AttachedType = typeof(UIElement))]
public sealed partial class UIElementHelper
{
private static void OnVisibilityObjectChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = (UIElement)dp;
element.Visibility = e.NewValue is null ? Visibility.Collapsed : Visibility.Visible;
}
private static void OnOpacityObjectChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = (UIElement)dp;
element.Opacity = e.NewValue is null ? 0D : 1D;
}
}

View File

@@ -0,0 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Control;
internal interface IXamlElementAccessor;

View File

@@ -3,7 +3,9 @@
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.Core.Caching;
using Snap.Hutao.Core.ExceptionService;
using System.Runtime.InteropServices;
namespace Snap.Hutao.Control.Image;
@@ -26,12 +28,11 @@ internal sealed class CachedImage : Implementation.ImageEx
/// <inheritdoc/>
protected override async Task<ImageSource?> ProvideCachedResourceAsync(Uri imageUri, CancellationToken token)
{
// We can only use Ioc to retrieve IImageCache, no IServiceProvider is available.
IImageCache imageCache = Ioc.Default.GetRequiredService<IImageCache>();
IImageCache imageCache = this.ServiceProvider().GetRequiredService<IImageCache>();
try
{
Verify.Operation(!string.IsNullOrEmpty(imageUri.Host), SH.ControlImageCachedImageInvalidResourceUri);
HutaoException.ThrowIf(string.IsNullOrEmpty(imageUri.Host), HutaoExceptionKind.ImageCacheInvalidUri, SH.ControlImageCachedImageInvalidResourceUri);
string file = await imageCache.GetFileFromCacheAsync(imageUri).ConfigureAwait(true); // BitmapImage need to be created by main thread.
token.ThrowIfCancellationRequested(); // check token state to determine whether the operation should be canceled.
return new BitmapImage(file.ToUri()); // BitmapImage initialize with a uri will increase image quality and loading speed.

View File

@@ -168,6 +168,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
if (surface.DecodedPhysicalSize.Size() <= 0D)
{
await Task.WhenAny(surfaceLoadTaskCompletionSource.Task, Task.Delay(5000, token)).ConfigureAwait(true);
await Task.Delay(50, token).ConfigureAwait(true);
}
LoadImageSurfaceCompleted(surface);
@@ -192,7 +193,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
{
await AnimationBuilder
.Create()
.Opacity(from: 0D, to: 1D, duration: ControlAnimationConstants.ImageFadeIn)
.Opacity(from: 0D, to: 1D, duration: ControlAnimationConstants.ImageScaleFadeIn)
.StartAsync(this, token)
.ConfigureAwait(true);
}
@@ -213,7 +214,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
{
await AnimationBuilder
.Create()
.Opacity(from: 1D, to: 0D, duration: ControlAnimationConstants.ImageFadeOut)
.Opacity(from: 1D, to: 0D, duration: ControlAnimationConstants.ImageScaleFadeOut)
.StartAsync(this, token)
.ConfigureAwait(true);
}

View File

@@ -7,21 +7,14 @@ using Windows.Media.Casting;
namespace Snap.Hutao.Control.Image.Implementation;
internal class ImageEx : ImageExBase
[DependencyProperty("NineGrid", typeof(Thickness))]
internal partial class ImageEx : ImageExBase
{
private static readonly DependencyProperty NineGridProperty = DependencyProperty.Register(nameof(NineGrid), typeof(Thickness), typeof(ImageEx), new PropertyMetadata(default(Thickness)));
public ImageEx()
: base()
{
}
public Thickness NineGrid
{
get => (Thickness)GetValue(NineGridProperty);
set => SetValue(NineGridProperty, value);
}
public override CompositionBrush GetAlphaMask()
{
if (IsInitialized && Image is Microsoft.UI.Xaml.Controls.Image image)

View File

@@ -6,6 +6,7 @@ using Microsoft.UI.Composition;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using Snap.Hutao.Win32;
using System.IO;
using Windows.Foundation;
@@ -158,7 +159,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
if (value)
{
control.LayoutUpdated += control.OnImageExBaseLayoutUpdated;
control.InvalidateLazyLoading();
}
else
@@ -169,7 +169,7 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
private static void LazyLoadingThresholdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ImageExBase control && control.EnableLazyLoading)
if (d is ImageExBase { EnableLazyLoading: true } control)
{
control.InvalidateLazyLoading();
}
@@ -229,9 +229,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
private void AttachPlaceholderSource(ImageSource? source)
{
// Setting the source at this point should call ImageExOpened/VisualStateManager.GoToState
// as we register to both the ImageOpened/ImageFailed events of the underlying control.
// We only need to call those methods if we fail in other cases before we get here.
if (PlaceholderImage is Microsoft.UI.Xaml.Controls.Image image)
{
image.Source = source;
@@ -240,6 +237,15 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
{
brush.ImageSource = source;
}
if (source is null)
{
VisualStateManager.GoToState(this, UnloadedState, true);
}
else if (source is BitmapSource { PixelHeight: > 0, PixelWidth: > 0 })
{
VisualStateManager.GoToState(this, LoadedState, true);
}
}
private async void SetSource(object? source)
@@ -311,8 +317,7 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
}
tokenSource?.Cancel();
tokenSource = new CancellationTokenSource();
tokenSource = new();
AttachPlaceholderSource(null);
@@ -443,9 +448,10 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
return;
}
Rect controlRect = TransformToVisual(hostElement)
.TransformBounds(new Rect(0, 0, ActualWidth, ActualHeight));
Rect controlRect = TransformToVisual(hostElement).TransformBounds(StructMarshal.Rect(ActualSize));
double lazyLoadingThreshold = LazyLoadingThreshold;
// Left/Top 1 Threshold, Right/Bottom 2 Threshold
Rect hostRect = new(
0 - lazyLoadingThreshold,
0 - lazyLoadingThreshold,

View File

@@ -1,151 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Composition;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
using System.Numerics;
using Windows.Foundation;
namespace Snap.Hutao.Control.Layout;
internal sealed class DefaultItemCollectionTransitionProvider : ItemCollectionTransitionProvider
{
private const double DefaultAnimationDurationInMs = 300.0;
static DefaultItemCollectionTransitionProvider()
{
AnimationSlowdownFactor = 1.0;
}
public static double AnimationSlowdownFactor { get; set; }
protected override bool ShouldAnimateCore(ItemCollectionTransition transition)
{
return true;
}
protected override void StartTransitions(IList<ItemCollectionTransition> transitions)
{
List<ItemCollectionTransition> addTransitions = [];
List<ItemCollectionTransition> removeTransitions = [];
List<ItemCollectionTransition> moveTransitions = [];
foreach (ItemCollectionTransition transition in addTransitions)
{
switch (transition.Operation)
{
case ItemCollectionTransitionOperation.Add:
addTransitions.Add(transition);
break;
case ItemCollectionTransitionOperation.Remove:
removeTransitions.Add(transition);
break;
case ItemCollectionTransitionOperation.Move:
moveTransitions.Add(transition);
break;
}
}
StartAddTransitions(addTransitions, removeTransitions.Count > 0, moveTransitions.Count > 0);
StartRemoveTransitions(removeTransitions);
StartMoveTransitions(moveTransitions, removeTransitions.Count > 0);
}
private static void StartAddTransitions(IList<ItemCollectionTransition> transitions, bool hasRemoveTransitions, bool hasMoveTransitions)
{
foreach (ItemCollectionTransition transition in transitions)
{
ItemCollectionTransitionProgress progress = transition.Start();
Visual visual = ElementCompositionPreview.GetElementVisual(progress.Element);
Compositor compositor = visual.Compositor;
ScalarKeyFrameAnimation fadeInAnimation = compositor.CreateScalarKeyFrameAnimation();
fadeInAnimation.InsertKeyFrame(0.0f, 0.0f);
if (hasMoveTransitions && hasRemoveTransitions)
{
fadeInAnimation.InsertKeyFrame(0.66f, 0.0f);
}
else if (hasMoveTransitions || hasRemoveTransitions)
{
fadeInAnimation.InsertKeyFrame(0.5f, 0.0f);
}
fadeInAnimation.InsertKeyFrame(1.0f, 1.0f);
fadeInAnimation.Duration = TimeSpan.FromMilliseconds(
DefaultAnimationDurationInMs * ((hasRemoveTransitions ? 1 : 0) + (hasMoveTransitions ? 1 : 0) + 1) * AnimationSlowdownFactor);
CompositionScopedBatch batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
visual.StartAnimation("Opacity", fadeInAnimation);
batch.End();
batch.Completed += (_, _) => progress.Complete();
}
}
private static void StartRemoveTransitions(IList<ItemCollectionTransition> transitions)
{
foreach (ItemCollectionTransition transition in transitions)
{
ItemCollectionTransitionProgress progress = transition.Start();
Visual visual = ElementCompositionPreview.GetElementVisual(progress.Element);
Compositor compositor = visual.Compositor;
ScalarKeyFrameAnimation fadeOutAnimation = compositor.CreateScalarKeyFrameAnimation();
fadeOutAnimation.InsertExpressionKeyFrame(0.0f, "this.CurrentValue");
fadeOutAnimation.InsertKeyFrame(1.0f, 0.0f);
fadeOutAnimation.Duration = TimeSpan.FromMilliseconds(DefaultAnimationDurationInMs * AnimationSlowdownFactor);
CompositionScopedBatch batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
visual.StartAnimation(nameof(Visual.Opacity), fadeOutAnimation);
batch.End();
batch.Completed += (_, _) =>
{
visual.Opacity = 1.0f;
progress.Complete();
};
}
}
private static void StartMoveTransitions(IList<ItemCollectionTransition> transitions, bool hasRemoveAnimations)
{
foreach (ItemCollectionTransition transition in transitions)
{
ItemCollectionTransitionProgress progress = transition.Start();
Visual visual = ElementCompositionPreview.GetElementVisual(progress.Element);
Compositor compositor = visual.Compositor;
CompositionScopedBatch batch = compositor.CreateScopedBatch(CompositionBatchTypes.Animation);
// Animate offset.
if (transition.OldBounds.X != transition.NewBounds.X ||
transition.OldBounds.Y != transition.NewBounds.Y)
{
AnimateOffset(visual, compositor, transition.OldBounds, transition.NewBounds, hasRemoveAnimations);
}
batch.End();
batch.Completed += (_, _) => progress.Complete();
}
}
private static void AnimateOffset(Visual visual, Compositor compositor, Rect oldBounds, Rect newBounds, bool hasRemoveAnimations)
{
Vector2KeyFrameAnimation offsetAnimation = compositor.CreateVector2KeyFrameAnimation();
offsetAnimation.SetVector2Parameter("delta", new Vector2(
(float)(oldBounds.X - newBounds.X),
(float)(oldBounds.Y - newBounds.Y)));
offsetAnimation.SetVector2Parameter("final", default);
offsetAnimation.InsertExpressionKeyFrame(0.0f, "this.CurrentValue + delta");
if (hasRemoveAnimations)
{
offsetAnimation.InsertExpressionKeyFrame(0.5f, "delta");
}
offsetAnimation.InsertExpressionKeyFrame(1.0f, "final");
offsetAnimation.Duration = TimeSpan.FromMilliseconds(
DefaultAnimationDurationInMs * ((hasRemoveAnimations ? 1 : 0) + 1) * AnimationSlowdownFactor);
visual.StartAnimation("TransformMatrix._41_42", offsetAnimation);
}
}

View File

@@ -4,6 +4,7 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Collections.Specialized;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Foundation;
@@ -18,14 +19,12 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
protected override void InitializeForContextCore(VirtualizingLayoutContext context)
{
context.LayoutState = new UniformStaggeredLayoutState(context);
base.InitializeForContextCore(context);
}
/// <inheritdoc/>
protected override void UninitializeForContextCore(VirtualizingLayoutContext context)
{
context.LayoutState = null;
base.UninitializeForContextCore(context);
}
/// <inheritdoc/>
@@ -82,16 +81,10 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
(int numberOfColumns, double columnWidth) = GetNumberOfColumnsAndWidth(availableWidth, MinItemWidth, MinColumnSpacing);
if (columnWidth != state.ColumnWidth)
{
// The items will need to be remeasured
state.Clear();
}
state.ColumnWidth = columnWidth;
// adjust for column spacing on all columns expect the first
double totalWidth = state.ColumnWidth + ((numberOfColumns - 1) * (state.ColumnWidth + MinColumnSpacing));
double totalWidth = ((state.ColumnWidth + MinColumnSpacing) * numberOfColumns) - MinColumnSpacing;
if (totalWidth > availableWidth)
{
numberOfColumns--;
@@ -103,7 +96,6 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
if (numberOfColumns != state.NumberOfColumns)
{
// The items will not need to be remeasured, but they will need to go into new columns
state.ClearColumns();
}
@@ -170,7 +162,7 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
item.Element.Measure(new Size(state.ColumnWidth, availableHeight));
if (item.Height != item.Element.DesiredSize.Height)
{
// this item changed size; we need to recalculate layout for everything after this
// this item changed size; we need to recalculate layout for everything after this item
state.RemoveFromIndex(i + 1);
item.Height = item.Element.DesiredSize.Height;
columnHeights[columnIndex] = item.Top + item.Height;
@@ -201,16 +193,16 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
// Cycle through each column and arrange the items that are within the realization bounds
for (int columnIndex = 0; columnIndex < state.NumberOfColumns; columnIndex++)
{
UniformStaggeredColumnLayout layout = state.GetColumnLayout(columnIndex);
foreach (ref readonly UniformStaggeredItem item in CollectionsMarshal.AsSpan(layout))
foreach (ref readonly UniformStaggeredItem item in CollectionsMarshal.AsSpan(state.GetColumnLayout(columnIndex)))
{
double bottom = item.Top + item.Height;
if (bottom < context.RealizationRect.Top)
{
// element is above the realization bounds
// Element is above the realization bounds
continue;
}
// Partial or fully in the view
if (item.Top <= context.RealizationRect.Bottom)
{
double itemHorizontalOffset = (state.ColumnWidth * columnIndex) + (MinColumnSpacing * columnIndex);
@@ -229,21 +221,22 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
return finalSize;
}
private static (int NumberOfColumns, double ColumnWidth) GetNumberOfColumnsAndWidth(double availableWidth, double minItemWidth, double minColumnSpacing)
private static (int NumberOfColumns, double ColumnWidth) GetNumberOfColumnsAndWidth(double availableWidth, double minItemWidth, double columnSpacing)
{
// test if the width can fit in 2 items
if ((2 * minItemWidth) + minColumnSpacing > availableWidth)
if ((2 * minItemWidth) + columnSpacing > availableWidth)
{
return (1, availableWidth);
}
int columnCount = Math.Max(1, (int)((availableWidth + minColumnSpacing) / (minItemWidth + minColumnSpacing)));
double columnWidthAddSpacing = (availableWidth + minColumnSpacing) / columnCount;
return (columnCount, columnWidthAddSpacing - minColumnSpacing);
int columnCount = Math.Max(1, (int)((availableWidth + columnSpacing) / (minItemWidth + columnSpacing)));
double columnWidthWithSpacing = (availableWidth + columnSpacing) / columnCount;
return (columnCount, columnWidthWithSpacing - columnSpacing);
}
private static int GetLowestColumnIndex(in ReadOnlySpan<double> columnHeights)
{
// We want to find the leftest column with the lowest height
int columnIndex = 0;
double height = columnHeights[0];
for (int j = 1; j < columnHeights.Length; j++)
@@ -260,13 +253,11 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
private static void OnMinItemWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UniformStaggeredLayout panel = (UniformStaggeredLayout)d;
panel.InvalidateMeasure();
((UniformStaggeredLayout)d).InvalidateMeasure();
}
private static void OnSpacingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UniformStaggeredLayout panel = (UniformStaggeredLayout)d;
panel.InvalidateMeasure();
((UniformStaggeredLayout)d).InvalidateMeasure();
}
}

View File

@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Runtime.InteropServices;
@@ -67,46 +66,6 @@ internal sealed class UniformStaggeredLayoutState
return columnLayout[columnIndex];
}
/// <summary>
/// Clear everything that has been calculated.
/// </summary>
internal void Clear()
{
// https://github.com/DGP-Studio/Snap.Hutao/issues/1079
// The first element must be force refreshed otherwise
// it will use the old one realized
// https://github.com/DGP-Studio/Snap.Hutao/issues/1099
// Now we need to refresh the first element of each column
// https://github.com/DGP-Studio/Snap.Hutao/issues/1099
// Finally we need to refresh the whole layout when we reset
if (context.ItemCount > 0)
{
for (int i = 0; i < context.ItemCount; i++)
{
RecycleElementAt(i);
}
}
columnLayout.Clear();
items.Clear();
}
/// <summary>
/// Clear the layout columns so they will be recalculated.
/// </summary>
internal void ClearColumns()
{
columnLayout.Clear();
}
/// <summary>
/// Gets the estimated height of the layout.
/// </summary>
/// <returns>The estimated height of the layout.</returns>
/// <remarks>
/// If all of the items have been calculated then the actual height will be returned.
/// If all of the items have not been calculated then an estimated height will be calculated based on the average height of the items.
/// </remarks>
internal double GetHeight()
{
double desiredHeight = columnLayout.Values.Max(c => c.Height);
@@ -139,10 +98,37 @@ internal sealed class UniformStaggeredLayoutState
return desiredHeight;
}
internal void Clear()
{
RecycleElements();
ClearColumns();
ClearItems();
}
internal void ClearColumns()
{
columnLayout.Clear();
}
internal void ClearItems()
{
items.Clear();
}
internal void RecycleElements()
{
if (context.ItemCount > 0)
{
for (int i = 0; i < items.Count; i++)
{
RecycleElementAt(i);
}
}
}
internal void RecycleElementAt(int index)
{
UIElement element = context.GetOrCreateElementAt(index);
context.RecycleElement(element);
context.RecycleElement(context.GetOrCreateElementAt(index));
}
internal void RemoveFromIndex(int index)
@@ -175,7 +161,7 @@ internal sealed class UniformStaggeredLayoutState
{
for (int i = startIndex; i <= endIndex; i++)
{
if (i > items.Count)
if (i >= items.Count)
{
break;
}
@@ -184,7 +170,7 @@ internal sealed class UniformStaggeredLayoutState
item.Height = 0;
item.Top = 0;
// We must recycle all elements to ensure that it gets the correct context
// We must recycle all removed elements to ensure that it gets the correct context
RecycleElementAt(i);
}

View File

@@ -0,0 +1,89 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using System.Data;
using System.Runtime.InteropServices;
using Windows.Foundation;
namespace Snap.Hutao.Control.Panel;
[DependencyProperty("Spacing", typeof(double), default(double), nameof(OnSpacingChanged))]
internal partial class EqualPanel : Microsoft.UI.Xaml.Controls.Panel
{
private double maxItemWidth;
private double maxItemHeight;
private int visibleItemsCount;
public EqualPanel()
{
RegisterPropertyChangedCallback(HorizontalAlignmentProperty, OnHorizontalAlignmentChanged);
}
protected override Size MeasureOverride(Size availableSize)
{
maxItemWidth = 0;
maxItemHeight = 0;
List<UIElement> elements = [.. Children.Where(element => element.Visibility == Visibility.Visible)];
visibleItemsCount = elements.Count;
foreach (ref readonly UIElement child in CollectionsMarshal.AsSpan(elements))
{
child.Measure(availableSize);
maxItemWidth = Math.Max(maxItemWidth, child.DesiredSize.Width);
maxItemHeight = Math.Max(maxItemHeight, child.DesiredSize.Height);
}
if (visibleItemsCount > 0)
{
// Return equal widths based on the widest item
// In very specific edge cases the AvailableWidth might be infinite resulting in a crash.
if (HorizontalAlignment is not HorizontalAlignment.Stretch || double.IsInfinity(availableSize.Width))
{
return new Size((maxItemWidth * visibleItemsCount) + (Spacing * (visibleItemsCount - 1)), maxItemHeight);
}
else
{
// Equal columns based on the available width, adjust for spacing
double totalWidth = availableSize.Width - (Spacing * (visibleItemsCount - 1));
maxItemWidth = totalWidth / visibleItemsCount;
return new Size(availableSize.Width, maxItemHeight);
}
}
else
{
return new Size(0, 0);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
double x = 0;
// Check if there's more (little) width available - if so, set max item width to the maximum possible as we have an almost perfect height.
if (finalSize.Width > (visibleItemsCount * maxItemWidth) + (Spacing * (visibleItemsCount - 1)))
{
maxItemWidth = (finalSize.Width - (Spacing * (visibleItemsCount - 1))) / visibleItemsCount;
}
IEnumerable<UIElement> elements = Children.Where(static e => e.Visibility == Visibility.Visible);
foreach (UIElement child in elements)
{
child.Arrange(new Rect(x, 0, maxItemWidth, maxItemHeight));
x += maxItemWidth + Spacing;
}
return finalSize;
}
private static void OnSpacingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as EqualPanel)?.InvalidateMeasure();
}
private void OnHorizontalAlignmentChanged(DependencyObject sender, DependencyProperty dp)
{
InvalidateMeasure();
}
}

View File

@@ -0,0 +1,58 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Windows.Foundation;
namespace Snap.Hutao.Control.Panel;
[DependencyProperty("MinItemWidth", typeof(double))]
[DependencyProperty("Spacing", typeof(double))]
internal partial class HorizontalEqualPanel : Microsoft.UI.Xaml.Controls.Panel
{
public HorizontalEqualPanel()
{
Loaded += OnLoaded;
SizeChanged += OnSizeChanged;
}
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement child in Children)
{
// ScrollViewer will always return an Infinity Size, we should use ActualWidth for this situation.
double availableWidth = double.IsInfinity(availableSize.Width) ? ActualWidth : availableSize.Width;
double childAvailableWidth = (availableWidth + Spacing) / Children.Count;
double childMaxAvailableWidth = Math.Max(MinItemWidth, childAvailableWidth);
child.Measure(new(childMaxAvailableWidth - Spacing, ActualHeight));
}
return base.MeasureOverride(availableSize);
}
protected override Size ArrangeOverride(Size finalSize)
{
int itemCount = Children.Count;
double availableWidthPerItem = (finalSize.Width - (Spacing * (itemCount - 1))) / itemCount;
double actualItemWidth = Math.Max(MinItemWidth, availableWidthPerItem);
double offset = 0;
foreach (UIElement child in Children)
{
child.Arrange(new Rect(offset, 0, actualItemWidth, finalSize.Height));
offset += actualItemWidth + Spacing;
}
return finalSize;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
MinWidth = (MinItemWidth * Children.Count) + (Spacing * (Children.Count - 1));
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
InvalidateMeasure();
}
}

View File

@@ -6,6 +6,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
Style="{StaticResource DefaultSegmentedStyle}"
mc:Ignorable="d">
<cwc:SegmentedItem

View File

@@ -4,6 +4,7 @@
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Setting;
using System.Collections.Frozen;
namespace Snap.Hutao.Control.Panel;
@@ -19,11 +20,11 @@ internal sealed partial class PanelSelector : Segmented
public const string List = nameof(List);
public const string Grid = nameof(Grid);
private static readonly Dictionary<int, string> IndexTypeMap = new()
{
[0] = List,
[1] = Grid,
};
private static readonly FrozenDictionary<int, string> IndexTypeMap = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(0, List),
KeyValuePair.Create(1, Grid),
]);
private readonly RoutedEventHandler loadedEventHandler;
private readonly RoutedEventHandler unloadedEventHandler;

View File

@@ -72,7 +72,11 @@ internal class ScopedPage : Page
DisposeViewModel();
}
DataContext = null;
if (this.IsDisposed())
{
return;
}
Unloaded -= unloadEventHandler;
}

View File

@@ -4,21 +4,19 @@
xmlns:cwm="using:CommunityToolkit.WinUI.Media">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<cwm:AttachedCardShadow
x:Key="CompatCardShadow"
BlurRadius="8"
Opacity="0.14"
Offset="0,4,0"/>
<x:Double x:Key="CompatShadowThemeOpacity">0.14</x:Double>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<cwm:AttachedCardShadow
x:Key="CompatCardShadow"
BlurRadius="8"
Opacity="0.28"
Offset="0,4,0"/>
<x:Double x:Key="CompatShadowThemeOpacity">0.28</x:Double>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<cwm:AttachedCardShadow
x:Key="CompatCardShadow"
BlurRadius="8"
Opacity="{ThemeResource CompatShadowThemeOpacity}"
Offset="0,4,0"/>
<Style x:Key="BorderCardStyle" TargetType="Border">
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>

View File

@@ -8,6 +8,9 @@
<ItemsPanelTemplate x:Key="WrapPanelSpacing0Template">
<cwcont:WrapPanel/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="WrapPanelSpacing2Template">
<cwcont:WrapPanel HorizontalSpacing="2" VerticalSpacing="2"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="WrapPanelSpacing4Template">
<cwcont:WrapPanel HorizontalSpacing="4" VerticalSpacing="4"/>
</ItemsPanelTemplate>
@@ -17,6 +20,9 @@
<ItemsPanelTemplate x:Key="HorizontalStackPanelSpacing2Template">
<StackPanel Orientation="Horizontal" Spacing="2"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="HorizontalStackPanelSpacing4Template">
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="StackPanelSpacing4Template">
<StackPanel Spacing="4"/>
</ItemsPanelTemplate>

View File

@@ -11,4 +11,6 @@ internal static class KnownColors
public static readonly Color Orange = StructMarshal.Color(0xFFBC6932);
public static readonly Color Purple = StructMarshal.Color(0xFFA156E0);
public static readonly Color Blue = StructMarshal.Color(0xFF5180CB);
public static readonly Color Green = StructMarshal.Color(0xFF2A8F72);
public static readonly Color White = StructMarshal.Color(0xFF72778B);
}

View File

@@ -0,0 +1,115 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cw="using:CommunityToolkit.WinUI"
xmlns:cwc="using:CommunityToolkit.WinUI.Controls"
xmlns:shcp="using:Snap.Hutao.Control.Panel"
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.Segmented/SegmentedItem/SegmentedItem.xaml"/>
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<StaticResource x:Key="SegmentedBackground" ResourceKey="ControlAltFillColorSecondaryBrush"/>
<StaticResource x:Key="SegmentedBorderBrush" ResourceKey="ControlStrokeColorDefaultBrush"/>
<Thickness x:Key="SegmentedBorderThickness">1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="SegmentedBackground" ResourceKey="ControlAltFillColorSecondaryBrush"/>
<StaticResource x:Key="SegmentedBorderBrush" ResourceKey="ControlStrokeColorDefaultBrush"/>
<Thickness x:Key="SegmentedBorderThickness">1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="SegmentedBackground" ResourceKey="SystemColorButtonFaceColor"/>
<StaticResource x:Key="SegmentedBorderBrush" ResourceKey="SystemColorHighlightColorBrush"/>
<Thickness x:Key="SegmentedBorderThickness">1</Thickness>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<x:Double x:Key="SegmentedItemSpacing">1</x:Double>
<x:Double x:Key="ButtonItemSpacing">2</x:Double>
<Style BasedOn="{StaticResource DefaultSegmentedStyle}" TargetType="cwc:Segmented"/>
<Style x:Key="DefaultSegmentedStyle" TargetType="cwc:Segmented">
<Style.Setters>
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
<Setter Property="Background" Value="{ThemeResource SegmentedBackground}"/>
<Setter Property="BorderBrush" Value="{ThemeResource SegmentedBorderBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource SegmentedBorderThickness}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="SelectionMode" Value="Single"/>
<Setter Property="IsItemClickEnabled" Value="False"/>
<win:Setter Property="SingleSelectionFollowsFocus" Value="False"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="TabNavigation" Value="Once"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<shcp:EqualPanel
HorizontalAlignment="{Binding (cw:FrameworkElementExtensions.Ancestor).HorizontalAlignment, RelativeSource={RelativeSource Self}}"
cw:FrameworkElementExtensions.AncestorType="cwc:Segmented"
Spacing="{ThemeResource SegmentedItemSpacing}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="cwc:Segmented">
<Grid>
<Border
VerticalAlignment="Stretch"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"/>
<ItemsPresenter Margin="{TemplateBinding Padding}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<Style
x:Key="PivotSegmentedStyle"
BasedOn="{StaticResource DefaultSegmentedStyle}"
TargetType="cwc:Segmented">
<Style.Setters>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource PivotSegmentedItemStyle}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="{ThemeResource SegmentedItemSpacing}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<Style
x:Key="ButtonSegmentedStyle"
BasedOn="{StaticResource DefaultSegmentedStyle}"
TargetType="cwc:Segmented">
<Style.Setters>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource ButtonSegmentedItemStyle}"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="{ThemeResource ButtonItemSpacing}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,25 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Win32;
using Windows.UI;
namespace Snap.Hutao.Control.Theme;
internal static class SystemColors
{
public static Color BaseLowColor(bool isDarkMode)
{
return isDarkMode ? StructMarshal.Color(0x33FFFFFF) : StructMarshal.Color(0x33000000);
}
public static Color BaseMediumLowColor(bool isDarkMode)
{
return isDarkMode ? StructMarshal.Color(0x66FFFFFF) : StructMarshal.Color(0x66000000);
}
public static Color BaseHighColor(bool isDarkMode)
{
return isDarkMode ? StructMarshal.Color(0xFFFFFFFF) : StructMarshal.Color(0xFF000000);
}
}

View File

@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Core.IO;
namespace Snap.Hutao.Core.Caching;
@@ -10,7 +9,7 @@ namespace Snap.Hutao.Core.Caching;
/// 为图像缓存提供抽象
/// </summary>
[HighQuality]
internal interface IImageCache : ICastService
internal interface IImageCache
{
/// <summary>
/// Gets the file path containing cached item for given Uri

View File

@@ -26,12 +26,12 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
{
private const string CacheFolderName = nameof(ImageCache);
private readonly FrozenDictionary<int, TimeSpan> retryCountToDelay = new Dictionary<int, TimeSpan>()
{
[0] = TimeSpan.FromSeconds(4),
[1] = TimeSpan.FromSeconds(16),
[2] = TimeSpan.FromSeconds(64),
}.ToFrozenDictionary();
private readonly FrozenDictionary<int, TimeSpan> retryCountToDelay = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(0, TimeSpan.FromSeconds(4)),
KeyValuePair.Create(1, TimeSpan.FromSeconds(16)),
KeyValuePair.Create(2, TimeSpan.FromSeconds(64)),
]);
private readonly ConcurrentDictionary<string, Task> concurrentTasks = new();

View File

@@ -25,6 +25,7 @@ internal static partial class IocHttpClientConfiguration
.ConfigurePrimaryHttpMessageHandler((handler, provider) =>
{
HttpClientHandler clientHandler = (HttpClientHandler)handler;
clientHandler.AllowAutoRedirect = true;
clientHandler.UseProxy = true;
clientHandler.Proxy = provider.GetRequiredService<DynamicHttpProxy>();
});

View File

@@ -23,8 +23,16 @@ internal sealed partial class ExceptionRecorder
public void Record(Application app)
{
app.UnhandledException += OnAppUnhandledException;
app.DebugSettings.FailFastOnErrors = false;
app.DebugSettings.IsBindingTracingEnabled = true;
app.DebugSettings.BindingFailed += OnXamlBindingFailed;
app.DebugSettings.IsXamlResourceReferenceTracingEnabled = true;
app.DebugSettings.XamlResourceReferenceFailed += OnXamlResourceReferenceFailed;
app.DebugSettings.LayoutCycleTracingLevel = LayoutCycleTracingLevel.High;
app.DebugSettings.LayoutCycleDebugBreakLevel = LayoutCycleDebugBreakLevel.High;
}
[SuppressMessage("", "CA2012")]

View File

@@ -18,6 +18,12 @@ internal sealed class HutaoException : Exception
public HutaoExceptionKind Kind { get; private set; }
[DoesNotReturn]
public static HutaoException Throw(HutaoExceptionKind kind, string message, Exception? innerException = default)
{
throw new HutaoException(kind, message, innerException);
}
public static void ThrowIf(bool condition, HutaoExceptionKind kind, string message, Exception? innerException = default)
{
if (condition)
@@ -25,4 +31,24 @@ internal sealed class HutaoException : Exception
throw new HutaoException(kind, message, innerException);
}
}
public static void ThrowIfNot(bool condition, HutaoExceptionKind kind, string message, Exception? innerException = default)
{
if (!condition)
{
throw new HutaoException(kind, message, innerException);
}
}
public static HutaoException ServiceTypeCastFailed<TFrom, TTo>(string name, Exception? innerException = default)
{
string message = $"This instance of '{typeof(TFrom).FullName}' '{name}' doesn't implement '{typeof(TTo).FullName}'";
throw new HutaoException(HutaoExceptionKind.ServiceTypeCastFailed, message, innerException);
}
public static HutaoException GachaStatisticsInvalidItemId(uint id, Exception? innerException = default)
{
string message = SH.FormatServiceGachaStatisticsFactoryItemIdInvalid(id);
throw new HutaoException(HutaoExceptionKind.GachaStatisticsInvalidItemId, message, innerException);
}
}

View File

@@ -6,4 +6,16 @@ namespace Snap.Hutao.Core.ExceptionService;
internal enum HutaoExceptionKind
{
None,
// Foundation
ServiceTypeCastFailed,
ImageCacheInvalidUri,
// IO
FileSystemCreateFileInsufficientPermissions,
PrivateNamedPipeContentHashIncorrect,
// Service
GachaStatisticsInvalidItemId,
GameFpsUnlockingFailed,
}

View File

@@ -29,7 +29,7 @@ internal readonly struct TempFile : IDisposable
}
catch (UnauthorizedAccessException ex)
{
ThrowHelper.RuntimeEnvironment(SH.CoreIOTempFileCreateFail, ex);
HutaoException.Throw(HutaoExceptionKind.FileSystemCreateFileInsufficientPermissions, SH.CoreIOTempFileCreateFail, ex);
}
if (delete)

View File

@@ -148,17 +148,15 @@ internal sealed partial class Activation : IActivation
await taskContext.SwitchToBackgroundAsync();
serviceProvider
.GetRequiredService<IMetadataService>()
.As<IMetadataServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
if (serviceProvider.GetRequiredService<IMetadataService>() is IMetadataServiceInitialization metadataServiceInitialization)
{
metadataServiceInitialization.InitializeInternalAsync().SafeForget();
}
serviceProvider
.GetRequiredService<IHutaoUserService>()
.As<IHutaoUserServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
if (serviceProvider.GetRequiredService<IHutaoUserService>() is IHutaoUserServiceInitialization hutaoUserServiceInitialization)
{
hutaoUserServiceInitialization.InitializeInternalAsync().SafeForget();
}
serviceProvider
.GetRequiredService<IDiscordService>()

View File

@@ -49,7 +49,7 @@ internal sealed partial class PrivateNamedPipeServer : IDisposable
{
byte[] content = new byte[header->ContentLength];
serverStream.ReadAtLeast(content, header->ContentLength, false);
ThrowHelper.InvalidDataIf(XxHash64.HashToUInt64(content) != header->Checksum, "PipePacket Content Hash incorrect");
HutaoException.ThrowIf(XxHash64.HashToUInt64(content) != header->Checksum, HutaoExceptionKind.PrivateNamedPipeContentHashIncorrect, "PipePacket Content Hash incorrect");
return content;
}

View File

@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Frozen;
using System.Text;
namespace Snap.Hutao.Core;
@@ -14,25 +15,25 @@ internal static class TypeNameHelper
{
private const char DefaultNestedTypeDelimiter = '+';
private static readonly Dictionary<Type, string> BuiltInTypeNames = new()
{
{ typeof(void), "void" },
{ typeof(bool), "bool" },
{ typeof(byte), "byte" },
{ typeof(char), "char" },
{ typeof(decimal), "decimal" },
{ typeof(double), "double" },
{ typeof(float), "float" },
{ typeof(int), "int" },
{ typeof(long), "long" },
{ typeof(object), "object" },
{ typeof(sbyte), "sbyte" },
{ typeof(short), "short" },
{ typeof(string), "string" },
{ typeof(uint), "uint" },
{ typeof(ulong), "ulong" },
{ typeof(ushort), "ushort" },
};
private static readonly FrozenDictionary<Type, string> BuiltInTypeNames = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(typeof(void), "void"),
KeyValuePair.Create(typeof(bool), "bool"),
KeyValuePair.Create(typeof(byte), "byte"),
KeyValuePair.Create(typeof(char), "char"),
KeyValuePair.Create(typeof(decimal), "decimal"),
KeyValuePair.Create(typeof(double), "double"),
KeyValuePair.Create(typeof(float), "float"),
KeyValuePair.Create(typeof(int), "int"),
KeyValuePair.Create(typeof(long), "long"),
KeyValuePair.Create(typeof(object), "object"),
KeyValuePair.Create(typeof(sbyte), "sbyte"),
KeyValuePair.Create(typeof(short), "short"),
KeyValuePair.Create(typeof(string), "string"),
KeyValuePair.Create(typeof(uint), "uint"),
KeyValuePair.Create(typeof(ulong), "ulong"),
KeyValuePair.Create(typeof(ushort), "ushort"),
]);
/// <summary>
/// 获取对象类型的显示名称

View File

@@ -9,6 +9,7 @@ namespace Snap.Hutao.Core.Validation;
/// 封装验证方法,简化微软验证
/// </summary>
[HighQuality]
[Obsolete("Use HutaoException instead")]
internal static class Must
{
/// <summary>

View File

@@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Model;
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Win32.Foundation;
using Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
using System.Text;
@@ -17,6 +18,7 @@ namespace Snap.Hutao.Core.Windowing.HotKey;
internal sealed class HotKeyCombination : ObservableObject
{
private readonly ICurrentWindowReference currentWindowReference;
private readonly IInfoBarService infoBarService;
private readonly RuntimeOptions runtimeOptions;
private readonly string settingKey;
@@ -37,6 +39,7 @@ internal sealed class HotKeyCombination : ObservableObject
public HotKeyCombination(IServiceProvider serviceProvider, string settingKey, int hotKeyId, HOT_KEY_MODIFIERS defaultModifiers, VirtualKey defaultKey)
{
currentWindowReference = serviceProvider.GetRequiredService<ICurrentWindowReference>();
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
this.settingKey = settingKey;
@@ -186,6 +189,12 @@ internal sealed class HotKeyCombination : ObservableObject
HWND hwnd = currentWindowReference.GetWindowHandle();
BOOL result = RegisterHotKey(hwnd, hotKeyId, Modifiers, (uint)Key);
registered = result;
if (!result)
{
infoBarService.Warning(SH.FormatCoreWindowHotkeyCombinationRegisterFailed(SH.ViewPageSettingKeyShortcutAutoClickingHeader, DisplayName));
}
return result;
}

View File

@@ -13,6 +13,7 @@ using Snap.Hutao.Win32;
using Snap.Hutao.Win32.Foundation;
using Snap.Hutao.Win32.Graphics.Dwm;
using Snap.Hutao.Win32.UI.WindowsAndMessaging;
using System.Collections.Frozen;
using System.IO;
using Windows.Graphics;
using Windows.UI;
@@ -56,25 +57,22 @@ internal sealed class WindowController
private void InitializeCore()
{
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
AppOptions appOptions = serviceProvider.GetRequiredService<AppOptions>();
window.AppWindow.Title = SH.FormatAppNameAndVersion(runtimeOptions.Version);
window.AppWindow.SetIcon(Path.Combine(runtimeOptions.InstalledLocation, "Assets/Logo.ico"));
ExtendsContentIntoTitleBar();
RecoverOrInitWindowSize();
UpdateElementTheme(appOptions.ElementTheme);
UpdateImmersiveDarkMode(options.TitleBar, default!);
// appWindow.Show(true);
// appWindow.Show can't bring window to top.
window.Activate();
options.BringToForeground();
if (options.UseSystemBackdrop)
{
AppOptions appOptions = serviceProvider.GetRequiredService<AppOptions>();
UpdateSystemBackdrop(appOptions.BackdropType);
appOptions.PropertyChanged += OnOptionsPropertyChanged;
}
UpdateSystemBackdrop(appOptions.BackdropType);
appOptions.PropertyChanged += OnOptionsPropertyChanged;
subclass.Initialize();
@@ -122,13 +120,17 @@ internal sealed class WindowController
private void OnOptionsPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is nameof(AppOptions.BackdropType))
if (sender is not AppOptions options)
{
if (sender is AppOptions options)
{
UpdateSystemBackdrop(options.BackdropType);
}
return;
}
_ = e.PropertyName switch
{
nameof(AppOptions.BackdropType) => UpdateSystemBackdrop(options.BackdropType),
nameof(AppOptions.ElementTheme) => UpdateElementTheme(options.ElementTheme),
_ => false,
};
}
private void OnWindowClosed(object sender, WindowEventArgs args)
@@ -158,7 +160,7 @@ internal sealed class WindowController
}
}
private void UpdateSystemBackdrop(BackdropType backdropType)
private bool UpdateSystemBackdrop(BackdropType backdropType)
{
window.SystemBackdrop = backdropType switch
{
@@ -168,6 +170,15 @@ internal sealed class WindowController
BackdropType.Acrylic => new DesktopAcrylicBackdrop(),
_ => null,
};
return true;
}
private bool UpdateElementTheme(ElementTheme theme)
{
((FrameworkElement)window.Content).RequestedTheme = theme;
return true;
}
private void UpdateTitleButtonColor()
@@ -177,12 +188,12 @@ internal sealed class WindowController
appTitleBar.ButtonBackgroundColor = Colors.Transparent;
appTitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
IAppResourceProvider resourceProvider = serviceProvider.GetRequiredService<IAppResourceProvider>();
bool isDarkMode = Control.Theme.ThemeHelper.IsDarkMode(options.TitleBar.ActualTheme);
Color systemBaseLowColor = resourceProvider.GetResource<Color>("SystemBaseLowColor");
Color systemBaseLowColor = Control.Theme.SystemColors.BaseLowColor(isDarkMode);
appTitleBar.ButtonHoverBackgroundColor = systemBaseLowColor;
Color systemBaseMediumLowColor = resourceProvider.GetResource<Color>("SystemBaseMediumLowColor");
Color systemBaseMediumLowColor = Control.Theme.SystemColors.BaseMediumLowColor(isDarkMode);
appTitleBar.ButtonPressedBackgroundColor = systemBaseMediumLowColor;
// The Foreground doesn't accept Alpha channel. So we translate it to gray.
@@ -190,7 +201,7 @@ internal sealed class WindowController
byte result = (byte)((systemBaseMediumLowColor.A / 255.0) * light);
appTitleBar.ButtonInactiveForegroundColor = Color.FromArgb(0xFF, result, result, result);
Color systemBaseHighColor = resourceProvider.GetResource<Color>("SystemBaseHighColor");
Color systemBaseHighColor = Control.Theme.SystemColors.BaseHighColor(isDarkMode);
appTitleBar.ButtonForegroundColor = systemBaseHighColor;
appTitleBar.ButtonHoverForegroundColor = systemBaseHighColor;
appTitleBar.ButtonPressedForegroundColor = systemBaseHighColor;

View File

@@ -41,21 +41,18 @@ internal readonly struct WindowOptions
/// </summary>
public readonly bool PersistSize;
public readonly bool UseSystemBackdrop;
/// <summary>
/// 是否使用 Win UI 3 自带的拓展标题栏实现
/// </summary>
public readonly bool UseLegacyDragBarImplementation = !AppWindowTitleBar.IsCustomizationSupported();
public WindowOptions(Window window, FrameworkElement titleBar, SizeInt32 initSize, bool persistSize = false, bool useSystemBackdrop = true)
public WindowOptions(Window window, FrameworkElement titleBar, SizeInt32 initSize, bool persistSize = false)
{
Hwnd = WindowNative.GetWindowHandle(window);
InputNonClientPointerSource = InputNonClientPointerSource.GetForWindowId(window.AppWindow.Id);
TitleBar = titleBar;
InitSize = initSize;
PersistSize = persistSize;
UseSystemBackdrop = useSystemBackdrop;
}
/// <summary>

View File

@@ -18,20 +18,11 @@ internal static class DateTimeOffsetExtension
return defaultValue;
}
try
return value switch
{
return DateTimeOffset.FromUnixTimeSeconds(value);
}
catch (ArgumentOutOfRangeException)
{
try
{
return DateTimeOffset.FromUnixTimeMilliseconds(value);
}
catch (ArgumentOutOfRangeException)
{
return defaultValue;
}
}
>= -62135596800 and <= 253402300799 => DateTimeOffset.FromUnixTimeSeconds(value),
>= -62135596800000 and <= 253402300799999 => DateTimeOffset.FromUnixTimeMilliseconds(value),
_ => defaultValue,
};
}
}

View File

@@ -15,6 +15,12 @@ namespace Snap.Hutao.Extension;
[HighQuality]
internal static partial class EnumerableExtension
{
public static void Deconstruct<TKey, TElement>(this IGrouping<TKey, TElement> grouping, out TKey key, out IEnumerable<TElement> elements)
{
key = grouping.Key;
elements = grouping;
}
public static TElement? ElementAtOrLastOrDefault<TElement>(this IEnumerable<TElement> source, int index)
{
return source.ElementAtOrDefault(index) ?? source.LastOrDefault();
@@ -46,34 +52,6 @@ internal static partial class EnumerableExtension
return first;
}
public static string JoinToString<T>(this IEnumerable<T> source, char separator, Action<StringBuilder, T> selector)
{
StringBuilder resultBuilder = new();
IEnumerator<T> enumerator = source.GetEnumerator();
if (!enumerator.MoveNext())
{
return string.Empty;
}
T first = enumerator.Current;
selector(resultBuilder, first);
if (!enumerator.MoveNext())
{
return resultBuilder.ToString();
}
do
{
resultBuilder.Append(separator);
selector(resultBuilder, enumerator.Current);
}
while (enumerator.MoveNext());
return resultBuilder.ToString();
}
public static string JoinToString<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> source, char separator, Action<StringBuilder, TKey, TValue> selector)
{
StringBuilder resultBuilder = new();

View File

@@ -3,6 +3,7 @@
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Service;
namespace Snap.Hutao.Factory.ContentDialog;
@@ -15,6 +16,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
private readonly ICurrentWindowReference currentWindowReference;
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
private readonly AppOptions appOptions;
/// <inheritdoc/>
public async ValueTask<ContentDialogResult> CreateForConfirmAsync(string title, string content)
@@ -27,6 +29,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
Content = content,
DefaultButton = ContentDialogButton.Primary,
PrimaryButtonText = SH.ContentDialogConfirmPrimaryButtonText,
RequestedTheme = appOptions.ElementTheme,
};
return await dialog.ShowAsync();
@@ -44,6 +47,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
DefaultButton = defaultButton,
PrimaryButtonText = SH.ContentDialogConfirmPrimaryButtonText,
CloseButtonText = SH.ContentDialogCancelCloseButtonText,
RequestedTheme = appOptions.ElementTheme,
};
return await dialog.ShowAsync();
@@ -58,6 +62,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
XamlRoot = currentWindowReference.GetXamlRoot(),
Title = title,
Content = new ProgressBar() { IsIndeterminate = true },
RequestedTheme = appOptions.ElementTheme,
};
return dialog;
@@ -69,6 +74,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
await taskContext.SwitchToMainThreadAsync();
TContentDialog contentDialog = serviceProvider.CreateInstance<TContentDialog>(parameters);
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
contentDialog.RequestedTheme = appOptions.ElementTheme;
return contentDialog;
}
@@ -77,6 +83,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
{
TContentDialog contentDialog = serviceProvider.CreateInstance<TContentDialog>(parameters);
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
contentDialog.RequestedTheme = appOptions.ElementTheme;
return contentDialog;
}
}

View File

@@ -41,6 +41,30 @@
"Equatable": true,
"EqualityOperators": true
},
{
"Name": "FurnitureId",
"Documentation": "家具 Id",
"Equatable": true,
"EqualityOperators": true
},
{
"Name": "FurnitureMakeId",
"Documentation": "家具配方 Id",
"Equatable": true,
"EqualityOperators": true
},
{
"Name": "FurnitureSuiteId",
"Documentation": "家具套装 Id",
"Equatable": true,
"EqualityOperators": true
},
{
"Name": "FurnitureTypeId",
"Documentation": "家具分类 Id",
"Equatable": true,
"EqualityOperators": true
},
{
"Name": "Level",
"Documentation": "等级 1 - 90",

View File

@@ -27,7 +27,7 @@ internal sealed partial class MainWindow : Window, IWindowOptionsSource, IMinMax
public MainWindow(IServiceProvider serviceProvider)
{
InitializeComponent();
windowOptions = new(this, TitleBarView.DragArea, new(1200, 741), true, false);
windowOptions = new(this, TitleBarView.DragArea, new(1200, 741), true);
this.InitializeController(serviceProvider);
}

View File

@@ -0,0 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Message;
internal sealed class BackgroundImageTypeChangedMessage;

View File

@@ -11,10 +11,16 @@ internal static class CollectionsNameValue
return [.. Enum.GetValues<TEnum>().Select(x => new NameValue<TEnum>(x.ToString(), x))];
}
public static List<NameValue<TEnum>> FromEnum<TEnum>(Func<TEnum, bool> codiction)
public static List<NameValue<TEnum>> FromEnum<TEnum>(Func<TEnum, bool> condition)
where TEnum : struct, Enum
{
return [.. Enum.GetValues<TEnum>().Where(codiction).Select(x => new NameValue<TEnum>(x.ToString(), x))];
return [.. Enum.GetValues<TEnum>().Where(condition).Select(x => new NameValue<TEnum>(x.ToString(), x))];
}
public static List<NameValue<TEnum>> FromEnum<TEnum>(Func<TEnum, string> nameSelector)
where TEnum : struct, Enum
{
return [.. Enum.GetValues<TEnum>().Select(x => new NameValue<TEnum>(nameSelector(x), x))];
}
public static List<NameValue<TSource>> From<TSource>(IEnumerable<TSource> sources, Func<TSource, string> nameSelector)

View File

@@ -42,14 +42,14 @@ internal sealed partial class GachaItem
/// <summary>
/// 祈愿记录分类
/// </summary>
public GachaConfigType GachaType { get; set; }
public GachaType GachaType { get; set; }
/// <summary>
/// 祈愿记录查询分类
/// 合并保底的卡池使用此属性
/// 仅4种不含400
/// </summary>
public GachaConfigType QueryType { get; set; }
public GachaType QueryType { get; set; }
/// <summary>
/// 物品Id

View File

@@ -13,6 +13,7 @@ internal sealed partial class SettingEntry
public const string Culture = "Culture";
public const string SystemBackdropType = "SystemBackdropType";
public const string ElementTheme = "ElementTheme";
public const string BackgroundImageType = "BackgroundImageType";
public const string AnnouncementRegion = "AnnouncementRegion";

View File

@@ -17,7 +17,7 @@ internal sealed class UIGF : IJsonOnSerializing, IJsonOnDeserialized
/// <summary>
/// 当前版本
/// </summary>
public const string CurrentVersion = "v2.4";
public const string CurrentVersion = "v3.0";
/// <summary>
/// 信息
@@ -61,6 +61,7 @@ internal sealed class UIGF : IJsonOnSerializing, IJsonOnDeserialized
"v2.2" => UIGFVersion.Major2Minor2OrLower,
"v2.3" => UIGFVersion.Major2Minor3OrHigher,
"v2.4" => UIGFVersion.Major2Minor3OrHigher,
"v3.0" => UIGFVersion.Major2Minor3OrHigher,
_ => UIGFVersion.NotSupported,
};

View File

@@ -20,7 +20,7 @@ internal sealed class UIGFItem : GachaLogItem, IMappingFrom<UIGFItem, GachaItem,
/// </summary>
[JsonPropertyName("uigf_gacha_type")]
[JsonEnum(JsonSerializeType.NumberString)]
public GachaConfigType UIGFGachaType { get; set; } = default!;
public GachaType UIGFGachaType { get; set; } = default!;
public static UIGFItem From(GachaItem item, INameQuality nameQuality)
{

View File

@@ -0,0 +1,25 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.Intrinsic;
internal enum FurnitureDeploySurfaceType
{
Ground = 0,
Wall = 1,
Ceil = 2,
StackObjPlane = 3,
Door = 4,
Chandelier = 5,
Floor = 6,
WallBody = 7,
Carpet = 8,
LegoRockery = 9,
Stair = 10,
NPC = 11,
Animal = 12,
Apartment = 13,
FurnitureSuite = 14,
Road = 15,
Terrain = 16,
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.Intrinsic;
internal enum FurnitureDeployType
{
Interior,
Exterior,
InteriorRoom,
InteriorHall,
Skybox,
}

View File

@@ -0,0 +1,14 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.Intrinsic;
internal enum GroupRecordType
{
None,
Racing,
Balloon,
Stake,
Seek,
Explosion,
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Model.Intrinsic;
internal enum SpecialFurnitureType
{
NormalFurniture,
BlockDependent,
FarmField,
TeleportPoint,
Fishpond,
Npc,
Apartment,
FurnitureSuite,
Paimon,
Fish,
CustomBaseFurniture,
CustomNodeFurniture,
VirtualFurniture,
GroupFurniture,
CoopPictureFrame,
ChangeBgmFurniture,
ServerGadget,
Fishtank,
}

View File

@@ -1,22 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Model.Metadata.Achievement;
/// <summary>
/// 奖励
/// </summary>
internal sealed class Reward
{
/// <summary>
/// Id
/// </summary>
public MaterialId Id { get; set; }
/// <summary>
/// 数量
/// </summary>
public uint Count { get; set; }
}
internal sealed class Reward : IdCount;

View File

@@ -0,0 +1,55 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Control;
using Snap.Hutao.Model.Intrinsic;
using System.Collections.Frozen;
namespace Snap.Hutao.Model.Metadata.Converter;
internal sealed class AssociationTypeIconConverter : ValueConverter<AssociationType, Uri?>
{
private static readonly FrozenDictionary<string, AssociationType> LocalizedNameToAssociationType = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeMondstadt, AssociationType.ASSOC_TYPE_MONDSTADT),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeLiyue, AssociationType.ASSOC_TYPE_LIYUE),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeFatui, AssociationType.ASSOC_TYPE_FATUI),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeInazuma, AssociationType.ASSOC_TYPE_INAZUMA),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeRanger, AssociationType.ASSOC_TYPE_RANGER),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeSumeru, AssociationType.ASSOC_TYPE_SUMERU),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeFontaine, AssociationType.ASSOC_TYPE_FONTAINE),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeNatlan, AssociationType.ASSOC_TYPE_NATLAN),
KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeSnezhnaya, AssociationType.ASSOC_TYPE_SNEZHNAYA),
]);
public static Uri? AssociationTypeNameToIconUri(string associationTypeName)
{
return AssociationTypeToIconUri(LocalizedNameToAssociationType.GetValueOrDefault(associationTypeName));
}
public static Uri? AssociationTypeToIconUri(AssociationType type)
{
string? association = type switch
{
AssociationType.ASSOC_TYPE_MONDSTADT => "Mengde",
AssociationType.ASSOC_TYPE_LIYUE => "Liyue",
AssociationType.ASSOC_TYPE_FATUI => default,
AssociationType.ASSOC_TYPE_INAZUMA => "Inazuma",
AssociationType.ASSOC_TYPE_RANGER => default,
AssociationType.ASSOC_TYPE_SUMERU => "Sumeru",
AssociationType.ASSOC_TYPE_FONTAINE => "Fontaine",
AssociationType.ASSOC_TYPE_NATLAN => default,
AssociationType.ASSOC_TYPE_SNEZHNAYA => default,
_ => throw Must.NeverHappen(),
};
return association is null
? default
: Web.HutaoEndpoints.StaticRaw("ChapterIcon", $"UI_ChapterIcon_{association}.png").ToUri();
}
public override Uri? Convert(AssociationType from)
{
return AssociationTypeToIconUri(from);
}
}

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Control;
using Snap.Hutao.Model.Intrinsic;
using System.Collections.Frozen;
namespace Snap.Hutao.Model.Metadata.Converter;
@@ -12,27 +13,27 @@ namespace Snap.Hutao.Model.Metadata.Converter;
[HighQuality]
internal sealed class ElementNameIconConverter : ValueConverter<string, Uri>
{
private static readonly Dictionary<string, string> LocalizedNameToElementIconName = new()
{
[SH.ModelIntrinsicElementNameElec] = "Electric",
[SH.ModelIntrinsicElementNameFire] = "Fire",
[SH.ModelIntrinsicElementNameGrass] = "Grass",
[SH.ModelIntrinsicElementNameIce] = "Ice",
[SH.ModelIntrinsicElementNameRock] = "Rock",
[SH.ModelIntrinsicElementNameWater] = "Water",
[SH.ModelIntrinsicElementNameWind] = "Wind",
};
private static readonly FrozenDictionary<string, string> LocalizedNameToElementIconName = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(SH.ModelIntrinsicElementNameElec, "Electric"),
KeyValuePair.Create(SH.ModelIntrinsicElementNameFire, "Fire"),
KeyValuePair.Create(SH.ModelIntrinsicElementNameGrass, "Grass"),
KeyValuePair.Create(SH.ModelIntrinsicElementNameIce, "Ice"),
KeyValuePair.Create(SH.ModelIntrinsicElementNameRock, "Rock"),
KeyValuePair.Create(SH.ModelIntrinsicElementNameWater, "Water"),
KeyValuePair.Create(SH.ModelIntrinsicElementNameWind, "Wind"),
]);
private static readonly Dictionary<string, ElementType> LocalizedNameToElementType = new()
{
[SH.ModelIntrinsicElementNameElec] = ElementType.Electric,
[SH.ModelIntrinsicElementNameFire] = ElementType.Fire,
[SH.ModelIntrinsicElementNameGrass] = ElementType.Grass,
[SH.ModelIntrinsicElementNameIce] = ElementType.Ice,
[SH.ModelIntrinsicElementNameRock] = ElementType.Rock,
[SH.ModelIntrinsicElementNameWater] = ElementType.Water,
[SH.ModelIntrinsicElementNameWind] = ElementType.Wind,
};
private static readonly FrozenDictionary<string, ElementType> LocalizedNameToElementType = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(SH.ModelIntrinsicElementNameElec, ElementType.Electric),
KeyValuePair.Create(SH.ModelIntrinsicElementNameFire, ElementType.Fire),
KeyValuePair.Create(SH.ModelIntrinsicElementNameGrass, ElementType.Grass),
KeyValuePair.Create(SH.ModelIntrinsicElementNameIce, ElementType.Ice),
KeyValuePair.Create(SH.ModelIntrinsicElementNameRock, ElementType.Rock),
KeyValuePair.Create(SH.ModelIntrinsicElementNameWater, ElementType.Water),
KeyValuePair.Create(SH.ModelIntrinsicElementNameWind, ElementType.Wind),
]);
/// <summary>
/// 将中文元素名称转换为图标链接

View File

@@ -3,8 +3,9 @@
using Microsoft.UI;
using Snap.Hutao.Control;
using Snap.Hutao.Control.Theme;
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Win32;
using System.Collections.Frozen;
using Windows.UI;
namespace Snap.Hutao.Model.Metadata.Converter;
@@ -15,17 +16,39 @@ namespace Snap.Hutao.Model.Metadata.Converter;
[HighQuality]
internal sealed class QualityColorConverter : ValueConverter<QualityType, Color>
{
private static readonly FrozenDictionary<string, QualityType> LocalizedNameToQualityType = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(SH.ModelIntrinsicItemQualityWhite, QualityType.QUALITY_WHITE),
KeyValuePair.Create(SH.ModelIntrinsicItemQualityGreen, QualityType.QUALITY_GREEN),
KeyValuePair.Create(SH.ModelIntrinsicItemQualityBlue, QualityType.QUALITY_BLUE),
KeyValuePair.Create(SH.ModelIntrinsicItemQualityPurple, QualityType.QUALITY_PURPLE),
KeyValuePair.Create(SH.ModelIntrinsicItemQualityOrange, QualityType.QUALITY_ORANGE),
KeyValuePair.Create(SH.ModelIntrinsicItemQualityRed, QualityType.QUALITY_ORANGE_SP),
]);
private static readonly FrozenDictionary<QualityType, Color> QualityTypeToColor = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(QualityType.QUALITY_WHITE, KnownColors.White),
KeyValuePair.Create(QualityType.QUALITY_GREEN, KnownColors.Green),
KeyValuePair.Create(QualityType.QUALITY_BLUE, KnownColors.Blue),
KeyValuePair.Create(QualityType.QUALITY_PURPLE, KnownColors.Purple),
KeyValuePair.Create(QualityType.QUALITY_ORANGE, KnownColors.Orange),
KeyValuePair.Create(QualityType.QUALITY_ORANGE_SP, KnownColors.Orange),
]);
public static Color QualityNameToColor(string qualityName)
{
return QualityToColor(LocalizedNameToQualityType.GetValueOrDefault(qualityName));
}
public static Color QualityToColor(QualityType quality)
{
return QualityTypeToColor.GetValueOrDefault(quality, Colors.Transparent);
}
/// <inheritdoc/>
public override Color Convert(QualityType from)
{
return from switch
{
QualityType.QUALITY_WHITE => StructMarshal.Color(0xFF72778B),
QualityType.QUALITY_GREEN => StructMarshal.Color(0xFF2A8F72),
QualityType.QUALITY_BLUE => StructMarshal.Color(0xFF5180CB),
QualityType.QUALITY_PURPLE => StructMarshal.Color(0xFFA156E0),
QualityType.QUALITY_ORANGE or QualityType.QUALITY_ORANGE_SP => StructMarshal.Color(0xFFBC6932),
_ => Colors.Transparent,
};
return QualityToColor(from);
}
}

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Control;
using Snap.Hutao.Model.Intrinsic;
using System.Collections.Frozen;
namespace Snap.Hutao.Model.Metadata.Converter;
@@ -12,6 +13,20 @@ namespace Snap.Hutao.Model.Metadata.Converter;
[HighQuality]
internal sealed class WeaponTypeIconConverter : ValueConverter<WeaponType, Uri>
{
private static readonly FrozenDictionary<string, WeaponType> LocalizedNameToWeaponType = FrozenDictionary.ToFrozenDictionary(
[
KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeSwordOneHand, WeaponType.WEAPON_SWORD_ONE_HAND),
KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeBow, WeaponType.WEAPON_BOW),
KeyValuePair.Create(SH.ModelIntrinsicWeaponTypePole, WeaponType.WEAPON_POLE),
KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeClaymore, WeaponType.WEAPON_CLAYMORE),
KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeCatalyst, WeaponType.WEAPON_CATALYST),
]);
public static Uri WeaponTypeNameToIconUri(string weaponTypeName)
{
return WeaponTypeToIconUri(LocalizedNameToWeaponType.GetValueOrDefault(weaponTypeName));
}
/// <summary>
/// 将武器类型转换为图标链接
/// </summary>

View File

@@ -0,0 +1,50 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Model.Metadata.Furniture;
internal sealed class Furniture
{
public List<FurnitureTypeId> Types { get; set; } = default!;
public FurnitureDeploySurfaceType SurfaceType { get; set; }
public bool IsSpecial { get; set; }
public SpecialFurnitureType SpecialType { get; set; }
public uint Comfort { get; set; }
public uint Cost { get; set; }
public uint DiscountCost { get; set; }
public bool CanFloat { get; set; }
public bool IsUnique { get; set; }
public string? ItemIcon { get; set; }
public string? EffectIcon { get; set; }
public QualityType RankLevel { get; set; }
public List<FurnitureId> GruopUnits { get; set; } = default!;
public GroupRecordType GroupRecordType { get; set; }
public List<string> SourceTexts { get; set; } = default!;
public FurnitureId Id { get; set; }
public string Name { get; set; } = default!;
public string Description { get; set; } = default!;
public string? Icon { get; set; }
public uint Rank { get; set; }
}

View File

@@ -0,0 +1,17 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Model.Metadata.Furniture;
internal sealed class FurnitureMake
{
public FurnitureMakeId Id { get; set; }
public FurnitureId ItemId { get; set; }
public uint Experience { get; set; }
public List<IdCount> Materials { get; set; } = default!;
}

View File

@@ -0,0 +1,25 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Model.Metadata.Furniture;
internal sealed class FurnitureSuite
{
public FurnitureSuiteId Id { get; set; }
public List<FurnitureTypeId> Types { get; set; } = default!;
public string Name { get; set; } = default!;
public string Description { get; set; } = default!;
public string ItemIcon { get; set; } = default!;
public string? MapIcon { get; set; }
public List<AvatarId>? FavoriteNpcs { get; set; }
public List<FurnitureId> Units { get; set; } = default!;
}

View File

@@ -0,0 +1,28 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Model.Metadata.Furniture;
internal sealed class FurnitureType
{
public FurnitureTypeId Id { get; set; }
public uint Category { get; set; }
public string Name { get; set; } = default!;
public string Name2 { get; set; } = default!;
public string TabIcon { get; set; } = default!;
public FurnitureDeployType SceneType { get; set; }
public bool BagPageOnly { get; set; }
public bool IsShowInBag { get; set; }
public uint Sort { get; set; }
}

View File

@@ -49,7 +49,7 @@ internal sealed class GachaEvent
/// <summary>
/// 卡池类型
/// </summary>
public GachaConfigType Type { get; set; }
public GachaType Type { get; set; }
/// <summary>
/// 五星列表

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Primitive;
namespace Snap.Hutao.Model.Metadata;
internal class IdCount
{
/// <summary>
/// Id
/// </summary>
public MaterialId Id { get; set; }
/// <summary>
/// 数量
/// </summary>
public uint Count { get; set; }
}

View File

@@ -13,7 +13,7 @@
<Identity
Name="60568DGPStudio.SnapHutao"
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
Version="1.9.6.0" />
Version="1.9.8.0" />
<Properties>
<DisplayName>Snap Hutao</DisplayName>

View File

@@ -13,7 +13,7 @@
<Identity
Name="60568DGPStudio.SnapHutaoDev"
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
Version="1.9.6.0" />
Version="1.9.8.0" />
<Properties>
<DisplayName>Snap Hutao Dev</DisplayName>

View File

@@ -145,7 +145,7 @@
<value>Save</value>
</data>
<data name="ControlImageCachedImageInvalidResourceUri" xml:space="preserve">
<value>Invalid URL</value>
<value>Invalid Uri</value>
</data>
<data name="ControlImageCompositionImageHttpRequest" xml:space="preserve">
<value>HTTP GET {0}</value>
@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>No WebView2 Runtime detected</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>Register [{0}] hotkey [{1}] failed</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>Dark</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>Light</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>System</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>Export</value>
</data>
@@ -285,7 +297,7 @@
<comment>Need EXACT same string in game</comment>
</data>
<data name="ModelIntrinsicAssociationTypeInazuma" xml:space="preserve">
<value>Inadzuma</value>
<value>Inazuma</value>
<comment>Need EXACT same string in game</comment>
</data>
<data name="ModelIntrinsicAssociationTypeLiyue" xml:space="preserve">
@@ -546,7 +558,7 @@
<value>Uploaded {1} wish records of UID: {0}, stored {2}</value>
</data>
<data name="ServerPassportLoginRequired" xml:space="preserve">
<value>Please login or register Hutao account first</value>
<value>Please login or register Snap Hutao account first</value>
</data>
<data name="ServerPassportLoginSucceed" xml:space="preserve">
<value>Login successfully</value>
@@ -558,7 +570,7 @@
<value>Password has been set successfully</value>
</data>
<data name="ServerPassportServiceEmailHasNotRegistered" xml:space="preserve">
<value>Current email adress is not registered</value>
<value>Current email address is not registered</value>
</data>
<data name="ServerPassportServiceEmailHasRegistered" xml:space="preserve">
<value>Current emaill address is registered</value>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Character Showcase: {0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>Bing Daily Wallpaper</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>Hutao Daily Wallpaper</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>Genshin Official Launcher Wallpaper</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>Local Random Image</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>No Wallpaper</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Failed to save development plan status</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>Parametric Transformer is ready</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>Missing permission, unable to set your Discord Activity.</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Exploring in Teyvat</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>Character Event Wish</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>Chronicled Wish</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>Wanderlust Invocation</value>
</data>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Game Launcher</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>Cannot reorder in Admin Mode</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>Archive [{0}] added successfully</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Completed</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>Response stream does not contain valid content type</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>Queued</value>
</data>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>Launch Parameters</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>Auto start Better GUI for automation tasks after game launched</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Automated Tasks</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>General</value>
</data>
@@ -2202,7 +2247,7 @@
<value>File</value>
</data>
<data name="ViewPageLaunchGameInterProcessHeader" xml:space="preserve">
<value>InterProcess</value>
<value>Process Linkage</value>
</data>
<data name="ViewPageLaunchGameMonitorsDescription" xml:space="preserve">
<value>Run the software on the selected monitor</value>
@@ -2223,7 +2268,7 @@
<value>Try to start Starward after the game is started for game duration statistics</value>
</data>
<data name="ViewPageLaunchGamePlayTimeHeader" xml:space="preserve">
<value>Hours Played</value>
<value>Game Hours Record</value>
</data>
<data name="ViewPageLaunchGameProcessHeader" xml:space="preserve">
<value>Progress</value>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>Backdrop Material</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>Image Copyright Information</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>Change the source of wallpaper, restart Snap Hutao to apply the change</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>Wallpaper Image</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>Using local images as the background</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>Images cache are saved here</value>
</data>
@@ -2544,10 +2601,10 @@
<value>Reset Image Resource</value>
</data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsDescription" xml:space="preserve">
<value>在启动游戏页面的进程部分加入解锁帧率限制选项</value>
<value>Add Unlock Frame Rate Limit Option in Game Launcher Process Section</value>
</data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsHeader" xml:space="preserve">
<value>启动游戏-解锁帧率限制</value>
<value>Game Launcher - Unlock Frame Rate Limit</value>
</data>
<data name="ViewPageSettingSetDataFolderDescription" xml:space="preserve">
<value>You need to move data in the directory manually, otherwise new user data will be created.</value>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>Rate Snap Hutao</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>Change window theme</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>Theme</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>Contribute Translations</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 Runtime</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>Second Half</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>First Half</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>Artifact Set Combination</value>
</data>
@@ -2697,7 +2766,7 @@
<value>Character Appearance Rate = Character Appearance in this Floor (only count for 1 if repeated) / Total Number of Abyss Record of this Floor</value>
</data>
<data name="ViewSpiralAbyssAvatarUsageRankDescription" xml:space="preserve">
<value>Character Usage Rate = Character Appearance in this Floor (only count for 1 is repeated) / Number of Player who Own this Character</value>
<value>Character Usage Rate = Character Appearance in this Floor (only count for 1 if repeated) / Number of Player who Own this Character</value>
</data>
<data name="ViewSpiralAbyssBattleHeader" xml:space="preserve">
<value>Battle Statistics</value>
@@ -2853,7 +2922,7 @@
<value>〓Event Duration〓.*?\d\.\d Available throughout the entirety of Version</value>
</data>
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve">
<value>(?:〓Event Duration〓|Event Wish Duration|【Availability Duration】).*?(\d\.\dAfter the Version update).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
<value>(?:〓Event Duration〓|Event Wish Duration|【Availability Duration】|〓Discount Period〓).*?(\d\.\dAfter the Version update).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
</data>
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
<value>〓Update Maintenance Duration〓.+?&amp;lt;t class=\"t_(?:gl|lc)\".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>Character Event Wish-2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>Chronicled Wish</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>Beginners' Wish</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>WebView2 Runtime tidak terdeteksi.</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] Hotkey [{1}] gagal terdaftar</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>浅色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟随系统</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>Ekspor</value>
</data>
@@ -199,19 +211,19 @@
<value>Pilih akun untuk memulai</value>
</data>
<data name="MetadataSpecialNameMetaAvatarSexProInfoPronounBoyGirlD" xml:space="preserve">
<value>&lt;color=#1E90FF&gt;王子&lt;/color&gt;/&lt;color=#FFB6C1&gt;公主&lt;/color&gt;</value>
<value>&lt;color=#1E90FF&gt;Prince&lt;/color&gt;/&lt;color=#FFB6C1&gt;Princess&lt;/color&gt;</value>
</data>
<data name="MetadataSpecialNameMetaAvatarSexProInfoPronounBoyGirlFirst" xml:space="preserve">
<value>&lt;color=#1E90FF&gt;&lt;/color&gt;/&lt;color=#FFB6C1&gt;&lt;/color&gt;</value>
<value>&lt;color=#1E90FF&gt;I&lt;/color&gt;/&lt;color=#FFB6C1&gt;I&lt;/color&gt;</value>
</data>
<data name="MetadataSpecialNameNickname" xml:space="preserve">
<value>Pengembara</value>
</data>
<data name="MetadataSpecialNamePlayerAvatarSexProInfoPronounHeShe" xml:space="preserve">
<value>&lt;color=#1E90FF&gt;&lt;/color&gt;/&lt;color=#FFB6C1&gt;&lt;/color&gt;</value>
<value>&lt;color=#1E90FF&gt;He&lt;/color&gt;/&lt;color=#FFB6C1&gt;She&lt;/color&gt;</value>
</data>
<data name="MetadataSpecialNameRealNameId1" xml:space="preserve">
<value>流浪者</value>
<value>Pengembara</value>
</data>
<data name="ModelBindingAvatarPropertyWeaponAffixFormat" xml:space="preserve">
<value>Perbaiki {0}</value>
@@ -513,7 +525,7 @@
<value>Gelombang 4: Gelombang akan muncul hanya setelah membunuh semua musuh di gelombang sebelumnya</value>
</data>
<data name="ModelMetadataTowerWaveTypeWave99999" xml:space="preserve">
<value>维持场上 4 个盗宝团怪物,击杀后立即替换,总数 12</value>
<value>Tetapkan 4 Perampok Harta Karun di lapangan, langsung muncul kembali setelah mati. Total 12.</value>
</data>
<data name="ModelNameValueDefaultDescription" xml:space="preserve">
<value>Silakan perbarui data tampilan.</value>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Pameran Karakter: {0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>Wallpaper Harian Bing</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>Wallpaper Harian Hutao</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>Wallpaper Resmi Peluncur Genshin</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>Gambar Acak Lokal</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>Tanpa Gambar Latar</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Gagal menyimpan status rencana pengembangan</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>Parametric Transformer telah siap</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>Izin hilang, tidak dapat mengatur Aktivitas Discord Anda.</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Menjelajahi di Teyvat</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>Event Wish Karakter</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>Wanderlust Invocation</value>
</data>
@@ -1206,10 +1239,10 @@
<value>Catatan Realtime Webhook URL</value>
</data>
<data name="ViewDialogFeedbackEnableLoopbackContent" xml:space="preserve">
<value>解除限制后需要使用其他工具恢复限制</value>
<value>Anda memerlukan alat lain untuk mengembalikan loopback setelah dikecualikan</value>
</data>
<data name="ViewDialogFeedbackEnableLoopbackTitle" xml:space="preserve">
<value>是否解除 Loopback 限制</value>
<value>Konfirmasi untuk Mengonfigurasi Pengecualian Loopback</value>
</data>
<data name="ViewDialogGachaLogImportTitle" xml:space="preserve">
<value>Mengimpor riwayat wish</value>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Game Launcher</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>Tidak dapat mengurutkan dalam Mode Administrator</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>Arsip [{0}] berhasil ditambahkan</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Selesai</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>Stream respons tidak berisi tipe konten yang valid</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>Mengantre</value>
</data>
@@ -1887,16 +1926,16 @@
<value>Tautan Berguna</value>
</data>
<data name="ViewPageFeedbackCurrentProxyHeader" xml:space="preserve">
<value>当前代理</value>
<value>Proxy Saat ini</value>
</data>
<data name="ViewPageFeedbackCurrentProxyNoProxyDescription" xml:space="preserve">
<value>无代理</value>
<value>Tidak ada Proxy</value>
</data>
<data name="ViewPageFeedbackEnableLoopbackEnabledDescription" xml:space="preserve">
<value>已解除</value>
<value>Dikecualikan</value>
</data>
<data name="ViewPageFeedbackEnableLoopbackHeader" xml:space="preserve">
<value>解除 Loopback 限制</value>
<value>Konfigurasikan Pengecualian Loopback</value>
</data>
<data name="ViewPageFeedbackEngageWithUsDescription" xml:space="preserve">
<value>Tetap berhubungan dengan kami</value>
@@ -2010,7 +2049,7 @@
<value>Pratinjau</value>
</data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value>
<value>Statistik</value>
</data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>Senjata</value>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>Argumen Awalan</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>Mulai Otomatis Antarmuka Pengguna yang Lebih Baik untuk tugas otomatis setelah game diluncurkan</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>自动化任务</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>Umum</value>
</data>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>Backdrop Material</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>Informasi Hak Cipta Gambar</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>Ubah sumber gambar latar, restart Snap Hutao untuk menerapkan perubahan</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>Gambar Latar</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>当前背景为本地图片,如遇版权问题由用户个人负责</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>Cache gambar disimpan di sini</value>
</data>
@@ -2334,7 +2391,7 @@
<value>Berkas Cache</value>
</data>
<data name="ViewPageSettingCardHutaoPassportHeader" xml:space="preserve">
<value>胡桃通行证</value>
<value>Hutao Passport</value>
</data>
<data name="ViewPageSettingCopyDeviceIdAction" xml:space="preserve">
<value>Salin</value>
@@ -2529,10 +2586,10 @@
<value>Website Resmi</value>
</data>
<data name="ViewPageSettingOpenBackgroundImageFolderDescription" xml:space="preserve">
<value>自定义背景图片,支持 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式</value>
<value>Latar Belakang Kustom, format didukung bmp/gif/ico/jpg/jpeg/png/tiff/webp</value>
</data>
<data name="ViewPageSettingOpenBackgroundImageFolderHeader" xml:space="preserve">
<value>打开背景图片文件夹</value>
<value>Buka Berkas Latar Belakang</value>
</data>
<data name="ViewPageSettingResetAction" xml:space="preserve">
<value>Reset</value>
@@ -2544,10 +2601,10 @@
<value>Setel ulang Sumber Daya Gambar</value>
</data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsDescription" xml:space="preserve">
<value>在启动游戏页面的进程部分加入解锁帧率限制选项</value>
<value>Tambahkan Opsi Batasan FPS di Bagian Proses Peluncur Permainan</value>
</data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsHeader" xml:space="preserve">
<value>启动游戏-解锁帧率限制</value>
<value>Peluncur Permainan - Buka Limit FPS</value>
</data>
<data name="ViewPageSettingSetDataFolderDescription" xml:space="preserve">
<value>Anda perlu memindahkan data di direktori secara manual, jika tidak, data pengguna baru akan dibuat.</value>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>Beri Rating untuk Snap Hutao</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗体的颜色主题</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>颜色主题</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>Kontribusi penerjemahan</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 Runtime</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>Kombinasi Set Artefak</value>
</data>
@@ -2853,7 +2922,7 @@
<value>〓Durasi Event〓.*?\d\.\d Tersedia selama versi ini</value>
</data>
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve">
<value>(?:〓Durasi Event〓|Durasi Event Wish|【Ketersediaan DUrasi】).*?(\d\.\dSetelah pembaruan versi).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
<value>(?:〓Waktu Acara〓|Waktu Menginginkan|【Waktu Peluncuran】|〓Waktu Diskon〓).*?(\d\.\d Setelah Pembaruan Versi).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
</data>
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
<value>〓Durasi Pemeliharaan Pembaruan.+?&amp;lt;t class=\"t_(?:gl|lc)\".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>Event WIsh Karakter-2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>Wish Pemula</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>WebView2 ランタイムが検出されませんでした</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 热键 [{1}] 注册失败</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>浅色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟随系统</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>エクスポート</value>
</data>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>キャラクターラインナップ:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>必应每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>胡桃每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>官方启动器壁纸</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>本地随机图片</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>无背景图片</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>育成計画のステータスを保存できません</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>参量物質変化器は使用可能</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>テイワット大陸を探索中</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>イベント祈願・キャラクター</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>奔走世間</value>
</data>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>ゲームランチャー</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>アーカイブ [{0}] を作成しました</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>完了</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>待機中</value>
</data>
@@ -2010,7 +2049,7 @@
<value>一覧</value>
</data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value>
<value>統計</value>
</data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>武器</value>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>コマンドラインパラメーター</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>自动化任务</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>一般</value>
</data>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>テーマ</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>图片版权信息</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>更改窗体的背景图片来源,重启胡桃以尽快生效</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>背景图片</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>当前背景为本地图片,如遇版权问题由用户个人负责</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>イメージキャッシュはここに格納されます</value>
</data>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>レビューや感想</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗体的颜色主题</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>颜色主题</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>和訳を提供</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 ランタイム</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>おすすめ聖遺物</value>
</data>
@@ -2856,10 +2925,10 @@
<value>(?:〓イベント期間〓|祈願期間|【開始日時】).*?(\d\.\dバージョンアップ完了後).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
</data>
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
<value>〓更新日時〓.+?&amp;lt;t class=\"t_(?:gl|lc)\".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
<value>〓メンテナンス時間〓.+?&amp;lt;t class=\"t_(?:gl|lc)\".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
</data>
<data name="WebAnnouncementMatchVersionUpdateTitle" xml:space="preserve">
<value>Ver.\d\.\d 更新内容</value>
<value>Ver.\d\.\d.+正式リリース</value>
</data>
<data name="WebAnnouncementTimeDaysBeginFormat" xml:space="preserve">
<value>{0} 日後に開始</value>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>イベント祈願・キャラクター2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>初心者祈願</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>WebView2 런타임이 감지되지 않음</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 热键 [{1}] 注册失败</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>浅色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟随系统</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>내보내기</value>
</data>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色橱窗:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>必应每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>胡桃每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>官方启动器壁纸</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>本地随机图片</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>无背景图片</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>육성 계획 상태를 저장하지 못했습니다</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>매개 변수 변환기가 준비되었습니다</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>正在提瓦特大陆中探索</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>캐릭터 이벤트</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>세상 여행</value>
</data>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>게임 시작</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>아카이브 [{0}]가 추가되었습니다</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>완료</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>대기 중</value>
</data>
@@ -2010,7 +2049,7 @@
<value>개요</value>
</data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value>
<value>统计</value>
</data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>무기</value>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>启动参数</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>自动化任务</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>보통</value>
</data>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>배경 테마</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>图片版权信息</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>更改窗体的背景图片来源,重启胡桃以尽快生效</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>背景图片</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>当前背景为本地图片,如遇版权问题由用户个人负责</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>여기에 저장된 이미지 캐시</value>
</data>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>评价软件</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗体的颜色主题</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>颜色主题</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>번역에 기여하기</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 런타임</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>搭配圣遗物</value>
</data>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>캐릭터 이벤트 기원-2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>초심자 기원</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>O WebView2 Runtime não foi detectado</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 热键 [{1}] 注册失败</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>浅色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟随系统</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>Exportar</value>
</data>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Exibição de personagens: {0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>必应每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>胡桃每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>官方启动器壁纸</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>本地随机图片</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>无背景图片</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Falha ao salvar o status do planejamento</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>O Transformador Paramétrico está pronto</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Explorando em Teyvat</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>Evento de oração de personagem</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>Invocação do Mochileiro</value>
</data>
@@ -1104,7 +1137,7 @@
<value>Sorte média</value>
</data>
<data name="ViewControlStatisticsCardUpText" xml:space="preserve">
<value>Acima</value>
<value>Em destaque</value>
</data>
<data name="ViewControlStatisticsSegmentedItemContentPrediction" xml:space="preserve">
<value>Previsão</value>
@@ -1122,7 +1155,7 @@
<value>Planejamento</value>
</data>
<data name="ViewDailyNoteHeader" xml:space="preserve">
<value>Lembrete em tempo real</value>
<value>Lembretes</value>
</data>
<data name="ViewDataHeader" xml:space="preserve">
<value>Dados</value>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Inicializador</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>Arquivo [{0}] adicionado com sucesso</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Concluído</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>Em fila</value>
</data>
@@ -2010,7 +2049,7 @@
<value>Visão geral</value>
</data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value>
<value>Estatísticas globais</value>
</data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>Arma</value>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>Argumentos de inicialização</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>自动化任务</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>Geral</value>
</data>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>Material de pano de fundo</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>图片版权信息</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>更改窗体的背景图片来源,重启胡桃以尽快生效</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>背景图片</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>当前背景为本地图片,如遇版权问题由用户个人负责</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>O cache de imagens é salvo aqui</value>
</data>
@@ -2532,7 +2589,7 @@
<value>自定义背景图片,支持 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式</value>
</data>
<data name="ViewPageSettingOpenBackgroundImageFolderHeader" xml:space="preserve">
<value>打开背景图片文件夹</value>
<value>Abrir pasta do fundo</value>
</data>
<data name="ViewPageSettingResetAction" xml:space="preserve">
<value>Resetar</value>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>Avalie o Snap Hutao</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗体的颜色主题</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>颜色主题</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>Contribuir com traduções</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 Runtime</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>Combinação de conjuntos de artefatos</value>
</data>
@@ -2922,7 +2991,7 @@
<value>Recompensa de comissão diária resgatada</value>
</data>
<data name="WebDailyNoteHomeCoinRecoveryFormat" xml:space="preserve">
<value>Estará cheio em {0} {1:HH:mm}</value>
<value>Estará cheio {0} às {1:HH:mm}</value>
</data>
<data name="WebDailyNoteHomeLocked" xml:space="preserve">
<value>Bule de Relachá não desbloqueado</value>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>Evento de oração de personagem-2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>Oração de Novatos</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>未检测到 WebView2 运行时</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 热键 [{1}] 注册失败</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>浅色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟随系统</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>导出</value>
</data>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色橱窗:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>必应每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>胡桃每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>官方启动器壁纸</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>本地随机图片</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>无背景图片</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>保存养成计划状态失败</value>
</data>
@@ -842,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>角色活动</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>奔行世间</value>
</data>
@@ -1676,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>完成</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>等待中</value>
</data>
@@ -2196,7 +2229,7 @@
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
<value>自动化任务</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>常规</value>
@@ -2214,7 +2247,7 @@
<value>文件</value>
</data>
<data name="ViewPageLaunchGameInterProcessHeader" xml:space="preserve">
<value>进程</value>
<value>进程联动</value>
</data>
<data name="ViewPageLaunchGameMonitorsDescription" xml:space="preserve">
<value>在指定的显示器上运行</value>
@@ -2339,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>背景材质</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>图片版权信息</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>更改窗体的背景图片来源,重启胡桃以尽快生效</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>背景图片</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>当前背景为本地图片,如遇版权问题由用户个人负责</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>图片缓存 在此处存放</value>
</data>
@@ -2594,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>评价软件</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗体的颜色主题</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>颜色主题</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>贡献翻译</value>
</data>
@@ -2603,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 运行时</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>搭配圣遗物</value>
</data>
@@ -2865,7 +2922,7 @@
<value>〓活动时间〓.*?\d\.\d版本期间持续开放</value>
</data>
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve">
<value>(?:〓活动时间〓|祈愿时间|【上架时间】).*?(\d\.\d版本更新后).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
<value>(?:〓活动时间〓|祈愿时间|【上架时间】|〓折扣时间〓).*?(\d\.\d版本更新后).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
</data>
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
<value>〓更新时间〓.+?&amp;lt;t class=\"t_(?:gl|lc)\".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
@@ -3017,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>角色活动祈愿-2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>新手祈愿</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>Среда выполнения WebView2 не обнаружена</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 热键 [{1}] 注册失败</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>浅色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟随系统</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>Экспорт</value>
</data>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Демонстрация персонажей: {0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>必应每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>胡桃每日一图</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>官方启动器壁纸</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>本地随机图片</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>无背景图片</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Не удалось сохранить статус плана разработки.</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>Преобразователь готов</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Исследование Тейвата</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>角色活动</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>奔行世间</value>
</data>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Game Launcher</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>存档 [{0}] 添加成功</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Завершено</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>В процессе</value>
</data>
@@ -2010,7 +2049,7 @@
<value>总览</value>
</data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value>
<value>统计</value>
</data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>Оружие</value>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>启动参数</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>自动化任务</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>常规</value>
</data>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>背景材质</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>图片版权信息</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>更改窗体的背景图片来源,重启胡桃以尽快生效</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>背景图片</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>当前背景为本地图片,如遇版权问题由用户个人负责</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>图片缓存 在此处存放</value>
</data>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>评价软件</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗体的颜色主题</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>颜色主题</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>贡献翻译</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 Runtime</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>搭配圣遗物</value>
</data>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>Молитва события персонажа - 2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>Молитва новичка</value>
</data>

View File

@@ -186,6 +186,18 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>未檢測到 WebView2 運行時</value>
</data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 鍵盤快速鍵 [{1}] 註冊失敗</value>
</data>
<data name="CoreWindowThemeDark" xml:space="preserve">
<value>深色</value>
</data>
<data name="CoreWindowThemeLight" xml:space="preserve">
<value>淺色</value>
</data>
<data name="CoreWindowThemeSystem" xml:space="preserve">
<value>跟隨系統</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve">
<value>匯出</value>
</data>
@@ -205,7 +217,7 @@
<value>&lt;color=#1E90FF&gt;我&lt;/color&gt;/&lt;color=#FFB6C1&gt;我&lt;/color&gt;</value>
</data>
<data name="MetadataSpecialNameNickname" xml:space="preserve">
<value>旅</value>
<value>旅行者</value>
</data>
<data name="MetadataSpecialNamePlayerAvatarSexProInfoPronounHeShe" xml:space="preserve">
<value>&lt;color=#1E90FF&gt;他&lt;/color&gt;/&lt;color=#FFB6C1&gt;她&lt;/color&gt;</value>
@@ -513,7 +525,7 @@
<value>第四波:擊敗所有怪物,下一波才會出現</value>
</data>
<data name="ModelMetadataTowerWaveTypeWave99999" xml:space="preserve">
<value>维持场上 4 个盗宝团怪物,击杀后立即替换,总数 12 </value>
<value>維持場上 4 個盜寶團怪物,擊殺後立即替換,總數 12 </value>
</data>
<data name="ModelNameValueDefaultDescription" xml:space="preserve">
<value>請更新角色櫥窗數據</value>
@@ -767,6 +779,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色櫥窗:{0:MM-dd HH:mm}</value>
</data>
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
<value>Bing每日一圖</value>
</data>
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
<value>胡桃每日一圖</value>
</data>
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
<value>官方啟動器壁紙</value>
</data>
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
<value>本地隨機圖片</value>
</data>
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
<value>無背景圖片</value>
</data>
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>保存養成計劃狀態失敗</value>
</data>
@@ -824,6 +851,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>參量質變儀已準備完成</value>
</data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>權限不足,將無法為您設定 Discord Activity 狀態</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>正在提瓦特大陸中探索</value>
</data>
@@ -839,6 +869,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>角色活動</value>
</data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集錄祈願</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>奔行世間</value>
</data>
@@ -1206,7 +1239,7 @@
<value>即時便箋 Webhook Url</value>
</data>
<data name="ViewDialogFeedbackEnableLoopbackContent" xml:space="preserve">
<value>解除限制后需要使用其他工具恢限制</value>
<value>解除限制後需使用其他工具恢限制</value>
</data>
<data name="ViewDialogFeedbackEnableLoopbackTitle" xml:space="preserve">
<value>是否解除 Loopback 限制</value>
@@ -1391,6 +1424,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve">
<value>啟動遊戲</value>
</data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理員模式下無法拖動排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>存檔 [{0}] 添加成功</value>
</data>
@@ -1670,6 +1706,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>完成</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>回應內容不是有效的檔案位元組</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>待處理</value>
</data>
@@ -1887,16 +1926,16 @@
<value>常用連結</value>
</data>
<data name="ViewPageFeedbackCurrentProxyHeader" xml:space="preserve">
<value>前代理</value>
<value>前代理</value>
</data>
<data name="ViewPageFeedbackCurrentProxyNoProxyDescription" xml:space="preserve">
<value>代理</value>
<value>代理</value>
</data>
<data name="ViewPageFeedbackEnableLoopbackEnabledDescription" xml:space="preserve">
<value>已解除</value>
</data>
<data name="ViewPageFeedbackEnableLoopbackHeader" xml:space="preserve">
<value>解除 Loopback 限制</value>
<value>是否解除 Loopback 限制</value>
</data>
<data name="ViewPageFeedbackEngageWithUsDescription" xml:space="preserve">
<value>與我們密切聯繫</value>
@@ -2010,7 +2049,7 @@
<value>總覽</value>
</data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value>
<value>統計</value>
</data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>武器</value>
@@ -2186,6 +2225,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>啟動參數</value>
</data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在遊戲啟動後嘗試啟動並使用 Better GI 進行自動化任務</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>自動化任務</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>一般</value>
</data>
@@ -2202,7 +2247,7 @@
<value>檔案</value>
</data>
<data name="ViewPageLaunchGameInterProcessHeader" xml:space="preserve">
<value>行程間</value>
<value>進程聯動</value>
</data>
<data name="ViewPageLaunchGameMonitorsDescription" xml:space="preserve">
<value>在指定的屏幕上運行</value>
@@ -2327,6 +2372,18 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>背景材質</value>
</data>
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
<value>圖片版權訊息</value>
</data>
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
<value>更改視窗的背景圖片來源,重啟胡桃以盡快生效</value>
</data>
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
<value>背景圖片</value>
</data>
<data name="ViewPageSettingBackgroundImageLocalFolderCopyrightHeader" xml:space="preserve">
<value>當前背景為本地圖片,如遇版權問題由用戶個人負責</value>
</data>
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>圖片暫存存放在此</value>
</data>
@@ -2334,7 +2391,7 @@
<value>暫存檔案夾</value>
</data>
<data name="ViewPageSettingCardHutaoPassportHeader" xml:space="preserve">
<value>胡桃通行</value>
<value>胡桃通行</value>
</data>
<data name="ViewPageSettingCopyDeviceIdAction" xml:space="preserve">
<value>複製</value>
@@ -2529,10 +2586,10 @@
<value>前往官網</value>
</data>
<data name="ViewPageSettingOpenBackgroundImageFolderDescription" xml:space="preserve">
<value>自定背景片,支 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式</value>
<value>自定背景片,支 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式</value>
</data>
<data name="ViewPageSettingOpenBackgroundImageFolderHeader" xml:space="preserve">
<value>打背景图片文件夹</value>
<value>打背景圖片資料夾</value>
</data>
<data name="ViewPageSettingResetAction" xml:space="preserve">
<value>重設</value>
@@ -2544,10 +2601,10 @@
<value>重設圖片資源</value>
</data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsDescription" xml:space="preserve">
<value>在启动游戏页面的进程部分加入解锁帧率限制选项</value>
<value>在啟動遊戲頁面的程序部分加入解鎖幀率限制選項</value>
</data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsHeader" xml:space="preserve">
<value>启动游戏-解锁帧率限制</value>
<value>啟動遊戲-解鎖幀率限制</value>
</data>
<data name="ViewPageSettingSetDataFolderDescription" xml:space="preserve">
<value>更改目錄后需要手動移動目錄内的數據,否則會重新創建用戶數據</value>
@@ -2582,6 +2639,12 @@
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
<value>評價軟體</value>
</data>
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
<value>更改窗體的顏色主題</value>
</data>
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
<value>顏色主題</value>
</data>
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
<value>貢獻翻譯</value>
</data>
@@ -2591,6 +2654,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>WebView 2 運行時</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceDownHeader" xml:space="preserve">
<value>下半</value>
</data>
<data name="ViewPageSpiralAbyssTeamAppearanceUpHeader" xml:space="preserve">
<value>上半</value>
</data>
<data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>搭配聖遺物</value>
</data>
@@ -2853,7 +2922,7 @@
<value>〓活動時間〓.*?\d\.\d版本期間持續開放</value>
</data>
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve">
<value>(?:〓活動時間〓|祈願時間|【上架時間】).*?(\d\.\d版本更新後).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
<value>(?:〓活動時間〓|祈願時間|【上架時間】|〓折扣時間〓).*?(\d\.\d版本更新後).*?~.*?&amp;lt;t class="t_(?:gl|lc)".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
</data>
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
<value>〓更新時間〓.+?&amp;lt;t class=\"t_(?:gl|lc)\".*?&amp;gt;(.*?)&amp;lt;/t&amp;gt;</value>
@@ -3005,6 +3074,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>角色活動祈願-2</value>
</data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集錄祈願</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>新手祈願</value>
</data>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -85,8 +85,13 @@ internal sealed partial class AnnouncementService : IAnnouncementService
{
foreach (ref readonly Announcement item in CollectionsMarshal.AsSpan(listWrapper.List))
{
item.Subtitle = new StringBuilder(item.Subtitle).Replace("\r<br>", string.Empty).ToString();
item.Content = AnnouncementRegex.XmlTimeTagRegex.Replace(item.Content, x => x.Groups[1].Value);
item.Subtitle = new StringBuilder(item.Subtitle)
.Replace("\r<br>", string.Empty)
.Replace("<br />", string.Empty)
.ToString();
item.Content = AnnouncementRegex
.XmlTimeTagRegex()
.Replace(item.Content, x => x.Groups[1].Value);
}
}
}
@@ -133,7 +138,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
continue;
}
MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex.Matches(announcement.Content);
MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex().Matches(announcement.Content);
if (matches.Count < 2)
{
continue;

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity;
@@ -16,6 +17,7 @@ internal sealed partial class AppOptions : DbStoreOptions
{
private bool? isEmptyHistoryWishVisible;
private BackdropType? backdropType;
private ElementTheme? elementTheme;
private BackgroundImageType? backgroundImageType;
private Region? region;
private string? geetestCustomCompositeUrl;
@@ -34,9 +36,24 @@ internal sealed partial class AppOptions : DbStoreOptions
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, EnumToStringOrEmpty);
}
public Lazy<List<NameValue<ElementTheme>>> LazyElementThemes { get; } = new(() =>
[
new(SH.CoreWindowThemeLight, ElementTheme.Light),
new(SH.CoreWindowThemeDark, ElementTheme.Dark),
new(SH.CoreWindowThemeSystem, ElementTheme.Default),
]);
public ElementTheme ElementTheme
{
get => GetOption(ref elementTheme, SettingEntry.ElementTheme, EnumParse<ElementTheme>, ElementTheme.Default).Value;
set => SetOption(ref elementTheme, SettingEntry.ElementTheme, value, EnumToStringOrEmpty);
}
public List<NameValue<BackgroundImageType>> BackgroundImageTypes { get; } = CollectionsNameValue.FromEnum<BackgroundImageType>(type => type.GetLocalizedDescription());
public BackgroundImageType BackgroundImageType
{
get => GetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, EnumParse<BackgroundImageType>, BackgroundImageType.HutaoOfficialLauncher).Value;
get => GetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, EnumParse<BackgroundImageType>, BackgroundImageType.None).Value;
set => SetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, value, EnumToStringOrEmpty);
}

View File

@@ -2,11 +2,6 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Media.Imaging;
using Snap.Hutao.Control.Media;
using Snap.Hutao.Core;
using System.IO;
using System.Runtime.InteropServices;
using Windows.Graphics.Imaging;
using Windows.UI;
namespace Snap.Hutao.Service.BackgroundImage;

View File

@@ -0,0 +1,15 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.ComponentModel;
using Snap.Hutao.Web.Hutao.Wallpaper;
namespace Snap.Hutao.Service.BackgroundImage;
[Injection(InjectAs.Singleton)]
internal sealed partial class BackgroundImageOptions : ObservableObject
{
private Wallpaper? wallpaper;
public Wallpaper? Wallpaper { get => wallpaper; set => SetProperty(ref wallpaper, value); }
}

View File

@@ -5,11 +5,11 @@ using Snap.Hutao.Control.Media;
using Snap.Hutao.Core;
using Snap.Hutao.Core.Caching;
using Snap.Hutao.Core.IO;
using Snap.Hutao.Service.Game.Scheme;
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher;
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher.Content;
using Snap.Hutao.Web.Hutao.Wallpaper;
using Snap.Hutao.Web.Response;
using Snap.Hutao.Win32.Foundation;
using System.IO;
using System.Runtime.InteropServices;
using Windows.Graphics.Imaging;
namespace Snap.Hutao.Service.BackgroundImage;
@@ -20,22 +20,24 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
{
private static readonly HashSet<string> AllowedFormats = [".bmp", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".tiff", ".webp"];
private readonly BackgroundImageOptions backgroundImageOptions;
private readonly IServiceProvider serviceProvider;
private readonly RuntimeOptions runtimeOptions;
private readonly ITaskContext taskContext;
private readonly AppOptions appOptions;
private HashSet<string> backgroundPathSet;
private HashSet<string> currentBackgroundPathSet;
public async ValueTask<ValueResult<bool, BackgroundImage>> GetNextBackgroundImageAsync(BackgroundImage? previous)
public async ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous)
{
HashSet<string> backgroundSet = await SkipOrInitBackgroundAsync().ConfigureAwait(false);
if (backgroundSet.Count <= 0)
{
return new(false, default!);
return new(true, default!);
}
string path = System.Random.Shared.GetItems(backgroundSet.ToArray(), 1)[0];
string path = System.Random.Shared.GetItems([.. backgroundSet], 1)[0];
backgroundSet.Remove(path);
if (string.Equals(path, previous?.Path, StringComparison.OrdinalIgnoreCase))
@@ -45,7 +47,21 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
using (FileStream fileStream = File.OpenRead(path))
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream.AsRandomAccessStream());
BitmapDecoder decoder;
try
{
decoder = await BitmapDecoder.CreateAsync(fileStream.AsRandomAccessStream());
}
catch (COMException comException)
{
if (comException.HResult != HRESULT.E_FAIL)
{
throw;
}
return new(false, default!);
}
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight);
Bgra32 accentColor = softwareBitmap.GetAccentColor();
@@ -65,32 +81,58 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync()
{
if (backgroundPathSet is not { Count: > 0 })
switch (appOptions.BackgroundImageType)
{
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
Directory.CreateDirectory(backgroundFolder);
backgroundPathSet = Directory
.GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories)
.Where(path => AllowedFormats.Contains(Path.GetExtension(path)))
.ToHashSet();
// No image found
if (backgroundPathSet.Count <= 0)
{
ResourceClient resourceClient = serviceProvider.GetRequiredService<ResourceClient>();
string launguageCode = serviceProvider.GetRequiredService<CultureOptions>().LanguageCode;
LaunchScheme scheme = launguageCode is "zh-cn"
? KnownLaunchSchemes.Get().First(scheme => !scheme.IsOversea && scheme.IsNotCompatOnly)
: KnownLaunchSchemes.Get().First(scheme => scheme.IsOversea && scheme.IsNotCompatOnly);
Response<GameContent> response = await resourceClient.GetContentAsync(scheme, launguageCode).ConfigureAwait(false);
if (response is { Data.Advertisement.Background: string url })
case BackgroundImageType.LocalFolder:
{
ValueFile file = await serviceProvider.GetRequiredService<IImageCache>().GetFileFromCacheAsync(url.ToUri()).ConfigureAwait(false);
backgroundPathSet = [file];
if (currentBackgroundPathSet is not { Count: > 0 })
{
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
Directory.CreateDirectory(backgroundFolder);
currentBackgroundPathSet = Directory
.GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories)
.Where(path => AllowedFormats.Contains(Path.GetExtension(path)))
.ToHashSet();
}
backgroundImageOptions.Wallpaper = default;
break;
}
case BackgroundImageType.HutaoBing:
await SetCurrentBackgroundPathSetAsync(client => client.GetBingWallpaperAsync()).ConfigureAwait(false);
break;
case BackgroundImageType.HutaoDaily:
await SetCurrentBackgroundPathSetAsync(client => client.GetTodayWallpaperAsync()).ConfigureAwait(false);
break;
case BackgroundImageType.HutaoOfficialLauncher:
await SetCurrentBackgroundPathSetAsync(client => client.GetLauncherWallpaperAsync()).ConfigureAwait(false);
break;
default:
currentBackgroundPathSet = [];
break;
}
currentBackgroundPathSet ??= [];
return currentBackgroundPathSet;
async Task SetCurrentBackgroundPathSetAsync(Func<HutaoWallpaperClient, ValueTask<Response<Wallpaper>>> responseFactory)
{
HutaoWallpaperClient wallpaperClient = serviceProvider.GetRequiredService<HutaoWallpaperClient>();
Response<Wallpaper> response = await responseFactory(wallpaperClient).ConfigureAwait(false);
if (response is { Data: Wallpaper wallpaper })
{
await taskContext.SwitchToMainThreadAsync();
backgroundImageOptions.Wallpaper = wallpaper;
await taskContext.SwitchToBackgroundAsync();
if (wallpaper.Url is { } url)
{
ValueFile file = await serviceProvider.GetRequiredService<IImageCache>().GetFileFromCacheAsync(url).ConfigureAwait(false);
currentBackgroundPathSet = [file];
}
}
}
return backgroundPathSet;
}
}

View File

@@ -3,11 +3,21 @@
namespace Snap.Hutao.Service.BackgroundImage;
[Localization]
internal enum BackgroundImageType
{
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeNone))]
None,
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeLocalFolder))]
LocalFolder,
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeBing))]
HutaoBing,
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeDaily))]
HutaoDaily,
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeLauncher))]
HutaoOfficialLauncher,
}

View File

@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.BackgroundImage;
internal interface IBackgroundImageService
{
ValueTask<ValueResult<bool, BackgroundImage>> GetNextBackgroundImageAsync(BackgroundImage? previous);
ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous);
}

View File

@@ -39,7 +39,7 @@ internal sealed partial class CultivationService : ICultivationService
List<InventoryItem> entities = cultivationDbService.GetInventoryItemListByProjectId(projectId);
List<InventoryItemView> results = [];
foreach (Material meta in context.EnumerateInventroyMaterial())
foreach (Material meta in context.EnumerateInventoryMaterial())
{
InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.From(projectId, meta.Id);
results.Add(new(entity, meta, saveCommand));

View File

@@ -41,39 +41,33 @@ internal sealed partial class DiscordService : IDiscordService, IDisposable
private bool IsSupported()
{
try
{
// Actually requires a discord client to be running on Windows platform.
// If not, discord core creation code will throw.
Process[] discordProcesses = Process.GetProcessesByName("Discord");
// Actually requires a discord client to be running on Windows platform.
// If not, discord core creation code will throw.
Process[] discordProcesses = Process.GetProcessesByName("Discord");
if (discordProcesses.Length <= 0)
if (discordProcesses.Length <= 0)
{
return false;
}
foreach (Process process in discordProcesses)
{
try
{
_ = process.Handle;
}
catch (Exception)
{
if (!isInitialized)
{
isInitialized = true;
infoBarService.Warning(SH.ServiceDiscordActivityElevationRequiredHint);
}
return false;
}
foreach (Process process in discordProcesses)
{
try
{
_ = process.Handle;
}
catch (Exception)
{
if (!isInitialized)
{
infoBarService.Warning(SH.ServiceDiscordActivityElevationRequiredHint);
}
return false;
}
}
return true;
}
finally
{
isInitialized = true;
}
return true;
}
}

View File

@@ -1,41 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
using System.Collections.Frozen;
using System.Runtime.CompilerServices;
namespace Snap.Hutao.Service.GachaLog.Factory;
/// <summary>
/// 祈愿配置类型比较器
/// </summary>
internal sealed class GachaConfigTypeComparer : IComparer<GachaConfigType>
{
private static readonly Lazy<GachaConfigTypeComparer> LazyShared = new(() => new());
private static readonly FrozenDictionary<GachaConfigType, int> OrderMap = new Dictionary<GachaConfigType, int>()
{
[GachaConfigType.AvatarEventWish] = 0,
[GachaConfigType.AvatarEventWish2] = 1,
[GachaConfigType.WeaponEventWish] = 2,
[GachaConfigType.StandardWish] = 3,
[GachaConfigType.NoviceWish] = 4,
}.ToFrozenDictionary();
/// <summary>
/// 共享的比较器
/// </summary>
public static GachaConfigTypeComparer Shared { get => LazyShared.Value; }
/// <inheritdoc/>
public int Compare(GachaConfigType x, GachaConfigType y)
{
return OrderOf(x) - OrderOf(y);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int OrderOf(GachaConfigType type)
{
return OrderMap.GetValueOrDefault(type, 0);
}
}

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Model.Metadata.Abstraction;
using Snap.Hutao.ViewModel.GachaLog;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using Windows.UI;
@@ -25,7 +26,7 @@ internal static class GachaStatisticsExtension
bool isPreviousUp = true;
// mark the IsGuarantee
foreach (SummaryItem item in summaryItems)
foreach (ref readonly SummaryItem item in CollectionsMarshal.AsSpan(summaryItems))
{
if (item.IsUp && (!isPreviousUp))
{
@@ -62,4 +63,4 @@ internal static class GachaStatisticsExtension
ReadOnlySpan<byte> codes = MD5.HashData(Encoding.UTF8.GetBytes(name));
return Color.FromArgb(255, codes.Slice(0, 5).Average(), codes.Slice(5, 5).Average(), codes.Slice(10, 5).Average());
}
}
}

Some files were not shown because too many files have changed in this diff Show More