feat: Auto-update with ZIP portable (v1.7.5)
Some checks failed
CI / run (push) Has been cancelled

- Add update notification dialog on startup
- Implement portable ZIP update mechanism with robocopy
- Auto-restart after update
- Remove update banner, show dialog directly
- Fix Windows Server compatibility
This commit is contained in:
Umbrix Admin
2026-01-20 13:43:51 +03:00
parent 0b46de4fa8
commit 5989a67239
2 changed files with 37 additions and 8 deletions

View File

@@ -213,13 +213,14 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
final updateScript = '''
@echo off
echo Waiting for application to close...
timeout /t 3 /nobreak > nul
timeout /t 2 /nobreak > nul
echo Updating files...
xcopy /E /Y "${tempDir.path}\\*" "$appDir\\"
robocopy "${tempDir.path}" "$appDir" /E /IS /IT /COPY:DAT /DCOPY:DAT /R:3 /W:1
echo Cleanup...
rmdir /S /Q "${tempDir.path}"
del "$savePath"
echo Starting application...
start "" "$exePath"
@@ -233,16 +234,16 @@ del "%~f0"
if (context.mounted) {
CustomToast.success('Обновление установлено! Приложение перезагрузится...').show(context);
await Future.delayed(const Duration(milliseconds: 500));
context.pop();
}
// Запустить скрипт и закрыть приложение
await Process.start('cmd', ['/c', scriptPath], mode: ProcessStartMode.detached);
// Запустить скрипт в фоне
Process.start('cmd', ['/c', 'start', '/min', scriptPath], mode: ProcessStartMode.detached);
// Задержка перед выходом
Future.delayed(const Duration(seconds: 1), () {
exit(0);
});
// Немедленный выход из приложения
await Future.delayed(const Duration(milliseconds: 200));
exit(0);
return;
} catch (e) {

View File

@@ -1,10 +1,14 @@
import 'package:dartx/dartx.dart';
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:umbrix/core/app_info/app_info_provider.dart';
import 'package:umbrix/core/localization/translations.dart';
import 'package:umbrix/core/model/failures.dart';
import 'package:umbrix/core/router/router.dart';
import 'package:umbrix/features/app_update/notifier/app_update_notifier.dart';
import 'package:umbrix/features/app_update/notifier/app_update_state.dart';
import 'package:umbrix/features/app_update/widget/new_version_dialog.dart';
import 'package:umbrix/features/common/nested_app_bar.dart';
import 'package:umbrix/features/home/widget/connection_button.dart';
import 'package:umbrix/features/home/widget/empty_profiles_home_body.dart';
@@ -24,6 +28,30 @@ class HomePage extends HookConsumerWidget {
final t = ref.watch(translationsProvider);
final hasAnyProfile = ref.watch(hasAnyProfileProvider);
final activeProfile = ref.watch(activeProfileProvider);
// Показываем диалог об обновлении
final appUpdateState = ref.watch(appUpdateNotifierProvider);
final appInfo = ref.watch(appInfoProvider).requireValue;
final hasShownDialog = useState(false);
useEffect(() {
if (appUpdateState is AppUpdateStateAvailable && !hasShownDialog.value) {
hasShownDialog.value = true;
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => NewVersionDialog(
appInfo.version,
appUpdateState.versionInfo,
),
);
});
}
return null;
}, [appUpdateState]);
return Scaffold(
body: Stack(