feat: Windows support - auto-update system + proper app icon
Some checks failed
CI / run (push) Has been cancelled
Some checks failed
CI / run (push) Has been cancelled
- PowerShell silent installer with UAC elevation - Smart asset detection (x64 priority for .exe) - Cross-platform restart after update - Auto-check updates on launch (5 sec delay) - Multi-layer .ico with 6 sizes (16-256px) - Windows build documentation added
This commit is contained in:
@@ -25,6 +25,19 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
||||
|
||||
static final _dialogKey = GlobalKey(debugLabel: 'new version dialog');
|
||||
|
||||
/// Перезапуск приложения (кроссплатформенный метод)
|
||||
void _restartApplication() {
|
||||
final executable = Platform.resolvedExecutable;
|
||||
loggy.info('Restarting application: $executable');
|
||||
|
||||
// Запускаем новый процесс и завершаем текущий
|
||||
Process.start(executable, []).then((_) {
|
||||
exit(0);
|
||||
}).catchError((e) {
|
||||
loggy.error('Failed to restart application', e);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> show(BuildContext context) async {
|
||||
if (_dialogKey.currentContext == null) {
|
||||
return showDialog(
|
||||
@@ -57,19 +70,18 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
||||
downloadProgress.value = 0.0;
|
||||
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
|
||||
|
||||
// Определяем нужное расширение файла
|
||||
String fileExt = '';
|
||||
if (Platform.isWindows)
|
||||
fileExt = '.exe';
|
||||
else if (Platform.isMacOS)
|
||||
fileExt = '.dmg';
|
||||
else if (Platform.isLinux)
|
||||
fileExt = '.deb';
|
||||
else if (Platform.isLinux) fileExt = '.deb';
|
||||
|
||||
// Ищем asset с нужным расширением
|
||||
final downloadUrl = newVersion.findAssetByExtension(fileExt);
|
||||
|
||||
|
||||
if (downloadUrl == null) {
|
||||
if (context.mounted) {
|
||||
CustomToast.error('Файл установки $fileExt не найден в релизе').show(context);
|
||||
@@ -87,7 +99,7 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
||||
});
|
||||
|
||||
loggy.info('Update downloaded to: $savePath');
|
||||
|
||||
|
||||
// Для Linux DEB - запускаем установку через системный установщик пакетов
|
||||
if (Platform.isLinux && fileExt == '.deb') {
|
||||
try {
|
||||
@@ -95,17 +107,66 @@ class NewVersionDialog extends HookConsumerWidget with PresLogger {
|
||||
final result = await Process.run('pkexec', ['apt', 'install', '-y', savePath]);
|
||||
if (result.exitCode == 0) {
|
||||
if (context.mounted) {
|
||||
CustomToast.success('Обновление установлено! Перезапустите приложение.').show(context);
|
||||
CustomToast.success('Обновление установлено! Приложение перезагрузится...').show(context);
|
||||
context.pop();
|
||||
}
|
||||
|
||||
// Автоматический перезапуск после небольшой задержки
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
_restartApplication();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
loggy.warning('Failed to install via pkexec apt: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Для других платформ или если apt не сработал - просто открываем файл
|
||||
|
||||
// Для Windows EXE - запускаем тихую установку
|
||||
if (Platform.isWindows && fileExt == '.exe') {
|
||||
try {
|
||||
if (context.mounted) {
|
||||
CustomToast('Установка обновления...', type: AlertType.info).show(context);
|
||||
}
|
||||
|
||||
// Запускаем установщик в тихом режиме с правами администратора
|
||||
// /VERYSILENT - без UI, /SUPPRESSMSGBOXES - без диалогов
|
||||
// /NORESTART - не перезагружать систему
|
||||
final result = await Process.run(
|
||||
'powershell',
|
||||
[
|
||||
'-Command',
|
||||
'Start-Process',
|
||||
'-FilePath',
|
||||
'"$savePath"',
|
||||
'-ArgumentList',
|
||||
'"/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART"',
|
||||
'-Verb',
|
||||
'RunAs',
|
||||
'-Wait'
|
||||
],
|
||||
);
|
||||
|
||||
if (result.exitCode == 0) {
|
||||
if (context.mounted) {
|
||||
CustomToast.success('Обновление установлено! Приложение перезагрузится...').show(context);
|
||||
context.pop();
|
||||
}
|
||||
|
||||
// Автоматический перезапуск после небольшой задержки
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
_restartApplication();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
loggy.warning('Failed to install via PowerShell: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Для других платформ или если автоустановка не сработала - просто открываем файл
|
||||
final result = await OpenFile.open(savePath);
|
||||
|
||||
if (result.type != ResultType.done && context.mounted) {
|
||||
|
||||
Reference in New Issue
Block a user