v2rayN/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs

306 lines
10 KiB
C#
Raw Normal View History

2024-09-01 08:39:45 +00:00
using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.Reactive;
namespace ServiceLib.ViewModels
{
public class CheckUpdateViewModel : MyReactiveObject
{
private const string _geo = "GeoFiles";
2024-09-06 01:40:45 +00:00
private string _v2rayN = ECoreType.v2rayN.ToString();
2024-09-01 08:39:45 +00:00
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; }
public CheckUpdateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
2024-10-07 01:51:41 +00:00
_config = AppHandler.Instance.Config;
2024-09-01 08:39:45 +00:00
_updateView = updateView;
2024-09-04 07:47:17 +00:00
CheckUpdateCmd = ReactiveCommand.CreateFromTask(async () =>
2024-09-01 08:39:45 +00:00
{
2024-10-21 05:46:13 +00:00
await CheckUpdate();
2024-09-01 08:39:45 +00:00
});
2024-10-21 05:46:13 +00:00
EnableCheckPreReleaseUpdate = _config.GuiItem.CheckPreReleaseUpdate;
2024-09-01 08:39:45 +00:00
this.WhenAnyValue(
x => x.EnableCheckPreReleaseUpdate,
y => y == true)
.Subscribe(c => { _config.GuiItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate; });
2024-10-21 05:46:13 +00:00
RefreshSubItems();
2024-09-01 08:39:45 +00:00
}
private void RefreshSubItems()
{
_checkUpdateItem.Clear();
_checkUpdateItem.Add(new CheckUpdateItem()
{
2024-10-07 12:10:00 +00:00
IsSelected = false,
CoreType = _v2rayN,
Remarks = ResUI.menuCheckUpdate,
2024-09-01 08:39:45 +00:00
});
_checkUpdateItem.Add(new CheckUpdateItem()
{
2024-10-07 12:10:00 +00:00
IsSelected = true,
CoreType = ECoreType.Xray.ToString(),
Remarks = ResUI.menuCheckUpdate,
2024-09-01 08:39:45 +00:00
});
_checkUpdateItem.Add(new CheckUpdateItem()
{
2024-10-07 12:10:00 +00:00
IsSelected = true,
CoreType = ECoreType.mihomo.ToString(),
Remarks = ResUI.menuCheckUpdate,
2024-09-01 08:39:45 +00:00
});
2024-10-17 07:28:32 +00:00
_checkUpdateItem.Add(new CheckUpdateItem()
2024-09-01 08:39:45 +00:00
{
2024-10-17 07:28:32 +00:00
IsSelected = true,
CoreType = ECoreType.sing_box.ToString(),
Remarks = ResUI.menuCheckUpdate,
});
2024-09-01 08:39:45 +00:00
_checkUpdateItem.Add(new CheckUpdateItem()
{
2024-10-07 12:10:00 +00:00
IsSelected = true,
CoreType = _geo,
Remarks = ResUI.menuCheckUpdate,
2024-09-01 08:39:45 +00:00
});
}
2024-09-04 07:47:17 +00:00
private async Task CheckUpdate()
2024-09-01 08:39:45 +00:00
{
_lstUpdated.Clear();
2024-10-07 12:10:00 +00:00
_lstUpdated = _checkUpdateItem.Where(x => x.IsSelected == true)
.Select(x => new CheckUpdateItem() { CoreType = x.CoreType }).ToList();
2024-09-01 08:39:45 +00:00
2024-10-21 05:46:13 +00:00
for (var k = _checkUpdateItem.Count - 1; k >= 0; k--)
2024-09-01 08:39:45 +00:00
{
var item = _checkUpdateItem[k];
2024-10-21 05:46:13 +00:00
if (item.IsSelected != true) continue;
UpdateView(item.CoreType, "...");
if (item.CoreType == _geo)
{
await CheckUpdateGeo();
}
else if (item.CoreType == _v2rayN)
{
await CheckUpdateN(EnableCheckPreReleaseUpdate);
}
else if (item.CoreType == ECoreType.mihomo.ToString())
{
await CheckUpdateCore(item, false);
}
else
2024-09-01 08:39:45 +00:00
{
2024-10-21 05:46:13 +00:00
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
2024-09-01 08:39:45 +00:00
}
}
2024-10-21 05:46:13 +00:00
await UpdateFinished();
2024-09-01 08:39:45 +00:00
}
private void UpdatedPlusPlus(string coreType, string fileName)
{
2024-10-07 12:10:00 +00:00
var item = _lstUpdated.FirstOrDefault(x => x.CoreType == coreType);
2024-09-01 08:39:45 +00:00
if (item == null)
{
return;
}
2024-10-07 12:10:00 +00:00
item.IsFinished = true;
2024-09-01 08:39:45 +00:00
if (!fileName.IsNullOrEmpty())
{
2024-10-07 12:10:00 +00:00
item.FileName = fileName;
2024-09-01 08:39:45 +00:00
}
}
2024-09-04 07:47:17 +00:00
private async Task CheckUpdateGeo()
2024-09-01 08:39:45 +00:00
{
void _updateUI(bool success, string msg)
{
UpdateView(_geo, msg);
if (success)
{
UpdatedPlusPlus(_geo, "");
}
}
2024-10-07 02:39:43 +00:00
await (new UpdateService()).UpdateGeoFileAll(_config, _updateUI)
2024-09-04 07:47:17 +00:00
.ContinueWith(t =>
{
UpdatedPlusPlus(_geo, "");
});
2024-09-01 08:39:45 +00:00
}
2024-09-04 07:47:17 +00:00
private async Task CheckUpdateN(bool preRelease)
2024-09-01 08:39:45 +00:00
{
void _updateUI(bool success, string msg)
{
2024-09-06 01:40:45 +00:00
UpdateView(_v2rayN, msg);
2024-09-01 08:39:45 +00:00
if (success)
{
2024-09-06 01:40:45 +00:00
UpdateView(_v2rayN, ResUI.OperationSuccess);
UpdatedPlusPlus(_v2rayN, msg);
2024-09-01 08:39:45 +00:00
}
}
2024-10-07 02:39:43 +00:00
await (new UpdateService()).CheckUpdateGuiN(_config, _updateUI, preRelease)
2024-09-04 07:47:17 +00:00
.ContinueWith(t =>
{
2024-09-06 01:40:45 +00:00
UpdatedPlusPlus(_v2rayN, "");
2024-09-04 07:47:17 +00:00
});
2024-09-01 08:39:45 +00:00
}
2024-09-04 07:47:17 +00:00
private async Task CheckUpdateCore(CheckUpdateItem item, bool preRelease)
2024-09-01 08:39:45 +00:00
{
void _updateUI(bool success, string msg)
{
2024-10-07 12:10:00 +00:00
UpdateView(item.CoreType, msg);
2024-09-01 08:39:45 +00:00
if (success)
{
2024-10-07 12:10:00 +00:00
UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
2024-09-01 08:39:45 +00:00
2024-10-07 12:10:00 +00:00
UpdatedPlusPlus(item.CoreType, msg);
2024-09-01 08:39:45 +00:00
}
}
2024-10-07 12:10:00 +00:00
var type = (ECoreType)Enum.Parse(typeof(ECoreType), item.CoreType);
2024-10-07 02:39:43 +00:00
await (new UpdateService()).CheckUpdateCore(type, _config, _updateUI, preRelease)
2024-09-04 07:47:17 +00:00
.ContinueWith(t =>
{
2024-10-07 12:10:00 +00:00
UpdatedPlusPlus(item.CoreType, "");
2024-09-04 07:47:17 +00:00
});
2024-09-01 08:39:45 +00:00
}
2024-10-04 09:10:30 +00:00
private async Task UpdateFinished()
2024-09-01 08:39:45 +00:00
{
2024-10-07 12:10:00 +00:00
if (_lstUpdated.Count > 0 && _lstUpdated.Count(x => x.IsFinished == true) == _lstUpdated.Count)
2024-09-01 08:39:45 +00:00
{
_updateView?.Invoke(EViewAction.DispatcherCheckUpdateFinished, false);
2024-10-04 09:10:30 +00:00
await Task.Delay(2000);
await UpgradeCore();
2024-09-01 08:39:45 +00:00
2024-10-07 12:10:00 +00:00
if (_lstUpdated.Any(x => x.CoreType == _v2rayN && x.IsFinished == true))
2024-09-01 08:39:45 +00:00
{
2024-10-04 09:10:30 +00:00
await Task.Delay(1000);
2024-09-01 08:39:45 +00:00
UpgradeN();
}
2024-10-04 09:10:30 +00:00
await Task.Delay(1000);
2024-09-01 08:39:45 +00:00
_updateView?.Invoke(EViewAction.DispatcherCheckUpdateFinished, true);
}
}
public void UpdateFinishedResult(bool blReload)
{
if (blReload)
{
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
}
else
{
Locator.Current.GetService<MainWindowViewModel>()?.CloseCore();
}
}
private void UpgradeN()
{
try
{
2024-10-07 12:10:00 +00:00
var fileName = _lstUpdated.FirstOrDefault(x => x.CoreType == _v2rayN)?.FileName;
2024-09-01 08:39:45 +00:00
if (fileName.IsNullOrEmpty())
{
return;
}
if (!Utils.UpgradeAppExists(out _))
{
UpdateView(_v2rayN, ResUI.UpgradeAppNotExistTip);
return;
}
2024-10-09 12:13:25 +00:00
Locator.Current.GetService<MainWindowViewModel>()?.UpgradeApp(fileName);
2024-09-01 08:39:45 +00:00
}
catch (Exception ex)
{
2024-09-06 01:40:45 +00:00
UpdateView(_v2rayN, ex.Message);
2024-09-01 08:39:45 +00:00
}
}
private async Task UpgradeCore()
2024-09-01 08:39:45 +00:00
{
foreach (var item in _lstUpdated)
{
2024-10-07 12:10:00 +00:00
if (item.FileName.IsNullOrEmpty())
2024-09-01 08:39:45 +00:00
{
continue;
}
2024-10-07 12:10:00 +00:00
var fileName = item.FileName;
2024-09-01 08:39:45 +00:00
if (!File.Exists(fileName))
{
continue;
}
2024-10-17 07:28:32 +00:00
var toPath = Utils.GetBinPath("", item.CoreType);
2024-09-01 08:39:45 +00:00
if (fileName.Contains(".tar.gz"))
{
2024-10-17 07:28:32 +00:00
FileManager.DecompressTarFile(fileName, toPath);
var dir = new DirectoryInfo(toPath);
if (dir.Exists)
{
foreach (var subDir in dir.GetDirectories())
{
FileManager.CopyDirectory(subDir.FullName, toPath, false, null);
subDir.Delete(true);
}
}
2024-09-01 08:39:45 +00:00
}
else if (fileName.Contains(".gz"))
{
2024-10-17 07:28:32 +00:00
FileManager.DecompressFile(fileName, toPath, item.CoreType);
2024-09-01 08:39:45 +00:00
}
else
{
FileManager.ZipExtractToFile(fileName, toPath, _config.GuiItem.IgnoreGeoUpdateCore ? "geo" : "");
2024-09-01 08:39:45 +00:00
}
if (Utils.IsLinux())
{
var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList();
foreach (var file in filesList)
{
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType));
}
}
2024-10-07 12:10:00 +00:00
UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfully);
2024-09-01 08:39:45 +00:00
if (File.Exists(fileName))
{
File.Delete(fileName);
}
}
}
private void UpdateView(string coreType, string msg)
{
var item = new CheckUpdateItem()
{
2024-10-07 12:10:00 +00:00
CoreType = coreType,
Remarks = msg,
2024-09-01 08:39:45 +00:00
};
_updateView?.Invoke(EViewAction.DispatcherCheckUpdate, item);
}
public void UpdateViewResult(CheckUpdateItem item)
{
2024-10-07 12:10:00 +00:00
var found = _checkUpdateItem.FirstOrDefault(t => t.CoreType == item.CoreType);
2024-10-17 07:28:32 +00:00
if (found == null) return;
var itemCopy = JsonUtils.DeepCopy(found);
itemCopy.Remarks = item.Remarks;
_checkUpdateItem.Replace(found, itemCopy);
2024-09-01 08:39:45 +00:00
}
}
}