Compare commits

..

97 Commits

Author SHA1 Message Date
Lightczx
4aa9557526 code style 2024-03-07 16:20:10 +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
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
51c4e66472 reorder launch pipeline 2024-02-20 14:37:29 +08:00
Lightczx
48875195bf add wallpaper api 2024-02-20 14:25:48 +08:00
qhy040404
a179e0e838 Update build.cake (#1405) 2024-02-20 11:54:15 +08:00
qhy040404
00c3e94e97 Update alpha.yml 2024-02-20 11:27:14 +08:00
qhy040404
eec7224c07 Update alpha.yml 2024-02-20 11:27:13 +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
DismissedLight
11620816ec Merge pull request #1403 from DGP-Studio/dependabot/nuget/src/Snap.Hutao/develop/packages-a995a009f5 2024-02-20 09:07:19 +08:00
dependabot[bot]
c5b75d6f82 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.0 to 3.2.1
- [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/v.3.2.0...v3.2.1)

---
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-02-19 09:59:22 +00: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
Lightczx
a9295c0a37 impl #1388 2024-02-19 16:58:55 +08:00
DismissedLight
29cd690032 Merge pull request #1402 from DGP-Studio/dependabot/nuget/src/Snap.Hutao/develop/packages-f23264728b 2024-02-19 15:45:00 +08:00
dependabot[bot]
78d8539ae2 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.0 to 3.2.1
- [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/v.3.2.0...v3.2.1)

Updates `MSTest.TestFramework` from 3.2.0 to 3.2.1
- [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/v.3.2.0...v3.2.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
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 07:44:34 +00:00
Lightczx
7dec87586b fix #1233 2024-02-19 11:33:27 +08:00
Lightczx
d169f355f3 impl #1233 2024-02-19 10:33:25 +08:00
qhy040404
e1784e2078 Update issue templates 2024-02-18 21:16:44 +08:00
Lightczx
32b1b698df update logging message 2024-02-18 17:30:24 +08:00
Lightczx
d6c7df1593 update gacha statistics card style 2024-02-18 15:30:05 +08:00
Lightczx
904fdf7fc9 fix #1391 2024-02-18 09:43:51 +08:00
Lightczx
b3e4ebb5d3 bump nuget package version 2024-02-18 09:33:11 +08:00
DismissedLight
09b9af4575 Merge pull request #1401 from DGP-Studio/fix/1400
fix #1400
2024-02-18 09:18:48 +08:00
Lightczx
8930548f44 code style 2024-02-18 09:19:09 +08:00
DismissedLight
34dbcc6f5d Merge pull request #1392 from DGP-Studio/dependabot/nuget/src/Snap.Hutao/develop/packages-dd5dd83d2f 2024-02-18 09:00:11 +08:00
qhy040404
75c25cec53 show warning if discord is not available 2024-02-17 14:00:23 +08:00
qhy040404
22251ca937 fix #1400 2024-02-17 11:28:36 +08:00
qhy040404
57c9531db8 fix #1365 again 2024-02-16 22:19:55 +08:00
dependabot[bot]
fd73743159 Bump the packages group in /src/Snap.Hutao with 1 update
Bumps the packages group in /src/Snap.Hutao with 1 update: [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest).


Updates `Microsoft.NET.Test.Sdk` from 17.8.0 to 17.9.0
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.8.0...v17.9.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: packages
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 07:47:05 +00:00
qhy040404
6594d9032d fix wrong setting state 2024-02-12 11:29:25 +08:00
DismissedLight
ae1b452697 minor fix 2024-02-09 15:40:48 +08:00
DismissedLight
bc3df782e4 Merge pull request #1380 from DGP-Studio/fix/1379
fix #1379
2024-02-09 14:16:39 +08:00
qhy040404
635b52980b Update .gitlab-ci.yml 2024-02-07 21:13:59 +08:00
197 changed files with 3903 additions and 1264 deletions

View File

@@ -51,7 +51,7 @@ body:
description: | description: |
在胡桃工具箱的反馈中心界面,你可以找到并复制你的设备 ID 在胡桃工具箱的反馈中心界面,你可以找到并复制你的设备 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: validations:
required: false required: false
@@ -107,4 +107,3 @@ body:
options: options:
- label: 我认为上述的描述已经足以详细,以允许开发人员能复现该问题 - label: 我认为上述的描述已经足以详细,以允许开发人员能复现该问题
required: true required: true

View File

@@ -51,7 +51,7 @@ body:
description: | description: |
In Snap Hutao's Feedback Center, you can find and copy your device ID 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 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: validations:
required: false required: false
@@ -107,4 +107,3 @@ body:
options: options:
- label: I believe the description above is detail enough to allow developers to reproduce the issue - label: I believe the description above is detail enough to allow developers to reproduce the issue
required: true required: true

View File

@@ -14,3 +14,7 @@ updates:
packages: packages:
patterns: patterns:
- "*" - "*"
- package-ecosystem: "github-actions"
directory: "/.github/workflows" # GitHub Workflows
schedule:
interval: "weekly"

View File

@@ -13,16 +13,28 @@ on:
- '**.md' - '**.md'
- 'LICENSE' - 'LICENSE'
- '**.yml' - '**.yml'
pull_request:
branches:
- develop
paths-ignore:
- '.gitattributes'
- '.github/**'
- '.gitignore'
- '.gitmodules'
- '**.md'
- 'LICENSE'
- '**.yml'
- '**.resx'
jobs: jobs:
build: build:
runs-on: self-hosted runs-on: self-hosted
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4
- name: Setup .NET - name: Setup .NET
uses: actions/setup-dotnet@v4.0.0 uses: actions/setup-dotnet@v4
with: with:
dotnet-version: 8.0 dotnet-version: 8.0
@@ -34,20 +46,21 @@ jobs:
VERSION_API_TOKEN: ${{ secrets.VERSION_API_TOKEN }} VERSION_API_TOKEN: ${{ secrets.VERSION_API_TOKEN }}
- name: Sign Msix - name: Sign Msix
if: success() && github.event_name != 'pull_request'
shell: pwsh shell: pwsh
run: | run: |
[System.Convert]::FromBase64String("${{ secrets.CERTIFICATE }}") | Set-Content -AsByteStream temp.pfx [System.Convert]::FromBase64String("${{ secrets.CERTIFICATE }}") | Set-Content -AsByteStream temp.pfx
signtool.exe sign /debug /v /a /fd SHA256 /f temp.pfx /p ${{ secrets.PW }} ${{ github.workspace }}\src\output\Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix signtool.exe sign /debug /v /a /fd SHA256 /f temp.pfx /p ${{ secrets.PW }} ${{ github.workspace }}\src\output\Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
- name: Upload signed msix - name: Upload signed msix
if: success() if: success() && github.event_name != 'pull_request'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: Snap.Hutao.Alpha-${{ steps.cake.outputs.version }} name: Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}
path: ${{ github.workspace }}/src/output/Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix path: ${{ github.workspace }}/src/output/Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
- name: Add summary - name: Add summary
if: success() if: success() && github.event_name != 'pull_request'
shell: pwsh shell: pwsh
run: | run: |
$summary = " $summary = "

View File

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

View File

@@ -1,5 +1,5 @@
#tool "nuget:?package=nuget.commandline&version=6.5.0" #tool "nuget:?package=nuget.commandline&version=6.9.1"
#addin nuget:?package=Cake.Http&version=3.0.2 #addin nuget:?package=Cake.Http&version=4.0.0
var target = Argument("target", "Build"); var target = Argument("target", "Build");
var configuration = Argument("configuration", "Release"); var configuration = Argument("configuration", "Release");
@@ -33,6 +33,14 @@ if (GitHubActions.IsRunningOnGitHubActions)
repoDir = GitHubActions.Environment.Workflow.Workspace.FullPath; repoDir = GitHubActions.Environment.Workflow.Workspace.FullPath;
outputPath = System.IO.Path.Combine(repoDir, "src", "output"); outputPath = System.IO.Path.Combine(repoDir, "src", "output");
if (GitHubActions.Environment.PullRequest.IsPullRequest)
{
version = System.DateTime.Now.ToString("yyyy.M.d.0");
Information("Is Pull Request. Skip version.");
}
else
{
var versionAuth = HasEnvironmentVariable("VERSION_API_TOKEN") ? EnvironmentVariable("VERSION_API_TOKEN") : throw new Exception("Cannot find VERSION_API_TOKEN"); var versionAuth = HasEnvironmentVariable("VERSION_API_TOKEN") ? EnvironmentVariable("VERSION_API_TOKEN") : throw new Exception("Cannot find VERSION_API_TOKEN");
version = HttpGet( version = HttpGet(
"https://internal.snapgenshin.cn/BuildIntergration/RequestNewVersion", "https://internal.snapgenshin.cn/BuildIntergration/RequestNewVersion",
@@ -44,7 +52,9 @@ if (GitHubActions.IsRunningOnGitHubActions)
} }
} }
); );
Information($"Version: {version}"); Information($"Version: {version}");
}
GitHubActions.Commands.SetOutputParameter("version", version); GitHubActions.Commands.SetOutputParameter("version", version);
} }

