Skip to content

Commit

Permalink
fix(ux): update the search focus for emojis, emoticons, and gifs
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho authored Mar 5, 2024
2 parents 2ad380d + 7ab3ba7 commit a652251
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 58 deletions.
56 changes: 33 additions & 23 deletions lib/components/root/emoji.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'package:collection/collection.dart';
import 'package:flemozi/collections/emojis.dart';
import 'package:flemozi/components/root/twemoji.dart';
import 'package:flemozi/hooks/use_window_listeners.dart';
import 'package:flemozi/intents/close_window.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flemozi/collections/emojis.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';

typedef RatioEmojiType = ({
Expand All @@ -21,14 +21,16 @@ typedef RatioEmojiType = ({
});

class Emoji extends HookWidget {
const Emoji({Key? key}) : super(key: key);
const Emoji({super.key});

@override
Widget build(BuildContext context) {
final searchFocusNode = useFocusNode();
final searchTerm = useState("");
final firstEmojiFocusNode = useFocusNode();

FocusScope.of(context).requestFocus(searchFocusNode);

final filteredEmojis = useMemoized(
() {
if (searchTerm.value.isEmpty) {
Expand Down Expand Up @@ -80,7 +82,7 @@ class Emoji extends HookWidget {

useWindowListeners(
onWindowFocus: () {
searchFocusNode.requestFocus();
FocusScope.of(context).requestFocus(searchFocusNode);
},
);

Expand Down Expand Up @@ -128,28 +130,36 @@ class Emoji extends HookWidget {
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.arrowDown): () {
FocusScope.of(context).requestFocus(firstEmojiFocusNode);
Padding(
padding: const EdgeInsets.only( bottom: 12.0),
child: CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.arrowDown): () {
if (filteredEmojis.isNotEmpty) {
FocusScope.of(context).requestFocus(firstEmojiFocusNode);
}
},
},
},
child: TextField(
autofocus: true,
focusNode: searchFocusNode,
decoration: const InputDecoration(
hintText: "Search",
prefixIcon: Icon(Icons.search),
child: TextField(
autofocus: true,
focusNode: searchFocusNode,
decoration: const InputDecoration(
hintText: "Search",
prefixIcon: Icon(Icons.search),
),
onChanged: (value) {
searchTerm.value = value;
},
onSubmitted: (value) {
if (filteredEmojis.isNotEmpty) {
FocusScope.of(context).requestFocus(firstEmojiFocusNode);
} else {
FocusScope.of(context).requestFocus(searchFocusNode);
}
},
),
onChanged: (value) {
searchTerm.value = value;
},
onSubmitted: (value) {
searchFocusNode.nextFocus();
},
),
),
const SizedBox(height: 10),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
Expand All @@ -163,7 +173,7 @@ class Emoji extends HookWidget {
return HookBuilder(builder: (context) {
final focusnodeUn = useFocusNode();
final focusNode =
index == 0 ? firstEmojiFocusNode : focusnodeUn;
index == 0 ? firstEmojiFocusNode : focusnodeUn;
final emoji = filteredEmojis.elementAt(index);
final tooltipKey = GlobalKey<TooltipState>();

Expand All @@ -184,7 +194,7 @@ class Emoji extends HookWidget {
return CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.escape): () {
searchFocusNode.requestFocus();
FocusScope.of(context).requestFocus(searchFocusNode);
},
},
child: Tooltip(
Expand Down
50 changes: 30 additions & 20 deletions lib/components/root/emoticon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart';

class Emoticon extends HookWidget {
const Emoticon({Key? key}) : super(key: key);
const Emoticon({super.key});

@override
Widget build(BuildContext context) {
final searchFocusNode = useFocusNode();
final searchTerm = useState("");
final firstEmoticonFocusNode = useFocusNode();

FocusScope.of(context).requestFocus(searchFocusNode);

final List<Map<String, String>> filteredEmoticons = useMemoized(
() {
if (searchTerm.value.isEmpty) {
Expand Down Expand Up @@ -70,28 +72,36 @@ class Emoticon extends HookWidget {
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.arrowDown): () {
FocusScope.of(context).requestFocus(firstEmoticonFocusNode);
Padding(
padding: const EdgeInsets.only(bottom: 12.0),
child: CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.arrowDown): () {
if (filteredEmoticons.isNotEmpty) {
FocusScope.of(context).requestFocus(firstEmoticonFocusNode);
}
},
},
},
child: TextField(
autofocus: true,
focusNode: searchFocusNode,
decoration: const InputDecoration(
hintText: "Search",
prefixIcon: Icon(Icons.search),
child: TextField(
autofocus: true,
focusNode: searchFocusNode,
decoration: const InputDecoration(
hintText: "Search",
prefixIcon: Icon(Icons.search),
),
onChanged: (value) {
searchTerm.value = value;
},
onSubmitted: (value) {
if (filteredEmoticons.isNotEmpty) {
firstEmoticonFocusNode.requestFocus();
} else {
FocusScope.of(context).requestFocus(searchFocusNode);
}
},
),
onChanged: (value) {
searchTerm.value = value;
},
onSubmitted: (value) {
searchFocusNode.nextFocus();
},
),
),
const SizedBox(height: 10),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
Expand Down Expand Up @@ -165,7 +175,7 @@ class Emoticon extends HookWidget {
return CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.escape): () {
searchFocusNode.requestFocus();
FocusScope.of(context).requestFocus(searchFocusNode);
},
},
child: Tooltip(
Expand Down
42 changes: 27 additions & 15 deletions lib/components/root/gif.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const placeholder = SizedBox(
);

class Gif extends HookConsumerWidget {
const Gif({Key? key}) : super(key: key);
const Gif({super.key});

@override
Widget build(BuildContext context, ref) {
Expand Down Expand Up @@ -86,6 +86,8 @@ class Gif extends HookConsumerWidget {
final gifs =
text.value.isEmpty || searchGifs.isEmpty ? displayGifs : searchGifs;

FocusScope.of(context).requestFocus(searchFocusNode);

useEffect(() {
if (text.value.isNotEmpty) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
Expand Down Expand Up @@ -120,18 +122,28 @@ class Gif extends HookConsumerWidget {

return Column(
children: [
CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.arrowDown): () {
FocusScope.of(context).requestFocus(focusNode);
Padding(
padding: const EdgeInsets.only(bottom: 12.0),
child: CallbackShortcuts(
bindings: {
LogicalKeySet(LogicalKeyboardKey.arrowDown): () {
FocusScope.of(context).requestFocus(focusNode);
},
},
},
child: TextField(
autofocus: true,
focusNode: searchFocusNode,
onChanged: (value) => text.value = value,
decoration: const InputDecoration(
hintText: 'Search GIFs and Stickers',
child: TextField(
autofocus: true,
focusNode: searchFocusNode,
onChanged: (value) => text.value = value,
onSubmitted: (_) => {
if (gifs.isNotEmpty) {
FocusScope.of(context).requestFocus(focusNode),
} else {
FocusScope.of(context).requestFocus(searchFocusNode),
}
},
decoration: const InputDecoration(
hintText: 'Search GIFs and Stickers',
),
),
),
),
Expand Down Expand Up @@ -194,8 +206,8 @@ class Gif extends HookConsumerWidget {
}
}
},
child: Stack(
children: const [
child: const Stack(
children: [
Center(
child: SizedBox(
height: 50,
Expand All @@ -221,7 +233,7 @@ class Gif extends HookConsumerWidget {
if (imageFile == null) {
return;
}
await ClipboardWriter.instance.write([
await SystemClipboard.instance?.write([
DataWriterItem(suggestedName: basename(gif))
..add(Formats.png(imageFile))
..add(Formats.bmp(imageFile))
Expand Down

0 comments on commit a652251

Please sign in to comment.