diff --git a/lib/models/file_metadata.dart b/lib/models/file_metadata.dart index 6e1d9ed..60d23c2 100644 --- a/lib/models/file_metadata.dart +++ b/lib/models/file_metadata.dart @@ -23,10 +23,6 @@ class FileMetadata extends base.FileMetadata with DataModelMixin { super.fromJson(); Map toJson() => super.toMap(); - - // String? get version => tagMap['version']?.firstOrNull; - int? get versionCode => int.tryParse(event.getTag('version') ?? ''); - String? get apkSignatureHash => event.getTag('apk_signature_hash'); } mixin FileMetadataAdapter on Adapter { diff --git a/lib/models/local_app.dart b/lib/models/local_app.dart index 7058dce..1884eed 100644 --- a/lib/models/local_app.dart +++ b/lib/models/local_app.dart @@ -10,6 +10,7 @@ import 'package:zapstore/main.data.dart'; import 'package:zapstore/models/app.dart'; import 'package:zapstore/utils/extensions.dart'; import 'package:zapstore/utils/system_info.dart'; +import 'package:zapstore/utils/version.dart'; part 'local_app.g.dart'; @@ -166,8 +167,9 @@ mixin LocalAppAdapter on Adapter { comp = app.latestMetadata!.versionCode!.compareTo(code); } + // If versionCode was not available or not enough, compare string version if (comp == 0) { - comp = app.latestMetadata!.version!.compareTo(installedVersion); + comp = compareVersions(installedVersion, app.latestMetadata!.version!); } if (comp == 1) return AppInstallStatus.updatable; diff --git a/lib/utils/version.dart b/lib/utils/version.dart new file mode 100644 index 0000000..d6545f7 --- /dev/null +++ b/lib/utils/version.dart @@ -0,0 +1,40 @@ +import 'dart:math'; + +int compareVersions(String version1, String version2) { + // Split the versions into main and pre-release components + final parts1 = version1.split('-'); + final parts2 = version2.split('-'); + + // Split the main version into numeric parts + final mainVersion1 = parts1[0].split('.').map(int.parse).toList(); + final mainVersion2 = parts2[0].split('.').map(int.parse).toList(); + + // Compare the main version parts + for (var i = 0; i < max(mainVersion1.length, mainVersion2.length); i++) { + final v1 = i < mainVersion1.length ? mainVersion1[i] : 0; + final v2 = i < mainVersion2.length ? mainVersion2[i] : 0; + + if (v1 < v2) return 1; // version2 is higher + if (v1 > v2) return -1; // version1 is higher + } + + // If main versions are equal, compare pre-release versions if they exist + final preRelease1 = parts1.length > 1 ? parts1[1] : ''; + final preRelease2 = parts2.length > 1 ? parts2[1] : ''; + + if (preRelease1.isEmpty && preRelease2.isNotEmpty) + return -1; // version2 is higher + if (preRelease2.isEmpty && preRelease1.isNotEmpty) + return 1; // version1 is higher + + if (preRelease1.isEmpty && preRelease2.isEmpty) return 0; // both are equal + + // Compare pre-release versions lexicographically + final comparison = preRelease1.compareTo(preRelease2); + + return comparison < 0 + ? -1 + : comparison > 0 + ? 1 + : 0; +} diff --git a/pubspec.lock b/pubspec.lock index 8df2ca8..4aa7bd8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1018,8 +1018,8 @@ packages: dependency: "direct main" description: path: "." - ref: "6e7c86bc98a8a08b67b8fe8f70d3fcbd58d6476c" - resolved-ref: "6e7c86bc98a8a08b67b8fe8f70d3fcbd58d6476c" + ref: "512eab9828d2d1ca9e1b7e48a5742a3b08b9b99f" + resolved-ref: "512eab9828d2d1ca9e1b7e48a5742a3b08b9b99f" url: "https://github.com/purplebase/purplebase" source: git version: "0.2.0" diff --git a/pubspec.yaml b/pubspec.yaml index 77fade0..2c5cb58 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,7 @@ dependency_overrides: # path: ../../purplebase/purplebase git: url: https://github.com/purplebase/purplebase - ref: 6e7c86bc98a8a08b67b8fe8f70d3fcbd58d6476c + ref: 512eab9828d2d1ca9e1b7e48a5742a3b08b9b99f flutter_data: git: url: https://github.com/zapstore/flutter_data diff --git a/test/version_test.dart b/test/version_test.dart new file mode 100644 index 0000000..587b84e --- /dev/null +++ b/test/version_test.dart @@ -0,0 +1,18 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:zapstore/utils/version.dart'; + +void main() { + group('version parsing', () { + test('returns correct comparison', () { + expect(compareVersions("1.2.3", "1.2.3"), 0); + expect(compareVersions("1.2.3", "1.2.3-alpha"), -1); + expect(compareVersions("1.2.3-alpha", "1.2.3-beta"), -1); + expect(compareVersions("1.2.3-beta", "1.2.3-alpha"), 1); + expect(compareVersions("1.9.0", "1.10.0"), 1); + expect(compareVersions("1.26.8", "1.27.2"), 1); + expect(compareVersions("0.2.7", "0.2.11"), 1); + expect(compareVersions("0.2.11", "0.2.7"), -1); + expect(compareVersions("2024.9", "2024.10-beta2"), 1); + }); + }); +}