Compare commits

...

16 Commits

Author SHA1 Message Date
29ca263130 🚀 Launch 1.2.1+13 2024-08-16 01:03:55 +08:00
7332f68d9c Live preview of post editor 2024-08-16 00:52:36 +08:00
e9e6f3313e 👽 Use capital to deal with mfa 2024-08-13 10:54:42 +08:00
85764c37c2 🚨 Fix livekit android complie issue
Following issue:
https://github.com/livekit/client-sdk-flutter/issues/569
2024-08-12 09:06:30 +08:00
ef1f29f905 🐛 Fix edit post won't rollback thumbnail 2024-08-11 02:07:09 +08:00
22026efa7d Thumbnail 2024-08-11 01:57:58 +08:00
4a3e6a9e15 🚀 Launch 1.2.1+12 2024-08-11 00:50:25 +08:00
00092ba7b6 Some useful options 2024-08-11 00:36:27 +08:00
b5da8ece4a Use capital share link 2024-08-10 18:24:47 +08:00
dfe9165bc9 🐛 Bug fixes on upload attachment 2024-08-10 01:17:31 +08:00
3d45b54236 ⬆️ Upgrade flutter & deps 2024-08-10 01:16:40 +08:00
7f63fe7f0e 💄 Better sidebar navigation 2024-08-10 00:51:54 +08:00
bc5dbab9c5 Dismissible refresh notification 2024-08-10 00:49:21 +08:00
9910fc7a92 Channel content auto refresh after long time background activity 2024-08-10 00:43:55 +08:00
2356eac118 Better side navigation bar 2024-08-09 22:59:24 +08:00
0135b8d838 Better screenshare 2024-08-09 22:40:05 +08:00
24 changed files with 481 additions and 193 deletions

View File

@ -12,6 +12,17 @@ subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}" project.buildDir = "${rootProject.buildDir}/${project.name}"
} }
subprojects { subprojects {
// TO FIX LIVEKIT ISSUE BY THIS
// https://github.com/livekit/client-sdk-flutter/issues/569#issuecomment-2275686786
afterEvaluate { project ->
if (project.plugins.hasPlugin("com.android.application") ||
project.plugins.hasPlugin("com.android.library")) {
project.android {
compileSdkVersion 34
buildToolsVersion "34.0.0"
}
}
}
project.evaluationDependsOn(":app") project.evaluationDependsOn(":app")
} }

View File

@ -145,14 +145,14 @@ PODS:
- Flutter - Flutter
- screen_brightness_ios (0.1.0): - screen_brightness_ios (0.1.0):
- Flutter - Flutter
- SDWebImage (5.19.4): - SDWebImage (5.19.6):
- SDWebImage/Core (= 5.19.4) - SDWebImage/Core (= 5.19.6)
- SDWebImage/Core (5.19.4) - SDWebImage/Core (5.19.6)
- Sentry/HybridSDK (8.32.0) - Sentry/HybridSDK (8.33.0)
- sentry_flutter (8.6.0): - sentry_flutter (8.7.0):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- Sentry/HybridSDK (= 8.32.0) - Sentry/HybridSDK (= 8.33.0)
- share_plus (0.0.1): - share_plus (0.0.1):
- Flutter - Flutter
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
@ -319,9 +319,9 @@ SPEC CHECKSUMS:
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
protocol_handler_ios: a5db8abc38526ee326988b808be621e5fd568990 protocol_handler_ios: a5db8abc38526ee326988b808be621e5fd568990
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d SDWebImage: a79252b60f4678812d94316c91da69ec83089c9f
Sentry: 96ae1dcdf01a644bc3a3b1dc279cecaf48a833fb Sentry: 8560050221424aef0bebc8e31eedf00af80f90a6
sentry_flutter: 090351ce1ff5f96a4b33ef9455b7e3b28185387d sentry_flutter: e26b861f744e5037a3faf9bf56603ec65d658a61
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec

View File

@ -1,7 +1,7 @@
import UIKit import UIKit
import Flutter import Flutter
@UIApplicationMain @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,

View File

@ -10,6 +10,7 @@ import 'package:solian/widgets/posts/editor/post_editor_categories_tags.dart';
import 'package:solian/widgets/posts/editor/post_editor_date.dart'; import 'package:solian/widgets/posts/editor/post_editor_date.dart';
import 'package:solian/widgets/posts/editor/post_editor_overview.dart'; import 'package:solian/widgets/posts/editor/post_editor_overview.dart';
import 'package:solian/widgets/posts/editor/post_editor_publish_zone.dart'; import 'package:solian/widgets/posts/editor/post_editor_publish_zone.dart';
import 'package:solian/widgets/posts/editor/post_editor_thumbnail.dart';
import 'package:solian/widgets/posts/editor/post_editor_visibility.dart'; import 'package:solian/widgets/posts/editor/post_editor_visibility.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -31,6 +32,7 @@ class PostEditorController extends GetxController {
Rx<DateTime?> publishedUntil = Rx(null); Rx<DateTime?> publishedUntil = Rx(null);
RxList<int> attachments = RxList<int>.empty(growable: true); RxList<int> attachments = RxList<int>.empty(growable: true);
RxList<String> tags = RxList<String>.empty(growable: true); RxList<String> tags = RxList<String>.empty(growable: true);
Rx<int?> thumbnail = Rx(null);
RxList<int> visibleUsers = RxList.empty(growable: true); RxList<int> visibleUsers = RxList.empty(growable: true);
RxList<int> invisibleUsers = RxList.empty(growable: true); RxList<int> invisibleUsers = RxList.empty(growable: true);
@ -125,6 +127,15 @@ class PostEditorController extends GetxController {
); );
} }
Future<void> editThumbnail(BuildContext context) {
return showDialog(
context: context,
builder: (context) => PostEditorThumbnailDialog(
controller: this,
),
);
}
void toggleDraftMode() { void toggleDraftMode() {
isDraft.value = !isDraft.value; isDraft.value = !isDraft.value;
} }
@ -165,6 +176,7 @@ class PostEditorController extends GetxController {
visibleUsers.clear(); visibleUsers.clear();
invisibleUsers.clear(); invisibleUsers.clear();
visibility.value = 0; visibility.value = 0;
thumbnail.value = null;
publishedAt.value = null; publishedAt.value = null;
publishedUntil.value = null; publishedUntil.value = null;
isDraft.value = false; isDraft.value = false;
@ -196,6 +208,7 @@ class PostEditorController extends GetxController {
tags.refresh(); tags.refresh();
attachments.value = value.body['attachments']?.cast<int>() ?? List.empty(); attachments.value = value.body['attachments']?.cast<int>() ?? List.empty();
attachments.refresh(); attachments.refresh();
thumbnail.value = value.body['thumbnail'];
contentLength.value = contentController.text.length; contentLength.value = contentController.text.length;
} }
@ -246,6 +259,7 @@ class PostEditorController extends GetxController {
'title': title, 'title': title,
'description': description, 'description': description,
'content': contentController.text, 'content': contentController.text,
'thumbnail': thumbnail.value,
'tags': tags.map((x) => {'alias': x}).toList(), 'tags': tags.map((x) => {'alias': x}).toList(),
'attachments': attachments, 'attachments': attachments,
'visible_users': visibleUsers, 'visible_users': visibleUsers,
@ -269,6 +283,7 @@ class PostEditorController extends GetxController {
contentController.text = value['content'] ?? ''; contentController.text = value['content'] ?? '';
attachments.value = value['attachments'].cast<int>() ?? List.empty(); attachments.value = value['attachments'].cast<int>() ?? List.empty();
attachments.refresh(); attachments.refresh();
thumbnail.value = value['thumbnail'];
visibility.value = value['visibility']; visibility.value = value['visibility'];
isDraft.value = value['is_draft']; isDraft.value = value['is_draft'];
if (value['visible_users'] != null) { if (value['visible_users'] != null) {
@ -308,7 +323,8 @@ class PostEditorController extends GetxController {
descriptionController.text.isNotEmpty, descriptionController.text.isNotEmpty,
contentController.text.isNotEmpty, contentController.text.isNotEmpty,
attachments.isNotEmpty, attachments.isNotEmpty,
tags.isNotEmpty tags.isNotEmpty,
thumbnail.value != null,
].any((x) => x); ].any((x) => x);
} }

View File

@ -138,9 +138,7 @@ class AttachmentUploaderController extends GetxController {
queueOfUpload[idx].isCompleted = true; queueOfUpload[idx].isCompleted = true;
} }
queueOfUpload.value = queueOfUpload queueOfUpload.removeWhere((x) => x.error == null);
.where((x) => x.error == null && x.isCompleted)
.toList(growable: true);
_stopProgressSyncTimer(); _stopProgressSyncTimer();
_syncProgress(); _syncProgress();

View File

@ -79,8 +79,8 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
onPressed: () { onPressed: () {
const redirect = 'solink://auth?status=done'; const redirect = 'solink://auth?status=done';
launchUrlString( launchUrlString(
ServiceFinder.buildUrl('passport', ServiceFinder.buildUrl('capital',
'/mfa?redirect_uri=$redirect&ticketId=${e.ticketId}'), '/auth/mfa?redirect_uri=$redirect&ticketId=${e.ticketId}'),
mode: LaunchMode.inAppWebView, mode: LaunchMode.inAppWebView,
); );
Navigator.pop(context); Navigator.pop(context);

View File

@ -20,7 +20,6 @@ import 'package:solian/widgets/app_bar_leading.dart';
import 'package:solian/widgets/app_bar_title.dart'; import 'package:solian/widgets/app_bar_title.dart';
import 'package:solian/widgets/channel/channel_call_indicator.dart'; import 'package:solian/widgets/channel/channel_call_indicator.dart';
import 'package:solian/widgets/chat/call/chat_call_action.dart'; import 'package:solian/widgets/chat/call/chat_call_action.dart';
import 'package:solian/widgets/chat/chat_event.dart';
import 'package:solian/widgets/chat/chat_event_list.dart'; import 'package:solian/widgets/chat/chat_event_list.dart';
import 'package:solian/widgets/chat/chat_message_input.dart'; import 'package:solian/widgets/chat/chat_message_input.dart';
import 'package:solian/widgets/current_state_action.dart'; import 'package:solian/widgets/current_state_action.dart';
@ -39,7 +38,10 @@ class ChannelChatScreen extends StatefulWidget {
State<ChannelChatScreen> createState() => _ChannelChatScreenState(); State<ChannelChatScreen> createState() => _ChannelChatScreenState();
} }
class _ChannelChatScreenState extends State<ChannelChatScreen> { class _ChannelChatScreenState extends State<ChannelChatScreen>
with WidgetsBindingObserver {
DateTime? _isOutOfSyncSince;
bool _isBusy = false; bool _isBusy = false;
int? _accountId; int? _accountId;
@ -123,20 +125,38 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
}); });
} }
void _keepUpdateWithServer() {
_getOngoingCall();
_chatController.getEvents(_channel!, widget.realm);
setState(() => _isOutOfSyncSince = null);
}
Event? _messageToReplying; Event? _messageToReplying;
Event? _messageToEditing; Event? _messageToEditing;
Widget buildHistoryBody(Event item, {bool isMerged = false}) { @override
return ChatEvent( void didChangeAppLifecycleState(AppLifecycleState state) {
key: Key('m${item.uuid}'), switch (state) {
item: item, case AppLifecycleState.resumed:
isMerged: isMerged, if (_isOutOfSyncSince == null) break;
chatController: _chatController, if (DateTime.now().difference(_isOutOfSyncSince!).inSeconds < 60) break;
); _keepUpdateWithServer();
break;
case AppLifecycleState.paused:
if (mounted) {
setState(() => _isOutOfSyncSince = DateTime.now());
}
break;
default:
break;
}
} }
@override @override
void initState() { void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_accountId = Get.find<AuthProvider>().userProfile.value!['id']; _accountId = Get.find<AuthProvider>().userProfile.value!['id'];
_chatController = ChatEventController(); _chatController = ChatEventController();
@ -147,21 +167,10 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
_chatController.getEvents(_channel!, widget.realm); _chatController.getEvents(_channel!, widget.realm);
_listenMessages(); _listenMessages();
}); });
super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_isBusy || _channel == null) {
return Material(
color: Theme.of(context).colorScheme.surface,
child: const Center(
child: CircularProgressIndicator(),
),
);
}
String title = _channel?.name ?? 'loading'.tr; String title = _channel?.name ?? 'loading'.tr;
String? placeholder; String? placeholder;
@ -185,7 +194,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
actions: [ actions: [
const BackgroundStateWidget(), const BackgroundStateWidget(),
Builder(builder: (context) { Builder(builder: (context) {
if (_isBusy) return const SizedBox(); if (_isBusy || _channel == null) return const SizedBox();
return ChatCallButton( return ChatCallButton(
realm: _channel!.realm, realm: _channel!.realm,
channel: _channel!, channel: _channel!,
@ -195,6 +205,8 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
IconButton( IconButton(
icon: const Icon(Icons.more_vert), icon: const Icon(Icons.more_vert),
onPressed: () { onPressed: () {
if (_channel == null) return;
AppRouter.instance AppRouter.instance
.pushNamed( .pushNamed(
'channelDetail', 'channelDetail',
@ -219,66 +231,94 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
), ),
], ],
), ),
body: Column( body: Builder(builder: (context) {
children: [ if (_isBusy || _channel == null) {
if (_ongoingCall != null) return const Center(
ChannelCallIndicator( child: CircularProgressIndicator(),
channel: _channel!, );
ongoingCall: _ongoingCall!, }
return Column(
children: [
if (_ongoingCall != null)
ChannelCallIndicator(
channel: _channel!,
ongoingCall: _ongoingCall!,
),
Expanded(
child: ChatEventList(
scope: widget.realm,
channel: _channel!,
chatController: _chatController,
onEdit: (item) {
setState(() => _messageToEditing = item);
},
onReply: (item) {
setState(() => _messageToReplying = item);
},
),
), ),
Expanded( if (_isOutOfSyncSince != null)
child: ChatEventList( ListTile(
scope: widget.realm, contentPadding: const EdgeInsets.only(left: 16, right: 8),
channel: _channel!, tileColor: Theme.of(context).colorScheme.surfaceContainerLow,
chatController: _chatController, leading: const Icon(Icons.history_toggle_off),
onEdit: (item) { title: Text('messageOutOfSync'.tr),
setState(() => _messageToEditing = item); subtitle: Text('messageOutOfSyncCaption'.tr),
}, trailing: IconButton(
onReply: (item) { icon: const Icon(Icons.close),
setState(() => _messageToReplying = item); onPressed: () {
}, setState(() => _isOutOfSyncSince = null);
),
),
Obx(() {
if (_chatController.isLoading.isTrue) {
return const LinearProgressIndicator().animate().slideY();
} else {
return const SizedBox();
}
}),
ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
child: SafeArea(
child: ChatMessageInput(
edit: _messageToEditing,
reply: _messageToReplying,
realm: widget.realm,
placeholder: placeholder,
channel: _channel!,
onSent: (Event item) {
setState(() {
_chatController.addPendingEvent(item);
});
},
onReset: () {
setState(() {
_messageToReplying = null;
_messageToEditing = null;
});
}, },
), ),
onTap: _isBusy
? null
: () {
_keepUpdateWithServer();
},
),
Obx(() {
if (_chatController.isLoading.isTrue) {
return const LinearProgressIndicator().animate().slideY();
} else {
return const SizedBox();
}
}),
ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
child: SafeArea(
child: ChatMessageInput(
edit: _messageToEditing,
reply: _messageToReplying,
realm: widget.realm,
placeholder: placeholder,
channel: _channel!,
onSent: (Event item) {
setState(() {
_chatController.addPendingEvent(item);
});
},
onReset: () {
setState(() {
_messageToReplying = null;
_messageToEditing = null;
});
},
),
),
), ),
), ),
), ],
], );
), }),
); );
} }
@override @override
void dispose() { void dispose() {
_subscription?.cancel(); _subscription?.cancel();
WidgetsBinding.instance.removeObserver(this);
super.dispose(); super.dispose();
} }
} }

View File

@ -208,7 +208,12 @@ class PostCreatePopup extends StatelessWidget {
children: [ children: [
x.icon, x.icon,
const SizedBox(height: 8), const SizedBox(height: 8),
Text(x.label), Expanded(
child: Text(
x.label,
overflow: TextOverflow.fade,
),
),
], ],
).paddingAll(18), ).paddingAll(18),
), ),

View File

@ -14,6 +14,7 @@ import 'package:solian/router.dart';
import 'package:solian/theme.dart'; import 'package:solian/theme.dart';
import 'package:solian/widgets/app_bar_leading.dart'; import 'package:solian/widgets/app_bar_leading.dart';
import 'package:solian/widgets/app_bar_title.dart'; import 'package:solian/widgets/app_bar_title.dart';
import 'package:solian/widgets/markdown_text_content.dart';
import 'package:solian/widgets/posts/post_item.dart'; import 'package:solian/widgets/posts/post_item.dart';
import 'package:badges/badges.dart' as badges; import 'package:badges/badges.dart' as badges;
@ -90,6 +91,7 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
context.showErrorDialog(resp.bodyString); context.showErrorDialog(resp.bodyString);
} else { } else {
_editorController.localClear(); _editorController.localClear();
_editorController.currentClear();
AppRouter.instance.pop(resp.body); AppRouter.instance.pop(resp.body);
} }
@ -254,30 +256,51 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
], ],
), ),
Expanded( Expanded(
child: ListView( child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (_isBusy) Expanded(
const LinearProgressIndicator().animate().scaleX(), child: ListView(
Container( children: [
padding: const EdgeInsets.symmetric( if (_isBusy)
horizontal: 16, const LinearProgressIndicator().animate().scaleX(),
vertical: 8, Container(
), padding: const EdgeInsets.symmetric(
child: TextField( horizontal: 16,
maxLines: null, vertical: 8,
autofocus: true, ),
autocorrect: true, child: TextField(
keyboardType: TextInputType.multiline, maxLines: null,
controller: _editorController.contentController, autofocus: true,
focusNode: _contentFocusNode, autocorrect: true,
decoration: InputDecoration.collapsed( keyboardType: TextInputType.multiline,
hintText: 'postContentPlaceholder'.tr, controller: _editorController.contentController,
), focusNode: _contentFocusNode,
onTapOutside: (_) => decoration: InputDecoration.collapsed(
FocusManager.instance.primaryFocus?.unfocus(), hintText: 'postContentPlaceholder'.tr,
),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
),
),
const SizedBox(height: 120)
],
), ),
), ),
const SizedBox(height: 120) if (SolianTheme.isLargeScreen(context))
const VerticalDivider(width: 0.3, thickness: 0.3)
.paddingSymmetric(
horizontal: 8,
),
if (SolianTheme.isLargeScreen(context))
Expanded(
child: SingleChildScrollView(
child: MarkdownTextContent(
content: _editorController.contentController.text,
parentId: 'post-editor-preview',
).paddingOnly(top: 8),
),
),
], ],
), ),
), ),
@ -453,6 +476,23 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
_editorController.editPublishZone(context); _editorController.editPublishZone(context);
}, },
), ),
IconButton(
icon: Obx(() {
return badges.Badge(
showBadge:
_editorController.thumbnail.value != null,
position: badges.BadgePosition.topEnd(
top: -4,
end: -6,
),
child: const Icon(Icons.preview),
);
}),
color: Theme.of(context).colorScheme.primary,
onPressed: () {
_editorController.editThumbnail(context);
},
),
IconButton( IconButton(
icon: Obx(() { icon: Obx(() {
return badges.Badge( return badges.Badge(
@ -475,14 +515,15 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
MarkdownToolbar( MarkdownToolbar(
hideImage: true, hideImage: true,
useIncludedTextField: false, useIncludedTextField: false,
backgroundColor: Colors.transparent, backgroundColor:
Theme.of(context).colorScheme.surface,
iconColor: Theme.of(context).colorScheme.onSurface, iconColor: Theme.of(context).colorScheme.onSurface,
controller: _editorController.contentController, controller: _editorController.contentController,
focusNode: _contentFocusNode, focusNode: _contentFocusNode,
borderRadius: borderRadius:
const BorderRadius.all(Radius.circular(20)), const BorderRadius.all(Radius.circular(20)),
width: 40, width: 40,
).paddingSymmetric(horizontal: 4), ).paddingSymmetric(horizontal: 2),
], ],
).paddingSymmetric(horizontal: 6, vertical: 8), ).paddingSymmetric(horizontal: 6, vertical: 8),
), ),

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:solian/controllers/chat_events_controller.dart';
import 'package:solian/exts.dart'; import 'package:solian/exts.dart';
import 'package:solian/providers/theme_switcher.dart'; import 'package:solian/providers/theme_switcher.dart';
import 'package:solian/router.dart'; import 'package:solian/router.dart';
@ -93,6 +94,18 @@ class _SettingScreenState extends State<SettingScreen> {
AppRouter.instance.pushNamed('about'); AppRouter.instance.pushNamed('about');
}, },
), ),
TextButton(
style: const ButtonStyle(
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
),
child: Text('messageHistoryWipe'.tr),
onPressed: () {
final chatHistory = ChatEventController();
chatHistory.initialize().then((_) async {
await chatHistory.database.localEvents.wipeLocalEvents();
});
},
),
], ],
).paddingSymmetric(horizontal: 12, vertical: 8), ).paddingSymmetric(horizontal: 12, vertical: 8),
], ],

View File

@ -5,15 +5,15 @@ abstract class ServiceFinder {
static const String dealerUrl = static const String dealerUrl =
devFlag ? 'http://localhost:8442' : 'https://api.sn.solsynth.dev'; devFlag ? 'http://localhost:8442' : 'https://api.sn.solsynth.dev';
static const String passportUrl = static const String capitalUrl =
devFlag ? 'http://localhost:8444' : 'https://id.solsynth.dev'; devFlag ? 'http://localhost:8444' : 'https://solsynth.dev';
static String buildUrl(String serviceName, String? append) { static String buildUrl(String serviceName, String? append) {
append ??= ''; append ??= '';
if (serviceName == 'dealer') { if (serviceName == 'dealer') {
return '$dealerUrl$append'; return '$dealerUrl$append';
} else if (serviceName == 'passport') { } else if (serviceName == 'capital') {
return '$passportUrl$append'; return '$capitalUrl$append';
} }
return '$dealerUrl/cgi/$serviceName$append'; return '$dealerUrl/cgi/$serviceName$append';
} }

View File

@ -119,6 +119,9 @@ const i18nEnglish = {
'postVisibleUsers': 'Visible users', 'postVisibleUsers': 'Visible users',
'postInvisibleUsers': 'Invisible users', 'postInvisibleUsers': 'Invisible users',
'postOverview': 'Overview', 'postOverview': 'Overview',
'postThumbnail': 'Thumbnail',
'postThumbnailAttachmentNew': 'Upload thumbnail',
'postThumbnailAttachment': 'Attachment serial number',
'postPinned': 'Pinned', 'postPinned': 'Pinned',
'postListNews': 'News', 'postListNews': 'News',
'postListShuffle': 'Random', 'postListShuffle': 'Random',
@ -351,7 +354,7 @@ const i18nEnglish = {
'attachmentSaved': 'Attachment saved to your system album.', 'attachmentSaved': 'Attachment saved to your system album.',
'cropImage': 'Crop Image', 'cropImage': 'Crop Image',
'stickerUploader': 'Upload sticker', 'stickerUploader': 'Upload sticker',
'stickerUploaderAttachmentNew': 'Upload new attachment', 'stickerUploaderAttachmentNew': 'Upload sticker',
'stickerUploaderAttachment': 'Attachment serial number', 'stickerUploaderAttachment': 'Attachment serial number',
'stickerUploaderPack': 'Sticker pack serial number', 'stickerUploaderPack': 'Sticker pack serial number',
'stickerUploaderPackHint': 'stickerUploaderPackHint':
@ -370,4 +373,8 @@ const i18nEnglish = {
'callStatusDisconnected': 'Disconnected', 'callStatusDisconnected': 'Disconnected',
'callStatusConnecting': 'Connecting', 'callStatusConnecting': 'Connecting',
'callStatusReconnected': 'Reconnecting', 'callStatusReconnected': 'Reconnecting',
'messageOutOfSync': 'May Out of Sync with Server',
'messageOutOfSyncCaption':
'Since the App has entered the background, there may be a time difference between the message list and the server. Click to Refresh.',
'messageHistoryWipe': 'Wipe local message history',
}; };

View File

@ -113,6 +113,9 @@ const i18nSimplifiedChinese = {
'postVisibleUsers': '可见帖子者', 'postVisibleUsers': '可见帖子者',
'postInvisibleUsers': '隐藏帖子者', 'postInvisibleUsers': '隐藏帖子者',
'postOverview': '帖子概览', 'postOverview': '帖子概览',
'postThumbnail': '帖子缩略图',
'postThumbnailAttachmentNew': '上传附件作为缩略图',
'postThumbnailAttachment': '附件序列号',
'postPinned': '已置顶', 'postPinned': '已置顶',
'postEditorModeStory': '发个帖子', 'postEditorModeStory': '发个帖子',
'postEditorModeArticle': '撰写文章', 'postEditorModeArticle': '撰写文章',
@ -322,7 +325,7 @@ const i18nSimplifiedChinese = {
'attachmentSaved': '附件已保存到系统相册', 'attachmentSaved': '附件已保存到系统相册',
'cropImage': '裁剪图片', 'cropImage': '裁剪图片',
'stickerUploader': '上传贴图', 'stickerUploader': '上传贴图',
'stickerUploaderAttachmentNew': '上传附件', 'stickerUploaderAttachmentNew': '上传附件作为贴图',
'stickerUploaderAttachment': '附件序列号', 'stickerUploaderAttachment': '附件序列号',
'stickerUploaderPack': '贴图包序号', 'stickerUploaderPack': '贴图包序号',
'stickerUploaderPackHint': '没有该序号?请转到我们的创作者平台创建一个贴图包。', 'stickerUploaderPackHint': '没有该序号?请转到我们的创作者平台创建一个贴图包。',
@ -337,4 +340,7 @@ const i18nSimplifiedChinese = {
'callStatusDisconnected': '已断开', 'callStatusDisconnected': '已断开',
'callStatusConnecting': '连接中', 'callStatusConnecting': '连接中',
'callStatusReconnected': '重连中', 'callStatusReconnected': '重连中',
'messageOutOfSync': '消息可能与服务器脱节',
'messageOutOfSyncCaption': '由于 App 进入后台,消息列表可能与服务器存在时差,点击刷新。',
'messageHistoryWipe': '清除消息记录',
}; };

View File

@ -159,8 +159,9 @@ class _ControlsWidgetState extends State<ControlsWidget> {
} }
var track = await LocalVideoTrack.createScreenShareTrack( var track = await LocalVideoTrack.createScreenShareTrack(
ScreenShareCaptureOptions( ScreenShareCaptureOptions(
captureScreenAudio: true,
sourceId: source.id, sourceId: source.id,
maxFrameRate: 15.0, maxFrameRate: 30.0,
), ),
); );
await _participant.publishVideoTrack(track); await _participant.publishVideoTrack(track);
@ -174,6 +175,7 @@ class _ControlsWidgetState extends State<ControlsWidget> {
var track = await LocalVideoTrack.createScreenShareTrack( var track = await LocalVideoTrack.createScreenShareTrack(
const ScreenShareCaptureOptions( const ScreenShareCaptureOptions(
useiOSBroadcastExtension: true, useiOSBroadcastExtension: true,
captureScreenAudio: true,
maxFrameRate: 30.0, maxFrameRate: 30.0,
), ),
); );

View File

@ -4,17 +4,17 @@ import 'package:get/utils.dart';
abstract class AppNavigation { abstract class AppNavigation {
static List<AppNavigationDestination> destinations = [ static List<AppNavigationDestination> destinations = [
AppNavigationDestination( AppNavigationDestination(
icon: const Icon(Icons.home), icon: Icons.home,
label: 'home'.tr, label: 'home'.tr,
page: 'home', page: 'home',
), ),
AppNavigationDestination( AppNavigationDestination(
icon: const Icon(Icons.workspaces), icon: Icons.workspaces,
label: 'realms'.tr, label: 'realms'.tr,
page: 'realms', page: 'realms',
), ),
AppNavigationDestination( AppNavigationDestination(
icon: const Icon(Icons.forum), icon: Icons.forum,
label: 'channelTypeDirect'.tr, label: 'channelTypeDirect'.tr,
page: 'chat', page: 'chat',
), ),
@ -25,7 +25,7 @@ abstract class AppNavigation {
} }
class AppNavigationDestination { class AppNavigationDestination {
final Widget icon; final IconData icon;
final String label; final String label;
final String page; final String page;

View File

@ -1,3 +1,5 @@
import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/models/account_status.dart'; import 'package:solian/models/account_status.dart';
@ -40,15 +42,6 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
rootScaffoldKey.currentState!.closeDrawer(); rootScaffoldKey.currentState!.closeDrawer();
} }
Widget _buildSettingButton() {
return IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
AppRouter.instance.pushNamed('settings');
_closeDrawer();
});
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -63,6 +56,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
backgroundColor: backgroundColor:
SolianTheme.isLargeScreen(context) ? Colors.transparent : null, SolianTheme.isLargeScreen(context) ? Colors.transparent : null,
child: SafeArea( child: SafeArea(
bottom: false,
child: Column( child: Column(
children: [ children: [
Obx(() { Obx(() {
@ -72,7 +66,6 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
leading: const Icon(Icons.account_circle), leading: const Icon(Icons.account_circle),
title: Text('guest'.tr), title: Text('guest'.tr),
subtitle: Text('unsignedIn'.tr), subtitle: Text('unsignedIn'.tr),
trailing: _buildSettingButton(),
onTap: () { onTap: () {
AppRouter.instance.goNamed('account'); AppRouter.instance.goNamed('account');
_closeDrawer(); _closeDrawer();
@ -81,7 +74,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
} }
return ListTile( return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 24), contentPadding: const EdgeInsets.only(left: 20, right: 20),
title: Text( title: Text(
auth.userProfile.value!['nick'], auth.userProfile.value!['nick'],
maxLines: 1, maxLines: 1,
@ -137,7 +130,6 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
), ),
); );
}), }),
trailing: _buildSettingButton(),
onTap: () { onTap: () {
AppRouter.instance.goNamed('account'); AppRouter.instance.goNamed('account');
_closeDrawer(); _closeDrawer();
@ -154,7 +146,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
}); });
}, },
); );
}).paddingOnly(top: 8), }).paddingSymmetric(vertical: 8),
const Divider(thickness: 0.3, height: 1), const Divider(thickness: 0.3, height: 1),
Column( Column(
children: AppNavigation.destinations children: AppNavigation.destinations
@ -163,7 +155,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(
horizontal: 20, horizontal: 20,
), ),
leading: e.icon, leading: Icon(e.icon, size: 20).paddingAll(2),
title: Text(e.label), title: Text(e.label),
enabled: true, enabled: true,
onTap: () { onTap: () {
@ -182,6 +174,26 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
}, },
), ),
), ),
const Divider(thickness: 0.3, height: 1),
Column(
children: [
ListTile(
minTileHeight: 0,
contentPadding: const EdgeInsets.symmetric(
horizontal: 20,
),
leading: const Icon(Icons.settings, size: 20).paddingAll(2),
title: Text('settings'.tr),
onTap: () {
AppRouter.instance.pushNamed('settings');
_closeDrawer();
},
),
],
).paddingOnly(
top: 8,
bottom: math.max(8, MediaQuery.of(context).padding.bottom),
),
], ],
), ),
), ),

View File

@ -68,6 +68,7 @@ class AppNavigationRegions extends StatelessWidget {
.map((element) { .map((element) {
return ExpansionTile( return ExpansionTile(
minTileHeight: 0, minTileHeight: 0,
initiallyExpanded: true,
tilePadding: const EdgeInsets.only(left: 20, right: 24), tilePadding: const EdgeInsets.only(left: 20, right: 24),
backgroundColor: Theme.of(context).colorScheme.surfaceContainer, backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
collapsedBackgroundColor: collapsedBackgroundColor:
@ -80,6 +81,7 @@ class AppNavigationRegions extends StatelessWidget {
); );
}).toList(), }).toList(),
), ),
const SliverPadding(padding: EdgeInsets.only(bottom: 8)),
], ],
); );
}); });

View File

@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/controllers/post_editor_controller.dart';
import 'package:solian/widgets/attachments/attachment_editor.dart';
class PostEditorThumbnailDialog extends StatefulWidget {
final PostEditorController controller;
const PostEditorThumbnailDialog({super.key, required this.controller});
@override
State<PostEditorThumbnailDialog> createState() =>
_PostEditorThumbnailDialogState();
}
class _PostEditorThumbnailDialogState extends State<PostEditorThumbnailDialog> {
final TextEditingController _attachmentController = TextEditingController();
void _promptUploadNewAttachment() {
showModalBottomSheet(
context: context,
builder: (context) => AttachmentEditorPopup(
usage: 'i.attachment',
singleMode: true,
imageOnly: true,
autoUpload: true,
onAdd: (value) {
setState(() {
_attachmentController.text = value.toString();
});
widget.controller.thumbnail.value = value;
},
initialAttachments: const [],
onRemove: (_) {},
),
);
}
@override
void initState() {
_attachmentController.text =
widget.controller.thumbnail.value?.toString() ?? '';
super.initState();
}
@override
void dispose() {
_attachmentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('postThumbnail'.tr),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Text('postThumbnailAttachmentNew'.tr),
contentPadding: const EdgeInsets.only(left: 16, right: 13),
trailing: const Icon(Icons.chevron_right),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
onTap: () {
_promptUploadNewAttachment();
},
),
const SizedBox(height: 8),
TextField(
controller: _attachmentController,
decoration: InputDecoration(
isDense: true,
border: const OutlineInputBorder(),
prefixText: '#',
labelText: 'postThumbnailAttachment'.tr,
),
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
),
],
),
actions: [
TextButton(
onPressed: () {
widget.controller.thumbnail.value =
int.tryParse(_attachmentController.text);
Navigator.pop(context);
},
child: Text('confirm'.tr),
),
],
);
}
}