View File

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

View File

@@ -6,6 +6,7 @@
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<XamlControlsResources/> <XamlControlsResources/>
<ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.TokenizingTextBox/TokenizingTextBox.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Loading.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Loading.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Image/CachedImage.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Image/CachedImage.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/Card.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Theme/Card.xaml"/>
@@ -22,6 +23,7 @@
<ResourceDictionary Source="ms-appx:///Control/Theme/PageOverride.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Theme/PageOverride.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/PivotOverride.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Theme/PivotOverride.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/ScrollViewer.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/SettingsStyle.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/Thickness.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Theme/Thickness.xaml"/>
<ResourceDictionary Source="ms-appx:///Control/Theme/TransitionCollection.xaml"/> <ResourceDictionary Source="ms-appx:///Control/Theme/TransitionCollection.xaml"/>

View File

@@ -23,10 +23,12 @@ internal static class ControlAnimationConstants
/// <summary> /// <summary>
/// 图像淡入 /// 图像淡入
/// </summary> /// </summary>
public static readonly TimeSpan ImageFadeIn = TimeSpan.FromSeconds(0.3); public static readonly TimeSpan ImageScaleFadeIn = TimeSpan.FromSeconds(0.3);
/// <summary> /// <summary>
/// 图像淡出 /// 图像淡出
/// </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,67 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Controls;
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;
}
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));
// TODO: CornerRadius
// Popup? popup = this.FindDescendant("SuggestionsPopup") as Popup;
}
}
private void OnQuerySubmitted(Microsoft.UI.Xaml.Controls.AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (args.ChosenSuggestion is not null)
{
return;
}
CommandExtension.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)
{
CommandExtension.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 CommunityToolkit.WinUI.Behaviors;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Snap.Hutao.Control.Extension;
namespace Snap.Hutao.Control.Behavior; namespace Snap.Hutao.Control.Behavior;
@@ -45,10 +46,6 @@ internal sealed partial class InvokeCommandOnLoadedBehavior : BehaviorBase<UIEle
return; return;
} }
if (Command is not null && Command.CanExecute(CommandParameter)) executed = Command.TryExecute(CommandParameter);
{
Command.Execute(CommandParameter);
executed = true;
}
} }
} }

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

@@ -0,0 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Control.Brush;
internal sealed class ColorSegmentCollection : List<IColorSegment>
{
}

View File

@@ -9,5 +9,5 @@ internal interface IColorSegment
{ {
Color Color { get; } Color Color { get; }
double Value { get; } double Value { get; set; }
} }

View File

@@ -9,31 +9,44 @@ using System.Runtime.InteropServices;
namespace Snap.Hutao.Control.Brush; namespace Snap.Hutao.Control.Brush;
[DependencyProperty("Source", typeof(List<IColorSegment>), default!, nameof(OnSourceChanged))] [DependencyProperty("Source", typeof(ColorSegmentCollection), default!, nameof(OnSourceChanged))]
internal sealed partial class SegmentedBar : ContentControl internal sealed partial class SegmentedBar : ContentControl
{ {
private readonly LinearGradientBrush brush = new() { StartPoint = new(0, 0), EndPoint = new(1, 0), }; private readonly LinearGradientBrush brush = new() { StartPoint = new(0, 0), EndPoint = new(1, 0), };
public SegmentedBar() public SegmentedBar()
{ {
HorizontalContentAlignment = HorizontalAlignment.Stretch;
VerticalContentAlignment = VerticalAlignment.Stretch;
Content = new Rectangle() Content = new Rectangle()
{ {
Fill = brush, Fill = brush,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
}; };
} }
private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{ {
SegmentedBar segmentedBar = (SegmentedBar)obj; UpdateLinearGradientBrush((SegmentedBar)obj);
}
private static void UpdateLinearGradientBrush(SegmentedBar segmentedBar)
{
GradientStopCollection collection = segmentedBar.brush.GradientStops; GradientStopCollection collection = segmentedBar.brush.GradientStops;
collection.Clear(); collection.Clear();
if (args.NewValue as List<IColorSegment> is [_, ..] list) ColorSegmentCollection segmentCollection = segmentedBar.Source;
double total = segmentCollection.Sum(seg => seg.Value);
if (total is 0D)
{ {
double total = list.Sum(seg => seg.Value); return;
}
double offset = 0; double offset = 0;
foreach (ref readonly IColorSegment segment in CollectionsMarshal.AsSpan(list)) foreach (ref readonly IColorSegment segment in CollectionsMarshal.AsSpan(segmentCollection))
{ {
collection.Add(new() { Color = segment.Color, Offset = offset, }); collection.Add(new() { Color = segment.Color, Offset = offset, });
offset += segment.Value / total; offset += segment.Value / total;
@@ -41,4 +54,3 @@ internal sealed partial class SegmentedBar : ContentControl
} }
} }
} }
}

View File

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

@@ -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

@@ -192,7 +192,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
{ {
await AnimationBuilder await AnimationBuilder
.Create() .Create()
.Opacity(from: 0D, to: 1D, duration: ControlAnimationConstants.ImageFadeIn) .Opacity(from: 0D, to: 1D, duration: ControlAnimationConstants.ImageScaleFadeIn)
.StartAsync(this, token) .StartAsync(this, token)
.ConfigureAwait(true); .ConfigureAwait(true);
} }
@@ -213,7 +213,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
{ {
await AnimationBuilder await AnimationBuilder
.Create() .Create()
.Opacity(from: 1D, to: 0D, duration: ControlAnimationConstants.ImageFadeOut) .Opacity(from: 1D, to: 0D, duration: ControlAnimationConstants.ImageScaleFadeOut)
.StartAsync(this, token) .StartAsync(this, token)
.ConfigureAwait(true); .ConfigureAwait(true);
} }

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

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

View File

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

View File

@@ -17,6 +17,9 @@
<ItemsPanelTemplate x:Key="HorizontalStackPanelSpacing2Template"> <ItemsPanelTemplate x:Key="HorizontalStackPanelSpacing2Template">
<StackPanel Orientation="Horizontal" Spacing="2"/> <StackPanel Orientation="Horizontal" Spacing="2"/>
</ItemsPanelTemplate> </ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="HorizontalStackPanelSpacing4Template">
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="StackPanelSpacing4Template"> <ItemsPanelTemplate x:Key="StackPanelSpacing4Template">
<StackPanel Spacing="4"/> <StackPanel Spacing="4"/>
</ItemsPanelTemplate> </ItemsPanelTemplate>

View File

@@ -0,0 +1,16 @@
// 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 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

@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved. // Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license. // Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO;
namespace Snap.Hutao.Core.Caching; namespace Snap.Hutao.Core.Caching;
@@ -10,7 +9,7 @@ namespace Snap.Hutao.Core.Caching;
/// 为图像缓存提供抽象 /// 为图像缓存提供抽象
/// </summary> /// </summary>
[HighQuality] [HighQuality]
internal interface IImageCache : ICastService internal interface IImageCache
{ {
/// <summary> /// <summary>
/// Gets the file path containing cached item for given Uri /// 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 const string CacheFolderName = nameof(ImageCache);
private readonly FrozenDictionary<int, TimeSpan> retryCountToDelay = new Dictionary<int, TimeSpan>() private readonly FrozenDictionary<int, TimeSpan> retryCountToDelay = FrozenDictionary.ToFrozenDictionary(
{ [
[0] = TimeSpan.FromSeconds(4), KeyValuePair.Create(0, TimeSpan.FromSeconds(4)),
[1] = TimeSpan.FromSeconds(16), KeyValuePair.Create(1, TimeSpan.FromSeconds(16)),
[2] = TimeSpan.FromSeconds(64), KeyValuePair.Create(2, TimeSpan.FromSeconds(64)),
}.ToFrozenDictionary(); ]);
private readonly ConcurrentDictionary<string, Task> concurrentTasks = new(); private readonly ConcurrentDictionary<string, Task> concurrentTasks = new();
@@ -42,10 +42,20 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
private string? baseFolder; private string? baseFolder;
private string? cacheFolder; private string? cacheFolder;
private string CacheFolder
{
get => LazyInitializer.EnsureInitialized(ref cacheFolder, () =>
{
baseFolder ??= serviceProvider.GetRequiredService<RuntimeOptions>().LocalCache;
DirectoryInfo info = Directory.CreateDirectory(Path.Combine(baseFolder, CacheFolderName));
return info.FullName;
});
}
/// <inheritdoc/> /// <inheritdoc/>
public void RemoveInvalid() public void RemoveInvalid()
{ {
RemoveInternal(Directory.GetFiles(GetCacheFolder()).Where(file => IsFileInvalid(file, false))); RemoveCore(Directory.GetFiles(CacheFolder).Where(file => IsFileInvalid(file, false)));
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -62,7 +72,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
return; return;
} }
string folder = GetCacheFolder(); string folder = CacheFolder;
string[] files = Directory.GetFiles(folder); string[] files = Directory.GetFiles(folder);
List<string> filesToDelete = []; List<string> filesToDelete = [];
@@ -75,16 +85,16 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
} }
} }
RemoveInternal(filesToDelete); RemoveCore(filesToDelete);
} }
/// <inheritdoc/> /// <inheritdoc/>
public async ValueTask<ValueFile> GetFileFromCacheAsync(Uri uri) public async ValueTask<ValueFile> GetFileFromCacheAsync(Uri uri)
{ {
string fileName = GetCacheFileName(uri); string fileName = GetCacheFileName(uri);
string filePath = Path.Combine(GetCacheFolder(), fileName); string filePath = Path.Combine(CacheFolder, fileName);
if (File.Exists(filePath) && new FileInfo(filePath).Length != 0) if (!IsFileInvalid(filePath))
{ {
return filePath; return filePath;
} }
@@ -94,10 +104,12 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
{ {
if (concurrentTasks.TryAdd(fileName, taskCompletionSource.Task)) if (concurrentTasks.TryAdd(fileName, taskCompletionSource.Task))
{ {
logger.LogDebug("Begin downloading image file from '{Uri}' to '{File}'", uri, filePath);
await DownloadFileAsync(uri, filePath).ConfigureAwait(false); await DownloadFileAsync(uri, filePath).ConfigureAwait(false);
} }
else if (concurrentTasks.TryGetValue(fileName, out Task? task)) else if (concurrentTasks.TryGetValue(fileName, out Task? task))
{ {
logger.LogDebug("Waiting for a queued image download task to complete for '{Uri}'", uri);
await task.ConfigureAwait(false); await task.ConfigureAwait(false);
} }
@@ -115,7 +127,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
public ValueFile GetFileFromCategoryAndName(string category, string fileName) public ValueFile GetFileFromCategoryAndName(string category, string fileName)
{ {
Uri dummyUri = Web.HutaoEndpoints.StaticRaw(category, fileName).ToUri(); Uri dummyUri = Web.HutaoEndpoints.StaticRaw(category, fileName).ToUri();
return Path.Combine(GetCacheFolder(), GetCacheFileName(dummyUri)); return Path.Combine(CacheFolder, GetCacheFileName(dummyUri));
} }
private static string GetCacheFileName(Uri uri) private static string GetCacheFileName(Uri uri)
@@ -137,17 +149,18 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
return fileInfo.Length == 0; return fileInfo.Length == 0;
} }
private void RemoveInternal(IEnumerable<string> filePaths) private void RemoveCore(IEnumerable<string> filePaths)
{ {
foreach (string filePath in filePaths) foreach (string filePath in filePaths)
{ {
try try
{ {
File.Delete(filePath); File.Delete(filePath);
logger.LogInformation("Remove cached image succeed:{File}", filePath);
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogWarning(ex, "Remove Cache Image Failed:{File}", filePath); logger.LogWarning(ex, "Remove cached image failed:{File}", filePath);
} }
} }
} }
@@ -155,14 +168,17 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
[SuppressMessage("", "SH003")] [SuppressMessage("", "SH003")]
private async Task DownloadFileAsync(Uri uri, string baseFile) private async Task DownloadFileAsync(Uri uri, string baseFile)
{ {
logger.LogInformation("Begin downloading for {Uri}", uri);
int retryCount = 0; int retryCount = 0;
HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache)); HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache));
while (retryCount < 3) while (retryCount < 3)
{ {
using (HttpResponseMessage message = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) using (HttpResponseMessage message = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
{ {
if (message.RequestMessage is { RequestUri: { } target } && target != uri)
{
logger.LogDebug("The Request '{Source}' has been redirected to '{Target}'", uri, target);
}
if (message.IsSuccessStatusCode) if (message.IsSuccessStatusCode)
{ {
using (Stream httpStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false)) using (Stream httpStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false))
@@ -181,7 +197,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
{ {
retryCount++; retryCount++;
TimeSpan delay = message.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount]; TimeSpan delay = message.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount];
logger.LogInformation("Retry {Uri} after {Delay}.", uri, delay); logger.LogInformation("Retry download '{Uri}' after {Delay}.", uri, delay);
await Task.Delay(delay).ConfigureAwait(false); await Task.Delay(delay).ConfigureAwait(false);
break; break;
} }
@@ -192,18 +208,4 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
} }
} }
} }
private string GetCacheFolder()
{
if (cacheFolder is not null)
{
return cacheFolder;
}
baseFolder ??= serviceProvider.GetRequiredService<RuntimeOptions>().LocalCache;
DirectoryInfo info = Directory.CreateDirectory(Path.Combine(baseFolder, CacheFolderName));
cacheFolder = info.FullName;
return cacheFolder;
}
} }

View File

@@ -14,7 +14,7 @@ namespace Snap.Hutao.Core.Database;
internal static class QueryableExtension internal static class QueryableExtension
{ {
/// <summary> /// <summary>
/// source.Where(predicate).ExecuteDelete() /// <code>source.Where(predicate).ExecuteDelete()</code>
/// </summary> /// </summary>
/// <typeparam name="TSource">源类型</typeparam> /// <typeparam name="TSource">源类型</typeparam>
/// <param name="source">源</param> /// <param name="source">源</param>
@@ -27,7 +27,7 @@ internal static class QueryableExtension
} }
/// <summary> /// <summary>
/// source.Where(predicate).ExecuteDeleteAsync(token) /// <code>source.Where(predicate).ExecuteDeleteAsync(token)</code>
/// </summary> /// </summary>
/// <typeparam name="TSource">源类型</typeparam> /// <typeparam name="TSource">源类型</typeparam>
/// <param name="source">源</param> /// <param name="source">源</param>

View File

@@ -6,6 +6,7 @@ namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
/// <summary> /// <summary>
/// 可转换类型服务 /// 可转换类型服务
/// </summary> /// </summary>
[Obsolete("Not useful anymore")]
internal interface ICastService internal interface ICastService
{ {
} }

View File

@@ -1,18 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
/// <summary>
/// 有名称的对象
/// 指示该对象可通过名称区分
/// </summary>
[Obsolete("无意义的接口")]
[HighQuality]
internal interface INamedService
{
/// <summary>
/// 名称
/// </summary>
string Name { get; }
}

View File

@@ -1,16 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
/// <summary>
/// 海外服/HoYoLAB 可区分
/// </summary>
[Obsolete("Use IOverseaSupportFactory instead")]
internal interface IOverseaSupport
{
/// <summary>
/// 是否为 海外服/HoYoLAB
/// </summary>
public bool IsOversea { get; }
}

View File

@@ -17,6 +17,7 @@ internal static class CastServiceExtension
/// <typeparam name="T">目标转换类型</typeparam> /// <typeparam name="T">目标转换类型</typeparam>
/// <param name="service">对象</param> /// <param name="service">对象</param>
/// <returns>转换类型后的对象</returns> /// <returns>转换类型后的对象</returns>
[Obsolete("Not useful anymore")]
public static T? As<T>(this ICastService service) public static T? As<T>(this ICastService service)
where T : class where T : class
{ {

View File

@@ -51,8 +51,13 @@ internal static class DependencyInjection
CultureOptions cultureOptions = serviceProvider.GetRequiredService<CultureOptions>(); CultureOptions cultureOptions = serviceProvider.GetRequiredService<CultureOptions>();
cultureOptions.SystemCulture = CultureInfo.CurrentCulture; cultureOptions.SystemCulture = CultureInfo.CurrentCulture;
ILogger<CultureOptions> logger = serviceProvider.GetRequiredService<ILogger<CultureOptions>>();
logger.LogDebug("System Culture: {System}", cultureOptions.SystemCulture);
CultureInfo cultureInfo = cultureOptions.CurrentCulture; CultureInfo cultureInfo = cultureOptions.CurrentCulture;
logger.LogDebug("Current Culture: {Current}", cultureInfo);
CultureInfo.DefaultThreadCurrentCulture = cultureInfo; CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo; CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
CultureInfo.CurrentCulture = cultureInfo; CultureInfo.CurrentCulture = cultureInfo;
@@ -63,6 +68,7 @@ internal static class DependencyInjection
SH.Culture = cultureInfo; SH.Culture = cultureInfo;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void InitializeConsoleWindow(this IServiceProvider serviceProvider) private static void InitializeConsoleWindow(this IServiceProvider serviceProvider)
{ {
_ = serviceProvider.GetRequiredService<ConsoleWindowLifeTime>(); _ = serviceProvider.GetRequiredService<ConsoleWindowLifeTime>();

View File

@@ -47,17 +47,13 @@ internal static class IocConfiguration
{ {
if (context.Database.GetPendingMigrations().Any()) if (context.Database.GetPendingMigrations().Any())
{ {
#if DEBUG
System.Diagnostics.Debug.WriteLine("[Database] Performing AppDbContext Migrations"); System.Diagnostics.Debug.WriteLine("[Database] Performing AppDbContext Migrations");
#endif
context.Database.Migrate(); context.Database.Migrate();
} }
} }
builder builder
#if DEBUG
.EnableSensitiveDataLogging() .EnableSensitiveDataLogging()
#endif
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.UseSqlite(sqlConnectionString); .UseSqlite(sqlConnectionString);
} }

View File

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

View File

@@ -17,6 +17,6 @@ internal readonly struct MeasureExecutionToken : IDisposable
public void Dispose() public void Dispose()
{ {
logger.LogInformation("{Caller} toke {Time} ms", callerName, stopwatch.GetElapsedTime().TotalMilliseconds); logger.LogDebug("{Caller} toke {Time} ms", callerName, stopwatch.GetElapsedTime().TotalMilliseconds);
} }
} }

View File

@@ -7,6 +7,7 @@ namespace Snap.Hutao.Core.ExceptionService;
/// 数据库损坏异常 /// 数据库损坏异常
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[Obsolete("Use HutaoException instead")]
internal sealed class DatabaseCorruptedException : Exception internal sealed class DatabaseCorruptedException : Exception
{ {
/// <summary> /// <summary>

View File

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

View File

@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved. // Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license. // Licensed under the MIT license.
using System.Numerics;
namespace Snap.Hutao.Core.ExceptionService; namespace Snap.Hutao.Core.ExceptionService;
internal sealed class HutaoException : Exception internal sealed class HutaoException : Exception
@@ -18,6 +20,12 @@ internal sealed class HutaoException : Exception
public HutaoExceptionKind Kind { get; private set; } 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) public static void ThrowIf(bool condition, HutaoExceptionKind kind, string message, Exception? innerException = default)
{ {
if (condition) if (condition)
@@ -25,4 +33,16 @@ internal sealed class HutaoException : Exception
throw new HutaoException(kind, message, innerException); 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,8 @@ namespace Snap.Hutao.Core.ExceptionService;
internal enum HutaoExceptionKind internal enum HutaoExceptionKind
{ {
None, None,
ServiceTypeCastFailed,
FileSystemCreateFileInsufficientPermissions,
PrivateNamedPipeContentHashIncorrect,
GachaStatisticsInvalidItemId,
} }

View File

@@ -8,6 +8,7 @@ namespace Snap.Hutao.Core.ExceptionService;
/// 用户的计算机中的某些设置不符合要求 /// 用户的计算机中的某些设置不符合要求
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[Obsolete("Use HutaoException instead")]
internal sealed class RuntimeEnvironmentException : Exception internal sealed class RuntimeEnvironmentException : Exception
{ {
/// <summary> /// <summary>

View File

@@ -13,6 +13,7 @@ namespace Snap.Hutao.Core.ExceptionService;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[System.Diagnostics.StackTraceHidden] [System.Diagnostics.StackTraceHidden]
[Obsolete("Use HutaoException instead")]
internal static class ThrowHelper internal static class ThrowHelper
{ {
[DoesNotReturn] [DoesNotReturn]

View File

@@ -7,6 +7,7 @@ namespace Snap.Hutao.Core.ExceptionService;
/// 用户数据损坏异常 /// 用户数据损坏异常
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[Obsolete("Use HutaoException instead")]
internal sealed class UserdataCorruptedException : Exception internal sealed class UserdataCorruptedException : Exception
{ {
/// <summary> /// <summary>

View File

@@ -28,6 +28,7 @@ internal sealed unsafe class LoopbackManager : ObservableObject
INET_FIREWALL_APP_CONTAINER* pContainers = default; INET_FIREWALL_APP_CONTAINER* pContainers = default;
try try
{
{ {
WIN32_ERROR error = NetworkIsolationEnumAppContainers(NETISO_FLAG.NETISO_FLAG_MAX, out uint acCount, out pContainers); WIN32_ERROR error = NetworkIsolationEnumAppContainers(NETISO_FLAG.NETISO_FLAG_MAX, out uint acCount, out pContainers);
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error)); Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error));
@@ -43,14 +44,16 @@ internal sealed unsafe class LoopbackManager : ObservableObject
} }
} }
} }
}
finally finally
{ {
// This function returns 1 rather than 0 specfied in the document. // This function returns 1 rather than 0 specfied in the document.
_ = NetworkIsolationFreeAppContainers(pContainers); _ = NetworkIsolationFreeAppContainers(pContainers);
} }
WIN32_ERROR error2 = NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids); {
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2)); WIN32_ERROR error = NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids);
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error));
for (uint i = 0; i < accCount; i++) for (uint i = 0; i < accCount; i++)
{ {
ConvertSidToStringSidW((pSids + i)->Sid, out PWSTR stringSid); ConvertSidToStringSidW((pSids + i)->Sid, out PWSTR stringSid);
@@ -62,6 +65,7 @@ internal sealed unsafe class LoopbackManager : ObservableObject
} }
} }
} }
}
public bool IsLoopbackEnabled { get => isLoopbackEnabled; private set => SetProperty(ref isLoopbackEnabled, value); } public bool IsLoopbackEnabled { get => isLoopbackEnabled; private set => SetProperty(ref isLoopbackEnabled, value); }

View File

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

View File

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

View File

@@ -49,7 +49,7 @@ internal sealed partial class PrivateNamedPipeServer : IDisposable
{ {
byte[] content = new byte[header->ContentLength]; byte[] content = new byte[header->ContentLength];
serverStream.ReadAtLeast(content, header->ContentLength, false); 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; return content;
} }

View File

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

View File

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

View File

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

View File

@@ -15,6 +15,12 @@ namespace Snap.Hutao.Extension;
[HighQuality] [HighQuality]
internal static partial class EnumerableExtension 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) public static TElement? ElementAtOrLastOrDefault<TElement>(this IEnumerable<TElement> source, int index)
{ {
return source.ElementAtOrDefault(index) ?? source.LastOrDefault(); return source.ElementAtOrDefault(index) ?? source.LastOrDefault();
@@ -46,34 +52,6 @@ internal static partial class EnumerableExtension
return first; 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) public static string JoinToString<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> source, char separator, Action<StringBuilder, TKey, TValue> selector)
{ {
StringBuilder resultBuilder = new(); StringBuilder resultBuilder = new();

View File

@@ -41,6 +41,30 @@
"Equatable": true, "Equatable": true,
"EqualityOperators": 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", "Name": "Level",
"Documentation": "等级 1 - 90", "Documentation": "等级 1 - 90",

View File

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

@@ -0,0 +1,627 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Snap.Hutao.Model.Entity.Database;
#nullable disable
namespace Snap.Hutao.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20240219020258_AddPerferredUidOnUser")]
partial class AddPerferredUidOnUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "8.0.2");
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<Guid>("ArchiveId")
.HasColumnType("TEXT");
b.Property<uint>("Current")
.HasColumnType("INTEGER");
b.Property<uint>("Id")
.HasColumnType("INTEGER");
b.Property<int>("Status")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("Time")
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.HasIndex("ArchiveId");
b.ToTable("achievements");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.AchievementArchive", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<bool>("IsSelected")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.ToTable("achievement_archives");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.AvatarInfo", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CalculatorRefreshTime")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("GameRecordRefreshTime")
.HasColumnType("TEXT");
b.Property<string>("Info")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("ShowcaseRefreshTime")
.HasColumnType("TEXT");
b.Property<string>("Uid")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.ToTable("avatar_infos");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntry", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<uint>("Id")
.HasColumnType("INTEGER");
b.Property<Guid>("ProjectId")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("InnerId");
b.HasIndex("ProjectId");
b.ToTable("cultivate_entries");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntryLevelInformation", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<uint>("AvatarLevelFrom")
.HasColumnType("INTEGER");
b.Property<uint>("AvatarLevelTo")
.HasColumnType("INTEGER");
b.Property<Guid>("EntryId")
.HasColumnType("TEXT");
b.Property<uint>("SkillALevelFrom")
.HasColumnType("INTEGER");
b.Property<uint>("SkillALevelTo")
.HasColumnType("INTEGER");
b.Property<uint>("SkillELevelFrom")
.HasColumnType("INTEGER");
b.Property<uint>("SkillELevelTo")
.HasColumnType("INTEGER");
b.Property<uint>("SkillQLevelFrom")
.HasColumnType("INTEGER");
b.Property<uint>("SkillQLevelTo")
.HasColumnType("INTEGER");
b.Property<uint>("WeaponLevelFrom")
.HasColumnType("INTEGER");
b.Property<uint>("WeaponLevelTo")
.HasColumnType("INTEGER");
b.HasKey("InnerId");
b.HasIndex("EntryId")
.IsUnique();
b.ToTable("cultivate_entry_level_informations");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateItem", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<uint>("Count")
.HasColumnType("INTEGER");
b.Property<Guid>("EntryId")
.HasColumnType("TEXT");
b.Property<bool>("IsFinished")
.HasColumnType("INTEGER");
b.Property<uint>("ItemId")
.HasColumnType("INTEGER");
b.HasKey("InnerId");
b.HasIndex("EntryId");
b.ToTable("cultivate_items");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateProject", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("AttachedUid")
.HasColumnType("TEXT");
b.Property<bool>("IsSelected")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.ToTable("cultivate_projects");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.DailyNoteEntry", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("DailyNote")
.HasColumnType("TEXT");
b.Property<bool>("DailyTaskNotify")
.HasColumnType("INTEGER");
b.Property<bool>("DailyTaskNotifySuppressed")
.HasColumnType("INTEGER");
b.Property<bool>("ExpeditionNotify")
.HasColumnType("INTEGER");
b.Property<bool>("ExpeditionNotifySuppressed")
.HasColumnType("INTEGER");
b.Property<bool>("HomeCoinNotifySuppressed")
.HasColumnType("INTEGER");
b.Property<int>("HomeCoinNotifyThreshold")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("RefreshTime")
.HasColumnType("TEXT");
b.Property<bool>("ResinNotifySuppressed")
.HasColumnType("INTEGER");
b.Property<int>("ResinNotifyThreshold")
.HasColumnType("INTEGER");
b.Property<bool>("TransformerNotify")
.HasColumnType("INTEGER");
b.Property<bool>("TransformerNotifySuppressed")
.HasColumnType("INTEGER");
b.Property<string>("Uid")
.IsRequired()
.HasColumnType("TEXT");
b.Property<Guid>("UserId")
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.HasIndex("UserId");
b.ToTable("daily_notes");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.GachaArchive", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<bool>("IsSelected")
.HasColumnType("INTEGER");
b.Property<string>("Uid")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.ToTable("gacha_archives");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.GachaItem", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<Guid>("ArchiveId")
.HasColumnType("TEXT");
b.Property<int>("GachaType")
.HasColumnType("INTEGER");
b.Property<long>("Id")
.HasColumnType("INTEGER");
b.Property<uint>("ItemId")
.HasColumnType("INTEGER");
b.Property<int>("QueryType")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset>("Time")
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.HasIndex("ArchiveId");
b.ToTable("gacha_items");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.GameAccount", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("AttachUid")
.HasColumnType("TEXT");
b.Property<int>("Index")
.HasColumnType("INTEGER");
b.Property<string>("MihoyoSDK")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("InnerId");
b.ToTable("game_accounts");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryItem", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<uint>("Count")
.HasColumnType("INTEGER");
b.Property<uint>("ItemId")
.HasColumnType("INTEGER");
b.Property<Guid>("ProjectId")
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.HasIndex("ProjectId");
b.ToTable("inventory_items");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryReliquary", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("AppendPropIdList")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("ItemId")
.HasColumnType("INTEGER");
b.Property<int>("Level")
.HasColumnType("INTEGER");
b.Property<int>("MainPropId")
.HasColumnType("INTEGER");
b.Property<Guid>("ProjectId")
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.HasIndex("ProjectId");
b.ToTable("inventory_reliquaries");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryWeapon", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<int>("ItemId")
.HasColumnType("INTEGER");
b.Property<int>("Level")
.HasColumnType("INTEGER");
b.Property<Guid>("ProjectId")
.HasColumnType("TEXT");
b.Property<int>("PromoteLevel")
.HasColumnType("INTEGER");
b.HasKey("InnerId");
b.HasIndex("ProjectId");
b.ToTable("inventory_weapons");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.ObjectCacheEntry", b =>
{
b.Property<string>("Key")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("ExpireTime")
.HasColumnType("TEXT");
b.Property<string>("Value")
.HasColumnType("TEXT");
b.HasKey("Key");
b.ToTable("object_cache");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.SettingEntry", b =>
{
b.Property<string>("Key")
.HasColumnType("TEXT");
b.Property<string>("Value")
.HasColumnType("TEXT");
b.HasKey("Key");
b.ToTable("settings");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.SpiralAbyssEntry", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<uint>("ScheduleId")
.HasColumnType("INTEGER");
b.Property<string>("SpiralAbyss")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Uid")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("InnerId");
b.ToTable("spiral_abysses");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.User", b =>
{
b.Property<Guid>("InnerId")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("Aid")
.HasColumnType("TEXT");
b.Property<string>("CookieToken")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CookieTokenLastUpdateTime")
.HasColumnType("TEXT");
b.Property<string>("Fingerprint")
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("FingerprintLastUpdateTime")
.HasColumnType("TEXT");
b.Property<int>("Index")
.HasColumnType("INTEGER");
b.Property<bool>("IsOversea")
.HasColumnType("INTEGER");
b.Property<bool>("IsSelected")
.HasColumnType("INTEGER");
b.Property<string>("LToken")
.HasColumnType("TEXT")
.HasColumnName("Ltoken");
b.Property<string>("Mid")
.HasColumnType("TEXT");
b.Property<string>("PreferredUid")
.HasColumnType("TEXT");
b.Property<string>("SToken")
.HasColumnType("TEXT")
.HasColumnName("Stoken");
b.HasKey("InnerId");
b.ToTable("users");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.AchievementArchive", "Archive")
.WithMany()
.HasForeignKey("ArchiveId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Archive");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntry", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
.WithMany()
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Project");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntryLevelInformation", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.CultivateEntry", "Entry")
.WithOne("LevelInformation")
.HasForeignKey("Snap.Hutao.Model.Entity.CultivateEntryLevelInformation", "EntryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Entry");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateItem", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.CultivateEntry", "Entry")
.WithMany()
.HasForeignKey("EntryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Entry");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.DailyNoteEntry", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.GachaItem", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.GachaArchive", "Archive")
.WithMany()
.HasForeignKey("ArchiveId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Archive");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryItem", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
.WithMany()
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Project");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryReliquary", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
.WithMany()
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Project");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryWeapon", b =>
{
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
.WithMany()
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Project");
});
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntry", b =>
{
b.Navigation("LevelInformation");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,29 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Snap.Hutao.Migrations
{
/// <inheritdoc />
public partial class AddPerferredUidOnUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PreferredUid",
table: "users",
type: "TEXT",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PreferredUid",
table: "users");
}
}
}

View File

@@ -15,7 +15,7 @@ namespace Snap.Hutao.Migrations
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "8.0.1"); modelBuilder.HasAnnotation("ProductVersion", "8.0.2");
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b => modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
{ {
@@ -503,6 +503,9 @@ namespace Snap.Hutao.Migrations
b.Property<string>("Mid") b.Property<string>("Mid")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<string>("PreferredUid")
.HasColumnType("TEXT");
b.Property<string>("SToken") b.Property<string>("SToken")
.HasColumnType("TEXT") .HasColumnType("TEXT")
.HasColumnName("Stoken"); .HasColumnName("Stoken");

View File

@@ -11,10 +11,16 @@ internal static class CollectionsNameValue
return [.. Enum.GetValues<TEnum>().Select(x => new NameValue<TEnum>(x.ToString(), x))]; 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 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) 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>
/// 祈愿记录分类 /// 祈愿记录分类
/// </summary> /// </summary>
public GachaConfigType GachaType { get; set; } public GachaType GachaType { get; set; }
/// <summary> /// <summary>
/// 祈愿记录查询分类 /// 祈愿记录查询分类
/// 合并保底的卡池使用此属性 /// 合并保底的卡池使用此属性
/// 仅4种不含400 /// 仅4种不含400
/// </summary> /// </summary>
public GachaConfigType QueryType { get; set; } public GachaType QueryType { get; set; }
/// <summary> /// <summary>
/// 物品Id /// 物品Id

View File

@@ -13,6 +13,7 @@ internal sealed partial class SettingEntry
public const string Culture = "Culture"; public const string Culture = "Culture";
public const string SystemBackdropType = "SystemBackdropType"; public const string SystemBackdropType = "SystemBackdropType";
public const string BackgroundImageType = "BackgroundImageType";
public const string AnnouncementRegion = "AnnouncementRegion"; public const string AnnouncementRegion = "AnnouncementRegion";
@@ -42,6 +43,7 @@ internal sealed partial class SettingEntry
public const string LaunchIsUseCloudThirdPartyMobile = "Launch.IsUseCloudThirdPartyMobile"; public const string LaunchIsUseCloudThirdPartyMobile = "Launch.IsUseCloudThirdPartyMobile";
public const string LaunchIsWindowsHDREnabled = "Launch.IsWindowsHDREnabled"; public const string LaunchIsWindowsHDREnabled = "Launch.IsWindowsHDREnabled";
public const string LaunchUseStarwardPlayTimeStatistics = "Launch.UseStarwardPlayTimeStatistics"; public const string LaunchUseStarwardPlayTimeStatistics = "Launch.UseStarwardPlayTimeStatistics";
public const string LaunchUseBetterGenshinImpactAutomation = "Launch.UseBetterGenshinImpactAutomation";
public const string LaunchSetDiscordActivityWhenPlaying = "Launch.SetDiscordActivityWhenPlaying"; public const string LaunchSetDiscordActivityWhenPlaying = "Launch.SetDiscordActivityWhenPlaying";
[Obsolete("不再支持多开")] [Obsolete("不再支持多开")]

View File

@@ -71,6 +71,8 @@ internal sealed class User : ISelectable, IReorderable, IMappingFrom<User, Cooki
public int Index { get; set; } public int Index { get; set; }
public string? PreferredUid { get; set; }
/// <summary> /// <summary>
/// 创建一个新的用户 /// 创建一个新的用户
/// </summary> /// </summary>

View File

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

@@ -8,15 +8,4 @@ namespace Snap.Hutao.Model.Metadata.Achievement;
/// <summary> /// <summary>
/// 奖励 /// 奖励
/// </summary> /// </summary>
internal sealed class Reward internal sealed class Reward : IdCount;
{
/// <summary>
/// Id
/// </summary>
public MaterialId Id { get; set; }
/// <summary>
/// 数量
/// </summary>
public uint Count { get; set; }
}

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

View File

@@ -3,8 +3,9 @@
using Microsoft.UI; using Microsoft.UI;
using Snap.Hutao.Control; using Snap.Hutao.Control;
using Snap.Hutao.Control.Theme;
using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Intrinsic;
using Snap.Hutao.Win32; using System.Collections.Frozen;
using Windows.UI; using Windows.UI;
namespace Snap.Hutao.Model.Metadata.Converter; namespace Snap.Hutao.Model.Metadata.Converter;
@@ -15,17 +16,39 @@ namespace Snap.Hutao.Model.Metadata.Converter;
[HighQuality] [HighQuality]
internal sealed class QualityColorConverter : ValueConverter<QualityType, Color> 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/> /// <inheritdoc/>
public override Color Convert(QualityType from) public override Color Convert(QualityType from)
{ {
return from switch return QualityToColor(from);
{
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,
};
} }
} }

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Control; using Snap.Hutao.Control;
using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Intrinsic;
using System.Collections.Frozen;
namespace Snap.Hutao.Model.Metadata.Converter; namespace Snap.Hutao.Model.Metadata.Converter;
@@ -12,6 +13,20 @@ namespace Snap.Hutao.Model.Metadata.Converter;
[HighQuality] [HighQuality]
internal sealed class WeaponTypeIconConverter : ValueConverter<WeaponType, Uri> 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>
/// 将武器类型转换为图标链接 /// 将武器类型转换为图标链接
/// </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,18 @@
// 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 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,26 @@
// 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 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>
/// 卡池类型 /// 卡池类型
/// </summary> /// </summary>
public GachaConfigType Type { get; set; } public GachaType Type { get; set; }
/// <summary> /// <summary>
/// 五星列表 /// 五星列表

View File

@@ -0,0 +1,20 @@
// 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;
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 <Identity
Name="60568DGPStudio.SnapHutao" Name="60568DGPStudio.SnapHutao"
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52" Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
Version="1.9.6.0" /> Version="1.9.7.0" />
<Properties> <Properties>
<DisplayName>Snap Hutao</DisplayName> <DisplayName>Snap Hutao</DisplayName>

View File

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

View File

@@ -145,7 +145,7 @@
<value>Save</value> <value>Save</value>
</data> </data>
<data name="ControlImageCachedImageInvalidResourceUri" xml:space="preserve"> <data name="ControlImageCachedImageInvalidResourceUri" xml:space="preserve">
<value>Invalid URL</value> <value>Invalid Uri</value>
</data> </data>
<data name="ControlImageCompositionImageHttpRequest" xml:space="preserve"> <data name="ControlImageCompositionImageHttpRequest" xml:space="preserve">
<value>HTTP GET {0}</value> <value>HTTP GET {0}</value>
@@ -285,7 +285,7 @@
<comment>Need EXACT same string in game</comment> <comment>Need EXACT same string in game</comment>
</data> </data>
<data name="ModelIntrinsicAssociationTypeInazuma" xml:space="preserve"> <data name="ModelIntrinsicAssociationTypeInazuma" xml:space="preserve">
<value>Inadzuma</value> <value>Inazuma</value>
<comment>Need EXACT same string in game</comment> <comment>Need EXACT same string in game</comment>
</data> </data>
<data name="ModelIntrinsicAssociationTypeLiyue" xml:space="preserve"> <data name="ModelIntrinsicAssociationTypeLiyue" xml:space="preserve">
@@ -546,7 +546,7 @@
<value>Uploaded {1} wish records of UID: {0}, stored {2}</value> <value>Uploaded {1} wish records of UID: {0}, stored {2}</value>
</data> </data>
<data name="ServerPassportLoginRequired" xml:space="preserve"> <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>
<data name="ServerPassportLoginSucceed" xml:space="preserve"> <data name="ServerPassportLoginSucceed" xml:space="preserve">
<value>Login successfully</value> <value>Login successfully</value>
@@ -558,7 +558,7 @@
<value>Password has been set successfully</value> <value>Password has been set successfully</value>
</data> </data>
<data name="ServerPassportServiceEmailHasNotRegistered" xml:space="preserve"> <data name="ServerPassportServiceEmailHasNotRegistered" xml:space="preserve">
<value>Current email adress is not registered</value> <value>Current email address is not registered</value>
</data> </data>
<data name="ServerPassportServiceEmailHasRegistered" xml:space="preserve"> <data name="ServerPassportServiceEmailHasRegistered" xml:space="preserve">
<value>Current emaill address is registered</value> <value>Current emaill address is registered</value>
@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Character Showcase: {0:MM-dd HH:mm}</value> <value>Character Showcase: {0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Failed to save development plan status</value> <value>Failed to save development plan status</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>Parametric Transformer is ready</value> <value>Parametric Transformer is ready</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>Missing permission, unable to set your Discord Activity.</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Exploring in Teyvat</value> <value>Exploring in Teyvat</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Game Launcher</value> <value>Game Launcher</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>Cannot reorder in Admin Mode</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>Archive [{0}] added successfully</value> <value>Archive [{0}] added successfully</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Completed</value> <value>Completed</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>Response stream does not contain valid content type</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>Queued</value> <value>Queued</value>
</data> </data>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>Launch Parameters</value> <value>Launch Parameters</value>
</data> </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>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>General</value> <value>General</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>Backdrop Material</value> <value>Backdrop Material</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>Images cache are saved here</value> <value>Images cache are saved here</value>
</data> </data>
@@ -2544,10 +2583,10 @@
<value>Reset Image Resource</value> <value>Reset Image Resource</value>
</data> </data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsDescription" xml:space="preserve"> <data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsDescription" xml:space="preserve">
<value>在启动游戏页面的进程部分加入解锁帧率限制选项</value> <value>Add Unlock Frame Rate Limit Option in Game Launcher Process Section</value>
</data> </data>
<data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsHeader" xml:space="preserve"> <data name="ViewPageSettingsAdvancedOptionsLaunchUnlockFpsHeader" xml:space="preserve">
<value>启动游戏-解锁帧率限制</value> <value>Game Launcher - Unlock Frame Rate Limit</value>
</data> </data>
<data name="ViewPageSettingSetDataFolderDescription" xml:space="preserve"> <data name="ViewPageSettingSetDataFolderDescription" xml:space="preserve">
<value>You need to move data in the directory manually, otherwise new user data will be created.</value> <value>You need to move data in the directory manually, otherwise new user data will be created.</value>

View File

@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Pameran Karakter: {0:MM-dd HH:mm}</value> <value>Pameran Karakter: {0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Gagal menyimpan status rencana pengembangan</value> <value>Gagal menyimpan status rencana pengembangan</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>Parametric Transformer telah siap</value> <value>Parametric Transformer telah siap</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Menjelajahi di Teyvat</value> <value>Menjelajahi di Teyvat</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Game Launcher</value> <value>Game Launcher</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>Arsip [{0}] berhasil ditambahkan</value> <value>Arsip [{0}] berhasil ditambahkan</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Selesai</value> <value>Selesai</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>Mengantre</value> <value>Mengantre</value>
</data> </data>
@@ -2010,7 +2034,7 @@
<value>Pratinjau</value> <value>Pratinjau</value>
</data> </data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve"> <data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value> <value>Statistik</value>
</data> </data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve"> <data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>Senjata</value> <value>Senjata</value>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>Argumen Awalan</value> <value>Argumen Awalan</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>Umum</value> <value>Umum</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>Backdrop Material</value> <value>Backdrop Material</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>Cache gambar disimpan di sini</value> <value>Cache gambar disimpan di sini</value>
</data> </data>

View File

@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>キャラクターラインナップ:{0:MM-dd HH:mm}</value> <value>キャラクターラインナップ:{0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>育成計画のステータスを保存できません</value> <value>育成計画のステータスを保存できません</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>参量物質変化器は使用可能</value> <value>参量物質変化器は使用可能</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>テイワット大陸を探索中</value> <value>テイワット大陸を探索中</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>ゲームランチャー</value> <value>ゲームランチャー</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>アーカイブ [{0}] を作成しました</value> <value>アーカイブ [{0}] を作成しました</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>完了</value> <value>完了</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>待機中</value> <value>待機中</value>
</data> </data>
@@ -2010,7 +2034,7 @@
<value>一覧</value> <value>一覧</value>
</data> </data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve"> <data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value> <value>統計</value>
</data> </data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve"> <data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>武器</value> <value>武器</value>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>コマンドラインパラメーター</value> <value>コマンドラインパラメーター</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>一般</value> <value>一般</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>テーマ</value> <value>テーマ</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>イメージキャッシュはここに格納されます</value> <value>イメージキャッシュはここに格納されます</value>
</data> </data>

View File

@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色橱窗:{0:MM-dd HH:mm}</value> <value>角色橱窗:{0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>육성 계획 상태를 저장하지 못했습니다</value> <value>육성 계획 상태를 저장하지 못했습니다</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>매개 변수 변환기가 준비되었습니다</value> <value>매개 변수 변환기가 준비되었습니다</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>正在提瓦特大陆中探索</value> <value>正在提瓦特大陆中探索</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>게임 시작</value> <value>게임 시작</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>아카이브 [{0}]가 추가되었습니다</value> <value>아카이브 [{0}]가 추가되었습니다</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>완료</value> <value>완료</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>대기 중</value> <value>대기 중</value>
</data> </data>
@@ -2010,7 +2034,7 @@
<value>개요</value> <value>개요</value>
</data> </data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve"> <data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value> <value>统计</value>
</data> </data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve"> <data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>무기</value> <value>무기</value>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>启动参数</value> <value>启动参数</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>보통</value> <value>보통</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>배경 테마</value> <value>배경 테마</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>여기에 저장된 이미지 캐시</value> <value>여기에 저장된 이미지 캐시</value>
</data> </data>

View File

@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Exibição de personagens: {0:MM-dd HH:mm}</value> <value>Exibição de personagens: {0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Falha ao salvar o status do planejamento</value> <value>Falha ao salvar o status do planejamento</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>O Transformador Paramétrico está pronto</value> <value>O Transformador Paramétrico está pronto</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Explorando em Teyvat</value> <value>Explorando em Teyvat</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Inicializador</value> <value>Inicializador</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>Arquivo [{0}] adicionado com sucesso</value> <value>Arquivo [{0}] adicionado com sucesso</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Concluído</value> <value>Concluído</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>Em fila</value> <value>Em fila</value>
</data> </data>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>Argumentos de inicialização</value> <value>Argumentos de inicialização</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>Geral</value> <value>Geral</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>Material de pano de fundo</value> <value>Material de pano de fundo</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>O cache de imagens é salvo aqui</value> <value>O cache de imagens é salvo aqui</value>
</data> </data>
@@ -2532,7 +2571,7 @@
<value>自定义背景图片,支持 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式</value> <value>自定义背景图片,支持 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式</value>
</data> </data>
<data name="ViewPageSettingOpenBackgroundImageFolderHeader" xml:space="preserve"> <data name="ViewPageSettingOpenBackgroundImageFolderHeader" xml:space="preserve">
<value>打开背景图片文件夹</value> <value>Abrir pasta do fundo</value>
</data> </data>
<data name="ViewPageSettingResetAction" xml:space="preserve"> <data name="ViewPageSettingResetAction" xml:space="preserve">
<value>Resetar</value> <value>Resetar</value>

View File

@@ -186,6 +186,9 @@
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve"> <data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
<value>未检测到 WebView2 运行时</value> <value>未检测到 WebView2 运行时</value>
</data> </data>
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
<value>[{0}] 热键 [{1}] 注册失败</value>
</data>
<data name="FilePickerExportCommit" xml:space="preserve"> <data name="FilePickerExportCommit" xml:space="preserve">
<value>导出</value> <value>导出</value>
</data> </data>
@@ -767,6 +770,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色橱窗:{0:MM-dd HH:mm}</value> <value>角色橱窗:{0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>保存养成计划状态失败</value> <value>保存养成计划状态失败</value>
</data> </data>
@@ -824,6 +842,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>参量质变仪已准备完成</value> <value>参量质变仪已准备完成</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>正在提瓦特大陆中探索</value> <value>正在提瓦特大陆中探索</value>
</data> </data>
@@ -839,6 +860,9 @@
<data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve"> <data name="ServiceGachaLogFactoryAvatarWishName" xml:space="preserve">
<value>角色活动</value> <value>角色活动</value>
</data> </data>
<data name="ServiceGachaLogFactoryChronicledWishName" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve"> <data name="ServiceGachaLogFactoryPermanentWishName" xml:space="preserve">
<value>奔行世间</value> <value>奔行世间</value>
</data> </data>
@@ -1673,6 +1697,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>完成</value> <value>完成</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>等待中</value> <value>等待中</value>
</data> </data>
@@ -2189,6 +2216,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>启动参数</value> <value>启动参数</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>常规</value> <value>常规</value>
</data> </data>
@@ -2330,6 +2363,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>背景材质</value> <value>背景材质</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>图片缓存 在此处存放</value> <value>图片缓存 在此处存放</value>
</data> </data>
@@ -2594,6 +2636,12 @@
<data name="ViewPageSettingWebview2Header" xml:space="preserve"> <data name="ViewPageSettingWebview2Header" xml:space="preserve">
<value>Webview2 运行时</value> <value>Webview2 运行时</value>
</data> </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"> <data name="ViewPageWiKiAvatarArtifactSetCombinationHeader" xml:space="preserve">
<value>搭配圣遗物</value> <value>搭配圣遗物</value>
</data> </data>
@@ -2856,7 +2904,7 @@
<value>〓活动时间〓.*?\d\.\d版本期间持续开放</value> <value>〓活动时间〓.*?\d\.\d版本期间持续开放</value>
</data> </data>
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve"> <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>
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve"> <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>
@@ -3008,6 +3056,9 @@
<data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve"> <data name="WebGachaConfigTypeAvatarEventWish2" xml:space="preserve">
<value>角色活动祈愿-2</value> <value>角色活动祈愿-2</value>
</data> </data>
<data name="WebGachaConfigTypeChronicledWish" xml:space="preserve">
<value>集录祈愿</value>
</data>
<data name="WebGachaConfigTypeNoviceWish" xml:space="preserve"> <data name="WebGachaConfigTypeNoviceWish" xml:space="preserve">
<value>新手祈愿</value> <value>新手祈愿</value>
</data> </data>

View File

@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>Демонстрация персонажей: {0:MM-dd HH:mm}</value> <value>Демонстрация персонажей: {0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>Не удалось сохранить статус плана разработки.</value> <value>Не удалось сохранить статус плана разработки.</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>Преобразователь готов</value> <value>Преобразователь готов</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>Исследование Тейвата</value> <value>Исследование Тейвата</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>Game Launcher</value> <value>Game Launcher</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>存档 [{0}] 添加成功</value> <value>存档 [{0}] 添加成功</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>Завершено</value> <value>Завершено</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>В процессе</value> <value>В процессе</value>
</data> </data>
@@ -2010,7 +2034,7 @@
<value>总览</value> <value>总览</value>
</data> </data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve"> <data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value> <value>统计</value>
</data> </data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve"> <data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>Оружие</value> <value>Оружие</value>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>启动参数</value> <value>启动参数</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>常规</value> <value>常规</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>背景材质</value> <value>背景材质</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>图片缓存 在此处存放</value> <value>图片缓存 在此处存放</value>
</data> </data>

View File

@@ -767,6 +767,21 @@
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve"> <data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
<value>角色櫥窗:{0:MM-dd HH:mm}</value> <value>角色櫥窗:{0:MM-dd HH:mm}</value>
</data> </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"> <data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
<value>保存養成計劃狀態失敗</value> <value>保存養成計劃狀態失敗</value>
</data> </data>
@@ -824,6 +839,9 @@
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve"> <data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
<value>參量質變儀已準備完成</value> <value>參量質變儀已準備完成</value>
</data> </data>
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
</data>
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve"> <data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
<value>正在提瓦特大陸中探索</value> <value>正在提瓦特大陸中探索</value>
</data> </data>
@@ -1391,6 +1409,9 @@
<data name="ViewLaunchGameHeader" xml:space="preserve"> <data name="ViewLaunchGameHeader" xml:space="preserve">
<value>啟動遊戲</value> <value>啟動遊戲</value>
</data> </data>
<data name="ViewListViewDragElevatedHint" xml:space="preserve">
<value>管理员模式下无法拖动排序</value>
</data>
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve"> <data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
<value>存檔 [{0}] 添加成功</value> <value>存檔 [{0}] 添加成功</value>
</data> </data>
@@ -1670,6 +1691,9 @@
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
<value>完成</value> <value>完成</value>
</data> </data>
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
<value>响应内容不是有效的文件字节流</value>
</data>
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve"> <data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
<value>待處理</value> <value>待處理</value>
</data> </data>
@@ -2010,7 +2034,7 @@
<value>總覽</value> <value>總覽</value>
</data> </data>
<data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve"> <data name="ViewPageGahcaLogPivotStatistics" xml:space="preserve">
<value>全球祈愿统计</value> <value>統計</value>
</data> </data>
<data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve"> <data name="ViewPageGahcaLogPivotWeapon" xml:space="preserve">
<value>武器</value> <value>武器</value>
@@ -2186,6 +2210,12 @@
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve"> <data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
<value>啟動參數</value> <value>啟動參數</value>
</data> </data>
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
</data>
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
<value>Better GI</value>
</data>
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve"> <data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
<value>一般</value> <value>一般</value>
</data> </data>
@@ -2327,6 +2357,15 @@
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve"> <data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
<value>背景材質</value> <value>背景材質</value>
</data> </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="ViewPageSettingCacheFolderDescription" xml:space="preserve"> <data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
<value>圖片暫存存放在此</value> <value>圖片暫存存放在此</value>
</data> </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)) foreach (ref readonly Announcement item in CollectionsMarshal.AsSpan(listWrapper.List))
{ {
item.Subtitle = new StringBuilder(item.Subtitle).Replace("\r<br>", string.Empty).ToString(); item.Subtitle = new StringBuilder(item.Subtitle)
item.Content = AnnouncementRegex.XmlTimeTagRegex.Replace(item.Content, x => x.Groups[1].Value); .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; continue;
} }
MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex.Matches(announcement.Content); MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex().Matches(announcement.Content);
if (matches.Count < 2) if (matches.Count < 2)
{ {
continue; continue;

View File

@@ -5,6 +5,7 @@ using Snap.Hutao.Core.Windowing;
using Snap.Hutao.Model; using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction; using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.BackgroundImage;
using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Hoyolab;
namespace Snap.Hutao.Service; namespace Snap.Hutao.Service;
@@ -15,6 +16,7 @@ internal sealed partial class AppOptions : DbStoreOptions
{ {
private bool? isEmptyHistoryWishVisible; private bool? isEmptyHistoryWishVisible;
private BackdropType? backdropType; private BackdropType? backdropType;
private BackgroundImageType? backgroundImageType;
private Region? region; private Region? region;
private string? geetestCustomCompositeUrl; private string? geetestCustomCompositeUrl;
@@ -28,8 +30,16 @@ internal sealed partial class AppOptions : DbStoreOptions
public BackdropType BackdropType public BackdropType BackdropType
{ {
get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, v => Enum.Parse<BackdropType>(v), BackdropType.Mica).Value; get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, EnumParse<BackdropType>, BackdropType.Mica).Value;
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, value => value.ToStringOrEmpty()); set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, 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.None).Value;
set => SetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, value, EnumToStringOrEmpty);
} }
public Lazy<List<NameValue<Region>>> LazyRegions { get; } = new(KnownRegions.Get); public Lazy<List<NameValue<Region>>> LazyRegions { get; } = new(KnownRegions.Get);
@@ -45,4 +55,16 @@ internal sealed partial class AppOptions : DbStoreOptions
get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl); get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl);
set => SetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl, value); set => SetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl, value);
} }
private static T? EnumParse<T>(string input)
where T : struct, Enum
{
return Enum.Parse<T>(input);
}
private static string EnumToStringOrEmpty<T>(T? input)
where T : struct, Enum
{
return input.ToStringOrEmpty();
}
} }

