mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: stop hover when scrolling (#4801)
This commit is contained in:
parent
2af93a9bcb
commit
ba965caa8f
@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -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),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user