diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index d03e7fc..4166bc2 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 77; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -448,14 +448,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; @@ -491,14 +487,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; diff --git a/lib/database/message_repository.dart b/lib/database/message_repository.dart index c75e640..72b71d5 100644 --- a/lib/database/message_repository.dart +++ b/lib/database/message_repository.dart @@ -309,7 +309,7 @@ class MessageRepository { } Future retryMessage(String pendingMessageId) async { - final message = pendingMessages[pendingMessageId]; + final message = await getMessageById(pendingMessageId); if (message == null) { throw Exception('Message not found'); } diff --git a/lib/screens/chat/room.dart b/lib/screens/chat/room.dart index 599e361..5633d69 100644 --- a/lib/screens/chat/room.dart +++ b/lib/screens/chat/room.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -319,6 +321,15 @@ class ChatRoomScreen extends HookConsumerWidget { ); } + void sendTypingStatus() async { + final wsState = ref.read(websocketStateProvider.notifier); + wsState.sendMessage( + jsonEncode( + WebSocketPacket(type: 'messages.typing', data: {'chat_room_id': id}), + ), + ); + } + var isLoading = false; // Add scroll listener for pagination @@ -414,6 +425,8 @@ class ChatRoomScreen extends HookConsumerWidget { } } + useEffect(() {}); + final compactHeader = isWideScreen(context); final listController = useMemoized(() => ListController(), []); @@ -720,7 +733,7 @@ class ChatRoomScreen extends HookConsumerWidget { } } -class _ChatInput extends ConsumerWidget { +class _ChatInput extends HookConsumerWidget { final TextEditingController messageController; final SnChatRoom chatRoom; final VoidCallback onSend; @@ -751,46 +764,59 @@ class _ChatInput extends ConsumerWidget { required this.onAttachmentsChanged, }); - void _handleKeyPress(BuildContext context, WidgetRef ref, RawKeyEvent event) { - if (event is! RawKeyDownEvent) return; - - final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; - final isModifierPressed = event.isMetaPressed || event.isControlPressed; - - if (isPaste && isModifierPressed) { - _handlePaste(); - return; - } - - final enterToSend = ref.read(appSettingsNotifierProvider).enterToSend; - final isEnter = event.logicalKey == LogicalKeyboardKey.enter; - - if (isEnter) { - if (enterToSend && !isModifierPressed) { - onSend(); - } else if (!enterToSend && isModifierPressed) { - onSend(); - } - } - } - - Future _handlePaste() async { - final clipboard = await Pasteboard.image; - if (clipboard == null) return; - - onAttachmentsChanged([ - ...attachments, - UniversalFile( - data: XFile.fromData(clipboard, mimeType: "image/jpeg"), - type: UniversalFileType.image, - ), - ]); - } - @override Widget build(BuildContext context, WidgetRef ref) { + final inputFocusNode = useFocusNode(); + final enterToSend = ref.watch(appSettingsNotifierProvider).enterToSend; + final isMobile = !kIsWeb && (Platform.isAndroid || Platform.isIOS); + + void send() { + inputFocusNode.requestFocus(); + onSend.call(); + } + + Future handlePaste() async { + final clipboard = await Pasteboard.image; + if (clipboard == null) return; + + onAttachmentsChanged([ + ...attachments, + UniversalFile( + data: XFile.fromData(clipboard, mimeType: "image/jpeg"), + type: UniversalFileType.image, + ), + ]); + } + + void handleKeyPress( + BuildContext context, + WidgetRef ref, + RawKeyEvent event, + ) { + if (event is! RawKeyDownEvent) return; + + final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; + final isModifierPressed = event.isMetaPressed || event.isControlPressed; + + if (isPaste && isModifierPressed) { + handlePaste(); + return; + } + + final enterToSend = ref.read(appSettingsNotifierProvider).enterToSend; + final isEnter = event.logicalKey == LogicalKeyboardKey.enter; + + if (isEnter) { + if (enterToSend && !isModifierPressed) { + send(); + } else if (!enterToSend && isModifierPressed) { + send(); + } + } + } + return Material( elevation: 8, color: Theme.of(context).colorScheme.surface, @@ -892,12 +918,23 @@ class _ChatInput extends ConsumerWidget { Expanded( child: RawKeyboardListener( focusNode: FocusNode(), - onKey: (event) => _handleKeyPress(context, ref, event), + onKey: (event) => handleKeyPress(context, ref, event), child: TextField( + focusNode: inputFocusNode, controller: messageController, - onSubmitted: enterToSend ? (_) => onSend() : null, + onSubmitted: + (enterToSend && isMobile) + ? (_) { + send(); + } + : null, + keyboardType: + (enterToSend && isMobile) + ? TextInputType.text + : TextInputType.multiline, + textInputAction: TextInputAction.send, inputFormatters: [ - if (enterToSend) + if (enterToSend && !isMobile) TextInputFormatter.withFunction((oldValue, newValue) { if (newValue.text.endsWith('\n')) { return oldValue; @@ -932,7 +969,7 @@ class _ChatInput extends ConsumerWidget { IconButton( icon: const Icon(Icons.send), color: Theme.of(context).colorScheme.primary, - onPressed: onSend, + onPressed: send, ), ], ).padding(bottom: MediaQuery.of(context).padding.bottom),