♻️ Add splash screen for loading data
This commit is contained in:
parent
c7d5cb48ac
commit
f763c7515a
@ -407,6 +407,7 @@
|
|||||||
"articleWrittenAt": "Written at {}",
|
"articleWrittenAt": "Written at {}",
|
||||||
"articleEditedAt": "Edited at {}",
|
"articleEditedAt": "Edited at {}",
|
||||||
"attachmentSaved": "Saved to album",
|
"attachmentSaved": "Saved to album",
|
||||||
|
"attachmentSavedDesktop": "Saved to Downloads folder",
|
||||||
"openInAlbum": "Open in album",
|
"openInAlbum": "Open in album",
|
||||||
"postAbuseReport": "Report Post",
|
"postAbuseReport": "Report Post",
|
||||||
"postAbuseReportDescription": "Report posts that violate our user agreement and community guidelines to help us improve the content on Solar Network. Please describe how this post violates the relevant rules. Do not include any sensitive information. We will process your report within 24 hours.",
|
"postAbuseReportDescription": "Report posts that violate our user agreement and community guidelines to help us improve the content on Solar Network. Please describe how this post violates the relevant rules. Do not include any sensitive information. We will process your report within 24 hours.",
|
||||||
@ -442,5 +443,6 @@
|
|||||||
"postImageShareReadMore": "Scan the QR code to read full post",
|
"postImageShareReadMore": "Scan the QR code to read full post",
|
||||||
"postImageShareAds": "Explore posts on the Solar Network",
|
"postImageShareAds": "Explore posts on the Solar Network",
|
||||||
"postShare": "Share",
|
"postShare": "Share",
|
||||||
"postShareImage": "Share via Image"
|
"postShareImage": "Share via Image",
|
||||||
|
"appInitializing": "Initializing"
|
||||||
}
|
}
|
||||||
|
@ -405,6 +405,7 @@
|
|||||||
"articleWrittenAt": "发表于 {}",
|
"articleWrittenAt": "发表于 {}",
|
||||||
"articleEditedAt": "编辑于 {}",
|
"articleEditedAt": "编辑于 {}",
|
||||||
"attachmentSaved": "已保存到相册",
|
"attachmentSaved": "已保存到相册",
|
||||||
|
"attachmentSavedDesktop": "已保存到下载目录",
|
||||||
"openInAlbum": "在相册中打开",
|
"openInAlbum": "在相册中打开",
|
||||||
"postAbuseReport": "检举帖子",
|
"postAbuseReport": "检举帖子",
|
||||||
"postAbuseReportDescription": "检举不符合我们用户协议以及社区准则的帖子,来帮助我们更好的维护 Solar Network 上的内容。请在下面描述该帖子如何违反我么的相关规定。请勿填写任何敏感信息。我们将会在 24 小时内处理您的检举。",
|
"postAbuseReportDescription": "检举不符合我们用户协议以及社区准则的帖子,来帮助我们更好的维护 Solar Network 上的内容。请在下面描述该帖子如何违反我么的相关规定。请勿填写任何敏感信息。我们将会在 24 小时内处理您的检举。",
|
||||||
@ -440,5 +441,6 @@
|
|||||||
"postImageShareReadMore": "扫描右侧 QRCode 查看全文",
|
"postImageShareReadMore": "扫描右侧 QRCode 查看全文",
|
||||||
"postImageShareAds": "来 Solar Network 探索更多有趣帖子",
|
"postImageShareAds": "来 Solar Network 探索更多有趣帖子",
|
||||||
"postShare": "分享",
|
"postShare": "分享",
|
||||||
"postShareImage": "分享帖图"
|
"postShareImage": "分享帖图",
|
||||||
|
"appInitializing": "正在初始化"
|
||||||
}
|
}
|
||||||
|
@ -405,6 +405,7 @@
|
|||||||
"articleWrittenAt": "發表於 {}",
|
"articleWrittenAt": "發表於 {}",
|
||||||
"articleEditedAt": "編輯於 {}",
|
"articleEditedAt": "編輯於 {}",
|
||||||
"attachmentSaved": "已保存到相冊",
|
"attachmentSaved": "已保存到相冊",
|
||||||
|
"attachmentSavedDesktop": "已保存到下載目錄",
|
||||||
"openInAlbum": "在相冊中打開",
|
"openInAlbum": "在相冊中打開",
|
||||||
"postAbuseReport": "檢舉帖子",
|
"postAbuseReport": "檢舉帖子",
|
||||||
"postAbuseReportDescription": "檢舉不符合我們用户協議以及社區準則的帖子,來幫助我們更好的維護 Solar Network 上的內容。請在下面描述該帖子如何違反我麼的相關規定。請勿填寫任何敏感信息。我們將會在 24 小時內處理您的檢舉。",
|
"postAbuseReportDescription": "檢舉不符合我們用户協議以及社區準則的帖子,來幫助我們更好的維護 Solar Network 上的內容。請在下面描述該帖子如何違反我麼的相關規定。請勿填寫任何敏感信息。我們將會在 24 小時內處理您的檢舉。",
|
||||||
|
@ -405,6 +405,7 @@
|
|||||||
"articleWrittenAt": "發表於 {}",
|
"articleWrittenAt": "發表於 {}",
|
||||||
"articleEditedAt": "編輯於 {}",
|
"articleEditedAt": "編輯於 {}",
|
||||||
"attachmentSaved": "已儲存到相簿",
|
"attachmentSaved": "已儲存到相簿",
|
||||||
|
"attachmentSavedDesktop": "已儲存到下載目錄",
|
||||||
"openInAlbum": "在相簿中開啟",
|
"openInAlbum": "在相簿中開啟",
|
||||||
"postAbuseReport": "檢舉帖子",
|
"postAbuseReport": "檢舉帖子",
|
||||||
"postAbuseReportDescription": "檢舉不符合我們使用者協議以及社群準則的帖子,來幫助我們更好的維護 Solar Network 上的內容。請在下面描述該帖子如何違反我麼的相關規定。請勿填寫任何敏感資訊。我們將會在 24 小時內處理您的檢舉。",
|
"postAbuseReportDescription": "檢舉不符合我們使用者協議以及社群準則的帖子,來幫助我們更好的維護 Solar Network 上的內容。請在下面描述該帖子如何違反我麼的相關規定。請勿填寫任何敏感資訊。我們將會在 24 小時內處理您的檢舉。",
|
||||||
|
@ -7,11 +7,13 @@ import 'package:easy_localization_loader/easy_localization_loader.dart';
|
|||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
import 'package:responsive_framework/responsive_framework.dart';
|
import 'package:responsive_framework/responsive_framework.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/firebase_options.dart';
|
import 'package:surface/firebase_options.dart';
|
||||||
import 'package:surface/providers/channel.dart';
|
import 'package:surface/providers/channel.dart';
|
||||||
import 'package:surface/providers/chat_call.dart';
|
import 'package:surface/providers/chat_call.dart';
|
||||||
@ -29,6 +31,7 @@ import 'package:surface/router.dart';
|
|||||||
import 'package:surface/types/chat.dart';
|
import 'package:surface/types/chat.dart';
|
||||||
import 'package:surface/types/realm.dart';
|
import 'package:surface/types/realm.dart';
|
||||||
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
|
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
|
||||||
|
import 'package:surface/widgets/dialog.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@ -94,7 +97,7 @@ class SolianApp extends StatelessWidget {
|
|||||||
ChangeNotifierProvider(create: (ctx) => ChatChannelProvider(ctx)),
|
ChangeNotifierProvider(create: (ctx) => ChatChannelProvider(ctx)),
|
||||||
ChangeNotifierProvider(create: (ctx) => ChatCallProvider(ctx)),
|
ChangeNotifierProvider(create: (ctx) => ChatCallProvider(ctx)),
|
||||||
],
|
],
|
||||||
child: AppMainContent(),
|
child: _AppDelegate(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
breakpoints: [
|
breakpoints: [
|
||||||
@ -106,8 +109,8 @@ class SolianApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppMainContent extends StatelessWidget {
|
class _AppDelegate extends StatelessWidget {
|
||||||
const AppMainContent({super.key});
|
const _AppDelegate({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -129,6 +132,76 @@ class AppMainContent extends StatelessWidget {
|
|||||||
...context.localizationDelegates,
|
...context.localizationDelegates,
|
||||||
],
|
],
|
||||||
routerConfig: appRouter,
|
routerConfig: appRouter,
|
||||||
|
builder: (context, child) {
|
||||||
|
return _AppSplashScreen(child: child!);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AppSplashScreen extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const _AppSplashScreen({super.key, required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_AppSplashScreen> createState() => _AppSplashScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppSplashScreenState extends State<_AppSplashScreen> {
|
||||||
|
bool _isReady = false;
|
||||||
|
|
||||||
|
Future<void> _initialize() async {
|
||||||
|
try {
|
||||||
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
await sn.initializeUserAgent();
|
||||||
|
if (!mounted) return;
|
||||||
|
final ua = context.read<UserProvider>();
|
||||||
|
await ua.initialize();
|
||||||
|
if (!mounted) return;
|
||||||
|
final ws = context.read<WebSocketProvider>();
|
||||||
|
await ws.tryConnect();
|
||||||
|
if (!mounted) return;
|
||||||
|
final notify = context.read<NotificationProvider>();
|
||||||
|
await notify.registerPushNotifications();
|
||||||
|
} catch (err) {
|
||||||
|
if (!mounted) return;
|
||||||
|
await context.showErrorDialog(err);
|
||||||
|
} finally {
|
||||||
|
setState(() => _isReady = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (!_isReady) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
|
body: Container(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 180),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Image.asset("assets/icon/icon.png", width: 64, height: 64),
|
||||||
|
const Gap(6),
|
||||||
|
LinearProgressIndicator(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
),
|
||||||
|
const Gap(20),
|
||||||
|
Text('appInitializing'.tr(), textAlign: TextAlign.center),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).center(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return widget.child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,14 +16,6 @@ class NotificationProvider extends ChangeNotifier {
|
|||||||
NotificationProvider(BuildContext context) {
|
NotificationProvider(BuildContext context) {
|
||||||
_sn = context.read<SnNetworkProvider>();
|
_sn = context.read<SnNetworkProvider>();
|
||||||
_ua = context.read<UserProvider>();
|
_ua = context.read<UserProvider>();
|
||||||
|
|
||||||
// Delay to wait user provider ready to use
|
|
||||||
Future.delayed(const Duration(milliseconds: 3000), () async {
|
|
||||||
if (!_ua.isAuthorized) return;
|
|
||||||
log("Registering push notifications...");
|
|
||||||
await registerPushNotifications();
|
|
||||||
log("Registered push notification subscriber successfully!");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> registerPushNotifications() async {
|
Future<void> registerPushNotifications() async {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:synchronized/synchronized.dart';
|
import 'package:synchronized/synchronized.dart';
|
||||||
|
|
||||||
@ -23,6 +27,8 @@ class SnNetworkProvider {
|
|||||||
|
|
||||||
late final SharedPreferences _prefs;
|
late final SharedPreferences _prefs;
|
||||||
|
|
||||||
|
String? _userAgent;
|
||||||
|
|
||||||
SnNetworkProvider() {
|
SnNetworkProvider() {
|
||||||
client = Dio();
|
client = Dio();
|
||||||
|
|
||||||
@ -46,6 +52,9 @@ class SnNetworkProvider {
|
|||||||
if (atk != null) {
|
if (atk != null) {
|
||||||
options.headers['Authorization'] = 'Bearer $atk';
|
options.headers['Authorization'] = 'Bearer $atk';
|
||||||
}
|
}
|
||||||
|
if (_userAgent != null) {
|
||||||
|
options.headers['User-Agent'] = _userAgent!;
|
||||||
|
}
|
||||||
return handler.next(options);
|
return handler.next(options);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -53,11 +62,39 @@ class SnNetworkProvider {
|
|||||||
|
|
||||||
SharedPreferences.getInstance().then((prefs) {
|
SharedPreferences.getInstance().then((prefs) {
|
||||||
_prefs = prefs;
|
_prefs = prefs;
|
||||||
client.options.baseUrl =
|
client.options.baseUrl = _prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault;
|
||||||
_prefs.getString(kNetworkServerStoreKey) ?? kNetworkServerDefault;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> initializeUserAgent() async {
|
||||||
|
final String platformInfo;
|
||||||
|
if (kIsWeb) {
|
||||||
|
final deviceInfo = await DeviceInfoPlugin().webBrowserInfo;
|
||||||
|
platformInfo = 'Web; ${deviceInfo.vendor}';
|
||||||
|
} else if (Platform.isAndroid) {
|
||||||
|
final deviceInfo = await DeviceInfoPlugin().androidInfo;
|
||||||
|
platformInfo = 'Android; ${deviceInfo.brand} ${deviceInfo.model}; ${deviceInfo.id}';
|
||||||
|
} else if (Platform.isIOS) {
|
||||||
|
final deviceInfo = await DeviceInfoPlugin().iosInfo;
|
||||||
|
platformInfo = 'iOS; ${deviceInfo.model}; ${deviceInfo.name}';
|
||||||
|
} else if (Platform.isMacOS) {
|
||||||
|
final deviceInfo = await DeviceInfoPlugin().macOsInfo;
|
||||||
|
platformInfo = 'MacOS; ${deviceInfo.model}; ${deviceInfo.hostName}';
|
||||||
|
} else if (Platform.isWindows) {
|
||||||
|
final deviceInfo = await DeviceInfoPlugin().windowsInfo;
|
||||||
|
platformInfo = 'Windows NT; ${deviceInfo.productName}; ${deviceInfo.computerName}';
|
||||||
|
} else if (Platform.isLinux) {
|
||||||
|
final deviceInfo = await DeviceInfoPlugin().linuxInfo;
|
||||||
|
platformInfo = 'Linux; ${deviceInfo.prettyName}';
|
||||||
|
} else {
|
||||||
|
platformInfo = 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
|
_userAgent = 'Solian/${packageInfo.version}+${packageInfo.buildNumber} ($platformInfo)';
|
||||||
|
}
|
||||||
|
|
||||||
final tkLock = Lock();
|
final tkLock = Lock();
|
||||||
|
|
||||||
Completer<String?>? _refreshCompleter;
|
Completer<String?>? _refreshCompleter;
|
||||||
|
@ -19,16 +19,17 @@ class UserProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
UserProvider(BuildContext context) {
|
UserProvider(BuildContext context) {
|
||||||
_sn = context.read<SnNetworkProvider>();
|
_sn = context.read<SnNetworkProvider>();
|
||||||
|
}
|
||||||
|
|
||||||
SharedPreferences.getInstance().then((prefs) {
|
Future<void> initialize() async {
|
||||||
final value = prefs.getString(kAtkStoreKey);
|
final prefs = await SharedPreferences.getInstance();
|
||||||
isAuthorized = value != null;
|
final value = prefs.getString(kAtkStoreKey);
|
||||||
notifyListeners();
|
isAuthorized = value != null;
|
||||||
refreshUser().then((value) {
|
notifyListeners();
|
||||||
if (value != null) {
|
refreshUser().then((value) {
|
||||||
log('Logged in as @${value.name}');
|
if (value != null) {
|
||||||
}
|
log('Logged in as @${value.name}');
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,16 +23,13 @@ class WebSocketProvider extends ChangeNotifier {
|
|||||||
WebSocketProvider(BuildContext context) {
|
WebSocketProvider(BuildContext context) {
|
||||||
_sn = context.read<SnNetworkProvider>();
|
_sn = context.read<SnNetworkProvider>();
|
||||||
_ua = context.read<UserProvider>();
|
_ua = context.read<UserProvider>();
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for the userinfo provide initialize authorization status
|
Future<void> tryConnect() async {
|
||||||
Future.delayed(const Duration(milliseconds: 250), () async {
|
if (!_ua.isAuthorized) return;
|
||||||
if (_ua.isAuthorized) {
|
|
||||||
log('[WebSocket] Connecting to the server...');
|
log('[WebSocket] Connecting to the server...');
|
||||||
await connect();
|
await connect();
|
||||||
} else {
|
|
||||||
log('[WebSocket] Unable connect to the server, unauthorized.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> connect({noRetry = false}) async {
|
Future<void> connect({noRetry = false}) async {
|
||||||
|
@ -65,10 +65,6 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await Gal.hasAccess(toAlbum: true)) {
|
|
||||||
if (!await Gal.requestAccess(toAlbum: true)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() => _isDownloading = true);
|
setState(() => _isDownloading = true);
|
||||||
|
|
||||||
var extName = extension(item.name);
|
var extName = extension(item.name);
|
||||||
@ -85,6 +81,9 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
bool isSuccess = false;
|
bool isSuccess = false;
|
||||||
try {
|
try {
|
||||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
|
if (!await Gal.hasAccess(toAlbum: true)) {
|
||||||
|
if (!await Gal.requestAccess(toAlbum: true)) return;
|
||||||
|
}
|
||||||
await Gal.putImage(imagePath, album: 'Solar Network');
|
await Gal.putImage(imagePath, album: 'Solar Network');
|
||||||
} else {
|
} else {
|
||||||
await FileSaver.instance.saveFile(
|
await FileSaver.instance.saveFile(
|
||||||
@ -104,11 +103,13 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
|
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
context.showSnackbar(
|
context.showSnackbar(
|
||||||
'attachmentSaved'.tr(),
|
(!kIsWeb && (Platform.isIOS || Platform.isAndroid)) ? 'attachmentSaved'.tr() : 'attachmentSavedDesktop'.tr(),
|
||||||
action: SnackBarAction(
|
action: (!kIsWeb && (Platform.isIOS || Platform.isAndroid))
|
||||||
label: 'openInAlbum'.tr(),
|
? SnackBarAction(
|
||||||
onPressed: () async => Gal.open(),
|
label: 'openInAlbum'.tr(),
|
||||||
),
|
onPressed: () async => Gal.open(),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +261,7 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
).padding(right: 8),
|
).padding(right: 8),
|
||||||
),
|
),
|
||||||
InkWell(
|
InkWell(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
onTap: _isDownloading
|
onTap: _isDownloading
|
||||||
? null
|
? null
|
||||||
: () => _saveToAlbum(widget.data.length > 1 ? _pageController.page?.round() ?? 0 : 0),
|
: () => _saveToAlbum(widget.data.length > 1 ? _pageController.page?.round() ?? 0 : 0),
|
||||||
@ -335,10 +337,11 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
'${item.size} Bytes',
|
'${item.size} Bytes',
|
||||||
style: metaTextStyle,
|
style: metaTextStyle,
|
||||||
),
|
),
|
||||||
Text(
|
if (item.metadata['width'] != null && item.metadata['height'] != null)
|
||||||
'${item.metadata['width']}x${item.metadata['height']}',
|
Text(
|
||||||
style: metaTextStyle,
|
'${item.metadata['width']}x${item.metadata['height']}',
|
||||||
),
|
style: metaTextStyle,
|
||||||
|
),
|
||||||
if (item.metadata['ratio'] != null)
|
if (item.metadata['ratio'] != null)
|
||||||
Text(
|
Text(
|
||||||
(item.metadata['ratio'] as num).toStringAsFixed(2),
|
(item.metadata['ratio'] as num).toStringAsFixed(2),
|
||||||
|
@ -12,13 +12,12 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
import 'package:surface/controllers/chat_message_controller.dart';
|
import 'package:surface/controllers/chat_message_controller.dart';
|
||||||
import 'package:surface/controllers/post_write_controller.dart';
|
import 'package:surface/controllers/post_write_controller.dart';
|
||||||
import 'package:surface/providers/sn_attachment.dart';
|
import 'package:surface/providers/sn_attachment.dart';
|
||||||
|
import 'package:surface/providers/user_directory.dart';
|
||||||
import 'package:surface/types/chat.dart';
|
import 'package:surface/types/chat.dart';
|
||||||
import 'package:surface/widgets/dialog.dart';
|
import 'package:surface/widgets/dialog.dart';
|
||||||
import 'package:surface/widgets/markdown_content.dart';
|
import 'package:surface/widgets/markdown_content.dart';
|
||||||
import 'package:surface/widgets/post/post_media_pending_list.dart';
|
import 'package:surface/widgets/post/post_media_pending_list.dart';
|
||||||
|
|
||||||
import '../../providers/user_directory.dart';
|
|
||||||
|
|
||||||
class ChatMessageInput extends StatefulWidget {
|
class ChatMessageInput extends StatefulWidget {
|
||||||
final ChatMessageController controller;
|
final ChatMessageController controller;
|
||||||
final SnChannelMember? otherMember;
|
final SnChannelMember? otherMember;
|
||||||
|
10
pubspec.lock
10
pubspec.lock
@ -359,7 +359,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.10"
|
version: "0.7.10"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: device_info_plus
|
name: device_info_plus
|
||||||
sha256: "4fa68e53e26ab17b70ca39f072c285562cfc1589df5bb1e9295db90f6645f431"
|
sha256: "4fa68e53e26ab17b70ca39f072c285562cfc1589df5bb1e9295db90f6645f431"
|
||||||
@ -1558,18 +1558,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "7f172d1b06de5da47b6264c2692ee2ead20bbbc246690427cdb4fc301cd0c549"
|
sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.4"
|
version: "2.4.0"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_foundation
|
name: shared_preferences_foundation
|
||||||
sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d"
|
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.3"
|
version: "2.5.4"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2.0.1+23
|
version: 2.0.1+24
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
@ -101,6 +101,7 @@ dependencies:
|
|||||||
screenshot: ^3.0.0
|
screenshot: ^3.0.0
|
||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
file_saver: ^0.2.14
|
file_saver: ^0.2.14
|
||||||
|
device_info_plus: ^11.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
Reference in New Issue
Block a user