Compare commits

...

7 Commits

Author SHA1 Message Date
a2f9a1efb4 Optimize post quick reply 2025-08-10 01:45:02 +08:00
LittleSheep
823e3c5de6 🔀 Merge pull request #160 from Texas0295/v3
[FIX] linux_firebase_guard: skip FirebaseMessaging calls on Linux
2025-08-10 01:11:29 +08:00
Texas0295
faac7bac35 🐛 linux: guard FirebaseMessaging calls when Firebase is not initialized 2025-08-10 00:40:49 +08:00
1fac1bfe02 🐛 Fix post item and payment 2025-08-10 00:26:32 +08:00
9394b1d9c8 🐛 Serval bug fixes 2025-08-09 23:24:21 +08:00
43dd13bac4 🐛 Fix status update issue 2025-08-09 22:55:46 +08:00
65bc372103 🐛 Fix iOS NSE wrong avatar path 2025-08-09 22:55:35 +08:00
12 changed files with 86 additions and 45 deletions

View File

@@ -706,6 +706,7 @@
"copyToClipboardTooltip": "Copy to clipboard", "copyToClipboardTooltip": "Copy to clipboard",
"postForwardingTo": "Forwarding to", "postForwardingTo": "Forwarding to",
"postReplyingTo": "Replying to", "postReplyingTo": "Replying to",
"postReplyPlaceholder": "Post your reply",
"postEditing": "You are editing an existing post", "postEditing": "You are editing an existing post",
"postArticle": "Article", "postArticle": "Article",
"aboutDeviceName": "Device Name", "aboutDeviceName": "Device Name",

View File

