├── .gitignore
├── .vs
├── ModsUpdateUI
│ └── v15
│ │ ├── .suo
│ │ └── Server
│ │ └── sqlite3
│ │ ├── db.lock
│ │ ├── storage.ide
│ │ ├── storage.ide-shm
│ │ └── storage.ide-wal
├── ProjectSettings.json
├── VSWorkspaceState.json
└── slnx.sqlite
├── AppUpdate
├── App.config
├── AppUpdate.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── LICENSE
├── ModsUpdateUI.sln
├── ModsUpdateUI
├── App.config
├── App.xaml
├── App.xaml.cs
├── Configurations
│ ├── ConfigurationManager.cs
│ ├── DownloadModsConfig.cs
│ ├── SoftwareInfo.cs
│ └── UpdateModsConfig.cs
├── Constants.cs
├── Converters
│ ├── ArrayToStringConverter.cs
│ ├── IntToBooleanConverter.cs
│ └── TwoNumsToPercentage.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Models
│ ├── LocalModInfo.cs
│ └── RemoteModInfo.cs
├── ModsUpdateUI.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Services
│ ├── ApplicationService.cs
│ ├── GithubService.cs
│ ├── LocalService.cs
│ └── ServiceManager.cs
├── Utils
│ └── Utilities.cs
├── ViewModels
│ ├── ModsDownloadViewModel.cs
│ └── ModsUpdateViewModel.cs
├── Views
│ ├── AboutView.xaml
│ ├── AboutView.xaml.cs
│ ├── ModsDownloadConfigView.xaml
│ ├── ModsDownloadConfigView.xaml.cs
│ ├── ModsDownloadView.xaml
│ ├── ModsDownloadView.xaml.cs
│ ├── ModsUpdateConfigView.xaml
│ ├── ModsUpdateConfigView.xaml.cs
│ ├── ModsUpdateView.xaml
│ └── ModsUpdateView.xaml.cs
└── packages.config
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ModsUpdateUI/obj/
2 | ModsUpdateUI/bin/
3 | packages/
4 | AppUpdate/bin/
5 | AppUpdate/obj/
6 | .vs/
--------------------------------------------------------------------------------
/.vs/ModsUpdateUI/v15/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevinSusen/ModsUpdateUI/fee3b5701775d3b922ddb48acfdfa4253fcad7a0/.vs/ModsUpdateUI/v15/.suo
--------------------------------------------------------------------------------
/.vs/ModsUpdateUI/v15/Server/sqlite3/db.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevinSusen/ModsUpdateUI/fee3b5701775d3b922ddb48acfdfa4253fcad7a0/.vs/ModsUpdateUI/v15/Server/sqlite3/db.lock
--------------------------------------------------------------------------------
/.vs/ModsUpdateUI/v15/Server/sqlite3/storage.ide:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevinSusen/ModsUpdateUI/fee3b5701775d3b922ddb48acfdfa4253fcad7a0/.vs/ModsUpdateUI/v15/Server/sqlite3/storage.ide
--------------------------------------------------------------------------------
/.vs/ModsUpdateUI/v15/Server/sqlite3/storage.ide-shm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevinSusen/ModsUpdateUI/fee3b5701775d3b922ddb48acfdfa4253fcad7a0/.vs/ModsUpdateUI/v15/Server/sqlite3/storage.ide-shm
--------------------------------------------------------------------------------
/.vs/ModsUpdateUI/v15/Server/sqlite3/storage.ide-wal:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevinSusen/ModsUpdateUI/fee3b5701775d3b922ddb48acfdfa4253fcad7a0/.vs/ModsUpdateUI/v15/Server/sqlite3/storage.ide-wal
--------------------------------------------------------------------------------
/.vs/ProjectSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "CurrentProjectSetting": null
3 | }
--------------------------------------------------------------------------------
/.vs/VSWorkspaceState.json:
--------------------------------------------------------------------------------
1 | {
2 | "ExpandedNodes": [
3 | "",
4 | "\\AppUpdate\\Properties",
5 | "\\ModsUpdateUI\\ViewModels"
6 | ],
7 | "SelectedNode": "\\.gitignore",
8 | "PreviewInSolutionExplorer": false
9 | }
--------------------------------------------------------------------------------
/.vs/slnx.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevinSusen/ModsUpdateUI/fee3b5701775d3b922ddb48acfdfa4253fcad7a0/.vs/slnx.sqlite
--------------------------------------------------------------------------------
/AppUpdate/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/AppUpdate/AppUpdate.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {549DF3AB-AE6D-46F0-BA51-A1D6917ED330}
8 | Exe
9 | AppUpdate
10 | AppUpdate
11 | v4.6.1
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | 7.1
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 | 7.1
36 |
37 |
38 |
39 | ..\packages\Octokit.0.32.0\lib\net45\Octokit.dll
40 |
41 |
42 | ..\packages\ShellProgressBar.4.2.0\lib\netstandard2.0\ShellProgressBar.dll
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/AppUpdate/Program.cs:
--------------------------------------------------------------------------------
1 | using Octokit;
2 | using ShellProgressBar;
3 | using System;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Net;
7 | using System.Threading.Tasks;
8 |
9 | namespace AppUpdate
10 | {
11 | class Program
12 | {
13 | private static ProgressBar _bar;
14 |
15 | static async Task Main(string[] args)
16 | {
17 | var (uri, size) = await GetAppUriAsync();
18 |
19 | var options = new ProgressBarOptions
20 | {
21 | ProgressBarOnBottom = true,
22 | CollapseWhenFinished = true
23 | };
24 | using (_bar = new ProgressBar(size, "Downloading...", options))
25 | {
26 | using (WebClient client = new WebClient())
27 | {
28 | client.DownloadProgressChanged += Client_DownloadProgressChanged;
29 | client.DownloadFileAsync(uri, Path.GetTempPath() + Path.GetFileName(uri.AbsolutePath));
30 | while (client.IsBusy) ;
31 |
32 | Console.WriteLine("下载完成");
33 | Process.Start("cmd.exe", "/k ..\\update.bat ModsUpdateUI.7z");
34 | Process.GetCurrentProcess().Kill();
35 | }
36 | }
37 | }
38 |
39 | private static async Task<(Uri, int)> GetAppUriAsync()
40 | {
41 | GitHubClient _client = new GitHubClient(new ProductHeaderValue("Update"));
42 | Release result = null;
43 | try
44 | {
45 | result = await _client.Repository.Release.GetLatest("DevinSusen", "ModsUpdateUI");
46 | }
47 | catch (Exception)
48 | {
49 | Console.WriteLine("网络错误");
50 | Environment.Exit(1);
51 | }
52 |
53 | Uri u = new Uri(result.Assets[0].BrowserDownloadUrl);
54 | int size = result.Assets[0].Size;
55 | return (u, size);
56 | }
57 |
58 | private static void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
59 | {
60 | for (int i = 0; i < e.BytesReceived; i++)
61 | _bar.Tick();
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/AppUpdate/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("AppUpdate")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AppUpdate")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("549df3ab-ae6d-46f0-ba51-a1d6917ed330")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/AppUpdate/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Devin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ModsUpdateUI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModsUpdateUI", "ModsUpdateUI\ModsUpdateUI.csproj", "{F14E4732-17E8-4E65-BD5E-D210A298E771}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppUpdate", "AppUpdate\AppUpdate.csproj", "{549DF3AB-AE6D-46F0-BA51-A1D6917ED330}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {F14E4732-17E8-4E65-BD5E-D210A298E771}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {F14E4732-17E8-4E65-BD5E-D210A298E771}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {F14E4732-17E8-4E65-BD5E-D210A298E771}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {F14E4732-17E8-4E65-BD5E-D210A298E771}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {549DF3AB-AE6D-46F0-BA51-A1D6917ED330}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {549DF3AB-AE6D-46F0-BA51-A1D6917ED330}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {549DF3AB-AE6D-46F0-BA51-A1D6917ED330}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {549DF3AB-AE6D-46F0-BA51-A1D6917ED330}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {B9E08F78-BAC9-485D-9CC6-F5FE20A67DE6}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/ModsUpdateUI/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ModsUpdateUI/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/ModsUpdateUI/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace ModsUpdateUI
4 | {
5 | ///
6 | /// App.xaml 的交互逻辑
7 | ///
8 | public partial class App : Application
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Configurations/ConfigurationManager.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System.IO;
3 |
4 | namespace ModsUpdateUI.Configurations
5 | {
6 | public static class ConfigurationManager
7 | {
8 | #region Download Configuration
9 | private static DownloadModsConfig _downloadModsConfig = null;
10 |
11 | public static DownloadModsConfig DownloadModsConfiguration
12 | {
13 | get
14 | {
15 | if (_downloadModsConfig == null)
16 | _downloadModsConfig = LoadConfig(Constants.DownloadModsConfigPath);
17 | return _downloadModsConfig;
18 | }
19 | }
20 | #endregion
21 |
22 | #region Update Mods Configuration
23 | private static UpdateModsConfig _updateModsConfig = null;
24 |
25 | public static UpdateModsConfig UpdateModsConfiguration
26 | {
27 | get
28 | {
29 | if (_updateModsConfig == null)
30 | _updateModsConfig = LoadConfig(Constants.UpdateModsConfigPath);
31 | return _updateModsConfig;
32 | }
33 | }
34 | #endregion
35 |
36 | #region Load Configuration
37 |
38 | private static T LoadConfig(string fileName) where T : new()
39 | {
40 | if (!File.Exists(fileName))
41 | return InitConfiguration(fileName);
42 | string s = File.ReadAllText(fileName);
43 | return JsonConvert.DeserializeObject(s);
44 | }
45 |
46 | private static T InitConfiguration(string fileName) where T : new()
47 | {
48 | T t = new T();
49 | SaveConfiguration(t, fileName);
50 | return t;
51 | }
52 | #endregion
53 |
54 | #region Save Configuration
55 |
56 | public static void SaveConfiguration(T t, string fileName) where T : new()
57 | {
58 | string s = JsonConvert.SerializeObject(t, Formatting.Indented);
59 | File.WriteAllText(fileName, s);
60 | }
61 |
62 | #endregion
63 |
64 | #region Software Mata Data
65 |
66 | private static SoftwareInfo _sinfo = null;
67 |
68 | public static SoftwareInfo SoftwareInformation
69 | {
70 | get
71 | {
72 | if (_sinfo == null)
73 | _sinfo = LoadConfig(Constants.SoftwareMataDataPath);
74 | return _sinfo;
75 | }
76 | }
77 |
78 | #endregion
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Configurations/DownloadModsConfig.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.IO;
4 |
5 | namespace ModsUpdateUI.Configurations
6 | {
7 | public class DownloadModsConfig
8 | {
9 | ///
10 | /// 下载目录
11 | ///
12 | [JsonProperty("DownloadDirectory")]
13 | public string DownloadDirectory { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
14 |
15 | ///
16 | /// 是否自动解压
17 | ///
18 | [JsonProperty("IsAutoDecompress")]
19 | public bool IsAutoDecompress { get; set; } = false;
20 |
21 | ///
22 | /// 解压后是否删除原文件
23 | ///
24 | [JsonProperty("IsDeleteFileWhenDecompress")]
25 | public bool IsDeleteFileWhenDecompress { get; set; } = true;
26 |
27 | ///
28 | /// Github账户名
29 | ///
30 | [JsonProperty("Owner")]
31 | public string Owner { get; set; } = "phorcys";
32 |
33 | ///
34 | /// 代码库
35 | ///
36 | [JsonProperty("Repository")]
37 | public string Repository { get; set; } = "Taiwu_mods";
38 |
39 | ///
40 | /// 该配置是否已经合法
41 | ///
42 | /// 如果true,则配置生效
43 | [JsonIgnore]
44 | public bool IsOK { get => !string.IsNullOrWhiteSpace(Owner) && !string.IsNullOrWhiteSpace(Repository); }
45 |
46 | ///
47 | /// 是否可以下载
48 | ///
49 | /// 如果true,则可以开始下载
50 | [JsonIgnore]
51 | public bool CanDownload { get => Directory.Exists(DownloadDirectory); }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Configurations/SoftwareInfo.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 |
4 | namespace ModsUpdateUI.Configurations
5 | {
6 | public class SoftwareInfo
7 | {
8 | [JsonProperty("Author")]
9 | public string Author { get; set; } = "Devin Tung";
10 |
11 | [JsonProperty("HomePage")]
12 | public Uri HomePage { get; set; } = new Uri(@"https://github.com/DevinSusen/ModsUpdateUI");
13 |
14 | [JsonProperty("Version")]
15 | public string Version { get; set; } = "1.2";
16 |
17 | [JsonProperty("ReleaseTime")]
18 | public DateTime ReleaseTime { get; set; } = DateTime.Now;
19 |
20 | [JsonProperty("Dependencies")]
21 | public Dependency[] Dependencies { get; set; }
22 | }
23 |
24 | public class Dependency
25 | {
26 | [JsonProperty("Name")]
27 | public string Name { get; set; }
28 |
29 | [JsonProperty("Author")]
30 | public string Author { get; set; }
31 |
32 | [JsonProperty("License")]
33 | public string License { get; set; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Configurations/UpdateModsConfig.cs:
--------------------------------------------------------------------------------
1 | using ModsUpdateUI.Utils;
2 | using Newtonsoft.Json;
3 | using System.IO;
4 |
5 | namespace ModsUpdateUI.Configurations
6 | {
7 | public class UpdateModsConfig
8 | {
9 | ///
10 | /// Mod的存放目录
11 | ///
12 | [JsonProperty("ModsDirectory")]
13 | public string ModsDirectory { get; set; } = Utilities.GetTheScrollOfTaiwuModsFolder();
14 |
15 | ///
16 | /// 所有者
17 | ///
18 | [JsonProperty("Owner")]
19 | public string Owner { get; set; } = "phorcys";
20 |
21 | ///
22 | /// 仓库名
23 | ///
24 | [JsonProperty("Repository")]
25 | public string Repository { get; set; } = "Taiwu_mods";
26 |
27 | ///
28 | /// 要查看的文件类型
29 | ///
30 | [JsonProperty("FileType")]
31 | public string FileType { get; set; } = "application/zip";
32 |
33 | ///
34 | /// 存储信息文件
35 | ///
36 | [JsonProperty("InfoFile")]
37 | public string InfoFile { get; set; } = "Info.json";
38 |
39 | ///
40 | /// 该配置是否已经合法
41 | ///
42 | /// 如果true,则配置生效
43 | [JsonIgnore]
44 | public bool IsOK { get => Directory.Exists(ModsDirectory); }
45 |
46 | ///
47 | /// 是否可以可以更新
48 | ///
49 | /// 如果true,则可以开始更新
50 | [JsonIgnore]
51 | public bool CanUpdate { get => !string.IsNullOrWhiteSpace(Owner) && !string.IsNullOrWhiteSpace(Repository); }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace ModsUpdateUI
2 | {
3 | public static class Constants
4 | {
5 | #region Steam Key
6 | public const string SteamRegistryKey64 = @"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Valve\Steam";
7 | public const string SteamRegistryKey32 = @"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam";
8 | #endregion
9 |
10 | #region TaiWu
11 | public const string TaiWuModsFolder = @"\steamapps\common\The Scroll Of Taiwu\Mods";
12 |
13 | public const string TaiWuSaveFilesFolder = @"\steamapps\common\The Scroll Of Taiwu\The Scroll Of Taiwu Alpha V1.0_Data\SaveFiles";
14 | #endregion
15 |
16 | #region Configuration
17 | public const string DownloadModsConfigPath = @"DownloadModsConfig.json";
18 | public const string UpdateModsConfigPath = @"UpdateModsConfig.json";
19 |
20 | public const string SoftwareMataDataPath = @"MataData.json";
21 | #endregion
22 |
23 | #region File Type
24 |
25 | public const string ZipType = @"application/zip";
26 | public const string JsonType = @"application/json";
27 |
28 | #endregion
29 |
30 | #region CheckUpdate
31 |
32 | public const string UpdateApplication = @"AppUpdate.exe";
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Converters/ArrayToStringConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace ModsUpdateUI.Converters
6 | {
7 | public class ArrayToStringConverter : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | string splitCode = parameter as string;
12 | if (!(value is string[] vs))
13 | return "";
14 | if (!string.IsNullOrEmpty(splitCode))
15 | return string.Join(splitCode, vs);
16 | else return string.Join(",", vs);
17 | }
18 |
19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
20 | {
21 | throw new NotImplementedException();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Converters/IntToBooleanConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace ModsUpdateUI.Converters
6 | {
7 | public class IntToBooleanConverter : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | int v = System.Convert.ToInt32(value);
12 | if (v > 0)
13 | return true;
14 | return false;
15 | }
16 |
17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
18 | {
19 | throw new NotImplementedException();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Converters/TwoNumsToPercentage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace ModsUpdateUI.Converters
6 | {
7 | class TwoNumsToPercentage : IMultiValueConverter
8 | {
9 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | int v = System.Convert.ToInt32(values[0]);
12 | bool isSuc = int.TryParse(values[1].ToString(), out int all);
13 | if (all == 0)
14 | return 0;
15 | return v * 100 / all;
16 | }
17 |
18 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
19 | {
20 | throw new NotImplementedException();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ModsUpdateUI/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
26 |
31 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
51 |
52 |
53 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
79 |
80 |
85 |
89 |
101 |
102 |
103 |
108 |
112 |
124 |
125 |
126 |
186 |
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/ModsUpdateUI/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using MahApps.Metro.Controls;
2 | using ModsUpdateUI.Configurations;
3 | using ModsUpdateUI.Services;
4 | using ModsUpdateUI.Views;
5 | using System.Diagnostics;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace ModsUpdateUI
10 | {
11 | ///
12 | /// MainWindow.xaml 的交互逻辑
13 | ///
14 | public partial class MainWindow : MetroWindow
15 | {
16 | public MainWindow()
17 | {
18 | InitializeComponent();
19 |
20 | CheckUpdateAsync();
21 | }
22 |
23 | private async void CheckUpdateAsync()
24 | {
25 | if (await CanUpdate())
26 | {
27 | var result = MessageBox.Show("有更新,是否下载?", "检查更新", MessageBoxButton.YesNo);
28 | if (result == MessageBoxResult.Yes)
29 | {
30 | Process.Start(@"https://github.com/DevinSusen/ModsUpdateUI/releases");
31 | }
32 | }
33 | }
34 |
35 | private async Task CanUpdate()
36 | {
37 | ApplicationService service = new ApplicationService();
38 | return await service.CheckUpdateAsync();
39 | }
40 |
41 | private async void CheckUpdateButton_Click(object sender, RoutedEventArgs e)
42 | {
43 | if(await CanUpdate())
44 | {
45 | var result = MessageBox.Show("有更新,是否下载?", "检查更新", MessageBoxButton.YesNo);
46 | if (result == MessageBoxResult.Yes)
47 | {
48 | Process.Start(@"https://github.com/DevinSusen/ModsUpdateUI/releases");
49 | }
50 | }
51 | else
52 | {
53 | MessageBox.Show("当前已是最新版本", "检查更新");
54 | }
55 | }
56 |
57 | private void WikiButton_Click(object sender, RoutedEventArgs e)
58 | {
59 | Process.Start(@"https://github.com/DevinSusen/ModsUpdateUI");
60 | }
61 |
62 | private void AboutButton_Click(object sender, RoutedEventArgs e)
63 | {
64 | AboutView view = new AboutView();
65 | view.Show();
66 | }
67 |
68 | private void ModsDownloadConfigButton_Click(object sender, RoutedEventArgs e)
69 | {
70 | ModsDownloadConfigView view = new ModsDownloadConfigView();
71 | view.Show();
72 | }
73 |
74 | private void ModsUpdateConfigButton_Click(object sender, RoutedEventArgs e)
75 | {
76 | ModsUpdateConfigView view = new ModsUpdateConfigView();
77 | view.Show();
78 | }
79 |
80 | private void DownloadModsButton_Click(object sender, RoutedEventArgs e)
81 | {
82 | if (!ConfigurationManager.DownloadModsConfiguration.IsOK)
83 | return;
84 | ModsDownloadView view = new ModsDownloadView();
85 | view.Show();
86 | }
87 |
88 | private void UpdateModsButton_Click(object sender, RoutedEventArgs e)
89 | {
90 | if (!ConfigurationManager.UpdateModsConfiguration.IsOK)
91 | return;
92 | ModsUpdateView view = new ModsUpdateView();
93 | view.Show();
94 | }
95 |
96 | //private void PackButton_Click(object sender, RoutedEventArgs e)
97 | //{
98 | // string email = EmailTextBox.Text.Trim();
99 | // string password = EmailPasswordBox.Password;
100 | // if (!IsValidEmail(email))
101 | // {
102 | // //TODO: Message
103 | // return;
104 | // }
105 | // string path = CompressSaveFiles(Utils.Utilities.GetTheScrollOfTaiwuSaveFilesFolder());
106 | // MailMessage mail = new MailMessage(email, email);
107 | // mail.Subject = "存档";
108 | // mail.SubjectEncoding = Encoding.UTF8;
109 | // mail.Attachments.Add(new Attachment(path));
110 |
111 | // SmtpClient client = new SmtpClient();
112 | //}
113 |
114 | //private bool IsValidEmail(string email)
115 | //{
116 | // try
117 | // {
118 | // var addr = new MailAddress(email);
119 | // return addr.Address == email;
120 | // }
121 | // catch
122 | // {
123 | // return false;
124 | // }
125 | //}
126 |
127 | //private string CompressSaveFiles(string filePath)
128 | //{
129 | // Process proc = new Process();
130 | // string basePath = new DirectoryInfo("..").FullName + Path.DirectorySeparatorChar + @"tools";
131 | // string exePath = basePath + @"\7za.exe";
132 | // proc.StartInfo.FileName = exePath;
133 | // string compFile = basePath + @"\Save.7z";
134 | // proc.StartInfo.Arguments = "a " + compFile + " " + filePath;
135 | // proc.StartInfo.CreateNoWindow = false;
136 | // proc.Start();
137 | // proc.WaitForExit();
138 | // proc.Close();
139 | // return compFile;
140 | //}
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Models/LocalModInfo.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 |
6 | namespace ModsUpdateUI.Models
7 | {
8 | public class LocalModInfo
9 | {
10 | ///
11 | /// 标识
12 | ///
13 | [JsonProperty("Id")]
14 | public string Id { get; set; }
15 |
16 | ///
17 | /// 显示名
18 | ///
19 | [JsonProperty("DisplayName")]
20 | public string DisplayName { get; set; }
21 |
22 | ///
23 | /// 作者
24 | ///
25 | [JsonProperty("Author")]
26 | public string Author { get; set; }
27 |
28 | ///
29 | /// 版本号
30 | ///
31 | [JsonProperty("Version")]
32 | public string Version { get; set; }
33 |
34 | ///
35 | /// 程序集名称
36 | ///
37 | [JsonProperty("AssemblyName")]
38 | public string AssemblyName { get; set; }
39 |
40 | ///
41 | /// 加载方法
42 | ///
43 | [JsonProperty("EntryMethod")]
44 | public string EntryMethod { get; set; }
45 |
46 | ///
47 | /// 该Mod的前置需求
48 | ///
49 | [JsonProperty("Requirements")]
50 | public string[] Requirements { get; set; }
51 |
52 | ///
53 | /// 主页
54 | ///
55 | [JsonProperty("HomePage")]
56 | public Uri HomePage { get; set; }
57 |
58 | ///
59 | /// Mod地址
60 | ///
61 | [JsonProperty("Repository")]
62 | public string Repository { get; set; }
63 |
64 | ///
65 | /// 简介
66 | ///
67 | [JsonProperty("Description")]
68 | public string Description { get; set; }
69 |
70 | ///
71 | /// 管理器版本
72 | ///
73 | [JsonProperty("ManagerVersion")]
74 | public string ManagerVersion { get; set; }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Models/RemoteModInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace ModsUpdateUI.Models
5 | {
6 | public class RemoteModInfo
7 | {
8 | ///
9 | /// Mod的唯一标识符
10 | ///
11 | public int Id { get; set; } // "id": 10918193
12 |
13 | ///
14 | /// Mod名称
15 | ///
16 | public string Name { get; set; } // "name": "AllWin-1.0.1.zip"
17 |
18 | ///
19 | /// 文件类型
20 | ///
21 | public string ContentType { get; set; } // "content_type": "application/zip",
22 |
23 | ///
24 | /// 版本
25 | ///
26 | public string Version // "name": "AllWin-1.0.1.zip" -> "1.0.1"
27 | {
28 | get
29 | {
30 | string fileName = Path.GetFileNameWithoutExtension(Name);
31 | int idx = fileName.IndexOf('-');
32 | if (idx == -1)
33 | return "?";
34 | return fileName.Substring(idx+1);
35 | }
36 | }
37 |
38 | ///
39 | /// 大小 以Byte为单位
40 | ///
41 | public int Size { get; set; } // "size": 2723,
42 |
43 | ///
44 | /// 最后更新时间
45 | ///
46 | public DateTime Updated { get; set; }// "updated_at": "2019-02-04T08:56:54Z",
47 |
48 | ///
49 | /// 下载地址
50 | ///
51 | public string BrowserDownloadUrl { get; set; } // "browser_download_url": "https://github.com/phorcys/Taiwu_mods/releases/download/release190204.1/AllWin-1.0.1.zip"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModsUpdateUI/ModsUpdateUI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F14E4732-17E8-4E65-BD5E-D210A298E771}
8 | WinExe
9 | ModsUpdateUI
10 | ModsUpdateUI
11 | v4.6.1
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 | 7.1
37 |
38 |
39 |
40 | ..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll
41 |
42 |
43 | ..\packages\MahApps.Metro.1.6.5\lib\net46\MahApps.Metro.dll
44 |
45 |
46 | ..\packages\MaterialDesignColors.1.1.3\lib\net45\MaterialDesignColors.dll
47 |
48 |
49 | ..\packages\MaterialDesignThemes.2.5.0.1205\lib\net45\MaterialDesignThemes.Wpf.dll
50 |
51 |
52 | ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
53 |
54 |
55 | ..\packages\Octokit.0.32.0\lib\net45\Octokit.dll
56 |
57 |
58 |
59 |
60 |
61 |
62 | 4.0
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | MSBuild:Compile
71 | Designer
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | AboutView.xaml
90 |
91 |
92 | ModsDownloadConfigView.xaml
93 |
94 |
95 | ModsDownloadView.xaml
96 |
97 |
98 | ModsUpdateView.xaml
99 |
100 |
101 | ModsUpdateConfigView.xaml
102 |
103 |
104 | MSBuild:Compile
105 | Designer
106 |
107 |
108 | App.xaml
109 | Code
110 |
111 |
112 | MainWindow.xaml
113 | Code
114 |
115 |
116 | Designer
117 | MSBuild:Compile
118 |
119 |
120 | Designer
121 | MSBuild:Compile
122 |
123 |
124 | Designer
125 | MSBuild:Compile
126 |
127 |
128 | Designer
129 | MSBuild:Compile
130 |
131 |
132 | Designer
133 | MSBuild:Compile
134 |
135 |
136 |
137 |
138 |
139 |
140 | Code
141 |
142 |
143 | True
144 | True
145 | Resources.resx
146 |
147 |
148 | True
149 | Settings.settings
150 | True
151 |
152 |
153 | ResXFileCodeGenerator
154 | Resources.Designer.cs
155 |
156 |
157 |
158 | SettingsSingleFileGenerator
159 | Settings.Designer.cs
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("ModsUpdateUI")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("ModsUpdateUI")]
15 | [assembly: AssemblyCopyright("Copyright © 2019")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ModsUpdateUI.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModsUpdateUI.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 覆盖当前线程的 CurrentUICulture 属性
56 | /// 使用此强类型的资源类的资源查找。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ModsUpdateUI.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Services/ApplicationService.cs:
--------------------------------------------------------------------------------
1 | using Octokit;
2 | using System.Threading.Tasks;
3 |
4 | namespace ModsUpdateUI.Services
5 | {
6 | internal class ApplicationService
7 | {
8 | public async Task CheckUpdateAsync()
9 | {
10 | GithubService service = new GithubService("DevinSusen", "ModsUpdateUI");
11 | var result = await service.GetLastestReleaseAsync();
12 | double newVersion = double.Parse(result.TagName.Substring(1));
13 | double oldVersion = double.Parse(Configurations.ConfigurationManager.SoftwareInformation.Version);
14 | return newVersion > oldVersion;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Services/GithubService.cs:
--------------------------------------------------------------------------------
1 | using ModsUpdateUI.Models;
2 | using Octokit;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace ModsUpdateUI.Services
7 | {
8 | public class GithubService
9 | {
10 | private GitHubClient _client = new GitHubClient(new ProductHeaderValue("user"));
11 |
12 | public string Owner { get; }
13 |
14 | public string Repos { get; }
15 |
16 | public GithubService(string owner, string repos)
17 | {
18 | Owner = owner;
19 | Repos = repos;
20 | }
21 |
22 | public async Task GetLastestReleaseAsync() => await _client.Repository.Release.GetLatest(Owner, Repos);
23 |
24 | public async Task> GetLastestModsAsync()
25 | {
26 | Release result;
27 | List mods = new List();
28 | try
29 | {
30 | result = await _client.Repository.Release.GetLatest(Owner, Repos);
31 | }
32 | catch (System.Exception)
33 | {
34 | return mods;
35 | }
36 |
37 | foreach (var i in result.Assets)
38 | {
39 | RemoteModInfo info = new RemoteModInfo
40 | {
41 | BrowserDownloadUrl = i.BrowserDownloadUrl,
42 | ContentType = i.ContentType,
43 | Id = i.Id,
44 | Name = i.Name,
45 | Size = i.Size,
46 | Updated = i.UpdatedAt.DateTime
47 | };
48 | mods.Add(info);
49 | }
50 | return mods;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Services/LocalService.cs:
--------------------------------------------------------------------------------
1 | using ModsUpdateUI.Models;
2 | using Newtonsoft.Json;
3 | using System.Collections.Generic;
4 | using System.IO;
5 |
6 | namespace ModsUpdateUI.Services
7 | {
8 | public class LocalService
9 | {
10 | ///
11 | /// 本机存放目录
12 | ///
13 | public string LocalPath { get; }
14 |
15 | ///
16 | /// 元信息文件
17 | ///
18 | public string InfoFileName { get; }
19 |
20 | ///
21 | /// 构造LocalService
22 | ///
23 | /// 本机存放目录
24 | /// 元信息文件
25 | public LocalService(string path, string infoFileName)
26 | {
27 | LocalPath = path;
28 | InfoFileName = infoFileName;
29 | }
30 |
31 | ///
32 | /// 获得本机已下载的Mod
33 | ///
34 | /// Mods文件夹路径
35 | /// Mod元信息文件
36 | /// 所有Mod信息的集合
37 | public List FromDirectory()
38 | {
39 | List infos = new List();
40 |
41 | foreach (var i in Directory.EnumerateDirectories(LocalPath))
42 | {
43 | DirectoryInfo info = new DirectoryInfo(i);
44 | string infoFilePath = info.FullName + @"\" + InfoFileName;
45 | if (!File.Exists(infoFilePath))
46 | continue;
47 | string content = File.ReadAllText(infoFilePath);
48 | infos.Add(JsonConvert.DeserializeObject(content));
49 | }
50 | return infos;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Services/ServiceManager.cs:
--------------------------------------------------------------------------------
1 | using ModsUpdateUI.Configurations;
2 |
3 | namespace ModsUpdateUI.Services
4 | {
5 | public static class ServiceManager
6 | {
7 | private static LocalService _localService = null;
8 |
9 | public static LocalService LocalService
10 | {
11 | get
12 | {
13 | if (_localService == null)
14 | _localService = new LocalService(ConfigurationManager.UpdateModsConfiguration.ModsDirectory, ConfigurationManager.UpdateModsConfiguration.InfoFile);
15 | return _localService;
16 | }
17 | }
18 |
19 | private static GithubService _githubService = null;
20 |
21 | public static GithubService GithubService
22 | {
23 | get
24 | {
25 | if (_githubService == null)
26 | _githubService = new GithubService(ConfigurationManager.DownloadModsConfiguration.Owner, ConfigurationManager.DownloadModsConfiguration.Repository);
27 | return _githubService;
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Utils/Utilities.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 |
3 | namespace ModsUpdateUI.Utils
4 | {
5 | public static class Utilities
6 | {
7 | ///
8 | /// Get Steam's installation path
9 | ///
10 | /// null if can't find it. The path if it exists.
11 | public static string GetSteamFolder()
12 | {
13 | object value = Registry.GetValue(Constants.SteamRegistryKey64, @"InstallPath", null);
14 | if(value == null)
15 | value = Registry.GetValue(Constants.SteamRegistryKey32, @"InstallPath", null);
16 | if (value == null)
17 | return null;
18 | return value as string;
19 | }
20 |
21 | ///
22 | /// Get the mods folder of The Scroll Of Taiwu.
23 | ///
24 | /// empty string if can't find it
25 | public static string GetTheScrollOfTaiwuModsFolder()
26 | {
27 | string steamPath = GetSteamFolder();
28 | if (steamPath == null)
29 | return "";
30 | return steamPath + Constants.TaiWuModsFolder;
31 | }
32 |
33 | public static string GetTheScrollOfTaiwuSaveFilesFolder()
34 | {
35 | string steamPath = GetSteamFolder();
36 | if (steamPath == null)
37 | return "";
38 | return steamPath + Constants.TaiWuSaveFilesFolder;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ModsUpdateUI/ViewModels/ModsDownloadViewModel.cs:
--------------------------------------------------------------------------------
1 | using ModsUpdateUI.Models;
2 | using ModsUpdateUI.Services;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.ComponentModel;
6 | using System.Runtime.CompilerServices;
7 | using System.Linq;
8 | using System.IO;
9 | using System;
10 | using ModsUpdateUI.Configurations;
11 | using MaterialDesignThemes.Wpf;
12 | using System.IO.Compression;
13 | using System.Threading.Tasks;
14 |
15 | namespace ModsUpdateUI.ViewModels
16 | {
17 | public class ModsDownloadViewModel : INotifyPropertyChanged
18 | {
19 | private List _allItems;
20 | private ObservableCollection _modItems;
21 | public ObservableCollection ModItems
22 | {
23 | get => _modItems;
24 | private set
25 | {
26 | _modItems = value;
27 | OnPropertyChanged("ModItems");
28 | }
29 | }
30 |
31 | private readonly ISnackbarMessageQueue _snackbarMessQueue;
32 |
33 | private string _fileTypeFilter;
34 | public string FileTypeFilter
35 | {
36 | get => _fileTypeFilter;
37 | set
38 | {
39 | _fileTypeFilter = value;
40 | OnPropertyChanged("FileTypeFilter");
41 | GetListByFileType(value);
42 | }
43 | }
44 |
45 | private List _fileTypes;
46 | public List FileTypes
47 | {
48 | get => _fileTypes;
49 | set
50 | {
51 | _fileTypes = value;
52 | OnPropertyChanged("FileTypes");
53 | }
54 | }
55 |
56 | private List _downloadItems;
57 | public List DownloadItems
58 | {
59 | get => _downloadItems;
60 | set
61 | {
62 | _downloadItems = value;
63 | OnPropertyChanged("DownloadItems");
64 | }
65 | }
66 |
67 | private int _leavingCount;
68 | public int LeavingCount
69 | {
70 | get => _leavingCount;
71 | set
72 | {
73 | _leavingCount = value;
74 | OnPropertyChanged("LeavingCount");
75 | }
76 | }
77 |
78 | private int _downloadedCount;
79 | public int DownloadedCount
80 | {
81 | get => _downloadedCount;
82 | set
83 | {
84 | _downloadedCount = value;
85 | OnPropertyChanged("DownloadedCount");
86 | }
87 | }
88 |
89 | private string _message;
90 | public string Message
91 | {
92 | get => _message;
93 | set
94 | {
95 | _message = value;
96 | OnPropertyChanged("Message");
97 | _snackbarMessQueue.Enqueue(value);
98 | }
99 | }
100 |
101 | #region Download
102 | private System.Net.WebClient _client;
103 | private System.Net.WebClient Client
104 | {
105 | get
106 | {
107 | if (_client == null)
108 | _client = new System.Net.WebClient();
109 | return _client;
110 | }
111 | }
112 |
113 | public async Task DownloadAsync()
114 | {
115 | await Task.Run(() => DownloadMod());
116 | }
117 |
118 | private void DownloadMod()
119 | {
120 | DownloadedCount = 0;
121 | LeavingCount = DownloadItems.Count;
122 | if (LeavingCount > 0)
123 | {
124 | Client.DownloadFileCompleted += Client_DownloadFileCompleted;
125 | Client.DownloadFileAsync(new Uri(DownloadItems[0].ModInfo.BrowserDownloadUrl),
126 | ConfigurationManager.DownloadModsConfiguration.DownloadDirectory + Path.DirectorySeparatorChar + DownloadItems[0].ModInfo.Name);
127 | while(Client.IsBusy);
128 | }
129 | else Message = "未选择待下载项目";
130 | }
131 |
132 | private void Client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
133 | {
134 | if (ConfigurationManager.DownloadModsConfiguration.IsAutoDecompress)
135 | {
136 | if (DownloadItems[0].ModInfo.ContentType == Constants.ZipType)
137 | {
138 | string path = ConfigurationManager.DownloadModsConfiguration.DownloadDirectory + Path.DirectorySeparatorChar + DownloadItems[0].ModInfo.Name;
139 | DecompressFile(path, ConfigurationManager.DownloadModsConfiguration.IsDeleteFileWhenDecompress);
140 | }
141 | }
142 | DownloadItems.RemoveAt(0);
143 | DownloadedCount += 1;
144 | LeavingCount -= 1;
145 | if (LeavingCount > 0)
146 | {
147 | Client.DownloadFileAsync(new Uri(DownloadItems[0].ModInfo.BrowserDownloadUrl),
148 | ConfigurationManager.DownloadModsConfiguration.DownloadDirectory + Path.DirectorySeparatorChar + DownloadItems[0].ModInfo.Name);
149 | }
150 | else
151 | {
152 | Message = "下载完毕";
153 | Client.DownloadFileCompleted -= Client_DownloadFileCompleted;
154 | }
155 | }
156 |
157 | private void DecompressFile(string filePath, bool canDelete)
158 | {
159 | try
160 | {
161 | ZipFile.ExtractToDirectory(filePath, ConfigurationManager.DownloadModsConfiguration.DownloadDirectory);
162 | }
163 | catch (Exception)
164 | {
165 | Message = "出现错误,请检查您的网络,并重新尝试。";
166 | if(File.Exists(filePath))
167 | File.Delete(filePath);
168 | return;
169 | }
170 |
171 | if (canDelete)
172 | File.Delete(filePath);
173 | }
174 |
175 | #endregion
176 |
177 | #region Show
178 |
179 | public void GetAll()
180 | {
181 | ModItems = new ObservableCollection(_allItems);
182 | }
183 |
184 | public void GetUndownloaded()
185 | {
186 | var result = from mod in _allItems
187 | where !mod.IsExists
188 | select mod;
189 | ModItems = new ObservableCollection(result);
190 | }
191 |
192 | public void GetDownloaded()
193 | {
194 | var result = from mod in _allItems
195 | where mod.IsExists
196 | select mod;
197 | ModItems = new ObservableCollection(result);
198 | }
199 |
200 | public void GetListByFileType(string fileType)
201 | {
202 | if (fileType == "All")
203 | GetAll();
204 | else
205 | {
206 | var result = from mod in _allItems
207 | where mod.ModInfo.ContentType == fileType
208 | select mod;
209 | ModItems = new ObservableCollection(result);
210 | }
211 | }
212 |
213 | #endregion
214 |
215 | #region Constructor
216 |
217 | public ModsDownloadViewModel(ISnackbarMessageQueue messageQueue)
218 | {
219 | _snackbarMessQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue));
220 | InitAsync();
221 | }
222 |
223 | private async void InitAsync()
224 | {
225 | var result = await ServiceManager.GithubService.GetLastestModsAsync();
226 | _allItems = DownloadModItem.FromRemoteList(result);
227 | ModItems = new ObservableCollection(_allItems);
228 |
229 | FileTypes = new List(result.Select(m => m.ContentType).Distinct())
230 | {
231 | "All"
232 | };
233 | FileTypeFilter = "All";
234 | Message = "数据加载完成";
235 | }
236 |
237 | #endregion
238 |
239 | public event PropertyChangedEventHandler PropertyChanged;
240 |
241 | public void OnPropertyChanged([CallerMemberName]string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
242 | }
243 |
244 | public partial class DownloadModItem : INotifyPropertyChanged
245 | {
246 | private RemoteModInfo _modInfo;
247 | public RemoteModInfo ModInfo
248 | {
249 | get => _modInfo;
250 | set
251 | {
252 | _modInfo = value;
253 | OnPropertyChanged("ModInfo");
254 | }
255 | }
256 |
257 | private bool _isChecked;
258 | public bool IsChecked
259 | {
260 | get => _isChecked;
261 | set
262 | {
263 | _isChecked = value;
264 | OnPropertyChanged("IsChecked");
265 | }
266 | }
267 |
268 | private bool _isExisting;
269 | public bool IsExists
270 | {
271 | get => _isExisting;
272 | set
273 | {
274 | _isExisting = value;
275 | OnPropertyChanged("IsExists");
276 | }
277 | }
278 |
279 | //private bool _visibility;
280 | //public bool Visibility
281 | //{
282 | // get => _visibility;
283 | // set
284 | // {
285 | // _visibility = value;
286 | // OnPropertyChanged("Visibility");
287 | // }
288 | //}
289 |
290 | public event PropertyChangedEventHandler PropertyChanged;
291 |
292 | public void OnPropertyChanged([CallerMemberName]string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
293 | }
294 |
295 | public partial class DownloadModItem
296 | {
297 | public static List FromRemoteList(List items)
298 | {
299 | List downloadMods = new List();
300 | LocalService ls = new LocalService(ConfigurationManager.UpdateModsConfiguration.ModsDirectory, ConfigurationManager.UpdateModsConfiguration.InfoFile);
301 | var lss = ls.FromDirectory();
302 | foreach(var i in items)
303 | {
304 | DownloadModItem item = new DownloadModItem
305 | {
306 | ModInfo = i,
307 | IsChecked = false
308 | };
309 | downloadMods.Add(item);
310 | string fileName = Path.GetFileNameWithoutExtension(i.Name);
311 | int idx = fileName.IndexOf('-');
312 | if (idx == -1)
313 | continue;
314 | var name = fileName.Substring(0, idx);
315 | if (lss.Exists(v => v.Id == name))
316 | item.IsExists = true;
317 | else item.IsExists = false;
318 | }
319 | return downloadMods;
320 | }
321 | }
322 | }
323 |
--------------------------------------------------------------------------------
/ModsUpdateUI/ViewModels/ModsUpdateViewModel.cs:
--------------------------------------------------------------------------------
1 | using ModsUpdateUI.Models;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Runtime.CompilerServices;
6 | using ModsUpdateUI.Services;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 | using System;
10 | using ModsUpdateUI.Configurations;
11 | using System.IO;
12 | using System.IO.Compression;
13 | using MaterialDesignThemes.Wpf;
14 |
15 | namespace ModsUpdateUI.ViewModels
16 | {
17 | public class ModsUpdateViewModel : INotifyPropertyChanged
18 | {
19 | private readonly ISnackbarMessageQueue _snackbarMessQueue;
20 |
21 | public void GetUpdatableMods()
22 | {
23 | var result = from mod in ModItems
24 | where mod.CanUpdate
25 | select mod;
26 | ModItems = new ObservableCollection(result);
27 | }
28 |
29 | public void GetAllMods() => ModItems = new ObservableCollection(_allItems);
30 |
31 | private bool _isChecking = true;
32 | public bool IsChecking
33 | {
34 | get => _isChecking;
35 | set
36 | {
37 | _isChecking = value;
38 | OnPropertyChanged("IsChecking");
39 | }
40 | }
41 |
42 | public async void CheckUpdateAsync()
43 | {
44 | var result = await _remoteMods;
45 | var lists = result.Where(v => v.ContentType == Constants.ZipType);
46 | ChangeToRemoteItems(lists);
47 | foreach (var i in ModItems)
48 | i.CanUpdate = i.CheckUpdate(lists);
49 | IsChecking = false;
50 | }
51 |
52 | private string _message;
53 | public string Message
54 | {
55 | get => _message;
56 | set
57 | {
58 | _message = value;
59 | OnPropertyChanged("Message");
60 | _snackbarMessQueue.Enqueue(value);
61 | }
62 | }
63 |
64 | private System.Net.WebClient _client;
65 | private System.Net.WebClient Client
66 | {
67 | get
68 | {
69 | if (_client == null)
70 | _client = new System.Net.WebClient();
71 | return _client;
72 | }
73 | }
74 |
75 | private int _updateCount;
76 | public int UpdateCount
77 | {
78 | get => _updateCount;
79 | set
80 | {
81 | _updateCount = value;
82 | OnPropertyChanged("UpdateCount");
83 | }
84 | }
85 |
86 | private int _updatedCount;
87 | public int UpdatedCount
88 | {
89 | get => _updatedCount;
90 | set
91 | {
92 | _updatedCount = value;
93 | OnPropertyChanged("UpdatedCount");
94 | }
95 | }
96 |
97 | private List _map;
98 | private List _updateItems;
99 | public List UpdateItems
100 | {
101 | get => _updateItems;
102 | set
103 | {
104 | _updateItems = value;
105 | OnPropertyChanged("UpdateItems");
106 | _map = new List();
107 | foreach (var i in value)
108 | {
109 | var it = _mappingRemote.First(v => v.Name.StartsWith(i.ModInfo.Id));
110 | _map.Add(it);
111 | }
112 | }
113 | }
114 |
115 | private List _mappingRemote = new List();
116 |
117 | private void ChangeToRemoteItems(IEnumerable lists)
118 | {
119 | foreach(var i in ModItems)
120 | {
121 | var it = lists.FirstOrDefault(v => v.Name.StartsWith(i.ModInfo.Id));
122 | if (it == default(RemoteModInfo))
123 | continue;
124 | _mappingRemote.Add(it);
125 | }
126 | }
127 |
128 | public async Task UpdateAsync()
129 | {
130 | await Task.Run(() => UpdateMod());
131 | }
132 |
133 | private void UpdateMod()
134 | {
135 | UpdatedCount = 0;
136 | UpdateCount = UpdateItems.Count;
137 | if (UpdateCount > 0)
138 | {
139 | Client.DownloadFileCompleted += Client_DownloadFileCompleted;
140 | Client.DownloadFileAsync(new Uri(_map[0].BrowserDownloadUrl),
141 | ConfigurationManager.UpdateModsConfiguration.ModsDirectory + Path.DirectorySeparatorChar + _map[0].Name);
142 | while (Client.IsBusy) ;
143 | }
144 | else Message = "未选择待更新项目";
145 | }
146 |
147 | private void Client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
148 | {
149 | string prefix = ConfigurationManager.UpdateModsConfiguration.ModsDirectory + Path.DirectorySeparatorChar;
150 | string name = _map[0].Name.Substring(0, _map[0].Name.LastIndexOf('-'));
151 | Directory.Delete(prefix + name, true);
152 | DecompressFile(prefix + _map[0].Name);
153 | _map.RemoveAt(0);
154 | UpdatedCount += 1;
155 | UpdateCount -= 1;
156 | if (UpdateCount > 0)
157 | {
158 | Client.DownloadFileAsync(new Uri(_map[0].BrowserDownloadUrl),
159 | ConfigurationManager.UpdateModsConfiguration.ModsDirectory + Path.DirectorySeparatorChar + _map[0].Name);
160 | }
161 | else
162 | {
163 | Message = "更新完毕";
164 | Client.DownloadFileCompleted -= Client_DownloadFileCompleted;
165 | }
166 | }
167 |
168 | private void DecompressFile(string filePath)
169 | {
170 | try
171 | {
172 | ZipFile.ExtractToDirectory(filePath, ConfigurationManager.UpdateModsConfiguration.ModsDirectory);
173 | }
174 | catch (Exception)
175 | {
176 | Message = "出现错误,请检查您的网络,并重新尝试。";
177 | if (File.Exists(filePath))
178 | File.Delete(filePath);
179 | return;
180 | }
181 | File.Delete(filePath);
182 | }
183 |
184 | private Task> _remoteMods;
185 |
186 | public ModsUpdateViewModel(ISnackbarMessageQueue messageQueue)
187 | {
188 | _snackbarMessQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue));
189 |
190 | _allItems = UpdateModItem.FromLocalModInfo(ServiceManager.LocalService.FromDirectory());
191 | ModItems = new ObservableCollection(_allItems);
192 |
193 | InitAsync();
194 | }
195 |
196 | public void InitAsync()
197 | {
198 | GithubService service = new GithubService(ConfigurationManager.UpdateModsConfiguration.Owner, ConfigurationManager.UpdateModsConfiguration.Repository);
199 | _remoteMods = service.GetLastestModsAsync();
200 | Message = "数据加载完成";
201 | }
202 |
203 | public event PropertyChangedEventHandler PropertyChanged;
204 |
205 | private readonly List _allItems;
206 |
207 | private ObservableCollection _modItems;
208 | public ObservableCollection ModItems
209 | {
210 | get => _modItems;
211 | private set
212 | {
213 | _modItems = value;
214 | OnPropertyChanged("ModItems");
215 | }
216 | }
217 |
218 | public void OnPropertyChanged([CallerMemberName]string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
219 | }
220 |
221 |
222 | public partial class UpdateModItem : INotifyPropertyChanged
223 | {
224 | private LocalModInfo _modInfo;
225 | public LocalModInfo ModInfo
226 | {
227 | get => _modInfo;
228 | set
229 | {
230 | _modInfo = value;
231 | OnPropertyChanged("ModInfo");
232 | }
233 | }
234 |
235 | private bool _isChecked;
236 | public bool IsChecked
237 | {
238 | get => _isChecked;
239 | set
240 | {
241 | _isChecked = value;
242 | OnPropertyChanged("IsChecked");
243 | }
244 | }
245 |
246 | private bool _canUpdate;
247 | public bool CanUpdate
248 | {
249 | get => _canUpdate;
250 | set
251 | {
252 | _canUpdate = value;
253 | OnPropertyChanged("CanUpdate");
254 | }
255 | }
256 |
257 | //private bool _visibility;
258 | //public bool Visibility
259 | //{
260 | // get => _visibility;
261 | // set
262 | // {
263 | // _visibility = value;
264 | // OnPropertyChanged("Visibility");
265 | // }
266 | //}
267 |
268 | public event PropertyChangedEventHandler PropertyChanged;
269 |
270 | public void OnPropertyChanged([CallerMemberName]string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
271 | }
272 |
273 | public partial class UpdateModItem
274 | {
275 | public static List FromLocalModInfo(List infos)
276 | {
277 | List items = new List();
278 | foreach (var i in infos)
279 | {
280 | items.Add(new UpdateModItem
281 | {
282 | ModInfo = i,
283 | IsChecked = false,
284 | CanUpdate = false
285 | });
286 | }
287 | return items;
288 | }
289 |
290 | public bool CheckUpdate(IEnumerable infos)
291 | {
292 | var it = infos.FirstOrDefault(v => v.Name.StartsWith(ModInfo.Id));
293 | if (it == default(RemoteModInfo))
294 | return false;
295 | if (it.Version != ModInfo.Version)
296 | return true;
297 | return false;
298 | }
299 | }
300 | }
301 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/AboutView.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
28 |
32 |
36 |
39 |
42 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
60 |
61 |
63 |
64 |
67 |
68 |
69 |
70 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/AboutView.xaml.cs:
--------------------------------------------------------------------------------
1 | using MahApps.Metro.Controls;
2 | using ModsUpdateUI.Configurations;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace ModsUpdateUI.Views
7 | {
8 | ///
9 | /// AboutView.xaml 的交互逻辑
10 | ///
11 | public partial class AboutView : MetroWindow
12 | {
13 | public AboutView()
14 | {
15 | InitializeComponent();
16 | DataContext = this;
17 | }
18 |
19 | public List Dependencies { get; set; } = ConfigurationManager.SoftwareInformation.Dependencies.ToList();
20 |
21 | public SoftwareInfo MataInfo { get; set; } = ConfigurationManager.SoftwareInformation;
22 |
23 | private void HomePageButton_Click(object sender, System.Windows.RoutedEventArgs e) => System.Diagnostics.Process.Start(MataInfo.HomePage.ToString());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsDownloadConfigView.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
41 |
42 |
43 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
56 |
57 |
58 |
59 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
70 |
72 |
76 |
77 |
78 |
80 |
82 |
86 |
87 |
88 |
90 |
92 |
97 |
98 |
99 |
101 |
104 |
108 |
109 |
113 |
114 |
119 |
120 |
121 |
122 |
126 |
127 |
132 |
133 |
134 |
135 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsDownloadConfigView.xaml.cs:
--------------------------------------------------------------------------------
1 | using MahApps.Metro.Controls;
2 | using System;
3 | using ModsUpdateUI.Configurations;
4 | using FolderBrowserDialog = System.Windows.Forms.FolderBrowserDialog;
5 | using System.IO;
6 |
7 | namespace ModsUpdateUI.Views
8 | {
9 | ///
10 | /// DownloadModsConfigView.xaml 的交互逻辑
11 | ///
12 | public partial class ModsDownloadConfigView : MetroWindow
13 | {
14 | public ModsDownloadConfigView()
15 | {
16 | InitializeComponent();
17 |
18 | Init();
19 | }
20 |
21 | public string ErrorMessage
22 | {
23 | set => AlertSnackbarMessage.Content = value;
24 | }
25 |
26 | private void Init()
27 | {
28 | DownloadModsConfig config = ConfigurationManager.DownloadModsConfiguration;
29 | DownloadDirTextBox.Text = config.DownloadDirectory;
30 | OwnerTextBox.Text = config.Owner;
31 | CodeRepoTextBox.Text = config.Repository;
32 | AutoDecompressTButton.IsChecked = config.IsAutoDecompress;
33 | DeleteFileTButton.IsChecked = config.IsDeleteFileWhenDecompress;
34 | }
35 |
36 | private void SaveButton_Click(object sender, System.Windows.RoutedEventArgs e)
37 | {
38 | if (!SetNewConfig())
39 | {
40 | AlertSnackbar.IsActive = true;
41 | return;
42 | }
43 | ConfigurationManager.SaveConfiguration(ConfigurationManager.DownloadModsConfiguration, Constants.DownloadModsConfigPath);
44 | AlertSnackbar.IsActive = true;
45 | }
46 |
47 | private bool SetNewConfig()
48 | {
49 | DownloadModsConfig config = ConfigurationManager.DownloadModsConfiguration;
50 | string path = DownloadDirTextBox.Text.Trim();
51 | if (!Directory.Exists(path))
52 | {
53 | ErrorMessage = "下载目录不存在,保存失败";
54 | return false;
55 | }
56 |
57 | config.DownloadDirectory = path;
58 | config.Owner = OwnerTextBox.Text.Trim();
59 | config.Repository = CodeRepoTextBox.Text.Trim();
60 | config.IsAutoDecompress = AutoDecompressTButton.IsChecked ?? false;
61 | config.IsDeleteFileWhenDecompress = DeleteFileTButton.IsChecked ?? true;
62 |
63 | ErrorMessage = "保存成功,部分设置可能需要下次启动生效";
64 | return true;
65 | }
66 |
67 | private void DownloadDirTextBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
68 | {
69 | FolderBrowserDialog folderDialog = new FolderBrowserDialog
70 | {
71 | ShowNewFolderButton = false,
72 | SelectedPath = AppDomain.CurrentDomain.BaseDirectory
73 | };
74 | System.Windows.Forms.DialogResult result = folderDialog.ShowDialog();
75 |
76 | if (result == System.Windows.Forms.DialogResult.OK)
77 | DownloadDirTextBox.Text = folderDialog.SelectedPath;
78 | }
79 |
80 | private void ApplyButton_Click(object sender, System.Windows.RoutedEventArgs e)
81 | {
82 | if (!SetNewConfig())
83 | {
84 | AlertSnackbar.IsActive = true;
85 | return;
86 | }
87 | }
88 |
89 | private void SnackbarMessage_ActionClick(object sender, System.Windows.RoutedEventArgs e) => AlertSnackbar.IsActive = false;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsDownloadView.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
36 |
42 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
65 |
69 |
70 |
82 |
83 |
84 |
85 |
86 |
87 |
95 |
96 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
155 |
156 |
163 |
164 |
178 |
179 |
180 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsDownloadView.xaml.cs:
--------------------------------------------------------------------------------
1 | using MahApps.Metro.Controls;
2 | using ModsUpdateUI.ViewModels;
3 | using System.Collections.Generic;
4 |
5 | namespace ModsUpdateUI.Views
6 | {
7 | ///
8 | /// ModsDownloadView.xaml 的交互逻辑
9 | ///
10 | public partial class ModsDownloadView : MetroWindow
11 | {
12 | public ModsDownloadView()
13 | {
14 | InitializeComponent();
15 |
16 | _model = new ModsDownloadViewModel(AlertSnackbar.MessageQueue);
17 | DataContext = _model;
18 | DataListView.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
19 | }
20 |
21 | private void ItemContainerGenerator_ItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e) => DataLoadedProgressBar.IsIndeterminate = false;
22 |
23 | private readonly ModsDownloadViewModel _model;
24 |
25 | private void AllModsButton_Click(object sender, System.Windows.RoutedEventArgs e) => _model.GetAll();
26 |
27 | private void UndownloadItemButton_Click(object sender, System.Windows.RoutedEventArgs e) => _model.GetUndownloaded();
28 |
29 | private void DownloadedItemButton_Click(object sender, System.Windows.RoutedEventArgs e) => _model.GetDownloaded();
30 |
31 | private async void DownloadButton_Click(object sender, System.Windows.RoutedEventArgs e)
32 | {
33 | List items = new List();
34 | foreach(var i in DataListView.SelectedItems)
35 | items.Add(i as DownloadModItem);
36 | _model.DownloadItems = items;
37 | await _model.DownloadAsync();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsUpdateConfigView.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
57 |
58 |
59 |
60 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
86 |
88 |
92 |
93 |
94 |
96 |
98 |
102 |
103 |
104 |
106 |
108 |
113 |
114 |
115 |
117 |
120 |
124 |
125 |
126 |
128 |
131 |
135 |
137 |
138 |
139 |
140 |
141 |
142 |
146 |
151 |
152 |
153 |
154 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsUpdateConfigView.xaml.cs:
--------------------------------------------------------------------------------
1 | using MahApps.Metro.Controls;
2 | using ModsUpdateUI.Configurations;
3 | using System;
4 | using System.IO;
5 | using FolderBrowserDialog = System.Windows.Forms.FolderBrowserDialog;
6 |
7 | namespace ModsUpdateUI.Views
8 | {
9 | ///
10 | /// UpdateModsConfigView.xaml 的交互逻辑
11 | ///
12 | public partial class ModsUpdateConfigView : MetroWindow
13 | {
14 | public ModsUpdateConfigView()
15 | {
16 | InitializeComponent();
17 | Init();
18 | }
19 |
20 | private void Init()
21 | {
22 | UpdateModsConfig config = ConfigurationManager.UpdateModsConfiguration;
23 | ModsDirTextBox.Text = config.ModsDirectory;
24 | OwnerTextBox.Text = config.Owner;
25 | CodeRepoTextBox.Text = config.Repository;
26 | MataInfoTextBox.Text = config.InfoFile;
27 | FileTypeCombpBox.Text = config.FileType;
28 | }
29 |
30 | private void ModsDirTextBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
31 | {
32 | FolderBrowserDialog folderDialog = new FolderBrowserDialog
33 | {
34 | ShowNewFolderButton = false,
35 | SelectedPath = AppDomain.CurrentDomain.BaseDirectory
36 | };
37 | System.Windows.Forms.DialogResult result = folderDialog.ShowDialog();
38 |
39 | if (result == System.Windows.Forms.DialogResult.OK)
40 | ModsDirTextBox.Text = folderDialog.SelectedPath;
41 | }
42 |
43 | private void SaveButton_Click(object sender, System.Windows.RoutedEventArgs e)
44 | {
45 | if(!SetNewConfig())
46 | {
47 | AlertSnackbar.IsActive = true;
48 | return;
49 | }
50 | ConfigurationManager.SaveConfiguration(ConfigurationManager.UpdateModsConfiguration, Constants.UpdateModsConfigPath);
51 | AlertSnackbar.IsActive = true;
52 | }
53 |
54 | private void ApplyButton_Click(object sender, System.Windows.RoutedEventArgs e)
55 | {
56 | if (!SetNewConfig())
57 | {
58 | AlertSnackbar.IsActive = true;
59 | return;
60 | }
61 | }
62 |
63 | private bool SetNewConfig()
64 | {
65 | UpdateModsConfig config = ConfigurationManager.UpdateModsConfiguration;
66 | string path = ModsDirTextBox.Text.Trim();
67 | if(!Directory.Exists(path))
68 | {
69 | AlertSnackbarMessage.Content = "Mods文件夹不存在,保存失败";
70 | return false;
71 | }
72 |
73 | config.ModsDirectory = path;
74 | config.Owner = OwnerTextBox.Text.Trim();
75 | config.Repository = CodeRepoTextBox.Text.Trim();
76 | config.InfoFile = MataInfoTextBox.Text.Trim();
77 | config.FileType = FileTypeCombpBox.Text.Trim();
78 |
79 | AlertSnackbarMessage.Content = "保存成功";
80 | return true;
81 | }
82 |
83 | private void SnackbarMessage_ActionClick(object sender, System.Windows.RoutedEventArgs e) => AlertSnackbar.IsActive = false;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsUpdateView.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
30 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
49 |
50 |
62 |
63 |
64 |
65 |
66 |
67 |
75 |
76 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
139 |
140 |
147 |
148 |
162 |
163 |
164 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
--------------------------------------------------------------------------------
/ModsUpdateUI/Views/ModsUpdateView.xaml.cs:
--------------------------------------------------------------------------------
1 | using MahApps.Metro.Controls;
2 | using ModsUpdateUI.ViewModels;
3 | using System.Collections.Generic;
4 | using System.Windows;
5 |
6 | namespace ModsUpdateUI.Views
7 | {
8 | ///
9 | /// ModsUpdateView.xaml 的交互逻辑
10 | ///
11 | public partial class ModsUpdateView : MetroWindow
12 | {
13 | public ModsUpdateView()
14 | {
15 | InitializeComponent();
16 |
17 | _model = new ModsUpdateViewModel(AlertSnackbar.MessageQueue);
18 | DataContext = _model;
19 | DataListView.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
20 | }
21 |
22 | private void ItemContainerGenerator_ItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e) => _model.CheckUpdateAsync();
23 |
24 | private readonly ModsUpdateViewModel _model;
25 |
26 | private void UpdatableModsButton_Click(object sender, RoutedEventArgs e) => _model.GetUpdatableMods();
27 |
28 | private void AllModsButton_Click(object sender, RoutedEventArgs e) => _model.GetAllMods();
29 |
30 | private async void UpdateButton_Click(object sender, RoutedEventArgs e)
31 | {
32 | List items = new List();
33 | foreach(var it in DataListView.SelectedItems)
34 | {
35 | UpdateModItem item = it as UpdateModItem;
36 | if (!item.CanUpdate)
37 | continue;
38 | items.Add(item);
39 | }
40 | _model.UpdateItems = items;
41 | await _model.UpdateAsync();
42 | }
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/ModsUpdateUI/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ModsUpdateUI
2 |
3 | ## 编译及依赖
4 |
5 | 使用 Visual Studio 2017+ 打开ModsUpdateUI.sln, 编译
6 |
7 | C# 7.1+
8 |
9 | ### 依赖
10 |
11 | framework版本
12 |
13 | .Net Framework 4.6.1+
14 |
15 | 包依赖:
16 |
17 | MahApps.Metro 1.6.5+
18 |
19 | MaterialDesignColors 1.1.3+
20 |
21 | MaterialDesignThemes 2.5.0.1205+
22 |
23 | Newtonsoft.Json 12.0.1+
24 |
25 | Octokit 0.32.0+
26 |
27 | ShellProgressBar (Optional)
28 |
29 | ## License
30 |
31 | [MIT](LICENSE)
32 |
--------------------------------------------------------------------------------