From 3943caeedb4eb2ad02fe00712b95b644fde2d77f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Mar 2024 03:04:05 -0400 Subject: [PATCH 1/6] Resume failed downloads when possible (#634) --- lib/providers/apps_provider.dart | 134 +++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 32 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4b1d0e6..cff5b0b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -202,14 +202,18 @@ Future checkPartialDownloadHash(String url, int bytesToGrab, Future downloadFile( String url, String fileNameNoExt, Function? onProgress, String destDir, {bool useExisting = true, Map? headers}) async { + // Send the initial request but cancel it as soon as you have the headers + var reqHeaders = headers ?? {}; var req = Request('GET', Uri.parse(url)); - if (headers != null) { - req.headers.addAll(headers); - } + req.headers.addAll(reqHeaders); var client = http.Client(); StreamedResponse response = await client.send(req); - String ext = - response.headers['content-disposition']?.split('.').last ?? 'apk'; + var resHeaders = response.headers; + + // Use the headers to decide what the file extension is, and + // whether it supports partial downloads (range request), and + // what the total size of the file is (if provided) + String ext = resHeaders['content-disposition']?.split('.').last ?? 'apk'; if (ext.endsWith('"') || ext.endsWith("other")) { ext = ext.substring(0, ext.length - 1); } @@ -217,41 +221,107 @@ Future downloadFile( ext = 'apk'; } File downloadedFile = File('$destDir/$fileNameNoExt.$ext'); - if (!(downloadedFile.existsSync() && useExisting)) { - File tempDownloadedFile = File('${downloadedFile.path}.part'); - if (tempDownloadedFile.existsSync()) { - tempDownloadedFile.deleteSync(recursive: true); - } - var length = response.contentLength; - var received = 0; - double? progress; - var sink = tempDownloadedFile.openWrite(); - await response.stream.map((s) { - received += s.length; - progress = (length != null ? received / length * 100 : 30); - if (onProgress != null) { - onProgress(progress); + + bool rangeFeatureEnabled = false; + if (resHeaders['accept-ranges']?.isNotEmpty == true) { + rangeFeatureEnabled = + resHeaders['accept-ranges']?.trim().toLowerCase() == 'bytes'; + } + + // If you have an existing file that is usable, + // decide whether you can use it (either return full or resume partial) + var fullContentLength = response.contentLength; + if (useExisting && downloadedFile.existsSync()) { + var length = downloadedFile.lengthSync(); + if (fullContentLength == null) { + // Assume full + client.close(); + return downloadedFile; + } else { + // Check if resume needed/possible + if (length == fullContentLength) { + client.close(); + return downloadedFile; } - return s; - }).pipe(sink); - await sink.close(); - progress = null; + if (length > fullContentLength) { + useExisting = false; + } + } + } + + // Download to a '.temp' file (to distinguish btn. complete/incomplete files) + File tempDownloadedFile = File('${downloadedFile.path}.part'); + + // If the range feature is not available (or you need to start a ranged req from 0), + // complete the already-started request, else cancel it and start a ranged request, + // and open the file for writing in the appropriate mode + var targetFileLength = useExisting && tempDownloadedFile.existsSync() + ? tempDownloadedFile.lengthSync() + : null; + int rangeStart = targetFileLength ?? 0; + IOSink? sink; + if (rangeFeatureEnabled && fullContentLength != null && rangeStart > 0) { + client.close(); + client = http.Client(); + req = Request('GET', Uri.parse(url)); + req.headers.addAll(reqHeaders); + req.headers.addAll({'range': 'bytes=$rangeStart-${fullContentLength - 1}'}); + response = await client.send(req); + sink = tempDownloadedFile.openWrite(mode: FileMode.writeOnlyAppend); + } else if (tempDownloadedFile.existsSync()) { + tempDownloadedFile.deleteSync(recursive: true); + } + sink ??= tempDownloadedFile.openWrite(mode: FileMode.writeOnly); + + // Perform the download + var received = 0; + double? progress; + if (rangeStart > 0 && fullContentLength != null) { + received = rangeStart; + } + await response.stream.map((s) { + received += s.length; + progress = + (fullContentLength != null ? (received / fullContentLength) * 100 : 30); if (onProgress != null) { onProgress(progress); } - if (response.statusCode != 200) { - tempDownloadedFile.deleteSync(recursive: true); - throw response.reasonPhrase ?? tr('unexpectedError'); - } - if (tempDownloadedFile.existsSync()) { - tempDownloadedFile.renameSync(downloadedFile.path); - } - } else { - client.close(); + return s; + }).pipe(sink); + await sink.close(); + progress = null; + if (onProgress != null) { + onProgress(progress); } + if (response.statusCode < 200 || response.statusCode > 299) { + tempDownloadedFile.deleteSync(recursive: true); + throw response.reasonPhrase ?? tr('unexpectedError'); + } + print(tempDownloadedFile.lengthSync()); + print(fullContentLength); + if (tempDownloadedFile.existsSync()) { + tempDownloadedFile.renameSync(downloadedFile.path); + } + client.close(); return downloadedFile; } +Future> getHeaders(String url, + {Map? headers}) async { + var req = http.Request('GET', Uri.parse(url)); + if (headers != null) { + req.headers.addAll(headers); + } + var client = http.Client(); + var response = await client.send(req); + if (response.statusCode < 200 || response.statusCode > 299) { + throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError')); + } + var returnHeaders = response.headers; + client.close(); + return returnHeaders; +} + Future getInstalledInfo(String? packageName, {bool printErr = true}) async { if (packageName != null) { From e95f57553003d5ac53b5ca70739f6f8b671b1f0a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Mar 2024 04:01:09 -0400 Subject: [PATCH 2/6] Typo: 'Installed' not 'Updated' (#1469) + Bugfix: Don't incorrectly show message when user cancels --- lib/pages/app.dart | 5 ++++- lib/providers/apps_provider.dart | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index cbccc9c..f4f20fc 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -361,6 +361,9 @@ class _AppPageState extends State { !areDownloadsRunning ? () async { try { + var successMessage = app?.app.installedVersion == null + ? tr('installed') + : tr('appsUpdated'); HapticFeedback.heavyImpact(); var res = await appsProvider.downloadAndInstallLatestApps( app?.app.id != null ? [app!.app.id] : [], @@ -368,7 +371,7 @@ class _AppPageState extends State { ); if (res.isNotEmpty && !trackOnly) { // ignore: use_build_context_synchronously - showMessage(tr('appsUpdated'), context); + showMessage(successMessage, context); } if (res.isNotEmpty && mounted) { Navigator.of(context).pop(); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index cff5b0b..e152163 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -563,13 +563,13 @@ class AppsProvider with ChangeNotifier { zipFile: File(filePath), destinationDir: Directory(destinationPath)); } - Future installXApkDir(DownloadedXApkDir dir, + Future installXApkDir(DownloadedXApkDir dir, {bool needsBGWorkaround = false}) async { // We don't know which APKs in an XAPK are supported by the user's device // So we try installing all of them and assume success if at least one installed // If 0 APKs installed, throw the first install error encountered + var somethingInstalled = false; try { - var somethingInstalled = false; MultiAppMultiError errors = MultiAppMultiError(); for (var file in dir.extracted .listSync(recursive: true, followLinks: false) @@ -596,6 +596,7 @@ class AppsProvider with ChangeNotifier { } finally { dir.extracted.delete(recursive: true); } + return somethingInstalled; } Future installApk(DownloadedApk file, @@ -828,17 +829,18 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { if (!skipInstalls) { + bool sayInstalled = true; if (downloadedFile != null) { if (willBeSilent && context == null) { installApk(downloadedFile, needsBGWorkaround: true); } else { - await installApk(downloadedFile); + sayInstalled = await installApk(downloadedFile); } } else { if (willBeSilent && context == null) { installXApkDir(downloadedDir!, needsBGWorkaround: true); } else { - await installXApkDir(downloadedDir!); + sayInstalled = await installXApkDir(downloadedDir!); } } if (willBeSilent && context == null) { @@ -846,7 +848,9 @@ class AppsProvider with ChangeNotifier { [apps[id]!.app], id: id.hashCode)); } - installedIds.add(id); + if (sayInstalled) { + installedIds.add(id); + } } } finally { apps[id]?.downloadProgress = null; From 4e968826ba9f24cf96f97029f1aa7a451cc34e21 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Mar 2024 04:15:43 -0400 Subject: [PATCH 3/6] Add changelog button to app page (#1474) --- lib/pages/app.dart | 29 ++++++-- lib/pages/apps.dart | 177 ++++++++++++++++++++++---------------------- 2 files changed, 109 insertions(+), 97 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index f4f20fc..6970cb3 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -4,6 +4,7 @@ import 'package:flutter/services.dart'; import 'package:obtainium/components/generated_form_modal.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/main.dart'; +import 'package:obtainium/pages/apps.dart'; import 'package:obtainium/pages/settings.dart'; import 'package:obtainium/providers/apps_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; @@ -108,6 +109,7 @@ class _AppPageState extends State { infoLines = '$infoLines\n${app?.app.apkUrls.length == 1 ? app?.app.apkUrls[0].key : plural('apk', app?.app.apkUrls.length ?? 0)}'; } + var changeLogFn = app != null ? getChangeLogFn(context, app.app) : null; return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, @@ -125,13 +127,26 @@ class _AppPageState extends State { .textTheme .bodyLarge! .copyWith(fontWeight: FontWeight.bold)), - app?.app.releaseDate == null - ? const SizedBox.shrink() - : Text( - app!.app.releaseDate.toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.labelSmall, - ), + changeLogFn != null || app?.app.releaseDate != null + ? GestureDetector( + onTap: changeLogFn, + child: Text( + app?.app.releaseDate == null + ? tr('changes') + : app!.app.releaseDate.toString(), + textAlign: TextAlign.center, + style: + Theme.of(context).textTheme.labelSmall!.copyWith( + decoration: changeLogFn != null + ? TextDecoration.underline + : null, + fontStyle: changeLogFn != null + ? FontStyle.italic + : null, + ), + ), + ) + : const SizedBox.shrink(), const SizedBox( height: 8, ), diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 0a94dd6..52125ed 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -26,6 +26,92 @@ class AppsPage extends StatefulWidget { State createState() => AppsPageState(); } +showChangeLogDialog(BuildContext context, App app, String? changesUrl, + AppSource appSource, String changeLog) { + showDialog( + context: context, + builder: (BuildContext context) { + return GeneratedFormModal( + title: tr('changes'), + items: const [], + message: app.latestVersion, + additionalWidgets: [ + changesUrl != null + ? GestureDetector( + child: Text( + changesUrl, + style: const TextStyle( + decoration: TextDecoration.underline, + fontStyle: FontStyle.italic), + ), + onTap: () { + launchUrlString(changesUrl, + mode: LaunchMode.externalApplication); + }, + ) + : const SizedBox.shrink(), + changesUrl != null + ? const SizedBox( + height: 16, + ) + : const SizedBox.shrink(), + appSource.changeLogIfAnyIsMarkDown + ? SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height - 350, + child: Markdown( + data: changeLog, + onTapLink: (text, href, title) { + if (href != null) { + launchUrlString( + href.startsWith('http://') || + href.startsWith('https://') + ? href + : '${Uri.parse(app.url).origin}/$href', + mode: LaunchMode.externalApplication); + } + }, + extensionSet: md.ExtensionSet( + md.ExtensionSet.gitHubFlavored.blockSyntaxes, + [ + md.EmojiSyntax(), + ...md.ExtensionSet.gitHubFlavored.inlineSyntaxes + ], + ), + )) + : Text(changeLog), + ], + singleNullReturnButton: tr('ok'), + ); + }); +} + +getChangeLogFn(BuildContext context, App app) { + AppSource appSource = + SourceProvider().getSource(app.url, overrideSource: app.overrideSource); + String? changesUrl = appSource.changeLogPageFromStandardUrl(app.url); + String? changeLog = app.changeLog; + if (changeLog?.split('\n').length == 1) { + if (RegExp( + '(http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?') + .hasMatch(changeLog!)) { + if (changesUrl == null) { + changesUrl = changeLog; + changeLog = null; + } + } + } + return (changeLog == null && changesUrl == null) + ? null + : () { + if (changeLog != null) { + showChangeLogDialog(context, app, changesUrl, appSource, changeLog); + } else { + launchUrlString(changesUrl!, mode: LaunchMode.externalApplication); + } + }; +} + class AppsPageState extends State { AppsFilter filter = AppsFilter(); final AppsFilter neutralFilter = AppsFilter(); @@ -262,66 +348,6 @@ class AppsPageState extends State { .where((a) => selectedAppIds.contains(a.id)) .toSet(); - showChangeLogDialog( - String? changesUrl, AppSource appSource, String changeLog, int index) { - showDialog( - context: context, - builder: (BuildContext context) { - return GeneratedFormModal( - title: tr('changes'), - items: const [], - message: listedApps[index].app.latestVersion, - additionalWidgets: [ - changesUrl != null - ? GestureDetector( - child: Text( - changesUrl, - style: const TextStyle( - decoration: TextDecoration.underline, - fontStyle: FontStyle.italic), - ), - onTap: () { - launchUrlString(changesUrl, - mode: LaunchMode.externalApplication); - }, - ) - : const SizedBox.shrink(), - changesUrl != null - ? const SizedBox( - height: 16, - ) - : const SizedBox.shrink(), - appSource.changeLogIfAnyIsMarkDown - ? SizedBox( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height - 350, - child: Markdown( - data: changeLog, - onTapLink: (text, href, title) { - if (href != null) { - launchUrlString( - href.startsWith('http://') || - href.startsWith('https://') - ? href - : '${Uri.parse(listedApps[index].app.url).origin}/$href', - mode: LaunchMode.externalApplication); - } - }, - extensionSet: md.ExtensionSet( - md.ExtensionSet.gitHubFlavored.blockSyntaxes, - [ - md.EmojiSyntax(), - ...md.ExtensionSet.gitHubFlavored.inlineSyntaxes - ], - ), - )) - : Text(changeLog), - ], - singleNullReturnButton: tr('ok'), - ); - }); - } - getLoadingWidgets() { return [ if (listedApps.isEmpty) @@ -351,35 +377,6 @@ class AppsPageState extends State { ]; } - getChangeLogFn(int appIndex) { - AppSource appSource = SourceProvider().getSource( - listedApps[appIndex].app.url, - overrideSource: listedApps[appIndex].app.overrideSource); - String? changesUrl = - appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url); - String? changeLog = listedApps[appIndex].app.changeLog; - if (changeLog?.split('\n').length == 1) { - if (RegExp( - '(http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?') - .hasMatch(changeLog!)) { - if (changesUrl == null) { - changesUrl = changeLog; - changeLog = null; - } - } - } - return (changeLog == null && changesUrl == null) - ? null - : () { - if (changeLog != null) { - showChangeLogDialog(changesUrl, appSource, changeLog, appIndex); - } else { - launchUrlString(changesUrl!, - mode: LaunchMode.externalApplication); - } - }; - } - getUpdateButton(int appIndex) { return IconButton( visualDensity: VisualDensity.compact, @@ -444,7 +441,7 @@ class AppsPageState extends State { } getSingleAppHorizTile(int index) { - var showChangesFn = getChangeLogFn(index); + var showChangesFn = getChangeLogFn(context, listedApps[index].app); var hasUpdate = listedApps[index].app.installedVersion != null && listedApps[index].app.installedVersion != listedApps[index].app.latestVersion; From 0db27c773b51c3ef2505e897df46e2e4ee08e951 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Mar 2024 04:52:17 -0400 Subject: [PATCH 4/6] Upgrade packages, increment version --- pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index fa08f4a..a3b488c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -38,10 +38,10 @@ packages: dependency: "direct main" description: name: app_links - sha256: "3ced568a5d9e309e99af71285666f1f3117bddd0bd5b3317979dccc1a40cada4" + sha256: fd7fc1569870b4b0d90d17a9f36661a6ff92400fecb6e4adab4abe0f0488bb5f url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "4.0.0" archive: dependency: transitive description: @@ -307,10 +307,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "55b9b229307a10974b26296ff29f2e132256ba4bd74266939118eaefa941cb00" + sha256: f9a05409385b77b06c18f200a41c7c2711ebf7415669350bb0f8474c07bd40d1 url: "https://pub.dev" source: hosted - version: "16.3.3" + version: "17.0.0" flutter_local_notifications_linux: dependency: transitive description: @@ -783,10 +783,10 @@ packages: dependency: transitive description: name: sqflite_common - sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.4" stack_trace: dependency: transitive description: @@ -959,10 +959,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0" + sha256: f038ee2fae73b509dde1bc9d2c5a50ca92054282de17631a9a3d515883740934 url: "https://pub.dev" source: hosted - version: "3.15.0" + version: "3.16.0" webview_flutter_platform_interface: dependency: transitive description: @@ -975,10 +975,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86" + sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7 url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "3.13.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1a44b56..0d987f6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.5+2255 # When changing this, update the tag in main() accordingly +version: 1.0.6+2256 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -38,7 +38,7 @@ dependencies: cupertino_icons: ^1.0.5 path_provider: ^2.0.11 flutter_fgbg: ^0.3.0 # Try removing reliance on this - flutter_local_notifications: ^16.1.0 + flutter_local_notifications: ^17.0.0 provider: ^6.0.3 http: ^1.0.0 webview_flutter: ^4.0.0 @@ -66,7 +66,7 @@ dependencies: connectivity_plus: ^5.0.0 shared_storage: ^0.8.0 crypto: ^3.0.3 - app_links: ^3.5.0 + app_links: ^4.0.0 background_fetch: ^1.2.1 dev_dependencies: From f905aa7dfdc9527a8180edcedc66fed38938a38e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Mar 2024 05:12:31 -0400 Subject: [PATCH 5/6] Made required changes according to https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply --- android/app/build.gradle | 21 +++++++++------------ android/build.gradle | 19 ------------------- android/settings.gradle | 30 ++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 249b190..b953de3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,9 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -21,11 +22,6 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'dev.rikka.tools.refine' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { @@ -33,7 +29,8 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion rootProject.ext.compileSdkVersion + namespace "dev.imranr.obtainium" + compileSdk flutter.compileSdkVersion ndkVersion flutter.ndkVersion compileOptions { @@ -54,7 +51,7 @@ android { // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion 24 - targetSdkVersion rootProject.ext.targetSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/build.gradle b/android/build.gradle index 5d6d8f4..89b0d75 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,22 +1,3 @@ -buildscript { - ext.kotlin_version = '1.8.10' - ext { - compileSdkVersion = 34 // or latest - targetSdkVersion = 34 // or latest - appCompatVersion = "1.4.2" // or latest - } - repositories { - google() - mavenCentral() - } - - dependencies { - classpath "com.android.tools.build:gradle:7.4.2" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "dev.rikka.tools.refine:gradle-plugin:4.3.1" - } -} - allprojects { repositories { google() diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bc..5fd7f48 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,25 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.4.2" apply false + id "org.jetbrains.kotlin.android" version "1.8.10" apply false +} + +include ":app" From da496f7c53ae77526b494bcdb67a439240cadd4a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Mar 2024 05:14:08 -0400 Subject: [PATCH 6/6] GitHub actions: Don't add '-beta' to beta tags (pre-release mark is enough) --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b378687..f35af1a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,7 +42,6 @@ jobs: if [ ${{ inputs.beta }} == true ]; then BETA=true; else BETA=false; fi echo "beta=$BETA" >> $GITHUB_OUTPUT TAG="v$VERSION" - if [ $BETA == true ]; then TAG="$TAG"-beta; fi echo "tag=$TAG" >> $GITHUB_OUTPUT - name: Build APKs