mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: take the max value of the keyboard height and the view insets bottom to make the toolbar visible (#5700)
* fix: android toolbar will be blocked if the scroll bar is hidden * fix: last opened view is synced in same workspace * fix: fallback to space if the section sidebar contains space * chore: revert last opened view code * fix: integration tests
This commit is contained in:
parent
2d11215bb2
commit
2ecc2a67a9
@ -11,6 +11,7 @@ void main() {
|
||||
testWidgets('toggle theme mode', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
await tester.wait(1000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:appflowy/plugins/document/application/document_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_menu/_close_keyboard_or_menu_button.dart';
|
||||
@ -9,6 +10,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_too
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -284,6 +286,14 @@ class _MobileToolbarState extends State<_MobileToolbar>
|
||||
|
||||
if (canUpdateCachedKeyboardHeight) {
|
||||
cachedKeyboardHeight.value = height;
|
||||
|
||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||
// cache the keyboard height with the view padding in Android
|
||||
if (cachedKeyboardHeight.value != 0) {
|
||||
cachedKeyboardHeight.value +=
|
||||
MediaQuery.of(context).viewPadding.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (height == 0) {
|
||||
@ -385,13 +395,19 @@ class _MobileToolbarState extends State<_MobileToolbar>
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: showMenuNotifier,
|
||||
builder: (_, showingMenu, __) {
|
||||
var paddingHeight = height;
|
||||
if (Platform.isAndroid) {
|
||||
paddingHeight =
|
||||
height + MediaQuery.of(context).viewPadding.bottom;
|
||||
var keyboardHeight = height;
|
||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||
if (!showingMenu) {
|
||||
// take the max value of the keyboard height and the view padding
|
||||
// to make sure the toolbar is above the keyboard
|
||||
keyboardHeight = max(
|
||||
keyboardHeight,
|
||||
MediaQuery.of(context).viewInsets.bottom,
|
||||
);
|
||||
}
|
||||
}
|
||||
return SizedBox(
|
||||
height: paddingHeight,
|
||||
height: keyboardHeight,
|
||||
child: (showingMenu && selectedMenuIndex != null)
|
||||
? widget.toolbarItems[selectedMenuIndex!].menuBuilder?.call(
|
||||
context,
|
||||
|
@ -5,6 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'
|
||||
show WorkspaceSettingPB;
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'home_bloc.freezed.dart';
|
||||
|
||||
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
|
@ -54,9 +54,11 @@ class SidebarSectionsBloc
|
||||
_initial(userProfile, workspaceId);
|
||||
final sectionViews = await _getSectionViews();
|
||||
if (sectionViews != null) {
|
||||
final containsSpace = _containsSpace(sectionViews);
|
||||
emit(
|
||||
state.copyWith(
|
||||
section: sectionViews,
|
||||
containsSpace: containsSpace,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -65,9 +67,11 @@ class SidebarSectionsBloc
|
||||
_reset(userProfile, workspaceId);
|
||||
final sectionViews = await _getSectionViews();
|
||||
if (sectionViews != null) {
|
||||
final containsSpace = _containsSpace(sectionViews);
|
||||
emit(
|
||||
state.copyWith(
|
||||
section: sectionViews,
|
||||
containsSpace: containsSpace,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -160,9 +164,11 @@ class SidebarSectionsBloc
|
||||
_initial(userProfile, workspaceId);
|
||||
final sectionViews = await _getSectionViews();
|
||||
if (sectionViews != null) {
|
||||
final containsSpace = _containsSpace(sectionViews);
|
||||
emit(
|
||||
state.copyWith(
|
||||
section: sectionViews,
|
||||
containsSpace: containsSpace,
|
||||
),
|
||||
);
|
||||
// try to open the fist view in public section or private section
|
||||
@ -229,6 +235,11 @@ class SidebarSectionsBloc
|
||||
}
|
||||
}
|
||||
|
||||
bool _containsSpace(SidebarSection section) {
|
||||
return section.publicViews.any((view) => view.isSpace) ||
|
||||
section.privateViews.any((view) => view.isSpace);
|
||||
}
|
||||
|
||||
void _initial(UserProfilePB userProfile, String workspaceId) {
|
||||
_workspaceService = WorkspaceService(workspaceId: workspaceId);
|
||||
|
||||
@ -292,6 +303,7 @@ class SidebarSectionsState with _$SidebarSectionsState {
|
||||
required SidebarSection section,
|
||||
@Default(null) ViewPB? lastCreatedRootView,
|
||||
FlowyResult<void, FlowyError>? createRootViewResult,
|
||||
@Default(true) bool containsSpace,
|
||||
}) = _SidebarSectionsState;
|
||||
|
||||
factory SidebarSectionsState.initial() => const SidebarSectionsState(
|
||||
|
@ -4,12 +4,14 @@ import 'dart:convert';
|
||||
import 'package:appflowy/core/config/kv.dart';
|
||||
import 'package:appflowy/core/config/kv_keys.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/shared/list_extension.dart';
|
||||
import 'package:appflowy/startup/startup.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/workspace/application/view/view_service.dart';
|
||||
import 'package:appflowy/workspace/application/workspace/prelude.dart';
|
||||
import 'package:appflowy/workspace/application/workspace/workspace_sections_listener.dart';
|
||||
import 'package:appflowy/workspace/application/workspace/workspace_service.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/space_icon_popup.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
@ -20,6 +22,7 @@ import 'package:appflowy_result/appflowy_result.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
@ -68,6 +71,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
_initial(userProfile, workspaceId);
|
||||
|
||||
final (spaces, publicViews, privateViews) = await _getSpaces();
|
||||
|
||||
final shouldShowUpgradeDialog = await this.shouldShowUpgradeDialog(
|
||||
spaces: spaces,
|
||||
publicViews: publicViews,
|
||||
@ -82,13 +86,12 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
currentSpace: currentSpace,
|
||||
isExpanded: isExpanded,
|
||||
shouldShowUpgradeDialog: shouldShowUpgradeDialog,
|
||||
isInitialized: true,
|
||||
),
|
||||
);
|
||||
|
||||
if (shouldShowUpgradeDialog) {
|
||||
if (!integrationMode().isTest) {
|
||||
add(const SpaceEvent.migrate());
|
||||
}
|
||||
if (shouldShowUpgradeDialog && !integrationMode().isTest) {
|
||||
add(const SpaceEvent.migrate());
|
||||
}
|
||||
|
||||
if (openFirstPage) {
|
||||
@ -192,13 +195,31 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
open: (space) async {
|
||||
await _openSpace(space);
|
||||
final isExpanded = await _getSpaceExpandStatus(space);
|
||||
emit(state.copyWith(currentSpace: space, isExpanded: isExpanded));
|
||||
final views = await ViewBackendService.getChildViews(
|
||||
viewId: space.id,
|
||||
);
|
||||
final currentSpace = views.fold(
|
||||
(views) {
|
||||
space.freeze();
|
||||
return space.rebuild((b) {
|
||||
b.childViews.clear();
|
||||
b.childViews.addAll(views);
|
||||
});
|
||||
},
|
||||
(_) => space,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
currentSpace: currentSpace,
|
||||
isExpanded: isExpanded,
|
||||
),
|
||||
);
|
||||
|
||||
// don't open the page automatically on mobile
|
||||
if (PlatformExtension.isDesktop) {
|
||||
// open the first page by default
|
||||
if (space.childViews.isNotEmpty) {
|
||||
final firstPage = space.childViews.first;
|
||||
if (currentSpace.childViews.isNotEmpty) {
|
||||
final firstPage = currentSpace.childViews.first;
|
||||
emit(
|
||||
state.copyWith(
|
||||
lastCreatedPage: firstPage,
|
||||
@ -330,8 +351,9 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
||||
if (sectionViews == null || sectionViews.views.isEmpty) {
|
||||
return (<ViewPB>[], <ViewPB>[], <ViewPB>[]);
|
||||
}
|
||||
final publicViews = sectionViews.publicViews;
|
||||
final privateViews = sectionViews.privateViews;
|
||||
|
||||
final publicViews = sectionViews.publicViews.unique((e) => e.id);
|
||||
final privateViews = sectionViews.privateViews.unique((e) => e.id);
|
||||
|
||||
final publicSpaces = publicViews.where((e) => e.isSpace);
|
||||
final privateSpaces = privateViews.where((e) => e.isSpace);
|
||||
@ -690,6 +712,7 @@ class SpaceState with _$SpaceState {
|
||||
FlowyResult<void, FlowyError>? createPageResult,
|
||||
@Default(false) bool shouldShowUpgradeDialog,
|
||||
@Default(false) bool isDuplicatingSpace,
|
||||
@Default(false) bool isInitialized,
|
||||
}) = _SpaceState;
|
||||
|
||||
factory SpaceState.initial() => const SpaceState();
|
||||
|
@ -1,7 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/blank/blank.dart';
|
||||
@ -29,14 +27,16 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/sidebar_space.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/space_migration.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/sidebar_workspace.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
|
||||
show UserProfilePB;
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
Loading? _duplicateSpaceLoading;
|
||||
@ -360,10 +360,29 @@ class _SidebarState extends State<_Sidebar> {
|
||||
Widget _renderFolderOrSpace(EdgeInsets menuHorizontalInset) {
|
||||
final spaceState = context.read<SpaceBloc>().state;
|
||||
final workspaceState = context.read<UserWorkspaceBloc>().state;
|
||||
|
||||
if (!spaceState.isInitialized) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// there's no space or the workspace is not collaborative,
|
||||
// show the folder section (Workspace, Private, Personal)
|
||||
// otherwise, show the space
|
||||
return spaceState.spaces.isEmpty || !workspaceState.isCollabWorkspaceOn
|
||||
final sidebarSectionBloc = context.watch<SidebarSectionsBloc>();
|
||||
final containsSpace = sidebarSectionBloc.state.containsSpace;
|
||||
|
||||
Log.info('fetch the space info from sidebar section: $containsSpace');
|
||||
Log.info(
|
||||
'fetch the space info from space: ${spaceState.spaces.isNotEmpty}',
|
||||
);
|
||||
|
||||
if (containsSpace && spaceState.spaces.isEmpty) {
|
||||
context.read<SpaceBloc>().add(const SpaceEvent.didReceiveSpaceUpdate());
|
||||
}
|
||||
|
||||
return !containsSpace ||
|
||||
spaceState.spaces.isEmpty ||
|
||||
!workspaceState.isCollabWorkspaceOn
|
||||
? Expanded(
|
||||
child: Padding(
|
||||
padding: menuHorizontalInset - const EdgeInsets.only(right: 6),
|
||||
|
Loading…
Reference in New Issue
Block a user