From 4cfd83cbc41329407f0bb3584da9955691ba1573 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Mon, 13 May 2024 13:26:19 +0800 Subject: [PATCH] fix: page style issues (#5317) * fix: 7 emojis per line * fix: remove shadow of the icons using presets cover * fix: expand appbar buttons size * fix: save new title name when it changed * feat: add cover image preview * fix: dismiss unsplash and presets panel auto * feat: add selected color for cover image and layout section * fix: selected icon size too small * fix: dismiss page style panel before pushing to emoji and font selector * chore: update back button icon * chore: bump version 0.5.7 --- CHANGELOG.md | 18 ++ frontend/Makefile.toml | 2 +- .../base/mobile_view_page_bloc.dart | 9 +- .../presentation/base/app_bar/app_bar.dart | 3 +- .../base/view_page/app_bar_buttons.dart | 16 +- .../cover/document_immersive_cover.dart | 16 +- .../image/unsplash_image_widget.dart | 53 +++-- .../page_style/_page_style_cover_image.dart | 208 +++++++++++++----- .../page_style/_page_style_icon.dart | 73 +++--- .../page_style/_page_style_layout.dart | 22 +- .../page_style/page_style_bottom_sheet.dart | 2 +- frontend/appflowy_flutter/pubspec.yaml | 2 +- .../flowy_icons/16x/m_app_bar_back.svg | 6 +- frontend/resources/translations/en.json | 3 +- 14 files changed, 294 insertions(+), 139 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acbf0b7999..550cd2bbce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,22 @@ # Release Notes +## Version 0.5.7 - 05/10/2024 +### Bug Fixes +- Resolved page opening issue on Android. +- Fixed text input inconsistency on Kanban board cards. + +## Version 0.5.6 - 05/07/2024 +### New Features +- Team collaboration is live! Add members to your workspace to edit and collaborate on pages together. +- Collaborate in real time on the same page with other members. Edits made by others will appear instantly. +- Create multiple workspaces for different kinds of content. +- Customize your entire page on mobile through the Page Style menu with options for layout, font, font size, emoji, and cover image. +- Open a row record as a full page. +### Bug Fixes +- Resolved issue with setting background color for the Simple Table block. +- Adjusted toolbar for various screen sizes. +- Added a request for photo permission before uploading images on mobile. +- Exported creation and last modification timestamps to CSV. + ## Version 0.5.5 - 04/24/2024 ### New Features - Improved the display of code blocks with line numbers diff --git a/frontend/Makefile.toml b/frontend/Makefile.toml index 5c6950e179..d5fad27238 100644 --- a/frontend/Makefile.toml +++ b/frontend/Makefile.toml @@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true CARGO_MAKE_CRATE_FS_NAME = "dart_ffi" CARGO_MAKE_CRATE_NAME = "dart-ffi" LIB_NAME = "dart_ffi" -APPFLOWY_VERSION = "0.5.6" +APPFLOWY_VERSION = "0.5.7" FLUTTER_DESKTOP_FEATURES = "dart" PRODUCT_NAME = "AppFlowy" MACOSX_DEPLOYMENT_TARGET = "11.0" diff --git a/frontend/appflowy_flutter/lib/mobile/application/base/mobile_view_page_bloc.dart b/frontend/appflowy_flutter/lib/mobile/application/base/mobile_view_page_bloc.dart index c9a6b8a8f0..50426b5761 100644 --- a/frontend/appflowy_flutter/lib/mobile/application/base/mobile_view_page_bloc.dart +++ b/frontend/appflowy_flutter/lib/mobile/application/base/mobile_view_page_bloc.dart @@ -1,8 +1,10 @@ import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart'; +import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy/workspace/application/view/prelude.dart'; import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -21,6 +23,9 @@ class MobileViewPageBloc initial: () async { _registerListeners(); + final userProfilePB = + await UserBackendService.getCurrentUserProfile() + .fold((s) => s, (f) => null); final result = await ViewBackendService.getView(viewId); final isImmersiveMode = _isImmersiveMode(result.fold((s) => s, (f) => null)); @@ -29,6 +34,7 @@ class MobileViewPageBloc isLoading: false, result: result, isImmersiveMode: isImmersiveMode, + userProfilePB: userProfilePB, ), ); }, @@ -71,7 +77,7 @@ class MobileViewPageBloc final cover = view.cover; if (cover == null || cover.type == PageStyleCoverImageType.none) { return false; - } else if (view.layout == ViewLayoutPB.Document) { + } else if (view.layout == ViewLayoutPB.Document && !cover.isPresets) { // only support immersive mode for document layout return true; } @@ -93,6 +99,7 @@ class MobileViewPageState with _$MobileViewPageState { @Default(true) bool isLoading, @Default(null) FlowyResult? result, @Default(false) bool isImmersiveMode, + @Default(null) UserProfilePB? userProfilePB, }) = _MobileViewPageState; factory MobileViewPageState.initial() => const MobileViewPageState(); diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/base/app_bar/app_bar.dart b/frontend/appflowy_flutter/lib/mobile/presentation/base/app_bar/app_bar.dart index b6a50d9661..335f1af489 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/base/app_bar/app_bar.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/base/app_bar/app_bar.dart @@ -37,6 +37,7 @@ class FlowyAppBar extends AppBar { Widget? title, String? titleText, FlowyAppBarLeadingType leadingType = FlowyAppBarLeadingType.back, + double? leadingWidth, Widget? leading, super.centerTitle, VoidCallback? onTapLeading, @@ -52,7 +53,7 @@ class FlowyAppBar extends AppBar { titleSpacing: 0, elevation: 0, leading: leading ?? leadingType.getWidget(onTapLeading), - leadingWidth: leadingType.width, + leadingWidth: leadingWidth ?? leadingType.width, toolbarHeight: 44.0, bottom: showDivider ? const PreferredSize( diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/base/view_page/app_bar_buttons.dart b/frontend/appflowy_flutter/lib/mobile/presentation/base/view_page/app_bar_buttons.dart index af2a423b4a..d712aa5aec 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/base/view_page/app_bar_buttons.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/base/view_page/app_bar_buttons.dart @@ -43,8 +43,9 @@ class MobileViewPageImmersiveAppBar extends StatelessWidget AppBarTheme.of(context).backgroundColor?.withOpacity(opacity), showDivider: false, title: Opacity(opacity: opacity >= 0.99 ? 1.0 : 0, child: title), + leadingWidth: 44, leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 2.0, vertical: 4.0), + padding: const EdgeInsets.only(top: 4.0, bottom: 4.0, left: 12.0), child: _buildAppBarBackButton(context), ), actions: actions, @@ -59,7 +60,7 @@ class MobileViewPageImmersiveAppBar extends StatelessWidget child: _ImmersiveAppBarButton( icon: FlowySvgs.m_app_bar_back_s, dimension: 30.0, - iconPadding: 6.0, + iconPadding: 3.0, isImmersiveMode: context.read().state.isImmersiveMode, appBarOpacity: appBarOpacity, @@ -104,7 +105,7 @@ class MobileViewPageMoreButton extends StatelessWidget { child: _ImmersiveAppBarButton( icon: FlowySvgs.m_app_bar_more_s, dimension: 30.0, - iconPadding: 5.0, + iconPadding: 3.0, isImmersiveMode: isImmersiveMode, appBarOpacity: appBarOpacity, ), @@ -144,8 +145,11 @@ class MobileViewPageLayoutButton extends StatelessWidget { showHeader: true, title: LocaleKeys.pageStyle_title.tr(), backgroundColor: Theme.of(context).colorScheme.background, - builder: (_) => BlocProvider.value( - value: context.read(), + builder: (_) => MultiBlocProvider( + providers: [ + BlocProvider.value(value: context.read()), + BlocProvider.value(value: context.read()), + ], child: PageStyleBottomSheet( view: context.read().state.view, ), @@ -155,7 +159,7 @@ class MobileViewPageLayoutButton extends StatelessWidget { child: _ImmersiveAppBarButton( icon: FlowySvgs.m_layout_s, dimension: 30.0, - iconPadding: 5.0, + iconPadding: 3.0, isImmersiveMode: isImmersiveMode, appBarOpacity: appBarOpacity, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/cover/document_immersive_cover.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/cover/document_immersive_cover.dart index b5070c3dec..741b3c16ee 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/cover/document_immersive_cover.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/cover/document_immersive_cover.dart @@ -149,14 +149,11 @@ class _DocumentImmersiveCoverState extends State { fontSize: 28.0, fontWeight: FontWeight.w700, fontFamily: fontFamily, - color: state.cover.type == PageStyleCoverImageType.none - ? null - : Colors.white, + color: + state.cover.isNone || state.cover.isPresets ? null : Colors.white, ), - onSubmitted: (value) { - scrollController.position.jumpTo(0); - context.read().add(ViewEvent.rename(value)); - }, + onChanged: _rename, + onSubmitted: _rename, ); } @@ -250,4 +247,9 @@ class _DocumentImmersiveCoverState extends State { focusNode.unfocus(disposition: UnfocusDisposition.previouslyFocusedChild); } } + + void _rename(String name) { + scrollController.position.jumpTo(0); + context.read().add(ViewEvent.rename(name)); + } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart index a7ec64e5ce..36d90ac6fb 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart @@ -131,12 +131,16 @@ class _UnsplashImages extends StatelessWidget { }; final mainAxisSpacing = switch (type) { UnsplashImageType.halfScreen => 16.0, - UnsplashImageType.fullScreen => 8.0, + UnsplashImageType.fullScreen => 16.0, + }; + final crossAxisSpacing = switch (type) { + UnsplashImageType.halfScreen => 10.0, + UnsplashImageType.fullScreen => 16.0, }; return GridView.count( crossAxisCount: crossAxisCount, mainAxisSpacing: mainAxisSpacing, - crossAxisSpacing: 10.0, + crossAxisSpacing: crossAxisSpacing, childAspectRatio: 4 / 3, children: photos .map( @@ -197,28 +201,31 @@ class _UnsplashImage extends StatelessWidget { } Widget _buildFullScreenImage(BuildContext context) { - return Stack( - children: [ - LayoutBuilder( - builder: (context, constraints) { - return Image.network( - photo.urls.thumb.toString(), - fit: BoxFit.cover, - width: constraints.maxWidth, - height: constraints.maxHeight, - ); - }, - ), - Positioned( - bottom: 6, - left: 6, - child: FlowyText.medium( - photo.name, - fontSize: 10.0, - color: Colors.white, + return ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Stack( + children: [ + LayoutBuilder( + builder: (context, constraints) { + return Image.network( + photo.urls.thumb.toString(), + fit: BoxFit.cover, + width: constraints.maxWidth, + height: constraints.maxHeight, + ); + }, ), - ), - ], + Positioned( + bottom: 9, + left: 10, + child: FlowyText.medium( + photo.name, + fontSize: 13.0, + color: Colors.white, + ), + ), + ], + ), ); } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_cover_image.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_cover_image.dart index 1d6b100534..3055c7c440 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_cover_image.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_cover_image.dart @@ -1,16 +1,21 @@ import 'dart:async'; +import 'dart:io'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/mobile/application/base/mobile_view_page_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/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/appflowy_network_image.dart'; import 'package:appflowy/shared/feedback_gesture_detector.dart'; +import 'package:appflowy/shared/flowy_gradient_colors.dart'; import 'package:appflowy/shared/permission/permission_checker.dart'; import 'package:appflowy/user/application/user_service.dart'; +import 'package:appflowy/util/string_extension.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_result/appflowy_result.dart'; @@ -19,6 +24,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:go_router/go_router.dart'; import 'package:image_picker/image_picker.dart'; class PageStyleCoverImage extends StatelessWidget { @@ -33,13 +39,11 @@ class PageStyleCoverImage extends StatelessWidget { final backgroundColor = context.pageStyleBackgroundColor; return BlocBuilder( builder: (context, state) { - return Row( + return Column( children: [ - _buildOptionGroup( - context, - backgroundColor, - state, - ), + _buildOptionGroup(context, backgroundColor, state), + const VSpace(16.0), + _buildPreview(context, state), ], ); }, @@ -51,46 +55,124 @@ class PageStyleCoverImage extends StatelessWidget { Color backgroundColor, DocumentPageStyleState state, ) { - return Expanded( - child: Container( - decoration: BoxDecoration( - color: backgroundColor, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(12), - right: Radius.circular(12), + return Container( + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(12), + right: Radius.circular(12), + ), + ), + padding: const EdgeInsets.all(4.0), + child: Row( + children: [ + _CoverOptionButton( + showLeftCorner: true, + showRightCorner: false, + selected: state.coverImage.isPresets, + onTap: () => _showPresets(context), + child: const _PresetCover(), ), - ), - padding: const EdgeInsets.all(4.0), - child: Row( - children: [ - _CoverOptionButton( - showLeftCorner: true, - showRightCorner: false, - selected: state.coverImage.isPresets, - onTap: () => _showPresets(context), - child: const _PresetCover(), - ), - _CoverOptionButton( - showLeftCorner: false, - showRightCorner: false, - selected: state.coverImage.isPhoto, - onTap: () => _pickImage(context), - child: const _PhotoCover(), - ), - _CoverOptionButton( - showLeftCorner: false, - showRightCorner: true, - selected: state.coverImage.isUnsplashImage, - onTap: () => _showUnsplash(context), - child: const _UnsplashCover(), - ), - ], - ), + _CoverOptionButton( + showLeftCorner: false, + showRightCorner: false, + selected: state.coverImage.isPhoto, + onTap: () => _pickImage(context), + child: const _PhotoCover(), + ), + _CoverOptionButton( + showLeftCorner: false, + showRightCorner: true, + selected: state.coverImage.isUnsplashImage, + onTap: () => _showUnsplash(context), + child: const _UnsplashCover(), + ), + ], ), ); } + Widget _buildPreview( + BuildContext context, + DocumentPageStyleState state, + ) { + final cover = state.coverImage; + if (cover.isNone) { + return const SizedBox.shrink(); + } + + final value = cover.value; + final type = cover.type; + + Widget preview = const SizedBox.shrink(); + + if (type == PageStyleCoverImageType.customImage || + type == PageStyleCoverImageType.unsplashImage) { + final userProfilePB = + context.read().state.userProfilePB; + preview = FlowyNetworkImage( + url: value, + userProfilePB: userProfilePB, + ); + } + + if (type == PageStyleCoverImageType.builtInImage) { + preview = Image.asset( + PageStyleCoverImageType.builtInImagePath(value), + fit: BoxFit.cover, + ); + } + + if (type == PageStyleCoverImageType.pureColor) { + final color = value.coverColor(context); + if (color != null) { + preview = ColoredBox( + color: color, + ); + } + } + + if (type == PageStyleCoverImageType.gradientColor) { + preview = Container( + decoration: BoxDecoration( + gradient: FlowyGradientColor.fromId(value).linear, + ), + ); + } + + if (type == PageStyleCoverImageType.localImage) { + preview = Image.file( + File(value), + fit: BoxFit.cover, + ); + } + + return Row( + children: [ + FlowyText(LocaleKeys.pageStyle_image.tr()), + const Spacer(), + Container( + width: 40, + height: 28, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(6.0)), + border: Border.all(color: const Color(0x1F222533)), + ), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(5.0)), + child: preview, + ), + ), + ], + ); + } + void _showPresets(BuildContext context) { + final pageStyleBloc = context.read(); + + context.pop(); + showMobileBottomSheet( context, showDragHandle: true, @@ -99,18 +181,18 @@ class PageStyleCoverImage extends StatelessWidget { showHeader: true, showRemoveButton: true, onRemove: () { - context.read().add( - DocumentPageStyleEvent.updateCoverImage( - PageStyleCover.none(), - ), - ); + pageStyleBloc.add( + DocumentPageStyleEvent.updateCoverImage( + PageStyleCover.none(), + ), + ); }, - title: LocaleKeys.pageStyle_pageCover.tr(), + title: LocaleKeys.pageStyle_presets.tr(), barrierColor: Colors.transparent, backgroundColor: Theme.of(context).colorScheme.background, builder: (_) { return BlocProvider.value( - value: context.read(), + value: pageStyleBloc, child: const PageCoverBottomSheet(), ); }, @@ -174,6 +256,9 @@ class PageStyleCoverImage extends StatelessWidget { } void _showUnsplash(BuildContext context) { + final pageStyleBloc = context.read(); + context.pop(); + showMobileBottomSheet( context, showDragHandle: true, @@ -181,15 +266,15 @@ class PageStyleCoverImage extends StatelessWidget { showDoneButton: true, showHeader: true, showRemoveButton: true, - title: LocaleKeys.pageStyle_coverImage.tr(), + title: LocaleKeys.pageStyle_unsplash.tr(), barrierColor: Colors.transparent, backgroundColor: Theme.of(context).colorScheme.background, onRemove: () { - context.read().add( - DocumentPageStyleEvent.updateCoverImage( - PageStyleCover.none(), - ), - ); + pageStyleBloc.add( + DocumentPageStyleEvent.updateCoverImage( + PageStyleCover.none(), + ), + ); }, builder: (_) { return ConstrainedBox( @@ -204,14 +289,14 @@ class PageStyleCoverImage extends StatelessWidget { child: UnsplashImageWidget( type: UnsplashImageType.fullScreen, onSelectUnsplashImage: (url) { - context.read().add( - DocumentPageStyleEvent.updateCoverImage( - PageStyleCover( - type: PageStyleCoverImageType.unsplashImage, - value: url, - ), - ), - ); + pageStyleBloc.add( + DocumentPageStyleEvent.updateCoverImage( + PageStyleCover( + type: PageStyleCoverImageType.unsplashImage, + value: url, + ), + ), + ); }, ), ), @@ -308,6 +393,7 @@ class _CoverOptionButton extends StatelessWidget { duration: Durations.medium1, decoration: selected ? ShapeDecoration( + color: const Color(0x141AC3F2), shape: RoundedRectangleBorder( side: const BorderSide( width: 1.50, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_icon.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_icon.dart index 5dc49fa8ff..ae975048d6 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_icon.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_icon.dart @@ -11,8 +11,9 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_emoji_mart/flutter_emoji_mart.dart'; +import 'package:go_router/go_router.dart'; -class PageStyleIcon extends StatelessWidget { +class PageStyleIcon extends StatefulWidget { const PageStyleIcon({ super.key, required this.view, @@ -20,10 +21,15 @@ class PageStyleIcon extends StatelessWidget { final ViewPB view; + @override + State createState() => _PageStyleIconState(); +} + +class _PageStyleIconState extends State { @override Widget build(BuildContext context) { return BlocProvider( - create: (_) => PageStyleIconBloc(view: view) + create: (_) => PageStyleIconBloc(view: widget.view) ..add(const PageStyleIconEvent.initial()), child: BlocBuilder( builder: (context, state) { @@ -60,6 +66,10 @@ class PageStyleIcon extends StatelessWidget { } void _showIconSelector(BuildContext context, String selectedIcon) { + context.pop(); + + final pageStyleIconBloc = PageStyleIconBloc(view: widget.view) + ..add(const PageStyleIconEvent.initial()); showMobileBottomSheet( context, showDragHandle: true, @@ -75,13 +85,13 @@ class PageStyleIcon extends StatelessWidget { initialChildSize: 0.61, showRemoveButton: true, onRemove: () { - context.read().add( - const PageStyleIconEvent.updateIcon('', true), - ); + pageStyleIconBloc.add( + const PageStyleIconEvent.updateIcon('', true), + ); }, scrollableWidgetBuilder: (_, controller) { return BlocProvider.value( - value: context.read(), + value: pageStyleIconBloc, child: Expanded( child: Scrollbar( controller: controller, @@ -112,6 +122,8 @@ class _IconSelectorState extends State<_IconSelector> { EmojiData? emojiData; List availableEmojis = []; + PageStyleIconBloc? pageStyleIconBloc; + @override void initState() { super.initState(); @@ -131,6 +143,14 @@ class _IconSelectorState extends State<_IconSelector> { }, ); } + + pageStyleIconBloc = context.read(); + } + + @override + void dispose() { + pageStyleIconBloc?.close(); + super.dispose(); } @override @@ -146,7 +166,7 @@ class _IconSelectorState extends State<_IconSelector> { _buildSearchBar(context), Expanded( child: GridView.count( - crossAxisCount: _getEmojiPerLine(context), + crossAxisCount: 7, controller: widget.scrollController, children: [ for (final emoji in availableEmojis) @@ -165,27 +185,33 @@ class _IconSelectorState extends State<_IconSelector> { String emoji, String? selectedEmoji, ) { - Widget child = Center( - child: FlowyText.emoji( - emoji, - fontSize: 24, + Widget child = SizedBox.square( + dimension: 24.0, + child: Center( + child: FlowyText.emoji( + emoji, + fontSize: 24, + ), ), ); if (emoji == selectedEmoji) { - child = Container( - margin: const EdgeInsets.all(8.0), - decoration: ShapeDecoration( - shape: RoundedRectangleBorder( - side: const BorderSide( - width: 1.50, - strokeAlign: BorderSide.strokeAlignOutside, - color: Color(0xFF00BCF0), + child = Center( + child: Container( + width: 40, + height: 40, + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: const BorderSide( + width: 1.40, + strokeAlign: BorderSide.strokeAlignOutside, + color: Color(0xFF00BCF0), + ), + borderRadius: BorderRadius.circular(10), ), - borderRadius: BorderRadius.circular(9), ), + child: child, ), - child: child, ); } @@ -208,11 +234,6 @@ class _IconSelectorState extends State<_IconSelector> { return availableEmojis; } - int _getEmojiPerLine(BuildContext context) { - final width = MediaQuery.of(context).size.width; - return width ~/ 48.0; // the size of the emoji - } - Widget _buildSearchBar(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_layout.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_layout.dart index bbe0fda27c..7b8d5cfb92 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_layout.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/_page_style_layout.dart @@ -11,6 +11,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:go_router/go_router.dart'; const kPageStyleLayoutHeight = 52.0; @@ -117,6 +118,7 @@ class _OptionGroup extends StatelessWidget { duration: Durations.medium1, decoration: selected ? ShapeDecoration( + color: const Color(0x141AC3F2), shape: RoundedRectangleBorder( side: const BorderSide( width: 1.50, @@ -180,7 +182,10 @@ class _FontButton extends StatelessWidget { const HSpace(16.0), FlowyText(LocaleKeys.titleBar_font.tr()), const Spacer(), - FlowyText(fontFamilyDisplayName), + FlowyText( + fontFamilyDisplayName, + color: context.pageStyleTextColor, + ), const HSpace(6.0), const FlowySvg(FlowySvgs.m_page_style_arrow_right_s), const HSpace(12.0), @@ -193,6 +198,9 @@ class _FontButton extends StatelessWidget { } void _showFontSelector(BuildContext context) { + final pageStyleBloc = context.read(); + context.pop(); + showMobileBottomSheet( context, showDragHandle: true, @@ -208,7 +216,7 @@ class _FontButton extends StatelessWidget { initialChildSize: 0.61, scrollableWidgetBuilder: (_, controller) { return BlocProvider.value( - value: context.read(), + value: pageStyleBloc, child: BlocBuilder( builder: (context, state) { return Expanded( @@ -219,11 +227,11 @@ class _FontButton extends StatelessWidget { selectedFontFamilyName: state.fontFamily ?? defaultFontFamily, onFontFamilySelected: (fontFamilyName) { - context.read().add( - DocumentPageStyleEvent.updateFontFamily( - fontFamilyName, - ), - ); + pageStyleBloc.add( + DocumentPageStyleEvent.updateFontFamily( + fontFamilyName, + ), + ); }, ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/page_style_bottom_sheet.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/page_style_bottom_sheet.dart index 18238ffc79..29dec9ad67 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/page_style_bottom_sheet.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/page_style/page_style_bottom_sheet.dart @@ -25,7 +25,7 @@ class PageStyleBottomSheet extends StatelessWidget { children: [ // cover image FlowyText( - LocaleKeys.pageStyle_backgroundImage.tr(), + LocaleKeys.pageStyle_coverImage.tr(), color: context.pageStyleTextColor, fontSize: 14.0, ), diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 93b9db3fb1..fa2e0f5c9f 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.5.6 +version: 0.5.7 environment: flutter: ">=3.19.0" diff --git a/frontend/resources/flowy_icons/16x/m_app_bar_back.svg b/frontend/resources/flowy_icons/16x/m_app_bar_back.svg index 817fec672b..7a5d7cb387 100644 --- a/frontend/resources/flowy_icons/16x/m_app_bar_back.svg +++ b/frontend/resources/flowy_icons/16x/m_app_bar_back.svg @@ -1,5 +1,5 @@ - - - + + + diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 1c4943797b..5e45d4bb0e 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -1611,7 +1611,8 @@ "photoPermissionDescription": "Allow access to the photo library for uploading images.", "openSettings": "Open Settings", "photoPermissionTitle": "AppFlowy Would Like to Access Your Photo Library", - "doNotAllow": "Don't Allow" + "doNotAllow": "Don't Allow", + "image": "Image" }, "commandPalette": { "placeholder": "Type to search for views...",