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:
Lucas.Xu
2024-05-07 19:44:00 +08:00
committed by GitHub
parent b4279f8004
commit 6220680ce0
23 changed files with 234 additions and 191 deletions

View File

@ -57,9 +57,9 @@ class DocumentAppearance {
class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
DocumentAppearanceCubit()
: super(
DocumentAppearance(
const DocumentAppearance(
fontSize: 16.0,
fontFamily: builtInFontFamily(),
fontFamily: defaultFontFamily,
codeFontFamily: builtInCodeFontFamily,
),
);
@ -69,7 +69,7 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
final fontSize =
prefs.getDouble(KVKeys.kDocumentAppearanceFontSize) ?? 16.0;
final fontFamily = prefs.getString(KVKeys.kDocumentAppearanceFontFamily) ??
builtInFontFamily();
defaultFontFamily;
final defaultTextDirection =
prefs.getString(KVKeys.kDocumentAppearanceDefaultTextDirection);

View File

@ -127,7 +127,7 @@ class _DocumentImmersiveCoverState extends State<DocumentImmersiveCover> {
BuildContext context,
DocumentImmersiveCoverState state,
) {
String? fontFamily = builtInFontFamily();
String? fontFamily = defaultFontFamily;
final documentFontFamily =
context.read<DocumentPageStyleBloc>().state.fontFamily;
if (documentFontFamily != null && fontFamily != documentFontFamily) {

View File

@ -1,6 +1,8 @@
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_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:flowy_infra/file_picker/file_picker_service.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -20,22 +22,28 @@ class UploadImageFileWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FlowyHover(
child: FlowyButton(
showDefaultBoxDecorationOnMobile: true,
text: Container(
margin: const EdgeInsets.all(4.0),
alignment: Alignment.center,
child: FlowyText(
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
),
final child = FlowyButton(
showDefaultBoxDecorationOnMobile: true,
text: Container(
margin: const EdgeInsets.all(4.0),
alignment: Alignment.center,
child: FlowyText(
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
),
onTap: _uploadImage,
),
onTap: () => _uploadImage(context),
);
if (PlatformExtension.isDesktopOrWeb) {
return FlowyHover(
child: child,
);
}
return child;
}
Future<void> _uploadImage() async {
Future<void> _uploadImage(BuildContext context) async {
if (PlatformExtension.isDesktopOrWeb) {
// on desktop, the users can pick a image file from folder
final result = await getIt<FilePickerService>().pickFiles(
@ -45,6 +53,12 @@ class UploadImageFileWidget extends StatelessWidget {
);
onPickFile(result?.files.firstOrNull?.path);
} 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
final result = await ImagePicker().pickImage(source: ImageSource.gallery);
onPickFile(result?.path);

View File

@ -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/plugins.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:flutter/material.dart';
import 'package:go_router/go_router.dart';

View File

@ -4,13 +4,12 @@ import 'package:appflowy/generated/flowy_svgs.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/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/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_style_util.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_backend/log.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:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
class PageStyleCoverImage extends StatelessWidget {
PageStyleCoverImage({
@ -121,7 +118,8 @@ class PageStyleCoverImage extends StatelessWidget {
}
Future<void> _pickImage(BuildContext context) async {
final photoPermission = await _checkPhotoPermission(context);
final photoPermission =
await PermissionChecker.checkPhotoPermission(context);
if (!photoPermission) {
Log.error('Has no permission to access the photo library');
return;
@ -129,9 +127,7 @@ class PageStyleCoverImage extends StatelessWidget {
XFile? result;
try {
result = await _imagePicker.pickImage(
source: ImageSource.gallery,
);
result = await _imagePicker.pickImage(source: ImageSource.gallery);
} catch (e) {
Log.error('Error while picking image: $e');
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 {

View File

@ -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/plugins/document/presentation/editor_plugins/page_style/_page_style_util.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:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -163,11 +164,8 @@ class _FontButton extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<DocumentPageStyleBloc, DocumentPageStyleState>(
builder: (context, state) {
String fontFamily = state.fontFamily ?? builtInFontFamily();
if (fontFamily == builtInFontFamily()) {
fontFamily =
LocaleKeys.settings_appearance_fontFamily_defaultFont.tr();
}
final fontFamilyDisplayName =
(state.fontFamily ?? defaultFontFamily).fontFamilyDisplayName;
return GestureDetector(
onTap: () => _showFontSelector(context),
behavior: HitTestBehavior.opaque,
@ -182,7 +180,7 @@ class _FontButton extends StatelessWidget {
const HSpace(16.0),
FlowyText(LocaleKeys.titleBar_font.tr()),
const Spacer(),
FlowyText(fontFamily),
FlowyText(fontFamilyDisplayName),
const HSpace(6.0),
const FlowySvg(FlowySvgs.m_page_style_arrow_right_s),
const HSpace(12.0),
@ -219,7 +217,7 @@ class _FontButton extends StatelessWidget {
child: FontSelector(
scrollController: controller,
selectedFontFamilyName:
state.fontFamily ?? builtInFontFamily(),
state.fontFamily ?? defaultFontFamily,
onFontFamilySelected: (fontFamilyName) {
context.read<DocumentPageStyleBloc>().add(
DocumentPageStyleEvent.updateFontFamily(

View File

@ -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/inline_actions/inline_actions_menu.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/settings/appearance/appearance_cubit.dart';
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
@ -92,7 +92,7 @@ class EditorStyleCustomizer {
final theme = Theme.of(context);
final fontSize = pageStyle.fontLayout.fontSize;
final lineHeight = pageStyle.lineHeightLayout.lineHeight;
final fontFamily = pageStyle.fontFamily ?? builtInFontFamily();
final fontFamily = pageStyle.fontFamily ?? defaultFontFamily;
final defaultTextDirection =
context.read<DocumentAppearanceCubit>().state.defaultTextDirection;
final baseTextStyle = this.baseTextStyle(fontFamily);
@ -178,7 +178,7 @@ class EditorStyleCustomizer {
TextStyle outlineBlockPlaceholderStyleBuilder() {
final fontSize = context.read<DocumentAppearanceCubit>().state.fontSize;
return TextStyle(
fontFamily: builtInFontFamily(),
fontFamily: defaultFontFamily,
fontSize: fontSize,
height: 1.5,
color: Theme.of(context).colorScheme.onBackground.withOpacity(0.6),
@ -219,7 +219,8 @@ class EditorStyleCustomizer {
try {
return getGoogleFontSafely(fontFamily, fontWeight: fontWeight);
} on Exception {
if ([builtInFontFamily(), builtInCodeFontFamily].contains(fontFamily)) {
if ([defaultFontFamily, fallbackFontFamily, builtInCodeFontFamily]
.contains(fontFamily)) {
return TextStyle(fontFamily: fontFamily, fontWeight: fontWeight);
}