Skip to content

Commit

Permalink
TW-724 Improve composer with enter shortcut and need support Vietnamese
Browse files Browse the repository at this point in the history
  • Loading branch information
drminh2807 authored and hoangdat committed Oct 5, 2023
1 parent 0496746 commit b052f2a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 78 deletions.
6 changes: 4 additions & 2 deletions lib/pages/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class ChatController extends State<Chat>
final ValueNotifier<bool> showScrollDownButtonNotifier = ValueNotifier(false);
final ValueNotifier<bool> showEmojiPickerNotifier = ValueNotifier(false);
FocusNode inputFocus = FocusNode();
FocusNode keyboardFocus = FocusNode();

Timer? typingCoolDown;
Timer? typingTimeout;
Expand Down Expand Up @@ -1178,8 +1179,9 @@ class ChatController extends State<Chat>
return index + 1;
}

void onInputBarSubmitted(_) {
send();
void onInputBarSubmitted(_) async {
await send();
await Future.delayed(const Duration(milliseconds: 100));
FocusScope.of(context).requestFocus(inputFocus);
}

Expand Down
1 change: 1 addition & 0 deletions lib/pages/chat/chat_input_row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class ChatInputRow extends StatelessWidget {
textInputAction: AppConfig.sendOnEnter ? TextInputAction.send : null,
onSubmitted: controller.onInputBarSubmitted,
focusNode: controller.inputFocus,
keyboardFocusNode: controller.keyboardFocus,
controller: controller.sendController,
decoration: InputDecoration(
hintText: L10n.of(context)!.chatMessage,
Expand Down
126 changes: 50 additions & 76 deletions lib/pages/chat/input_bar.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:fluffychat/utils/extension/raw_key_event_extension.dart';
import 'package:fluffychat/widgets/avatar/avatar.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:emojis/emoji.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
Expand All @@ -23,6 +23,7 @@ class InputBar extends StatelessWidget {
final TextInputAction? textInputAction;
final ValueChanged<String>? onSubmitted;
final FocusNode? focusNode;
final FocusNode keyboardFocusNode;
final TextEditingController? controller;
final InputDecoration? decoration;
final ValueChanged<String>? onChanged;
Expand All @@ -36,6 +37,7 @@ class InputBar extends StatelessWidget {
this.keyboardType,
this.onSubmitted,
this.focusNode,
required this.keyboardFocusNode,
this.controller,
this.decoration,
this.onChanged,
Expand Down Expand Up @@ -302,82 +304,54 @@ class InputBar extends StatelessWidget {
final useShortCuts = (PlatformInfos.isWeb ||
PlatformInfos.isDesktop ||
AppConfig.sendOnEnter);
return Shortcuts(
shortcuts: !useShortCuts
? {}
: {
LogicalKeySet(LogicalKeyboardKey.shift, LogicalKeyboardKey.enter):
NewLineIntent(),
LogicalKeySet(LogicalKeyboardKey.enter): SubmitLineIntent(),
},
child: Actions(
actions: !useShortCuts
? {}
: {
NewLineIntent: CallbackAction(
onInvoke: (i) {
final val = controller!.value;
final selection = val.selection.start;
final messageWithoutNewLine =
'${controller!.text.substring(0, val.selection.start)}\n${controller!.text.substring(val.selection.end)}';
controller!.value = TextEditingValue(
text: messageWithoutNewLine,
selection: TextSelection.fromPosition(
TextPosition(offset: selection + 1),
),
);
return null;
},
),
SubmitLineIntent: CallbackAction(
onInvoke: (i) {
onSubmitted!(controller!.text);
return null;
},
),
},
child: TypeAheadField<Map<String, String?>>(
direction: AxisDirection.up,
hideOnEmpty: true,
hideOnLoading: true,
keepSuggestionsOnSuggestionSelected: true,
debounceDuration: const Duration(milliseconds: 50),
// show suggestions after 50ms idle time (default is 300)
textFieldConfiguration: TextFieldConfiguration(
minLines: minLines,
maxLines: maxLines,
keyboardType: keyboardType!,
textInputAction: textInputAction,
autofocus: autofocus!,
style: InputBarStyle.getTypeAheadTextStyle(context),
onSubmitted: (text) {
// fix for library for now
// it sets the types for the callback incorrectly
onSubmitted!(text);
},
controller: controller,
decoration: decoration!,
focusNode: focusNode,
onChanged: (text) {
// fix for the library for now
// it sets the types for the callback incorrectly
onChanged!(text);
},
textCapitalization: TextCapitalization.sentences,
),
suggestionsCallback: getSuggestions,
itemBuilder: (context, suggestion) => SuggestionTile(
suggestion: suggestion,
client: Matrix.of(context).client,
),
onSuggestionSelected: (Map<String, String?> suggestion) =>
insertSuggestion(context, suggestion),
errorBuilder: (BuildContext context, Object? error) => Container(),
loadingBuilder: (BuildContext context) => Container(),
// fix loading briefly flickering a dark box
noItemsFoundBuilder: (BuildContext context) =>
Container(), // fix loading briefly showing no suggestions
return RawKeyboardListener(
focusNode: keyboardFocusNode,
onKey: (event) {
if (useShortCuts && event.isEnter) {
onSubmitted?.call(controller?.text ?? '');
}
},
child: TypeAheadField<Map<String, String?>>(
direction: AxisDirection.up,
hideOnEmpty: true,
hideOnLoading: true,
keepSuggestionsOnSuggestionSelected: true,
debounceDuration: const Duration(milliseconds: 50),
// show suggestions after 50ms idle time (default is 300)
textFieldConfiguration: TextFieldConfiguration(
minLines: minLines,
maxLines: maxLines,
keyboardType: keyboardType!,
textInputAction: textInputAction,
autofocus: autofocus!,
style: InputBarStyle.getTypeAheadTextStyle(context),
onSubmitted: (text) {
// fix for library for now
// it sets the types for the callback incorrectly
onSubmitted!(text);
},
controller: controller,
decoration: decoration!,
focusNode: focusNode,
onChanged: (text) {
// fix for the library for now
// it sets the types for the callback incorrectly
onChanged!(text);
},
textCapitalization: TextCapitalization.sentences,
),
suggestionsCallback: getSuggestions,
itemBuilder: (context, suggestion) => SuggestionTile(
suggestion: suggestion,
client: Matrix.of(context).client,
),
onSuggestionSelected: (Map<String, String?> suggestion) =>
insertSuggestion(context, suggestion),
errorBuilder: (BuildContext context, Object? error) => Container(),
loadingBuilder: (BuildContext context) => Container(),
// fix loading briefly flickering a dark box
noItemsFoundBuilder: (BuildContext context) =>
Container(), // fix loading briefly showing no suggestions
),
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/pages/chat_draft/draft_chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class DraftChatController extends State<DraftChat>
final AutoScrollController forwardListController = AutoScrollController();

FocusNode inputFocus = FocusNode();
FocusNode keyboardFocus = FocusNode();

bool showScrollDownButton = false;

Expand Down
2 changes: 2 additions & 0 deletions lib/pages/chat_draft/draft_chat_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class DraftChatView extends StatelessWidget {
onSubmitted:
controller.onInputBarSubmitted,
focusNode: controller.inputFocus,
keyboardFocusNode:
controller.keyboardFocus,
controller: controller.sendController,
decoration: DraftChatViewStyle
.bottomBarInputDecoration(context),
Expand Down
24 changes: 24 additions & 0 deletions lib/utils/extension/raw_key_event_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:flutter/services.dart';

// Refer: https://github.com/flutter/flutter/issues/35435#issuecomment-540582796
extension RawKeyEventExtension on RawKeyEvent {
bool get isEnter {
if (this is! RawKeyUpEvent) {
return false;
}
if (logicalKey == LogicalKeyboardKey.enter) {
return true;
}
if (data is RawKeyEventDataWeb) {
if ((data as RawKeyEventDataWeb).keyLabel == 'Enter') {
return true;
}
}
if (data is RawKeyEventDataAndroid) {
if ((data as RawKeyEventDataAndroid).keyCode == 13) {
return true;
}
}
return false;
}
}

0 comments on commit b052f2a

Please sign in to comment.