View File

@ -43,7 +43,7 @@ class _PostActionState extends State<PostAction> {
final box = context.findRenderObject() as RenderBox?; final box = context.findRenderObject() as RenderBox?;
if ((PlatformInfo.isAndroid || PlatformInfo.isIOS) && !noUri) { if ((PlatformInfo.isAndroid || PlatformInfo.isIOS) && !noUri) {
await Share.shareUri( await Share.shareUri(
Uri.parse('https://sn.solsynth.dev/posts/view/${widget.item.id}'), Uri.parse('https://solsynth.dev/posts/${widget.item.id}'),
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
); );
} else { } else {
@ -57,7 +57,7 @@ class _PostActionState extends State<PostAction> {
'username': widget.item.author.nick, 'username': widget.item.author.nick,
'content': 'content':
'${extraContent.join('\n')}${isExtraNotEmpty ? '\n\n' : ''}${widget.item.body['content'] ?? 'no content'}', '${extraContent.join('\n')}${isExtraNotEmpty ? '\n\n' : ''}${widget.item.body['content'] ?? 'no content'}',
'link': 'https://sn.solsynth.dev/posts/view/${widget.item.id}', 'link': 'https://solsynth.dev/posts/${widget.item.id}',
}), }),
subject: 'postShareSubject'.trParams({ subject: 'postShareSubject'.trParams({
'username': widget.item.author.nick, 'username': widget.item.author.nick,

View File

@ -76,6 +76,30 @@ class _PostItemState extends State<PostItem> {
} }
} }
Widget _buildThumbnail() {
if (widget.item.body['thumbnail'] == null) return const SizedBox();
const radius = BorderRadius.all(Radius.circular(8));
return AspectRatio(
aspectRatio: 16 / 9,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).dividerColor,
width: 0.3,
),
borderRadius: radius,
),
child: ClipRRect(
borderRadius: radius,
child: AttachmentSelfContainedEntry(
id: widget.item.body['thumbnail'],
parentId: 'p${item.id}-thumbnail',
),
),
),
);
}
Widget _buildHeader() { Widget _buildHeader() {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -283,6 +307,7 @@ class _PostItemState extends State<PostItem> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildThumbnail().paddingSymmetric(horizontal: 12, vertical: 4),
_buildHeader().paddingSymmetric(horizontal: 12), _buildHeader().paddingSymmetric(horizontal: 12),
_buildHeaderDivider().paddingSymmetric(horizontal: 12), _buildHeaderDivider().paddingSymmetric(horizontal: 12),
Stack( Stack(
@ -356,6 +381,7 @@ class _PostItemState extends State<PostItem> {
closedBuilder: (_, openContainer) => Column( closedBuilder: (_, openContainer) => Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildThumbnail().paddingSymmetric(horizontal: 12, vertical: 4),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -390,7 +416,7 @@ class _PostItemState extends State<PostItem> {
setState(() => _contentHeight = size.height); setState(() => _contentHeight = size.height);
}, },
child: MarkdownTextContent( child: MarkdownTextContent(
parentId: 'p${item.id}', parentId: 'p${item.id}-embed',
content: item.body['content'], content: item.body['content'],
isSelectable: widget.isContentSelectable, isSelectable: widget.isContentSelectable,
).paddingOnly(left: 12, right: 8), ).paddingOnly(left: 12, right: 8),

View File

@ -107,11 +107,11 @@ PODS:
- FlutterMacOS - FlutterMacOS
- screen_brightness_macos (0.1.0): - screen_brightness_macos (0.1.0):
- FlutterMacOS - FlutterMacOS
- Sentry/HybridSDK (8.32.0) - Sentry/HybridSDK (8.33.0)
- sentry_flutter (8.6.0): - sentry_flutter (8.7.0):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- Sentry/HybridSDK (= 8.32.0) - Sentry/HybridSDK (= 8.33.0)
- share_plus (0.0.1): - share_plus (0.0.1):
- FlutterMacOS - FlutterMacOS
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
@ -252,8 +252,8 @@ SPEC CHECKSUMS:
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
protocol_handler_macos: d10a6c01d6373389ffd2278013ab4c47ed6d6daa protocol_handler_macos: d10a6c01d6373389ffd2278013ab4c47ed6d6daa
screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
Sentry: 96ae1dcdf01a644bc3a3b1dc279cecaf48a833fb Sentry: 8560050221424aef0bebc8e31eedf00af80f90a6
sentry_flutter: 090351ce1ff5f96a4b33ef9455b7e3b28185387d sentry_flutter: e26b861f744e5037a3faf9bf56603ec65d658a61
share_plus: 36537c04ce0c3e3f5bd297ce4318b6d5ee5fd6cf share_plus: 36537c04ce0c3e3f5bd297ce4318b6d5ee5fd6cf
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec

View File

@ -1,7 +1,7 @@
import Cocoa import Cocoa
import FlutterMacOS import FlutterMacOS
@NSApplicationMain @main
class AppDelegate: FlutterAppDelegate { class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true return true

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "67.0.0" version: "72.0.0"
_flutterfire_internals: _flutterfire_internals:
dependency: transitive dependency: transitive
description: description:
@ -17,14 +17,19 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.40" version: "1.3.40"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.4.1" version: "6.7.0"
animations: animations:
dependency: "direct main" dependency: "direct main"
description: description:
@ -117,18 +122,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.11" version: "2.4.12"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.3.1" version: "7.3.2"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -173,10 +178,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: carousel_slider name: carousel_slider
sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42" sha256: "7b006ec356205054af5beaef62e2221160ea36b90fb70a35e4deacd49d0349ae"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.1" version: "5.0.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -237,10 +242,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: connectivity_plus name: connectivity_plus
sha256: "3e7d1d9dbae40ae82cbe6c23c518f0c4ffe32764ee9749b9a99d32cbac8734f6" sha256: "2056db5241f96cdc0126bd94459fc4cdc13876753768fc7a31c425e50a7177d0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.4" version: "6.0.5"
connectivity_plus_platform_interface: connectivity_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -325,10 +330,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "93429694c9253d2871b3af80cf11b3cbb5c65660d402ed7bf69854ce4a089f82" sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.1.1" version: "10.1.2"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -634,10 +639,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_markdown name: flutter_markdown
sha256: "2e8a801b1ded5ea001a4529c97b1f213dcb11c6b20668e081cafb23468593514" sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.3" version: "0.7.3+1"
flutter_markdown_selectionarea: flutter_markdown_selectionarea:
dependency: "direct main" dependency: "direct main"
description: description:
@ -972,18 +977,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.4" version: "10.0.5"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.5"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
@ -1032,6 +1037,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.0" version: "1.5.0"
macros:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
markdown: markdown:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1060,10 +1073,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.0" version: "0.11.1"
media_kit: media_kit:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1140,10 +1153,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.0" version: "1.15.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -1188,10 +1201,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: "4de6c36df77ffbcef0a5aefe04669d33f2d18397fea228277b852a2d4e58e860" sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.0.1" version: "8.0.2"
package_info_plus_platform_interface: package_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1548,18 +1561,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: sentry name: sentry
sha256: "76ad4fab90ff82427c26939bd79dc4df345a081e2b1cd5954b947e340b9af9a5" sha256: "0f787e27ff617e4f88f7074977240406a9c5509444bac64a4dfa5b3200fb5632"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.6.0" version: "8.7.0"
sentry_flutter: sentry_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
name: sentry_flutter name: sentry_flutter
sha256: a7c92014701093a7c0a373e1a47c54ec428d8468d8bf2b793fee7ea1b085c21b sha256: fbbb47d72ccca48be25bf3c2ced6ab6e872991af3a0ba78e54be8d138f2e053f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.6.0" version: "8.7.0"
share_plus: share_plus:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1588,26 +1601,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "041be4d9d2dc6079cf342bc8b761b03787e3b71192d658220a56cac9c04a0294" sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.1"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "671e7a931f55a08aa45be2a13fe7247f2a41237897df434b30d2012388191833" sha256: "776786cff96324851b656777648f36ac772d88bc4c669acff97b7fce5de3c849"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.0" version: "2.5.1"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_linux name: shared_preferences_linux
sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1620,18 +1633,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2" sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.2"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_windows name: shared_preferences_windows
sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
@ -1793,10 +1806,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.2"
timeago: timeago:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1873,10 +1886,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.2.0"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
@ -1929,10 +1942,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.2.1" version: "14.2.4"
volume_controller: volume_controller:
dependency: transitive dependency: transitive
description: description:
@ -2038,5 +2051,5 @@ packages:
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.4.0 <4.0.0" dart: ">=3.5.0-259.0.dev <4.0.0"
flutter: ">=3.22.0" flutter: ">=3.22.0"

View File

@ -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+9 version: 1.2.1+13
environment: environment:
sdk: ">=3.3.4 <4.0.0" sdk: ">=3.3.4 <4.0.0"
@ -19,7 +19,7 @@ dependencies:
flutter_markdown: ^0.7.1 flutter_markdown: ^0.7.1
flutter_animate: ^4.5.0 flutter_animate: ^4.5.0
flutter_secure_storage: ^9.2.1 flutter_secure_storage: ^9.2.1
carousel_slider: ^4.2.1 carousel_slider: ^5.0.0
url_launcher: ^6.2.6 url_launcher: ^6.2.6
infinite_scroll_pagination: ^4.0.0 infinite_scroll_pagination: ^4.0.0
image_picker: ^1.1.1 image_picker: ^1.1.1