@@ -178,25 +178,25 @@ PODS:
- sqflite_darwin (0.0.4): - sqflite_darwin (0.0.4):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqlite3 (3.50.3): - sqlite3 (3.50.4):
- sqlite3/common (= 3.50.3) - sqlite3/common (= 3.50.4)
- sqlite3/common (3.50.3) - sqlite3/common (3.50.4)
- sqlite3/dbstatvtab (3.50.3): - sqlite3/dbstatvtab (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/fts5 (3.50.3): - sqlite3/fts5 (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/math (3.50.3): - sqlite3/math (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/perf-threadsafe (3.50.3): - sqlite3/perf-threadsafe (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/rtree (3.50.3): - sqlite3/rtree (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/session (3.50.3): - sqlite3/session (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3_flutter_libs (0.0.1): - sqlite3_flutter_libs (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqlite3 (~> 3.50.3) - sqlite3 (~> 3.50.4)
- sqlite3/dbstatvtab - sqlite3/dbstatvtab
- sqlite3/fts5 - sqlite3/fts5
- sqlite3/math - sqlite3/math
@@ -406,8 +406,8 @@ SPEC CHECKSUMS:
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418 sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: 83105acd294c9137c026e2da1931c30b4588ab81 sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
sqlite3_flutter_libs: 616267f2fca40e9c6af8c5d82324e05667040b6e sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4 super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d url_launcher_ios: 694010445543906933d732453a59da0a173ae33d

View File

@@ -8,7 +8,7 @@
import Foundation import Foundation
func getAttachmentUrl(for identifier: String) -> String { func getAttachmentUrl(for identifier: String) -> String {
let serverBaseUrl = "https://nt.solian.app" let serverBaseUrl = "https://api.solian.app"
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/files/\(identifier)" return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/drive/files/\(identifier)"
} }

View File

@@ -181,6 +181,9 @@ class IslandApp extends HookConsumerWidget {
} }
useEffect(() { useEffect(() {
if (!kIsWeb && Platform.isLinux) {
return null;
}
const channel = MethodChannel('dev.solsynth.solian/notifications'); const channel = MethodChannel('dev.solsynth.solian/notifications');
Future<void> handleInitialLink() async { Future<void> handleInitialLink() async {

View File

@@ -58,7 +58,7 @@ class StickerPackDetailScreen extends HookConsumerWidget {
try { try {
showLoadingModal(context); showLoadingModal(context);
final apiClient = ref.watch(apiClientProvider); final apiClient = ref.watch(apiClientProvider);
await apiClient.delete('/stickers/$id/content/${sticker.id}'); await apiClient.delete('/sphere/stickers/$id/content/${sticker.id}');
ref.invalidate(stickerPackContentProvider(id)); ref.invalidate(stickerPackContentProvider(id));
} catch (err) { } catch (err) {
showErrorAlert(err); showErrorAlert(err);
@@ -297,7 +297,7 @@ class _StickerPackActionMenu extends HookConsumerWidget {
).then((confirm) { ).then((confirm) {
if (confirm) { if (confirm) {
final client = ref.watch(apiClientProvider); final client = ref.watch(apiClientProvider);
client.delete('/stickers/$packId'); client.delete('/sphere/stickers/$packId');
ref.invalidate(stickerPacksNotifierProvider); ref.invalidate(stickerPacksNotifierProvider);
if (context.mounted) context.pop(true); if (context.mounted) context.pop(true);
} }
@@ -325,7 +325,7 @@ Future<SnSticker?> stickerPackSticker(
if (query == null) return null; if (query == null) return null;
final apiClient = ref.watch(apiClientProvider); final apiClient = ref.watch(apiClientProvider);
final resp = await apiClient.get( final resp = await apiClient.get(
'/stickers/${query.packId}/content/${query.id}', '/sphere/stickers/${query.packId}/content/${query.id}',
); );
if (resp.data == null) return null; if (resp.data == null) return null;
return SnSticker.fromJson(resp.data); return SnSticker.fromJson(resp.data);
@@ -379,8 +379,8 @@ class EditStickersScreen extends HookConsumerWidget {
try { try {
final resp = await apiClient.request( final resp = await apiClient.request(
id == null id == null
? '/stickers/$packId/content' ? '/sphere/stickers/$packId/content'
: '/stickers/$packId/content/$id', : '/sphere/stickers/$packId/content/$id',
data: {'slug': slugController.text, 'image_id': imageController.text}, data: {'slug': slugController.text, 'image_id': imageController.text},
options: Options(method: id == null ? 'POST' : 'PATCH'), options: Options(method: id == null ? 'POST' : 'PATCH'),
); );

View File

@@ -92,6 +92,7 @@ class PostDetailScreen extends HookConsumerWidget {
right: 0, right: 0,
child: Material( child: Material(
elevation: 2, elevation: 2,
color: Theme.of(context).colorScheme.surfaceContainer,
child: postState child: postState
.when( .when(
data: data:
@@ -107,8 +108,8 @@ class PostDetailScreen extends HookConsumerWidget {
error: (_, _) => const SizedBox.shrink(), error: (_, _) => const SizedBox.shrink(),
) )
.padding( .padding(
bottom: MediaQuery.of(context).padding.bottom + 16, bottom: MediaQuery.of(context).padding.bottom + 8,
top: 16, top: 8,
horizontal: 16, horizontal: 16,
), ),
), ),

View File

@@ -55,7 +55,7 @@ class AccountStatusCreationSheet extends HookConsumerWidget {
'attitude': attitude.value, 'attitude': attitude.value,
'is_invisible': isInvisible.value, 'is_invisible': isInvisible.value,
'is_not_disturb': isNotDisturb.value, 'is_not_disturb': isNotDisturb.value,
'cleared_at': clearedAt.value?.toIso8601String(), 'cleared_at': clearedAt.value?.toUtc().toIso8601String(),
if (labelController.text.isNotEmpty) 'label': labelController.text, if (labelController.text.isNotEmpty) 'label': labelController.text,
}, },
options: Options(method: initialStatus == null ? 'POST' : 'PATCH'), options: Options(method: initialStatus == null ? 'POST' : 'PATCH'),

View File

@@ -248,7 +248,7 @@ class _PaymentContentState extends ConsumerState<_PaymentContent> {
try { try {
final client = ref.read(apiClientProvider); final client = ref.read(apiClientProvider);
final response = await client.post( final response = await client.post(
'/orders/${widget.order.id}/pay', '/id/orders/${widget.order.id}/pay',
data: {'pin_code': pin}, data: {'pin_code': pin},
); );

View File

@@ -273,7 +273,7 @@ class PostItem extends HookConsumerWidget {
: item.reactionsCount.entries : item.reactionsCount.entries
.sortedBy((e) => e.value) .sortedBy((e) => e.value)
.map((e) => e.key) .map((e) => e.key)
.first; .last;
final postLanguage = final postLanguage =
item.content != null item.content != null
@@ -480,7 +480,9 @@ class PostItem extends HookConsumerWidget {
], ],
), ),
) )
else if (item.content?.isNotEmpty ?? false) else if ((item.content?.isNotEmpty ?? false) ||
(item.title?.isNotEmpty ?? false) ||
(item.description?.isNotEmpty ?? false))
Padding( Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: renderingPadding.horizontal, left: renderingPadding.horizontal,

View File

@@ -1,11 +1,13 @@
import 'package:dio/dio.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
import 'package:island/models/publisher.dart'; import 'package:island/models/publisher.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/screens/creators/publishers.dart'; import 'package:island/screens/creators/publishers.dart';
import 'package:island/screens/posts/compose.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/post/publishers_modal.dart'; import 'package:island/widgets/post/publishers_modal.dart';
@@ -14,8 +16,14 @@ import 'package:styled_widget/styled_widget.dart';
class PostQuickReply extends HookConsumerWidget { class PostQuickReply extends HookConsumerWidget {
final SnPost parent; final SnPost parent;
final Function? onPosted; final VoidCallback? onPosted;
const PostQuickReply({super.key, required this.parent, this.onPosted}); final VoidCallback? onLaunch;
const PostQuickReply({
super.key,
required this.parent,
this.onPosted,
this.onLaunch,
});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
@@ -48,7 +56,7 @@ class PostQuickReply extends HookConsumerWidget {
'content': contentController.text, 'content': contentController.text,
'replied_post_id': parent.id, 'replied_post_id': parent.id,
}, },
options: Options(headers: {'X-Pub': currentPublisher.value?.name}), queryParameters: {'pub': currentPublisher.value?.name},
); );
contentController.clear(); contentController.clear();
onPosted?.call(); onPosted?.call();
@@ -83,9 +91,10 @@ class PostQuickReply extends HookConsumerWidget {
child: TextField( child: TextField(
controller: contentController, controller: contentController,
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Post your reply', hintText: 'postReplyPlaceholder'.tr(),
border: const OutlineInputBorder(), border: InputBorder.none,
isDense: true, isDense: true,
isCollapsed: true,
contentPadding: EdgeInsets.symmetric( contentPadding: EdgeInsets.symmetric(
horizontal: 12, horizontal: 12,
vertical: 8, vertical: 8,
@@ -97,6 +106,26 @@ class PostQuickReply extends HookConsumerWidget {
(_) => FocusManager.instance.primaryFocus?.unfocus(), (_) => FocusManager.instance.primaryFocus?.unfocus(),
), ),
), ),
IconButton(
onPressed: () {
onLaunch?.call();
GoRouter.of(context)
.pushNamed(
'postCompose',
extra: PostComposeInitialState(
content: contentController.text,
replyingTo: parent,
),
)
.then((value) {
if (value != null) onPosted?.call();
});
},
icon: const Icon(Symbols.launch, size: 20),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
constraints: const BoxConstraints(),
),
IconButton( IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
@@ -110,6 +139,7 @@ class PostQuickReply extends HookConsumerWidget {
: Icon(Symbols.send, size: 20), : Icon(Symbols.send, size: 20),
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
onPressed: submitting.value ? null : performAction, onPressed: submitting.value ? null : performAction,
constraints: const BoxConstraints(),
), ),
], ],
), ),

View File

@@ -38,14 +38,18 @@ class PostRepliesSheet extends HookConsumerWidget {
if (user.value != null) if (user.value != null)
Material( Material(
elevation: 2, elevation: 2,
color: Theme.of(context).colorScheme.surfaceContainerHigh,
child: PostQuickReply( child: PostQuickReply(
parent: post, parent: post,
onPosted: () { onPosted: () {
ref.invalidate(postRepliesNotifierProvider(post.id)); ref.invalidate(postRepliesNotifierProvider(post.id));
}, },
onLaunch: () {
Navigator.of(context).pop();
},
).padding( ).padding(
bottom: MediaQuery.of(context).padding.bottom + 16, bottom: MediaQuery.of(context).padding.bottom + 8,
top: 16, top: 8,
horizontal: 16, horizontal: 16,
), ),
), ),

View File

@@ -130,25 +130,25 @@ PODS:
- sqflite_darwin (0.0.4): - sqflite_darwin (0.0.4):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqlite3 (3.50.3): - sqlite3 (3.50.4):
- sqlite3/common (= 3.50.3) - sqlite3/common (= 3.50.4)
- sqlite3/common (3.50.3) - sqlite3/common (3.50.4)
- sqlite3/dbstatvtab (3.50.3): - sqlite3/dbstatvtab (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/fts5 (3.50.3): - sqlite3/fts5 (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/math (3.50.3): - sqlite3/math (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/perf-threadsafe (3.50.3): - sqlite3/perf-threadsafe (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/rtree (3.50.3): - sqlite3/rtree (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3/session (3.50.3): - sqlite3/session (3.50.4):
- sqlite3/common - sqlite3/common
- sqlite3_flutter_libs (0.0.1): - sqlite3_flutter_libs (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqlite3 (~> 3.50.3) - sqlite3 (~> 3.50.4)
- sqlite3/dbstatvtab - sqlite3/dbstatvtab
- sqlite3/fts5 - sqlite3/fts5
- sqlite3/math - sqlite3/math
@@ -328,8 +328,8 @@ SPEC CHECKSUMS:
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sign_in_with_apple: 6673c03c9e3643f6c8d33601943fbfa9ae99f94e sign_in_with_apple: 6673c03c9e3643f6c8d33601943fbfa9ae99f94e
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: 83105acd294c9137c026e2da1931c30b4588ab81 sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
sqlite3_flutter_libs: 616267f2fca40e9c6af8c5d82324e05667040b6e sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189 super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd