Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
153c15e5c9 | |||
6a0f42cdc9 | |||
01aaa5455e | |||
f3ceb5f967 | |||
b5e2fa4c25 | |||
8378024490 | |||
6d40d6bba3 | |||
77075c8dab | |||
dec34e297d | |||
358677ade0 | |||
d2f37ae45d |
@ -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
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"settingsNotificationBgService": "Background Notification Service",
|
"settingsNotificationBgService": "Background notification service",
|
||||||
"settingsNotificationBgServiceDesc": "A notification service is always installed on the device, so that some devices that do not support push notifications can receive notifications in the background. When this feature is enabled, push notifications will not be registered with the server, and you will always appear to be online in the eyes of others (except for invisible). You may need to turn off power and traffic optimization in the settings.",
|
"settingsNotificationBgServiceDesc": "A notification service is always installed on the device, so that some devices that do not support push notifications can receive notifications in the background. When this feature is enabled, push notifications will not be registered with the server, and you will always appear to be online in the eyes of others (except for invisible). You may need to turn off power and traffic optimization in the settings.",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"post": "Post",
|
"post": "Post",
|
||||||
@ -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,11 @@
|
|||||||
"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.",
|
||||||
|
"update": "Update",
|
||||||
|
"updateCheckStrictly": "Strict mode",
|
||||||
|
"updateCheckStrictlyDesc": "If enabled, the app will ask for updating once the local version is different from remote one.",
|
||||||
|
"updateMayAvailable": "App version @version is available, you can update from app store or our website."
|
||||||
}
|
}
|
||||||
|
@ -351,8 +351,7 @@
|
|||||||
"bsCheckForUpdate": "正在检查更新",
|
"bsCheckForUpdate": "正在检查更新",
|
||||||
"bsCheckForUpdateFailed": "无法检查更新",
|
"bsCheckForUpdateFailed": "无法检查更新",
|
||||||
"bsCheckForUpdateNew": "发现新版本",
|
"bsCheckForUpdateNew": "发现新版本",
|
||||||
"bsCheckForUpdateDescApple": "请前往 TestFlight 并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。",
|
"bsCheckForUpdateDesc": "请前往应用商店并将您的应用程序更新到最新版本,以防止出现错误并获取最新功能。",
|
||||||
"bsCheckForUpdateDescCommon": "请前往我们的网站下载并安装最新版本的应用程序,以防止出现错误并获取最新功能。",
|
|
||||||
"bsCheckingServer": "检查服务器状态中",
|
"bsCheckingServer": "检查服务器状态中",
|
||||||
"bsCheckingServerFail": "无法连接至服务器,请检查你的网络连接状态",
|
"bsCheckingServerFail": "无法连接至服务器,请检查你的网络连接状态",
|
||||||
"bsCheckingServerDown": "当前服务器不可用,请稍后重试",
|
"bsCheckingServerDown": "当前服务器不可用,请稍后重试",
|
||||||
@ -423,5 +422,11 @@
|
|||||||
"notificationTopicPostFeedback": "帖子反馈",
|
"notificationTopicPostFeedback": "帖子反馈",
|
||||||
"notificationTopicPostSubscription": "订阅源",
|
"notificationTopicPostSubscription": "订阅源",
|
||||||
"preferencesApplied": "偏好设置已应用",
|
"preferencesApplied": "偏好设置已应用",
|
||||||
"save": "保存"
|
"save": "保存",
|
||||||
|
"updateAvailable": "有可用更新",
|
||||||
|
"updateAvailableDesc": "有可用更新 (@from 到 @to) 你想现在下载安装吗?在等待下载期间你仍可以正常使用。",
|
||||||
|
"update": "更新",
|
||||||
|
"updateCheckStrictly": "严格模式",
|
||||||
|
"updateCheckStrictlyDesc": "如果启用,应用程序将会在本地版本与远程版本不同时询问更新,而不会检查版本号大小。",
|
||||||
|
"updateMayAvailable": "版本 @version 现已可用,你可以前往应用商店或是我们的官网下载更新。"
|
||||||
}
|
}
|
||||||
|
@ -54,22 +54,22 @@ PODS:
|
|||||||
- Firebase/Performance (11.0.0):
|
- Firebase/Performance (11.0.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebasePerformance (~> 11.0.0)
|
- FirebasePerformance (~> 11.0.0)
|
||||||
- firebase_analytics (11.3.1):
|
- firebase_analytics (11.3.2):
|
||||||
- Firebase/Analytics (= 11.0.0)
|
- Firebase/Analytics (= 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_core (3.4.1):
|
- firebase_core (3.5.0):
|
||||||
- Firebase/CoreOnly (= 11.0.0)
|
- Firebase/CoreOnly (= 11.0.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_crashlytics (4.1.1):
|
- firebase_crashlytics (4.1.2):
|
||||||
- Firebase/Crashlytics (= 11.0.0)
|
- Firebase/Crashlytics (= 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (15.1.1):
|
- firebase_messaging (15.1.2):
|
||||||
- Firebase/Messaging (= 11.0.0)
|
- Firebase/Messaging (= 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_performance (0.10.0-6):
|
- firebase_performance (0.10.0-7):
|
||||||
- Firebase/Performance (= 11.0.0)
|
- Firebase/Performance (= 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -154,6 +154,8 @@ PODS:
|
|||||||
- PromisesSwift (~> 2.1)
|
- PromisesSwift (~> 2.1)
|
||||||
- FirebaseSharedSwift (11.2.0)
|
- FirebaseSharedSwift (11.2.0)
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_app_update (0.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_background_service_ios (0.0.3):
|
- flutter_background_service_ios (0.0.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_keyboard_visibility (0.0.1):
|
- flutter_keyboard_visibility (0.0.1):
|
||||||
@ -306,6 +308,7 @@ DEPENDENCIES:
|
|||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
|
- firebase_performance (from `.symlinks/plugins/firebase_performance/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||||
- flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`)
|
- flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`)
|
||||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
@ -383,6 +386,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_performance/ios"
|
:path: ".symlinks/plugins/firebase_performance/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_app_update:
|
||||||
|
:path: ".symlinks/plugins/flutter_app_update/ios"
|
||||||
flutter_background_service_ios:
|
flutter_background_service_ios:
|
||||||
:path: ".symlinks/plugins/flutter_background_service_ios/ios"
|
:path: ".symlinks/plugins/flutter_background_service_ios/ios"
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
@ -445,11 +450,11 @@ SPEC CHECKSUMS:
|
|||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
|
||||||
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
|
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
|
||||||
firebase_analytics: b8ce6c2c4b245d3c3bb3a147965d09da0f455959
|
firebase_analytics: 4fd10182fd08bb8358f26ac8aca8dad7b6d0f592
|
||||||
firebase_core: ba84e940cf5cbbc601095f86556560937419195c
|
firebase_core: 2ec6b789859c7c24766344ec71fdf78639402d56
|
||||||
firebase_crashlytics: 4111f8198b78c99471c955af488cecd8224967e6
|
firebase_crashlytics: 60630a0f91ee432275fa1660fd8593079761448a
|
||||||
firebase_messaging: c40f84e7a98da956d5262fada373b5c458edcf13
|
firebase_messaging: a18e1e02b2e8e69097c8173e0c851be223b21c50
|
||||||
firebase_performance: 8b7b9ca5adf3a9b3afa12b4eb96b9cabefc2c248
|
firebase_performance: 12d45fdf120992fa879d990929bf73d4a5ced053
|
||||||
FirebaseABTesting: 2104d957ce33888a3d6f3bde298cdee376dde8f1
|
FirebaseABTesting: 2104d957ce33888a3d6f3bde298cdee376dde8f1
|
||||||
FirebaseAnalytics: 27eb78b97880ea4a004839b9bac0b58880f5a92a
|
FirebaseAnalytics: 27eb78b97880ea4a004839b9bac0b58880f5a92a
|
||||||
FirebaseCore: 3cf438f431f18c12cdf2aaf64434648b63f7e383
|
FirebaseCore: 3cf438f431f18c12cdf2aaf64434648b63f7e383
|
||||||
@ -464,6 +469,7 @@ SPEC CHECKSUMS:
|
|||||||
FirebaseSessions: adcec8b72d0066a385e3affcd1bcb1ebb3908ce6
|
FirebaseSessions: adcec8b72d0066a385e3affcd1bcb1ebb3908ce6
|
||||||
FirebaseSharedSwift: 7a0d78d155ede78407f0fdc89fbc914014c7c540
|
FirebaseSharedSwift: 7a0d78d155ede78407f0fdc89fbc914014c7c540
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
|
flutter_app_update: 65f61da626cb111d1b24674abc4b01728d7723bc
|
||||||
flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac
|
flutter_background_service_ios: e30e0d3ee69e4cee66272d0c78eacd48c2e94aac
|
||||||
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
||||||
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:solian/exts.dart';
|
import 'package:solian/exts.dart';
|
||||||
import 'package:solian/platform.dart';
|
import 'package:solian/platform.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
@ -13,6 +16,8 @@ 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';
|
||||||
|
import 'package:version/version.dart';
|
||||||
|
|
||||||
class BootstrapperShell extends StatefulWidget {
|
class BootstrapperShell extends StatefulWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@ -34,6 +39,8 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
|
|
||||||
int _periodCursor = 0;
|
int _periodCursor = 0;
|
||||||
|
|
||||||
|
final Completer _bootCompleter = Completer();
|
||||||
|
|
||||||
late final List<({String label, Future<void> Function() action})> _periods = [
|
late final List<({String label, Future<void> Function() action})> _periods = [
|
||||||
(
|
(
|
||||||
label: 'bsLoadingTheme',
|
label: 'bsLoadingTheme',
|
||||||
@ -46,24 +53,60 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
action: () async {
|
action: () async {
|
||||||
if (PlatformInfo.isWeb) return;
|
if (PlatformInfo.isWeb) return;
|
||||||
try {
|
try {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
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) {
|
final remoteVersionString =
|
||||||
|
(resp.body as List).firstOrNull?['name'] ?? '0.0.0';
|
||||||
|
final remoteVersion = Version.parse(remoteVersionString ?? '0.0.0');
|
||||||
|
final localVersion =
|
||||||
|
Version.parse(localVersionString.split('+').first);
|
||||||
|
final strictUpdate = prefs.getBool('check_update_strictly') ?? false;
|
||||||
|
if (remoteVersion > localVersion ||
|
||||||
|
(remoteVersionString != localVersionString && strictUpdate)) {
|
||||||
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({
|
||||||
|
'from': localVersionString,
|
||||||
|
'to': remoteVersionString,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_isErrored = true;
|
||||||
|
_subtitle = 'bsCheckForUpdateDesc'.tr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (remoteVersionString != localVersionString) {
|
||||||
|
_bootCompleter.future.then((_) {
|
||||||
|
context.showSnackbar('updateMayAvailable'.trParams({
|
||||||
|
'version': remoteVersionString,
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setState(() {
|
context.showErrorDialog('Unable to check update: $e');
|
||||||
_isErrored = true;
|
|
||||||
_subtitle = 'bsCheckForUpdateFailed'.tr;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -154,6 +197,9 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
|
_bootCompleter.complete();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +297,9 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
|
|||||||
_isBusy = false;
|
_isBusy = false;
|
||||||
_isErrored = false;
|
_isErrored = false;
|
||||||
});
|
});
|
||||||
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
|
_bootCompleter.complete();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isBusy = true;
|
_isBusy = true;
|
||||||
|
@ -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,9 +122,7 @@ 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(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -89,13 +89,13 @@ class ChannelProvider extends GetxController {
|
|||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Response> listAvailableChannel({String realm = 'global'}) async {
|
Future<Response> listAvailableChannel({String scope = 'global'}) async {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
|
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
|
||||||
|
|
||||||
final client = await auth.configureClient('messaging');
|
final client = await auth.configureClient('messaging');
|
||||||
|
|
||||||
final resp = await client.get('/channels/$realm/me/available');
|
final resp = await client.get('/channels/$scope/me/available');
|
||||||
if (resp.statusCode != 200) {
|
if (resp.statusCode != 200) {
|
||||||
throw RequestException(resp);
|
throw RequestException(resp);
|
||||||
}
|
}
|
||||||
|
@ -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,9 +33,12 @@ 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(
|
||||||
state: state,
|
key: const Key('global-bootstrapper'),
|
||||||
child: child,
|
child: RootShell(
|
||||||
|
state: state,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
@ -115,6 +115,7 @@ class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
|
|||||||
leading: const Icon(Icons.settings),
|
leading: const Icon(Icons.settings),
|
||||||
trailing: const Icon(Icons.chevron_right),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
title: Text('channelSettings'.tr),
|
title: Text('channelSettings'.tr),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
AppRouter.instance
|
AppRouter.instance
|
||||||
.pushNamed(
|
.pushNamed(
|
||||||
@ -174,6 +175,7 @@ class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.notifications_active),
|
leading: const Icon(Icons.notifications_active),
|
||||||
title: Text('channelNotifyLevel'.tr),
|
title: Text('channelNotifyLevel'.tr),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
trailing: DropdownButtonHideUnderline(
|
trailing: DropdownButtonHideUnderline(
|
||||||
child: DropdownButton2<int>(
|
child: DropdownButton2<int>(
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
@ -206,6 +208,7 @@ class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
leading: const Icon(Icons.supervisor_account),
|
leading: const Icon(Icons.supervisor_account),
|
||||||
trailing: const Icon(Icons.chevron_right),
|
trailing: const Icon(Icons.chevron_right),
|
||||||
title: Text('channelMembers'.tr),
|
title: Text('channelMembers'.tr),
|
||||||
@ -214,6 +217,7 @@ class _ChannelDetailScreenState extends State<ChannelDetailScreen> {
|
|||||||
...(_isOwned ? ownerActions : List.empty()),
|
...(_isOwned ? ownerActions : List.empty()),
|
||||||
const Divider(thickness: 0.3),
|
const Divider(thickness: 0.3),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
leading: _isOwned
|
leading: _isOwned
|
||||||
? const Icon(Icons.delete)
|
? const Icon(Icons.delete)
|
||||||
: const Icon(Icons.exit_to_app),
|
: const Icon(Icons.exit_to_app),
|
||||||
|
@ -183,18 +183,18 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
tileColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
tileColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
title: Row(
|
title: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
_editorController.title ?? 'title'.tr,
|
_editorController.title ?? 'title'.tr,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
const Gap(6),
|
|
||||||
if (_editorController.aliasController.text.isNotEmpty)
|
if (_editorController.aliasController.text.isNotEmpty)
|
||||||
Badge(
|
Badge(
|
||||||
label: Text('#${_editorController.aliasController.text}'),
|
label: Text('#${_editorController.aliasController.text}'),
|
||||||
),
|
).paddingOnly(bottom: 2),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
|
@ -34,7 +34,7 @@ class _RealmViewScreenState extends State<RealmViewScreen> {
|
|||||||
final List<Channel> _channels = List.empty(growable: true);
|
final List<Channel> _channels = List.empty(growable: true);
|
||||||
|
|
||||||
getRealm({String? overrideAlias}) async {
|
getRealm({String? overrideAlias}) async {
|
||||||
final RealmProvider provider = Get.find();
|
final RealmProvider realm = Get.find();
|
||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class _RealmViewScreenState extends State<RealmViewScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final resp = await provider.getRealm(_overrideAlias ?? widget.alias);
|
final resp = await realm.getRealm(_overrideAlias ?? widget.alias);
|
||||||
setState(() => _realm = Realm.fromJson(resp.body));
|
setState(() => _realm = Realm.fromJson(resp.body));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showErrorDialog(e);
|
context.showErrorDialog(e);
|
||||||
@ -55,14 +55,26 @@ class _RealmViewScreenState extends State<RealmViewScreen> {
|
|||||||
getChannels() async {
|
getChannels() async {
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
final ChannelProvider provider = Get.find();
|
final ChannelProvider channel = Get.find();
|
||||||
final resp = await provider.listChannel(scope: _realm!.alias);
|
final resp = await channel.listChannel(scope: _realm!.alias);
|
||||||
|
final availableResp = await channel.listAvailableChannel(
|
||||||
|
scope: _realm!.alias,
|
||||||
|
);
|
||||||
|
|
||||||
|
final Set<int> channelIdx = {};
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_channels.clear();
|
_channels.clear();
|
||||||
_channels.addAll(
|
_channels.addAll(
|
||||||
resp.body.map((e) => Channel.fromJson(e)).toList().cast<Channel>(),
|
resp.body.map((e) => Channel.fromJson(e)).toList().cast<Channel>(),
|
||||||
);
|
);
|
||||||
|
_channels.addAll(
|
||||||
|
availableResp.body
|
||||||
|
.map((e) => Channel.fromJson(e))
|
||||||
|
.toList()
|
||||||
|
.cast<Channel>(),
|
||||||
|
);
|
||||||
|
_channels.retainWhere((x) => channelIdx.add(x.id));
|
||||||
});
|
});
|
||||||
|
|
||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
|
@ -114,6 +114,21 @@ class _SettingScreenState extends State<SettingScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
_buildCaptionHeader('update'.tr),
|
||||||
|
CheckboxListTile(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 22),
|
||||||
|
secondary: const Icon(Icons.sync_alt),
|
||||||
|
title: Text('updateCheckStrictly'.tr),
|
||||||
|
subtitle: Text('updateCheckStrictlyDesc'.tr),
|
||||||
|
value: _prefs?.getBool('check_update_strictly') ?? false,
|
||||||
|
onChanged: (value) {
|
||||||
|
_prefs
|
||||||
|
?.setBool('check_update_strictly', value ?? false)
|
||||||
|
.then((_) {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
_buildCaptionHeader('more'.tr),
|
_buildCaptionHeader('more'.tr),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete_sweep),
|
leading: const Icon(Icons.delete_sweep),
|
||||||
|
@ -484,7 +484,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${fileType[0].toUpperCase()}${fileType.substring(1)} · ${element.size.formatBytes()}',
|
'${fileType.isNotEmpty ? fileType.capitalize : 'unknown'.tr} · ${element.size.formatBytes()}',
|
||||||
style: const TextStyle(fontSize: 12),
|
style: const TextStyle(fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -233,6 +233,7 @@ class _AttachmentItemVideoState extends State<_AttachmentItemVideo> {
|
|||||||
final ratio = widget.item.metadata?['ratio'] ?? 16 / 9;
|
final ratio = widget.item.metadata?['ratio'] ?? 16 / 9;
|
||||||
if (!_showContent) {
|
if (!_showContent) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (widget.item.metadata?['thumbnail'] != null)
|
if (widget.item.metadata?['thumbnail'] != null)
|
||||||
@ -400,6 +401,7 @@ class _AttachmentItemAudioState extends State<_AttachmentItemAudio> {
|
|||||||
const ratio = 16 / 9;
|
const ratio = 16 / 9;
|
||||||
if (!_showContent) {
|
if (!_showContent) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (widget.item.metadata?['thumbnail'] != null)
|
if (widget.item.metadata?['thumbnail'] != null)
|
||||||
|
@ -10,6 +10,7 @@ class AutoCacheImage extends StatelessWidget {
|
|||||||
final BoxFit? fit;
|
final BoxFit? fit;
|
||||||
final bool noProgressIndicator;
|
final bool noProgressIndicator;
|
||||||
final bool noErrorWidget;
|
final bool noErrorWidget;
|
||||||
|
final bool isDense;
|
||||||
|
|
||||||
const AutoCacheImage(
|
const AutoCacheImage(
|
||||||
this.url, {
|
this.url, {
|
||||||
@ -19,6 +20,7 @@ class AutoCacheImage extends StatelessWidget {
|
|||||||
this.fit,
|
this.fit,
|
||||||
this.noProgressIndicator = false,
|
this.noProgressIndicator = false,
|
||||||
this.noErrorWidget = false,
|
this.noErrorWidget = false,
|
||||||
|
this.isDense = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -46,13 +48,14 @@ class AutoCacheImage extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.close, size: 32)
|
Icon(Icons.close, size: isDense ? 24 : 32)
|
||||||
.animate(onPlay: (e) => e.repeat(reverse: true))
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
.fade(duration: 500.ms),
|
.fade(duration: 500.ms),
|
||||||
Text(
|
if (!isDense)
|
||||||
error.toString(),
|
Text(
|
||||||
textAlign: TextAlign.center,
|
error.toString(),
|
||||||
),
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -89,13 +92,14 @@ class AutoCacheImage extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.close, size: 32)
|
Icon(Icons.close, size: isDense ? 24 : 32)
|
||||||
.animate(onPlay: (e) => e.repeat(reverse: true))
|
.animate(onPlay: (e) => e.repeat(reverse: true))
|
||||||
.fade(duration: 500.ms),
|
.fade(duration: 500.ms),
|
||||||
Text(
|
if (!isDense)
|
||||||
error.toString(),
|
Text(
|
||||||
textAlign: TextAlign.center,
|
error.toString(),
|
||||||
),
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -415,6 +415,7 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
x.imageUrl,
|
x.imageUrl,
|
||||||
width: 28,
|
width: 28,
|
||||||
height: 28,
|
height: 28,
|
||||||
|
isDense: true,
|
||||||
),
|
),
|
||||||
display: x.name,
|
display: x.name,
|
||||||
content: x.textWarpedPlaceholder,
|
content: x.textWarpedPlaceholder,
|
||||||
|
@ -14,12 +14,14 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
final String content;
|
final String content;
|
||||||
final String parentId;
|
final String parentId;
|
||||||
final bool isSelectable;
|
final bool isSelectable;
|
||||||
|
final bool isLargeText;
|
||||||
|
|
||||||
const MarkdownTextContent({
|
const MarkdownTextContent({
|
||||||
super.key,
|
super.key,
|
||||||
required this.content,
|
required this.content,
|
||||||
required this.parentId,
|
required this.parentId,
|
||||||
this.isSelectable = false,
|
this.isSelectable = false,
|
||||||
|
this.isLargeText = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget _buildContent(BuildContext context) {
|
Widget _buildContent(BuildContext context) {
|
||||||
@ -35,6 +37,14 @@ class MarkdownTextContent extends StatelessWidget {
|
|||||||
styleSheet: MarkdownStyleSheet.fromTheme(
|
styleSheet: MarkdownStyleSheet.fromTheme(
|
||||||
Theme.of(context),
|
Theme.of(context),
|
||||||
).copyWith(
|
).copyWith(
|
||||||
|
textScaleFactor: isLargeText ? 1.1 : 1,
|
||||||
|
blockquote: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
blockquoteDecoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||||
|
),
|
||||||
horizontalRuleDecoration: BoxDecoration(
|
horizontalRuleDecoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
top: BorderSide(
|
top: BorderSide(
|
||||||
|
@ -341,64 +341,67 @@ class _PostItemState extends State<PostItem> {
|
|||||||
if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
return Card(
|
return Container(
|
||||||
margin: EdgeInsets.zero,
|
constraints: const BoxConstraints(maxWidth: 480),
|
||||||
child: Column(
|
child: Card(
|
||||||
children: snapshot.data!
|
margin: EdgeInsets.zero,
|
||||||
.map(
|
child: Column(
|
||||||
(x) => Row(
|
children: snapshot.data!
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
.map(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
(x) => Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
AccountAvatar(content: x.author.avatar, radius: 10),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const Gap(6),
|
children: [
|
||||||
Text(
|
AccountAvatar(content: x.author.avatar, radius: 10),
|
||||||
x.author.nick,
|
const Gap(6),
|
||||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
Text(
|
||||||
),
|
x.author.nick,
|
||||||
const Gap(6),
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
Text(
|
|
||||||
format(
|
|
||||||
x.publishedAt?.toLocal() ?? DateTime.now(),
|
|
||||||
locale: 'en_short',
|
|
||||||
),
|
),
|
||||||
).paddingOnly(top: 0.5),
|
const Gap(6),
|
||||||
const Gap(8),
|
Text(
|
||||||
Expanded(
|
format(
|
||||||
child: Column(
|
x.publishedAt?.toLocal() ?? DateTime.now(),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
locale: 'en_short',
|
||||||
children: [
|
),
|
||||||
MarkdownTextContent(
|
).paddingOnly(top: 0.5),
|
||||||
content: x.body['content'],
|
const Gap(8),
|
||||||
parentId: 'p${item.id}-featured-reply${x.id}',
|
Expanded(
|
||||||
),
|
child: Column(
|
||||||
if (x.body['attachments'] is List &&
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
x.body['attachments'].length > 0)
|
children: [
|
||||||
Row(
|
MarkdownTextContent(
|
||||||
children: [
|
content: x.body['content'],
|
||||||
Icon(
|
parentId: 'p${item.id}-featured-reply${x.id}',
|
||||||
Icons.file_copy,
|
|
||||||
size: 15,
|
|
||||||
color: unFocusColor,
|
|
||||||
).paddingOnly(right: 5),
|
|
||||||
Text(
|
|
||||||
'attachmentHint'.trParams(
|
|
||||||
{
|
|
||||||
'count': x.body['attachments'].length
|
|
||||||
.toString()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
style: TextStyle(color: unFocusColor),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
if (x.body['attachments'] is List &&
|
||||||
|
x.body['attachments'].length > 0)
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.file_copy,
|
||||||
|
size: 15,
|
||||||
|
color: unFocusColor,
|
||||||
|
).paddingOnly(right: 5),
|
||||||
|
Text(
|
||||||
|
'attachmentHint'.trParams(
|
||||||
|
{
|
||||||
|
'count': x.body['attachments'].length
|
||||||
|
.toString()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
style: TextStyle(color: unFocusColor),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
).paddingSymmetric(horizontal: 12, vertical: 8),
|
||||||
).paddingSymmetric(horizontal: 12, vertical: 8),
|
)
|
||||||
)
|
.toList(),
|
||||||
.toList(),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.animate()
|
.animate()
|
||||||
@ -550,6 +553,8 @@ class _PostItemState extends State<PostItem> {
|
|||||||
parentId: 'p${item.id}-embed',
|
parentId: 'p${item.id}-embed',
|
||||||
content: item.body['content'],
|
content: item.body['content'],
|
||||||
isSelectable: widget.isContentSelectable,
|
isSelectable: widget.isContentSelectable,
|
||||||
|
isLargeText: item.type == 'article' &&
|
||||||
|
widget.isFullContent,
|
||||||
).paddingOnly(left: 12, right: 8),
|
).paddingOnly(left: 12, right: 8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -21,19 +21,19 @@ PODS:
|
|||||||
- Firebase/Messaging (11.0.0):
|
- Firebase/Messaging (11.0.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 11.0.0)
|
- FirebaseMessaging (~> 11.0.0)
|
||||||
- firebase_analytics (11.3.1):
|
- firebase_analytics (11.3.2):
|
||||||
- Firebase/Analytics (= 11.0.0)
|
- Firebase/Analytics (= 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_core (3.4.1):
|
- firebase_core (3.5.0):
|
||||||
- Firebase/CoreOnly (~> 11.0.0)
|
- Firebase/CoreOnly (~> 11.0.0)
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_crashlytics (4.1.1):
|
- firebase_crashlytics (4.1.2):
|
||||||
- Firebase/CoreOnly (~> 11.0.0)
|
- Firebase/CoreOnly (~> 11.0.0)
|
||||||
- Firebase/Crashlytics (~> 11.0.0)
|
- Firebase/Crashlytics (~> 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_messaging (15.1.1):
|
- firebase_messaging (15.1.2):
|
||||||
- Firebase/CoreOnly (~> 11.0.0)
|
- Firebase/CoreOnly (~> 11.0.0)
|
||||||
- Firebase/Messaging (~> 11.0.0)
|
- Firebase/Messaging (~> 11.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
@ -338,10 +338,10 @@ SPEC CHECKSUMS:
|
|||||||
device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720
|
device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720
|
||||||
file_selector_macos: 54fdab7caa3ac3fc43c9fac4d7d8d231277f8cf2
|
file_selector_macos: 54fdab7caa3ac3fc43c9fac4d7d8d231277f8cf2
|
||||||
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
|
Firebase: 9f574c08c2396885b5e7e100ed4293d956218af9
|
||||||
firebase_analytics: 2169e28bb3ee1f765efe0fd4f5b5f625d92fda13
|
firebase_analytics: a2d0d907566e4a48e27745317f05b4b7db85edd9
|
||||||
firebase_core: 3f80bec72646b26618f0497e74ce8bcd608f03ca
|
firebase_core: c55630cdb8a01cf49eae741dd4bc8c93bdd546b8
|
||||||
firebase_crashlytics: 6b1e511297406a6efd4405dc6301da8843b9dfe1
|
firebase_crashlytics: a359f1f75a23e560c8c97b743ab684ba795d7688
|
||||||
firebase_messaging: ce70e6615f0cd906d80b7a651b960d76dad6de56
|
firebase_messaging: 12726b352752420d073ff075e328cc2f0ca14c47
|
||||||
FirebaseAnalytics: 27eb78b97880ea4a004839b9bac0b58880f5a92a
|
FirebaseAnalytics: 27eb78b97880ea4a004839b9bac0b58880f5a92a
|
||||||
FirebaseCore: 3cf438f431f18c12cdf2aaf64434648b63f7e383
|
FirebaseCore: 3cf438f431f18c12cdf2aaf64434648b63f7e383
|
||||||
FirebaseCoreExtension: cda74ddfb001224bd8fd1d6e74698b4ed07803de
|
FirebaseCoreExtension: cda74ddfb001224bd8fd1d6e74698b4ed07803de
|
||||||
|
76
pubspec.lock
76
pubspec.lock
@ -13,10 +13,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
sha256: ddc6f775260b89176d329dee26f88b9469ef46aa3228ff6a0b91caf2b2989692
|
sha256: "5fdcea390499dd26c808a3c662df5f4208d6bbc0643072eee94f1476249e2818"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.42"
|
version: "1.3.43"
|
||||||
_macros:
|
_macros:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: dart
|
description: dart
|
||||||
@ -490,114 +490,114 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_analytics
|
name: firebase_analytics
|
||||||
sha256: "7b5ae39d853ead76f9d030dc23389bfec4ea826d7cccb4eea4873dcb0cdd172b"
|
sha256: "9c52c099e9cbb852c7f1d2302c7eb34a15758834eca1877f7a779e6082f9882d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.3.1"
|
version: "11.3.2"
|
||||||
firebase_analytics_platform_interface:
|
firebase_analytics_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_analytics_platform_interface
|
name: firebase_analytics_platform_interface
|
||||||
sha256: "0205e05bb37abd29d5dec5cd89aeb04f3f58bf849aad21dd938be0507d52a40c"
|
sha256: "4ec57aee951832fdbf10ca722bbb83fe0001d6168d6c4cfea9ccee0df6afb1e0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.3"
|
version: "4.2.4"
|
||||||
firebase_analytics_web:
|
firebase_analytics_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_analytics_web
|
name: firebase_analytics_web
|
||||||
sha256: "434807f8b30526e21cc062410c28ee5c6680a13626c4443b5ffede29f84b0c74"
|
sha256: "95c594fb1e8960992a607b135459e2f9ea3683dd8d01e6b845cace7c6665ec7e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.10"
|
version: "0.5.10+1"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: "40921de9795fbf5887ed5c0adfdf4972d5a8d7ae7e1b2bb98dea39bc02626a88"
|
sha256: c7de9354eb2cd8bfe8059e1112174c9a58beda7051807207306bc48283277cfb
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.1"
|
version: "3.5.0"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_platform_interface
|
name: firebase_core_platform_interface
|
||||||
sha256: f7d7180c7f99babd4b4c517754d41a09a4943a0f7a69b65c894ca5c68ba66315
|
sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.1"
|
version: "5.3.0"
|
||||||
firebase_core_web:
|
firebase_core_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_web
|
name: firebase_core_web
|
||||||
sha256: f4ee170441ca141c5f9ee5ad8737daba3ee9c8e7efb6902aee90b4fbd178ce25
|
sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.18.0"
|
version: "2.18.1"
|
||||||
firebase_crashlytics:
|
firebase_crashlytics:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_crashlytics
|
name: firebase_crashlytics
|
||||||
sha256: c4fdbb14ba6f36794f89dc27fb5c759c9cc67ecbaeb079edc4dba515bbf9f555
|
sha256: "7821f9d8373b91f2a5ca8214226891d5870e196a7376f66350f65204387e9c15"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.1"
|
version: "4.1.2"
|
||||||
firebase_crashlytics_platform_interface:
|
firebase_crashlytics_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_crashlytics_platform_interface
|
name: firebase_crashlytics_platform_interface
|
||||||
sha256: "891d6f7ba4b93672d0e1265f27b6a9dccd56ba2cc30ce6496586b32d1d8770ac"
|
sha256: "8ed539fd9e9b6c07905f9f44c5f6d4785ac841a5a8195bd35586c8b1d54ec26d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.6.42"
|
version: "3.6.43"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging
|
name: firebase_messaging
|
||||||
sha256: cc02c4afd6510cd84586020670140c4a23fbe52af16cd260ccf8ede101bb8d1b
|
sha256: "32ce60b747e755b48d7112d728d4f736ba82acd98ec825626558d444d385fa3a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.1.1"
|
version: "15.1.2"
|
||||||
firebase_messaging_platform_interface:
|
firebase_messaging_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_platform_interface
|
name: firebase_messaging_platform_interface
|
||||||
sha256: d8a4984635f09213302243ea670fe5c42f3261d7d8c7c0a5f7dcd5d6c84be459
|
sha256: "69671a0f1a40c7b7c46ad0283e6f34ca2a59a0362ca14a240a4ea01c46e8a521"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.5.44"
|
version: "4.5.45"
|
||||||
firebase_messaging_web:
|
firebase_messaging_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_web
|
name: firebase_messaging_web
|
||||||
sha256: "258b9d637965db7855299b123533609ed95e52350746a723dfd1d8d6f3fac678"
|
sha256: "6890111a9d01d7b13d0f6fe74850812c334e903d2c80a2d9356a3abb8c3a9e9a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.9.0"
|
version: "3.9.1"
|
||||||
firebase_performance:
|
firebase_performance:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_performance
|
name: firebase_performance
|
||||||
sha256: "879ce4d83242cb7d1ec67a8b45daa351f230211778e34eeea979894839c4832a"
|
sha256: ed9a408b6d1f221fc0e2890dcf0733b604d1aea6cd3b897f97dd3f889f01ddfc
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.10.0+6"
|
version: "0.10.0+7"
|
||||||
firebase_performance_platform_interface:
|
firebase_performance_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_performance_platform_interface
|
name: firebase_performance_platform_interface
|
||||||
sha256: ac68eba644f593903a931ba7f26f0677b725d5a60f8f7bc0fed01d88a11d1463
|
sha256: bfcfbfcefeaf3853a72602675b786e13a609d49ac70fc325d302b5794b8b0c06
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.4+42"
|
version: "0.1.4+43"
|
||||||
firebase_performance_web:
|
firebase_performance_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_performance_web
|
name: firebase_performance_web
|
||||||
sha256: ff53b9c5d8601fc983d0173b88fdfd8abcc74948f0a3753f3c1ec276b680f23c
|
sha256: "2ac9e44a1be7b20f1a7a3912d84bf2e1ec76398f2dadc07b6b7c3173d590e329"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.7"
|
version: "0.1.7+1"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -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:
|
||||||
@ -2130,6 +2138,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
version:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: version
|
||||||
|
sha256: "3d4140128e6ea10d83da32fef2fa4003fccbf6852217bb854845802f04191f94"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
very_good_infinite_list:
|
very_good_infinite_list:
|
||||||
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.2+2
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.4 <4.0.0"
|
sdk: ">=3.3.4 <4.0.0"
|
||||||
@ -80,6 +80,8 @@ 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
|
||||||
|
version: ^3.0.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Reference in New Issue
Block a user