fix: stop hover when scrolling (#4801)

This commit is contained in:
Mathias Mogensen 2024-03-04 12:41:34 +01:00 committed by GitHub
parent 2af93a9bcb
commit ba965caa8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 83 additions and 14 deletions

View File

@ -1,3 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.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/workspace/application/menu/menu_bloc.dart'; import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
@ -8,17 +11,17 @@ import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
class PersonalFolder extends StatelessWidget { class PersonalFolder extends StatelessWidget {
const PersonalFolder({ const PersonalFolder({
super.key, super.key,
required this.views, required this.views,
this.isHoverEnabled = true,
}); });
final List<ViewPB> views; final List<ViewPB> views;
final bool isHoverEnabled;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -60,6 +63,7 @@ class PersonalFolder extends StatelessWidget {
}, },
onTertiarySelected: (view) => onTertiarySelected: (view) =>
context.read<TabsBloc>().openTab(view), context.read<TabsBloc>().openTab(view),
isHoverEnabled: isHoverEnabled,
), ),
), ),
], ],

View File

@ -1,3 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:appflowy/shared/feature_flags.dart'; import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart'; import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
@ -18,7 +22,6 @@ import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
show UserProfilePB; show UserProfilePB;
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.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_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
/// Home Sidebar is the left side bar of the home page. /// Home Sidebar is the left side bar of the home page.
@ -28,7 +31,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
/// - settings /// - settings
/// - scrollable document list /// - scrollable document list
/// - trash /// - trash
class HomeSideBar extends StatelessWidget { class HomeSideBar extends StatefulWidget {
const HomeSideBar({ const HomeSideBar({
super.key, super.key,
required this.userProfile, required this.userProfile,
@ -39,6 +42,43 @@ class HomeSideBar extends StatelessWidget {
final WorkspaceSettingPB workspaceSetting; final WorkspaceSettingPB workspaceSetting;
@override
State<HomeSideBar> createState() => _HomeSideBarState();
}
class _HomeSideBarState extends State<HomeSideBar> {
final _scrollController = ScrollController();
Timer? _srollDebounce;
bool isScrolling = false;
@override
void initState() {
super.initState();
_scrollController.addListener(_onScrollChanged);
}
void _onScrollChanged() {
setState(() => isScrolling = true);
_srollDebounce?.cancel();
_srollDebounce =
Timer(const Duration(milliseconds: 300), _setScrollStopped);
}
void _setScrollStopped() {
if (mounted) {
setState(() => isScrolling = false);
}
}
@override
void dispose() {
_srollDebounce?.cancel();
_scrollController.removeListener(_onScrollChanged);
_scrollController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return MultiBlocProvider(
@ -48,8 +88,8 @@ class HomeSideBar extends StatelessWidget {
), ),
BlocProvider( BlocProvider(
create: (_) => MenuBloc( create: (_) => MenuBloc(
user: userProfile, user: widget.userProfile,
workspaceId: workspaceSetting.workspaceId, workspaceId: widget.workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()), )..add(const MenuEvent.initial()),
), ),
], ],
@ -108,8 +148,14 @@ class HomeSideBar extends StatelessWidget {
Padding( Padding(
padding: menuHorizontalInset, padding: menuHorizontalInset,
child: FeatureFlag.collaborativeWorkspace.isOn child: FeatureFlag.collaborativeWorkspace.isOn
? SidebarWorkspace(userProfile: userProfile, views: views) ? SidebarWorkspace(
: SidebarUser(userProfile: userProfile, views: views), userProfile: widget.userProfile,
views: views,
)
: SidebarUser(
userProfile: widget.userProfile,
views: views,
),
), ),
const VSpace(20), const VSpace(20),
@ -118,9 +164,12 @@ class HomeSideBar extends StatelessWidget {
child: Padding( child: Padding(
padding: menuHorizontalInset, padding: menuHorizontalInset,
child: SingleChildScrollView( child: SingleChildScrollView(
controller: _scrollController,
physics: const ClampingScrollPhysics(),
child: SidebarFolder( child: SidebarFolder(
views: views, views: views,
favoriteViews: favoriteViews, favoriteViews: favoriteViews,
isHoverEnabled: !isScrolling,
), ),
), ),
), ),

View File

@ -1,20 +1,23 @@
import 'package:flutter/material.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart'; import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/folder/favorite_folder.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/folder/favorite_folder.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/folder/personal_folder.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/folder/personal_folder.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
class SidebarFolder extends StatelessWidget { class SidebarFolder extends StatelessWidget {
const SidebarFolder({ const SidebarFolder({
super.key, super.key,
required this.views, required this.views,
required this.favoriteViews, required this.favoriteViews,
this.isHoverEnabled = true,
}); });
final List<ViewPB> views; final List<ViewPB> views;
final List<ViewPB> favoriteViews; final List<ViewPB> favoriteViews;
final bool isHoverEnabled;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -38,7 +41,7 @@ class SidebarFolder extends StatelessWidget {
const VSpace(10), const VSpace(10),
], ],
// personal // personal
PersonalFolder(views: views), PersonalFolder(views: views, isHoverEnabled: isHoverEnabled),
], ],
); );
}, },

View File

@ -42,6 +42,7 @@ class ViewItem extends StatelessWidget {
this.isDraggable = true, this.isDraggable = true,
required this.isFeedback, required this.isFeedback,
this.height = 28.0, this.height = 28.0,
this.isHoverEnabled = true,
}); });
final ViewPB view; final ViewPB view;
@ -75,6 +76,8 @@ class ViewItem extends StatelessWidget {
final double height; final double height;
final bool isHoverEnabled;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
@ -101,6 +104,7 @@ class ViewItem extends StatelessWidget {
isDraggable: isDraggable, isDraggable: isDraggable,
isFeedback: isFeedback, isFeedback: isFeedback,
height: height, height: height,
isHoverEnabled: isHoverEnabled,
); );
}, },
), ),
@ -127,6 +131,7 @@ class InnerViewItem extends StatelessWidget {
this.isFirstChild = false, this.isFirstChild = false,
required this.isFeedback, required this.isFeedback,
required this.height, required this.height,
this.isHoverEnabled = true,
}); });
final ViewPB view; final ViewPB view;
@ -148,6 +153,8 @@ class InnerViewItem extends StatelessWidget {
final ViewItemOnSelected? onTertiarySelected; final ViewItemOnSelected? onTertiarySelected;
final double height; final double height;
final bool isHoverEnabled;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget child = SingleInnerViewItem( Widget child = SingleInnerViewItem(
@ -264,6 +271,7 @@ class SingleInnerViewItem extends StatefulWidget {
this.onTertiarySelected, this.onTertiarySelected,
required this.isFeedback, required this.isFeedback,
required this.height, required this.height,
this.isHoverEnabled = true,
}); });
final ViewPB view; final ViewPB view;
@ -282,6 +290,8 @@ class SingleInnerViewItem extends StatefulWidget {
final FolderCategoryType categoryType; final FolderCategoryType categoryType;
final double height; final double height;
final bool isHoverEnabled;
@override @override
State<SingleInnerViewItem> createState() => _SingleInnerViewItemState(); State<SingleInnerViewItem> createState() => _SingleInnerViewItemState();
} }
@ -292,13 +302,16 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (widget.isFeedback) {
return _buildViewItem(false);
}
final isSelected = final isSelected =
getIt<MenuSharedState>().latestOpenView?.id == widget.view.id; getIt<MenuSharedState>().latestOpenView?.id == widget.view.id;
if (widget.isFeedback || !widget.isHoverEnabled) {
return _buildViewItem(
false,
!widget.isHoverEnabled ? isSelected : false,
);
}
return FlowyHover( return FlowyHover(
style: HoverStyle( style: HoverStyle(
hoverColor: Theme.of(context).colorScheme.secondary, hoverColor: Theme.of(context).colorScheme.secondary,