2023-12-01 12:56:24 +03:30
|
|
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
2026-01-17 13:09:20 +03:00
|
|
|
|
import 'package:umbrix/core/model/environment.dart';
|
2023-12-01 12:56:24 +03:30
|
|
|
|
|
|
|
|
|
|
part 'remote_version_entity.freezed.dart';
|
|
|
|
|
|
|
|
|
|
|
|
@Freezed()
|
|
|
|
|
|
class RemoteVersionEntity with _$RemoteVersionEntity {
|
|
|
|
|
|
const RemoteVersionEntity._();
|
|
|
|
|
|
|
|
|
|
|
|
const factory RemoteVersionEntity({
|
|
|
|
|
|
required String version,
|
|
|
|
|
|
required String buildNumber,
|
|
|
|
|
|
required String releaseTag,
|
|
|
|
|
|
required bool preRelease,
|
|
|
|
|
|
required String url,
|
|
|
|
|
|
required DateTime publishedAt,
|
|
|
|
|
|
required Environment flavor,
|
2026-01-18 20:14:19 +03:00
|
|
|
|
@Default([]) List<ReleaseAsset> assets,
|
2023-12-01 12:56:24 +03:30
|
|
|
|
}) = _RemoteVersionEntity;
|
|
|
|
|
|
|
2026-01-19 17:48:21 +03:00
|
|
|
|
String get presentVersion => flavor == Environment.prod ? version : "$version ${flavor.name}";
|
2026-01-18 20:14:19 +03:00
|
|
|
|
|
2026-01-19 17:48:21 +03:00
|
|
|
|
/// Найти asset по расширению файла с умным определением
|
2026-01-18 20:14:19 +03:00
|
|
|
|
String? findAssetByExtension(String extension) {
|
|
|
|
|
|
try {
|
2026-01-19 17:48:21 +03:00
|
|
|
|
// Для Linux используем приоритет: .deb > .rpm > .AppImage
|
|
|
|
|
|
if (extension == '.deb' || extension == '.rpm' || extension == '.AppImage') {
|
|
|
|
|
|
final priorities = ['.deb', '.rpm', '.AppImage'];
|
|
|
|
|
|
|
|
|
|
|
|
for (final ext in priorities) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
final asset = assets.firstWhere((asset) => asset.name.endsWith(ext));
|
|
|
|
|
|
return asset.downloadUrl;
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Для Windows - ищем .exe с приоритетом x64
|
|
|
|
|
|
if (extension == '.exe') {
|
|
|
|
|
|
// Сначала ищем x64 setup/installer
|
|
|
|
|
|
for (final pattern in ['x64', 'amd64', 'win64', 'setup', 'installer']) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
final asset = assets.firstWhere(
|
|
|
|
|
|
(asset) => asset.name.toLowerCase().contains(pattern) && asset.name.endsWith('.exe'),
|
|
|
|
|
|
);
|
|
|
|
|
|
return asset.downloadUrl;
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Если не нашли специфичный - берём любой .exe
|
|
|
|
|
|
try {
|
|
|
|
|
|
final asset = assets.firstWhere((asset) => asset.name.endsWith('.exe'));
|
|
|
|
|
|
return asset.downloadUrl;
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Для macOS - ищем .dmg
|
|
|
|
|
|
if (extension == '.dmg') {
|
|
|
|
|
|
// Сначала ищем universal или arm64 (для M1/M2)
|
|
|
|
|
|
for (final pattern in ['universal', 'arm64', 'apple-silicon']) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
final asset = assets.firstWhere(
|
|
|
|
|
|
(asset) => asset.name.toLowerCase().contains(pattern) && asset.name.endsWith('.dmg'),
|
|
|
|
|
|
);
|
|
|
|
|
|
return asset.downloadUrl;
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Если не нашли - берём любой .dmg
|
|
|
|
|
|
try {
|
|
|
|
|
|
final asset = assets.firstWhere((asset) => asset.name.endsWith('.dmg'));
|
|
|
|
|
|
return asset.downloadUrl;
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Для других расширений - прямой поиск
|
2026-01-18 20:14:19 +03:00
|
|
|
|
return assets.firstWhere((asset) => asset.name.endsWith(extension)).downloadUrl;
|
|
|
|
|
|
} catch (_) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@freezed
|
|
|
|
|
|
class ReleaseAsset with _$ReleaseAsset {
|
|
|
|
|
|
const factory ReleaseAsset({
|
|
|
|
|
|
required String name,
|
|
|
|
|
|
required String downloadUrl,
|
|
|
|
|
|
required int size,
|
|
|
|
|
|
}) = _ReleaseAsset;
|
2023-12-01 12:56:24 +03:30
|
|
|
|
}
|