TF-3911 Add Keyboard shortcuts dictionary in Setting
This commit is contained in:
+190
@@ -0,0 +1,190 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_custom_tab_bar/custom_tab_bar.dart';
|
||||
import 'package:flutter_custom_tab_bar/indicator/custom_indicator.dart';
|
||||
import 'package:flutter_custom_tab_bar/indicator/linear_indicator.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/base/setting_detail_view_builder.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/keyboard_shortcut_extension.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/keyboard_shortcuts/widgets/shortcut_category_list_widget.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/keyboard_shortcuts/widgets/shortcut_tab_bar_widget.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/model/keyboard_shortcuts/keyboard_shortcut.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/model/keyboard_shortcuts/keyboard_shortcuts_manager.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/widgets/setting_explanation_widget.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/widgets/setting_header_widget.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class KeyboardShortcutsView extends StatefulWidget {
|
||||
const KeyboardShortcutsView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<KeyboardShortcutsView> createState() => _KeyboardShortcutsViewState();
|
||||
}
|
||||
|
||||
class _KeyboardShortcutsViewState extends State<KeyboardShortcutsView> {
|
||||
static const double _desktopTabViewMaxWidth = 618;
|
||||
|
||||
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||
final _imagePaths = Get.find<ImagePaths>();
|
||||
final _categories = ShortcutCategory.values;
|
||||
|
||||
late final CustomTabBarController _tabBarController;
|
||||
late final PageController _pageController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabBarController = CustomTabBarController();
|
||||
_pageController = PageController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pageController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
final allShortcuts = KeyboardShortcutsManager.generateKeyboardShortcuts(
|
||||
appLocalizations,
|
||||
);
|
||||
final isDesktop = _responsiveUtils.isDesktop(context);
|
||||
double tabBarMaxHeight = isDesktop ? 52 : 82;
|
||||
|
||||
return SettingDetailViewBuilder(
|
||||
responsiveUtils: _responsiveUtils,
|
||||
child: Container(
|
||||
color: SettingsUtils.getContentBackgroundColor(
|
||||
context,
|
||||
_responsiveUtils,
|
||||
),
|
||||
decoration: SettingsUtils.getBoxDecorationForContent(
|
||||
context,
|
||||
_responsiveUtils,
|
||||
),
|
||||
width: double.infinity,
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.symmetric(vertical: 30, horizontal: 22)
|
||||
: null,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (_responsiveUtils.isWebDesktop(context))
|
||||
SettingHeaderWidget(
|
||||
menuItem: AccountMenuItem.keyboardShortcuts,
|
||||
textStyle: ThemeUtils.textStyleInter600().copyWith(
|
||||
color: Colors.black.withValues(alpha: 0.9),
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
)
|
||||
else
|
||||
const SettingExplanationWidget(
|
||||
menuItem: AccountMenuItem.keyboardShortcuts,
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
start: 16,
|
||||
end: 16,
|
||||
bottom: 16,
|
||||
),
|
||||
isCenter: true,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: SettingsUtils.getBodyPadding(
|
||||
context,
|
||||
_responsiveUtils,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxWidth = constraints.maxWidth;
|
||||
final countCategories = _categories.length;
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
CustomTabBar(
|
||||
tabBarController: _tabBarController,
|
||||
height: tabBarMaxHeight,
|
||||
width: isDesktop
|
||||
? _desktopTabViewMaxWidth
|
||||
: maxWidth,
|
||||
itemCount: countCategories,
|
||||
builder: (_, index) {
|
||||
final category = _categories[index];
|
||||
return ShortcutTabBarWidget(
|
||||
index: index,
|
||||
label: category.getDisplayName(
|
||||
appLocalizations,
|
||||
isDesktop: isDesktop,
|
||||
),
|
||||
icon: isDesktop
|
||||
? null
|
||||
: category.getIcon(_imagePaths),
|
||||
width: isDesktop
|
||||
? category.getTabWidth()
|
||||
: maxWidth / countCategories,
|
||||
height: tabBarMaxHeight,
|
||||
);
|
||||
},
|
||||
indicator: LinearIndicator(
|
||||
color: AppColor.primaryLinShare,
|
||||
height: 1,
|
||||
bottom: 0,
|
||||
),
|
||||
pageController: _pageController,
|
||||
),
|
||||
PositionedDirectional(
|
||||
bottom: 0,
|
||||
start: 0,
|
||||
end: 0,
|
||||
child: Divider(
|
||||
color: Colors.black.withValues(alpha: 0.12),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: isDesktop
|
||||
? _desktopTabViewMaxWidth
|
||||
: double.infinity,
|
||||
child: PageView.builder(
|
||||
controller: _pageController,
|
||||
itemCount: _categories.length,
|
||||
physics: PlatformInfo.isMobile
|
||||
? const PageScrollPhysics()
|
||||
: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (_, index) {
|
||||
final category = _categories[index];
|
||||
final shortcutsByCategory = allShortcuts
|
||||
.where((shortcut) => shortcut.category == category)
|
||||
.toList();
|
||||
return ShortcutCategoryList(
|
||||
shortcutsByCategory: shortcutsByCategory,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/keyboard_shortcuts/widgets/shortcut_row_widget.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/model/keyboard_shortcuts/keyboard_shortcut.dart';
|
||||
|
||||
class ShortcutCategoryList extends StatelessWidget {
|
||||
final List<KeyboardShortcut> shortcutsByCategory;
|
||||
|
||||
const ShortcutCategoryList({
|
||||
super.key,
|
||||
required this.shortcutsByCategory,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.only(top: 40),
|
||||
itemCount: shortcutsByCategory.length,
|
||||
itemBuilder: (_, index) {
|
||||
final item = shortcutsByCategory[index];
|
||||
return ShortcutRow(item: item);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ShortcutKeyWidget extends StatelessWidget {
|
||||
final String label;
|
||||
|
||||
const ShortcutKeyWidget({super.key, required this.label});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsetsDirectional.only(end: 4),
|
||||
padding: const EdgeInsets.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.blue100,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(2)),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: AppColor.gray200,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Colors.black.withValues(alpha: 0.88),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/extensions/keyboard_shortcut_extension.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/keyboard_shortcuts/widgets/shortcut_key_widget.dart';
|
||||
import 'package:tmail_ui_user/features/manage_account/presentation/model/keyboard_shortcuts/keyboard_shortcut.dart';
|
||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||
|
||||
class ShortcutRow extends StatelessWidget {
|
||||
final KeyboardShortcut item;
|
||||
|
||||
const ShortcutRow({super.key, required this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
top: 5,
|
||||
bottom: 21,
|
||||
),
|
||||
child: Wrap(
|
||||
spacing: 27,
|
||||
runSpacing: 8,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
item.label,
|
||||
style: ThemeUtils.textStyleBodyBody3(
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.context.getDisplayName(AppLocalizations.of(context)),
|
||||
style: ThemeUtils.textStyleBodyBody3(
|
||||
color: AppColor.gray424244.withValues(alpha: 0.64),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children:
|
||||
item.keys.map((key) => ShortcutKeyWidget(label: key)).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/theme_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_custom_tab_bar/library.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class ShortcutTabBarWidget extends StatelessWidget {
|
||||
final int index;
|
||||
final String label;
|
||||
final String? icon;
|
||||
final double? height;
|
||||
final double? width;
|
||||
|
||||
const ShortcutTabBarWidget({
|
||||
super.key,
|
||||
required this.index,
|
||||
required this.label,
|
||||
this.icon,
|
||||
this.height,
|
||||
this.width,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final labelWidget = Text(
|
||||
label,
|
||||
style: ThemeUtils.textStyleInter400.copyWith(
|
||||
fontSize: 14,
|
||||
height: 20 / 14,
|
||||
letterSpacing: 0.25,
|
||||
color: AppColor.gray424244,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
|
||||
return TabBarItem(
|
||||
index: index,
|
||||
transform: ColorsTransform(
|
||||
highlightColor: AppColor.gray424244,
|
||||
normalColor: AppColor.gray424244,
|
||||
builder: (context, _) {
|
||||
if (icon != null) {
|
||||
return Container(
|
||||
height: height,
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
icon!,
|
||||
width: 20,
|
||||
height: 20,
|
||||
colorFilter: AppColor.gray686E76.asFilter(),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
labelWidget,
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
height: height,
|
||||
width: width,
|
||||
alignment: Alignment.center,
|
||||
margin: EdgeInsets.zero,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: labelWidget,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user