Compare commits

..

40 Commits

Author SHA1 Message Date
DismissedLight
96e42f51f0 Merge pull request #1254 from DGP-Studio/develop 2024-01-03 20:02:54 +08:00
DismissedLight
5a19c19759 update version 2024-01-03 20:01:47 +08:00
DismissedLight
8fb831ef7c fix startup launch game card crash 2024-01-03 19:58:54 +08:00
Masterain
a30c8d8678 Update automation 2024-01-03 03:56:53 -08:00
DismissedLight
2655e835f8 1.9.2 package 2024-01-03 19:34:56 +08:00
qhy040404
ffd74703cd Update MGMT-publish.yml 2024-01-03 19:26:23 +08:00
DismissedLight
584465dc45 Merge pull request #1253 from DGP-Studio/develop 2024-01-03 19:14:57 +08:00
DismissedLight
a1e751160d Merge pull request #1235 from DGP-Studio/l10n_develop 2024-01-03 19:04:09 +08:00
DismissedLight
d78d2cf51a typo 2024-01-03 18:21:11 +08:00
Masterain
24709bfbf9 Update .gitlab-ci.yml 2024-01-03 01:48:36 -08:00
Lightczx
9be396b175 impl #1228 2024-01-03 17:09:51 +08:00
Lightczx
bb83e76d33 impl #1241 2024-01-03 16:17:27 +08:00
Lightczx
1ca24c8a78 remove unused using 2024-01-03 14:37:17 +08:00
DismissedLight
3d56aef221 Merge pull request #1250 from DGP-Studio/feat/1244 2024-01-03 14:26:35 +08:00
Lightczx
d43f2e76c4 code style 2024-01-03 14:26:21 +08:00
Masterain
1d074f5313 New translations sh.resx (Chinese Traditional) 2023-12-31 03:24:56 -08:00
Masterain
769a1c3812 New translations sh.resx (Russian) 2023-12-31 03:24:55 -08:00
Masterain
b54717fa9b New translations sh.resx (Japanese) 2023-12-31 03:24:54 -08:00
Masterain
ffa0b05a12 New translations sh.resx (Indonesian) 2023-12-30 02:47:33 -08:00
Masterain
d07a33f3e4 New translations sh.resx (English) 2023-12-29 02:30:33 -08:00
Masterain
bbd274c391 Update README.md (#1234)
* Update README.md

* Update README.md
2023-12-28 01:34:20 -08:00
Masterain
f8a8a929ac New translations sh.resx (Indonesian) 2023-12-28 01:21:13 -08:00
Masterain
cf3298dbd0 New translations sh.resx (English) 2023-12-28 01:21:12 -08:00
Masterain
a8b887def2 New translations sh.resx (Chinese Traditional) 2023-12-28 01:21:11 -08:00
Masterain
5a937b0838 New translations sh.resx (Russian) 2023-12-28 01:21:10 -08:00
Masterain
c016ae1cb8 New translations sh.resx (Korean) 2023-12-28 01:21:08 -08:00
Masterain
c7fdf8001d New translations sh.resx (Japanese) 2023-12-28 01:21:07 -08:00
DismissedLight
b11526761e Merge pull request #1214 from DGP-Studio/develop 2023-12-23 19:19:45 +08:00
DismissedLight
6ee823094a Merge pull request #1207 from DGP-Studio/develop 2023-12-23 11:51:15 +08:00
qhy040404
14894b0b47 Update issue templates 2023-12-22 16:59:22 +08:00
Masterain
6834073603 Merge pull request #1204 from DGP-Studio/issue_template_publish
Update MGMT-publish.yml
2023-12-21 17:41:22 -08:00
qhy040404
911fe57fb2 check jihulab 2023-12-22 09:29:47 +08:00
qhy040404
7320cf7dd0 owner 2023-12-22 09:21:52 +08:00
qhy040404
bc6d03e442 Update MGMT-publish.yml 2023-12-22 09:20:30 +08:00
Masterain
307a49b346 Merge pull request #1191 from DGP-Studio/Masterain98-patch-2
Update .gitlab-ci.yml
2023-12-19 18:08:36 -08:00
Masterain
9f8d80ff43 Update .gitlab-ci.yml 2023-12-19 13:48:49 -08:00
Masterain
d34130b6c0 Update .gitlab-ci.yml 2023-12-17 02:44:15 -08:00
Masterain
2161f12069 Merge pull request #1187 from DGP-Studio/Masterain98-patch-1
Create .gitlab-ci.yml
2023-12-16 22:34:56 -08:00
Masterain
0bedd1894c Create .gitlab-ci.yml 2023-12-16 22:33:43 -08:00
DismissedLight
442db0bae4 Merge pull request #1184 from DGP-Studio/develop 2023-12-16 15:07:24 +08:00
26 changed files with 754 additions and 325 deletions

View File

@@ -22,7 +22,7 @@ body:
- label: 我知道文档站的导航栏中有**搜索功能**,且已经搜索过相关关键词
required: true
- label: 我的问题不是[已修复](https://github.com/DGP-Studio/Snap.Hutao/issues?q=is%3Aopen+is%3Aissue+label%3A%E5%B7%B2%E4%BF%AE%E5%A4%8D)的问题也不是一个别人已发布的**重复的**问题
- label: 我的问题不是[已完成](https://github.com/DGP-Studio/Snap.Hutao/issues?q=is%3Aopen+is%3Aissue+label%3A%E5%B7%B2%E5%AE%8C%E6%88%90)的问题也不是一个别人已发布的**重复的**问题
required: true
- type: input
@@ -51,7 +51,7 @@ body:
description: |
在胡桃工具箱的设置界面,你可以找到并复制你的设备 ID
如果你的问题涉及程序崩溃,请填写该项,这将有助于我们定位问题
如果你的程序已经无法启动,请下载并运行[此PowerShell脚本](https://github.com/DGP-Studio/ISSUE_TEMPLATES/releases/download/get_device_id/GetHutaoDeviceId.ps1),它将显示你的设备 ID
如果你的程序已经无法启动,请下载并运行[此工具](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.DiagTools.exe),它将显示你的设备 ID
validations:
required: false
@@ -87,7 +87,7 @@ body:
label: 发生了什么?
description: |
详细的描述问题发生前后的行为,以便我们解决问题。**如果你的问题涉及程序崩溃,你应当检查 Windows 事件查看器,并将相关的 `.Net 错误`详情附上**
如果你无法找到该日志,请下载并运行[此PowerShell脚本](https://github.com/DGP-Studio/ISSUE_TEMPLATES/releases/download/dump_log_script/dump_log_zh.ps1),它将输出错误日志
如果你无法找到该日志,请下载并运行[此工具](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.DiagTools.exe),它将转储问题日志至工具运行目录中的 `Snap.Hutao Error Log.txt`
validations:
required: true

View File

@@ -22,7 +22,7 @@ body:
- label: I and tried **search feature** in Snap Hutao document site, and no associated article
required: true
- label: My issue is not a [fixed issue](https://github.com/DGP-Studio/Snap.Hutao/issues?q=is%3Aopen+is%3Aissue+label%3A%E5%B7%B2%E4%BF%AE%E5%A4%8D), and it's not a duplicated issue
- label: My issue is not a [finished issue](https://github.com/DGP-Studio/Snap.Hutao/issues?q=is%3Aopen+is%3Aissue+label%3A%E5%B7%B2%E5%AE%8C%E6%88%90), and it's not a duplicated issue
required: true
- type: input
@@ -51,7 +51,7 @@ body:
description: |
In Snap Hutao's settings page, you can find and copy your device ID
If your issue is about program crash, please fill this so we can dump the log and locate the source easier
If your program cannot startup, please download and run [this PowerShell script](https://github.com/DGP-Studio/ISSUE_TEMPLATES/releases/download/get_device_id/GetHutaoDeviceId.ps1), it will shows your device ID.
If your program cannot startup, please download and run [this tool](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.DiagTools.exe), it will shows your device ID.
validations:
required: false
@@ -87,7 +87,7 @@ body:
label: What Happened?
description: |
Describe your issue in detail to help us identify the issue. **If your issue is about program crash, you should check Windows Event Viewer, and attach associated `.Net Error` details here**If your program cannot startup, please download and run [this PowerShell script](https://github.com/DGP-Studio/ISSUE_TEMPLATES/releases/download/get_device_id/GetHutaoDeviceId.ps1), it will shows your device ID.
If you cannot find it, please download and run [this PowerShell script](https://github.com/DGP-Studio/ISSUE_TEMPLATES/releases/download/dump_log_script/dump_log_en.ps1), it will dump the error log.
If you cannot find it, please download and run [this tool](https://github.com/DGP-Automation/ISSUE_TEMPLATES/releases/download/diagnosis_tools/Snap.Hutao.DiagTools.exe), it will dump the error log to `Snap.Hutao Error Log.txt` in the working directory of the tool.
validations:
required: true

View File

@@ -12,50 +12,26 @@ body:
value: |
## 创建版本
- [ ] 同步一次 [Crowdin](https://crowdin.com/project/snap-hutao) 翻译
- [ ] 发布 RC 版本Optional
- [ ] 合并入主分支
- [ ] 整理更新内容,等待翻译
- [ ] 打包
- [ ] 提交微软商店
- [ ] 包含更新日志
- [ ] 在 [Snap.Hutao.Docs@next-patch](https://github.com/DGP-Studio/Snap.Hutao.Docs/tree/next-patch) 分支更新文档并直接开 PR
- [ ] 更新日志
- [ ] 功能文档更新
## 发布版本 [半自动]
- [ ] 在 GitHub 个人设置中更新 [Publish-Automate Beta PAT](https://github.com/settings/tokens?type=beta),有效期需小于预计发版需要天数
- [ ] 将更新的 PAT 更新至 Publish-Automate 库的 [Actions Secrets](https://github.com/DGP-Studio/Publish-Automate/settings/secrets/actions) 中
***
***
- [ ] 运行 [Auto Publish Action](https://github.com/DGP-Studio/Publish-Automate/actions/workflows/auto-publish.yml)
- [ ] 在 https://store.rg-adguard.net/ 下载新版本安装包
- [ ] Store URL: https://apps.microsoft.com/store/detail/snap-hutao/9PH4NXJ2JN52
- [ ] 命名格式为 `Snap.Hutao x.x.x.msix`
- [ ] Merge 文档 PR
- [ ] 发布 Release
- [ ] 更新日志格式(以 1.6.2 版本为例)
```jsx
## Update log
https://hut.ao/en/statements/update-log.html#_1-6-2
## 更新日志
[此处从文档复制]
## What's Changed
**Full Changelog**: https://github.com/DGP-Studio/Snap.Hutao/compare/1.6.0...1.6.2
```
- [ ] 通知用户
- [ ] 主分支合并入 release 分支
- [ ] 等待 Release 自动发布
- [ ] 检查极狐是否同步完成 Release
- [ ] 通知用户
- type: checkboxes
id: checklist-final
attributes:
label: Final Check
description: Understand what you are doing
description: Understand what you are doing
options:
- label: I understand that I will get banned from repository if I don't have permission to use this template
required: true
required: true

View File

@@ -12,6 +12,7 @@ on:
- '.gitmodules'
- '**.md'
- 'LICENSE'
- '**.yml'
jobs:
build:

73
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,73 @@
stages:
- fetch
- release
- refresh
Fetch:
stage: fetch
rules:
- if: $CI_COMMIT_TAG
tags:
- us3
script:
- apt-get update -qy
- apt-get install -y curl jq
- RELEASE_INFO=$(curl -sSL "https://api.github.com/repos/$CI_PROJECT_PATH/releases/latest")
- ASSET_URL=$(echo "$RELEASE_INFO" | jq -r '.assets[] | select(.name | endswith(".msix")) | .browser_download_url')
- SHA256SUMS_URL=$(echo "$RELEASE_INFO" | jq -r '.assets[] | select(.name == "SHA256SUMS") | .browser_download_url')
- curl -LJO "$ASSET_URL"
- curl -LJO "$SHA256SUMS_URL"
- FILE_NAME=$(basename "$ASSET_URL")
- SHA256SUMS_NAME=$(basename "$SHA256SUMS_URL")
- echo "File name at script stage is $FILE_NAME"
- echo "SHA256SUMS name at script stage is $SHA256SUMS_NAME"
- echo "THIS_FILE_NAME=$FILE_NAME" >> next.env
- echo "THIS_SHA256SUMS_NAME=$SHA256SUMS_NAME" >> next.env
after_script:
- echo "Current Job ID is $CI_JOB_ID"
- echo "THIS_JOB_ID=$CI_JOB_ID" >> next.env
artifacts:
paths:
- "*.msix"
- "SHA256SUMS"
expire_in: 180 days
reports:
dotenv: next.env
release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG
needs:
- job: Fetch
artifacts: true
variables:
TAG: '$CI_COMMIT_TAG'
script:
- echo "Create Release $TAG"
- echo "$THIS_JOB_ID"
- echo "$THIS_FILE_NAME"
release:
name: '$TAG'
tag_name: '$TAG'
ref: '$TAG'
description: 'Release $TAG by CI'
assets:
links:
- name: "$THIS_FILE_NAME"
url: "https://$CI_SERVER_SHELL_SSH_HOST/$CI_PROJECT_PATH/-/jobs/$THIS_JOB_ID/artifacts/raw/$THIS_FILE_NAME?inline=false"
link_type: package
- name: "$THIS_SHA256SUMS_NAME"
url: "https://$CI_SERVER_SHELL_SSH_HOST/$CI_PROJECT_PATH/-/jobs/$THIS_JOB_ID/artifacts/raw/$THIS_SHA256SUMS_NAME?inline=false"
link_type: other
Refresh:
stage: refresh
rules:
- if: $CI_COMMIT_TAG
needs:
- job: release
script:
- apt-get install -y curl
- curl -X PATCH "$PURGE_URL"

View File

@@ -1,4 +1,4 @@
![Banner2-large](https://github.com/DGP-Studio/Snap.Hutao/assets/10614984/742129f4-f903-4d16-bf1e-3cbfad873ee4)
![HutaoRepoBanner2-20231222](https://github.com/DGP-Studio/Snap.Hutao/assets/10614984/2d178de1-95bc-44a1-a95e-20c5f11a8628)
胡桃工具箱是一款以 MIT 协议开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新 功能相结合,它提供了一套完整且实用的工具集,且无需依赖任何移动设备。它不对游戏客户端进行任何破坏性修改以确保工具箱的安全性
@@ -7,7 +7,29 @@ Snap Hutao is an open-source Genshin Impact toolkit under MIT license, designed
## 下载使用 / Download
[<img src="https://get.microsoft.com/images/zh-cn%20light.svg" width="30%" height="30%">](https://apps.microsoft.com/store/detail/snap-hutao/9PH4NXJ2JN52)
![](https://ci.appveyor.com/api/projects/status/n4s40t9llru4si9y?svg=true) [![GitHub Release](https://img.shields.io/github/release/DGP-Studio/Snap.Hutao?style=flat)](https://github.com/DGP-Studio/Snap.Hutao/releases/latest) [![Github All Releases](https://img.shields.io/github/downloads/DGP-Studio/Snap.Hutao/total.svg?style=flat)]()
---
#### 使用安装器安装 / Install with Snap.Hutao.Depolyment Installer
Snap.Hutao.Depolyment 是一个由 DGP-Studio 重新包装的 Windows 应用安装器,适用于缺少专业计算机知识的一般用户,可以在安装时同时解决缺少必要系统环境的问题。
Snap.Hutao.Depolyment is a Windows application installer repackaged by DGP-Studio for the users who lacks computer knowledge and can solve the problem of missing necessary system environment at the same time as the installation.
[从 GitHub 发布页获取 / Download from GitHub release](https://github.com/DGP-Studio/Snap.Hutao.Deployment/releases/latest)
[从极狐Lab 发布页获取 / Download from Jihu Gitlab release](https://jihulab.com/DGP-Studio/Snap.Hutao.Deployment/-/releases)
#### 使用 MSIX 包安装 / Install with MSIX Package
直接使用 Snap Hutao MSIX 安装包,使用 Windows 内置的 App Installer 即可安装。如在安装中出现问题,请查阅我们的[常见问题](https://hut.ao/zh/advanced/FAQ.html)文档
Install with Snap Hutao MSIX package, can be installed with Windows built-in App Installer. If you faced any issue, please check our [FAQ](https://hut.ao/en/advanced/FAQ.html) document.
[从 GitHub 发布页获取 / Download from GitHub release](https://github.com/DGP-Studio/Snap.Hutao/releases/latest)
[从极狐Lab 发布页获取 / Download from Jihu Gitlab release](https://jihulab.com/DGP-Studio/Snap.Hutao/-/releases)
## 贡献 / Contribute

View File

@@ -13,4 +13,9 @@ internal static class RuntimeOptionsExtension
Directory.CreateDirectory(directory);
return Path.Combine(directory, fileName);
}
public static string GetDataFolderServerCacheFolder(this RuntimeOptions options)
{
return Path.Combine(options.DataFolder, "ServerCache");
}
}

View File

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

View File

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

View File

@@ -60,45 +60,45 @@
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
@@ -120,6 +120,12 @@
<data name="AppDevNameAndVersion" xml:space="preserve">
<value>Snap Hutao Dev {0}</value>
</data>
<data name="AppElevatedDevNameAndVersion" xml:space="preserve">
<value>Snap Hutao Dev {0} [Administrator]</value>
</data>
<data name="AppElevatedNameAndVersion" xml:space="preserve">
<value>Snap Hutao {0} [Administrator]</value>
</data>
<data name="AppName" xml:space="preserve">
<value>Snap Hutao</value>
</data>
@@ -1547,6 +1553,9 @@
<data name="ViewModelLaunchGameSwitchGameAccountFail" xml:space="preserve">
<value>Switch game account failed</value>
</data>
<data name="ViewModelLaunchGameUnableToSwitchUidAttachedGameAccount" xml:space="preserve">
<value>Cannot select account [{1}] for Uid [{0}], the account does not belong to current server</value>
</data>
<data name="ViewModelSettingActionComplete" xml:space="preserve">
<value>Operation completed</value>
</data>
@@ -2138,6 +2147,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>Pre-download</value>
</data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>Select Game Path</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>This account has not been bound to the Real-time Note notification UID.</value>
</data>
@@ -2270,6 +2282,15 @@
<data name="ViewPageSettingDeviceIpHeader" xml:space="preserve">
<value>Device IP</value>
</data>
<data name="ViewPageSettingElevatedModeDescription" xml:space="preserve">
<value>Administrator mode will change some features' availability and behaviors</value>
</data>
<data name="ViewPageSettingElevatedModeHeader" xml:space="preserve">
<value>Administrator Mode</value>
</data>
<data name="ViewPageSettingElevatedModeRestartAction" xml:space="preserve">
<value>Restart with Administrator Mode</value>
</data>
<data name="ViewPageSettingEmptyHistoryVisibleDescription" xml:space="preserve">
<value>Show or hide wish event with no wish history</value>
</data>
@@ -2729,6 +2750,15 @@
<data name="WebBridgeShareCopyToClipboardSuccess" xml:space="preserve">
<value>Copied to clipboard</value>
</data>
<data name="WebDailyNoteArchonQuestStatusFinished" xml:space="preserve">
<value>Completed</value>
</data>
<data name="WebDailyNoteArchonQuestStatusNotOpen" xml:space="preserve">
<value>Locked</value>
</data>
<data name="WebDailyNoteArchonQuestStatusOngoing" xml:space="preserve">
<value>In Progress</value>
</data>
<data name="WebDailyNoteAttendanceRewardStatusFinishedNonReward" xml:space="preserve">
<value>Finished</value>
</data>

View File

@@ -60,45 +60,45 @@
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
@@ -120,6 +120,12 @@
<data name="AppDevNameAndVersion" xml:space="preserve">
<value>Snap Hutao Dev {0}</value>
</data>
<data name="AppElevatedDevNameAndVersion" xml:space="preserve">
<value>Snap Hutao Dev {0} [Administrator]</value>
</data>
<data name="AppElevatedNameAndVersion" xml:space="preserve">
<value>Snap Hutao {0} [Administrator]</value>
</data>
<data name="AppName" xml:space="preserve">
<value>Snap Hutao</value>
</data>
@@ -990,7 +996,7 @@
<value>Versi UIGF tidak didukung</value>
</data>
<data name="ServiceUpdateStatusVersionDescription" xml:space="preserve">
<value>发现新版本 {0}</value>
<value>Versi terbau {0} sudah tersedia.</value>
</data>
<data name="ServiceUserCurrentMultiMatched" xml:space="preserve">
<value>Beberapa pengguna tercatat sebagai dipilih</value>
@@ -1547,6 +1553,9 @@
<data name="ViewModelLaunchGameSwitchGameAccountFail" xml:space="preserve">
<value>Gagal ganti akun game</value>
</data>
<data name="ViewModelLaunchGameUnableToSwitchUidAttachedGameAccount" xml:space="preserve">
<value>Tidak bisa memilih akun [{1}] dengan UID [{0}], Akun itu tidak berada pada server tersebut</value>
</data>
<data name="ViewModelSettingActionComplete" xml:space="preserve">
<value>Tindakan selesai</value>
</data>
@@ -2091,7 +2100,7 @@
<value>Mengatur Status Aktivitas Discord Saya Ketika Saya Sedang Bermain Game</value>
</data>
<data name="ViewPageLaunchGameDiscordActivityHeader" xml:space="preserve">
<value>Discord Activity</value>
<value>Aktifitas Discord</value>
</data>
<data name="ViewPageLaunchGameFileHeader" xml:space="preserve">
<value>Berkas</value>
@@ -2138,6 +2147,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>Prapengunduhan</value>
</data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>Pilih Path Game</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>Akun ini belum terikat ke UID notifikasi Catatan Realtime.</value>
</data>
@@ -2270,6 +2282,15 @@
<data name="ViewPageSettingDeviceIpHeader" xml:space="preserve">
<value>ID Perangkat</value>
</data>
<data name="ViewPageSettingElevatedModeDescription" xml:space="preserve">
<value>Mode administrator akan mengubah ketersediaan dan perilaku beberapa fitur</value>
</data>
<data name="ViewPageSettingElevatedModeHeader" xml:space="preserve">
<value>Mode Admin</value>
</data>
<data name="ViewPageSettingElevatedModeRestartAction" xml:space="preserve">
<value>Restart menggunakan Mode Administrator</value>
</data>
<data name="ViewPageSettingEmptyHistoryVisibleDescription" xml:space="preserve">
<value>Tampilkan atau sembunyikan acara keinginan tanpa riwayat Wish</value>
</data>
@@ -2613,10 +2634,10 @@
<value>Mengunggah Data</value>
</data>
<data name="ViewTitileUpdatePackageReadyContent" xml:space="preserve">
<value>是否立即安装?</value>
<value>Pasang sekarang?</value>
</data>
<data name="ViewTitileUpdatePackageReadyTitle" xml:space="preserve">
<value>胡桃 {0} 版本已准备就绪</value>
<value>Snap Hutao versi {0} sudah siap</value>
</data>
<data name="ViewTitleAutoClicking" xml:space="preserve">
<value>Auto Click</value>
@@ -2729,6 +2750,15 @@
<data name="WebBridgeShareCopyToClipboardSuccess" xml:space="preserve">
<value>Disalin ke clipboard</value>
</data>
<data name="WebDailyNoteArchonQuestStatusFinished" xml:space="preserve">
<value>Selesai</value>
</data>
<data name="WebDailyNoteArchonQuestStatusNotOpen" xml:space="preserve">
<value>Terkunci</value>
</data>
<data name="WebDailyNoteArchonQuestStatusOngoing" xml:space="preserve">
<value>Dalam proses</value>
</data>
<data name="WebDailyNoteAttendanceRewardStatusFinishedNonReward" xml:space="preserve">
<value>Selesai</value>
</data>
@@ -2874,7 +2904,7 @@
<value>Server Internasional Server Asia</value>
</data>
<data name="WebHoyolabRegionOSCHT" xml:space="preserve">
<value>国际服 港澳台服</value>
<value>Server International: Server TW/HK/MU</value>
</data>
<data name="WebHoyolabRegionOSEURO" xml:space="preserve">
<value>Server Internasional Server Eropa</value>

View File

@@ -60,45 +60,45 @@
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
@@ -120,6 +120,12 @@
<data name="AppDevNameAndVersion" xml:space="preserve">
<value>胡桃 Dev {0}</value>
</data>
<data name="AppElevatedDevNameAndVersion" xml:space="preserve">
<value>胡桃Dev {0} [管理者]</value>
</data>
<data name="AppElevatedNameAndVersion" xml:space="preserve">
<value>胡桃 {0} [管理者]</value>
</data>
<data name="AppName" xml:space="preserve">
<value>胡桃</value>
</data>
@@ -990,7 +996,7 @@
<value>サポートされていないUIGFバージョン</value>
</data>
<data name="ServiceUpdateStatusVersionDescription" xml:space="preserve">
<value>发现新版本 {0}</value>
<value>新しいバージョン {0} が利用できます</value>
</data>
<data name="ServiceUserCurrentMultiMatched" xml:space="preserve">
<value>ユーザー情報を複数選択しています。</value>
@@ -1547,6 +1553,9 @@
<data name="ViewModelLaunchGameSwitchGameAccountFail" xml:space="preserve">
<value>アカウントの切り替えができませんでした</value>
</data>
<data name="ViewModelLaunchGameUnableToSwitchUidAttachedGameAccount" xml:space="preserve">
<value>UID [{0}] に対するアカウント [{1}] を選択できませんでした。このアカウントは現在のサーバーに属していません。</value>
</data>
<data name="ViewModelSettingActionComplete" xml:space="preserve">
<value>操作は完了しました</value>
</data>
@@ -1647,7 +1656,7 @@
<value>重要</value>
</data>
<data name="ViewPageAnnouncementViewDetails" xml:space="preserve">
<value>查看详情</value>
<value>詳細を表示</value>
</data>
<data name="ViewPageAvatarPropertyArtifactScore" xml:space="preserve">
<value>聖遺物スコア</value>
@@ -2138,6 +2147,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>事前ダウンロード</value>
</data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>ゲームのフォルダを選択</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>このアカウントはリアルタイムノート通知 UID として連携されていません。</value>
</data>
@@ -2270,6 +2282,15 @@
<data name="ViewPageSettingDeviceIpHeader" xml:space="preserve">
<value>デバイスのIP</value>
</data>
<data name="ViewPageSettingElevatedModeDescription" xml:space="preserve">
<value>管理者モードは一部の機能の使用可否と動作に影響します。</value>
</data>
<data name="ViewPageSettingElevatedModeHeader" xml:space="preserve">
<value>管理者モード</value>
</data>
<data name="ViewPageSettingElevatedModeRestartAction" xml:space="preserve">
<value>管理者モードで再起動</value>
</data>
<data name="ViewPageSettingEmptyHistoryVisibleDescription" xml:space="preserve">
<value>祈願履歴のないイベント限定祈願を祈願履歴に表示するかを変更します。</value>
</data>
@@ -2307,10 +2328,10 @@
<value>CAPTCHA</value>
</data>
<data name="ViewPageSettingHomeAnnouncementRegionDescription" xml:space="preserve">
<value>选择想要获取公告的游戏服务器</value>
<value>お知らせを受け取りたいサーバーを選択してください</value>
</data>
<data name="ViewPageSettingHomeAnnouncementRegionHeader" xml:space="preserve">
<value>公告所属服务器</value>
<value>お知らせのサーバー</value>
</data>
<data name="ViewpageSettingHomeCardDescription" xml:space="preserve">
<value>ダッシュボードを整理する</value>
@@ -2613,10 +2634,10 @@
<value>データをアップロード</value>
</data>
<data name="ViewTitileUpdatePackageReadyContent" xml:space="preserve">
<value>是否立即安装?</value>
<value>今すぐインストールしますか?</value>
</data>
<data name="ViewTitileUpdatePackageReadyTitle" xml:space="preserve">
<value>胡桃 {0} 版本已准备就绪</value>
<value>胡桃 {0} の準備が完了</value>
</data>
<data name="ViewTitleAutoClicking" xml:space="preserve">
<value>オートクリック</value>
@@ -2729,6 +2750,15 @@
<data name="WebBridgeShareCopyToClipboardSuccess" xml:space="preserve">
<value>クリップボードにコピーしました。</value>
</data>
<data name="WebDailyNoteArchonQuestStatusFinished" xml:space="preserve">
<value>すべて完了</value>
</data>
<data name="WebDailyNoteArchonQuestStatusNotOpen" xml:space="preserve">
<value>未解放</value>
</data>
<data name="WebDailyNoteArchonQuestStatusOngoing" xml:space="preserve">
<value>進行中</value>
</data>
<data name="WebDailyNoteAttendanceRewardStatusFinishedNonReward" xml:space="preserve">
<value>完了しました。</value>
</data>
@@ -2859,28 +2889,28 @@
<value>ダウンロードリンクのコピーに成功しました</value>
</data>
<data name="WebHoyolabInvalidRegion" xml:space="preserve">
<value>无效的服务器</value>
<value>無効なサーバー</value>
</data>
<data name="WebHoyolabInvalidUid" xml:space="preserve">
<value>無効なUIDです</value>
</data>
<data name="WebHoyolabRegionCNGF01" xml:space="preserve">
<value>国服 官方服</value>
<value>中国サーバー: 公式</value>
</data>
<data name="WebHoyolabRegionCNQD01" xml:space="preserve">
<value>国服 渠道服</value>
<value>中国サーバー: ビリビリ(bilibili)</value>
</data>
<data name="WebHoyolabRegionOSASIA" xml:space="preserve">
<value>国际服 亚服</value>
<value>国内サーバー: アジア</value>
</data>
<data name="WebHoyolabRegionOSCHT" xml:space="preserve">
<value>国际服 港澳台服</value>
<value>海外サーバー: 台湾/香港/モンゴル</value>
</data>
<data name="WebHoyolabRegionOSEURO" xml:space="preserve">
<value>国际服 欧服</value>
<value>海外サーバー: ヨーロッパ</value>
</data>
<data name="WebHoyolabRegionOSUSA" xml:space="preserve">
<value>国际服 美服</value>
<value>海外サーバー: 北アメリカ</value>
</data>
<data name="WebHutaoServiceUnAvailable" xml:space="preserve">
<value>胡桃サーバがメンテナンス中です</value>

View File

@@ -60,45 +60,45 @@
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
@@ -120,6 +120,12 @@
<data name="AppDevNameAndVersion" xml:space="preserve">
<value>호두 Dev {0}</value>
</data>
<data name="AppElevatedDevNameAndVersion" xml:space="preserve">
<value>胡桃Dev {0} [管理员]</value>
</data>
<data name="AppElevatedNameAndVersion" xml:space="preserve">
<value>胡桃 {0} [管理员]</value>
</data>
<data name="AppName" xml:space="preserve">
<value>호두</value>
</data>
@@ -1547,6 +1553,9 @@
<data name="ViewModelLaunchGameSwitchGameAccountFail" xml:space="preserve">
<value>계정 전환 살패</value>
</data>
<data name="ViewModelLaunchGameUnableToSwitchUidAttachedGameAccount" xml:space="preserve">
<value>无法选择UID [{0}] 对应的账号 [{1}],该账号不属于当前服务器</value>
</data>
<data name="ViewModelSettingActionComplete" xml:space="preserve">
<value>操作完成</value>
</data>
@@ -2138,6 +2147,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>사전 다운로드</value>
</data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>选择游戏路径</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>该账号尚未绑定实时便笺通知 UID</value>
</data>
@@ -2270,6 +2282,15 @@
<data name="ViewPageSettingDeviceIpHeader" xml:space="preserve">
<value>设备 IP</value>
</data>
<data name="ViewPageSettingElevatedModeDescription" xml:space="preserve">
<value>管理员模式会影响部分功能的可用性与行为</value>
</data>
<data name="ViewPageSettingElevatedModeHeader" xml:space="preserve">
<value>管理员模式</value>
</data>
<data name="ViewPageSettingElevatedModeRestartAction" xml:space="preserve">
<value>以管理员身份重启</value>
</data>
<data name="ViewPageSettingEmptyHistoryVisibleDescription" xml:space="preserve">
<value>기원 기록 페이지에 기록되지 않은 오래된 기원 이벤트를 표시하거나 숨깁니다</value>
</data>
@@ -2729,6 +2750,15 @@
<data name="WebBridgeShareCopyToClipboardSuccess" xml:space="preserve">
<value>已复制到剪贴板</value>
</data>
<data name="WebDailyNoteArchonQuestStatusFinished" xml:space="preserve">
<value>全部完成</value>
</data>
<data name="WebDailyNoteArchonQuestStatusNotOpen" xml:space="preserve">
<value>尚未开启</value>
</data>
<data name="WebDailyNoteArchonQuestStatusOngoing" xml:space="preserve">
<value>进行中</value>
</data>
<data name="WebDailyNoteAttendanceRewardStatusFinishedNonReward" xml:space="preserve">
<value>已完成</value>
</data>

View File

@@ -1271,6 +1271,12 @@
<data name="ViewDialogQRCodeTitle" xml:space="preserve">
<value>使用米游社扫描二维码</value>
</data>
<data name="ViewDialogReconfirmTextHeader" xml:space="preserve">
<value>请输入你正在启用的功能标题</value>
</data>
<data name="ViewDialogReconfirmTitle" xml:space="preserve">
<value>你正在启用一个危险功能</value>
</data>
<data name="ViewDialogSettingDeleteUserDataContent" xml:space="preserve">
<value>该操作是不可逆的,所有用户登录状态会丢失</value>
</data>
@@ -1574,6 +1580,12 @@
<data name="ViewModelSettingCreateDesktopShortcutFailed" xml:space="preserve">
<value>创建桌面快捷方式失败</value>
</data>
<data name="ViewModelSettingDeleteServerCacheFolderContent" xml:space="preserve">
<value>后续转换会重新下载所需的文件,确定要删除吗?</value>
</data>
<data name="ViewModelSettingDeleteServerCacheFolderTitle" xml:space="preserve">
<value>删除转换服务器游戏客户端缓存</value>
</data>
<data name="ViewModelSettingFolderSizeDescription" xml:space="preserve">
<value>已使用磁盘空间:{0}</value>
</data>
@@ -2415,7 +2427,7 @@
<value>在完整阅读原神和胡桃工具箱用户协议后,我选择启用「启动游戏-高级功能」</value>
</data>
<data name="ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader" xml:space="preserve">
<value>启动高级功能</value>
<value>高级功能</value>
</data>
<data name="ViewPageSettingKeyShortcutAutoClickingDescription" xml:space="preserve">
<value>更改自动连点功能的快捷键</value>
@@ -2570,6 +2582,12 @@
<data name="ViewSettingAllocConsoleHeader" xml:space="preserve">
<value>调试控制台</value>
</data>
<data name="ViewSettingDeleteServerCacheFolderDescription" xml:space="preserve">
<value>在启动游戏中转换服务器后会产生对应的游戏客户端文件用作缓存</value>
</data>
<data name="ViewSettingDeleteServerCacheFolderHeader" xml:space="preserve">
<value>删除转换服务器缓存</value>
</data>
<data name="ViewSettingFolderViewOpenFolderAction" xml:space="preserve">
<value>打开文件夹</value>
</data>

View File

@@ -60,45 +60,45 @@
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
@@ -120,11 +120,17 @@
<data name="AppDevNameAndVersion" xml:space="preserve">
<value>Snap Hutao Dev {0}</value>
</data>
<data name="AppElevatedDevNameAndVersion" xml:space="preserve">
<value>Ху Тао Dev {0} [Администратор]</value>
</data>
<data name="AppElevatedNameAndVersion" xml:space="preserve">
<value>Ху Тао {0} [Администратор]</value>
</data>
<data name="AppName" xml:space="preserve">
<value>Snap Hutao</value>
<value>Ху Тао</value>
</data>
<data name="AppNameAndVersion" xml:space="preserve">
<value>Snap Hutao {0}</value>
<value>Ху Тао {0}</value>
</data>
<data name="ContentDialogCancelCloseButtonText" xml:space="preserve">
<value>Отмена</value>
@@ -489,19 +495,19 @@
<value>Волна 3: Волна появится только после убийства всех врагов в предыдущей волне.</value>
</data>
<data name="ModelMetadataTowerWaveTypeWave4" xml:space="preserve">
<value>第四波:击败所有怪物,下一波才会出现</value>
<value>Четвертая волна: Победите всех монстров, прежде чем появится следующая волна</value>
</data>
<data name="ModelNameValueDefaultDescription" xml:space="preserve">
<value>请更新角色橱窗数据</value>
<value>Обновите данные витрины персонажей</value>
</data>
<data name="ModelNameValueDefaultName" xml:space="preserve">
<value>暂无数据</value>
<value>Нет данных</value>
</data>
<data name="ModelWeaponAffixFormat" xml:space="preserve">
<value>精炼 {0}</value>
<value>Уровень совершенствования {0}</value>
</data>
<data name="MustSelectUserAndUid" xml:space="preserve">
<value>必须登录 米游社/HoYoLAB 并选择一个用户与角色</value>
<value>Необходимо войти в учетную запись miHoYo/HoYoLAB и выбрать пользователя с персонажем</value>
</data>
<data name="ServerGachaLogServiceDeleteEntrySucceed" xml:space="preserve">
<value>删除了 Uid{0} 的 {1} 条祈愿记录</value>
@@ -1547,6 +1553,9 @@
<data name="ViewModelLaunchGameSwitchGameAccountFail" xml:space="preserve">
<value>切换账号失败</value>
</data>
<data name="ViewModelLaunchGameUnableToSwitchUidAttachedGameAccount" xml:space="preserve">
<value>无法选择UID [{0}] 对应的账号 [{1}],该账号不属于当前服务器</value>
</data>
<data name="ViewModelSettingActionComplete" xml:space="preserve">
<value>操作完成</value>
</data>
@@ -2138,6 +2147,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>预下载</value>
</data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>选择游戏路径</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>该账号尚未绑定实时便笺通知 UID</value>
</data>
@@ -2270,6 +2282,15 @@
<data name="ViewPageSettingDeviceIpHeader" xml:space="preserve">
<value>设备 IP</value>
</data>
<data name="ViewPageSettingElevatedModeDescription" xml:space="preserve">
<value>管理员模式会影响部分功能的可用性与行为</value>
</data>
<data name="ViewPageSettingElevatedModeHeader" xml:space="preserve">
<value>管理员模式</value>
</data>
<data name="ViewPageSettingElevatedModeRestartAction" xml:space="preserve">
<value>以管理员身份重启</value>
</data>
<data name="ViewPageSettingEmptyHistoryVisibleDescription" xml:space="preserve">
<value>在祈愿记录页面显示或隐藏无记录的历史祈愿活动</value>
</data>
@@ -2729,6 +2750,15 @@
<data name="WebBridgeShareCopyToClipboardSuccess" xml:space="preserve">
<value>已复制到剪贴板</value>
</data>
<data name="WebDailyNoteArchonQuestStatusFinished" xml:space="preserve">
<value>全部完成</value>
</data>
<data name="WebDailyNoteArchonQuestStatusNotOpen" xml:space="preserve">
<value>尚未开启</value>
</data>
<data name="WebDailyNoteArchonQuestStatusOngoing" xml:space="preserve">
<value>进行中</value>
</data>
<data name="WebDailyNoteAttendanceRewardStatusFinishedNonReward" xml:space="preserve">
<value>已完成</value>
</data>

View File

@@ -60,45 +60,45 @@
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
@@ -120,6 +120,12 @@
<data name="AppDevNameAndVersion" xml:space="preserve">
<value>胡桃 Dev {0}</value>
</data>
<data name="AppElevatedDevNameAndVersion" xml:space="preserve">
<value>胡桃Dev {0} [管理员]</value>
</data>
<data name="AppElevatedNameAndVersion" xml:space="preserve">
<value>胡桃 {0} [管理员]</value>
</data>
<data name="AppName" xml:space="preserve">
<value>胡桃</value>
</data>
@@ -142,7 +148,7 @@
<value>無效的 Uri</value>
</data>
<data name="ControlImageCompositionImageHttpRequest" xml:space="preserve">
<value>HTTP GET {0}</value>
<value>获取HTTP{0}</value>
</data>
<data name="ControlImageCompositionImageSystemException" xml:space="preserve">
<value>應用 CompositionImage 的源時發生異常</value>
@@ -292,7 +298,7 @@
<comment>Need EXACT same string in game</comment>
</data>
<data name="ModelIntrinsicBodyTypeBoy" xml:space="preserve">
<value>少</value>
<value>少</value>
</data>
<data name="ModelIntrinsicBodyTypeGirl" xml:space="preserve">
<value>少女</value>
@@ -304,7 +310,7 @@
<value>蘿莉</value>
</data>
<data name="ModelIntrinsicBodyTypeMale" xml:space="preserve">
<value>成</value>
<value>成年男子</value>
</data>
<data name="ModelIntrinsicElementNameElec" xml:space="preserve">
<value>雷</value>
@@ -373,7 +379,7 @@
<comment>Need EXACT same string in game</comment>
</data>
<data name="ModelMetadataAvatarPlayerName" xml:space="preserve">
<value>旅行者</value>
<value>旅</value>
</data>
<data name="ModelMetadataFetterInfoBirthdayFormat" xml:space="preserve">
<value>{0} 月 {1} 日</value>
@@ -480,7 +486,7 @@
<value>第一波:擊敗所有怪物,下一波才會出現</value>
</data>
<data name="ModelMetadataTowerWaveTypeWave1Additional" xml:space="preserve">
<value>第一波加:增援第一波怪物</value>
<value>第一波加:增援第一波怪物</value>
</data>
<data name="ModelMetadataTowerWaveTypeWave2" xml:space="preserve">
<value>第二波:擊敗所有怪物,下一波才會出現</value>
@@ -840,7 +846,7 @@
<value>找不到原神內置瀏覽器緩存路徑:\n{0}</value>
</data>
<data name="ServiceGachaLogUrlProviderCacheUrlNotFound" xml:space="preserve">
<value>找到可用的 Url</value>
<value>找到可用的 Url</value>
</data>
<data name="ServiceGachaLogUrlProviderManualInputInvalid" xml:space="preserve">
<value>提供的 Url 無效</value>
@@ -990,7 +996,7 @@
<value>不支援的 UIGF 版本</value>
</data>
<data name="ServiceUpdateStatusVersionDescription" xml:space="preserve">
<value>发现新版本 {0}</value>
<value>發現新版本 {0}</value>
</data>
<data name="ServiceUserCurrentMultiMatched" xml:space="preserve">
<value>已选中多条用户记录</value>
@@ -1547,6 +1553,9 @@
<data name="ViewModelLaunchGameSwitchGameAccountFail" xml:space="preserve">
<value>切換帳號失敗</value>
</data>
<data name="ViewModelLaunchGameUnableToSwitchUidAttachedGameAccount" xml:space="preserve">
<value>无法选择UID [{0}] 对应的账号 [{1}],该账号不属于当前服务器</value>
</data>
<data name="ViewModelSettingActionComplete" xml:space="preserve">
<value>操作完成</value>
</data>
@@ -2138,6 +2147,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>預下載</value>
</data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>选择游戏路径</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>該用戶尚未綁定即時便箋通知 UID</value>
</data>
@@ -2270,6 +2282,15 @@
<data name="ViewPageSettingDeviceIpHeader" xml:space="preserve">
<value>設備 IP</value>
</data>
<data name="ViewPageSettingElevatedModeDescription" xml:space="preserve">
<value>管理员模式会影响部分功能的可用性与行为</value>
</data>
<data name="ViewPageSettingElevatedModeHeader" xml:space="preserve">
<value>管理员模式</value>
</data>
<data name="ViewPageSettingElevatedModeRestartAction" xml:space="preserve">
<value>以管理员身份重启</value>
</data>
<data name="ViewPageSettingEmptyHistoryVisibleDescription" xml:space="preserve">
<value>在祈願紀錄頁面顯示或隱藏無記錄的歷史祈願活動</value>
</data>
@@ -2729,6 +2750,15 @@
<data name="WebBridgeShareCopyToClipboardSuccess" xml:space="preserve">
<value>已複製到剪貼簿</value>
</data>
<data name="WebDailyNoteArchonQuestStatusFinished" xml:space="preserve">
<value>全部完成</value>
</data>
<data name="WebDailyNoteArchonQuestStatusNotOpen" xml:space="preserve">
<value>尚未开启</value>
</data>
<data name="WebDailyNoteArchonQuestStatusOngoing" xml:space="preserve">
<value>进行中</value>
</data>
<data name="WebDailyNoteAttendanceRewardStatusFinishedNonReward" xml:space="preserve">
<value>已完成</value>
</data>

View File

@@ -173,6 +173,7 @@
<None Remove="View\Dialog\HutaoPassportUnregisterDialog.xaml" />
<None Remove="View\Dialog\LaunchGameAccountNameDialog.xaml" />
<None Remove="View\Dialog\LaunchGamePackageConvertDialog.xaml" />
<None Remove="View\Dialog\ReconfirmDialog.xaml" />
<None Remove="View\Dialog\UserDialog.xaml" />
<None Remove="View\Dialog\UserQRCodeDialog.xaml" />
<None Remove="View\Guide\GuideView.xaml" />
@@ -343,6 +344,11 @@
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<Page Update="View\Dialog\ReconfirmDialog.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Dialog\UserQRCodeDialog.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@@ -0,0 +1,21 @@
<ContentDialog
x:Class="Snap.Hutao.View.Dialog.ReconfirmDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
Title="{shcm:ResourceString Name=ViewDialogReconfirmTitle}"
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
DefaultButton="Close"
IsPrimaryButtonEnabled="False"
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
Style="{StaticResource DefaultContentDialogStyle}"
mc:Ignorable="d">
<TextBox
Margin="0,0,0,8"
VerticalAlignment="Top"
Header="{shcm:ResourceString Name=ViewDialogReconfirmTextHeader}"
Text="{x:Bind Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</ContentDialog>

View File

@@ -0,0 +1,35 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Snap.Hutao.View.Dialog;
[DependencyProperty("Text", typeof(string), default(string), nameof(OnTextChanged))]
internal sealed partial class ReconfirmDialog : ContentDialog
{
private readonly ITaskContext taskContext;
public ReconfirmDialog(IServiceProvider serviceProvider)
{
InitializeComponent();
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
}
public string ConfirmText { get; private set; } = default!;
public async ValueTask<bool> ConfirmAsync(string confirmText)
{
await taskContext.SwitchToMainThreadAsync();
ConfirmText = confirmText;
return await ShowAsync() is ContentDialogResult.Primary;
}
private static void OnTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
ReconfirmDialog dialog = (ReconfirmDialog)sender;
dialog.IsPrimaryButtonEnabled = string.Equals(dialog.Text, dialog.ConfirmText, StringComparison.Ordinal);
}
}

View File

@@ -374,9 +374,14 @@
Description="{shcm:ResourceString Name=ViewPageSettingSetDataFolderDescription}"
Header="{shcm:ResourceString Name=ViewPageSettingSetDataFolderHeader}"
IsClickEnabled="True"/>
<cwc:SettingsCard
ActionIcon="{shcm:FontIcon Glyph=&#xE76C;}"
Command="{Binding DeleteServerCacheFolderCommand}"
Description="{shcm:ResourceString Name=ViewSettingDeleteServerCacheFolderDescription}"
Header="{shcm:ResourceString Name=ViewSettingDeleteServerCacheFolderHeader}"
IsClickEnabled="True"/>
</cwc:SettingsExpander.Items>
</cwc:SettingsExpander>
<cwc:SettingsExpander
Description="{Binding CacheFolderView.Size}"
Header="{shcm:ResourceString Name=ViewPageSettingCacheFolderHeader}"
@@ -408,7 +413,6 @@
HeaderIcon="{cw:FontIcon Glyph=&#xE756;}">
<ToggleSwitch Width="120" IsOn="{Binding IsAllocConsoleDebugModeEnabled, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Header="{shcm:ResourceString Name=ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE730;}"
@@ -424,7 +428,7 @@
</cwc:SettingsCard.Description>
<StackPanel Orientation="Horizontal">
<shvc:Elevation Visibility="{Binding HutaoOptions.IsElevated, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
<ToggleSwitch Width="120" IsOn="{Binding LaunchOptions.IsAdvancedLaunchOptionsEnabled, Mode=TwoWay}"/>
<ToggleSwitch Width="120" IsOn="{Binding IsAdvancedLaunchOptionsEnabled, Mode=TwoWay}"/>
</StackPanel>
</cwc:SettingsCard>
<cwc:SettingsCard
@@ -443,4 +447,4 @@
</StackPanel>
</Grid>
</ScrollViewer>
</shc:ScopedPage>
</shc:ScopedPage>

View File

@@ -13,7 +13,16 @@ internal static class LaunchGameShared
{
public static LaunchScheme? GetCurrentLaunchSchemeFromConfigFile(IGameServiceFacade gameService, IInfoBarService infoBarService)
{
ChannelOptions options = gameService.GetChannelOptions();
ChannelOptions options;
try
{
options = gameService.GetChannelOptions();
}
catch (InvalidOperationException)
{
return default;
}
if (string.IsNullOrEmpty(options.ConfigFilePath))
{
try

View File

@@ -122,11 +122,56 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
public IPInformation? IPInformation { get => ipInformation; private set => SetProperty(ref ipInformation, value); }
[SuppressMessage("", "CA1822")]
public bool IsAllocConsoleDebugModeEnabled
{
get => LocalSetting.Get(SettingKeys.IsAllocConsoleDebugModeEnabled, false);
set => LocalSetting.Set(SettingKeys.IsAllocConsoleDebugModeEnabled, value);
set
{
ConfirmSetIsAllocConsoleDebugModeEnabledAsync(value).SafeForget();
async ValueTask ConfirmSetIsAllocConsoleDebugModeEnabledAsync(bool value)
{
if (value)
{
ReconfirmDialog dialog = await contentDialogFactory.CreateInstanceAsync<ReconfirmDialog>().ConfigureAwait(false);
if (await dialog.ConfirmAsync(SH.ViewSettingAllocConsoleHeader).ConfigureAwait(true))
{
LocalSetting.Set(SettingKeys.IsAllocConsoleDebugModeEnabled, true);
OnPropertyChanged(nameof(IsAllocConsoleDebugModeEnabled));
return;
}
}
LocalSetting.Set(SettingKeys.IsAllocConsoleDebugModeEnabled, false);
OnPropertyChanged(nameof(IsAllocConsoleDebugModeEnabled));
}
}
}
public bool IsAdvancedLaunchOptionsEnabled
{
get => launchOptions.IsAdvancedLaunchOptionsEnabled;
set
{
ConfirmSetIsAdvancedLaunchOptionsEnabledAsync(value).SafeForget();
async ValueTask ConfirmSetIsAdvancedLaunchOptionsEnabledAsync(bool value)
{
if (value)
{
ReconfirmDialog dialog = await contentDialogFactory.CreateInstanceAsync<ReconfirmDialog>().ConfigureAwait(false);
if (await dialog.ConfirmAsync(SH.ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader).ConfigureAwait(true))
{
launchOptions.IsAdvancedLaunchOptionsEnabled = true;
OnPropertyChanged(nameof(IsAllocConsoleDebugModeEnabled));
return;
}
}
launchOptions.IsAdvancedLaunchOptionsEnabled = false;
OnPropertyChanged(nameof(IsAllocConsoleDebugModeEnabled));
}
}
}
protected override async ValueTask<bool> InitializeUIAsync()
@@ -223,6 +268,26 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
}
}
[Command("DeleteServerCacheFolderCommand")]
private async Task DeleteServerCacheFolderAsync()
{
ContentDialogResult result = await contentDialogFactory.CreateForConfirmCancelAsync(
SH.ViewModelSettingDeleteServerCacheFolderTitle,
SH.ViewModelSettingDeleteServerCacheFolderContent)
.ConfigureAwait(false);
if (result is ContentDialogResult.Primary)
{
string cacheFolder = runtimeOptions.GetDataFolderServerCacheFolder();
if (Directory.Exists(cacheFolder))
{
Directory.Delete(cacheFolder, true);
}
infoBarService.Information(SH.ViewModelSettingActionComplete);
}
}
[Command("CopyDeviceIdCommand")]
private void CopyDeviceId()
{

View File

@@ -0,0 +1,41 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Web.WebView2.Core;
using Snap.Hutao.Core.IO.DataTransfer;
using Snap.Hutao.Service.Notification;
using System.Net.Http;
namespace Snap.Hutao.Web.Bridge;
internal sealed class BridgeShareContext
{
private readonly CoreWebView2 coreWebView2;
private readonly ITaskContext taskContext;
private readonly HttpClient httpClient;
private readonly IInfoBarService infoBarService;
private readonly IClipboardProvider clipboardProvider;
private readonly JsonSerializerOptions jsonSerializerOptions;
public BridgeShareContext(CoreWebView2 coreWebView2, ITaskContext taskContext, HttpClient httpClient, IInfoBarService infoBarService, IClipboardProvider clipboardProvider, JsonSerializerOptions jsonSerializerOptions)
{
this.httpClient = httpClient;
this.taskContext = taskContext;
this.infoBarService = infoBarService;
this.clipboardProvider = clipboardProvider;
this.coreWebView2 = coreWebView2;
this.jsonSerializerOptions = jsonSerializerOptions;
}
public CoreWebView2 CoreWebView2 { get => coreWebView2; }
public ITaskContext TaskContext { get => taskContext; }
public HttpClient HttpClient { get => httpClient; }
public IInfoBarService InfoBarService { get => infoBarService; }
public IClipboardProvider ClipboardProvider { get => clipboardProvider; }
public JsonSerializerOptions JsonSerializerOptions { get => jsonSerializerOptions; }
}

View File

@@ -0,0 +1,108 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Web.Bridge.Model;
using System.IO;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
namespace Snap.Hutao.Web.Bridge;
internal sealed partial class BridgeShareImplmentation
{
public static async ValueTask<IJsBridgeResult?> ShareAsync(JsParam<SharePayload> param, BridgeShareContext context)
{
SharePayload payload = param.Payload;
switch (payload.Type)
{
case "image":
{
ShareContent content = payload.Content;
if (content.ImageUrl is { Length: > 0 } imageUrl)
{
await ShareFromImageUrlAsync(context, imageUrl).ConfigureAwait(false);
}
else if (content.ImageBase64 is { } imageBase64)
{
await ShareFromImageBase64Async(context, imageBase64).ConfigureAwait(false);
}
break;
}
case "screenshot":
{
await context.TaskContext.SwitchToMainThreadAsync();
// https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-captureScreenshot
string jsonParameters = """{ "format": "png", "captureBeyondViewport": true }""";
string resultJson = await context.CoreWebView2.CallDevToolsProtocolMethodAsync("Page.captureScreenshot", jsonParameters);
CaptureScreenshotResult? result = JsonSerializer.Deserialize<CaptureScreenshotResult>(resultJson, context.JsonSerializerOptions);
ArgumentNullException.ThrowIfNull(result);
await ShareFromRawPixelDataAsync(context, result.Data).ConfigureAwait(false);
break;
}
}
return new JsResult<Dictionary<string, string>>()
{
Data = new()
{
["type"] = param.Payload.Type,
},
};
}
private static async ValueTask ShareFromImageUrlAsync(BridgeShareContext context, string imageUrl)
{
using (Stream stream = await context.HttpClient.GetStreamAsync(imageUrl).ConfigureAwait(false))
{
await ShareCoreAsync(context, stream, static (stream, web) => web.CopyToAsync(stream.AsStreamForWrite())).ConfigureAwait(false);
}
}
private static ValueTask ShareFromImageBase64Async(BridgeShareContext context, string base64ImageData)
{
return ShareFromRawPixelDataAsync(context, Convert.FromBase64String(base64ImageData));
}
private static ValueTask ShareFromRawPixelDataAsync(BridgeShareContext context, byte[] rawPixelData)
{
return ShareCoreAsync(context, rawPixelData, static (stream, bytes) => stream.AsStreamForWrite().WriteAsync(bytes).AsTask());
}
private static async ValueTask ShareCoreAsync<TData>(BridgeShareContext context, TData data, Func<InMemoryRandomAccessStream, TData, Task> asyncWriteData)
{
using (InMemoryRandomAccessStream rawPixelDataStream = new())
{
await asyncWriteData(rawPixelDataStream, data).ConfigureAwait(false);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(rawPixelDataStream);
using (InMemoryRandomAccessStream stream = new())
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetSoftwareBitmap(await decoder.GetSoftwareBitmapAsync());
await encoder.FlushAsync();
await context.TaskContext.SwitchToMainThreadAsync();
if (context.ClipboardProvider.SetBitmap(stream))
{
context.InfoBarService.Success(SH.WebBridgeShareCopyToClipboardSuccess);
}
else
{
context.InfoBarService.Error(SH.WebBridgeShareCopyToClipboardFailed);
}
}
}
}
private sealed class CaptureScreenshotResult
{
[JsonPropertyName("data")]
public byte[] Data { get; set; } = default!;
}
}

View File

@@ -14,12 +14,9 @@ using Snap.Hutao.Web.Hoyolab.Bbs.User;
using Snap.Hutao.Web.Hoyolab.DataSigning;
using Snap.Hutao.Web.Hoyolab.Takumi.Auth;
using Snap.Hutao.Web.Response;
using System.IO;
using System.Net.Http;
using System.Text;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
namespace Snap.Hutao.Web.Bridge;
@@ -84,15 +81,12 @@ internal class MiHoYoJSBridge
""";
private readonly SemaphoreSlim webMessageSemaphore = new(1);
private readonly Guid interfaceId = Guid.NewGuid();
private readonly Guid bridgeId = Guid.NewGuid();
private readonly UserAndUid userAndUid;
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
private readonly ILogger<MiHoYoJSBridge> logger;
private readonly IInfoBarService infoBarService;
private readonly IClipboardProvider clipboardProvider;
private readonly HttpClient httpClient;
private readonly TypedEventHandler<CoreWebView2, CoreWebView2WebMessageReceivedEventArgs> webMessageReceivedEventHandler;
private readonly TypedEventHandler<CoreWebView2, CoreWebView2DOMContentLoadedEventArgs> domContentLoadedEventHandler;
@@ -109,9 +103,6 @@ internal class MiHoYoJSBridge
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
logger = serviceProvider.GetRequiredService<ILogger<MiHoYoJSBridge>>();
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
clipboardProvider = serviceProvider.GetRequiredService<IClipboardProvider>();
httpClient = serviceProvider.GetRequiredService<HttpClient>();
webMessageReceivedEventHandler = OnWebMessageReceived;
domContentLoadedEventHandler = OnDOMContentLoaded;
@@ -132,11 +123,6 @@ internal class MiHoYoJSBridge
coreWebView2 = default!;
}
/// <summary>
/// 关闭
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual async ValueTask<IJsBridgeResult?> ClosePageAsync(JsParam param)
{
await taskContext.SwitchToMainThreadAsync();
@@ -152,21 +138,11 @@ internal class MiHoYoJSBridge
return null;
}
/// <summary>
/// 调整分享设置
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual IJsBridgeResult? ConfigureShare(JsParam param)
{
return null;
}
/// <summary>
/// 获取ActionTicket
/// </summary>
/// <param name="jsParam">参数</param>
/// <returns>响应</returns>
protected virtual async ValueTask<IJsBridgeResult?> GetActionTicketAsync(JsParam<ActionTypePayload> jsParam)
{
return await serviceProvider
@@ -175,11 +151,6 @@ internal class MiHoYoJSBridge
.ConfigureAwait(false);
}
/// <summary>
/// 异步获取账户信息
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual JsResult<Dictionary<string, string>> GetCookieInfo(JsParam param)
{
ArgumentNullException.ThrowIfNull(userAndUid.User.LToken);
@@ -195,11 +166,6 @@ internal class MiHoYoJSBridge
};
}
/// <summary>
/// 获取CookieToken
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual async ValueTask<JsResult<Dictionary<string, string>>> GetCookieTokenAsync(JsParam<CookieTokenPayload> param)
{
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
@@ -215,11 +181,6 @@ internal class MiHoYoJSBridge
return new() { Data = new() { [Cookie.COOKIE_TOKEN] = userAndUid.User.CookieToken[Cookie.COOKIE_TOKEN] } };
}
/// <summary>
/// 获取当前语言和时区
/// </summary>
/// <param name="param">param</param>
/// <returns>语言与时区</returns>
protected virtual JsResult<Dictionary<string, string>> GetCurrentLocale(JsParam<PushPagePayload> param)
{
MetadataOptions metadataOptions = serviceProvider.GetRequiredService<MetadataOptions>();
@@ -234,11 +195,6 @@ internal class MiHoYoJSBridge
};
}
/// <summary>
/// 获取1代动态密钥
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV1(JsParam param)
{
DataSignOptions options = DataSignOptions.CreateForGeneration1(SaltType.LK2, true);
@@ -251,11 +207,6 @@ internal class MiHoYoJSBridge
};
}
/// <summary>
/// 获取2代动态密钥
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV2(JsParam<DynamicSecrect2Playload> param)
{
DataSignOptions options = DataSignOptions.CreateForGeneration2(SaltType.X4, false, param.Payload.Body, param.Payload.GetQueryParam());
@@ -268,11 +219,6 @@ internal class MiHoYoJSBridge
};
}
/// <summary>
/// 获取Http请求头
/// </summary>
/// <param name="param">参数</param>
/// <returns>Http请求头</returns>
protected virtual JsResult<Dictionary<string, string>> GetHttpRequestHeader(JsParam param)
{
Dictionary<string, string> headers = new()
@@ -306,21 +252,11 @@ internal class MiHoYoJSBridge
{
}
/// <summary>
/// 获取状态栏高度
/// </summary>
/// <param name="param">参数</param>
/// <returns>结果</returns>
protected virtual JsResult<Dictionary<string, object>> GetStatusBarHeight(JsParam param)
{
return new() { Data = new() { ["statusBarHeight"] = 0 } };
}
/// <summary>
/// 获取用户基本信息
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
protected virtual async ValueTask<JsResult<Dictionary<string, object>>> GetUserInfoAsync(JsParam param)
{
Response<UserFullInfoWrapper> response = await serviceProvider
@@ -374,81 +310,18 @@ internal class MiHoYoJSBridge
return null;
}
protected virtual async ValueTask<IJsBridgeResult?> Share(JsParam<SharePayload> param)
protected virtual async ValueTask<IJsBridgeResult?> ShareAsync(JsParam<SharePayload> param)
{
if (param.Payload.Type is "image")
using (IServiceScope scope = serviceProvider.CreateScope())
{
if (param.Payload.Content.ImageUrl is { } imageUrl)
{
using (Stream stream = await httpClient.GetStreamAsync(imageUrl).ConfigureAwait(false))
{
using (InMemoryRandomAccessStream origStream = new())
{
await stream.CopyToAsync(origStream.AsStreamForWrite()).ConfigureAwait(false);
using (InMemoryRandomAccessStream imageStream = new())
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, imageStream);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(origStream);
encoder.SetSoftwareBitmap(await decoder.GetSoftwareBitmapAsync());
await encoder.FlushAsync();
await taskContext.SwitchToMainThreadAsync();
if (clipboardProvider.SetBitmap(imageStream))
{
infoBarService.Success(SH.WebBridgeShareCopyToClipboardSuccess);
}
else
{
infoBarService.Error(SH.WebBridgeShareCopyToClipboardFailed);
}
}
}
}
}
else if (param.Payload.Content.ImageBase64 is { } imageBase64)
{
await ShareImageBase64CoreAsync(imageBase64).ConfigureAwait(false);
}
}
else if (param.Payload.Type is "screenshot")
{
await taskContext.SwitchToMainThreadAsync();
string base64Json = await coreWebView2.CallDevToolsProtocolMethodAsync("Page.captureScreenshot", """{"format":"png","captureBeyondViewport":true}""");
string? base64 = JsonDocument.Parse(base64Json).RootElement.GetProperty("data").GetString();
ArgumentNullException.ThrowIfNull(base64);
JsonSerializerOptions jsonSerializerOptions = scope.ServiceProvider.GetRequiredService<JsonSerializerOptions>();
HttpClient httpClient = scope.ServiceProvider.GetRequiredService<HttpClient>();
IClipboardProvider clipboardProvider = scope.ServiceProvider.GetRequiredService<IClipboardProvider>();
IInfoBarService infoBarService = scope.ServiceProvider.GetRequiredService<IInfoBarService>();
await ShareImageBase64CoreAsync(base64).ConfigureAwait(false);
}
BridgeShareContext context = new(coreWebView2, taskContext, httpClient, infoBarService, clipboardProvider, jsonSerializerOptions);
return new JsResult<Dictionary<string, string>>()
{
Data = new()
{
["type"] = param.Payload.Type,
},
};
}
private async ValueTask ShareImageBase64CoreAsync(string base64)
{
using (MemoryStream imageStream = new())
{
await imageStream.WriteAsync(Convert.FromBase64String(base64)).ConfigureAwait(false);
using (InMemoryRandomAccessStream stream = new())
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream.AsRandomAccessStream());
encoder.SetSoftwareBitmap(await decoder.GetSoftwareBitmapAsync());
await encoder.FlushAsync();
await taskContext.SwitchToMainThreadAsync();
if (clipboardProvider.SetBitmap(stream))
{
infoBarService.Success(SH.WebBridgeShareCopyToClipboardSuccess);
}
else
{
infoBarService.Error(SH.WebBridgeShareCopyToClipboardFailed);
}
}
return await BridgeShareImplmentation.ShareAsync(param, context).ConfigureAwait(false);
}
}
@@ -519,7 +392,7 @@ internal class MiHoYoJSBridge
.Append(')')
.ToString();
logger?.LogInformation("[{Id}][ExecuteScript: {callback}]\n{payload}", interfaceId, callback, payload);
logger?.LogInformation("[{Id}][ExecuteScript: {callback}]\n{payload}", bridgeId, callback, payload);
await taskContext.SwitchToMainThreadAsync();
if (coreWebView2 is null || coreWebView2.IsDisposed())
@@ -533,7 +406,7 @@ internal class MiHoYoJSBridge
private async void OnWebMessageReceived(CoreWebView2 webView2, CoreWebView2WebMessageReceivedEventArgs args)
{
string message = args.TryGetWebMessageAsString();
logger.LogInformation("[{Id}][OnRawMessage]\n{message}", interfaceId, message);
logger.LogInformation("[{Id}][OnRawMessage]\n{message}", bridgeId, message);
JsParam? param = JsonSerializer.Deserialize<JsParam>(message);
ArgumentNullException.ThrowIfNull(param);
@@ -582,7 +455,7 @@ internal class MiHoYoJSBridge
"hideLoading" => null,
"login" => null,
"pushPage" => await PushPageAsync(param).ConfigureAwait(false),
"share" => await Share(param).ConfigureAwait(false),
"share" => await ShareAsync(param).ConfigureAwait(false),
"showLoading" => null,
_ => LogUnhandledMessage("Unhandled Message Type: {Method}", param.Method),
};

View File

@@ -6,20 +6,12 @@ namespace Snap.Hutao.Web.Bridge.Model;
[SuppressMessage("", "SA1124")]
internal sealed class ShareContent
{
#region Screenshot
[JsonPropertyName("preview")]
public bool Preview { get; set; }
#endregion
#region Image
[JsonPropertyName("image_url")]
public string? ImageUrl { get; set; }
[JsonPropertyName("image_base64")]
public string? ImageBase64 { get; set; }
#endregion
}