Merge branch 'develop' of https://github.com/DonutWare/Fladder into develop

This commit is contained in:
PartyDonut 2025-11-09 10:57:28 +01:00
commit a4ec2637fc
3 changed files with 79 additions and 19 deletions

View file

@ -1366,5 +1366,6 @@
"format": "jm" "format": "jm"
} }
} }
} },
"openImeKeyboard": "Open IME keyboard"
} }

View file

@ -13,7 +13,9 @@ class KeyboardLayouts {
['4', '5', '6', '(', ')', 'ABC'], ['4', '5', '6', '(', ')', 'ABC'],
['7', '8', '9', '@', '!', '?'], ['7', '8', '9', '@', '!', '?'],
['0', '/', '\$', '%', '+', '[', ']'], ['0', '/', '\$', '%', '+', '[', ']'],
['.', '-', '_', '"', ':'] ['.', '-', '_', '"', ':'],
['{', '}', '\\', '|', '~'],
['<', '>', '\$', '*', '=']
], ],
}, },
'es': { 'es': {
@ -29,7 +31,9 @@ class KeyboardLayouts {
['4', '5', '6', '(', ')', 'ABC'], ['4', '5', '6', '(', ')', 'ABC'],
['7', '8', '9', '@', '!', '?'], ['7', '8', '9', '@', '!', '?'],
['0', '/', '\$', '%', '+', '[', ']'], ['0', '/', '\$', '%', '+', '[', ']'],
['.', '-', '_', '"', ':'] ['.', '-', '_', '"', ':'],
['{', '}', '\\', '|', '~'],
['<', '>', '\$', '*', '=']
], ],
}, },
'de': { 'de': {
@ -46,7 +50,9 @@ class KeyboardLayouts {
['4', '5', '6', '(', ')', 'ABC'], ['4', '5', '6', '(', ')', 'ABC'],
['7', '8', '9', '@', '!', '?'], ['7', '8', '9', '@', '!', '?'],
['0', '/', '\$', '%', '+', '[', ']'], ['0', '/', '\$', '%', '+', '[', ']'],
['.', '-', '_', '"', ':'] ['.', '-', '_', '"', ':'],
['{', '}', '\\', '|', '~'],
['<', '>', '\$', '*', '=']
], ],
}, },
'fr': { 'fr': {
@ -64,7 +70,9 @@ class KeyboardLayouts {
['4', '5', '6', '(', ')', 'ABC'], ['4', '5', '6', '(', ')', 'ABC'],
['7', '8', '9', '@', '!', '?'], ['7', '8', '9', '@', '!', '?'],
['0', '/', '\$', '%', '+', '[', ']'], ['0', '/', '\$', '%', '+', '[', ']'],
['.', '-', '_', '"', ':'] ['.', '-', '_', '"', ':'],
['{', '}', '\\', '|', '~'],
['<', '>', '\$', '*', '=']
], ],
}, },
'ja': { 'ja': {
@ -81,7 +89,9 @@ class KeyboardLayouts {
['6', '7', '8', '9', '0', 'ABC'], ['6', '7', '8', '9', '0', 'ABC'],
['!', '@', '#', '\$', '%'], ['!', '@', '#', '\$', '%'],
['^', '&', '*', '(', ')'], ['^', '&', '*', '(', ')'],
['-', '_', '¥', '.', ','] ['-', '_', '¥', '.', ','],
['{', '}', '\\', '|', '~'],
['<', '>', '\$', '*', '=']
], ],
}, },
'zh': { 'zh': {
@ -97,7 +107,9 @@ class KeyboardLayouts {
['6', '7', '8', '9', '0', 'ABC'], ['6', '7', '8', '9', '0', 'ABC'],
['!', '@', '#', '\$', '%'], ['!', '@', '#', '\$', '%'],
['^', '&', '*', '(', ')'], ['^', '&', '*', '(', ')'],
['-', '_', '¥', '·', ''] ['-', '_', '¥', '·', ''],
['{', '}', '\\', '|', '~'],
['<', '>', '\$', '*', '=']
], ],
}, },
}; };

View file

@ -162,6 +162,9 @@ class _CustomKeyboardViewState extends State<_CustomKeyboardView> {
ValueNotifier<List<String>> searchQueryResults = ValueNotifier([]); ValueNotifier<List<String>> searchQueryResults = ValueNotifier([]);
final FocusNode internalTextField = FocusNode();
final FocusNode keyboardOpenFocusNode = FocusNode();
Future<void> startUpdate(String text) async { Future<void> startUpdate(String text) async {
final newValues = await widget.searchQuery?.call(widget.controller.text) ?? []; final newValues = await widget.searchQuery?.call(widget.controller.text) ?? [];
searchQueryResults.value = newValues; searchQueryResults.value = newValues;
@ -175,6 +178,15 @@ class _CustomKeyboardViewState extends State<_CustomKeyboardView> {
}); });
} }
@override
void dispose() {
scope.dispose();
internalTextField.dispose();
keyboardOpenFocusNode.dispose();
searchQueryResults.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (!scope.hasFocus) { if (!scope.hasFocus) {
@ -189,19 +201,54 @@ class _CustomKeyboardViewState extends State<_CustomKeyboardView> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
spacing: 16, spacing: 16,
children: [ children: [
Card( Row(
child: Padding( children: [
padding: const EdgeInsets.all(12.0), Expanded(
child: Text( child: ExcludeFocusTraversal(
widget.keyboardType == TextInputType.visiblePassword child: Card(
? List.generate( child: Padding(
widget.controller.text.length, padding: const EdgeInsets.all(12.0),
(index) => "*", child: TextField(
).join() focusNode: internalTextField,
: widget.controller.text, controller: widget.controller,
style: Theme.of(context).textTheme.titleLarge, showCursor: true,
keyboardType: widget.keyboardType,
textInputAction: widget.keyboardActionType,
obscureText: widget.keyboardType == TextInputType.visiblePassword,
onChanged: (value) {
setState(() {
widget.onChanged();
startUpdate(value);
});
},
onSubmitted: (value) {
internalTextField.unfocus();
keyboardOpenFocusNode.requestFocus();
setState(() {
widget.onChanged();
startUpdate(value);
});
},
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.zero,
),
style: Theme.of(context).textTheme.titleLarge,
),
),
),
),
), ),
), IconButton(
focusNode: keyboardOpenFocusNode,
onPressed: () => internalTextField.requestFocus(),
tooltip: context.localized.openImeKeyboard,
icon: const Icon(
IconsaxPlusBold.keyboard_open,
),
)
],
), ),
if (widget.searchQuery != null) if (widget.searchQuery != null)
ValueListenableBuilder( ValueListenableBuilder(