mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: support system default font family on desktop (#5279)
* fix: add permission check before selecting image in image block * feat: use system default font on desktop * fix: set appbar icon size to 30 * feat: add default font family on desktop
This commit is contained in:
parent
b4279f8004
commit
6220680ce0
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/settings_appearance.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/settings_appearance.dart';
|
||||||
@ -82,8 +83,10 @@ void main() {
|
|||||||
await tester.openSettingsPage(SettingsPage.appearance);
|
await tester.openSettingsPage(SettingsPage.appearance);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
find.textContaining(DefaultAppearanceSettings.kDefaultFontFamily),
|
find.textContaining(
|
||||||
findsOneWidget,
|
DefaultAppearanceSettings.kDefaultFontFamily.fontFamilyDisplayName,
|
||||||
|
),
|
||||||
|
findsNWidgets(2),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
|
||||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_service.dart';
|
import 'package:appflowy/workspace/application/view/view_service.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
@ -179,8 +178,8 @@ class DocumentPageStyleBloc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getSelectedFontFamily(Map layoutObject) {
|
String? _getSelectedFontFamily(Map layoutObject) {
|
||||||
return layoutObject[ViewExtKeys.fontKey] ?? builtInFontFamily();
|
return layoutObject[ViewExtKeys.fontKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
(PageStyleCoverImageType, String colorValue) _getSelectedCover(
|
(PageStyleCoverImageType, String colorValue) _getSelectedCover(
|
||||||
|
@ -216,7 +216,11 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
child: AppBarButton(
|
child: AppBarButton(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
onTap: (context) => context.pop(),
|
onTap: (context) => context.pop(),
|
||||||
child: _buildImmersiveAppBarIcon(FlowySvgs.m_app_bar_back_s),
|
child: _buildImmersiveAppBarIcon(
|
||||||
|
FlowySvgs.m_app_bar_back_s,
|
||||||
|
30.0,
|
||||||
|
iconPadding: 6.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: actions,
|
actions: actions,
|
||||||
@ -274,13 +278,13 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: _buildImmersiveAppBarIcon(FlowySvgs.m_layout_s),
|
child: _buildImmersiveAppBarIcon(FlowySvgs.m_layout_s, 30.0),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAppBarMoreButton(ViewPB view) {
|
Widget _buildAppBarMoreButton(ViewPB view) {
|
||||||
return AppBarButton(
|
return AppBarButton(
|
||||||
padding: const EdgeInsets.only(left: 8, right: 16, top: 2, bottom: 2),
|
padding: const EdgeInsets.only(left: 8, right: 16),
|
||||||
onTap: (context) {
|
onTap: (context) {
|
||||||
EditorNotification.exitEditing().post();
|
EditorNotification.exitEditing().post();
|
||||||
|
|
||||||
@ -292,12 +296,23 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
builder: (_) => _buildAppBarMoreBottomSheet(context),
|
builder: (_) => _buildAppBarMoreBottomSheet(context),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: _buildImmersiveAppBarIcon(FlowySvgs.m_app_bar_more_s),
|
child: _buildImmersiveAppBarIcon(FlowySvgs.m_app_bar_more_s, 30.0),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildImmersiveAppBarIcon(FlowySvgData icon) {
|
Widget _buildImmersiveAppBarIcon(
|
||||||
return ValueListenableBuilder(
|
FlowySvgData icon,
|
||||||
|
double dimension, {
|
||||||
|
double iconPadding = 5.0,
|
||||||
|
}) {
|
||||||
|
assert(
|
||||||
|
dimension > 0.0 && dimension <= kToolbarHeight,
|
||||||
|
'dimension must be greater than 0, and less than or equal to kToolbarHeight',
|
||||||
|
);
|
||||||
|
return UnconstrainedBox(
|
||||||
|
child: SizedBox.square(
|
||||||
|
dimension: dimension,
|
||||||
|
child: ValueListenableBuilder(
|
||||||
valueListenable: _isImmersiveMode,
|
valueListenable: _isImmersiveMode,
|
||||||
builder: (context, isImmersiveMode, child) {
|
builder: (context, isImmersiveMode, child) {
|
||||||
return ValueListenableBuilder(
|
return ValueListenableBuilder(
|
||||||
@ -314,7 +329,7 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget child = Container(
|
Widget child = Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
margin: EdgeInsets.all(iconPadding),
|
||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
icon,
|
icon,
|
||||||
color: color,
|
color: color,
|
||||||
@ -324,7 +339,7 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
if (isImmersiveMode && appBarOpacity <= 0.99) {
|
if (isImmersiveMode && appBarOpacity <= 0.99) {
|
||||||
child = DecoratedBox(
|
child = DecoratedBox(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(22),
|
borderRadius: BorderRadius.circular(dimension / 2.0),
|
||||||
color: Colors.black.withOpacity(0.2),
|
color: Colors.black.withOpacity(0.2),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
@ -335,6 +350,8 @@ class _MobileViewPageState extends State<MobileViewPage> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import 'package:appflowy/mobile/presentation/base/app_bar/app_bar.dart';
|
|||||||
import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_search_text_field.dart';
|
import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_search_text_field.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||||
import 'package:appflowy/shared/google_fonts_extension.dart';
|
import 'package:appflowy/shared/google_fonts_extension.dart';
|
||||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -13,7 +13,7 @@ import 'package:go_router/go_router.dart';
|
|||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
final List<String> _availableFonts = [
|
final List<String> _availableFonts = [
|
||||||
builtInFontFamily(),
|
defaultFontFamily,
|
||||||
...GoogleFonts.asMap().keys,
|
...GoogleFonts.asMap().keys,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -106,16 +106,12 @@ class _FontSelectorState extends State<FontSelector> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final fontFamilyName = availableFonts[index - 1];
|
final fontFamilyName = availableFonts[index - 1];
|
||||||
final usingDefaultFontFamily = fontFamilyName == builtInFontFamily();
|
final usingDefaultFontFamily = fontFamilyName == defaultFontFamily;
|
||||||
final fontFamily = !usingDefaultFontFamily
|
final fontFamily = !usingDefaultFontFamily
|
||||||
? getGoogleFontSafely(fontFamilyName).fontFamily
|
? getGoogleFontSafely(fontFamilyName).fontFamily
|
||||||
: TextStyle(fontFamily: builtInFontFamily()).fontFamily;
|
: defaultFontFamily;
|
||||||
return FlowyOptionTile.checkbox(
|
return FlowyOptionTile.checkbox(
|
||||||
// display the default font name if the font family name is empty
|
text: fontFamilyName.fontFamilyDisplayName,
|
||||||
// or using the default font family
|
|
||||||
text: fontFamilyName.isNotEmpty && !usingDefaultFontFamily
|
|
||||||
? fontFamilyName.parseFontFamilyName()
|
|
||||||
: LocaleKeys.settings_appearance_fontFamily_defaultFont.tr(),
|
|
||||||
isSelected: widget.selectedFontFamilyName == fontFamilyName,
|
isSelected: widget.selectedFontFamilyName == fontFamilyName,
|
||||||
showTopBorder: false,
|
showTopBorder: false,
|
||||||
onTap: () => widget.onFontFamilySelected(fontFamilyName),
|
onTap: () => widget.onFontFamilySelected(fontFamilyName),
|
||||||
|
@ -3,8 +3,8 @@ import 'dart:async';
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -22,9 +22,7 @@ class FontSetting extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final selectedFont = context.watch<AppearanceSettingsCubit>().state.font;
|
final selectedFont = context.watch<AppearanceSettingsCubit>().state.font;
|
||||||
final name = selectedFont == builtInFontFamily()
|
final name = selectedFont.fontFamilyDisplayName;
|
||||||
? LocaleKeys.settings_appearance_fontFamily_defaultFont.tr()
|
|
||||||
: selectedFont;
|
|
||||||
return MobileSettingItem(
|
return MobileSettingItem(
|
||||||
name: LocaleKeys.settings_appearance_fontFamily_label.tr(),
|
name: LocaleKeys.settings_appearance_fontFamily_label.tr(),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
|
@ -57,9 +57,9 @@ class DocumentAppearance {
|
|||||||
class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
|
class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
|
||||||
DocumentAppearanceCubit()
|
DocumentAppearanceCubit()
|
||||||
: super(
|
: super(
|
||||||
DocumentAppearance(
|
const DocumentAppearance(
|
||||||
fontSize: 16.0,
|
fontSize: 16.0,
|
||||||
fontFamily: builtInFontFamily(),
|
fontFamily: defaultFontFamily,
|
||||||
codeFontFamily: builtInCodeFontFamily,
|
codeFontFamily: builtInCodeFontFamily,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -69,7 +69,7 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
|
|||||||
final fontSize =
|
final fontSize =
|
||||||
prefs.getDouble(KVKeys.kDocumentAppearanceFontSize) ?? 16.0;
|
prefs.getDouble(KVKeys.kDocumentAppearanceFontSize) ?? 16.0;
|
||||||
final fontFamily = prefs.getString(KVKeys.kDocumentAppearanceFontFamily) ??
|
final fontFamily = prefs.getString(KVKeys.kDocumentAppearanceFontFamily) ??
|
||||||
builtInFontFamily();
|
defaultFontFamily;
|
||||||
final defaultTextDirection =
|
final defaultTextDirection =
|
||||||
prefs.getString(KVKeys.kDocumentAppearanceDefaultTextDirection);
|
prefs.getString(KVKeys.kDocumentAppearanceDefaultTextDirection);
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ class _DocumentImmersiveCoverState extends State<DocumentImmersiveCover> {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
DocumentImmersiveCoverState state,
|
DocumentImmersiveCoverState state,
|
||||||
) {
|
) {
|
||||||
String? fontFamily = builtInFontFamily();
|
String? fontFamily = defaultFontFamily;
|
||||||
final documentFontFamily =
|
final documentFontFamily =
|
||||||
context.read<DocumentPageStyleBloc>().state.fontFamily;
|
context.read<DocumentPageStyleBloc>().state.fontFamily;
|
||||||
if (documentFontFamily != null && fontFamily != documentFontFamily) {
|
if (documentFontFamily != null && fontFamily != documentFontFamily) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/shared/permission/permission_checker.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
import 'package:flowy_infra/file_picker/file_picker_service.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
@ -20,8 +22,7 @@ class UploadImageFileWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyHover(
|
final child = FlowyButton(
|
||||||
child: FlowyButton(
|
|
||||||
showDefaultBoxDecorationOnMobile: true,
|
showDefaultBoxDecorationOnMobile: true,
|
||||||
text: Container(
|
text: Container(
|
||||||
margin: const EdgeInsets.all(4.0),
|
margin: const EdgeInsets.all(4.0),
|
||||||
@ -30,12 +31,19 @@ class UploadImageFileWidget extends StatelessWidget {
|
|||||||
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
|
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: _uploadImage,
|
onTap: () => _uploadImage(context),
|
||||||
),
|
);
|
||||||
|
|
||||||
|
if (PlatformExtension.isDesktopOrWeb) {
|
||||||
|
return FlowyHover(
|
||||||
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _uploadImage() async {
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _uploadImage(BuildContext context) async {
|
||||||
if (PlatformExtension.isDesktopOrWeb) {
|
if (PlatformExtension.isDesktopOrWeb) {
|
||||||
// on desktop, the users can pick a image file from folder
|
// on desktop, the users can pick a image file from folder
|
||||||
final result = await getIt<FilePickerService>().pickFiles(
|
final result = await getIt<FilePickerService>().pickFiles(
|
||||||
@ -45,6 +53,12 @@ class UploadImageFileWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
onPickFile(result?.files.firstOrNull?.path);
|
onPickFile(result?.files.firstOrNull?.path);
|
||||||
} else {
|
} else {
|
||||||
|
final photoPermission =
|
||||||
|
await PermissionChecker.checkPhotoPermission(context);
|
||||||
|
if (!photoPermission) {
|
||||||
|
Log.error('Has no permission to access the photo library');
|
||||||
|
return;
|
||||||
|
}
|
||||||
// on mobile, the users can pick a image file from camera or image library
|
// on mobile, the users can pick a image file from camera or image library
|
||||||
final result = await ImagePicker().pickImage(source: ImageSource.gallery);
|
final result = await ImagePicker().pickImage(source: ImageSource.gallery);
|
||||||
onPickFile(result?.path);
|
onPickFile(result?.path);
|
||||||
|
@ -5,7 +5,7 @@ import 'package:appflowy/plugins/document/application/document_appearance_cubit.
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_menu/_toolbar_theme.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_menu/_toolbar_theme.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
import 'package:appflowy/shared/google_fonts_extension.dart';
|
import 'package:appflowy/shared/google_fonts_extension.dart';
|
||||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
@ -4,13 +4,12 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/show_flowy_mobile_confirm_dialog.dart';
|
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_cover_bottom_sheet.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_cover_bottom_sheet.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_style_util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_style_util.dart';
|
||||||
import 'package:appflowy/shared/feedback_gesture_detector.dart';
|
import 'package:appflowy/shared/feedback_gesture_detector.dart';
|
||||||
import 'package:appflowy/startup/tasks/device_info_task.dart';
|
import 'package:appflowy/shared/permission/permission_checker.dart';
|
||||||
import 'package:appflowy/user/application/user_service.dart';
|
import 'package:appflowy/user/application/user_service.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
@ -18,11 +17,9 @@ import 'package:appflowy_result/appflowy_result.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
|
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
|
|
||||||
class PageStyleCoverImage extends StatelessWidget {
|
class PageStyleCoverImage extends StatelessWidget {
|
||||||
PageStyleCoverImage({
|
PageStyleCoverImage({
|
||||||
@ -121,7 +118,8 @@ class PageStyleCoverImage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _pickImage(BuildContext context) async {
|
Future<void> _pickImage(BuildContext context) async {
|
||||||
final photoPermission = await _checkPhotoPermission(context);
|
final photoPermission =
|
||||||
|
await PermissionChecker.checkPhotoPermission(context);
|
||||||
if (!photoPermission) {
|
if (!photoPermission) {
|
||||||
Log.error('Has no permission to access the photo library');
|
Log.error('Has no permission to access the photo library');
|
||||||
return;
|
return;
|
||||||
@ -129,9 +127,7 @@ class PageStyleCoverImage extends StatelessWidget {
|
|||||||
|
|
||||||
XFile? result;
|
XFile? result;
|
||||||
try {
|
try {
|
||||||
result = await _imagePicker.pickImage(
|
result = await _imagePicker.pickImage(source: ImageSource.gallery);
|
||||||
source: ImageSource.gallery,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('Error while picking image: $e');
|
Log.error('Error while picking image: $e');
|
||||||
return;
|
return;
|
||||||
@ -224,54 +220,6 @@ class PageStyleCoverImage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _checkPhotoPermission(BuildContext context) async {
|
|
||||||
// check the permission first
|
|
||||||
final status = await Permission.photos.status;
|
|
||||||
// if the permission is permanently denied, we should open the app settings
|
|
||||||
if (status.isPermanentlyDenied && context.mounted) {
|
|
||||||
unawaited(
|
|
||||||
showFlowyMobileConfirmDialog(
|
|
||||||
context,
|
|
||||||
title: FlowyText.semibold(
|
|
||||||
LocaleKeys.pageStyle_photoPermissionTitle.tr(),
|
|
||||||
maxLines: 3,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
content: FlowyText(
|
|
||||||
LocaleKeys.pageStyle_photoPermissionDescription.tr(),
|
|
||||||
maxLines: 5,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
fontSize: 12.0,
|
|
||||||
),
|
|
||||||
actionAlignment: ConfirmDialogActionAlignment.vertical,
|
|
||||||
actionButtonTitle: LocaleKeys.pageStyle_openSettings.tr(),
|
|
||||||
actionButtonColor: Colors.blue,
|
|
||||||
cancelButtonTitle: LocaleKeys.pageStyle_doNotAllow.tr(),
|
|
||||||
cancelButtonColor: Colors.blue,
|
|
||||||
onActionButtonPressed: () {
|
|
||||||
openAppSettings();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} else if (status.isDenied) {
|
|
||||||
// https://github.com/Baseflow/flutter-permission-handler/issues/1262#issuecomment-2006340937
|
|
||||||
Permission permission = Permission.photos;
|
|
||||||
if (defaultTargetPlatform == TargetPlatform.android &&
|
|
||||||
ApplicationInfo.androidSDKVersion <= 32) {
|
|
||||||
permission = Permission.storage;
|
|
||||||
}
|
|
||||||
// if the permission is denied, we should request the permission
|
|
||||||
final newStatus = await permission.request();
|
|
||||||
if (newStatus.isDenied) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UnsplashCover extends StatelessWidget {
|
class _UnsplashCover extends StatelessWidget {
|
||||||
|
@ -5,6 +5,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_she
|
|||||||
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_style_util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/page_style/_page_style_util.dart';
|
||||||
import 'package:appflowy/shared/feedback_gesture_detector.dart';
|
import 'package:appflowy/shared/feedback_gesture_detector.dart';
|
||||||
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
@ -163,11 +164,8 @@ class _FontButton extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<DocumentPageStyleBloc, DocumentPageStyleState>(
|
return BlocBuilder<DocumentPageStyleBloc, DocumentPageStyleState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
String fontFamily = state.fontFamily ?? builtInFontFamily();
|
final fontFamilyDisplayName =
|
||||||
if (fontFamily == builtInFontFamily()) {
|
(state.fontFamily ?? defaultFontFamily).fontFamilyDisplayName;
|
||||||
fontFamily =
|
|
||||||
LocaleKeys.settings_appearance_fontFamily_defaultFont.tr();
|
|
||||||
}
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => _showFontSelector(context),
|
onTap: () => _showFontSelector(context),
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
@ -182,7 +180,7 @@ class _FontButton extends StatelessWidget {
|
|||||||
const HSpace(16.0),
|
const HSpace(16.0),
|
||||||
FlowyText(LocaleKeys.titleBar_font.tr()),
|
FlowyText(LocaleKeys.titleBar_font.tr()),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
FlowyText(fontFamily),
|
FlowyText(fontFamilyDisplayName),
|
||||||
const HSpace(6.0),
|
const HSpace(6.0),
|
||||||
const FlowySvg(FlowySvgs.m_page_style_arrow_right_s),
|
const FlowySvg(FlowySvgs.m_page_style_arrow_right_s),
|
||||||
const HSpace(12.0),
|
const HSpace(12.0),
|
||||||
@ -219,7 +217,7 @@ class _FontButton extends StatelessWidget {
|
|||||||
child: FontSelector(
|
child: FontSelector(
|
||||||
scrollController: controller,
|
scrollController: controller,
|
||||||
selectedFontFamilyName:
|
selectedFontFamilyName:
|
||||||
state.fontFamily ?? builtInFontFamily(),
|
state.fontFamily ?? defaultFontFamily,
|
||||||
onFontFamilySelected: (fontFamilyName) {
|
onFontFamilySelected: (fontFamilyName) {
|
||||||
context.read<DocumentPageStyleBloc>().add(
|
context.read<DocumentPageStyleBloc>().add(
|
||||||
DocumentPageStyleEvent.updateFontFamily(
|
DocumentPageStyleEvent.updateFontFamily(
|
||||||
|
@ -8,7 +8,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_too
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
|
import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
|
||||||
import 'package:appflowy/shared/google_fonts_extension.dart';
|
import 'package:appflowy/shared/google_fonts_extension.dart';
|
||||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
@ -92,7 +92,7 @@ class EditorStyleCustomizer {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final fontSize = pageStyle.fontLayout.fontSize;
|
final fontSize = pageStyle.fontLayout.fontSize;
|
||||||
final lineHeight = pageStyle.lineHeightLayout.lineHeight;
|
final lineHeight = pageStyle.lineHeightLayout.lineHeight;
|
||||||
final fontFamily = pageStyle.fontFamily ?? builtInFontFamily();
|
final fontFamily = pageStyle.fontFamily ?? defaultFontFamily;
|
||||||
final defaultTextDirection =
|
final defaultTextDirection =
|
||||||
context.read<DocumentAppearanceCubit>().state.defaultTextDirection;
|
context.read<DocumentAppearanceCubit>().state.defaultTextDirection;
|
||||||
final baseTextStyle = this.baseTextStyle(fontFamily);
|
final baseTextStyle = this.baseTextStyle(fontFamily);
|
||||||
@ -178,7 +178,7 @@ class EditorStyleCustomizer {
|
|||||||
TextStyle outlineBlockPlaceholderStyleBuilder() {
|
TextStyle outlineBlockPlaceholderStyleBuilder() {
|
||||||
final fontSize = context.read<DocumentAppearanceCubit>().state.fontSize;
|
final fontSize = context.read<DocumentAppearanceCubit>().state.fontSize;
|
||||||
return TextStyle(
|
return TextStyle(
|
||||||
fontFamily: builtInFontFamily(),
|
fontFamily: defaultFontFamily,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
height: 1.5,
|
height: 1.5,
|
||||||
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.6),
|
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.6),
|
||||||
@ -219,7 +219,8 @@ class EditorStyleCustomizer {
|
|||||||
try {
|
try {
|
||||||
return getGoogleFontSafely(fontFamily, fontWeight: fontWeight);
|
return getGoogleFontSafely(fontFamily, fontWeight: fontWeight);
|
||||||
} on Exception {
|
} on Exception {
|
||||||
if ([builtInFontFamily(), builtInCodeFontFamily].contains(fontFamily)) {
|
if ([defaultFontFamily, fallbackFontFamily, builtInCodeFontFamily]
|
||||||
|
.contains(fontFamily)) {
|
||||||
return TextStyle(fontFamily: fontFamily, fontWeight: fontWeight);
|
return TextStyle(fontFamily: fontFamily, fontWeight: fontWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
// Check if the user has the required permission to access the device's
|
||||||
|
// - camera
|
||||||
|
// - storage
|
||||||
|
// - ...
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/mobile/presentation/widgets/show_flowy_mobile_confirm_dialog.dart';
|
||||||
|
import 'package:appflowy/startup/tasks/device_info_task.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
class PermissionChecker {
|
||||||
|
static Future<bool> checkPhotoPermission(BuildContext context) async {
|
||||||
|
// check the permission first
|
||||||
|
final status = await Permission.photos.status;
|
||||||
|
// if the permission is permanently denied, we should open the app settings
|
||||||
|
if (status.isPermanentlyDenied && context.mounted) {
|
||||||
|
unawaited(
|
||||||
|
showFlowyMobileConfirmDialog(
|
||||||
|
context,
|
||||||
|
title: FlowyText.semibold(
|
||||||
|
LocaleKeys.pageStyle_photoPermissionTitle.tr(),
|
||||||
|
maxLines: 3,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
content: FlowyText(
|
||||||
|
LocaleKeys.pageStyle_photoPermissionDescription.tr(),
|
||||||
|
maxLines: 5,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
fontSize: 12.0,
|
||||||
|
),
|
||||||
|
actionAlignment: ConfirmDialogActionAlignment.vertical,
|
||||||
|
actionButtonTitle: LocaleKeys.pageStyle_openSettings.tr(),
|
||||||
|
actionButtonColor: Colors.blue,
|
||||||
|
cancelButtonTitle: LocaleKeys.pageStyle_doNotAllow.tr(),
|
||||||
|
cancelButtonColor: Colors.blue,
|
||||||
|
onActionButtonPressed: () {
|
||||||
|
openAppSettings();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (status.isDenied) {
|
||||||
|
// https://github.com/Baseflow/flutter-permission-handler/issues/1262#issuecomment-2006340937
|
||||||
|
Permission permission = Permission.photos;
|
||||||
|
if (defaultTargetPlatform == TargetPlatform.android &&
|
||||||
|
ApplicationInfo.androidSDKVersion <= 32) {
|
||||||
|
permission = Permission.storage;
|
||||||
|
}
|
||||||
|
// if the permission is denied, we should request the permission
|
||||||
|
final newStatus = await permission.request();
|
||||||
|
if (newStatus.isDenied) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/shared/patterns/common_patterns.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
extension FontFamilyExtension on String {
|
||||||
|
String parseFontFamilyName() => replaceAll('_regular', '')
|
||||||
|
.replaceAllMapped(camelCaseRegex, (m) => ' ${m.group(0)}');
|
||||||
|
|
||||||
|
// display the default font name if the font family name is empty
|
||||||
|
// or using the default font family
|
||||||
|
String get fontFamilyDisplayName => isEmpty || this == defaultFontFamily
|
||||||
|
? LocaleKeys.settings_appearance_fontFamily_defaultFont.tr()
|
||||||
|
: parseFontFamilyName();
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
import 'package:appflowy/shared/patterns/common_patterns.dart';
|
|
||||||
|
|
||||||
extension GoogleFontsParser on String {
|
|
||||||
String parseFontFamilyName() => replaceAll('_regular', '')
|
|
||||||
.replaceAllMapped(camelCaseRegex, (m) => ' ${m.group(0)}');
|
|
||||||
}
|
|
@ -1,9 +1,10 @@
|
|||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// A class for the default appearance settings for the app
|
/// A class for the default appearance settings for the app
|
||||||
class DefaultAppearanceSettings {
|
class DefaultAppearanceSettings {
|
||||||
static const kDefaultFontFamily = 'Poppins';
|
static const kDefaultFontFamily = defaultFontFamily;
|
||||||
static const kDefaultThemeMode = ThemeMode.system;
|
static const kDefaultThemeMode = ThemeMode.system;
|
||||||
static const kDefaultThemeName = "Default";
|
static const kDefaultThemeName = "Default";
|
||||||
static const kDefaultTheme = BuiltInTheme.defaultTheme;
|
static const kDefaultTheme = BuiltInTheme.defaultTheme;
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:appflowy/shared/google_fonts_extension.dart';
|
import 'package:appflowy/shared/google_fonts_extension.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
String builtInFontFamily() {
|
// the default font family is empty, so we can use the default font family of the platform
|
||||||
if (PlatformExtension.isDesktopOrWeb) {
|
// the system will choose the default font family of the platform
|
||||||
return 'Poppins';
|
// iOS: San Francisco
|
||||||
}
|
// Android: Roboto
|
||||||
|
// Desktop: Based on the OS
|
||||||
|
const defaultFontFamily = '';
|
||||||
|
|
||||||
if (Platform.isIOS) {
|
// the Poppins font is embedded in the app, so we can use it without GoogleFonts
|
||||||
return 'San Francisco';
|
// TODO(Lucas): after releasing version 0.5.6, remove it.
|
||||||
}
|
const fallbackFontFamily = 'Poppins';
|
||||||
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
return 'Roboto';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'Roboto';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'Poppins';
|
|
||||||
const builtInCodeFontFamily = 'RobotoMono';
|
const builtInCodeFontFamily = 'RobotoMono';
|
||||||
|
|
||||||
abstract class BaseAppearance {
|
abstract class BaseAppearance {
|
||||||
@ -48,17 +39,15 @@ abstract class BaseAppearance {
|
|||||||
letterSpacing = fontSize * (letterSpacing ?? 0.005);
|
letterSpacing = fontSize * (letterSpacing ?? 0.005);
|
||||||
|
|
||||||
final textStyle = TextStyle(
|
final textStyle = TextStyle(
|
||||||
fontFamily: fontFamily,
|
fontFamily: fontFamily.isEmpty ? null : fontFamily,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
fontWeight: fontWeight,
|
fontWeight: fontWeight,
|
||||||
fontFamilyFallback: [builtInFontFamily()],
|
|
||||||
letterSpacing: letterSpacing,
|
letterSpacing: letterSpacing,
|
||||||
height: lineHeight,
|
height: lineHeight,
|
||||||
);
|
);
|
||||||
|
|
||||||
// we embed Poppins font in the app, so we can use it without GoogleFonts
|
if (fontFamily == defaultFontFamily || fontFamily == fallbackFontFamily) {
|
||||||
if (fontFamily == builtInFontFamily()) {
|
|
||||||
return textStyle;
|
return textStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DesktopAppearance extends BaseAppearance {
|
class DesktopAppearance extends BaseAppearance {
|
||||||
@override
|
@override
|
||||||
@ -13,7 +12,6 @@ class DesktopAppearance extends BaseAppearance {
|
|||||||
String fontFamily,
|
String fontFamily,
|
||||||
String codeFontFamily,
|
String codeFontFamily,
|
||||||
) {
|
) {
|
||||||
assert(fontFamily.isNotEmpty);
|
|
||||||
assert(codeFontFamily.isNotEmpty);
|
assert(codeFontFamily.isNotEmpty);
|
||||||
|
|
||||||
final theme = brightness == Brightness.light
|
final theme = brightness == Brightness.light
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy/shared/google_fonts_extension.dart';
|
import 'package:appflowy/shared/google_fonts_extension.dart';
|
||||||
import 'package:appflowy/util/google_font_family_extension.dart';
|
import 'package:appflowy/util/font_family_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
@ -83,7 +83,10 @@ class FontFamilyDropDown extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
||||||
final List<String> availableFonts = GoogleFonts.asMap().keys.toList();
|
final List<String> availableFonts = [
|
||||||
|
defaultFontFamily,
|
||||||
|
...GoogleFonts.asMap().keys,
|
||||||
|
];
|
||||||
final ValueNotifier<String> query = ValueNotifier('');
|
final ValueNotifier<String> query = ValueNotifier('');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -94,10 +97,11 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final currentValue = widget.currentFontFamily.fontFamilyDisplayName;
|
||||||
return FlowySettingValueDropDown(
|
return FlowySettingValueDropDown(
|
||||||
popoverKey: ThemeFontFamilySetting.popoverKey,
|
popoverKey: ThemeFontFamilySetting.popoverKey,
|
||||||
popoverController: widget.popoverController,
|
popoverController: widget.popoverController,
|
||||||
currentValue: widget.currentFontFamily.parseFontFamilyName(),
|
currentValue: currentValue,
|
||||||
onClose: () {
|
onClose: () {
|
||||||
query.value = '';
|
query.value = '';
|
||||||
widget.onClose?.call();
|
widget.onClose?.call();
|
||||||
@ -168,8 +172,8 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
TextStyle style,
|
TextStyle style,
|
||||||
) {
|
) {
|
||||||
final buttonFontFamily = style.fontFamily!.parseFontFamilyName();
|
final buttonFontFamily =
|
||||||
|
style.fontFamily?.parseFontFamilyName() ?? defaultFontFamily;
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: buttonFontFamily,
|
message: buttonFontFamily,
|
||||||
waitDuration: const Duration(milliseconds: 150),
|
waitDuration: const Duration(milliseconds: 150),
|
||||||
@ -179,8 +183,8 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
onHover: (_) => FocusScope.of(context).unfocus(),
|
onHover: (_) => FocusScope.of(context).unfocus(),
|
||||||
text: FlowyText.medium(
|
text: FlowyText.medium(
|
||||||
buttonFontFamily,
|
buttonFontFamily.fontFamilyDisplayName,
|
||||||
fontFamily: style.fontFamily!,
|
fontFamily: buttonFontFamily,
|
||||||
),
|
),
|
||||||
rightIcon:
|
rightIcon:
|
||||||
buttonFontFamily == widget.currentFontFamily.parseFontFamilyName()
|
buttonFontFamily == widget.currentFontFamily.parseFontFamilyName()
|
||||||
@ -190,15 +194,14 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
if (widget.onFontFamilyChanged != null) {
|
if (widget.onFontFamilyChanged != null) {
|
||||||
widget.onFontFamilyChanged!(buttonFontFamily);
|
widget.onFontFamilyChanged!(buttonFontFamily);
|
||||||
} else {
|
} else {
|
||||||
final fontFamily = style.fontFamily!.parseFontFamilyName();
|
|
||||||
if (widget.currentFontFamily.parseFontFamilyName() !=
|
if (widget.currentFontFamily.parseFontFamilyName() !=
|
||||||
buttonFontFamily) {
|
buttonFontFamily) {
|
||||||
context
|
context
|
||||||
.read<AppearanceSettingsCubit>()
|
.read<AppearanceSettingsCubit>()
|
||||||
.setFontFamily(fontFamily);
|
.setFontFamily(buttonFontFamily);
|
||||||
context
|
context
|
||||||
.read<DocumentAppearanceCubit>()
|
.read<DocumentAppearanceCubit>()
|
||||||
.syncFontFamily(fontFamily);
|
.syncFontFamily(buttonFontFamily);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PopoverContainer.of(context).close();
|
PopoverContainer.of(context).close();
|
||||||
|
@ -36,7 +36,7 @@ void main() {
|
|||||||
AppTheme.fallback,
|
AppTheme.fallback,
|
||||||
),
|
),
|
||||||
verify: (bloc) {
|
verify: (bloc) {
|
||||||
expect(bloc.state.font, builtInFontFamily());
|
expect(bloc.state.font, defaultFontFamily);
|
||||||
expect(bloc.state.monospaceFont, 'SF Mono');
|
expect(bloc.state.monospaceFont, 'SF Mono');
|
||||||
expect(bloc.state.themeMode, ThemeMode.system);
|
expect(bloc.state.themeMode, ThemeMode.system);
|
||||||
},
|
},
|
||||||
|
@ -27,7 +27,7 @@ void main() {
|
|||||||
|
|
||||||
test('Initial state', () {
|
test('Initial state', () {
|
||||||
expect(cubit.state.fontSize, 16.0);
|
expect(cubit.state.fontSize, 16.0);
|
||||||
expect(cubit.state.fontFamily, builtInFontFamily());
|
expect(cubit.state.fontFamily, defaultFontFamily);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fetch document appearance from SharedPreferences', () async {
|
test('Fetch document appearance from SharedPreferences', () async {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/font_family_setting.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/font_family_setting.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -56,9 +58,9 @@ void main() {
|
|||||||
value: documentAppearanceCubit,
|
value: documentAppearanceCubit,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Scaffold(
|
child: const Scaffold(
|
||||||
body: ThemeFontFamilySetting(
|
body: ThemeFontFamilySetting(
|
||||||
currentFontFamily: builtInFontFamily(),
|
currentFontFamily: defaultFontFamily,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -71,7 +73,10 @@ void main() {
|
|||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// Verify the initial font family
|
// Verify the initial font family
|
||||||
expect(find.text(builtInFontFamily()), findsAtLeastNWidgets(1));
|
expect(
|
||||||
|
find.text(LocaleKeys.settings_appearance_fontFamily_defaultFont.tr()),
|
||||||
|
findsAtLeastNWidgets(1),
|
||||||
|
);
|
||||||
when(() => appearanceSettingsCubit.setFontFamily(any<String>()))
|
when(() => appearanceSettingsCubit.setFontFamily(any<String>()))
|
||||||
.thenAnswer((_) async {});
|
.thenAnswer((_) async {});
|
||||||
verifyNever(() => appearanceSettingsCubit.setFontFamily(any<String>()));
|
verifyNever(() => appearanceSettingsCubit.setFontFamily(any<String>()));
|
||||||
|
@ -128,7 +128,7 @@ pub struct DocumentSettingsPB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const APPEARANCE_DEFAULT_THEME: &str = "Default";
|
pub const APPEARANCE_DEFAULT_THEME: &str = "Default";
|
||||||
pub const APPEARANCE_DEFAULT_FONT: &str = "Poppins";
|
pub const APPEARANCE_DEFAULT_FONT: &str = ""; // Use system default font
|
||||||
pub const APPEARANCE_DEFAULT_MONOSPACE_FONT: &str = "SF Mono";
|
pub const APPEARANCE_DEFAULT_MONOSPACE_FONT: &str = "SF Mono";
|
||||||
const APPEARANCE_RESET_AS_DEFAULT: bool = true;
|
const APPEARANCE_RESET_AS_DEFAULT: bool = true;
|
||||||
const APPEARANCE_DEFAULT_IS_MENU_COLLAPSED: bool = false;
|
const APPEARANCE_DEFAULT_IS_MENU_COLLAPSED: bool = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user