diff --git a/analysis_options.yaml b/analysis_options.yaml index 6006d3a..68ce4d3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -15,6 +15,9 @@ linter: - avoid_unused_constructor_parameters - use_super_parameters +formatter: + page_width: 80 + analyzer: errors: # Treat these as info/ignore for existing codebase compatibility diff --git a/lib/src/layouts/keyboard_layout_provider.dart b/lib/src/layouts/keyboard_layout_provider.dart index 6631a46..51422c2 100644 --- a/lib/src/layouts/keyboard_layout_provider.dart +++ b/lib/src/layouts/keyboard_layout_provider.dart @@ -1,6 +1,7 @@ import 'keyboard_language.dart'; import 'languages/bengali.dart'; import 'languages/english.dart'; +import 'languages/french.dart'; /// Manages keyboard languages and provides access to layouts. /// @@ -102,4 +103,5 @@ void initializeKeyboardLayouts() { final provider = KeyboardLayoutProvider.instance; provider.registerLanguage(englishLanguage); provider.registerLanguage(bengaliLanguage); + provider.registerLanguage(frenchLanguage); } diff --git a/lib/src/layouts/languages/french.dart b/lib/src/layouts/languages/french.dart new file mode 100644 index 0000000..037b1d5 --- /dev/null +++ b/lib/src/layouts/languages/french.dart @@ -0,0 +1,299 @@ +import '../../enums.dart'; +import '../../models.dart'; +import '../keyboard_language.dart'; + +/// Standard AZERTY text layout - primary (letters). +final KeyboardLayout _textLayoutPrimary = [ + [ + VirtualKey.character(text: 'a'), + VirtualKey.character(text: 'z'), + VirtualKey.character(text: 'e'), + VirtualKey.character(text: 'r'), + VirtualKey.character(text: 't'), + VirtualKey.character(text: 'y'), + VirtualKey.character(text: 'u'), + VirtualKey.character(text: 'i'), + VirtualKey.character(text: 'o'), + VirtualKey.character(text: 'p'), + ], + [ + VirtualKey.character(text: 'q'), + VirtualKey.character(text: 's'), + VirtualKey.character(text: 'd'), + VirtualKey.character(text: 'f'), + VirtualKey.character(text: 'g'), + VirtualKey.character(text: 'h'), + VirtualKey.character(text: 'j'), + VirtualKey.character(text: 'k'), + VirtualKey.character(text: 'l'), + VirtualKey.character(text: 'm'), + ], + [ + VirtualKey.action(action: KeyAction.shift), + VirtualKey.character(text: 'w'), + VirtualKey.character(text: 'x'), + VirtualKey.character(text: 'c'), + VirtualKey.character(text: 'v'), + VirtualKey.character(text: 'b'), + VirtualKey.character(text: 'n'), + VirtualKey.character(text: "'"), + VirtualKey.action(action: KeyAction.backSpace), + ], + [ + VirtualKey.action(action: KeyAction.symbols, flex: 2), + VirtualKey.character(text: ','), + VirtualKey.action(action: KeyAction.space, flex: 4), + VirtualKey.character(text: '.'), + VirtualKey.action(action: KeyAction.enter, flex: 2), + ], +]; + +/// Text layout - secondary (numbers & common symbols). +final KeyboardLayout _textLayoutSecondary = [ + [ + VirtualKey.character(text: '1'), + VirtualKey.character(text: '2'), + VirtualKey.character(text: '3'), + VirtualKey.character(text: '4'), + VirtualKey.character(text: '5'), + VirtualKey.character(text: '6'), + VirtualKey.character(text: '7'), + VirtualKey.character(text: '8'), + VirtualKey.character(text: '9'), + VirtualKey.character(text: '0'), + ], + [ + VirtualKey.character(text: '@'), + VirtualKey.character(text: '#'), + VirtualKey.character(text: '€'), + VirtualKey.character(text: '_'), + VirtualKey.character(text: '&'), + VirtualKey.character(text: '-'), + VirtualKey.character(text: '+'), + VirtualKey.character(text: '('), + VirtualKey.character(text: ')'), + VirtualKey.character(text: '/'), + ], + [ + VirtualKey.action(action: KeyAction.symbolsAlt), + VirtualKey.character(text: '*'), + VirtualKey.character(text: '"'), + VirtualKey.character(text: "'"), + VirtualKey.character(text: ':'), + VirtualKey.character(text: ';'), + VirtualKey.character(text: '!'), + VirtualKey.character(text: '?'), + VirtualKey.action(action: KeyAction.backSpace), + ], + [ + VirtualKey.action(action: KeyAction.symbols, flex: 2), + VirtualKey.character(text: ','), + VirtualKey.action(action: KeyAction.space, flex: 4), + VirtualKey.character(text: '.'), + VirtualKey.action(action: KeyAction.enter, flex: 2), + ], +]; + +/// Text layout - tertiary (more symbols). +final KeyboardLayout _textLayoutTertiary = [ + [ + VirtualKey.character(text: '~'), + VirtualKey.character(text: '`'), + VirtualKey.character(text: '|'), + VirtualKey.character(text: '•'), + VirtualKey.character(text: '√'), + VirtualKey.character(text: 'π'), + VirtualKey.character(text: '÷'), + VirtualKey.character(text: '×'), + VirtualKey.character(text: '§'), + VirtualKey.character(text: '∆'), + ], + [ + VirtualKey.character(text: '£'), + VirtualKey.character(text: '¥'), + VirtualKey.character(text: r'$'), + VirtualKey.character(text: '¢'), + VirtualKey.character(text: '^'), + VirtualKey.character(text: '°'), + VirtualKey.character(text: '='), + VirtualKey.character(text: '{'), + VirtualKey.character(text: '}'), + VirtualKey.character(text: r'\'), + ], + [ + VirtualKey.action(action: KeyAction.symbolsAlt), + VirtualKey.character(text: '%'), + VirtualKey.character(text: '©'), + VirtualKey.character(text: '®'), + VirtualKey.character(text: '™'), + VirtualKey.character(text: '✓'), + VirtualKey.character(text: '['), + VirtualKey.character(text: ']'), + VirtualKey.action(action: KeyAction.backSpace), + ], + [ + VirtualKey.action(action: KeyAction.symbols, flex: 2), + VirtualKey.character(text: '<'), + VirtualKey.action(action: KeyAction.space, flex: 4), + VirtualKey.character(text: '>'), + VirtualKey.action(action: KeyAction.enter, flex: 2), + ], +]; + +/// Email keyboard - primary layout. +final KeyboardLayout _emailLayoutPrimary = [ + [ + VirtualKey.character(text: 'a'), + VirtualKey.character(text: 'z'), + VirtualKey.character(text: 'e'), + VirtualKey.character(text: 'r'), + VirtualKey.character(text: 't'), + VirtualKey.character(text: 'y'), + VirtualKey.character(text: 'u'), + VirtualKey.character(text: 'i'), + VirtualKey.character(text: 'o'), + VirtualKey.character(text: 'p'), + ], + [ + VirtualKey.character(text: 'q'), + VirtualKey.character(text: 's'), + VirtualKey.character(text: 'd'), + VirtualKey.character(text: 'f'), + VirtualKey.character(text: 'g'), + VirtualKey.character(text: 'h'), + VirtualKey.character(text: 'j'), + VirtualKey.character(text: 'k'), + VirtualKey.character(text: 'l'), + VirtualKey.character(text: 'm'), + ], + [ + VirtualKey.action(action: KeyAction.shift), + VirtualKey.character(text: 'w'), + VirtualKey.character(text: 'x'), + VirtualKey.character(text: 'c'), + VirtualKey.character(text: 'v'), + VirtualKey.character(text: 'b'), + VirtualKey.character(text: 'n'), + VirtualKey.character(text: ','), + VirtualKey.action(action: KeyAction.backSpace), + ], + [ + VirtualKey.action(action: KeyAction.symbols), + VirtualKey.character(text: '@'), + VirtualKey.action(action: KeyAction.space, flex: 3), + VirtualKey.character(text: '.'), + VirtualKey.character(text: '_'), + VirtualKey.character(text: '-'), + VirtualKey.action(action: KeyAction.done), + ], +]; + +/// Email keyboard - secondary & tertiary layouts. +/// These can mirror the text layout secondary/tertiary or include French-specific symbols as needed. +final KeyboardLayout _emailLayoutSecondary = _textLayoutSecondary; +final KeyboardLayout _emailLayoutTertiary = _textLayoutTertiary; + +/// URL keyboard - primary layout. +final KeyboardLayout _urlLayoutPrimary = [ + [ + VirtualKey.character(text: 'a'), + VirtualKey.character(text: 'z'), + VirtualKey.character(text: 'e'), + VirtualKey.character(text: 'r'), + VirtualKey.character(text: 't'), + VirtualKey.character(text: 'y'), + VirtualKey.character(text: 'u'), + VirtualKey.character(text: 'i'), + VirtualKey.character(text: 'o'), + VirtualKey.character(text: 'p'), + ], + [ + VirtualKey.character(text: 'q'), + VirtualKey.character(text: 's'), + VirtualKey.character(text: 'd'), + VirtualKey.character(text: 'f'), + VirtualKey.character(text: 'g'), + VirtualKey.character(text: 'h'), + VirtualKey.character(text: 'j'), + VirtualKey.character(text: 'k'), + VirtualKey.character(text: 'l'), + VirtualKey.character(text: 'm'), + ], + [ + VirtualKey.action(action: KeyAction.shift), + VirtualKey.character(text: 'w'), + VirtualKey.character(text: 'x'), + VirtualKey.character(text: 'c'), + VirtualKey.character(text: 'v'), + VirtualKey.character(text: 'b'), + VirtualKey.character(text: 'n'), + VirtualKey.character(text: ','), + VirtualKey.action(action: KeyAction.backSpace), + ], + [ + VirtualKey.action(action: KeyAction.symbols), + VirtualKey.character(text: '/'), + VirtualKey.character(text: '.'), + VirtualKey.action(action: KeyAction.space, flex: 2), + VirtualKey.character(text: '-'), + VirtualKey.character(text: ':'), + VirtualKey.action(action: KeyAction.go), + ], +]; + +final KeyboardLayout _urlLayoutSecondary = _textLayoutSecondary; +final KeyboardLayout _urlLayoutTertiary = _textLayoutTertiary; + +/// Number, signed number, and phone layouts remain the same as in English. +final KeyboardLayout _numberLayout = [ + [VirtualKey.character(text: '1'), VirtualKey.character(text: '2'), VirtualKey.character(text: '3')], + [VirtualKey.character(text: '4'), VirtualKey.character(text: '5'), VirtualKey.character(text: '6')], + [VirtualKey.character(text: '7'), VirtualKey.character(text: '8'), VirtualKey.character(text: '9')], + [VirtualKey.character(text: '.'), VirtualKey.character(text: '0'), VirtualKey.action(action: KeyAction.backSpace)], +]; + +final KeyboardLayout _signedNumberLayout = [ + [VirtualKey.character(text: '1'), VirtualKey.character(text: '2'), VirtualKey.character(text: '3')], + [VirtualKey.character(text: '4'), VirtualKey.character(text: '5'), VirtualKey.character(text: '6')], + [VirtualKey.character(text: '7'), VirtualKey.character(text: '8'), VirtualKey.character(text: '9')], + [VirtualKey.character(text: '-'), VirtualKey.character(text: '0'), VirtualKey.character(text: '.')], + [VirtualKey.action(action: KeyAction.backSpace, flex: 2), VirtualKey.action(action: KeyAction.done)], +]; + +final KeyboardLayout _phoneLayout = [ + [VirtualKey.character(text: '1'), VirtualKey.character(text: '2'), VirtualKey.character(text: '3')], + [VirtualKey.character(text: '4'), VirtualKey.character(text: '5'), VirtualKey.character(text: '6')], + [VirtualKey.character(text: '7'), VirtualKey.character(text: '8'), VirtualKey.character(text: '9')], + [VirtualKey.character(text: '*'), VirtualKey.character(text: '0'), VirtualKey.character(text: '#')], + [ + VirtualKey.character(text: '+'), + VirtualKey.action(action: KeyAction.backSpace), + VirtualKey.action(action: KeyAction.call), + ], +]; + +/// French (AZERTY) keyboard language. +final KeyboardLanguage frenchLanguage = KeyboardLanguage( + code: 'fr', + name: 'French', + nativeName: 'Français', + textLayouts: KeyboardLayoutSet( + primary: _textLayoutPrimary, + secondary: _textLayoutSecondary, + tertiary: _textLayoutTertiary, + ), + emailLayouts: KeyboardLayoutSet( + primary: _emailLayoutPrimary, + secondary: _emailLayoutSecondary, + tertiary: _emailLayoutTertiary, + ), + urlLayouts: KeyboardLayoutSet( + primary: _urlLayoutPrimary, + secondary: _urlLayoutSecondary, + tertiary: _urlLayoutTertiary, + ), + numberLayouts: KeyboardLayoutSet.single(_numberLayout), + numberSignedLayouts: KeyboardLayoutSet.single(_signedNumberLayout), + numberDecimalLayouts: KeyboardLayoutSet.single(_numberLayout), + phoneLayouts: KeyboardLayoutSet.single(_phoneLayout), +); diff --git a/lib/src/layouts/languages/languages.dart b/lib/src/layouts/languages/languages.dart index baa11c9..b68d533 100644 --- a/lib/src/layouts/languages/languages.dart +++ b/lib/src/layouts/languages/languages.dart @@ -12,3 +12,4 @@ library; export 'bengali.dart'; export 'english.dart'; +export 'french.dart'; diff --git a/lib/src/widgets/keyboard.dart b/lib/src/widgets/keyboard.dart index 9a07538..31c76fc 100644 --- a/lib/src/widgets/keyboard.dart +++ b/lib/src/widgets/keyboard.dart @@ -1,6 +1,8 @@ import 'dart:async'; import 'dart:math'; + import 'package:flutter/material.dart'; + import '../enums.dart'; import '../layouts/keyboard_language.dart'; import '../layouts/keyboard_layout_provider.dart'; @@ -32,6 +34,7 @@ class VirtualKeypad extends StatefulWidget { const VirtualKeypad({ super.key, this.type, + this.inputAction, this.height = 280, this.width, this.theme = VirtualKeypadTheme.light, @@ -45,6 +48,9 @@ class VirtualKeypad extends StatefulWidget { /// Override keyboard type. If null, uses the type from the focused text field. final KeyboardType? type; + /// Override input action. If null, uses the action from the focused text field. + final TextInputAction? inputAction; + /// Height of the keyboard in logical pixels. final double height; @@ -55,7 +61,7 @@ class VirtualKeypad extends StatefulWidget { final VirtualKeypadTheme theme; /// Optional callback invoked when any key is pressed. - final void Function(VirtualKey key)? onKeyPressed; + final void Function(VirtualKey key, String? text)? onKeyPressed; /// Custom layout when [type] is [KeyboardType.custom]. final KeyboardLayout? customLayout; @@ -130,7 +136,9 @@ class _VirtualKeypadState extends State { } TextInputAction get _effectiveInputAction { - return _scope?.activeInputAction ?? TextInputAction.done; + return widget.inputAction ?? + _scope?.activeInputAction ?? + TextInputAction.done; } KeyboardLayout get _currentLayout { @@ -185,9 +193,10 @@ class _VirtualKeypadState extends State { void _onKeyPressed(VirtualKey key) { final scope = _scope; + var text = key.text; if (key.isCharacter) { - final text = key.getInsertText(shift: _shift, capsLock: _capsLock); + text = key.getInsertText(shift: _shift, capsLock: _capsLock); scope?.insertText(text); if (_shift && !_capsLock) { @@ -197,7 +206,7 @@ class _VirtualKeypadState extends State { _handleAction(key.action!, scope); } - widget.onKeyPressed?.call(key); + widget.onKeyPressed?.call(key, text); } void _handleAction(KeyAction action, VirtualKeypadScopeState? scope) { @@ -338,6 +347,7 @@ class _VirtualKeypadState extends State { return _KeyWidget( key: ValueKey('${key.text ?? key.action}'), virtualKey: key, + type: _effectiveKeyboardType, height: keyHeight, baseWidth: baseKeyWidth, theme: widget.theme, @@ -377,6 +387,7 @@ class _KeyWidget extends StatefulWidget { const _KeyWidget({ super.key, required this.virtualKey, + required this.type, required this.height, required this.baseWidth, required this.theme, @@ -389,6 +400,7 @@ class _KeyWidget extends StatefulWidget { }); final VirtualKey virtualKey; + final KeyboardType type; final double height; final double baseWidth; final VirtualKeypadTheme theme; @@ -560,10 +572,19 @@ class _KeyWidgetState extends State<_KeyWidget> { ); case KeyAction.enter: - return Icon( - Icons.keyboard_return, - size: widget.theme.keyTextSize, - color: widget.theme.keyTextColor, + if (widget.type == KeyboardType.multiline) { + return Icon( + Icons.keyboard_return, + size: widget.theme.keyTextSize, + color: widget.theme.keyTextColor, + ); + } + return Text( + _getActionLabel(), + style: TextStyle( + fontSize: widget.theme.keyTextSize * 0.7, + color: widget.theme.keyTextColor, + ), ); case KeyAction.shift: