diff --git a/.github/workflows/spotube-release-binary.yml b/.github/workflows/spotube-release-binary.yml index 1527eb18..0fe1f1ba 100644 --- a/.github/workflows/spotube-release-binary.yml +++ b/.github/workflows/spotube-release-binary.yml @@ -166,4 +166,8 @@ jobs: omitPrereleaseDuringUpdate: true allowUpdates: true artifacts: Spotube-Release-Binaries/*,RELEASE.sha256sum,RELEASE.md5sum - body: 'Build Number: ${{github.run_number}}' + body: | + Build Number: ${{github.run_number}} + + Nightly release includes newest features but may contain bugs + It is preferred to use the stable version unless you know what you're doing diff --git a/lib/collections/env.dart b/lib/collections/env.dart index 8081c81e..89a777b6 100644 --- a/lib/collections/env.dart +++ b/lib/collections/env.dart @@ -33,7 +33,7 @@ abstract class Env { @EnviedField(varName: "RELEASE_CHANNEL", defaultValue: "nightly") static final String _releaseChannel = _Env._releaseChannel; - ReleaseChannel get releaseChannel => _releaseChannel == "stable" + static ReleaseChannel get releaseChannel => _releaseChannel == "stable" ? ReleaseChannel.stable : ReleaseChannel.nightly; diff --git a/lib/components/root/update_dialog.dart b/lib/components/root/update_dialog.dart index f5388aa1..f9621d6a 100644 --- a/lib/components/root/update_dialog.dart +++ b/lib/components/root/update_dialog.dart @@ -5,18 +5,23 @@ import 'package:version/version.dart'; class RootAppUpdateDialog extends StatelessWidget { final Version? version; - const RootAppUpdateDialog({super.key, this.version}); + final int? nightlyBuildNum; + + const RootAppUpdateDialog({super.key, this.version}) : nightlyBuildNum = null; + const RootAppUpdateDialog.nightly({super.key, required this.nightlyBuildNum}) + : version = null; @override Widget build(BuildContext context) { const url = "https://spotube.krtirtho.dev/downloads"; + const nightlyUrl = "https://spotube.krtirtho.dev/downloads/nightly"; return AlertDialog( title: const Text("Spotube has an update"), actions: [ FilledButton( child: const Text("Download Now"), onPressed: () => launchUrlString( - url, + nightlyBuildNum != null ? nightlyUrl : url, mode: LaunchMode.externalApplication, ), ), @@ -24,21 +29,26 @@ class RootAppUpdateDialog extends StatelessWidget { content: Column( mainAxisSize: MainAxisSize.min, children: [ - Text("Spotube v$version has been released"), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text("Read the latest "), - AnchorButton( - "release notes", - style: const TextStyle(color: Colors.blue), - onTap: () => launchUrlString( - url, - mode: LaunchMode.externalApplication, - ), - ), - ], + Text( + nightlyBuildNum != null + ? "Spotube Nightly $nightlyBuildNum has been releases" + : "Spotube v$version has been released", ), + if (nightlyBuildNum != null) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text("Read the latest "), + AnchorButton( + "release notes", + style: const TextStyle(color: Colors.blue), + onTap: () => launchUrlString( + url, + mode: LaunchMode.externalApplication, + ), + ), + ], + ), ], ), ); diff --git a/lib/pages/settings/about.dart b/lib/pages/settings/about.dart index 21b8117b..505eecb9 100644 --- a/lib/pages/settings/about.dart +++ b/lib/pages/settings/about.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:spotube/collections/assets.gen.dart'; +import 'package:spotube/collections/env.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/links/hyper_link.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; @@ -72,6 +73,13 @@ class AboutSpotube extends HookConsumerWidget { Text("v${packageInfo.version}") ], ), + TableRow( + children: [ + Text(context.l10n.channel), + colon, + Text(Env.releaseChannel.name) + ], + ), TableRow( children: [ Text(context.l10n.build_number), diff --git a/lib/utils/service_utils.dart b/lib/utils/service_utils.dart index 30c92e1d..d3158948 100644 --- a/lib/utils/service_utils.dart +++ b/lib/utils/service_utils.dart @@ -335,35 +335,63 @@ abstract class ServiceUtils { ) async { if (!Env.enableUpdateChecker) return; if (!ref.read(userPreferencesProvider.select((s) => s.checkUpdate))) return; - final packageInfo = await PackageInfo.fromPlatform(); - final value = await http.get( - Uri.parse( - "https://api.github.com/repos/KRTirtho/spotube/releases/latest", - ), - ); - final tagName = - (jsonDecode(value.body)["tag_name"] as String).replaceAll("v", ""); - final currentVersion = packageInfo.version == "Unknown" - ? null - : Version.parse(packageInfo.version); - final latestVersion = tagName == "nightly" ? null : Version.parse(tagName); + if (Env.releaseChannel == ReleaseChannel.nightly) { + final value = await http.get( + Uri.parse( + "https://api.github.com/repos/KRTirtho/spotube/releases/tags/nightly", + ), + ); - if (currentVersion == null || - latestVersion == null || - (latestVersion.isPreRelease && !currentVersion.isPreRelease) || - (!latestVersion.isPreRelease && currentVersion.isPreRelease)) return; + final body = jsonDecode(value.body)["body"] as String; - if (latestVersion <= currentVersion || !context.mounted) return; + final buildNum = int.tryParse( + RegExp(r'Build Number: (\d+)').firstMatch(body)?.group(1) ?? '0', + ) ?? + 0; - showDialog( - context: context, - barrierDismissible: true, - barrierColor: Colors.black26, - builder: (context) { - return RootAppUpdateDialog(version: latestVersion); - }, - ); + if (buildNum <= int.parse(packageInfo.buildNumber) || !context.mounted) { + return; + } + + await showDialog( + context: context, + barrierDismissible: true, + barrierColor: Colors.black26, + builder: (context) { + return RootAppUpdateDialog.nightly(nightlyBuildNum: buildNum); + }, + ); + } else { + final value = await http.get( + Uri.parse( + "https://api.github.com/repos/KRTirtho/spotube/releases/latest", + ), + ); + final tagName = + (jsonDecode(value.body)["tag_name"] as String).replaceAll("v", ""); + final currentVersion = packageInfo.version == "Unknown" + ? null + : Version.parse(packageInfo.version); + final latestVersion = + tagName == "nightly" ? null : Version.parse(tagName); + + if (currentVersion == null || + latestVersion == null || + (latestVersion.isPreRelease && !currentVersion.isPreRelease) || + (!latestVersion.isPreRelease && currentVersion.isPreRelease)) return; + + if (latestVersion <= currentVersion || !context.mounted) return; + + showDialog( + context: context, + barrierDismissible: true, + barrierColor: Colors.black26, + builder: (context) { + return RootAppUpdateDialog(version: latestVersion); + }, + ); + } } }