From d4f248fcd75d2a45e254264b70abfe589bbe730d Mon Sep 17 00:00:00 2001 From: Bonfra04 Date: Tue, 16 Jan 2024 01:48:51 +0100 Subject: [PATCH] auto update check --- analysis_options.yaml | 1 + android/app/src/main/AndroidManifest.xml | 11 ++ .../app/src/main/res/xml/provider_paths.xml | 4 + lib/backend/version.dart | 133 ++++++++++++++++++ lib/main.dart | 3 + lib/views/home.dart | 48 +++++++ pubspec.lock | 22 ++- pubspec.yaml | 6 +- 8 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 android/app/src/main/res/xml/provider_paths.xml create mode 100644 lib/backend/version.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index db42bd8..a3ce961 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -5,3 +5,4 @@ linter: unnecessary_this: false curly_braces_in_flow_control_structures: false unnecessary_brace_in_string_interps: false + control_flow_in_finally: false diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6489d01..8970577 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + + + + + + + diff --git a/lib/backend/version.dart b/lib/backend/version.dart new file mode 100644 index 0000000..662eb93 --- /dev/null +++ b/lib/backend/version.dart @@ -0,0 +1,133 @@ + +import 'dart:io'; +import 'dart:isolate'; +import 'dart:ui'; + +import 'package:flutter_downloader/flutter_downloader.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:stronzflix/utils/platform.dart'; +import 'package:stronzflix/utils/simple_http.dart' as http; +import 'dart:convert'; + +class VersionChecker +{ + static Map? __latestRelease; + + static Future> get _latestRelease async + { + if(VersionChecker.__latestRelease == null) { + String jsonString = await http.get('https://api.github.com/repos/Bonfra04/Stronzflix/releases/latest'); + VersionChecker.__latestRelease = jsonDecode(jsonString); + } + + return VersionChecker.__latestRelease!; + } + + static Future _getLastVersion() async + { + Map release = await VersionChecker._latestRelease; + String version = release['name'].toString().split("Stronzflix ")[1]; + return version; + } + + static Future _getCurrentVersion() async + { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + return packageInfo.version; + } + + static Future shouldUpdate() async + { + try { + String currentVersion = await _getCurrentVersion(); + String lastVersion = await _getLastVersion(); + return currentVersion != lastVersion; + } catch (_) { + return false; + } + } + + static Future _getPlatformUrl() async { + String platform; + if(Platform.isAndroid) + platform = ".apk"; + else if(Platform.isWindows) + platform = "Windows"; + else if(Platform.isLinux) + platform = "Linux"; + else + throw Exception("Unsupported platform"); + + List> assets = (await VersionChecker._latestRelease)['assets'] + .map>((dynamic asset) => asset as Map).toList(); + + for (Map asset in assets) { + if(asset['name'].toString().contains(platform)) { + String url = asset['browser_download_url']; + return url; + } + } + + throw Exception("No asset found for platform $platform"); + } + + static Future _updateDesktop(String downloadUrl) async { + await SPlatform.launchURL(downloadUrl); + } + + static Future cleanCache() async { + try { + String directory = (await getExternalStorageDirectory())!.absolute.path; + File file = File("${directory}/Stronzflix.apk"); + if(await file.exists()) + await file.delete(); + } catch (_) {} + } + + @pragma('vm:entry-point') + static void downloadCallback(String id, int status, int progress) { + final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port'); + send!.send([id, status, progress]); + } + + static final ReceivePort _port = ReceivePort(); + + static void _updateMobile(String downloadUrl) async { + String directory = (await getExternalStorageDirectory())!.absolute.path; + String? taskId; + + IsolateNameServer.registerPortWithName(VersionChecker._port.sendPort, 'downloader_send_port'); + VersionChecker._port.listen((dynamic data) { + DownloadTaskStatus status = DownloadTaskStatus.fromInt(data[1]); + + if(status == DownloadTaskStatus.complete) { + IsolateNameServer.removePortNameMapping('downloader_send_port'); + FlutterDownloader.open(taskId: taskId!); + } + }); + + FlutterDownloader.registerCallback(downloadCallback); + taskId = await FlutterDownloader.enqueue( + url: downloadUrl, + savedDir: directory, + showNotification: true, + openFileFromNotification: true, + ); + } + + static Future update() async { + try { + String downloadUrl = await VersionChecker._getPlatformUrl(); + if(SPlatform.isDesktop) + VersionChecker._updateDesktop(downloadUrl); + else if(SPlatform.isMobile) + VersionChecker._updateMobile(downloadUrl); + else + throw Exception("Unsupported platform"); + return true; + } finally { + return false; + } + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 19ca4c9..22ee2c4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:stronzflix/backend/streamingcommunity.dart'; import 'package:stronzflix/backend/vixxcloud.dart'; import 'package:stronzflix/utils/storage.dart'; @@ -15,6 +16,8 @@ void main() async { VixxCloud.instance; registerWith(options: {'platforms': [ 'linux', 'windows']}); + if(SPlatform.isMobile) + await FlutterDownloader.initialize(); if(SPlatform.isDesktop) await windowManager.ensureInitialized(); diff --git a/lib/views/home.dart b/lib/views/home.dart index 6806393..abe7dc0 100644 --- a/lib/views/home.dart +++ b/lib/views/home.dart @@ -1,6 +1,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:stronzflix/backend/media.dart'; +import 'package:stronzflix/backend/version.dart'; import 'package:stronzflix/components/result_card.dart'; import 'package:stronzflix/utils/platform.dart'; import 'package:stronzflix/utils/storage.dart'; @@ -45,6 +46,47 @@ class _HomePageState extends State { ); } + void _checkVersion() async { + if(SPlatform.isMobile) + await VersionChecker.cleanCache(); + if(!await VersionChecker.shouldUpdate()) + return; + + String action = SPlatform.isMobile ? "Installa" : "Scarica"; + + // ignore: use_build_context_synchronously + showDialog( + context: super.context, + builder: (context) => AlertDialog( + title: const Text('Aggiornamento disponibile!'), + content: RichText( + text: const TextSpan( + children: [ + TextSpan( + text: 'Una nuova versione di Stronzflix รจ disponibile.\n', + ), + TextSpan( + text: 'Vuoi aggiornare?', + )] + ) + ), + actions: [ + TextButton( + child: const Text('Ignora'), + onPressed: () => Navigator.of(context).pop() + ), + TextButton( + child: Text(action), + onPressed: () { + VersionChecker.update(); + Navigator.of(context).pop(); + } + ) + ] + ) + ); + } + AppBar _buildSearchBar(BuildContext context) { return AppBar( title: const Text("Stronzflix"), @@ -99,6 +141,12 @@ class _HomePageState extends State { ); } + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => this._checkVersion()); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/pubspec.lock b/pubspec.lock index 0a60af6..05fe340 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -182,6 +182,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_downloader: + dependency: "direct main" + description: + name: flutter_downloader + sha256: e130001cf85d8d7450b8318a4670c19e495dd8c102ad4b15a512e9405e7c451d + url: "https://pub.dev" + source: hosted + version: "1.11.6" flutter_lints: dependency: "direct dev" description: @@ -305,13 +313,13 @@ packages: source: hosted version: "0.5.0" package_info_plus: - dependency: transitive + dependency: "direct main" description: name: package_info_plus - sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" + sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "5.0.1" package_info_plus_platform_interface: dependency: transitive description: @@ -332,10 +340,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: @@ -681,10 +689,10 @@ packages: dependency: transitive description: name: wakelock_plus - sha256: f45a6c03aa3f8322e0a9d7f4a0482721c8789cb41d555407367650b8f9c26018 + sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" wakelock_plus_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8110fd7..c79169b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: stronzflix description: "Streaming application." publish_to: 'none' -version: 1.0.0+1 +version: 0.1.1 environment: sdk: '>=3.2.0 <4.0.0' @@ -12,17 +12,19 @@ dependencies: sdk: flutter video_player: ^2.8.1 + package_info_plus: ^5.0.1 fvp: ^0.11.0 video_player_web_hls: ^1.1.0 chewie: ^1.7.1 http: ^1.1.0 html_unescape: ^2.0.0 window_manager: ^0.3.7 - path_provider: ^2.1.1 + path_provider: ^2.1.2 shared_preferences: ^2.2.2 url_launcher: ^6.2.2 universal_html: ^2.2.4 cast: ^2.0.0 + flutter_downloader: ^1.11.6 dev_dependencies: flutter_test: