mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-12-14 08:44:40 +00:00
fix: some mobile search UI issues (#7845)
* fix: some mobile search UI issues * fix: some icon colors * fix: show 'Add Link' while creating a link on mobile * fix: add tapping event for mobile embed link * fix: bookmark can not open the non-http link * fix: improve the behavior of links on mobile * fix: switch workspace will refresh the reminders * chore: remove unused import * fix: test error
This commit is contained in:
parent
63aa5112ba
commit
d28987d16d
@ -53,6 +53,7 @@ class _MobileBottomSheetEditLinkWidgetState
|
|||||||
ViewPB? currentView;
|
ViewPB? currentView;
|
||||||
bool showErrorText = false;
|
bool showErrorText = false;
|
||||||
bool showRemoveLink = false;
|
bool showRemoveLink = false;
|
||||||
|
String title = LocaleKeys.editor_editLink.tr();
|
||||||
|
|
||||||
AppFlowyThemeData get theme => AppFlowyTheme.of(context);
|
AppFlowyThemeData get theme => AppFlowyTheme.of(context);
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ class _MobileBottomSheetEditLinkWidgetState
|
|||||||
)..searchRecentViews();
|
)..searchRecentViews();
|
||||||
if (linkInfo.link.isEmpty) {
|
if (linkInfo.link.isEmpty) {
|
||||||
isShowingSearchResult = true;
|
isShowingSearchResult = true;
|
||||||
|
title = LocaleKeys.toolbar_addLink.tr();
|
||||||
} else {
|
} else {
|
||||||
showRemoveLink = true;
|
showRemoveLink = true;
|
||||||
textFocusNode.requestFocus();
|
textFocusNode.requestFocus();
|
||||||
@ -104,7 +106,7 @@ class _MobileBottomSheetEditLinkWidgetState
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
BottomSheetHeader(
|
BottomSheetHeader(
|
||||||
title: LocaleKeys.editor_editLink.tr(),
|
title: title,
|
||||||
onClose: () => context.pop(),
|
onClose: () => context.pop(),
|
||||||
confirmButton: FlowyTextButton(
|
confirmButton: FlowyTextButton(
|
||||||
LocaleKeys.button_done.tr(),
|
LocaleKeys.button_done.tr(),
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
|
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/command_palette/search_result_ext.dart';
|
import 'package:appflowy/workspace/application/command_palette/search_result_ext.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
|
||||||
import 'package:appflowy_ui/appflowy_ui.dart';
|
import 'package:appflowy_ui/appflowy_ui.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.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';
|
||||||
@ -20,12 +22,18 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
final theme = AppFlowyTheme.of(context),
|
final theme = AppFlowyTheme.of(context),
|
||||||
textColor = theme.textColorScheme.primary;
|
textColor = theme.textColorScheme.primary;
|
||||||
final commandPaletteState = context.read<CommandPaletteBloc>().state;
|
final commandPaletteState = context.read<CommandPaletteBloc>().state;
|
||||||
|
final displayName = item.displayName.isEmpty
|
||||||
|
? LocaleKeys.menuAppHeader_defaultNewPageName.tr()
|
||||||
|
: item.displayName;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
buildIcon(theme),
|
SizedBox.square(
|
||||||
|
dimension: 24,
|
||||||
|
child: Center(child: buildIcon(theme)),
|
||||||
|
),
|
||||||
HSpace(12),
|
HSpace(12),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -35,7 +43,7 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
text: buildHighLightSpan(
|
text: buildHighLightSpan(
|
||||||
content: item.displayName,
|
content: displayName,
|
||||||
normal: theme.textStyle.heading4.standard(color: textColor),
|
normal: theme.textStyle.heading4.standard(color: textColor),
|
||||||
highlight: theme.textStyle.heading4
|
highlight: theme.textStyle.heading4
|
||||||
.standard(color: textColor)
|
.standard(color: textColor)
|
||||||
@ -45,7 +53,7 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
buildPath(commandPaletteState, theme),
|
buildPath(commandPaletteState, theme),
|
||||||
buildSummary(theme),
|
...buildSummary(theme),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -84,11 +92,11 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildSummary(AppFlowyThemeData theme) {
|
List<Widget> buildSummary(AppFlowyThemeData theme) {
|
||||||
if (item.content.isEmpty) {
|
if (item.content.isEmpty) return [];
|
||||||
return const SizedBox.shrink();
|
return [
|
||||||
}
|
VSpace(theme.spacing.m),
|
||||||
return RichText(
|
RichText(
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
text: buildHighLightSpan(
|
text: buildHighLightSpan(
|
||||||
@ -101,7 +109,8 @@ class MobileSearchResultCell extends StatelessWidget {
|
|||||||
backgroundColor: theme.fillColorScheme.themeSelect,
|
backgroundColor: theme.fillColorScheme.themeSelect,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
TextSpan buildHighLightSpan({
|
TextSpan buildHighLightSpan({
|
||||||
|
|||||||
@ -55,7 +55,7 @@ class _MobileSearchTextfieldState extends State<MobileSearchTextfield> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = AppFlowyTheme.of(context);
|
final theme = AppFlowyTheme.of(context);
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 40,
|
height: 42,
|
||||||
child: ValueListenableBuilder(
|
child: ValueListenableBuilder(
|
||||||
valueListenable: controller,
|
valueListenable: controller,
|
||||||
builder: (context, _, __) {
|
builder: (context, _, __) {
|
||||||
@ -84,14 +84,19 @@ class _MobileSearchTextfieldState extends State<MobileSearchTextfield> {
|
|||||||
if (!hasFocus || !hasText) return SizedBox.shrink();
|
if (!hasFocus || !hasText) return SizedBox.shrink();
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => focusNode.unfocus(),
|
onTap: () => focusNode.unfocus(),
|
||||||
child: Padding(
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: Container(
|
||||||
|
height: 42,
|
||||||
padding: EdgeInsets.only(left: 8),
|
padding: EdgeInsets.only(left: 8),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
LocaleKeys.button_cancel.tr(),
|
LocaleKeys.button_cancel.tr(),
|
||||||
style: theme.textStyle.body
|
style: theme.textStyle.body
|
||||||
.standard(color: theme.textColorScheme.action),
|
.standard(color: theme.textColorScheme.action),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import 'dart:math';
|
|||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:appflowy_ui/appflowy_ui.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -328,6 +329,7 @@ class _MobileSelectionMenuWidgetState extends State<MobileSelectionMenuWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildNoResultsWidget(BuildContext context) {
|
Widget _buildNoResultsWidget(BuildContext context) {
|
||||||
|
final theme = AppFlowyTheme.of(context);
|
||||||
return DecoratedBox(
|
return DecoratedBox(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).cardColor,
|
color: Theme.of(context).cardColor,
|
||||||
@ -350,7 +352,10 @@ class _MobileSelectionMenuWidgetState extends State<MobileSelectionMenuWidget> {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
LocaleKeys.inlineActions_noResults.tr(),
|
LocaleKeys.inlineActions_noResults.tr(),
|
||||||
style: TextStyle(fontSize: 18.0, color: Color(0x801F2225)),
|
style: TextStyle(
|
||||||
|
fontSize: 18.0,
|
||||||
|
color: theme.textColorScheme.primary,
|
||||||
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -12,6 +12,7 @@ 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';
|
||||||
|
import 'package:universal_platform/universal_platform.dart';
|
||||||
|
|
||||||
import 'link_embed_menu.dart';
|
import 'link_embed_menu.dart';
|
||||||
|
|
||||||
@ -156,7 +157,9 @@ class LinkEmbedBlockComponentState
|
|||||||
child: ValueListenableBuilder<bool>(
|
child: ValueListenableBuilder<bool>(
|
||||||
valueListenable: showActionsNotifier,
|
valueListenable: showActionsNotifier,
|
||||||
builder: (context, showActions, child) {
|
builder: (context, showActions, child) {
|
||||||
if (!showActions) return SizedBox.shrink();
|
if (!showActions || UniversalPlatform.isMobile) {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
return LinkEmbedMenu(
|
return LinkEmbedMenu(
|
||||||
editorState: context.read<EditorState>(),
|
editorState: context.read<EditorState>(),
|
||||||
node: node,
|
node: node,
|
||||||
@ -189,14 +192,22 @@ class LinkEmbedBlockComponentState
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: !UniversalPlatform.isMobile
|
||||||
|
? null
|
||||||
|
: () =>
|
||||||
|
afLaunchUrlString(url, addingHttpSchemeWhenFailed: true),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
|
borderRadius:
|
||||||
|
const BorderRadius.vertical(top: Radius.circular(16)),
|
||||||
child: FlowyNetworkImage(
|
child: FlowyNetworkImage(
|
||||||
url: linkInfo.imageUrl ?? '',
|
url: linkInfo.imageUrl ?? '',
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
@ -258,7 +269,13 @@ class LinkEmbedBlockComponentState
|
|||||||
child: CircularProgressIndicator.adaptive(),
|
child: CircularProgressIndicator.adaptive(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Center(
|
: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: !UniversalPlatform.isMobile
|
||||||
|
? null
|
||||||
|
: () =>
|
||||||
|
afLaunchUrlString(url, addingHttpSchemeWhenFailed: true),
|
||||||
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -299,6 +316,7 @@ class LinkEmbedBlockComponentState
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -122,7 +122,8 @@ class CustomLinkPreviewWidget extends StatelessWidget {
|
|||||||
return MouseRegion(
|
return MouseRegion(
|
||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => afLaunchUrlString(url),
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () => afLaunchUrlString(url, addingHttpSchemeWhenFailed: true),
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -133,7 +134,8 @@ class CustomLinkPreviewWidget extends StatelessWidget {
|
|||||||
editorState: context.read<EditorState>(),
|
editorState: context.read<EditorState>(),
|
||||||
extendActionWidgets: _buildExtendActionWidgets(context),
|
extendActionWidgets: _buildExtendActionWidgets(context),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => afLaunchUrlString(url),
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () => afLaunchUrlString(url, addingHttpSchemeWhenFailed: true),
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/link_previ
|
|||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:universal_platform/universal_platform.dart';
|
||||||
|
|
||||||
import 'custom_link_preview.dart';
|
import 'custom_link_preview.dart';
|
||||||
import 'default_selectable_mixin.dart';
|
import 'default_selectable_mixin.dart';
|
||||||
@ -148,7 +149,7 @@ class CustomLinkPreviewBlockComponentState
|
|||||||
child = Stack(
|
child = Stack(
|
||||||
children: [
|
children: [
|
||||||
child,
|
child,
|
||||||
if (showActions)
|
if (showActions && UniversalPlatform.isDesktopOrWeb)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 12,
|
top: 12,
|
||||||
right: 12,
|
right: 12,
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:universal_platform/universal_platform.dart';
|
||||||
|
|
||||||
import 'mention_link_error_preview.dart';
|
import 'mention_link_error_preview.dart';
|
||||||
import 'mention_link_preview.dart';
|
import 'mention_link_preview.dart';
|
||||||
@ -91,6 +92,10 @@ class _MentionLinkBlockState extends State<MentionLinkBlock> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final child = buildIconWithTitle(context);
|
||||||
|
|
||||||
|
if (UniversalPlatform.isMobile) return child;
|
||||||
|
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
key: ValueKey(showAtBottom),
|
key: ValueKey(showAtBottom),
|
||||||
controller: previewController,
|
controller: previewController,
|
||||||
@ -143,7 +148,12 @@ class _MentionLinkBlockState extends State<MentionLinkBlock> {
|
|||||||
onRemoveLink: removeLink,
|
onRemoveLink: removeLink,
|
||||||
onOpenLink: openLink,
|
onOpenLink: openLink,
|
||||||
),
|
),
|
||||||
child: buildIconWithTitle(context),
|
child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
onEnter: onEnter,
|
||||||
|
onExit: onExit,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,17 +161,12 @@ class _MentionLinkBlockState extends State<MentionLinkBlock> {
|
|||||||
final theme = AppFlowyTheme.of(context);
|
final theme = AppFlowyTheme.of(context);
|
||||||
final siteName = linkInfo.siteName, linkTitle = linkInfo.title ?? url;
|
final siteName = linkInfo.siteName, linkTitle = linkInfo.title ?? url;
|
||||||
|
|
||||||
return MouseRegion(
|
return GestureDetector(
|
||||||
cursor: SystemMouseCursors.click,
|
|
||||||
onEnter: onEnter,
|
|
||||||
onExit: onExit,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await afLaunchUrlString(url, addingHttpSchemeWhenFailed: true);
|
await afLaunchUrlString(url, addingHttpSchemeWhenFailed: true);
|
||||||
},
|
},
|
||||||
child: FlowyHoverContainer(
|
child: FlowyHoverContainer(
|
||||||
style:
|
style: HoverStyle(hoverColor: Theme.of(context).colorScheme.secondary),
|
||||||
HoverStyle(hoverColor: Theme.of(context).colorScheme.secondary),
|
|
||||||
applyStyle: isHovering,
|
applyStyle: isHovering,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -196,7 +201,6 @@ class _MentionLinkBlockState extends State<MentionLinkBlock> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,6 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
_listener = AppLifecycleListener(
|
_listener = AppLifecycleListener(
|
||||||
onResume: () {
|
onResume: () {
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(const ReminderEvent.refresh());
|
|
||||||
add(const ReminderEvent.resetTimer());
|
add(const ReminderEvent.resetTimer());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -437,15 +436,11 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
|
|
||||||
Future<bool> checkReminderAvailable(
|
Future<bool> checkReminderAvailable(
|
||||||
ReminderPB reminder,
|
ReminderPB reminder,
|
||||||
Set<String> reminderIds, {
|
Set<String> reminderIds,
|
||||||
Set<String>? removedIds,
|
) async {
|
||||||
}) async {
|
|
||||||
/// blockId is null means no node
|
/// blockId is null means no node
|
||||||
final blockId = reminder.meta[ReminderMetaKeys.blockId];
|
final blockId = reminder.meta[ReminderMetaKeys.blockId];
|
||||||
if (blockId == null) {
|
if (blockId == null) return false;
|
||||||
removedIds?.add(reminder.id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// check if schedule time is comming
|
/// check if schedule time is comming
|
||||||
final scheduledAt = reminder.scheduledAt.toDateTime();
|
final scheduledAt = reminder.scheduledAt.toDateTime();
|
||||||
@ -457,19 +452,13 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
final viewId = reminder.objectId;
|
final viewId = reminder.objectId;
|
||||||
final view =
|
final view =
|
||||||
await ViewBackendService.getView(viewId).fold((s) => s, (_) => null);
|
await ViewBackendService.getView(viewId).fold((s) => s, (_) => null);
|
||||||
if (view == null) {
|
if (view == null) return false;
|
||||||
removedIds?.add(reminder.id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// check if document is not null
|
/// check if document is not null
|
||||||
final document = await DocumentService()
|
final document = await DocumentService()
|
||||||
.openDocument(documentId: viewId)
|
.openDocument(documentId: viewId)
|
||||||
.fold((s) => s.toDocument(), (_) => null);
|
.fold((s) => s.toDocument(), (_) => null);
|
||||||
if (document == null) {
|
if (document == null) return false;
|
||||||
removedIds?.add(reminder.id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Node? searchById(Node current, String id) {
|
Node? searchById(Node current, String id) {
|
||||||
if (current.id == id) {
|
if (current.id == id) {
|
||||||
return current;
|
return current;
|
||||||
@ -488,10 +477,7 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
|
|
||||||
/// check if node is not null
|
/// check if node is not null
|
||||||
final node = searchById(document.root, blockId);
|
final node = searchById(document.root, blockId);
|
||||||
if (node == null) {
|
if (node == null) return false;
|
||||||
removedIds?.add(reminder.id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final textInserts = node.delta?.whereType<TextInsert>();
|
final textInserts = node.delta?.whereType<TextInsert>();
|
||||||
if (textInserts == null) return false;
|
if (textInserts == null) return false;
|
||||||
for (final text in textInserts) {
|
for (final text in textInserts) {
|
||||||
@ -502,8 +488,6 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removedIds?.add(reminder.id);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,19 +496,11 @@ class ReminderBloc extends Bloc<ReminderEvent, ReminderState> {
|
|||||||
) async {
|
) async {
|
||||||
final List<ReminderPB> availableReminders = [];
|
final List<ReminderPB> availableReminders = [];
|
||||||
final reminderIds = reminders.map((e) => e.id).toSet();
|
final reminderIds = reminders.map((e) => e.id).toSet();
|
||||||
final removedIds = <String>{};
|
|
||||||
for (final r in reminders) {
|
for (final r in reminders) {
|
||||||
if (await checkReminderAvailable(
|
if (await checkReminderAvailable(r, reminderIds)) {
|
||||||
r,
|
|
||||||
reminderIds,
|
|
||||||
removedIds: removedIds,
|
|
||||||
)) {
|
|
||||||
availableReminders.add(r);
|
availableReminders.add(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (final id in removedIds) {
|
|
||||||
add(ReminderEvent.remove(reminderId: id));
|
|
||||||
}
|
|
||||||
return availableReminders;
|
return availableReminders;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/shared/feature_flags.dart';
|
import 'package:appflowy/shared/feature_flags.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
|
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||||
import 'package:appflowy/user/application/user_listener.dart';
|
import 'package:appflowy/user/application/user_listener.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';
|
||||||
@ -285,6 +287,7 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
getIt<ReminderBloc>().add(ReminderEvent.started());
|
||||||
},
|
},
|
||||||
renameWorkspace: (workspaceId, name) async {
|
renameWorkspace: (workspaceId, name) async {
|
||||||
final result =
|
final result =
|
||||||
|
|||||||
@ -276,7 +276,7 @@ class DesktopHomeScreen extends StatelessWidget {
|
|||||||
.animatedPanelX(
|
.animatedPanelX(
|
||||||
closeX: -layout.notificationPanelWidth,
|
closeX: -layout.notificationPanelWidth,
|
||||||
isClosed: !layout.showNotificationPanel,
|
isClosed: !layout.showNotificationPanel,
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeOutQuad,
|
||||||
duration: layout.animDuration.inMilliseconds * 0.001,
|
duration: layout.animDuration.inMilliseconds * 0.001,
|
||||||
)
|
)
|
||||||
.positioned(
|
.positioned(
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
|||||||
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart';
|
import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
|
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
|
||||||
|
import 'package:appflowy_ui/appflowy_ui.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
@ -83,6 +84,7 @@ class SidebarTopMenu extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
final theme = AppFlowyTheme.of(context);
|
||||||
|
|
||||||
return ValueListenableBuilder(
|
return ValueListenableBuilder(
|
||||||
valueListenable: isSidebarOnHover,
|
valueListenable: isSidebarOnHover,
|
||||||
@ -97,10 +99,12 @@ class SidebarTopMenu extends StatelessWidget {
|
|||||||
onPointerDown: (_) =>
|
onPointerDown: (_) =>
|
||||||
context.read<HomeSettingBloc>().collapseMenu(),
|
context.read<HomeSettingBloc>().collapseMenu(),
|
||||||
child: FlowyHover(
|
child: FlowyHover(
|
||||||
child: Container(
|
child: SizedBox(
|
||||||
width: 24,
|
width: 24,
|
||||||
padding: const EdgeInsets.all(4),
|
child: FlowySvg(
|
||||||
child: const FlowySvg(FlowySvgs.hide_menu_s),
|
FlowySvgs.double_back_arrow_m,
|
||||||
|
color: theme.iconColorScheme.secondary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -4,6 +4,7 @@ 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/workspace/application/home/home_setting_bloc.dart';
|
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
||||||
|
import 'package:appflowy_ui/appflowy_ui.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||||
@ -81,6 +82,7 @@ class FlowyNavigation extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
final theme = AppFlowyTheme.of(context);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(right: 8.0),
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@ -101,8 +103,10 @@ class FlowyNavigation extends StatelessWidget {
|
|||||||
child: FlowyIconButton(
|
child: FlowyIconButton(
|
||||||
width: 24,
|
width: 24,
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
iconPadding: const EdgeInsets.all(4),
|
icon: FlowySvg(
|
||||||
icon: const FlowySvg(FlowySvgs.hide_menu_s),
|
FlowySvgs.double_back_arrow_m,
|
||||||
|
color: theme.iconColorScheme.secondary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -99,8 +99,9 @@ class _NotificationPanelState extends State<NotificationPanel>
|
|||||||
Widget buildTitle({
|
Widget buildTitle({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required VoidCallback onHide,
|
required VoidCallback onHide,
|
||||||
}) =>
|
}) {
|
||||||
Container(
|
final theme = AppFlowyTheme.of(context);
|
||||||
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
height: 24,
|
height: 24,
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -112,19 +113,23 @@ class _NotificationPanelState extends State<NotificationPanel>
|
|||||||
),
|
),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
FlowyIconButton(
|
FlowyIconButton(
|
||||||
icon: FlowySvg(FlowySvgs.hide_menu_s),
|
|
||||||
width: 24,
|
width: 24,
|
||||||
|
icon: FlowySvg(
|
||||||
|
FlowySvgs.double_back_arrow_m,
|
||||||
|
color: theme.iconColorScheme.secondary,
|
||||||
|
),
|
||||||
richTooltipText: colappsedButtonTooltip(context),
|
richTooltipText: colappsedButtonTooltip(context),
|
||||||
onPressed: onHide,
|
onPressed: onHide,
|
||||||
iconPadding: const EdgeInsets.all(4),
|
|
||||||
),
|
),
|
||||||
HSpace(8),
|
HSpace(8),
|
||||||
buildMoreActionButton(context),
|
buildMoreActionButton(context),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget buildMoreActionButton(BuildContext context) {
|
Widget buildMoreActionButton(BuildContext context) {
|
||||||
|
final theme = AppFlowyTheme.of(context);
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
constraints: BoxConstraints.loose(const Size(240, 78)),
|
constraints: BoxConstraints.loose(const Size(240, 78)),
|
||||||
offset: const Offset(-24, 24),
|
offset: const Offset(-24, 24),
|
||||||
@ -134,13 +139,15 @@ class _NotificationPanelState extends State<NotificationPanel>
|
|||||||
onClose: () => keepEditorFocusNotifier.decrease(),
|
onClose: () => keepEditorFocusNotifier.decrease(),
|
||||||
popupBuilder: (_) => buildMoreActions(),
|
popupBuilder: (_) => buildMoreActions(),
|
||||||
child: FlowyIconButton(
|
child: FlowyIconButton(
|
||||||
icon: FlowySvg(FlowySvgs.three_dots_s),
|
|
||||||
width: 24,
|
width: 24,
|
||||||
|
icon: FlowySvg(
|
||||||
|
FlowySvgs.three_dots_m,
|
||||||
|
color: theme.iconColorScheme.secondary,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
keepEditorFocusNotifier.increase();
|
keepEditorFocusNotifier.increase();
|
||||||
moreActionController.show();
|
moreActionController.show();
|
||||||
},
|
},
|
||||||
iconPadding: const EdgeInsets.all(4),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
4
frontend/resources/flowy_icons/24x/double_back_arrow.svg
Normal file
4
frontend/resources/flowy_icons/24x/double_back_arrow.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11.25 6.75L6 12L11.25 17.25" stroke="#171717" stroke-width="1.2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M17.4375 6.75L12.1875 12L17.4375 17.25" stroke="#171717" stroke-width="1.2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 407 B |
5
frontend/resources/flowy_icons/24x/three_dots.svg
Normal file
5
frontend/resources/flowy_icons/24x/three_dots.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.325 12.0004C8.325 12.746 7.72058 13.3504 6.975 13.3504C6.22942 13.3504 5.625 12.746 5.625 12.0004C5.625 11.2548 6.22942 10.6504 6.975 10.6504C7.72058 10.6504 8.325 11.2548 8.325 12.0004Z" fill="#171717"/>
|
||||||
|
<path d="M13.3499 12.0004C13.3499 12.746 12.7455 13.3504 11.9999 13.3504C11.2543 13.3504 10.6499 12.746 10.6499 12.0004C10.6499 11.2548 11.2543 10.6504 11.9999 10.6504C12.7455 10.6504 13.3499 11.2548 13.3499 12.0004Z" fill="#171717"/>
|
||||||
|
<path d="M18.375 12.0004C18.375 12.746 17.7706 13.3504 17.025 13.3504C16.2795 13.3504 15.675 12.746 15.675 12.0004C15.675 11.2548 16.2795 10.6504 17.025 10.6504C17.7706 10.6504 18.375 11.2548 18.375 12.0004Z" fill="#171717"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 781 B |
Loading…
x
Reference in New Issue
Block a user