mirror of https://github.com/2dust/v2rayN
Refactor check updates
parent
d6ca317b20
commit
f0d05a7d4e
|
@ -168,6 +168,10 @@ namespace ServiceLib.Common
|
||||||
{
|
{
|
||||||
progress.Report(101);
|
progress.Report(101);
|
||||||
}
|
}
|
||||||
|
else if (value.Error != null)
|
||||||
|
{
|
||||||
|
throw value.Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,5 +38,7 @@
|
||||||
DispatcherReload,
|
DispatcherReload,
|
||||||
DispatcherRefreshServersBiz,
|
DispatcherRefreshServersBiz,
|
||||||
DispatcherRefreshIcon,
|
DispatcherRefreshIcon,
|
||||||
|
DispatcherCheckUpdate,
|
||||||
|
DispatcherCheckUpdateFinished,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -50,6 +50,7 @@ namespace ServiceLib.Handler
|
||||||
downloadHandle.Error += (sender2, args) =>
|
downloadHandle.Error += (sender2, args) =>
|
||||||
{
|
{
|
||||||
_updateFunc(false, args.GetException().Message);
|
_updateFunc(false, args.GetException().Message);
|
||||||
|
_updateFunc(false, "");
|
||||||
};
|
};
|
||||||
AbsoluteCompleted += (sender2, args) =>
|
AbsoluteCompleted += (sender2, args) =>
|
||||||
{
|
{
|
||||||
|
@ -61,19 +62,20 @@ namespace ServiceLib.Handler
|
||||||
url = args.Url;
|
url = args.Url;
|
||||||
AskToDownload(downloadHandle, url, true).ContinueWith(task =>
|
AskToDownload(downloadHandle, url, true).ContinueWith(task =>
|
||||||
{
|
{
|
||||||
_updateFunc(false, url);
|
_updateFunc(false, "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_updateFunc(false, args.Msg);
|
_updateFunc(false, args.Msg);
|
||||||
|
_updateFunc(false, "");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_updateFunc(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN));
|
_updateFunc(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN));
|
||||||
CheckUpdateAsync(ECoreType.v2rayN, preRelease);
|
CheckUpdateAsync(downloadHandle, ECoreType.v2rayN, preRelease);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckUpdateCore(ECoreType type, Config config, Action<bool, string> update, bool preRelease)
|
public async void CheckUpdateCore(ECoreType type, Config config, Action<bool, string> update, bool preRelease)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_updateFunc = update;
|
_updateFunc = update;
|
||||||
|
@ -103,7 +105,8 @@ namespace ServiceLib.Handler
|
||||||
};
|
};
|
||||||
downloadHandle.Error += (sender2, args) =>
|
downloadHandle.Error += (sender2, args) =>
|
||||||
{
|
{
|
||||||
_updateFunc(true, args.GetException().Message);
|
_updateFunc(false, args.GetException().Message);
|
||||||
|
_updateFunc(false, "");
|
||||||
};
|
};
|
||||||
|
|
||||||
AbsoluteCompleted += (sender2, args) =>
|
AbsoluteCompleted += (sender2, args) =>
|
||||||
|
@ -116,16 +119,17 @@ namespace ServiceLib.Handler
|
||||||
url = args.Url;
|
url = args.Url;
|
||||||
AskToDownload(downloadHandle, url, true).ContinueWith(task =>
|
AskToDownload(downloadHandle, url, true).ContinueWith(task =>
|
||||||
{
|
{
|
||||||
_updateFunc(false, url);
|
_updateFunc(false, "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_updateFunc(false, args.Msg);
|
_updateFunc(false, args.Msg);
|
||||||
|
_updateFunc(false, "");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_updateFunc(false, string.Format(ResUI.MsgStartUpdating, type));
|
_updateFunc(false, string.Format(ResUI.MsgStartUpdating, type));
|
||||||
CheckUpdateAsync(type, preRelease);
|
CheckUpdateAsync(downloadHandle, type, preRelease);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> update)
|
public void UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> update)
|
||||||
|
@ -267,6 +271,7 @@ namespace ServiceLib.Handler
|
||||||
{
|
{
|
||||||
await UpdateGeoFile("geosite", _config, update);
|
await UpdateGeoFile("geosite", _config, update);
|
||||||
await UpdateGeoFile("geoip", _config, update);
|
await UpdateGeoFile("geoip", _config, update);
|
||||||
|
_updateFunc(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,14 +287,14 @@ namespace ServiceLib.Handler
|
||||||
|
|
||||||
#region private
|
#region private
|
||||||
|
|
||||||
private async void CheckUpdateAsync(ECoreType type, bool preRelease)
|
private async void CheckUpdateAsync(DownloadHandler downloadHandle, ECoreType type, bool preRelease)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
||||||
string url = coreInfo.coreReleaseApiUrl;
|
string url = coreInfo.coreReleaseApiUrl;
|
||||||
|
|
||||||
var result = await (new DownloadHandler()).DownloadStringAsync(url, true, Global.AppName);
|
var result = await downloadHandle.DownloadStringAsync(url, true, Global.AppName);
|
||||||
if (!Utils.IsNullOrEmpty(result))
|
if (!Utils.IsNullOrEmpty(result))
|
||||||
{
|
{
|
||||||
ResponseHandler(type, result, preRelease);
|
ResponseHandler(type, result, preRelease);
|
||||||
|
@ -483,7 +488,7 @@ namespace ServiceLib.Handler
|
||||||
//}
|
//}
|
||||||
//if (blDownload)
|
//if (blDownload)
|
||||||
//{
|
//{
|
||||||
await downloadHandle.DownloadFileAsync(url, true, 600);
|
await downloadHandle.DownloadFileAsync(url, true, 60);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ServiceLib.Models
|
||||||
|
{
|
||||||
|
public class CheckUpdateItem
|
||||||
|
{
|
||||||
|
public bool? isSelected { get; set; }
|
||||||
|
public string coreType { get; set; }
|
||||||
|
public string? remarks { get; set; }
|
||||||
|
public string? fileName { get; set; }
|
||||||
|
public bool? isFinished { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,323 @@
|
||||||
|
using DynamicData;
|
||||||
|
using DynamicData.Binding;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
using Splat;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reactive;
|
||||||
|
|
||||||
|
namespace ServiceLib.ViewModels
|
||||||
|
{
|
||||||
|
public class CheckUpdateViewModel : MyReactiveObject
|
||||||
|
{
|
||||||
|
private const string _geo = "GeoFiles";
|
||||||
|
private List<CheckUpdateItem> _lstUpdated = [];
|
||||||
|
|
||||||
|
private IObservableCollection<CheckUpdateItem> _checkUpdateItem = new ObservableCollectionExtended<CheckUpdateItem>();
|
||||||
|
public IObservableCollection<CheckUpdateItem> CheckUpdateItems => _checkUpdateItem;
|
||||||
|
public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }
|
||||||
|
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
||||||
|
[Reactive] public bool IsCheckUpdate { get; set; }
|
||||||
|
[Reactive] public bool AutoRun { get; set; }
|
||||||
|
|
||||||
|
public CheckUpdateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||||
|
{
|
||||||
|
_config = LazyConfig.Instance.Config;
|
||||||
|
_updateView = updateView;
|
||||||
|
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
|
||||||
|
|
||||||
|
RefreshSubItems();
|
||||||
|
|
||||||
|
CheckUpdateCmd = ReactiveCommand.Create(() =>
|
||||||
|
{
|
||||||
|
CheckUpdate();
|
||||||
|
});
|
||||||
|
EnableCheckPreReleaseUpdate = _config.guiItem.checkPreReleaseUpdate;
|
||||||
|
IsCheckUpdate = true;
|
||||||
|
|
||||||
|
this.WhenAnyValue(
|
||||||
|
x => x.EnableCheckPreReleaseUpdate,
|
||||||
|
y => y == true)
|
||||||
|
.Subscribe(c => { _config.guiItem.checkPreReleaseUpdate = EnableCheckPreReleaseUpdate; });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshSubItems()
|
||||||
|
{
|
||||||
|
_checkUpdateItem.Clear();
|
||||||
|
|
||||||
|
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||||
|
{
|
||||||
|
isSelected = false,
|
||||||
|
coreType = ECoreType.v2rayN.ToString(),
|
||||||
|
remarks = ResUI.menuCheckUpdate,
|
||||||
|
});
|
||||||
|
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||||
|
{
|
||||||
|
isSelected = true,
|
||||||
|
coreType = ECoreType.Xray.ToString(),
|
||||||
|
remarks = ResUI.menuCheckUpdate,
|
||||||
|
});
|
||||||
|
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||||
|
{
|
||||||
|
isSelected = true,
|
||||||
|
coreType = ECoreType.mihomo.ToString(),
|
||||||
|
remarks = ResUI.menuCheckUpdate,
|
||||||
|
});
|
||||||
|
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||||
|
{
|
||||||
|
isSelected = true,
|
||||||
|
coreType = ECoreType.sing_box.ToString(),
|
||||||
|
remarks = ResUI.menuCheckUpdate,
|
||||||
|
});
|
||||||
|
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||||
|
{
|
||||||
|
isSelected = true,
|
||||||
|
coreType = _geo,
|
||||||
|
remarks = ResUI.menuCheckUpdate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckUpdate()
|
||||||
|
{
|
||||||
|
_lstUpdated.Clear();
|
||||||
|
|
||||||
|
for (int k = _checkUpdateItem.Count - 1; k >= 0; k--)
|
||||||
|
{
|
||||||
|
var item = _checkUpdateItem[k];
|
||||||
|
if (item.isSelected == true)
|
||||||
|
{
|
||||||
|
IsCheckUpdate = false;
|
||||||
|
_lstUpdated.Add(new CheckUpdateItem() { coreType = item.coreType });
|
||||||
|
UpdateView(item.coreType, "...");
|
||||||
|
if (item.coreType == _geo)
|
||||||
|
{
|
||||||
|
CheckUpdateGeo();
|
||||||
|
}
|
||||||
|
else if (item.coreType == ECoreType.v2rayN.ToString())
|
||||||
|
{
|
||||||
|
CheckUpdateN(EnableCheckPreReleaseUpdate);
|
||||||
|
}
|
||||||
|
else if (item.coreType == ECoreType.mihomo.ToString())
|
||||||
|
{
|
||||||
|
CheckUpdateCore(item, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatedPlusPlus(string coreType, string fileName)
|
||||||
|
{
|
||||||
|
var item = _lstUpdated.FirstOrDefault(x => x.coreType == coreType);
|
||||||
|
if (item == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item.isFinished = true;
|
||||||
|
if (!fileName.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
item.fileName = fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckUpdateGeo()
|
||||||
|
{
|
||||||
|
void _updateUI(bool success, string msg)
|
||||||
|
{
|
||||||
|
UpdateView(_geo, msg);
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
UpdatedPlusPlus(_geo, "");
|
||||||
|
UpdateFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(new UpdateHandler()).UpdateGeoFileAll(_config, _updateUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckUpdateN(bool preRelease)
|
||||||
|
{
|
||||||
|
//Check for standalone windows .Net version
|
||||||
|
if (Utils.IsWindows()
|
||||||
|
&& File.Exists(Path.Combine(Utils.StartupPath(), "wpfgfx_cor3.dll"))
|
||||||
|
&& File.Exists(Path.Combine(Utils.StartupPath(), "D3DCompiler_47_cor3.dll"))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UpdateView(ResUI.UpdateStandalonePackageTip, ResUI.UpdateStandalonePackageTip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateUI(bool success, string msg)
|
||||||
|
{
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
UpdateView(ECoreType.v2rayN.ToString(), ResUI.OperationSuccess);
|
||||||
|
UpdatedPlusPlus(ECoreType.v2rayN.ToString(), msg);
|
||||||
|
UpdateFinished();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msg.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
UpdatedPlusPlus(ECoreType.v2rayN.ToString(), "");
|
||||||
|
UpdateFinished();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateView(ECoreType.v2rayN.ToString(), msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(new UpdateHandler()).CheckUpdateGuiN(_config, _updateUI, preRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckUpdateCore(CheckUpdateItem item, bool preRelease)
|
||||||
|
{
|
||||||
|
void _updateUI(bool success, string msg)
|
||||||
|
{
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
UpdateView(item.coreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
|
||||||
|
|
||||||
|
UpdatedPlusPlus(item.coreType, msg);
|
||||||
|
UpdateFinished();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msg.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
UpdatedPlusPlus(item.coreType, "");
|
||||||
|
UpdateFinished();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateView(item.coreType, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var type = (ECoreType)Enum.Parse(typeof(ECoreType), item.coreType);
|
||||||
|
(new UpdateHandler()).CheckUpdateCore(type, _config, _updateUI, preRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateFinished()
|
||||||
|
{
|
||||||
|
if (_lstUpdated.Count > 0 && _lstUpdated.Count(x => x.isFinished == true) == _lstUpdated.Count)
|
||||||
|
{
|
||||||
|
_updateView?.Invoke(EViewAction.DispatcherCheckUpdateFinished, false);
|
||||||
|
|
||||||
|
UpgradeCore();
|
||||||
|
|
||||||
|
if (_lstUpdated.Any(x => x.coreType == ECoreType.v2rayN.ToString() && x.isFinished == true))
|
||||||
|
{
|
||||||
|
UpgradeN();
|
||||||
|
}
|
||||||
|
_updateView?.Invoke(EViewAction.DispatcherCheckUpdateFinished, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateFinishedResult(bool blReload)
|
||||||
|
{
|
||||||
|
if (blReload)
|
||||||
|
{
|
||||||
|
IsCheckUpdate = true;
|
||||||
|
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Locator.Current.GetService<MainWindowViewModel>()?.CloseCore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeN()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fileName = _lstUpdated.FirstOrDefault(x => x.coreType == ECoreType.v2rayN.ToString())?.fileName;
|
||||||
|
if (fileName.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process process = new()
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "v2rayUpgrade",
|
||||||
|
Arguments = fileName.AppendQuotes(),
|
||||||
|
WorkingDirectory = Utils.StartupPath()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
process.Start();
|
||||||
|
if (process.Id > 0)
|
||||||
|
{
|
||||||
|
Locator.Current.GetService<MainWindowViewModel>()?.MyAppExitAsync(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
UpdateView(ECoreType.v2rayN.ToString(), ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpgradeCore()
|
||||||
|
{
|
||||||
|
foreach (var item in _lstUpdated)
|
||||||
|
{
|
||||||
|
if (item.fileName.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileName = Utils.GetTempPath(Utils.GetDownloadFileName(item.fileName));
|
||||||
|
if (!File.Exists(fileName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string toPath = Utils.GetBinPath("", item.coreType);
|
||||||
|
|
||||||
|
if (fileName.Contains(".tar.gz"))
|
||||||
|
{
|
||||||
|
//It's too complicated to unzip. TODO
|
||||||
|
}
|
||||||
|
else if (fileName.Contains(".gz"))
|
||||||
|
{
|
||||||
|
FileManager.UncompressedFile(fileName, toPath, item.coreType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileManager.ZipExtractToFile(fileName, toPath, _config.guiItem.ignoreGeoUpdateCore ? "geo" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateView(item.coreType, ResUI.MsgUpdateV2rayCoreSuccessfully);
|
||||||
|
|
||||||
|
if (File.Exists(fileName))
|
||||||
|
{
|
||||||
|
File.Delete(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateView(string coreType, string msg)
|
||||||
|
{
|
||||||
|
var item = new CheckUpdateItem()
|
||||||
|
{
|
||||||
|
coreType = coreType,
|
||||||
|
remarks = msg,
|
||||||
|
};
|
||||||
|
_updateView?.Invoke(EViewAction.DispatcherCheckUpdate, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateViewResult(CheckUpdateItem item)
|
||||||
|
{
|
||||||
|
var found = _checkUpdateItem.FirstOrDefault(t => t.coreType == item.coreType);
|
||||||
|
if (found != null)
|
||||||
|
{
|
||||||
|
var itemCopy = JsonUtils.DeepCopy(found);
|
||||||
|
itemCopy.remarks = item.remarks;
|
||||||
|
_checkUpdateItem.Replace(found, itemCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -852,7 +852,7 @@ namespace ServiceLib.ViewModels
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CloseCore()
|
public void CloseCore()
|
||||||
{
|
{
|
||||||
ConfigHandler.SaveConfig(_config, false);
|
ConfigHandler.SaveConfig(_config, false);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
<reactiveui:ReactiveUserControl
|
||||||
|
x:Class="v2rayN.Views.CheckUpdateView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
|
d:DesignHeight="450"
|
||||||
|
d:DesignWidth="800"
|
||||||
|
x:TypeArguments="vms:CheckUpdateViewModel"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<DockPanel Margin="16">
|
||||||
|
<StackPanel
|
||||||
|
Margin="8"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
DockPanel.Dock="Bottom"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="9"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource SettingItemMargin}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsEnableCheckPreReleaseUpdate}" />
|
||||||
|
<ToggleButton
|
||||||
|
x:Name="togEnableCheckPreReleaseUpdate"
|
||||||
|
Grid.Row="9"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="{StaticResource SettingItemMargin}"
|
||||||
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
x:Name="btnCheckUpdate"
|
||||||
|
Grid.Row="2"
|
||||||
|
Width="100"
|
||||||
|
Margin="8"
|
||||||
|
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
|
||||||
|
Content="{x:Static resx:ResUI.menuCheckUpdate}"
|
||||||
|
IsCancel="True"
|
||||||
|
IsDefault="True"
|
||||||
|
Style="{StaticResource MaterialDesignFlatButton}" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
Grid.Row="2"
|
||||||
|
Width="100"
|
||||||
|
Margin="8"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
|
||||||
|
Content="{x:Static resx:ResUI.menuClose}"
|
||||||
|
IsCancel="True"
|
||||||
|
IsDefault="True"
|
||||||
|
Style="{StaticResource MaterialDesignFlatButton}" />
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel>
|
||||||
|
<ListView
|
||||||
|
x:Name="lstCheckUpdates"
|
||||||
|
BorderThickness="1"
|
||||||
|
ItemContainerStyle="{StaticResource lvItemSelected}">
|
||||||
|
<ListView.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Vertical" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListView.ItemsPanel>
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Border
|
||||||
|
Width="500"
|
||||||
|
Height="50"
|
||||||
|
Margin="8"
|
||||||
|
Padding="0"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="1*" />
|
||||||
|
<ColumnDefinition Width="1*" />
|
||||||
|
<ColumnDefinition Width="3*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ToggleButton
|
||||||
|
x:Name="togAutoRefresh"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="8"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
IsChecked="{Binding isSelected}" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="1"
|
||||||
|
Style="{StaticResource ListItemTitle}"
|
||||||
|
Text="{Binding coreType}" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="2"
|
||||||
|
Style="{StaticResource ListItemSubTitle}"
|
||||||
|
Text="{Binding remarks}"
|
||||||
|
TextWrapping="WrapWithOverflow" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
|
</reactiveui:ReactiveUserControl>
|
|
@ -0,0 +1,50 @@
|
||||||
|
using ReactiveUI;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace v2rayN.Views
|
||||||
|
{
|
||||||
|
public partial class CheckUpdateView
|
||||||
|
{
|
||||||
|
public CheckUpdateView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
ViewModel = new CheckUpdateViewModel(UpdateViewHandler);
|
||||||
|
|
||||||
|
this.WhenActivated(disposables =>
|
||||||
|
{
|
||||||
|
this.OneWayBind(ViewModel, vm => vm.CheckUpdateItems, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
||||||
|
|
||||||
|
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||||
|
this.OneWayBind(ViewModel, vm => vm.IsCheckUpdate, v => v.btnCheckUpdate.IsEnabled).DisposeWith(disposables);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case EViewAction.DispatcherCheckUpdate:
|
||||||
|
if (obj is null) return false;
|
||||||
|
Application.Current?.Dispatcher.Invoke((() =>
|
||||||
|
{
|
||||||
|
ViewModel?.UpdateViewResult((CheckUpdateItem)obj);
|
||||||
|
}), DispatcherPriority.Normal);
|
||||||
|
break;
|
||||||
|
case EViewAction.DispatcherCheckUpdateFinished:
|
||||||
|
if (obj is null) return false;
|
||||||
|
Application.Current?.Dispatcher.Invoke((() =>
|
||||||
|
{
|
||||||
|
ViewModel?.UpdateFinishedResult((bool)obj);
|
||||||
|
}), DispatcherPriority.Normal);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return await Task.FromResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -212,7 +212,7 @@
|
||||||
</Menu>
|
</Menu>
|
||||||
<Separator />
|
<Separator />
|
||||||
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
|
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
|
||||||
<MenuItem Padding="8,0">
|
<MenuItem Name="menuCheckUpdate" Padding="8,0">
|
||||||
<MenuItem.Header>
|
<MenuItem.Header>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<materialDesign:PackIcon
|
<materialDesign:PackIcon
|
||||||
|
@ -222,27 +222,6 @@
|
||||||
<TextBlock Text="{x:Static resx:ResUI.menuCheckUpdate}" />
|
<TextBlock Text="{x:Static resx:ResUI.menuCheckUpdate}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</MenuItem.Header>
|
</MenuItem.Header>
|
||||||
<MenuItem
|
|
||||||
x:Name="menuCheckUpdateN"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="V2rayN" />
|
|
||||||
<MenuItem
|
|
||||||
x:Name="menuCheckUpdateXrayCore"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="Xray Core" />
|
|
||||||
<MenuItem
|
|
||||||
x:Name="menuCheckUpdateMihomoCore"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="Mihomo Core" />
|
|
||||||
<MenuItem
|
|
||||||
x:Name="menuCheckUpdateSingBoxCore"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="Sing-box Core" />
|
|
||||||
<Separator Margin="-40,5" />
|
|
||||||
<MenuItem
|
|
||||||
x:Name="menuCheckUpdateGeo"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="Geo files" />
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ReactiveUI;
|
using MaterialDesignThemes.Wpf;
|
||||||
|
using ReactiveUI;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
@ -15,6 +16,7 @@ namespace v2rayN.Views
|
||||||
public partial class MainWindow
|
public partial class MainWindow
|
||||||
{
|
{
|
||||||
private static Config _config;
|
private static Config _config;
|
||||||
|
private CheckUpdateView? _checkUpdateView;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
|
@ -30,6 +32,7 @@ namespace v2rayN.Views
|
||||||
menuPromotion.Click += menuPromotion_Click;
|
menuPromotion.Click += menuPromotion_Click;
|
||||||
menuClose.Click += menuClose_Click;
|
menuClose.Click += menuClose_Click;
|
||||||
menuExit.Click += menuExit_Click;
|
menuExit.Click += menuExit_Click;
|
||||||
|
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||||
|
|
||||||
MessageBus.Current.Listen<string>(Global.CommandSendSnackMsg).Subscribe(x => DelegateSnackMsg(x));
|
MessageBus.Current.Listen<string>(Global.CommandSendSnackMsg).Subscribe(x => DelegateSnackMsg(x));
|
||||||
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
||||||
|
@ -71,11 +74,11 @@ namespace v2rayN.Views
|
||||||
//this.BindCommand(ViewModel, vm => vm.ImportOldGuiConfigCmd, v => v.menuImportOldGuiConfig).DisposeWith(disposables);
|
//this.BindCommand(ViewModel, vm => vm.ImportOldGuiConfigCmd, v => v.menuImportOldGuiConfig).DisposeWith(disposables);
|
||||||
|
|
||||||
//check update
|
//check update
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateNCmd, v => v.menuCheckUpdateN).DisposeWith(disposables);
|
//this.BindCommand(ViewModel, vm => vm.CheckUpdateNCmd, v => v.menuCheckUpdateN).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateXrayCoreCmd, v => v.menuCheckUpdateXrayCore).DisposeWith(disposables);
|
//this.BindCommand(ViewModel, vm => vm.CheckUpdateXrayCoreCmd, v => v.menuCheckUpdateXrayCore).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateClashMetaCoreCmd, v => v.menuCheckUpdateMihomoCore).DisposeWith(disposables);
|
//this.BindCommand(ViewModel, vm => vm.CheckUpdateClashMetaCoreCmd, v => v.menuCheckUpdateMihomoCore).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateSingBoxCoreCmd, v => v.menuCheckUpdateSingBoxCore).DisposeWith(disposables);
|
//this.BindCommand(ViewModel, vm => vm.CheckUpdateSingBoxCoreCmd, v => v.menuCheckUpdateSingBoxCore).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateGeoCmd, v => v.menuCheckUpdateGeo).DisposeWith(disposables);
|
//this.BindCommand(ViewModel, vm => vm.CheckUpdateGeoCmd, v => v.menuCheckUpdateGeo).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
||||||
|
@ -193,6 +196,12 @@ namespace v2rayN.Views
|
||||||
AddHelpMenuItem();
|
AddHelpMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MenuCheckUpdate_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_checkUpdateView ??= new CheckUpdateView();
|
||||||
|
DialogHost.Show(_checkUpdateView, "RootDialog");
|
||||||
|
}
|
||||||
|
|
||||||
#region Event
|
#region Event
|
||||||
|
|
||||||
private void OnProgramStarted(object state, bool timeout)
|
private void OnProgramStarted(object state, bool timeout)
|
||||||
|
@ -297,6 +306,7 @@ namespace v2rayN.Views
|
||||||
var clipboardData = WindowsUtils.GetClipboardData();
|
var clipboardData = WindowsUtils.GetClipboardData();
|
||||||
ViewModel?.AddServerViaClipboardAsync(clipboardData);
|
ViewModel?.AddServerViaClipboardAsync(clipboardData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.AdjustMainLvColWidth:
|
case EViewAction.AdjustMainLvColWidth:
|
||||||
Application.Current?.Dispatcher.Invoke((() =>
|
Application.Current?.Dispatcher.Invoke((() =>
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue