Compare commits
268 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5c5c1c95c | ||
|
|
a4f555ea40 | ||
|
|
1ea0a14926 | ||
|
|
a26b6fc528 | ||
|
|
e4523d540c | ||
|
|
6a309321f6 | ||
|
|
512b1257a8 | ||
|
|
d5b668cb8d | ||
|
|
32177491da | ||
|
|
e5012d9051 | ||
|
|
cad1182ade | ||
|
|
e58d982e72 | ||
|
|
9749c6c342 | ||
|
|
179b78ca83 | ||
|
|
79118cdb4d | ||
|
|
35e7aaef4e | ||
|
|
97f5904efa | ||
|
|
50112cb3f6 | ||
|
|
3dd7a8c85f | ||
|
|
ca06fe7b02 | ||
|
|
04e9f7db72 | ||
|
|
7facf43332 | ||
|
|
bc7cf93137 | ||
|
|
877dd93bad | ||
|
|
98b3f2d202 | ||
|
|
0a7bd55dab | ||
|
|
e9a8e906da | ||
|
|
93523c8832 | ||
|
|
541455e51d | ||
|
|
cdc48a1a4f | ||
|
|
ab65a62c11 | ||
|
|
9e90cfb1c8 | ||
|
|
b1ace71648 | ||
|
|
015c731df0 | ||
|
|
8ea4411e2a | ||
|
|
f90b828bb4 | ||
|
|
97cbe7cf55 | ||
|
|
09abb46159 | ||
|
|
523374ed3d | ||
|
|
9decb67cff | ||
|
|
af26c06cfc | ||
|
|
b550b91cc9 | ||
|
|
2ba6377088 | ||
|
|
18f8137f41 | ||
|
|
32ae92e49d | ||
|
|
805fd31bf8 | ||
|
|
b65e0c94f0 | ||
|
|
7e3d7e9076 | ||
|
|
2c162d1fef | ||
|
|
bfacf42d71 | ||
|
|
eeee171b78 | ||
|
|
9861a3df37 | ||
|
|
84b9a9de23 | ||
|
|
11828bd280 | ||
|
|
b29d66d6b6 | ||
|
|
a25d1ba4ce | ||
|
|
5505927ca1 | ||
|
|
d3a60451a4 | ||
|
|
915635a843 | ||
|
|
918e84be61 | ||
|
|
a8a3354217 | ||
|
|
b6f6c5d54b | ||
|
|
a9e0e3db39 | ||
|
|
ece3f2cd08 | ||
|
|
7612a2e7c0 | ||
|
|
eee34ec4c7 | ||
|
|
e24a7436b4 | ||
|
|
a543bf3091 | ||
|
|
1d88360528 | ||
|
|
f21d04fadc | ||
|
|
0cd6bf95a9 | ||
|
|
4de01d2f62 | ||
|
|
05d226ad15 | ||
|
|
eabf2a9ea8 | ||
|
|
e796afbbb0 | ||
|
|
d6099f10ad | ||
|
|
f837b39ecf | ||
|
|
770cabce81 | ||
|
|
cec4b2a23a | ||
|
|
c60748626a | ||
|
|
51d8ee5d6e | ||
|
|
64c020a5fb | ||
|
|
934fb75fa5 | ||
|
|
85b9fc1a08 | ||
|
|
314f86966a | ||
|
|
5aba2eab97 | ||
|
|
fdf2311f0c | ||
|
|
b0b3553d0c | ||
|
|
388cdf1848 | ||
|
|
22f4f411ea | ||
|
|
b89c66fd6b | ||
|
|
0295d4fc22 | ||
|
|
d85811ee99 | ||
|
|
dc8d7ac913 | ||
|
|
a832ea96ea | ||
|
|
29582efaee | ||
|
|
6caeb1d238 | ||
|
|
439a8dd475 | ||
|
|
60c7e65abb | ||
|
|
5c0984b064 | ||
|
|
9b8cce30a7 | ||
|
|
463a842cb1 | ||
|
|
8ee2908633 | ||
|
|
c71ecd89e3 | ||
|
|
128b985609 | ||
|
|
b1a03662d9 | ||
|
|
706fb3404b | ||
|
|
63e1273d6a | ||
|
|
400a3b99ae | ||
|
|
c0c1774db8 | ||
|
|
099fbf4052 | ||
|
|
5c4405e545 | ||
|
|
ac68579d6a | ||
|
|
f3387bb8c8 | ||
|
|
e50c1b9184 | ||
|
|
54535cd822 | ||
|
|
ece2737633 | ||
|
|
4b012424b9 | ||
|
|
6d66af6c84 | ||
|
|
027874d4cf | ||
|
|
3001936ab3 | ||
|
|
400e097fa7 | ||
|
|
ffce055d75 | ||
|
|
a820c41ad7 | ||
|
|
485010c895 | ||
|
|
5feddf566e | ||
|
|
cdfe306b16 | ||
|
|
189c61ddea | ||
|
|
0ac7d6e94d | ||
|
|
042e3b5747 | ||
|
|
0372f1a8e3 | ||
|
|
08a630fd43 | ||
|
|
3781cad896 | ||
|
|
78bc2f09d5 | ||
|
|
8c52921b3e | ||
|
|
605aecb216 | ||
|
|
e3e124d52f | ||
|
|
0866e1947b | ||
|
|
dbcb7dd879 | ||
|
|
44687dd87b | ||
|
|
1a209f6c8d | ||
|
|
8633b78725 | ||
|
|
2e20701c6c | ||
|
|
9c4d4cda1e | ||
|
|
a32481980b | ||
|
|
b5577e76a5 | ||
|
|
6c2ff9b3c9 | ||
|
|
818365b816 | ||
|
|
d7dd8c6f0d | ||
|
|
faad104e0e | ||
|
|
2f6ee75f80 | ||
|
|
34f319bdac | ||
|
|
f242808768 | ||
|
|
98f18f91d8 | ||
|
|
0fd1f6959a | ||
|
|
ba46ed64db | ||
|
|
0fb8312605 | ||
|
|
b722554950 | ||
|
|
165c33ef2c | ||
|
|
54bb3d634b | ||
|
|
629975480a | ||
|
|
5a36448c23 | ||
|
|
80a6aaab46 | ||
|
|
6c83cd3da5 | ||
|
|
e60a04a2bc | ||
|
|
aec483510f | ||
|
|
c245fe654e | ||
|
|
898d95bb1d | ||
|
|
1df22e5b75 | ||
|
|
332e09fef0 | ||
|
|
2a77daf2ca | ||
|
|
8a47ea8727 | ||
|
|
b3937ac810 | ||
|
|
ed5c52dc63 | ||
|
|
461d139602 | ||
|
|
164ec2af33 | ||
|
|
e30523c621 | ||
|
|
11d0405102 | ||
|
|
a1c0b4f830 | ||
|
|
e476ed5960 | ||
|
|
ffc999360d | ||
|
|
84058011c7 | ||
|
|
c18e0c40c5 | ||
|
|
ad78515094 | ||
|
|
38367a090d | ||
|
|
ce30f609fb | ||
|
|
f4b9cc7c48 | ||
|
|
7c2212f44c | ||
|
|
95eddef457 | ||
|
|
02447bc966 | ||
|
|
fb88e33d16 | ||
|
|
5fa36416ef | ||
|
|
7076caaa5d | ||
|
|
b7b1155cfc | ||
|
|
6351f2b460 | ||
|
|
35ac2f33ba | ||
|
|
f8ff1988bb | ||
|
|
907d70ba71 | ||
|
|
a5bdc17712 | ||
|
|
f078d92f33 | ||
|
|
f2d4f0f1d3 | ||
|
|
fcde9b21ae | ||
|
|
24f09861fd | ||
|
|
47708adc83 | ||
|
|
79a254235a | ||
|
|
d9bcb3b16b | ||
|
|
cf7dd548a2 | ||
|
|
04deeb7086 | ||
|
|
9fb2da41cd | ||
|
|
bb01f3a3cb | ||
|
|
f7f2d9c867 | ||
|
|
01b7e58b3e | ||
|
|
2518ae0b90 | ||
|
|
7d4a8cdcd9 | ||
|
|
623893e00e | ||
|
|
0d34c81bcf | ||
|
|
5f3d0126b3 | ||
|
|
5d1fe3f38a | ||
|
|
c810ffa625 | ||
|
|
ee70205245 | ||
|
|
06c8b347d3 | ||
|
|
5c6ab1dee9 | ||
|
|
ad440e0561 | ||
|
|
ca56d8c636 | ||
|
|
da0ee0cca6 | ||
|
|
5d00d9cc0d | ||
|
|
e8b27e6655 | ||
|
|
0ac79012d1 | ||
|
|
bb2665b75e | ||
|
|
d22ac39c1d | ||
|
|
a312603d61 | ||
|
|
0732ea0e06 | ||
|
|
e4d2b3055c | ||
|
|
5668931230 | ||
|
|
5126337138 | ||
|
|
4d634d3264 | ||
|
|
15a69fd0de | ||
|
|
c232891fe7 | ||
|
|
c35c2a5700 | ||
|
|
42305094f8 | ||
|
|
9ef48ab05c | ||
|
|
eec010870a | ||
|
|
a24fbf535d | ||
|
|
f7bd184a3c | ||
|
|
267f285101 | ||
|
|
2a1e77a9db | ||
|
|
abdc8e2e9f | ||
|
|
64f1af293b | ||
|
|
e0336d6b30 | ||
|
|
23f3e5df77 | ||
|
|
4a027a8d3f | ||
|
|
80459708a7 | ||
|
|
650b67bea0 | ||
|
|
18b3d23b1c | ||
|
|
bf08ffa89e | ||
|
|
915b1aae32 | ||
|
|
71a1bdc173 | ||
|
|
af4180bdeb | ||
|
|
a70593c529 | ||
|
|
810f8704e6 | ||
|
|
0165c03ae6 | ||
|
|
423188c16a | ||
|
|
5fb935635b | ||
|
|
761049ec17 | ||
|
|
3f8c8874f3 | ||
|
|
b8f354bbc7 | ||
|
|
d45c40d4d7 | ||
|
|
6b309c4886 |
13
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: https://afdian.net/a/DismissedLight
|
||||
33
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -15,17 +15,15 @@ body:
|
||||
description: |-
|
||||
请确保你已完整执行检查清单,否则你的 Issue 可能会被忽略
|
||||
options:
|
||||
- label: 我已完整阅读[胡桃工具箱文档](https://hut.ao/FAQ/most-frequent-questions.html),并认为我的问题没有在文档中得到解答
|
||||
required: true
|
||||
- label: 我并未完整阅读[胡桃工具箱文档](https://hut.ao/advanced/FAQ.html)
|
||||
|
||||
- label: 我不知道文档站的导航栏中有**搜索功能**,也没有搜索过相关关键词
|
||||
|
||||
- label: 我使用的操作系统是[受支持的版本](https://hut.ao/quick-start.html#%E6%9C%80%E4%BD%8E%E7%B3%BB%E7%BB%9F%E8%A6%81%E6%B1%82)
|
||||
required: true
|
||||
- label: 我使用的操作系统是不[受支持的版本](https://hut.ao/quick-start.html#%E6%9C%80%E4%BD%8E%E7%B3%BB%E7%BB%9F%E8%A6%81%E6%B1%82)
|
||||
|
||||
- label: 我确认没有其他人已经提出了相同或类似的问题
|
||||
required: true
|
||||
|
||||
- label: 我会在下方的表单中附上充足的信息以帮助开发人员确定问题
|
||||
required: true
|
||||
- label: 我没有**通过搜索功能**确认其他人提出过相同或类似的问题
|
||||
|
||||
- label: 我不明白上述的勾选项是**一个有助于快速排查问题的检查清单**,而是随手确认的选项
|
||||
|
||||
- type: input
|
||||
id: winver
|
||||
@@ -33,7 +31,7 @@ body:
|
||||
label: Windows 版本
|
||||
description: |
|
||||
`Win+R` 输入 `winver` 回车后在打开的窗口第二行可以找到
|
||||
placeholder: 例:22000.556
|
||||
placeholder: 例:22621.1105
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -42,7 +40,7 @@ body:
|
||||
attributes:
|
||||
label: Snap Hutao 版本
|
||||
description: 在应用标题,应用程序的设置界面中靠下的位置可以找到
|
||||
placeholder: 例:1.1.0
|
||||
placeholder: 例:1.4.15.0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -68,6 +66,7 @@ body:
|
||||
- 游戏启动器
|
||||
- 实时便笺
|
||||
- 养成计算器
|
||||
- 用户面板
|
||||
- 文件缓存
|
||||
- 祈愿记录
|
||||
- 玩家查询
|
||||
@@ -95,14 +94,4 @@ body:
|
||||
description: 详细的描述你期望发生的行为,突出与目前(可能不正确的)行为的不同
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: 相关的崩溃日志
|
||||
description: |
|
||||
在资源管理器中直接输入`%userprofile%/Documents/Hutao`即可进入文件夹
|
||||
如果应用程序崩溃了,请将`log.db` 文件上传,文件包含了敏感信息,谨慎上传
|
||||
如果这个表单是关于导入祈愿记录的问题,请包含你导入的`Json`文件
|
||||
> **务必不要上传`user.db`文件,该文件包含你的帐号敏感信息**
|
||||
|
||||
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -14,7 +14,7 @@ body:
|
||||
id: back
|
||||
attributes:
|
||||
label: 背景与动机
|
||||
description: 添加此功能的理由
|
||||
description: 添加此功能的理由,如果你想要实现多个功能,请分别发起多个单独的 Issue
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/network-issue.yml
vendored
@@ -21,8 +21,8 @@ body:
|
||||
**在填写下面的问题之前请先使用我们的网络诊断工具**
|
||||
**这个工具将会生成一份报告,请将这份报告拖入下面的框中,让其与你的工单一起被上传提交**
|
||||
- 你可以点击下面的链接以下载网络诊断工具:
|
||||
- [胡桃资源站](https://d.hut.ao/d/tools/network-diagnosis-tool.exe)
|
||||
- [GitHub](https://github.com/DGP-Studio/Snap.Hutao/files/10081999/network-diagnosis-hutao.zip)
|
||||
- [胡桃资源站](https://d.hut.ao/d/tools/network-diagnosis-hutao.exe)
|
||||
- [GitHub](https://github.com/Masterain98/network-diagnosis-tool/releases/latest/download/network-diagnosis-hutao.exe)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -41,7 +41,7 @@ body:
|
||||
id: user-isp
|
||||
attributes:
|
||||
label: 你的运营商
|
||||
description: 中国用户请精确到省级行政区,海外地区请精确到国家
|
||||
description: 海外用户请选其它
|
||||
options:
|
||||
- 中国电信
|
||||
- 中国联通
|
||||
@@ -60,7 +60,9 @@ body:
|
||||
- 完全无法连接服务器
|
||||
- 连接速度慢
|
||||
- 获取到了不正确的页面或数据
|
||||
- 图片下载错误(429 Error)
|
||||
- 客户端提示 429 Error
|
||||
- 客户端图片下载错误
|
||||
- 客户端图片预下载错误
|
||||
- 其它
|
||||
validations:
|
||||
required: true
|
||||
|
||||
11
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "nuget" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
20
.github/workflows/PublishDistribution.yml
vendored
@@ -2,7 +2,7 @@ name: PublishDistribution
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
types: [released]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -16,14 +16,14 @@ jobs:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Download Publish.zip
|
||||
# Download Assets
|
||||
- name: Download Release
|
||||
timeout-minutes: 5
|
||||
uses: robinraju/release-downloader@v1.5
|
||||
uses: robinraju/release-downloader@v1.7
|
||||
with:
|
||||
repository: "DGP-Studio/Snap.Hutao"
|
||||
latest: true
|
||||
fileName: "*.zip"
|
||||
fileName: "*.msix"
|
||||
out-file-path: ./release-download
|
||||
|
||||
# Upload to Drive
|
||||
@@ -38,4 +38,14 @@ jobs:
|
||||
$RCCONF
|
||||
EOF
|
||||
|
||||
rclone copy ./release-download/* dgpODCN:/snaphutao/Releases/
|
||||
rclone copy ./release-download/* dgpODCN:/releases/
|
||||
|
||||
# Purge Patch System Cache
|
||||
- name: Purge Patch
|
||||
env:
|
||||
PATCH_HOSTS: ${{ secrets.PATCH_HOSTS }}
|
||||
PURGE_TOKEN: ${{ secrets.PURGE_TOKEN }}
|
||||
PURGE_URL: ${{ secrets.PURGE_URL }}
|
||||
run: |
|
||||
sudo echo "$PATCH_HOSTS" | sudo tee -a /etc/hosts
|
||||
curl --header "Authorization: token $PURGE_TOKEN" $PURGE_URL
|
||||
|
||||
7
.gitignore
vendored
@@ -4,9 +4,6 @@
|
||||
|
||||
.vs/
|
||||
|
||||
src/Snap.Hutao/SettingsUI/bin
|
||||
src/Snap.Hutao/SettingsUI/obj
|
||||
|
||||
src/Snap.Hutao/Snap.Hutao/bin/
|
||||
src/Snap.Hutao/Snap.Hutao/obj/
|
||||
src/Snap.Hutao/Snap.Hutao/Snap.Hutao_TemporaryKey.pfx
|
||||
@@ -18,5 +15,5 @@ src/Snap.Hutao/Snap.Hutao.Installer/Properties/PublishProfiles/FolderProfile.pub
|
||||
src/Snap.Hutao/Snap.Hutao.SourceGeneration/bin/
|
||||
src/Snap.Hutao/Snap.Hutao.SourceGeneration/obj/
|
||||
|
||||
src/Snap.Hutao/Snap.Hutao.Win32/bin/
|
||||
src/Snap.Hutao/Snap.Hutao.Win32/obj/
|
||||
src/Snap.Hutao/Snap.Hutao.Test/bin/
|
||||
src/Snap.Hutao/Snap.Hutao.Test/obj/
|
||||
13
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Code of Conduct
|
||||
|
||||
> Snap Hutao is adapting the following rules to keep the community safety.
|
||||
|
||||
When participating in our open source community, we want all members to respect and support each other. To ensure the comfort and safety of our community members, we have established the following code of conduct:
|
||||
|
||||
1. Respect diversity and inclusivity. We welcome people from different countries, regions, genders, sexual orientations, abilities, religions, and cultural backgrounds to participate in our community, and we encourage respect for all differences.
|
||||
2. Prohibit discrimination and harassment. We do not tolerate any form of discrimination, harassment, personal attacks, or insults. This includes but is not limited to race, gender, sexual orientation, age, religion, nationality, cultural background, physical and mental health status.
|
||||
3. Respect privacy and personal information. We protect the privacy and personal information of community members and prohibit the public disclosure of any private information. If you need to disclose certain information, please make sure you have obtained the relevant person's permission.
|
||||
4. Keep honesty and transparency. We expect community members to maintain honesty and transparency and not intentionally mislead or deceive others.
|
||||
5. Respect community rules and other members. We encourage community members to follow community rules and guidelines and maintain a polite and respectful attitude towards other members. If you find that other members are violating community rules, please report it to community administrators or organizers in a timely manner.
|
||||
|
||||
The above is our community's code of conduct, and we expect all community members to abide by these rules. We will actively address behaviors that violate these rules. We believe that through mutual respect and support, we can build a friendly, inclusive, and beneficial open source community.
|
||||
19
NuGet.Config
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="Microsoft CsWin32" value="https://pkgs.dev.azure.com/azure-public/winsdk/_packaging/CI/nuget/v3/index.json" />
|
||||
<add key="CommunityToolkit Labs" value="https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
<packageRestore>
|
||||
<add key="enabled" value="True" />
|
||||
<add key="automatic" value="True" />
|
||||
</packageRestore>
|
||||
<bindingRedirects>
|
||||
<add key="skip" value="False" />
|
||||
</bindingRedirects>
|
||||
<packageManagement>
|
||||
<add key="format" value="1" />
|
||||
<add key="disabled" value="False" />
|
||||
</packageManagement>
|
||||
</configuration>
|
||||
35
README.md
@@ -1,24 +1,34 @@
|
||||
# [Snap.Hutao](https://hut.ao)
|
||||
> 唷,找本堂主有何贵干呀?
|
||||

|
||||
|
||||

|
||||
胡桃工具箱是一个 Windows 平台的开源的原神工具箱,旨在帮助玩家获得更好的游戏体验; 它是对官方移动端工具的一种非破坏性功能扩展,为不习惯在移动端进行原神游戏的 PC 玩家提供一个在 Windows 平台下获得接近移动端功能权利的途径
|
||||
|
||||
# 特别感谢
|
||||
Snap Hutao is an open-source Genshin Impact toolbox on Windows platform, aim to provide a better gaming experience for players. It's an nondestructive feature extension from Genshin Impact's official mobile application, to provide similar feature on desktop, to allow PC gamers gain deserved benefits from mobile platforms.
|
||||
|
||||
### 原神组织与个人
|
||||
## 下载使用 / 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)
|
||||
|
||||
## 贡献 / Contribute
|
||||
|
||||
* [向我们提交 PR / Make Pull Requests](https://github.com/DGP-Studio/Snap.Hutao/pulls)
|
||||
* [在 Crowdin 上进行本地化 / Translate project on Crowdin](https://translate.hut.ao/)
|
||||
* [为我们更新文档 / Enhance our Document ](https://github.com/DGP-Studio/Snap.Hutao.Docs)
|
||||
|
||||
## 特别感谢 / Special Thanks
|
||||
|
||||
* [HolographicHat](https://github.com/HolographicHat)
|
||||
* [UIGF organization](https://uigf.org)
|
||||
|
||||
### 特定的原神项目
|
||||
### 特定的原神项目 / Specific Genshin-related Project
|
||||
|
||||
* [biuuu/genshin-wish-export](https://github.com/biuuu/genshin-wish-export)
|
||||
* [xunkong/xunkong](https://github.com/xunkong/xunkong)
|
||||
* [YuehaiTeam/cocogoat](https://github.com/YuehaiTeam/cocogoat)
|
||||
|
||||
### 使用的技术栈
|
||||
### 使用的技术栈 / Tech Stack
|
||||
|
||||
* [CommunityToolkit/dotnet](https://github.com/CommunityToolkit/dotnet)
|
||||
* [CommunityToolkit/Labs-Windows](https://github.com/CommunityToolkit/Labs-Windows)
|
||||
* [CommunityToolkit/WindowsCommunityToolkit](https://github.com/CommunityToolkit/WindowsCommunityToolkit)
|
||||
* [dahall/taskscheduler](https://github.com/dahall/taskscheduler)
|
||||
* [dotnet/efcore](https://github.com/dotnet/efcore)
|
||||
@@ -28,4 +38,13 @@
|
||||
* [microsoft/vs-threading](https://github.com/microsoft/vs-threading)
|
||||
* [microsoft/vs-validation](https://github.com/microsoft/vs-validation)
|
||||
* [microsoft/WindowsAppSDK](https://github.com/microsoft/WindowsAppSDK)
|
||||
* [microsoft/microsoft-ui-xaml](https://github.com/microsoft/microsoft-ui-xaml)
|
||||
* [microsoft/microsoft-ui-xaml](https://github.com/microsoft/microsoft-ui-xaml)
|
||||
|
||||
### 支撑项目 / Supporter Project
|
||||
|
||||
* [Snap.Hutao.Server](https://github.com/DGP-Studio/Snap.Hutao.Server)
|
||||
* [Snap.Metadata](https://github.com/DGP-Studio/Snap.Metadata)
|
||||
* [Snap.Data.Mapper](https://github.com/DGP-Studio/Snap.Data.Mapper)
|
||||
|
||||
## 近期活跃数据 / Active Stat
|
||||

|
||||
|
||||
12
SECURITY.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| >=1.4.11 | :white_check_mark: |
|
||||
| <1.4.11 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please [open an issue](https://github.com/DGP-Studio/Snap.Hutao/issues/new/choose)
|
||||
@@ -8,7 +8,28 @@
|
||||
# 6. Run
|
||||
|
||||
trigger:
|
||||
- main
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
paths:
|
||||
exclude:
|
||||
- README.md
|
||||
- azure-pipelines.yml
|
||||
- .github/ISSUE_TEMPLATE/*.yml
|
||||
- .github/workflows/*.yml
|
||||
- src/Snap.Hutao/Snap.Hutao/Resource/Localization/*.resx
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
paths:
|
||||
exclude:
|
||||
- README.md
|
||||
- azure-pipelines.yml
|
||||
- .github/ISSUE_TEMPLATE/*.yml
|
||||
- .github/workflows/*.yml
|
||||
- src/Snap.Hutao/Snap.Hutao/Resource/Localization/*.resx
|
||||
|
||||
|
||||
pool:
|
||||
vmImage: 'windows-2022'
|
||||
@@ -19,7 +40,7 @@ variables:
|
||||
project: $(Build.SourcesDirectory)/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj'
|
||||
buildPlatform: 'x64'
|
||||
buildConfiguration: 'Release'
|
||||
build_date: $[ format('{0:yyyy}.{0:MM}.{0:dd}', pipeline.startTime) ]
|
||||
build_date: $[ format('{0:yyyy}.{0:M}.{0:d}', pipeline.startTime) ]
|
||||
|
||||
|
||||
steps:
|
||||
@@ -44,7 +65,8 @@ steps:
|
||||
inputs:
|
||||
command: 'restore'
|
||||
restoreSolution: '$(solution)'
|
||||
feedsToUse: 'select'
|
||||
feedsToUse: 'config'
|
||||
nugetConfigPath: '$(Build.SourcesDirectory)/NuGet.Config'
|
||||
|
||||
- task: MsixPackaging@1
|
||||
displayName: Build binary package
|
||||
@@ -62,7 +84,7 @@ steps:
|
||||
|
||||
- task: MagicChunks@2
|
||||
inputs:
|
||||
sourcePath: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.18362.0\win10-x64\AppxManifest.xml'
|
||||
sourcePath: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.19041.0\win10-x64\AppxManifest.xml'
|
||||
fileType: 'Xml'
|
||||
targetPathType: 'source'
|
||||
transformationType: 'json'
|
||||
@@ -72,7 +94,8 @@ steps:
|
||||
"Package/Identity/@Publisher": "CN=DGP Studio CI",
|
||||
"Package/Identity/@Version": "$(build_date).$(rev_number)",
|
||||
"Package/Properties/DisplayName": "胡桃 Alpha",
|
||||
"Package/Properties/PublisherDisplayName":"DGP Studio CI"
|
||||
"Package/Properties/PublisherDisplayName":"DGP Studio CI",
|
||||
"Package/Applications/Application/uap:VisualElements/@DisplayName": "胡桃 Alpha"
|
||||
}
|
||||
|
||||
- task: CmdLine@2
|
||||
@@ -82,7 +105,7 @@ steps:
|
||||
mkdir Assets
|
||||
|
||||
mkdir Resource
|
||||
workingDirectory: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.18362.0\win10-x64'
|
||||
workingDirectory: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.19041.0\win10-x64'
|
||||
|
||||
|
||||
- task: CopyFiles@2
|
||||
@@ -90,33 +113,36 @@ steps:
|
||||
inputs:
|
||||
SourceFolder: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\Assets'
|
||||
Contents: '**'
|
||||
TargetFolder: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.18362.0\win10-x64\Assets'
|
||||
TargetFolder: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.19041.0\win10-x64\Assets'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy Resource Folder
|
||||
inputs:
|
||||
SourceFolder: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\Resource'
|
||||
Contents: '**'
|
||||
TargetFolder: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.18362.0\win10-x64\Resource'
|
||||
TargetFolder: '$(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.19041.0\win10-x64\Resource'
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: Build MSIX
|
||||
inputs:
|
||||
script: '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\makeappx.exe" pack /d $(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.18362.0\win10-x64 /p $(Build.ArtifactStagingDirectory)/Snap.Hutao.Alpha-$(build_date).$(rev_number).msix'
|
||||
script: '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\makeappx.exe" pack /d $(Build.SourcesDirectory)\src\Snap.Hutao\Snap.Hutao\bin\x64\Release\net7.0-windows10.0.19041.0\win10-x64 /p $(Build.ArtifactStagingDirectory)/Snap.Hutao.Alpha-$(build_date).$(rev_number).msix'
|
||||
|
||||
- task: MsixSigning@1
|
||||
name: signMsix
|
||||
displayName: Sign MSIX package
|
||||
inputs:
|
||||
package: '$(Build.ArtifactStagingDirectory)/Snap.Hutao.Alpha-$(build_date).$(rev_number).msix'
|
||||
certificate: 'DGP_Studio_CI.pfx'
|
||||
passwordVariable: 'pw'
|
||||
condition: succeeded()
|
||||
|
||||
- task: PublishPipelineArtifact@1
|
||||
displayName: 'Upload Output'
|
||||
inputs:
|
||||
targetPath: '$(Build.ArtifactStagingDirectory)/'
|
||||
artifact: 'Output'
|
||||
publishLocation: 'pipeline'
|
||||
|
||||
#- task: PublishPipelineArtifact@1
|
||||
# displayName: 'Upload Output'
|
||||
# inputs:
|
||||
# targetPath: '$(Build.ArtifactStagingDirectory)/'
|
||||
# artifact: 'Output'
|
||||
# publishLocation: 'pipeline'
|
||||
|
||||
- task: DownloadSecureFile@1
|
||||
name: cerFile
|
||||
@@ -135,13 +161,28 @@ steps:
|
||||
title: '$(build_date).$(rev_number)'
|
||||
releaseNotesSource: 'inline'
|
||||
releaseNotesInline: |
|
||||
## 提示 (Hint)
|
||||
该发布版本由 CI 程序自动打包生成,属于 `Alpha` 测试版,仅用于开发调试和内部测试用途。使用该版本可能存在意料之外的风险,请仅在有明确用途的情况下使用该版本。
|
||||
|
||||
This release is a Alpha Testing version generated by CI program automatically in a purpose of debugging and interal testing. Using this release may have unexpected risk, please only use it when you know what you are doing.
|
||||
## 普通用户请勿下载
|
||||
该版本是由 CI 程序自动打包生成的 `Alpha` 测试版本,**仅供开发者测试使用**
|
||||
|
||||
普通用户请[点击这里](https://github.com/DGP-Studio/Snap.Hutao/releases/latest/)下载最新的稳定版本
|
||||
|
||||
assets: |
|
||||
$(Build.ArtifactStagingDirectory)/*
|
||||
$(cerFile.secureFilePath)
|
||||
isPreRelease: true
|
||||
changeLogCompareToRelease: 'lastFullRelease'
|
||||
changeLogType: 'commitBased'
|
||||
changeLogType: 'commitBased'
|
||||
|
||||
- task: DownloadSecureFile@1
|
||||
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
|
||||
name: RcloneConfigFile
|
||||
displayName: Download Rclone Config
|
||||
inputs:
|
||||
secureFile: 'rclone.conf'
|
||||
|
||||
- task: rclone@1
|
||||
displayName: Upload CI via Rclone
|
||||
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
|
||||
inputs:
|
||||
arguments: 'copy $(Build.ArtifactStagingDirectory)/Snap.Hutao.Alpha-$(build_date).$(rev_number).msix downloadDGPCN:/releases/Alpha/'
|
||||
configPath: '$(RcloneConfigFile.secureFilePath)'
|
||||
|
||||
3
crowdin.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
files:
|
||||
- source: /src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
|
||||
translation: /src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.%osx_locale%.resx
|
||||
BIN
res/HutaoIcon2.jpg
Normal file
|
After Width: | Height: | Size: 785 KiB |
BIN
res/HutaoIcon2.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
res/HutaoIconSource.jpg
Normal file
|
After Width: | Height: | Size: 733 KiB |
BIN
res/HutaoIconSourceTransparentBackground.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
res/HutaoRepoBanner.png
Normal file
|
After Width: | Height: | Size: 699 KiB |
BIN
res/HutaoRepoBanner.psd
Normal file
3
res/LEGAL NOTICE.md
Normal file
@@ -0,0 +1,3 @@
|
||||
本文件夹中的所有图片,均由 [DGP Studio](https://github.com/DGP-Studio) 委托 [Bilibili 画画的芦苇](https://space.bilibili.com/274422134) 绘制
|
||||
|
||||
Copyright ©2023 DGP Studio, All Rights Reserved.
|
||||
@@ -10,13 +10,13 @@ csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = false:silent
|
||||
csharp_style_expression_bodied_indexers = false:silent
|
||||
csharp_style_expression_bodied_accessors = when_on_single_line:silent
|
||||
csharp_style_expression_bodied_accessors = when_on_single_line:suggestion
|
||||
csharp_style_expression_bodied_lambdas = when_on_single_line:silent
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
csharp_style_var_when_type_is_apparent = false:silent
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
csharp_style_var_for_built_in_types = false:warning
|
||||
csharp_style_var_when_type_is_apparent = false:warning
|
||||
csharp_style_var_elsewhere = false:warning
|
||||
csharp_prefer_simple_using_statement = false:suggestion
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_namespace_declarations = file_scoped:silent
|
||||
@@ -24,11 +24,11 @@ csharp_prefer_static_local_function = false:suggestion
|
||||
|
||||
[*.{cs,vb}]
|
||||
end_of_line = crlf
|
||||
dotnet_style_qualification_for_field = false:silent
|
||||
dotnet_style_qualification_for_property = false:silent
|
||||
dotnet_style_qualification_for_method = false:silent
|
||||
dotnet_style_qualification_for_event = false:silent
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
dotnet_style_qualification_for_field = false:suggestion
|
||||
dotnet_style_qualification_for_property = false:suggestion
|
||||
dotnet_style_qualification_for_method = false:suggestion
|
||||
dotnet_style_qualification_for_event = false:suggestion
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
|
||||
dotnet_code_quality_unused_parameters = non_public:suggestion
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
indent_size = 4
|
||||
@@ -165,6 +165,7 @@ dotnet_diagnostic.CA1805.severity = suggestion
|
||||
dotnet_diagnostic.VSTHRD111.severity = suggestion
|
||||
csharp_style_prefer_top_level_statements = true:silent
|
||||
csharp_style_prefer_readonly_struct = true:suggestion
|
||||
csharp_style_prefer_utf8_string_literals = true:suggestion
|
||||
|
||||
[*.vb]
|
||||
#### 命名样式 ####
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace SettingsUI.Controls;
|
||||
|
||||
public class CheckBoxWithDescriptionControl : CheckBox
|
||||
{
|
||||
private readonly CheckBoxWithDescriptionControl _checkBoxSubTextControl;
|
||||
|
||||
public CheckBoxWithDescriptionControl()
|
||||
{
|
||||
_checkBoxSubTextControl = this;
|
||||
Loaded += CheckBoxSubTextControl_Loaded;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
Update();
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Header))
|
||||
{
|
||||
AutomationProperties.SetName(this, Header);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckBoxSubTextControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
StackPanel panel = new() { Orientation = Orientation.Vertical };
|
||||
|
||||
// Add text box only if the description is not empty. Required for additional plugin options.
|
||||
if (!string.IsNullOrWhiteSpace(Description))
|
||||
{
|
||||
panel.Children.Add(new TextBlock() { Margin = new Thickness(0, 10, 0, 0), Text = Header });
|
||||
//Style = (Style)Application.Current.Resources["SecondaryIsEnabledTextBlockStyle"]
|
||||
panel.Children.Add(new IsEnabledTextBlock() { Text = Description });
|
||||
}
|
||||
else
|
||||
{
|
||||
panel.Children.Add(new TextBlock() { Margin = new Thickness(0, 0, 0, 0), Text = Header });
|
||||
}
|
||||
|
||||
_checkBoxSubTextControl.Content = panel;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
"Header",
|
||||
typeof(string),
|
||||
typeof(CheckBoxWithDescriptionControl),
|
||||
new PropertyMetadata(default(string)));
|
||||
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
"Description",
|
||||
typeof(object),
|
||||
typeof(CheckBoxWithDescriptionControl),
|
||||
new PropertyMetadata(default(string)));
|
||||
|
||||
[Localizable(true)]
|
||||
public string Header
|
||||
{
|
||||
get => (string)GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
|
||||
[Localizable(true)]
|
||||
public string Description
|
||||
{
|
||||
get => (string)GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace SettingsUI.Controls;
|
||||
|
||||
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
|
||||
public class IsEnabledTextBlock : Control
|
||||
{
|
||||
public IsEnabledTextBlock()
|
||||
{
|
||||
DefaultStyleKey = typeof(IsEnabledTextBlock);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
IsEnabledChanged -= IsEnabledTextBlock_IsEnabledChanged;
|
||||
SetEnabledState();
|
||||
IsEnabledChanged += IsEnabledTextBlock_IsEnabledChanged;
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
|
||||
"Text",
|
||||
typeof(string),
|
||||
typeof(IsEnabledTextBlock),
|
||||
null);
|
||||
|
||||
[Localizable(true)]
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
private void IsEnabledTextBlock_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
SetEnabledState();
|
||||
}
|
||||
|
||||
private void SetEnabledState()
|
||||
{
|
||||
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:SettingsUI.Controls">
|
||||
|
||||
<Style TargetType="local:IsEnabledTextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:IsEnabledTextBlock">
|
||||
<Grid>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Label.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<TextBlock x:Name="Label"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Text="{TemplateBinding Text}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style TargetType="local:IsEnabledTextBlock" x:Key="SecondaryIsEnabledTextBlockStyle">
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<Setter Property="FontSize" Value="{StaticResource SecondaryTextFontSize}"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,156 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace SettingsUI.Controls;
|
||||
|
||||
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
|
||||
[TemplatePart(Name = PartIconPresenter, Type = typeof(ContentPresenter))]
|
||||
[TemplatePart(Name = PartDescriptionPresenter, Type = typeof(ContentPresenter))]
|
||||
public class Setting : ContentControl
|
||||
{
|
||||
private const string PartIconPresenter = "IconPresenter";
|
||||
private const string PartDescriptionPresenter = "DescriptionPresenter";
|
||||
private ContentPresenter? _iconPresenter;
|
||||
private ContentPresenter? _descriptionPresenter;
|
||||
private Setting? _setting;
|
||||
|
||||
public Setting()
|
||||
{
|
||||
DefaultStyleKey = typeof(Setting);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
"Header",
|
||||
typeof(string),
|
||||
typeof(Setting),
|
||||
new PropertyMetadata(default(string), OnHeaderChanged));
|
||||
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
"Description",
|
||||
typeof(object),
|
||||
typeof(Setting),
|
||||
new PropertyMetadata(null, OnDescriptionChanged));
|
||||
|
||||
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
|
||||
"Icon",
|
||||
typeof(object),
|
||||
typeof(Setting),
|
||||
new PropertyMetadata(default(string), OnIconChanged));
|
||||
|
||||
public static readonly DependencyProperty ActionContentProperty = DependencyProperty.Register(
|
||||
"ActionContent",
|
||||
typeof(object),
|
||||
typeof(Setting),
|
||||
null);
|
||||
|
||||
[Localizable(true)]
|
||||
public string Header
|
||||
{
|
||||
get => (string)GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
|
||||
[Localizable(true)]
|
||||
public object Description
|
||||
{
|
||||
get => GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
public object Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
|
||||
public object ActionContent
|
||||
{
|
||||
get => GetValue(ActionContentProperty);
|
||||
set => SetValue(ActionContentProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
IsEnabledChanged -= Setting_IsEnabledChanged;
|
||||
_setting = this;
|
||||
_iconPresenter = (ContentPresenter)_setting.GetTemplateChild(PartIconPresenter);
|
||||
_descriptionPresenter = (ContentPresenter)_setting.GetTemplateChild(PartDescriptionPresenter);
|
||||
Update();
|
||||
SetEnabledState();
|
||||
IsEnabledChanged += Setting_IsEnabledChanged;
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((Setting)d).Update();
|
||||
}
|
||||
|
||||
private static void OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((Setting)d).Update();
|
||||
}
|
||||
|
||||
private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((Setting)d).Update();
|
||||
}
|
||||
|
||||
private void Setting_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
SetEnabledState();
|
||||
}
|
||||
|
||||
private void SetEnabledState()
|
||||
{
|
||||
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_setting == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_setting.ActionContent != null)
|
||||
{
|
||||
if (_setting.ActionContent.GetType() != typeof(Button))
|
||||
{
|
||||
// We do not want to override the default AutomationProperties.Name of a button. Its Content property already describes what it does.
|
||||
if (!string.IsNullOrEmpty(_setting.Header))
|
||||
{
|
||||
AutomationProperties.SetName((UIElement)_setting.ActionContent, _setting.Header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_setting._iconPresenter != null)
|
||||
{
|
||||
if (_setting.Icon == null)
|
||||
{
|
||||
_setting._iconPresenter.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_setting._iconPresenter.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
if (_setting.Description == null)
|
||||
{
|
||||
_setting._descriptionPresenter!.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_setting._descriptionPresenter!.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:SettingsUI.Controls">
|
||||
|
||||
<Style TargetType="controls:Setting">
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource CardBorderThickness}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Padding" Value="16" />
|
||||
<Setter Property="Margin" Value="0,0,0,0"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:Setting">
|
||||
<Grid x:Name="RootGrid"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
MinHeight="48">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="HeaderPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
<Setter Target="DescriptionPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
<Setter Target="IconPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- Icon -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- Header and subtitle -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- Action control -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentPresenter x:Name="IconPresenter"
|
||||
Content="{TemplateBinding Icon}"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="20"
|
||||
IsTextScaleFactorEnabled="False"
|
||||
Margin="2,0,18,0"
|
||||
MaxWidth="20"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
Foreground="{ThemeResource CardPrimaryForegroundBrush}"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="0,0,16,0">
|
||||
|
||||
<TextBlock
|
||||
x:Name="HeaderPresenter"
|
||||
Text="{TemplateBinding Header}"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource CardPrimaryForegroundBrush}" />
|
||||
|
||||
<ContentPresenter
|
||||
x:Name="DescriptionPresenter"
|
||||
Content="{TemplateBinding Description}"
|
||||
FontSize="{StaticResource SecondaryTextFontSize}"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}">
|
||||
<ContentPresenter.Resources>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource CaptionTextBlockStyle}">
|
||||
<Style.Setters>
|
||||
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
<Style TargetType="HyperlinkButton" BasedOn="{StaticResource TextButtonStyle}">
|
||||
<Style.Setters>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Padding" Value="0,0,0,0"/>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</ContentPresenter.Resources>
|
||||
</ContentPresenter>
|
||||
</StackPanel>
|
||||
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
Content="{TemplateBinding ActionContent}"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace SettingsUI.Controls;
|
||||
|
||||
public partial class SettingExpander : Expander
|
||||
{
|
||||
public SettingExpander()
|
||||
{
|
||||
DefaultStyleKey = typeof(Expander);
|
||||
Style = (Style)Application.Current.Resources["SettingExpanderStyle"];
|
||||
RegisterPropertyChangedCallback(Expander.HeaderProperty, OnHeaderChanged);
|
||||
}
|
||||
|
||||
private static void OnHeaderChanged(DependencyObject d, DependencyProperty dp)
|
||||
{
|
||||
SettingExpander self = (SettingExpander)d;
|
||||
if (self.Header != null)
|
||||
{
|
||||
if (self.Header.GetType() == typeof(Setting))
|
||||
{
|
||||
Setting selfSetting = (Setting)self.Header;
|
||||
selfSetting.Style = (Style)Application.Current.Resources["ExpanderHeaderSettingStyle"];
|
||||
|
||||
if (!string.IsNullOrEmpty(selfSetting.Header))
|
||||
{
|
||||
AutomationProperties.SetName(self, selfSetting.Header);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace SettingsUI.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a control that can contain multiple settings (or other) controls
|
||||
/// </summary>
|
||||
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
|
||||
[TemplatePart(Name = PartDescriptionPresenter, Type = typeof(ContentPresenter))]
|
||||
public partial class SettingsGroup : ItemsControl
|
||||
{
|
||||
private const string PartDescriptionPresenter = "DescriptionPresenter";
|
||||
private ContentPresenter? _descriptionPresenter;
|
||||
private SettingsGroup? _settingsGroup;
|
||||
|
||||
public SettingsGroup()
|
||||
{
|
||||
DefaultStyleKey = typeof(SettingsGroup);
|
||||
}
|
||||
|
||||
[Localizable(true)]
|
||||
public string Header
|
||||
{
|
||||
get => (string)GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
"Header",
|
||||
typeof(string),
|
||||
typeof(SettingsGroup),
|
||||
new PropertyMetadata(default(string)));
|
||||
|
||||
[Localizable(true)]
|
||||
public object Description
|
||||
{
|
||||
get => GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
"Description",
|
||||
typeof(object),
|
||||
typeof(SettingsGroup),
|
||||
new PropertyMetadata(null, OnDescriptionChanged));
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
IsEnabledChanged -= SettingsGroup_IsEnabledChanged;
|
||||
_settingsGroup = this;
|
||||
_descriptionPresenter = (ContentPresenter)_settingsGroup.GetTemplateChild(PartDescriptionPresenter);
|
||||
SetEnabledState();
|
||||
IsEnabledChanged += SettingsGroup_IsEnabledChanged;
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((SettingsGroup)d).Update();
|
||||
}
|
||||
|
||||
private void SettingsGroup_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
SetEnabledState();
|
||||
}
|
||||
|
||||
private void SetEnabledState()
|
||||
{
|
||||
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_settingsGroup == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_settingsGroup.Description == null)
|
||||
{
|
||||
_settingsGroup._descriptionPresenter!.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_settingsGroup._descriptionPresenter!.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new SettingsGroupAutomationPeer(this);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:SettingsUI.Controls">
|
||||
|
||||
<Style TargetType="controls:SettingsGroup">
|
||||
<Setter Property="ItemsPanel">
|
||||
<Setter.Value>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Spacing="2"/>
|
||||
</ItemsPanelTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:SettingsGroup">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="HeaderPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
<Setter Target="DescriptionPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="HeaderPresenter"
|
||||
Text="{TemplateBinding Header}"
|
||||
Grid.Row="0"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Margin="1,32,0,0"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
|
||||
<ContentPresenter
|
||||
x:Name="DescriptionPresenter"
|
||||
Content="{TemplateBinding Description}"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Margin="1,4,0,0"
|
||||
Grid.Row="1"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}">
|
||||
<ContentPresenter.Resources>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource CaptionTextBlockStyle}">
|
||||
<Style.Setters>
|
||||
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
<Style TargetType="HyperlinkButton" BasedOn="{StaticResource TextButtonStyle}">
|
||||
<Style.Setters>
|
||||
<Setter Property="Padding" Value="0,0,0,0"/>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</ContentPresenter.Resources>
|
||||
</ContentPresenter>
|
||||
<ItemsPresenter Grid.Row="2" Margin="0,8,0,0"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
|
||||
namespace SettingsUI.Controls;
|
||||
|
||||
public class SettingsGroupAutomationPeer : FrameworkElementAutomationPeer
|
||||
{
|
||||
public SettingsGroupAutomationPeer(SettingsGroup owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
protected override string GetNameCore()
|
||||
{
|
||||
SettingsGroup? selectedSettingsGroup = (SettingsGroup)Owner;
|
||||
return selectedSettingsGroup.Header;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0-windows10.0.18362.0</TargetFrameworks>
|
||||
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>SettingsUI</RootNamespace>
|
||||
<Platforms>x64</Platforms>
|
||||
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.221116.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\IsEnabledTextBlock\IsEnabledTextBlock.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\SettingsGroup\SettingsGroup.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\Setting\Setting.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Styles\Button.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Styles\Common.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Styles\TextBlock.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Themes\Colors.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Themes\Generic.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Themes\SettingsExpanderStyles.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Themes\SettingsUI.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,700 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)">
|
||||
|
||||
<Style
|
||||
x:Key="SettingButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="16,5,16,6"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="HyperlinkButtonStyle" TargetType="HyperlinkButton">
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TextButtonStyle" TargetType="ButtonBase">
|
||||
<Setter Property="Background" Value="{ThemeResource HyperlinkButtonBackground}"/>
|
||||
<Setter Property="Foreground" Value="{ThemeResource HyperlinkButtonForeground}"/>
|
||||
<Setter Property="MinWidth" Value="0"/>
|
||||
<Setter Property="MinHeight" Value="0"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ButtonBase">
|
||||
<Grid
|
||||
Margin="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="4">
|
||||
<ContentPresenter
|
||||
x:Name="Text"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontWeight="SemiBold"/>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- This style overrides the default style so that all ToggleSwitches are right aligned, with the label on the left -->
|
||||
<Style x:Key="ToggleSwitchSettingStyle" TargetType="ToggleSwitch">
|
||||
<Setter Property="Foreground" Value="{ThemeResource ToggleSwitchContentForeground}"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Right"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Right"/>
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
|
||||
<Setter Property="ManipulationMode" Value="System,TranslateX"/>
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}"/>
|
||||
|
||||
<Setter Property="FocusVisualMargin" Value="-7,-3,-7,-3"/>
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ToggleSwitch">
|
||||
<Grid
|
||||
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ContentPresenter
|
||||
x:Name="HeaderContentPresenter"
|
||||
Grid.Row="0"
|
||||
Margin="{ThemeResource ToggleSwitchTopHeaderMargin}"
|
||||
VerticalAlignment="Top"
|
||||
x:DeferLoadStrategy="Lazy"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
Foreground="{ThemeResource ToggleSwitchHeaderForeground}"
|
||||
IsHitTestVisible="False"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="Collapsed"/>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top">
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="{ThemeResource ToggleSwitchPreContentMargin}"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="{ThemeResource ToggleSwitchPostContentMargin}"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="12" MaxWidth="12"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid
|
||||
x:Name="SwitchAreaGrid"
|
||||
Grid.RowSpan="3"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="0,5"
|
||||
contract7NotPresent:CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Background="{ThemeResource ToggleSwitchContainerBackground}"
|
||||
Control.IsTemplateFocusTarget="True"/>
|
||||
<ContentPresenter
|
||||
x:Name="OffContentPresenter"
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding OffContent}"
|
||||
ContentTemplate="{TemplateBinding OffContentTemplate}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsHitTestVisible="False"
|
||||
Opacity="0"/>
|
||||
<ContentPresenter
|
||||
x:Name="OnContentPresenter"
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding OnContent}"
|
||||
ContentTemplate="{TemplateBinding OnContentTemplate}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsHitTestVisible="False"
|
||||
Opacity="0"/>
|
||||
<Rectangle
|
||||
x:Name="OuterBorder"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="40"
|
||||
Height="20"
|
||||
Fill="{ThemeResource ToggleSwitchFillOff}"
|
||||
RadiusX="10"
|
||||
RadiusY="10"
|
||||
Stroke="{ThemeResource ToggleSwitchStrokeOff}"
|
||||
StrokeThickness="{ThemeResource ToggleSwitchOuterBorderStrokeThickness}"/>
|
||||
<Rectangle
|
||||
x:Name="SwitchKnobBounds"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="40"
|
||||
Height="20"
|
||||
Fill="{ThemeResource ToggleSwitchFillOn}"
|
||||
Opacity="0"
|
||||
RadiusX="10"
|
||||
RadiusY="10"
|
||||
Stroke="{ThemeResource ToggleSwitchStrokeOn}"
|
||||
StrokeThickness="{ThemeResource ToggleSwitchOnStrokeThickness}"/>
|
||||
<Grid
|
||||
x:Name="SwitchKnob"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="20"
|
||||
Height="20"
|
||||
HorizontalAlignment="Left">
|
||||
<Border
|
||||
x:Name="SwitchKnobOn"
|
||||
Grid.Column="2"
|
||||
Width="12"
|
||||
Height="12"
|
||||
Margin="0,0,1,0"
|
||||
HorizontalAlignment="Center"
|
||||
contract7Present:BackgroundSizing="OuterBorderEdge"
|
||||
Background="{ThemeResource ToggleSwitchKnobFillOn}"
|
||||
BorderBrush="{ThemeResource ToggleSwitchKnobStrokeOn}"
|
||||
CornerRadius="7"
|
||||
Opacity="0"
|
||||
RenderTransformOrigin="0.5, 0.5">
|
||||
<Border.RenderTransform>
|
||||
<CompositeTransform/>
|
||||
</Border.RenderTransform>
|
||||
</Border>
|
||||
<Rectangle
|
||||
x:Name="SwitchKnobOff"
|
||||
Grid.Column="2"
|
||||
Width="12"
|
||||
Height="12"
|
||||
Margin="-1,0,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="{ThemeResource ToggleSwitchKnobFillOff}"
|
||||
RadiusX="7"
|
||||
RadiusY="7"
|
||||
RenderTransformOrigin="0.5, 0.5">
|
||||
<Rectangle.RenderTransform>
|
||||
<CompositeTransform/>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
<Grid.RenderTransform>
|
||||
<TranslateTransform x:Name="KnobTranslateTransform"/>
|
||||
</Grid.RenderTransform>
|
||||
</Grid>
|
||||
<Thumb
|
||||
x:Name="SwitchThumb"
|
||||
Grid.RowSpan="3"
|
||||
Grid.ColumnSpan="3"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
<Thumb.Template>
|
||||
<ControlTemplate TargetType="Thumb">
|
||||
<Rectangle Fill="Transparent"/>
|
||||
</ControlTemplate>
|
||||
</Thumb.Template>
|
||||
</Thumb>
|
||||
|
||||
</Grid>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="Stroke">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOff}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOff}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOff}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOn}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOn}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Stroke">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOn}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchContainerBackground}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchStrokeOffPointerOver}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchFillOffPointerOver}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOffPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOnPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOnPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Stroke">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOnPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchContainerBackgroundPointerOver}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="14"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="14"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="14"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="14"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
|
||||
<VisualState.Setters>
|
||||
<Setter Target="SwitchKnobOn.HorizontalAlignment" Value="Right"/>
|
||||
<Setter Target="SwitchKnobOn.Margin" Value="0,0,3,0"/>
|
||||
<Setter Target="SwitchKnobOff.HorizontalAlignment" Value="Left"/>
|
||||
<Setter Target="SwitchKnobOff.Margin" Value="3,0,0,0"/>
|
||||
</VisualState.Setters>
|
||||
|
||||
<Storyboard>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchStrokeOffPressed}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchFillOffPressed}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOnPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Stroke">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOnPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOffPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOnPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchContainerBackgroundPressed}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="17"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="14"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="17"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFasterAnimationDuration}"
|
||||
Value="14"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchHeaderForegroundDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OffContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchContentForegroundDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OnContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchContentForegroundDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchStrokeOffDisabled}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchFillOffDisabled}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchFillOnDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Stroke">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchStrokeOnDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOffDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleSwitchKnobFillOnDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
|
||||
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="{ThemeResource ToggleSwitchContainerBackgroundDisabled}"/>
|
||||
</ColorAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlNormalAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOn"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlNormalAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Width">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlNormalAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames
|
||||
EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="SwitchKnobOff"
|
||||
Storyboard.TargetProperty="Height">
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlNormalAnimationDuration}"
|
||||
Value="12"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="ToggleStates">
|
||||
|
||||
<VisualStateGroup.Transitions>
|
||||
<VisualTransition
|
||||
x:Name="DraggingToOnTransition"
|
||||
GeneratedDuration="0"
|
||||
From="Dragging"
|
||||
To="On">
|
||||
|
||||
<Storyboard>
|
||||
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOnOffset}" TargetName="SwitchKnob"/>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
<VisualTransition
|
||||
x:Name="OnToDraggingTransition"
|
||||
GeneratedDuration="0"
|
||||
From="On"
|
||||
To="Dragging">
|
||||
<Storyboard>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="0" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="0" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="0" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
<VisualTransition
|
||||
x:Name="DraggingToOffTransition"
|
||||
GeneratedDuration="0"
|
||||
From="Dragging"
|
||||
To="Off">
|
||||
|
||||
<Storyboard>
|
||||
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOffOffset}" TargetName="SwitchKnob"/>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
<VisualTransition
|
||||
x:Name="OnToOffTransition"
|
||||
GeneratedDuration="0"
|
||||
From="On"
|
||||
To="Off">
|
||||
|
||||
<Storyboard>
|
||||
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOnToOffOffset}" TargetName="SwitchKnob"/>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
<VisualTransition
|
||||
x:Name="OffToOnTransition"
|
||||
GeneratedDuration="0"
|
||||
From="Off"
|
||||
To="On">
|
||||
|
||||
<Storyboard>
|
||||
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOffToOnOffset}" TargetName="SwitchKnob"/>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
</VisualStateGroup.Transitions>
|
||||
<VisualState x:Name="Dragging"/>
|
||||
<VisualState x:Name="Off"/>
|
||||
<VisualState x:Name="On">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="KnobTranslateTransform"
|
||||
Storyboard.TargetProperty="X"
|
||||
To="20"
|
||||
Duration="0"/>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Opacity">
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="ContentStates">
|
||||
<VisualState x:Name="OffContent">
|
||||
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="OffContentPresenter"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="1"
|
||||
Duration="0"/>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OffContentPresenter" Storyboard.TargetProperty="IsHitTestVisible">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<x:Boolean>True</x:Boolean>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="OnContent">
|
||||
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="OnContentPresenter"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="1"
|
||||
Duration="0"/>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OnContentPresenter" Storyboard.TargetProperty="IsHitTestVisible">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<x:Boolean>True</x:Boolean>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,13 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:SettingsUI.Controls">
|
||||
<Style x:Key="ListViewItemSettingStyle" TargetType="ListViewItem">
|
||||
<Setter Property="Margin" Value="0,0,0,2"/>
|
||||
<Setter Property="Padding" Value="0,0,0,0"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultCheckBoxStyle}" TargetType="controls:CheckBoxWithDescriptionControl"/>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,20 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Style x:Key="OobeSubtitleStyle" TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="0,16,0,0"/>
|
||||
<Setter Property="Foreground" Value="{ThemeResource DefaultTextForegroundThemeBrush}"/>
|
||||
<Setter Property="AutomationProperties.HeadingLevel" Value="Level3"/>
|
||||
<Setter Property="FontFamily" Value="XamlAutoFontFamily"/>
|
||||
<Setter Property="FontSize" Value="{StaticResource BodyTextBlockFontSize}"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
<Setter Property="LineStackingStrategy" Value="MaxHeight"/>
|
||||
<Setter Property="TextLineBounds" Value="Full"/>
|
||||
</Style>
|
||||
|
||||
<x:Double x:Key="SecondaryTextFontSize">12</x:Double>
|
||||
<Style x:Key="SecondaryTextStyle" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="{StaticResource SecondaryTextFontSize}"/>
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,30 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<StaticResource x:Key="CardBackgroundBrush" ResourceKey="CardBackgroundFillColorDefaultBrush"/>
|
||||
<StaticResource x:Key="CardBorderBrush" ResourceKey="CardStrokeColorDefaultBrush"/>
|
||||
<StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="TextFillColorPrimaryBrush"/>
|
||||
<SolidColorBrush x:Key="InfoBarInformationalSeverityBackgroundBrush" Color="#FF34424d"/>
|
||||
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF5fb2f2</Color>
|
||||
<Thickness x:Key="CardBorderThickness">1</Thickness>
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="CardBackgroundBrush" ResourceKey="CardBackgroundFillColorDefaultBrush"/>
|
||||
<StaticResource x:Key="CardBorderBrush" ResourceKey="CardStrokeColorDefaultBrush"/>
|
||||
<StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="TextFillColorPrimaryBrush"/>
|
||||
<SolidColorBrush x:Key="InfoBarInformationalSeverityBackgroundBrush" Color="#FFd3e7f7"/>
|
||||
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF0063b1</Color>
|
||||
<Thickness x:Key="CardBorderThickness">1</Thickness>
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="CardBackgroundBrush" ResourceKey="SystemColorButtonFaceColorBrush"/>
|
||||
<StaticResource x:Key="CardBorderBrush" ResourceKey="SystemColorButtonTextColorBrush"/>
|
||||
<StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="SystemColorButtonTextColorBrush"/>
|
||||
<SolidColorBrush x:Key="InfoBarInformationalSeverityBackgroundBrush" Color="#FF34424d"/>
|
||||
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF5fb2f2</Color>
|
||||
<Thickness x:Key="CardBorderThickness">2</Thickness>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,9 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ms-appx:///SettingsUI/Controls/Setting/Setting.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///SettingsUI/Controls/SettingsGroup/SettingsGroup.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///SettingsUI/Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -1,48 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:SettingsUI.Controls">
|
||||
|
||||
<!-- Thickness -->
|
||||
<Thickness x:Key="ExpanderContentPadding">0</Thickness>
|
||||
<Thickness x:Key="ExpanderSettingMargin">56, 8, 40, 8</Thickness>
|
||||
|
||||
<SolidColorBrush x:Key="ExpanderChevronPointerOverBackground">Transparent</SolidColorBrush>
|
||||
|
||||
<!-- Styles -->
|
||||
<!-- Setting used in a Expander header -->
|
||||
<Style x:Key="ExpanderHeaderSettingStyle" TargetType="controls:Setting">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="BorderBrush" Value="Transparent"/>
|
||||
<Setter Property="Padding" Value="0,14,0,14"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
|
||||
<Thickness x:Key="ExpanderChevronMargin">0,0,8,0</Thickness>
|
||||
|
||||
<!-- Setting used in a Expander header -->
|
||||
<Style x:Key="ExpanderContentSettingStyle" TargetType="controls:Setting">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderThickness" Value="0,1,0,0"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="Padding" Value="{StaticResource ExpanderSettingMargin}"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
|
||||
<!-- Setting expander style -->
|
||||
<Style x:Key="SettingExpanderStyle" TargetType="Expander">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource CardBorderThickness}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ExpanderSeparatorStyle" TargetType="Rectangle">
|
||||
<Setter Property="Height" Value="1"/>
|
||||
<Setter Property="Stroke" Value="{ThemeResource CardBorderBrush}"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,12 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Styles/Common.xaml"/>
|
||||
<ResourceDictionary Source="../Styles/TextBlock.xaml"/>
|
||||
<ResourceDictionary Source="../Styles/Button.xaml"/>
|
||||
<ResourceDictionary Source="../Themes/Colors.xaml"/>
|
||||
<ResourceDictionary Source="../Themes/SettingsExpanderStyles.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<x:Double x:Key="SettingActionControlMinWidth">240</x:Double>
|
||||
</ResourceDictionary>
|
||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.Installer;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
private const string AppxKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Appx";
|
||||
private const string AppxKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock";
|
||||
private const string ValueName = "AllowDevelopmentWithoutDevLicense";
|
||||
|
||||
public static async Task Main(string[] args)
|
||||
|
||||
@@ -11,7 +11,7 @@ using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.SourceGeneration.DedendencyInjection;
|
||||
namespace Snap.Hutao.SourceGeneration.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
/// 注入HttpClient代码生成器
|
||||
@@ -19,11 +19,12 @@ namespace Snap.Hutao.SourceGeneration.DedendencyInjection;
|
||||
/// 防止在运行时动态查找注入类型
|
||||
/// </summary>
|
||||
[Generator]
|
||||
public class HttpClientGenerator : ISourceGenerator
|
||||
internal sealed class HttpClientGenerator : ISourceGenerator
|
||||
{
|
||||
private const string DefaultName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.Default";
|
||||
private const string XRpcName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.XRpc";
|
||||
private const string XRpc2Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.XRpc2";
|
||||
private const string DefaultName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.Default";
|
||||
private const string XRpcName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.XRpc";
|
||||
private const string XRpc2Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.XRpc2";
|
||||
private const string XRpc3Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.XRpc3";
|
||||
|
||||
private const string PrimaryHttpMessageHandlerAttributeName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.PrimaryHttpMessageHandlerAttribute";
|
||||
private const string DynamicSecretAttributeName = "Snap.Hutao.Web.Hoyolab.DynamicSecret.UseDynamicSecretAttribute";
|
||||
@@ -44,38 +45,38 @@ public class HttpClientGenerator : ISourceGenerator
|
||||
return;
|
||||
}
|
||||
|
||||
string toolName = this.GetGeneratorType().FullName;
|
||||
|
||||
StringBuilder sourceCodeBuilder = new();
|
||||
|
||||
sourceCodeBuilder.Append($@"// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
sourceCodeBuilder.Append($$"""
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
// This class is generated by Snap.Hutao.SourceGeneration
|
||||
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Snap.Hutao.Core.DependencyInjection;
|
||||
|
||||
internal static partial class IocHttpClientConfiguration
|
||||
{
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{nameof(HttpClientGenerator)}}","1.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public static partial IServiceCollection AddHttpClients(this IServiceCollection services)
|
||||
{
|
||||
""");
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
using System.Net.Http;
|
||||
FillWithHttpClients(receiver, sourceCodeBuilder);
|
||||
|
||||
namespace Snap.Hutao.Core.DependencyInjection;
|
||||
sourceCodeBuilder.Append("""
|
||||
|
||||
internal static partial class IocHttpClientConfiguration
|
||||
{{
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""{toolName}"",""1.0.0.0"")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public static partial IServiceCollection AddHttpClients(this IServiceCollection services)
|
||||
{{");
|
||||
|
||||
FillWithInjectionServices(receiver, sourceCodeBuilder);
|
||||
sourceCodeBuilder.Append(@"
|
||||
return services;
|
||||
}
|
||||
}");
|
||||
return services;
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
context.AddSource("IocHttpClientConfiguration.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8));
|
||||
}
|
||||
|
||||
private static void FillWithInjectionServices(HttpClientSyntaxContextReceiver receiver, StringBuilder sourceCodeBuilder)
|
||||
private static void FillWithHttpClients(HttpClientSyntaxContextReceiver receiver, StringBuilder sourceCodeBuilder)
|
||||
{
|
||||
List<string> lines = new();
|
||||
StringBuilder lineBuilder = new();
|
||||
@@ -84,29 +85,39 @@ internal static partial class IocHttpClientConfiguration
|
||||
{
|
||||
lineBuilder.Clear().Append("\r\n");
|
||||
lineBuilder.Append(@" services.AddHttpClient<");
|
||||
lineBuilder.Append($"{classSymbol.ToDisplayString()}>(");
|
||||
|
||||
AttributeData httpClientInfo = classSymbol
|
||||
.GetAttributes()
|
||||
.Single(attr => attr.AttributeClass!.ToDisplayString() == HttpClientSyntaxContextReceiver.AttributeName);
|
||||
ImmutableArray<TypedConstant> arguments = httpClientInfo.ConstructorArguments;
|
||||
|
||||
TypedConstant injectAs = arguments[0];
|
||||
if (arguments.Length == 2)
|
||||
{
|
||||
TypedConstant interfaceType = arguments[1];
|
||||
lineBuilder.Append($"{interfaceType.Value}, ");
|
||||
}
|
||||
|
||||
string injectAsName = injectAs.ToCSharpString();
|
||||
TypedConstant configuration = arguments[0];
|
||||
|
||||
lineBuilder.Append($"{classSymbol.ToDisplayString()}>(");
|
||||
|
||||
string injectAsName = configuration.ToCSharpString();
|
||||
switch (injectAsName)
|
||||
{
|
||||
case DefaultName:
|
||||
lineBuilder.Append(@"DefaultConfiguration)");
|
||||
lineBuilder.Append("DefaultConfiguration)");
|
||||
break;
|
||||
case XRpcName:
|
||||
lineBuilder.Append(@"XRpcConfiguration)");
|
||||
lineBuilder.Append("XRpcConfiguration)");
|
||||
break;
|
||||
case XRpc2Name:
|
||||
lineBuilder.Append(@"XRpc2Configuration)");
|
||||
lineBuilder.Append("XRpc2Configuration)");
|
||||
break;
|
||||
case XRpc3Name:
|
||||
lineBuilder.Append("XRpc3Configuration)");
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"非法的HttpClientConfigration值: [{injectAsName}]");
|
||||
throw new InvalidOperationException($"非法的 HttpClientConfiguration 值: [{injectAsName}]");
|
||||
}
|
||||
|
||||
AttributeData? handlerInfo = classSymbol
|
||||
@@ -120,11 +131,11 @@ internal static partial class IocHttpClientConfiguration
|
||||
|
||||
foreach (KeyValuePair<string, TypedConstant> property in properties)
|
||||
{
|
||||
lineBuilder.Append(" ");
|
||||
lineBuilder.Append(' ');
|
||||
lineBuilder.Append(property.Key);
|
||||
lineBuilder.Append(" = ");
|
||||
lineBuilder.Append(property.Value.ToCSharpString());
|
||||
lineBuilder.Append(",");
|
||||
lineBuilder.Append(',');
|
||||
}
|
||||
|
||||
lineBuilder.Append(" })");
|
||||
@@ -135,7 +146,7 @@ internal static partial class IocHttpClientConfiguration
|
||||
lineBuilder.Append(".AddHttpMessageHandler<DynamicSecretHandler>()");
|
||||
}
|
||||
|
||||
lineBuilder.Append(";");
|
||||
lineBuilder.Append(';');
|
||||
|
||||
lines.Add(lineBuilder.ToString());
|
||||
}
|
||||
@@ -11,7 +11,7 @@ using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.SourceGeneration.DedendencyInjection;
|
||||
namespace Snap.Hutao.SourceGeneration.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
/// 注入代码生成器
|
||||
@@ -19,11 +19,12 @@ namespace Snap.Hutao.SourceGeneration.DedendencyInjection;
|
||||
/// 防止在运行时动态查找注入类型
|
||||
/// </summary>
|
||||
[Generator]
|
||||
public class InjectionGenerator : ISourceGenerator
|
||||
internal sealed class InjectionGenerator : ISourceGenerator
|
||||
{
|
||||
private const string InjectAsSingletonName = "Snap.Hutao.Core.DependencyInjection.Annotation.InjectAs.Singleton";
|
||||
private const string InjectAsTransientName = "Snap.Hutao.Core.DependencyInjection.Annotation.InjectAs.Transient";
|
||||
private const string InjectAsScopedName = "Snap.Hutao.Core.DependencyInjection.Annotation.InjectAs.Scoped";
|
||||
private const string CRLF = "\r\n";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
@@ -41,30 +42,28 @@ public class InjectionGenerator : ISourceGenerator
|
||||
return;
|
||||
}
|
||||
|
||||
string toolName = this.GetGeneratorType().FullName;
|
||||
|
||||
StringBuilder sourceCodeBuilder = new();
|
||||
sourceCodeBuilder.Append($@"// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
sourceCodeBuilder.Append($$"""
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
// This class is generated by Snap.Hutao.SourceGeneration
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Snap.Hutao.Core.DependencyInjection;
|
||||
|
||||
internal static partial class ServiceCollectionExtension
|
||||
{{
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""{toolName}"",""1.0.0.0"")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public static partial IServiceCollection AddInjections(this IServiceCollection services)
|
||||
{{");
|
||||
namespace Snap.Hutao.Core.DependencyInjection;
|
||||
|
||||
internal static partial class ServiceCollectionExtension
|
||||
{
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{nameof(InjectionGenerator)}}","1.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
public static partial IServiceCollection AddInjections(this IServiceCollection services)
|
||||
{
|
||||
""");
|
||||
|
||||
FillWithInjectionServices(receiver, sourceCodeBuilder);
|
||||
sourceCodeBuilder.Append(@"
|
||||
return services;
|
||||
}
|
||||
}");
|
||||
sourceCodeBuilder.Append("""
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
context.AddSource("ServiceCollectionExtension.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8));
|
||||
}
|
||||
@@ -76,46 +75,42 @@ internal static partial class ServiceCollectionExtension
|
||||
|
||||
foreach (INamedTypeSymbol classSymbol in receiver.Classes)
|
||||
{
|
||||
IEnumerable<AttributeData> datas = classSymbol
|
||||
AttributeData injectionInfo = classSymbol
|
||||
.GetAttributes()
|
||||
.Where(attr => attr.AttributeClass!.ToDisplayString() == InjectionSyntaxContextReceiver.AttributeName);
|
||||
.Single(attr => attr.AttributeClass!.ToDisplayString() == InjectionSyntaxContextReceiver.AttributeName);
|
||||
|
||||
foreach (AttributeData injectionInfo in datas)
|
||||
lineBuilder
|
||||
.Clear()
|
||||
.Append(CRLF);
|
||||
|
||||
ImmutableArray<TypedConstant> arguments = injectionInfo.ConstructorArguments;
|
||||
TypedConstant injectAs = arguments[0];
|
||||
|
||||
string injectAsName = injectAs.ToCSharpString();
|
||||
switch (injectAsName)
|
||||
{
|
||||
lineBuilder
|
||||
.Clear()
|
||||
.Append("\r\n");
|
||||
|
||||
ImmutableArray<TypedConstant> arguments = injectionInfo.ConstructorArguments;
|
||||
|
||||
TypedConstant injectAs = arguments[0];
|
||||
|
||||
string injectAsName = injectAs.ToCSharpString();
|
||||
switch (injectAsName)
|
||||
{
|
||||
case InjectAsSingletonName:
|
||||
lineBuilder.Append(@" services.AddSingleton(");
|
||||
break;
|
||||
case InjectAsTransientName:
|
||||
lineBuilder.Append(@" services.AddTransient(");
|
||||
break;
|
||||
case InjectAsScopedName:
|
||||
lineBuilder.Append(@" services.AddScoped(");
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"非法的 InjectAs 值: [{injectAsName}]");
|
||||
}
|
||||
|
||||
if (arguments.Length == 2)
|
||||
{
|
||||
TypedConstant interfaceType = arguments[1];
|
||||
lineBuilder.Append($"{interfaceType.ToCSharpString()}, ");
|
||||
}
|
||||
|
||||
lineBuilder.Append($"typeof({classSymbol.ToDisplayString()}));");
|
||||
|
||||
lines.Add(lineBuilder.ToString());
|
||||
case InjectAsSingletonName:
|
||||
lineBuilder.Append(@" services.AddSingleton<");
|
||||
break;
|
||||
case InjectAsTransientName:
|
||||
lineBuilder.Append(@" services.AddTransient<");
|
||||
break;
|
||||
case InjectAsScopedName:
|
||||
lineBuilder.Append(@" services.AddScoped<");
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"非法的 InjectAs 值: [{injectAsName}]");
|
||||
}
|
||||
|
||||
if (arguments.Length == 2)
|
||||
{
|
||||
TypedConstant interfaceType = arguments[1];
|
||||
lineBuilder.Append($"{interfaceType.Value}, ");
|
||||
}
|
||||
|
||||
lineBuilder.Append($"{classSymbol.ToDisplayString()}>();");
|
||||
|
||||
lines.Add(lineBuilder.ToString());
|
||||
}
|
||||
|
||||
foreach (string line in lines.OrderBy(x => x))
|
||||
@@ -153,4 +148,4 @@ internal static partial class ServiceCollectionExtension
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[assembly: SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:启用分析器发布跟踪", Justification = "<挂起>", Scope = "member", Target = "~F:Snap.Hutao.SourceGeneration.TodoAnalyzer.Descriptor")]
|
||||
[assembly: SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:启用分析器发布跟踪", Justification = "<挂起>", Scope = "member", Target = "~F:Snap.Hutao.SourceGeneration.TypeInternalAnalyzer.typeInternalDescriptor")]
|
||||
|
||||
439
src/Snap.Hutao/Snap.Hutao.SourceGeneration/JsonParser.cs
Normal file
@@ -0,0 +1,439 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.SourceGeneration;
|
||||
|
||||
// Really simple JSON parser in ~300 lines
|
||||
// - Attempts to parse JSON files with minimal GC allocation
|
||||
// - Nice and simple "[1,2,3]".FromJson<List<int>>() API
|
||||
// - Classes and structs can be parsed too!
|
||||
// class Foo { public int Value; }
|
||||
// "{\"Value\":10}".FromJson<Foo>()
|
||||
// - Can parse JSON without type information into Dictionary<string,object> and List<object> e.g.
|
||||
// "[1,2,3]".FromJson<object>().GetType() == typeof(List<object>)
|
||||
// "{\"Value\":10}".FromJson<object>().GetType() == typeof(Dictionary<string,object>)
|
||||
// - No JIT Emit support to support AOT compilation on iOS
|
||||
// - Attempts are made to NOT throw an exception if the JSON is corrupted or invalid: returns null instead.
|
||||
// - Only public fields and property setters on classes/structs will be written to
|
||||
//
|
||||
// Limitations:
|
||||
// - No JIT Emit support to parse structures quickly
|
||||
// - Limited to parsing <2GB JSON files (due to int.MaxValue)
|
||||
// - Parsing of abstract classes or interfaces is NOT supported and will throw an exception.
|
||||
public static class JsonParser
|
||||
{
|
||||
[ThreadStatic]
|
||||
private static Stack<List<string>>? splitArrayPool;
|
||||
|
||||
[ThreadStatic]
|
||||
private static StringBuilder? stringBuilder;
|
||||
|
||||
[ThreadStatic]
|
||||
private static Dictionary<Type, Dictionary<string, FieldInfo>>? fieldInfoCache;
|
||||
|
||||
[ThreadStatic]
|
||||
private static Dictionary<Type, Dictionary<string, PropertyInfo>>? propertyInfoCache;
|
||||
|
||||
public static T? FromJson<T>(this string json)
|
||||
{
|
||||
// Initialize, if needed, the ThreadStatic variables
|
||||
propertyInfoCache ??= new Dictionary<Type, Dictionary<string, PropertyInfo>>();
|
||||
fieldInfoCache ??= new Dictionary<Type, Dictionary<string, FieldInfo>>();
|
||||
stringBuilder ??= new StringBuilder();
|
||||
splitArrayPool ??= new Stack<List<string>>();
|
||||
|
||||
//Remove all whitespace not within strings to make parsing simpler
|
||||
stringBuilder.Length = 0;
|
||||
for (int i = 0; i < json.Length; i++)
|
||||
{
|
||||
char c = json[i];
|
||||
if (c == '"')
|
||||
{
|
||||
i = AppendUntilStringEnd(true, i, json);
|
||||
continue;
|
||||
}
|
||||
if (char.IsWhiteSpace(c))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
stringBuilder.Append(c);
|
||||
}
|
||||
|
||||
//Parse the thing!
|
||||
return (T?)ParseValue(typeof(T), stringBuilder.ToString());
|
||||
}
|
||||
|
||||
private static int AppendUntilStringEnd(bool appendEscapeCharacter, int startIdx, string json)
|
||||
{
|
||||
stringBuilder!.Append(json[startIdx]);
|
||||
for (int i = startIdx + 1; i < json.Length; i++)
|
||||
{
|
||||
if (json[i] == '\\')
|
||||
{
|
||||
if (appendEscapeCharacter)
|
||||
{
|
||||
stringBuilder.Append(json[i]);
|
||||
}
|
||||
|
||||
stringBuilder.Append(json[i + 1]);
|
||||
i++;//Skip next character as it is escaped
|
||||
}
|
||||
else if (json[i] == '"')
|
||||
{
|
||||
stringBuilder.Append(json[i]);
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.Append(json[i]);
|
||||
}
|
||||
}
|
||||
return json.Length - 1;
|
||||
}
|
||||
|
||||
//Splits { <value>:<value>, <value>:<value> } and [ <value>, <value> ] into a list of <value> strings
|
||||
private static List<string> Split(string json)
|
||||
{
|
||||
List<string> splitArray = splitArrayPool!.Count > 0 ? splitArrayPool.Pop() : new List<string>();
|
||||
splitArray.Clear();
|
||||
if (json.Length == 2)
|
||||
{
|
||||
return splitArray;
|
||||
}
|
||||
|
||||
int parseDepth = 0;
|
||||
stringBuilder!.Length = 0;
|
||||
for (int i = 1; i < json.Length - 1; i++)
|
||||
{
|
||||
switch (json[i])
|
||||
{
|
||||
case '[':
|
||||
case '{':
|
||||
parseDepth++;
|
||||
break;
|
||||
case ']':
|
||||
case '}':
|
||||
parseDepth--;
|
||||
break;
|
||||
case '"':
|
||||
i = AppendUntilStringEnd(true, i, json);
|
||||
continue;
|
||||
case ',':
|
||||
case ':':
|
||||
if (parseDepth == 0)
|
||||
{
|
||||
splitArray.Add(stringBuilder.ToString());
|
||||
stringBuilder.Length = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
stringBuilder.Append(json[i]);
|
||||
}
|
||||
|
||||
splitArray.Add(stringBuilder.ToString());
|
||||
|
||||
return splitArray;
|
||||
}
|
||||
|
||||
internal static object? ParseValue(Type type, string json)
|
||||
{
|
||||
if (type == typeof(string))
|
||||
{
|
||||
if (json.Length <= 2)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
StringBuilder parseStringBuilder = new(json.Length);
|
||||
for (int i = 1; i < json.Length - 1; ++i)
|
||||
{
|
||||
if (json[i] == '\\' && i + 1 < json.Length - 1)
|
||||
{
|
||||
int j = "\"\\nrtbf/".IndexOf(json[i + 1]);
|
||||
if (j >= 0)
|
||||
{
|
||||
parseStringBuilder.Append("\"\\\n\r\t\b\f/"[j]);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (json[i + 1] == 'u' && i + 5 < json.Length - 1)
|
||||
{
|
||||
if (uint.TryParse(json.Substring(i + 2, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out uint c))
|
||||
{
|
||||
parseStringBuilder.Append((char)c);
|
||||
i += 5;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
parseStringBuilder.Append(json[i]);
|
||||
}
|
||||
return parseStringBuilder.ToString();
|
||||
}
|
||||
if (type.IsPrimitive)
|
||||
{
|
||||
object result = Convert.ChangeType(json, type, System.Globalization.CultureInfo.InvariantCulture);
|
||||
return result;
|
||||
}
|
||||
if (type == typeof(decimal))
|
||||
{
|
||||
decimal.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out decimal result);
|
||||
return result;
|
||||
}
|
||||
if (type == typeof(DateTime))
|
||||
{
|
||||
DateTime.TryParse(json.Replace("\"", ""), System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime result);
|
||||
return result;
|
||||
}
|
||||
if (json == "null")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (type.IsEnum)
|
||||
{
|
||||
if (json[0] == '"')
|
||||
{
|
||||
json = json.Substring(1, json.Length - 2);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Enum.Parse(type, json, false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (type.IsArray)
|
||||
{
|
||||
Type arrayType = type.GetElementType();
|
||||
if (json[0] != '[' || json[json.Length - 1] != ']')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<string> elems = Split(json);
|
||||
Array newArray = Array.CreateInstance(arrayType, elems.Count);
|
||||
for (int i = 0; i < elems.Count; i++)
|
||||
{
|
||||
newArray.SetValue(ParseValue(arrayType, elems[i]), i);
|
||||
}
|
||||
|
||||
splitArrayPool!.Push(elems);
|
||||
return newArray;
|
||||
}
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
|
||||
{
|
||||
Type listType = type.GetGenericArguments()[0];
|
||||
if (json[0] != '[' || json[json.Length - 1] != ']')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<string> elems = Split(json);
|
||||
IList list = (IList)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count });
|
||||
for (int i = 0; i < elems.Count; i++)
|
||||
{
|
||||
list.Add(ParseValue(listType, elems[i]));
|
||||
}
|
||||
|
||||
splitArrayPool!.Push(elems);
|
||||
return list;
|
||||
}
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
||||
{
|
||||
Type keyType, valueType;
|
||||
{
|
||||
Type[] args = type.GetGenericArguments();
|
||||
keyType = args[0];
|
||||
valueType = args[1];
|
||||
}
|
||||
|
||||
//Refuse to parse dictionary keys that aren't of type string
|
||||
if (keyType != typeof(string))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//Must be a valid dictionary element
|
||||
if (json[0] != '{' || json[json.Length - 1] != '}')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
|
||||
List<string> elems = Split(json);
|
||||
if (elems.Count % 2 != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IDictionary dictionary = (IDictionary)type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { elems.Count / 2 });
|
||||
for (int i = 0; i < elems.Count; i += 2)
|
||||
{
|
||||
if (elems[i].Length <= 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string keyValue = elems[i].Substring(1, elems[i].Length - 2);
|
||||
object? val = ParseValue(valueType, elems[i + 1]);
|
||||
dictionary[keyValue] = val;
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
if (type == typeof(object))
|
||||
{
|
||||
return ParseAnonymousValue(json);
|
||||
}
|
||||
if (json[0] == '{' && json[json.Length - 1] == '}')
|
||||
{
|
||||
return ParseObject(type, json);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object? ParseAnonymousValue(string json)
|
||||
{
|
||||
if (json.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (json[0] == '{' && json[json.Length - 1] == '}')
|
||||
{
|
||||
List<string> elems = Split(json);
|
||||
if (elems.Count % 2 != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<string, object?> dict = new Dictionary<string, object?>(elems.Count / 2);
|
||||
for (int i = 0; i < elems.Count; i += 2)
|
||||
{
|
||||
dict[elems[i].Substring(1, elems[i].Length - 2)] = ParseAnonymousValue(elems[i + 1]);
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
if (json[0] == '[' && json[json.Length - 1] == ']')
|
||||
{
|
||||
List<string> items = Split(json);
|
||||
List<object?> finalList = new(items.Count);
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
finalList.Add(ParseAnonymousValue(items[i]));
|
||||
}
|
||||
|
||||
return finalList;
|
||||
}
|
||||
if (json[0] == '"' && json[json.Length - 1] == '"')
|
||||
{
|
||||
string str = json.Substring(1, json.Length - 2);
|
||||
return str.Replace("\\", string.Empty);
|
||||
}
|
||||
if (char.IsDigit(json[0]) || json[0] == '-')
|
||||
{
|
||||
if (json.Contains("."))
|
||||
{
|
||||
double.TryParse(json, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
int.TryParse(json, out int result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (json == "true")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (json == "false")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// handles json == "null" as well as invalid JSON
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Dictionary<string, T> CreateMemberNameDictionary<T>(T[] members) where T : MemberInfo
|
||||
{
|
||||
Dictionary<string, T> nameToMember = new(StringComparer.OrdinalIgnoreCase);
|
||||
for (int i = 0; i < members.Length; i++)
|
||||
{
|
||||
T member = members[i];
|
||||
if (member.IsDefined(typeof(IgnoreDataMemberAttribute), true))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = member.Name;
|
||||
if (member.IsDefined(typeof(DataMemberAttribute), true))
|
||||
{
|
||||
DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)Attribute.GetCustomAttribute(member, typeof(DataMemberAttribute), true);
|
||||
if (!string.IsNullOrEmpty(dataMemberAttribute.Name))
|
||||
{
|
||||
name = dataMemberAttribute.Name;
|
||||
}
|
||||
}
|
||||
|
||||
nameToMember.Add(name, member);
|
||||
}
|
||||
|
||||
return nameToMember;
|
||||
}
|
||||
|
||||
private static object ParseObject(Type type, string json)
|
||||
{
|
||||
object instance = FormatterServices.GetUninitializedObject(type);
|
||||
|
||||
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
|
||||
List<string> elems = Split(json);
|
||||
if (elems.Count % 2 != 0)
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
if (!fieldInfoCache!.TryGetValue(type, out Dictionary<string, FieldInfo> nameToField))
|
||||
{
|
||||
nameToField = CreateMemberNameDictionary(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
|
||||
fieldInfoCache.Add(type, nameToField);
|
||||
}
|
||||
if (!propertyInfoCache!.TryGetValue(type, out Dictionary<string, PropertyInfo> nameToProperty))
|
||||
{
|
||||
nameToProperty = CreateMemberNameDictionary(type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy));
|
||||
propertyInfoCache.Add(type, nameToProperty);
|
||||
}
|
||||
|
||||
for (int i = 0; i < elems.Count; i += 2)
|
||||
{
|
||||
if (elems[i].Length <= 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string key = elems[i].Substring(1, elems[i].Length - 2);
|
||||
string value = elems[i + 1];
|
||||
|
||||
if (nameToField.TryGetValue(key, out FieldInfo fieldInfo))
|
||||
{
|
||||
fieldInfo.SetValue(instance, ParseValue(fieldInfo.FieldType, value));
|
||||
}
|
||||
else if (nameToProperty.TryGetValue(key, out PropertyInfo propertyInfo))
|
||||
{
|
||||
propertyInfo.SetValue(instance, ParseValue(propertyInfo.PropertyType, value), null);
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.SourceGeneration;
|
||||
|
||||
[Generator]
|
||||
internal sealed class ReliquaryWeightConfigurationGenerator : ISourceGenerator
|
||||
{
|
||||
private const string ReliquaryWeightConfigurationFileName = "ReliquaryWeightConfiguration.json";
|
||||
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
AdditionalText configurationJsonFile = context.AdditionalFiles
|
||||
.First(af => Path.GetFileName(af.Path) == ReliquaryWeightConfigurationFileName);
|
||||
|
||||
string configurationJson = configurationJsonFile.GetText(context.CancellationToken)!.ToString();
|
||||
Dictionary<string, ReliquaryWeightConfigurationMetadata> metadataMap =
|
||||
JsonParser.FromJson<Dictionary<string, ReliquaryWeightConfigurationMetadata>>(configurationJson)!;
|
||||
|
||||
StringBuilder sourceCodeBuilder = new();
|
||||
sourceCodeBuilder.Append($$"""
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.AvatarInfo.Factory;
|
||||
|
||||
/// <summary>
|
||||
/// 圣遗物评分权重配置
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{nameof(ReliquaryWeightConfigurationGenerator)}}","1.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
internal static class ReliquaryWeightConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认
|
||||
/// </summary>
|
||||
public static readonly AffixWeight Default = new(0, 100, 75, 0, 100, 100, 0, 55, 0);
|
||||
|
||||
/// <summary>
|
||||
/// 词条权重
|
||||
/// </summary>
|
||||
public static readonly List<AffixWeight> AffixWeights = new()
|
||||
{
|
||||
|
||||
""");
|
||||
|
||||
foreach (KeyValuePair<string, ReliquaryWeightConfigurationMetadata> kvp in metadataMap.OrderBy(kvp => kvp.Key))
|
||||
{
|
||||
AppendAffixWeight(sourceCodeBuilder, kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
sourceCodeBuilder.Append($$"""
|
||||
};
|
||||
}
|
||||
""");
|
||||
|
||||
context.AddSource("ReliquaryWeightConfiguration.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8));
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.AddSource("ReliquaryWeightConfiguration.g.cs", ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendAffixWeight(StringBuilder builder, string id, ReliquaryWeightConfigurationMetadata metadata)
|
||||
{
|
||||
StringBuilder lineBuilder = new StringBuilder()
|
||||
.Append(" new AffixWeight(").Append(id).Append(',')
|
||||
.Append(' ').Append(metadata.Hp).Append(',')
|
||||
.Append(' ').Append(metadata.Attack).Append(',')
|
||||
.Append(' ').Append(metadata.Defense).Append(',')
|
||||
.Append(' ').Append(metadata.CritRate).Append(',')
|
||||
.Append(' ').Append(metadata.CritHurt).Append(',')
|
||||
.Append(' ').Append(metadata.Mastery).Append(',')
|
||||
.Append(' ').Append(metadata.Recharge).Append(',')
|
||||
.Append(' ').Append(metadata.Healing).Append(')')
|
||||
.Append('.').Append(metadata.ElementType).Append("(").Append(metadata.ElementHurt).Append(')');
|
||||
|
||||
if (metadata.PhysicialHurt != 0)
|
||||
{
|
||||
lineBuilder.Append(".Physical(").Append(metadata.PhysicialHurt).Append(')');
|
||||
}
|
||||
|
||||
lineBuilder.Append(',');
|
||||
|
||||
|
||||
builder.AppendLine(lineBuilder.ToString());
|
||||
}
|
||||
|
||||
private sealed class ReliquaryWeightConfigurationMetadata
|
||||
{
|
||||
[DataMember(Name = "hp")]
|
||||
public int Hp { get; set; }
|
||||
|
||||
[DataMember(Name = "atk")]
|
||||
public int Attack { get; set; }
|
||||
|
||||
[DataMember(Name = "def")]
|
||||
public int Defense { get; set; }
|
||||
|
||||
[DataMember(Name = "cpct")]
|
||||
public int CritRate { get; set; }
|
||||
|
||||
[DataMember(Name = "cdmg")]
|
||||
public int CritHurt { get; set; }
|
||||
|
||||
[DataMember(Name = "mastery")]
|
||||
public int Mastery { get; set; }
|
||||
|
||||
[DataMember(Name = "recharge")]
|
||||
public int Recharge { get; set; }
|
||||
|
||||
[DataMember(Name = "heal")]
|
||||
public int Healing { get; set; }
|
||||
|
||||
[DataMember(Name = "element")]
|
||||
public string ElementType { get; set; } = default!;
|
||||
|
||||
[DataMember(Name = "dmg")]
|
||||
public int ElementHurt { get; set; }
|
||||
|
||||
[DataMember(Name = "phy")]
|
||||
public int PhysicialHurt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>x64</Platforms>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="stylecop.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="stylecop.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" Version="3.3.4" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -18,11 +18,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4-beta1.22518.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" Version="3.3.4" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Snap.Hutao.SourceGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// 高亮TODO
|
||||
/// </summary>
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
internal class TodoAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private static readonly DiagnosticDescriptor Descriptor =
|
||||
new("SH0001", "TODO 项尚未实现", "此 TODO 项需要实现", "Standard", DiagnosticSeverity.Info, true);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get => ImmutableArray.Create(Descriptor); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
|
||||
context.RegisterSyntaxTreeAction(HandleSyntaxTree);
|
||||
}
|
||||
|
||||
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
|
||||
{
|
||||
SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);
|
||||
foreach (SyntaxTrivia node in root.DescendantTrivia(descendIntoTrivia: true))
|
||||
{
|
||||
switch (node.Kind())
|
||||
{
|
||||
case SyntaxKind.SingleLineCommentTrivia:
|
||||
case SyntaxKind.MultiLineCommentTrivia:
|
||||
string text = node.ToString().ToLowerInvariant();
|
||||
if (text.Contains("todo:"))
|
||||
{
|
||||
string hint = node.ToString().Substring(text.IndexOf("todo:") + 6);
|
||||
DiagnosticDescriptor descriptor = new("SH0001", "TODO 项尚未实现", hint, "Standard", DiagnosticSeverity.Info, true);
|
||||
context.ReportDiagnostic(Diagnostic.Create(descriptor, node.GetLocation()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Snap.Hutao.SourceGeneration;
|
||||
|
||||
/// <summary>
|
||||
/// 类型应为内部分析器
|
||||
/// </summary>
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
internal sealed class TypeInternalAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private static readonly DiagnosticDescriptor typeInternalDescriptor = new("SH001", "Type should be internal", "Type should be internal", "Quality", DiagnosticSeverity.Info, true);
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(typeInternalDescriptor);
|
||||
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
||||
context.EnableConcurrentExecution();
|
||||
|
||||
context.RegisterCompilationStartAction(CompilationStart);
|
||||
}
|
||||
|
||||
private void CompilationStart(CompilationStartAnalysisContext context)
|
||||
{
|
||||
context.RegisterSyntaxNodeAction(HandleSyntax<ClassDeclarationSyntax>, SyntaxKind.ClassDeclaration);
|
||||
context.RegisterSyntaxNodeAction(HandleSyntax<InterfaceDeclarationSyntax>, SyntaxKind.InterfaceDeclaration);
|
||||
context.RegisterSyntaxNodeAction(HandleSyntax<StructDeclarationSyntax>, SyntaxKind.StructDeclaration);
|
||||
context.RegisterSyntaxNodeAction(HandleSyntax<EnumDeclarationSyntax>, SyntaxKind.EnumDeclaration);
|
||||
}
|
||||
|
||||
private void HandleSyntax<TSyntax>(SyntaxNodeAnalysisContext classSyntax)
|
||||
where TSyntax : BaseTypeDeclarationSyntax
|
||||
{
|
||||
TSyntax syntax = (TSyntax)classSyntax.Node;
|
||||
|
||||
bool privateExists = false;
|
||||
bool internalExists = false;
|
||||
foreach(SyntaxToken token in syntax.Modifiers)
|
||||
{
|
||||
if (token.IsKind(SyntaxKind.PrivateKeyword))
|
||||
{
|
||||
privateExists = true;
|
||||
}
|
||||
if (token.IsKind(SyntaxKind.InternalKeyword))
|
||||
{
|
||||
internalExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!privateExists && !internalExists)
|
||||
{
|
||||
Location location = syntax.Identifier.GetLocation();
|
||||
Diagnostic diagnostic = Diagnostic.Create(typeInternalDescriptor, location);
|
||||
classSyntax.ReportDiagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/Snap.Hutao/Snap.Hutao.Test/CSharpLanguageFeatureTest.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace Snap.Hutao.Test;
|
||||
|
||||
[TestClass]
|
||||
public class CSharpLanguageFeatureTest
|
||||
{
|
||||
[TestMethod]
|
||||
public unsafe void NullStringFixedAlsoNullPointer()
|
||||
{
|
||||
string testStr = null!;
|
||||
fixed(char* pStr = testStr)
|
||||
{
|
||||
Assert.IsTrue(pStr == null);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public unsafe void EmptyStringFixedIsNullTerminator()
|
||||
{
|
||||
string testStr = string.Empty;
|
||||
fixed (char* pStr = testStr)
|
||||
{
|
||||
Assert.IsTrue(*pStr == '\0');
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/Snap.Hutao/Snap.Hutao.Test/DependencyInjectionTest.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace Snap.Hutao.Test;
|
||||
|
||||
[TestClass]
|
||||
public class DependencyInjectionTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void OriginalTypeNotDiscoverable()
|
||||
{
|
||||
IServiceProvider services = new ServiceCollection()
|
||||
.AddSingleton<IService, ServiceA>()
|
||||
.AddSingleton<IService, ServiceB>()
|
||||
.BuildServiceProvider();
|
||||
|
||||
Assert.IsNull(services.GetService<ServiceA>());
|
||||
Assert.IsNull(services.GetService<ServiceB>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ScopedServiceInitializeMultipleTimesInScope()
|
||||
{
|
||||
IServiceProvider services = new ServiceCollection()
|
||||
.AddScoped<IService, ServiceA>()
|
||||
.BuildServiceProvider();
|
||||
|
||||
IServiceScopeFactory scopeFactory = services.GetRequiredService<IServiceScopeFactory>();
|
||||
using (IServiceScope scope = scopeFactory.CreateScope())
|
||||
{
|
||||
IService service1 = scope.ServiceProvider.GetRequiredService<IService>();
|
||||
IService service2 = scope.ServiceProvider.GetRequiredService<IService>();
|
||||
Assert.AreNotEqual(service1.Id, service2.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private interface IService
|
||||
{
|
||||
Guid Id { get; }
|
||||
}
|
||||
|
||||
private sealed class ServiceA : IService
|
||||
{
|
||||
public Guid Id
|
||||
{
|
||||
get => Guid.NewGuid();
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ServiceB : IService
|
||||
{
|
||||
public Guid Id
|
||||
{
|
||||
get => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/Snap.Hutao/Snap.Hutao.Test/GlobalUsings.cs
Normal file
@@ -0,0 +1 @@
|
||||
global using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
26
src/Snap.Hutao/Snap.Hutao.Test/JsonSerializeTest.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Snap.Hutao.Test;
|
||||
|
||||
[TestClass]
|
||||
public class JsonSerializeTest
|
||||
{
|
||||
private const string SmapleObjectJson = """
|
||||
{
|
||||
"A" :1
|
||||
}
|
||||
""";
|
||||
|
||||
[TestMethod]
|
||||
public void DelegatePropertyCanSerialize()
|
||||
{
|
||||
Sample sample = JsonSerializer.Deserialize<Sample>(SmapleObjectJson)!;
|
||||
Assert.AreEqual(sample.B, 1);
|
||||
}
|
||||
|
||||
private class Sample
|
||||
{
|
||||
public int A { get => B; set => B = value; }
|
||||
public int B { get; set; }
|
||||
}
|
||||
}
|
||||
23
src/Snap.Hutao/Snap.Hutao.Test/Snap.Hutao.Test.csproj
Normal file
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -10,11 +10,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SettingsUI", "SettingsUI\SettingsUI.csproj", "{DCA5678C-896E-49FB-97A7-5A504A5CFF17}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Snap.Hutao.SourceGeneration", "Snap.Hutao.SourceGeneration\Snap.Hutao.SourceGeneration.csproj", "{8B96721E-5604-47D2-9B72-06FEBAD0CE00}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Snap.Hutao.Installer", "Snap.Hutao.Installer\Snap.Hutao.Installer.csproj", "{CEC01691-F65E-4874-9AE2-F571369A7631}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Snap.Hutao.Test", "Snap.Hutao.Test\Snap.Hutao.Test.csproj", "{D691BA9F-904C-4229-87A5-E14F2EFF2F64}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -52,24 +50,8 @@ Global
|
||||
{AAAB7CF0-F299-49B8-BDB4-4C320B3EC2C7}.Release|x86.ActiveCfg = Release|x86
|
||||
{AAAB7CF0-F299-49B8-BDB4-4C320B3EC2C7}.Release|x86.Build.0 = Release|x86
|
||||
{AAAB7CF0-F299-49B8-BDB4-4C320B3EC2C7}.Release|x86.Deploy.0 = Release|x86
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|x64.Build.0 = Debug|x64
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|arm64.ActiveCfg = Release|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|arm64.Build.0 = Release|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x64.ActiveCfg = Release|x64
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x64.Build.0 = Release|x64
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -84,22 +66,22 @@ Global
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x64.Build.0 = Release|x64
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|x64.Build.0 = Debug|x64
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|arm64.ActiveCfg = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|arm64.Build.0 = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CEC01691-F65E-4874-9AE2-F571369A7631}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|arm64.ActiveCfg = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|arm64.Build.0 = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"pathSegment": {
|
||||
"add": {
|
||||
".*": [ ".cs" ]
|
||||
".*": [ ".cs", ".resx" ]
|
||||
}
|
||||
},
|
||||
"fileSuffixToExtension": {
|
||||
@@ -19,11 +19,12 @@
|
||||
},
|
||||
"fileToFile": {
|
||||
"add": {
|
||||
".filenesting.json": [ "App.xaml.cs" ],
|
||||
"app.manifest": [ "App.xaml.cs" ],
|
||||
"Package.appxmanifest": [ "App.xaml.cs" ],
|
||||
"GlobalUsing.cs": [ "Program.cs" ],
|
||||
".filenesting.json": [ "Program.cs" ],
|
||||
".editorconfig": [ "Program.cs" ]
|
||||
"Package.appxmanifest": [ "App.xaml" ],
|
||||
"Package.StoreAssociation.xml": [ "App.xaml" ],
|
||||
".editorconfig": [ "Program.cs" ],
|
||||
"GlobalUsing.cs": [ "Program.cs" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,28 +10,28 @@
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<muxc:XamlControlsResources/>
|
||||
<ResourceDictionary Source="ms-appx:///SettingsUI/Themes/SettingsUI.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/FontStyle.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="AvatarPropertyAddValueColor">#FF74BF00</Color>
|
||||
<Color x:Key="CompatBackgroundColor">#FFF4F4F4</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Color x:Key="AvatarPropertyAddValueColor">#FF90E800</Color>
|
||||
<Color x:Key="CompatBackgroundColor">#FF242424</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<!-- Modify Window title bar color -->
|
||||
<StaticResource x:Key="WindowCaptionBackground" ResourceKey="ControlFillColorTransparentBrush"/>
|
||||
<StaticResource x:Key="WindowCaptionBackgroundDisabled" ResourceKey="ControlFillColorTransparentBrush"/>
|
||||
<!-- Page Transparent Background -->
|
||||
<StaticResource x:Key="ApplicationPageBackgroundThemeBrush" ResourceKey="ControlFillColorTransparentBrush"/>
|
||||
<!-- IconFont -->
|
||||
<FontFamily x:Key="SymbolThemeFontFamily">ms-appx:///Resource/Font/Segoe Fluent Icons.ttf#Segoe Fluent Icons</FontFamily>
|
||||
<!-- InfoBar Resource -->
|
||||
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>
|
||||
<Thickness x:Key="InfoBarContentRootPadding">16,0,0,0</Thickness>
|
||||
<Thickness x:Key="InfoBarIconMargin">19,16,19,16</Thickness>
|
||||
<Thickness x:Key="InfoBarContentRootPadding">0,0,0,0</Thickness>
|
||||
<x:Double x:Key="InfoBarIconFontSize">20</x:Double>
|
||||
<!-- Pivot Resource -->
|
||||
<x:Double x:Key="PivotHeaderItemFontSize">16</x:Double>
|
||||
<Thickness x:Key="PivotHeaderItemMargin">16,0,0,0</Thickness>
|
||||
@@ -42,49 +42,421 @@
|
||||
<CornerRadius x:Key="CompatCornerRadiusRight">0,6,6,0</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusBottom">0,0,6,6</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusSmall">2</CornerRadius>
|
||||
<!-- OpenPaneLength -->
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double>
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength2">268</x:Double>
|
||||
<GridLength x:Key="CompatGridLength2">268</GridLength>
|
||||
<!-- Brushes -->
|
||||
<SolidColorBrush x:Key="AvatarPropertyAddValueBrush" Color="{ThemeResource AvatarPropertyAddValueColor}"/>
|
||||
<!-- Settings -->
|
||||
<x:Double x:Key="SettingsCardSpacing">3</x:Double>
|
||||
|
||||
<Style
|
||||
x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="1,29,0,5"/>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
<!-- Uris -->
|
||||
<x:String x:Key="DocumentLink_MhyAccountSwitch">https://hut.ao/features/mhy-account-switch.html</x:String>
|
||||
<x:String x:Key="DocumentLink_BugReport">https://hut.ao/statements/bug-report.html</x:String>
|
||||
<x:String x:Key="DocumentLink_Translate">https://translate.hut.ao</x:String>
|
||||
<x:String x:Key="DocumentLink_Home">https://hut.ao</x:String>
|
||||
<x:String x:Key="HolographicHat_GetToken_Release">https://github.com/HolographicHat/GetToken/releases/latest</x:String>
|
||||
<x:String x:Key="Sponsor_Afadian">https://afdian.net/a/DismissedLight</x:String>
|
||||
|
||||
<x:String x:Key="UI_ItemIcon_None">https://static.snapgenshin.com/Bg/UI_ItemIcon_None.png</x:String>
|
||||
<x:String x:Key="UI_ImgSign_ItemIcon">https://static.snapgenshin.com/Bg/UI_ImgSign_ItemIcon.png</x:String>
|
||||
<x:String x:Key="UI_AvatarIcon_Costume_Card">https://static.snapgenshin.com/AvatarCard/UI_AvatarIcon_Costume_Card.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon25">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon25.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon71">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon71.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon250">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon250.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon272">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon293">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon293.png</x:String>
|
||||
<!-- Converters -->
|
||||
<cwuc:BoolNegationConverter x:Key="BoolNegationConverter"/>
|
||||
<cwuc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
<cwuc:FileSizeToFriendlyStringConverter x:Key="FileSizeToFriendlyStringConverter"/>
|
||||
<shmmc:AchievementIconConverter x:Key="AchievementIconConverter"/>
|
||||
<shmmc:AvatarCardConverter x:Key="AvatarCardConverter"/>
|
||||
<shmmc:AvatarIconConverter x:Key="AvatarIconConverter"/>
|
||||
<shmmc:AvatarNameCardPicConverter x:Key="AvatarNameCardPicConverter"/>
|
||||
<shmmc:AvatarSideIconConverter x:Key="AvatarSideIconConverter"/>
|
||||
<shmmc:DescParamDescriptor x:Key="DescParamDescriptor"/>
|
||||
<shmmc:ParameterDescriptor x:Key="DescParamDescriptor"/>
|
||||
<shmmc:ElementNameIconConverter x:Key="ElementNameIconConverter"/>
|
||||
<shmmc:EmotionIconConverter x:Key="EmotionIconConverter"/>
|
||||
<shmmc:EquipIconConverter x:Key="EquipIconConverter"/>
|
||||
<shmmc:GachaAvatarImgConverter x:Key="GachaAvatarImgConverter"/>
|
||||
<shmmc:GachaAvatarIconConverter x:Key="GachaAvatarIconConverter"/>
|
||||
<shmmc:GachaEquipIconConverter x:Key="GachaEquipIconConverter"/>
|
||||
<shmmc:ItemIconConverter x:Key="ItemIconConverter"/>
|
||||
<shmmc:PropertyInfoDescriptor x:Key="PropertyDescriptor"/>
|
||||
<shmmc:MonsterIconConverter x:Key="MonsterIconConverter"/>
|
||||
<shmmc:PropertyDescriptor x:Key="PropertyDescriptor"/>
|
||||
<shmmc:QualityColorConverter x:Key="QualityColorConverter"/>
|
||||
<shmmc:WeaponTypeIconConverter x:Key="WeaponTypeIconConverter"/>
|
||||
<shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/>
|
||||
<shvc:EmptyObjectToBoolConverter x:Key="EmptyObjectToBoolConverter"/>
|
||||
<shvc:EmptyObjectToBoolRevertConverter x:Key="EmptyObjectToBoolRevertConverter"/>
|
||||
<shvc:EmptyObjectToVisibilityConverter x:Key="EmptyObjectToVisibilityConverter"/>
|
||||
|
||||
<shvc:EmptyObjectToVisibilityRevertConverter x:Key="EmptyObjectToVisibilityRevertConverter"/>
|
||||
<shvc:Int32ToVisibilityConverter x:Key="Int32ToVisibilityConverter"/>
|
||||
<shvc:Int32ToVisibilityRevertConverter x:Key="Int32ToVisibilityRevertConverter"/>
|
||||
<shvc:StringBoolConverter x:Key="StringBoolConverter"/>
|
||||
<!-- Styles -->
|
||||
|
||||
<Style
|
||||
x:Key="LargeGridViewItemStyle"
|
||||
BasedOn="{StaticResource DefaultGridViewItemStyle}"
|
||||
TargetType="GridViewItem">
|
||||
<Setter Property="Margin" Value="0,0,12,12"/>
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="SettingButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="16,6,16,6"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="BorderCardStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="{StaticResource CompatCornerRadius}"/>
|
||||
</Style>
|
||||
<Style x:Key="WebView2ContentDialogStyle" TargetType="ContentDialog">
|
||||
<Setter Property="Foreground" Value="{ThemeResource ContentDialogForeground}"/>
|
||||
<Setter Property="Background" Value="{ThemeResource ContentDialogBackground}"/>
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ContentDialogBorderWidth}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource ContentDialogBorderBrush}"/>
|
||||
<Setter Property="IsTabStop" Value="False"/>
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ContentDialog">
|
||||
<Border x:Name="Container">
|
||||
<Grid x:Name="LayoutRoot" Visibility="Collapsed">
|
||||
<Rectangle x:Name="SmokeLayerBackground" Fill="{ThemeResource ContentDialogSmokeFill}"/>
|
||||
<Border
|
||||
x:Name="BackgroundElement"
|
||||
MinWidth="{ThemeResource ContentDialogMinWidth}"
|
||||
MinHeight="{ThemeResource ContentDialogMinHeight}"
|
||||
MaxWidth="{ThemeResource ContentDialogMaxWidth}"
|
||||
MaxHeight="{ThemeResource ContentDialogMaxHeight}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="InnerBorderEdge"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
FlowDirection="{TemplateBinding FlowDirection}"
|
||||
RenderTransformOrigin="0.5,0.5">
|
||||
<Border.RenderTransform>
|
||||
<ScaleTransform x:Name="ScaleTransform"/>
|
||||
</Border.RenderTransform>
|
||||
<Grid x:Name="DialogSpace" CornerRadius="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollViewer
|
||||
x:Name="ContentScrollViewer"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
IsTabStop="False"
|
||||
VerticalScrollBarVisibility="Disabled"
|
||||
ZoomMode="Disabled">
|
||||
<Grid
|
||||
Padding="0"
|
||||
BorderBrush="{ThemeResource ContentDialogSeparatorBorderBrush}"
|
||||
BorderThickness="{ThemeResource ContentDialogSeparatorThickness}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ContentControl
|
||||
x:Name="Title"
|
||||
Margin="{ThemeResource ContentDialogTitleMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Content="{TemplateBinding Title}"
|
||||
ContentTemplate="{TemplateBinding TitleTemplate}"
|
||||
FontFamily="{StaticResource ContentControlThemeFontFamily}"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsTabStop="False">
|
||||
<ContentControl.Template>
|
||||
<ControlTemplate TargetType="ContentControl">
|
||||
<ContentPresenter
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
MaxLines="2"
|
||||
TextWrapping="Wrap"/>
|
||||
</ControlTemplate>
|
||||
</ContentControl.Template>
|
||||
</ContentControl>
|
||||
<ContentPresenter
|
||||
x:Name="Content"
|
||||
Grid.Row="1"
|
||||
Margin="0,0,0,8"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
FontFamily="{StaticResource ContentControlThemeFontFamily}"
|
||||
FontSize="{StaticResource ControlContentThemeFontSize}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
TextWrapping="Wrap"/>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
<Grid
|
||||
x:Name="CommandSpace"
|
||||
Grid.Row="1"
|
||||
Padding="8,0,8,8"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom"
|
||||
XYFocusKeyboardNavigation="Enabled">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="PrimaryColumn" Width="*"/>
|
||||
<ColumnDefinition x:Name="FirstSpacer" Width="0"/>
|
||||
<ColumnDefinition x:Name="SecondaryColumn" Width="0"/>
|
||||
<ColumnDefinition x:Name="SecondSpacer" Width="{ThemeResource ContentDialogButtonSpacing}"/>
|
||||
<ColumnDefinition x:Name="CloseColumn" Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button
|
||||
x:Name="PrimaryButton"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="{TemplateBinding PrimaryButtonText}"
|
||||
ElementSoundMode="FocusOnly"
|
||||
IsEnabled="{TemplateBinding IsPrimaryButtonEnabled}"
|
||||
IsTabStop="False"
|
||||
Style="{TemplateBinding PrimaryButtonStyle}"/>
|
||||
<Button
|
||||
x:Name="SecondaryButton"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="{TemplateBinding SecondaryButtonText}"
|
||||
ElementSoundMode="FocusOnly"
|
||||
IsEnabled="{TemplateBinding IsSecondaryButtonEnabled}"
|
||||
IsTabStop="False"
|
||||
Style="{TemplateBinding SecondaryButtonStyle}"/>
|
||||
<Button
|
||||
x:Name="CloseButton"
|
||||
Grid.Column="4"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="{TemplateBinding CloseButtonText}"
|
||||
ElementSoundMode="FocusOnly"
|
||||
IsTabStop="False"
|
||||
Style="{TemplateBinding CloseButtonStyle}"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="DialogShowingStates">
|
||||
|
||||
<VisualStateGroup.Transitions>
|
||||
<VisualTransition To="DialogHidden">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="IsHitTestVisible">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="False"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleX">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0"/>
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFastAnimationDuration}"
|
||||
Value="1.05"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleY">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0"/>
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlFastAnimationDuration}"
|
||||
Value="1.05"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0"/>
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="0.0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
<VisualTransition To="DialogShowing">
|
||||
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleX">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.05"/>
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlNormalAnimationDuration}"
|
||||
Value="1.0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleY">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.05"/>
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
|
||||
KeyTime="{StaticResource ControlNormalAnimationDuration}"
|
||||
Value="1.0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0"/>
|
||||
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" Value="1.0"/>
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
</VisualStateGroup.Transitions>
|
||||
<VisualState x:Name="DialogHidden"/>
|
||||
<VisualState x:Name="DialogShowing">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PrimaryButton.IsTabStop" Value="True"/>
|
||||
<Setter Target="SecondaryButton.IsTabStop" Value="True"/>
|
||||
<Setter Target="CloseButton.IsTabStop" Value="True"/>
|
||||
<Setter Target="LayoutRoot.Visibility" Value="Visible"/>
|
||||
<Setter Target="BackgroundElement.TabFocusNavigation" Value="Cycle"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="DialogShowingWithoutSmokeLayer">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PrimaryButton.IsTabStop" Value="True"/>
|
||||
<Setter Target="SecondaryButton.IsTabStop" Value="True"/>
|
||||
<Setter Target="CloseButton.IsTabStop" Value="True"/>
|
||||
<Setter Target="LayoutRoot.Visibility" Value="Visible"/>
|
||||
<Setter Target="LayoutRoot.Background" Value="{x:Null}"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="DialogSizingStates">
|
||||
<VisualState x:Name="DefaultDialogSizing"/>
|
||||
<VisualState x:Name="FullDialogSizing">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="BackgroundElement.VerticalAlignment" Value="Stretch"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="ButtonsVisibilityStates">
|
||||
<VisualState x:Name="AllVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="FirstSpacer.Width" Value="{ThemeResource ContentDialogButtonSpacing}"/>
|
||||
<Setter Target="SecondaryColumn.Width" Value="*"/>
|
||||
<Setter Target="SecondaryButton.(Grid.Column)" Value="2"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="NoneVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="CommandSpace.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PrimaryVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PrimaryButton.(Grid.Column)" Value="4"/>
|
||||
<Setter Target="SecondaryButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="CloseButton.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SecondaryVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="SecondaryButton.(Grid.Column)" Value="4"/>
|
||||
<Setter Target="PrimaryButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="CloseButton.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CloseVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PrimaryButton.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="SecondaryButton.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PrimaryAndSecondaryVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="SecondaryButton.(Grid.Column)" Value="4"/>
|
||||
<Setter Target="CloseButton.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PrimaryAndCloseVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="SecondaryButton.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SecondaryAndCloseVisible">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PrimaryButton.Visibility" Value="Collapsed"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="DefaultButtonStates">
|
||||
<VisualState x:Name="NoDefaultButton"/>
|
||||
<VisualState x:Name="PrimaryAsDefaultButton">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PrimaryButton.Style" Value="{StaticResource AccentButtonStyle}"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SecondaryAsDefaultButton">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="SecondaryButton.Style" Value="{StaticResource AccentButtonStyle}"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CloseAsDefaultButton">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="CloseButton.Style" Value="{StaticResource AccentButtonStyle}"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="DialogBorderStates">
|
||||
<VisualState x:Name="NoBorder"/>
|
||||
<VisualState x:Name="AccentColorBorder">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="BackgroundElement.BorderBrush" Value="{ThemeResource SystemControlForegroundAccentBrush}"/>
|
||||
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<!-- ItemsPanelTemplate -->
|
||||
<ItemsPanelTemplate x:Key="ItemsStackPanelTemplate">
|
||||
<ItemsStackPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
|
||||
<ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate">
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
</Application>
|
||||
@@ -5,9 +5,8 @@ using CommunityToolkit.WinUI.Notifications;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.Exception;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using System.Diagnostics;
|
||||
using Windows.Storage;
|
||||
|
||||
@@ -15,9 +14,12 @@ namespace Snap.Hutao;
|
||||
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// This class must be public
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Injection(InjectAs.Singleton)]
|
||||
public partial class App : Application
|
||||
[SuppressMessage("", "SH001")]
|
||||
public sealed partial class App : Application
|
||||
{
|
||||
private readonly ILogger<App> logger;
|
||||
|
||||
@@ -25,7 +27,6 @@ public partial class App : Application
|
||||
/// Initializes the singleton application object.
|
||||
/// </summary>
|
||||
/// <param name="logger">日志器</param>
|
||||
/// <param name="appCenter">App Center</param>
|
||||
public App(ILogger<App> logger)
|
||||
{
|
||||
// load app resource
|
||||
@@ -50,8 +51,8 @@ public partial class App : Application
|
||||
firstInstance.Activated += Activation.Activate;
|
||||
ToastNotificationManagerCompat.OnActivated += Activation.NotificationActivate;
|
||||
|
||||
logger.LogInformation(EventIds.CommonLog, "Snap Hutao | {name} : {version}", CoreEnvironment.FamilyName, CoreEnvironment.Version);
|
||||
logger.LogInformation(EventIds.CommonLog, "Cache folder : {folder}", ApplicationData.Current.TemporaryFolder.Path);
|
||||
logger.LogInformation("Snap Hutao | {name} : {version}", CoreEnvironment.FamilyName, CoreEnvironment.Version);
|
||||
logger.LogInformation("Cache folder : {folder}", ApplicationData.Current.LocalCacheFolder.Path);
|
||||
|
||||
JumpListHelper.ConfigureAsync().SafeForget(logger);
|
||||
}
|
||||
|
||||
BIN
src/Snap.Hutao/Snap.Hutao/Assets/LargeTile.scale-100.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/LargeTile.scale-125.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/LargeTile.scale-150.png
Normal file
|
After Width: | Height: | Size: 314 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/LargeTile.scale-200.png
Normal file
|
After Width: | Height: | Size: 506 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/LargeTile.scale-400.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 1.0 MiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SmallTile.scale-100.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SmallTile.scale-125.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SmallTile.scale-150.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SmallTile.scale-200.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SmallTile.scale-400.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SplashScreen.scale-100.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SplashScreen.scale-125.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SplashScreen.scale-150.png
Normal file
|
After Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 500 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/SplashScreen.scale-400.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square150x150Logo.scale-100.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square150x150Logo.scale-125.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square150x150Logo.scale-150.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 150 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square150x150Logo.scale-400.png
Normal file
|
After Width: | Height: | Size: 480 KiB |
|
After Width: | Height: | Size: 969 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 969 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square44x44Logo.scale-100.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square44x44Logo.scale-125.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square44x44Logo.scale-150.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
BIN
src/Snap.Hutao/Snap.Hutao/Assets/Square44x44Logo.scale-400.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 969 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 3.1 KiB |