View File

@@ -2,17 +2,14 @@
// Licensed under the MIT license. // Licensed under the MIT license.
using Microsoft.UI.Xaml.Media.Imaging; 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; using Windows.UI;
namespace Snap.Hutao.Service.BackgroundImage; namespace Snap.Hutao.Service.BackgroundImage;
internal sealed class BackgroundImage internal sealed class BackgroundImage
{ {
public string Path { get; set; } = default!;
public BitmapImage ImageSource { get; set; } = default!; public BitmapImage ImageSource { get; set; } = default!;
public Color AccentColor { get; set; } public Color AccentColor { get; set; }

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;
using Snap.Hutao.Core.Caching; using Snap.Hutao.Core.Caching;
using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO;
using Snap.Hutao.Service.Game.Scheme; using Snap.Hutao.Web.Hutao.Wallpaper;
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher;
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher.Content;
using Snap.Hutao.Web.Response; using Snap.Hutao.Web.Response;
using Snap.Hutao.Win32.Foundation;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using Windows.Graphics.Imaging; using Windows.Graphics.Imaging;
namespace Snap.Hutao.Service.BackgroundImage; namespace Snap.Hutao.Service.BackgroundImage;
@@ -20,33 +20,48 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
{ {
private static readonly HashSet<string> AllowedFormats = [".bmp", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".tiff", ".webp"]; private static readonly HashSet<string> AllowedFormats = [".bmp", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".tiff", ".webp"];
private readonly BackgroundImageOptions backgroundImageOptions;
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;
private readonly RuntimeOptions runtimeOptions; private readonly RuntimeOptions runtimeOptions;
private readonly ITaskContext taskContext; 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); HashSet<string> backgroundSet = await SkipOrInitBackgroundAsync().ConfigureAwait(false);
if (backgroundSet.Count <= 0) 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); backgroundSet.Remove(path);
await taskContext.SwitchToMainThreadAsync(); if (string.Equals(path, previous?.Path, StringComparison.OrdinalIgnoreCase))
if (string.Equals(path, previous?.ImageSource.UriSource.ToString(), StringComparison.OrdinalIgnoreCase))
{ {
return new(false, default!); return new(false, default!);
} }
using (FileStream fileStream = File.OpenRead(path)) 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); SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight);
Bgra32 accentColor = softwareBitmap.GetAccentColor(); Bgra32 accentColor = softwareBitmap.GetAccentColor();
@@ -54,6 +69,7 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
BackgroundImage background = new() BackgroundImage background = new()
{ {
Path = path,
ImageSource = new(path.ToUri()), ImageSource = new(path.ToUri()),
AccentColor = accentColor, AccentColor = accentColor,
Luminance = accentColor.Luminance, Luminance = accentColor.Luminance,
@@ -65,32 +81,58 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync() private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync()
{ {
if (backgroundPathSet is null || backgroundPathSet.Count <= 0) switch (appOptions.BackgroundImageType)
{
case BackgroundImageType.LocalFolder:
{
if (currentBackgroundPathSet is not { Count: > 0 })
{ {
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder(); string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
Directory.CreateDirectory(backgroundFolder); Directory.CreateDirectory(backgroundFolder);
backgroundPathSet = Directory
currentBackgroundPathSet = Directory
.GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories) .GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories)
.Where(path => AllowedFormats.Contains(Path.GetExtension(path))) .Where(path => AllowedFormats.Contains(Path.GetExtension(path)))
.ToHashSet(); .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 })
{
ValueFile file = await serviceProvider.GetRequiredService<IImageCache>().GetFileFromCacheAsync(url.ToUri()).ConfigureAwait(false);
backgroundPathSet = [file];
}
}
} }
return backgroundPathSet; 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];
}
}
}
} }
} }

View File

@@ -0,0 +1,23 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
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 internal interface IBackgroundImageService
{ {
ValueTask<ValueResult<bool, BackgroundImage>> GetNextBackgroundImageAsync(BackgroundImage? previous); ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous);
} }

View File

@@ -7,7 +7,7 @@ using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.Entity.Database;
using Snap.Hutao.Model.Entity.Primitive; using Snap.Hutao.Model.Entity.Primitive;
using Snap.Hutao.Model.Metadata.Item; using Snap.Hutao.Model.Metadata.Item;
using Snap.Hutao.Service.Inventroy; using Snap.Hutao.Service.Inventory;
using Snap.Hutao.Service.Metadata.ContextAbstraction; using Snap.Hutao.Service.Metadata.ContextAbstraction;
using Snap.Hutao.ViewModel.Cultivation; using Snap.Hutao.ViewModel.Cultivation;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@@ -39,7 +39,7 @@ internal sealed partial class CultivationService : ICultivationService
List<InventoryItem> entities = cultivationDbService.GetInventoryItemListByProjectId(projectId); List<InventoryItem> entities = cultivationDbService.GetInventoryItemListByProjectId(projectId);
List<InventoryItemView> results = []; 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); InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.From(projectId, meta.Id);
results.Add(new(entity, meta, saveCommand)); results.Add(new(entity, meta, saveCommand));

View File

@@ -132,13 +132,6 @@ internal static class DiscordController
return; return;
} }
// Actually requires a discord client to be running on Windows platform.
// If not, the following creation code will throw.
if (System.Diagnostics.Process.GetProcessesByName("Discord").Length <= 0)
{
return;
}
lock (SyncRoot) lock (SyncRoot)
{ {
DiscordCreateParams @params = default; DiscordCreateParams @params = default;

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