✨ 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.autofocus" />
 | 
			
		||||
    <uses-permission android:name="android.permission.WAKE_LOCK" />
 | 
			
		||||
 
 | 
			
		||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
 | 
			
		||||
distributionPath=wrapper/dists
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
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 {
 | 
			
		||||
    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.firebase.crashlytics" version "2.8.1" apply false
 | 
			
		||||
    id "org.jetbrains.kotlin.android" version '2.0.0' apply false
 | 
			
		||||
 
 | 
			
		||||
@@ -68,6 +68,11 @@
 | 
			
		||||
  "notificationUnreadCount": "@count unread notifications",
 | 
			
		||||
  "errorHappened": "An error occurred",
 | 
			
		||||
  "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",
 | 
			
		||||
  "email": "Email",
 | 
			
		||||
  "username": "Username",
 | 
			
		||||
@@ -350,8 +355,7 @@
 | 
			
		||||
  "bsCheckForUpdate": "Checking For Updates",
 | 
			
		||||
  "bsCheckForUpdateFailed": "Unable to Check Updates",
 | 
			
		||||
  "bsCheckForUpdateNew": "Found New Version",
 | 
			
		||||
  "bsCheckForUpdateDescApple": "Please head to TestFlight 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.",
 | 
			
		||||
  "bsCheckForUpdateDesc": "Please head to app store and update your app to latest version to prevent error happens and get latest functions.",
 | 
			
		||||
  "bsCheckingServer": "Checking Server Status",
 | 
			
		||||
  "bsCheckingServerFail": "Unable connect to server, check your network connection",
 | 
			
		||||
  "bsCheckingServerDown": "Server currently unavailable, please retry later",
 | 
			
		||||
@@ -422,5 +426,7 @@
 | 
			
		||||
  "notificationTopicPostFeedback": "Post feedbacks",
 | 
			
		||||
  "notificationTopicPostSubscription": "Post subscriptions",
 | 
			
		||||
  "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": "正在检查更新",
 | 
			
		||||
  "bsCheckForUpdateFailed": "无法检查更新",
 | 
			
		||||
  "bsCheckForUpdateNew": "发现新版本",
 | 
			
		||||
  "bsCheckForUpdateDescApple": "请前往 TestFlight 并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。",
 | 
			
		||||
  "bsCheckForUpdateDescCommon": "请前往我们的网站下载并安装最新版本的应用程序,以防止出现错误并获取最新功能。",
 | 
			
		||||
  "bsCheckForUpdateDesc": "请前往应用商店并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。",
 | 
			
		||||
  "bsCheckingServer": "检查服务器状态中",
 | 
			
		||||
  "bsCheckingServerFail": "无法连接至服务器,请检查你的网络连接状态",
 | 
			
		||||
  "bsCheckingServerDown": "当前服务器不可用,请稍后重试",
 | 
			
		||||
@@ -423,5 +422,7 @@
 | 
			
		||||
  "notificationTopicPostFeedback": "帖子反馈",
 | 
			
		||||
  "notificationTopicPostSubscription": "订阅源",
 | 
			
		||||
  "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/services.dart';
 | 
			
		||||
import 'package:solian/widgets/sized_container.dart';
 | 
			
		||||
import 'package:flutter_app_update/flutter_app_update.dart';
 | 
			
		||||
 | 
			
		||||
class BootstrapperShell extends StatefulWidget {
 | 
			
		||||
  final Widget child;
 | 
			
		||||
@@ -49,15 +50,40 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
 | 
			
		||||
          final info = await PackageInfo.fromPlatform();
 | 
			
		||||
          final localVersionString = '${info.version}+${info.buildNumber}';
 | 
			
		||||
          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) {
 | 
			
		||||
            setState(() {
 | 
			
		||||
              _isErrored = true;
 | 
			
		||||
              _subtitle = PlatformInfo.isIOS || PlatformInfo.isMacOS
 | 
			
		||||
                  ? 'bsCheckForUpdateDescApple'.tr
 | 
			
		||||
                  : 'bsCheckForUpdateDescCommon'.tr;
 | 
			
		||||
              _subtitle = 'bsCheckForUpdateDesc'.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) {
 | 
			
		||||
          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) {
 | 
			
		||||
    Widget content = Text(exception.toString().capitalize!);
 | 
			
		||||
    if (exception is UnauthorizedException) {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:protocol_handler/protocol_handler.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:solian/background.dart';
 | 
			
		||||
import 'package:solian/bootstrapper.dart';
 | 
			
		||||
import 'package:solian/firebase_options.dart';
 | 
			
		||||
import 'package:solian/platform.dart';
 | 
			
		||||
import 'package:solian/providers/attachment_uploader.dart';
 | 
			
		||||
@@ -123,10 +122,8 @@ class SolianApp extends StatelessWidget {
 | 
			
		||||
          builder: (context, child) {
 | 
			
		||||
            return SystemShell(
 | 
			
		||||
              child: ScaffoldMessenger(
 | 
			
		||||
                child: BootstrapperShell(
 | 
			
		||||
                child: child ?? const SizedBox.shrink(),
 | 
			
		||||
              ),
 | 
			
		||||
              ),
 | 
			
		||||
            );
 | 
			
		||||
          },
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import 'package:animations/animations.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:solian/bootstrapper.dart';
 | 
			
		||||
import 'package:solian/models/realm.dart';
 | 
			
		||||
import 'package:solian/screens/about.dart';
 | 
			
		||||
import 'package:solian/screens/account.dart';
 | 
			
		||||
@@ -32,10 +33,13 @@ abstract class AppRouter {
 | 
			
		||||
  static GoRouter instance = GoRouter(
 | 
			
		||||
    routes: [
 | 
			
		||||
      ShellRoute(
 | 
			
		||||
        builder: (context, state, child) => RootShell(
 | 
			
		||||
        builder: (context, state, child) => BootstrapperShell(
 | 
			
		||||
          key: const Key('global-bootstrapper'),
 | 
			
		||||
          child: RootShell(
 | 
			
		||||
            state: state,
 | 
			
		||||
            child: child,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        routes: [
 | 
			
		||||
          GoRoute(
 | 
			
		||||
            path: '/',
 | 
			
		||||
 
 | 
			
		||||
@@ -635,6 +635,14 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    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:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ name: solian
 | 
			
		||||
description: "The Solar Network App"
 | 
			
		||||
publish_to: "none"
 | 
			
		||||
 | 
			
		||||
version: 1.2.1+40
 | 
			
		||||
version: 1.2.1+41
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  sdk: ">=3.3.4 <4.0.0"
 | 
			
		||||
@@ -80,6 +80,7 @@ dependencies:
 | 
			
		||||
  path_provider: ^2.1.4
 | 
			
		||||
  flutter_background_service: ^5.0.10
 | 
			
		||||
  flutter_local_notifications: ^17.2.2
 | 
			
		||||
  flutter_app_update: ^3.1.0
 | 
			
		||||
 | 
			
		||||
dev_dependencies:
 | 
			
		||||
  flutter_test:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user