diff --git a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs index dd930135..6dac9df7 100644 --- a/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs @@ -1,6 +1,8 @@ using System; // +++ using System.IO; // +++ using System.Linq; // +++ +using System.Threading.Tasks; // +++ +using System.Collections.Generic;// +++ using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -64,7 +66,7 @@ public class CheckUpdateViewModel : MyReactiveObject CheckUpdateModels.Add(GetCheckUpdateModel(_geo)); } - // +++ 新增:在打包环境(AppImage/DEB/RPM)下返回 true;其他返回 false + // ---- packaged env detection: AppImage or runs from /opt/v2rayN ---- private static bool IsPackagedInstall() { try @@ -72,28 +74,31 @@ public class CheckUpdateViewModel : MyReactiveObject if (Utils.IsWindows()) return false; - // AppImage: 环境变量 APPIMAGE 存在 + // AppImage: APPIMAGE var exists if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPIMAGE"))) return true; - // 安装到 /opt/v2rayN 视为打包安装(deb/rpm) - var sp = Utils.StartupPath()?.Replace('\\', '/'); - if (!string.IsNullOrEmpty(sp) && sp.StartsWith("/opt/v2rayN", StringComparison.OrdinalIgnoreCase)) - return true; - - if (Directory.Exists("/opt/v2rayN")) - return true; + // deb/rpm: current startup path is under /opt/v2rayN + var sp = Utils.StartupPath(); + if (!string.IsNullOrEmpty(sp)) + { + sp = sp.Replace('\\', '/'); + if (sp.Equals("/opt/v2rayN", StringComparison.OrdinalIgnoreCase) || + sp.StartsWith("/opt/v2rayN/", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } } catch { - // ignore } return false; } private CheckUpdateModel GetCheckUpdateModel(string coreType) { - // +++ 打包环境下禁用 v2rayN 自更新,默认关并标注 Not Support + // packaged env: disable v2rayN self-update if (coreType == _v2rayN && IsPackagedInstall()) { return new() @@ -114,7 +119,7 @@ public class CheckUpdateViewModel : MyReactiveObject private async Task SaveSelectedCoreTypes() { - // +++ 打包环境下,不保存 v2rayN 的选择状态 + // packaged env: do not persist v2rayN toggle var list = CheckUpdateModels .Where(t => t.IsSelected == true && !(IsPackagedInstall() && t.CoreType == _v2rayN)) .Select(t => t.CoreType ?? "") @@ -151,7 +156,6 @@ public class CheckUpdateViewModel : MyReactiveObject } else if (item.CoreType == _v2rayN) { - // +++ 打包环境下,直接跳过 v2rayN 自更新 if (IsPackagedInstall()) { await UpdateView(_v2rayN, "Not Support"); @@ -193,200 +197,4 @@ public class CheckUpdateViewModel : MyReactiveObject await UpdateView(_geo, msg); if (success) { - UpdatedPlusPlus(_geo, ""); - } - } - await (new UpdateService()).UpdateGeoFileAll(_config, _updateUI) - .ContinueWith(t => - { - UpdatedPlusPlus(_geo, ""); - }); - } - - private async Task CheckUpdateN(bool preRelease) - { - async Task _updateUI(bool success, string msg) - { - await UpdateView(_v2rayN, msg); - if (success) - { - await UpdateView(_v2rayN, ResUI.OperationSuccess); - UpdatedPlusPlus(_v2rayN, msg); - } - } - await (new UpdateService()).CheckUpdateGuiN(_config, _updateUI, preRelease) - .ContinueWith(t => - { - UpdatedPlusPlus(_v2rayN, ""); - }); - } - - private async Task CheckUpdateCore(CheckUpdateModel model, bool preRelease) - { - async Task _updateUI(bool success, string msg) - { - await UpdateView(model.CoreType, msg); - if (success) - { - await UpdateView(model.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore); - - UpdatedPlusPlus(model.CoreType, msg); - } - } - var type = (ECoreType)Enum.Parse(typeof(ECoreType), model.CoreType); - await (new UpdateService()).CheckUpdateCore(type, _config, _updateUI, preRelease) - .ContinueWith(t => - { - UpdatedPlusPlus(model.CoreType, ""); - }); - } - - private async Task UpdateFinished() - { - if (_lstUpdated.Count > 0 && _lstUpdated.Count(x => x.IsFinished == true) == _lstUpdated.Count) - { - await UpdateFinishedSub(false); - await Task.Delay(2000); - await UpgradeCore(); - - if (_lstUpdated.Any(x => x.CoreType == _v2rayN && x.IsFinished == true)) - { - await Task.Delay(1000); - await UpgradeN(); - } - await Task.Delay(1000); - await UpdateFinishedSub(true); - } - } - - private async Task UpdateFinishedSub(bool blReload) - { - RxApp.MainThreadScheduler.Schedule(blReload, (scheduler, blReload) => - { - _ = UpdateFinishedResult(blReload); - return Disposable.Empty; - }); - } - - public async Task UpdateFinishedResult(bool blReload) - { - if (blReload) - { - Locator.Current.GetService()?.Reload(); - } - else - { - Locator.Current.GetService()?.CloseCore(); - } - } - - private async Task UpgradeN() - { - try - { - var fileName = _lstUpdated.FirstOrDefault(x => x.CoreType == _v2rayN)?.FileName; - if (fileName.IsNullOrEmpty()) - { - return; - } - if (!Utils.UpgradeAppExists(out var upgradeFileName)) - { - await UpdateView(_v2rayN, ResUI.UpgradeAppNotExistTip); - NoticeManager.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip); - Logging.SaveLog("UpgradeApp does not exist"); - return; - } - - var id = ProcUtils.ProcessStart(upgradeFileName, fileName, Utils.StartupPath()); - if (id > 0) - { - await AppManager.Instance.AppExitAsync(true); - } - } - catch (Exception ex) - { - await UpdateView(_v2rayN, ex.Message); - } - } - - private async Task UpgradeCore() - { - foreach (var item in _lstUpdated) - { - if (item.FileName.IsNullOrEmpty()) - { - continue; - } - - var fileName = item.FileName; - if (!File.Exists(fileName)) - { - continue; - } - var toPath = Utils.GetBinPath("", item.CoreType); - - if (fileName.Contains(".tar.gz")) - { - FileManager.DecompressTarFile(fileName, toPath); - var dir = new DirectoryInfo(toPath); - if (dir.Exists) - { - foreach (var subDir in dir.GetDirectories()) - { - FileManager.CopyDirectory(subDir.FullName, toPath, false, true); - subDir.Delete(true); - } - } - } - else if (fileName.Contains(".gz")) - { - FileManager.DecompressFile(fileName, toPath, item.CoreType); - } - else - { - FileManager.ZipExtractToFile(fileName, toPath, "geo"); - } - - if (Utils.IsNonWindows()) - { - var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList(); - foreach (var file in filesList) - { - await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType.ToLower())); - } - } - - await UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfully); - - if (File.Exists(fileName)) - { - File.Delete(fileName); - } - } - } - - private async Task UpdateView(string coreType, string msg) - { - var item = new CheckUpdateModel() - { - CoreType = coreType, - Remarks = msg, - }; - - RxApp.MainThreadScheduler.Schedule(item, (scheduler, model) => - { - _ = UpdateViewResult(model); - return Disposable.Empty; - }); - } - - public async Task UpdateViewResult(CheckUpdateModel model) - { - var found = CheckUpdateModels.FirstOrDefault(t => t.CoreType == model.CoreType); - if (found == null) - { - return; - } - found.Remarks = model.Remarks; - } -} + Updated