✨ Android self-update
This commit is contained in:
		@@ -1,4 +1,4 @@
 | 
				
			|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="dev.solsynth.solian">
 | 
				
			||||||
    <uses-feature android:name="android.hardware.camera" />
 | 
					    <uses-feature android:name="android.hardware.camera" />
 | 
				
			||||||
    <uses-feature android:name="android.hardware.camera.autofocus" />
 | 
					    <uses-feature android:name="android.hardware.camera.autofocus" />
 | 
				
			||||||
    <uses-permission android:name="android.permission.WAKE_LOCK" />
 | 
					    <uses-permission android:name="android.permission.WAKE_LOCK" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
 | 
				
			|||||||
distributionPath=wrapper/dists
 | 
					distributionPath=wrapper/dists
 | 
				
			||||||
zipStoreBase=GRADLE_USER_HOME
 | 
					zipStoreBase=GRADLE_USER_HOME
 | 
				
			||||||
zipStorePath=wrapper/dists
 | 
					zipStorePath=wrapper/dists
 | 
				
			||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
 | 
					distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ pluginManagement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
plugins {
 | 
					plugins {
 | 
				
			||||||
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
 | 
					    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
 | 
				
			||||||
    id "com.android.application" version '8.4.0' apply false
 | 
					    id "com.android.application" version '8.6.0' apply false
 | 
				
			||||||
    id "com.google.gms.google-services" version "4.3.15" apply false
 | 
					    id "com.google.gms.google-services" version "4.3.15" apply false
 | 
				
			||||||
    id "com.google.firebase.crashlytics" version "2.8.1" apply false
 | 
					    id "com.google.firebase.crashlytics" version "2.8.1" apply false
 | 
				
			||||||
    id "org.jetbrains.kotlin.android" version '2.0.0' apply false
 | 
					    id "org.jetbrains.kotlin.android" version '2.0.0' apply false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,11 @@
 | 
				
			|||||||
  "notificationUnreadCount": "@count unread notifications",
 | 
					  "notificationUnreadCount": "@count unread notifications",
 | 
				
			||||||
  "errorHappened": "An error occurred",
 | 
					  "errorHappened": "An error occurred",
 | 
				
			||||||
  "errorHappenedUnauthorized": "Unauthorized request, please sign in or try resign in.",
 | 
					  "errorHappenedUnauthorized": "Unauthorized request, please sign in or try resign in.",
 | 
				
			||||||
 | 
					  "errorHappenedRequestBad": "Request error, the server refused to process the request. Please check your request data.",
 | 
				
			||||||
 | 
					  "errorHappenedRequestForbidden": "Request error, insufficient permissions.",
 | 
				
			||||||
 | 
					  "errorHappenedRequestNotFound": "Request error, the requested data does not exist.",
 | 
				
			||||||
 | 
					  "errorHappenedRequestConnection": "Network request failed. Please check the connection status and service status, then try again.",
 | 
				
			||||||
 | 
					  "errorHappenedRequestUnknown": "Request error, unknown type. Please take a full screenshot of this message and submit feedback.",
 | 
				
			||||||
  "forgotPassword": "Forgot password",
 | 
					  "forgotPassword": "Forgot password",
 | 
				
			||||||
  "email": "Email",
 | 
					  "email": "Email",
 | 
				
			||||||
  "username": "Username",
 | 
					  "username": "Username",
 | 
				
			||||||
@@ -350,8 +355,7 @@
 | 
				
			|||||||
  "bsCheckForUpdate": "Checking For Updates",
 | 
					  "bsCheckForUpdate": "Checking For Updates",
 | 
				
			||||||
  "bsCheckForUpdateFailed": "Unable to Check Updates",
 | 
					  "bsCheckForUpdateFailed": "Unable to Check Updates",
 | 
				
			||||||
  "bsCheckForUpdateNew": "Found New Version",
 | 
					  "bsCheckForUpdateNew": "Found New Version",
 | 
				
			||||||
  "bsCheckForUpdateDescApple": "Please head to TestFlight and update your app to latest version to prevent error happens and get latest functions.",
 | 
					  "bsCheckForUpdateDesc": "Please head to app store and update your app to latest version to prevent error happens and get latest functions.",
 | 
				
			||||||
  "bsCheckForUpdateDescCommon": "Please head to our website download and install latest version of application to prevent error happens and get latest functions.",
 | 
					 | 
				
			||||||
  "bsCheckingServer": "Checking Server Status",
 | 
					  "bsCheckingServer": "Checking Server Status",
 | 
				
			||||||
  "bsCheckingServerFail": "Unable connect to server, check your network connection",
 | 
					  "bsCheckingServerFail": "Unable connect to server, check your network connection",
 | 
				
			||||||
  "bsCheckingServerDown": "Server currently unavailable, please retry later",
 | 
					  "bsCheckingServerDown": "Server currently unavailable, please retry later",
 | 
				
			||||||
@@ -422,5 +426,7 @@
 | 
				
			|||||||
  "notificationTopicPostFeedback": "Post feedbacks",
 | 
					  "notificationTopicPostFeedback": "Post feedbacks",
 | 
				
			||||||
  "notificationTopicPostSubscription": "Post subscriptions",
 | 
					  "notificationTopicPostSubscription": "Post subscriptions",
 | 
				
			||||||
  "preferencesApplied": "Preferences has been applied.",
 | 
					  "preferencesApplied": "Preferences has been applied.",
 | 
				
			||||||
  "save": "Save"
 | 
					  "save": "Save",
 | 
				
			||||||
 | 
					  "updateAvailable": "Update available",
 | 
				
			||||||
 | 
					  "updateAvailableDesc": "There is an update available (@version). Do you want to download and install it now? You can still use the app normally while waiting for the download to complete."
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -351,8 +351,7 @@
 | 
				
			|||||||
  "bsCheckForUpdate": "正在检查更新",
 | 
					  "bsCheckForUpdate": "正在检查更新",
 | 
				
			||||||
  "bsCheckForUpdateFailed": "无法检查更新",
 | 
					  "bsCheckForUpdateFailed": "无法检查更新",
 | 
				
			||||||
  "bsCheckForUpdateNew": "发现新版本",
 | 
					  "bsCheckForUpdateNew": "发现新版本",
 | 
				
			||||||
  "bsCheckForUpdateDescApple": "请前往 TestFlight 并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。",
 | 
					  "bsCheckForUpdateDesc": "请前往应用商店并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。",
 | 
				
			||||||
  "bsCheckForUpdateDescCommon": "请前往我们的网站下载并安装最新版本的应用程序,以防止出现错误并获取最新功能。",
 | 
					 | 
				
			||||||
  "bsCheckingServer": "检查服务器状态中",
 | 
					  "bsCheckingServer": "检查服务器状态中",
 | 
				
			||||||
  "bsCheckingServerFail": "无法连接至服务器,请检查你的网络连接状态",
 | 
					  "bsCheckingServerFail": "无法连接至服务器,请检查你的网络连接状态",
 | 
				
			||||||
  "bsCheckingServerDown": "当前服务器不可用,请稍后重试",
 | 
					  "bsCheckingServerDown": "当前服务器不可用,请稍后重试",
 | 
				
			||||||
@@ -423,5 +422,7 @@
 | 
				
			|||||||
  "notificationTopicPostFeedback": "帖子反馈",
 | 
					  "notificationTopicPostFeedback": "帖子反馈",
 | 
				
			||||||
  "notificationTopicPostSubscription": "订阅源",
 | 
					  "notificationTopicPostSubscription": "订阅源",
 | 
				
			||||||
  "preferencesApplied": "偏好设置已应用",
 | 
					  "preferencesApplied": "偏好设置已应用",
 | 
				
			||||||
  "save": "保存"
 | 
					  "save": "保存",
 | 
				
			||||||
 | 
					  "updateAvailable": "有可用更新",
 | 
				
			||||||
 | 
					  "updateAvailableDesc": "有可用更新 (@version) 你想现在下载安装吗?在等待下载期间你仍可以正常使用。"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ import 'package:solian/providers/theme_switcher.dart';
 | 
				
			|||||||
import 'package:solian/providers/websocket.dart';
 | 
					import 'package:solian/providers/websocket.dart';
 | 
				
			||||||
import 'package:solian/services.dart';
 | 
					import 'package:solian/services.dart';
 | 
				
			||||||
import 'package:solian/widgets/sized_container.dart';
 | 
					import 'package:solian/widgets/sized_container.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_app_update/flutter_app_update.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BootstrapperShell extends StatefulWidget {
 | 
					class BootstrapperShell extends StatefulWidget {
 | 
				
			||||||
  final Widget child;
 | 
					  final Widget child;
 | 
				
			||||||
@@ -49,15 +50,40 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
 | 
				
			|||||||
          final info = await PackageInfo.fromPlatform();
 | 
					          final info = await PackageInfo.fromPlatform();
 | 
				
			||||||
          final localVersionString = '${info.version}+${info.buildNumber}';
 | 
					          final localVersionString = '${info.version}+${info.buildNumber}';
 | 
				
			||||||
          final resp = await GetConnect().get(
 | 
					          final resp = await GetConnect().get(
 | 
				
			||||||
            'https://git.solsynth.dev/api/v1/repos/hydrogen/solian/tags?limit=1',
 | 
					            'https://git.solsynth.dev/api/v1/repos/hydrogen/solian/tags?page=1&limit=1',
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          if (resp.body[0]['name'] != localVersionString) {
 | 
					          if (resp.body[0]['name'] != localVersionString) {
 | 
				
			||||||
            setState(() {
 | 
					            setState(() {
 | 
				
			||||||
              _isErrored = true;
 | 
					              _isErrored = true;
 | 
				
			||||||
              _subtitle = PlatformInfo.isIOS || PlatformInfo.isMacOS
 | 
					              _subtitle = 'bsCheckForUpdateDesc'.tr;
 | 
				
			||||||
                  ? 'bsCheckForUpdateDescApple'.tr
 | 
					 | 
				
			||||||
                  : 'bsCheckForUpdateDescCommon'.tr;
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (PlatformInfo.isAndroid) {
 | 
				
			||||||
 | 
					              context
 | 
				
			||||||
 | 
					                  .showConfirmDialog(
 | 
				
			||||||
 | 
					                'updateAvailable'.tr,
 | 
				
			||||||
 | 
					                'updateAvailableDesc'.trParams({
 | 
				
			||||||
 | 
					                  'version': resp.body[0]['name'],
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					                  .then((result) {
 | 
				
			||||||
 | 
					                if (result) {
 | 
				
			||||||
 | 
					                  final model = UpdateModel(
 | 
				
			||||||
 | 
					                    'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk',
 | 
				
			||||||
 | 
					                    'solian-app-arm64-v8a-release.apk',
 | 
				
			||||||
 | 
					                    'ic_launcher',
 | 
				
			||||||
 | 
					                    'https://testflight.apple.com/join/YJ0lmN6O',
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                  AzhonAppUpdate.update(model);
 | 
				
			||||||
 | 
					                  if (mounted) {
 | 
				
			||||||
 | 
					                    setState(() {
 | 
				
			||||||
 | 
					                      _isErrored = false;
 | 
				
			||||||
 | 
					                      _subtitle = null;
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
          setState(() {
 | 
					          setState(() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,28 @@ extension AppExtensions on BuildContext {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<bool> showConfirmDialog(String title, body) async {
 | 
				
			||||||
 | 
					    return await showDialog<bool>(
 | 
				
			||||||
 | 
					          useRootNavigator: true,
 | 
				
			||||||
 | 
					          context: this,
 | 
				
			||||||
 | 
					          builder: (ctx) => AlertDialog(
 | 
				
			||||||
 | 
					            title: Text(title),
 | 
				
			||||||
 | 
					            content: Text(body),
 | 
				
			||||||
 | 
					            actions: [
 | 
				
			||||||
 | 
					              TextButton(
 | 
				
			||||||
 | 
					                onPressed: () => Navigator.pop(ctx, false),
 | 
				
			||||||
 | 
					                child: Text('cancel'.tr),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              TextButton(
 | 
				
			||||||
 | 
					                onPressed: () => Navigator.pop(ctx, true),
 | 
				
			||||||
 | 
					                child: Text('okay'.tr),
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ) ??
 | 
				
			||||||
 | 
					        false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> showErrorDialog(dynamic exception) {
 | 
					  Future<void> showErrorDialog(dynamic exception) {
 | 
				
			||||||
    Widget content = Text(exception.toString().capitalize!);
 | 
					    Widget content = Text(exception.toString().capitalize!);
 | 
				
			||||||
    if (exception is UnauthorizedException) {
 | 
					    if (exception is UnauthorizedException) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,6 @@ import 'package:go_router/go_router.dart';
 | 
				
			|||||||
import 'package:protocol_handler/protocol_handler.dart';
 | 
					import 'package:protocol_handler/protocol_handler.dart';
 | 
				
			||||||
import 'package:provider/provider.dart';
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
import 'package:solian/background.dart';
 | 
					import 'package:solian/background.dart';
 | 
				
			||||||
import 'package:solian/bootstrapper.dart';
 | 
					 | 
				
			||||||
import 'package:solian/firebase_options.dart';
 | 
					import 'package:solian/firebase_options.dart';
 | 
				
			||||||
import 'package:solian/platform.dart';
 | 
					import 'package:solian/platform.dart';
 | 
				
			||||||
import 'package:solian/providers/attachment_uploader.dart';
 | 
					import 'package:solian/providers/attachment_uploader.dart';
 | 
				
			||||||
@@ -123,10 +122,8 @@ class SolianApp extends StatelessWidget {
 | 
				
			|||||||
          builder: (context, child) {
 | 
					          builder: (context, child) {
 | 
				
			||||||
            return SystemShell(
 | 
					            return SystemShell(
 | 
				
			||||||
              child: ScaffoldMessenger(
 | 
					              child: ScaffoldMessenger(
 | 
				
			||||||
                child: BootstrapperShell(
 | 
					 | 
				
			||||||
                child: child ?? const SizedBox.shrink(),
 | 
					                child: child ?? const SizedBox.shrink(),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import 'package:animations/animations.dart';
 | 
					import 'package:animations/animations.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:go_router/go_router.dart';
 | 
					import 'package:go_router/go_router.dart';
 | 
				
			||||||
 | 
					import 'package:solian/bootstrapper.dart';
 | 
				
			||||||
import 'package:solian/models/realm.dart';
 | 
					import 'package:solian/models/realm.dart';
 | 
				
			||||||
import 'package:solian/screens/about.dart';
 | 
					import 'package:solian/screens/about.dart';
 | 
				
			||||||
import 'package:solian/screens/account.dart';
 | 
					import 'package:solian/screens/account.dart';
 | 
				
			||||||
@@ -32,10 +33,13 @@ abstract class AppRouter {
 | 
				
			|||||||
  static GoRouter instance = GoRouter(
 | 
					  static GoRouter instance = GoRouter(
 | 
				
			||||||
    routes: [
 | 
					    routes: [
 | 
				
			||||||
      ShellRoute(
 | 
					      ShellRoute(
 | 
				
			||||||
        builder: (context, state, child) => RootShell(
 | 
					        builder: (context, state, child) => BootstrapperShell(
 | 
				
			||||||
 | 
					          key: const Key('global-bootstrapper'),
 | 
				
			||||||
 | 
					          child: RootShell(
 | 
				
			||||||
            state: state,
 | 
					            state: state,
 | 
				
			||||||
            child: child,
 | 
					            child: child,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
        routes: [
 | 
					        routes: [
 | 
				
			||||||
          GoRoute(
 | 
					          GoRoute(
 | 
				
			||||||
            path: '/',
 | 
					            path: '/',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -635,6 +635,14 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "4.5.0"
 | 
					    version: "4.5.0"
 | 
				
			||||||
 | 
					  flutter_app_update:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: flutter_app_update
 | 
				
			||||||
 | 
					      sha256: "2b83278d5cc807f543e623d5b466216316104335a4918d9cc4556f39985fe84a"
 | 
				
			||||||
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "3.1.0"
 | 
				
			||||||
  flutter_background_service:
 | 
					  flutter_background_service:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ name: solian
 | 
				
			|||||||
description: "The Solar Network App"
 | 
					description: "The Solar Network App"
 | 
				
			||||||
publish_to: "none"
 | 
					publish_to: "none"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
version: 1.2.1+40
 | 
					version: 1.2.1+41
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ">=3.3.4 <4.0.0"
 | 
					  sdk: ">=3.3.4 <4.0.0"
 | 
				
			||||||
@@ -80,6 +80,7 @@ dependencies:
 | 
				
			|||||||
  path_provider: ^2.1.4
 | 
					  path_provider: ^2.1.4
 | 
				
			||||||
  flutter_background_service: ^5.0.10
 | 
					  flutter_background_service: ^5.0.10
 | 
				
			||||||
  flutter_local_notifications: ^17.2.2
 | 
					  flutter_local_notifications: ^17.2.2
 | 
				
			||||||
 | 
					  flutter_app_update: ^3.1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user