Skip to content

Commit

Permalink
fixed issue where drawer icon does not trigger the drawer to open on …
Browse files Browse the repository at this point in the history
…the feed page
  • Loading branch information
hjiangsu committed Jan 8, 2024
1 parent 2684214 commit f4a8373
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 124 deletions.
18 changes: 14 additions & 4 deletions lib/feed/view/feed_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class FeedPage extends StatefulWidget {
this.communityName,
this.userId,
this.username,
this.scaffoldStateKey,
});

/// The type of feed to display.
Expand Down Expand Up @@ -80,6 +81,9 @@ class FeedPage extends StatefulWidget {
/// This is useful if we want to keep the user on the "same" page
final bool useGlobalFeedBloc;

/// The scaffold key which holds the drawer
final GlobalKey<ScaffoldState>? scaffoldStateKey;

@override
State<FeedPage> createState() => _FeedPageState();
}
Expand Down Expand Up @@ -123,7 +127,7 @@ class _FeedPageState extends State<FeedPage> with AutomaticKeepAliveClientMixin<

return BlocProvider.value(
value: bloc,
child: const FeedView(),
child: FeedView(scaffoldStateKey: widget.scaffoldStateKey),
);
}

Expand All @@ -139,13 +143,16 @@ class _FeedPageState extends State<FeedPage> with AutomaticKeepAliveClientMixin<
username: widget.username,
reset: true,
)),
child: const FeedView(),
child: FeedView(scaffoldStateKey: widget.scaffoldStateKey),
);
}
}

class FeedView extends StatefulWidget {
const FeedView({super.key});
const FeedView({super.key, this.scaffoldStateKey});

/// The scaffold key which holds the drawer
final GlobalKey<ScaffoldState>? scaffoldStateKey;

@override
State<FeedView> createState() => _FeedViewState();
Expand Down Expand Up @@ -291,7 +298,10 @@ class _FeedViewState extends State<FeedView> {
physics: showCommunitySidebar ? const NeverScrollableScrollPhysics() : null, // Disable scrolling on the feed page when the community sidebar is open
controller: _scrollController,
slivers: <Widget>[
FeedPageAppBar(showAppBarTitle: (state.feedType == FeedType.general && state.status != FeedStatus.initial) ? true : showAppBarTitle),
FeedPageAppBar(
showAppBarTitle: (state.feedType == FeedType.general && state.status != FeedStatus.initial) ? true : showAppBarTitle,
scaffoldStateKey: widget.scaffoldStateKey,
),
// Display loading indicator until the feed is fetched
if (state.status == FeedStatus.initial)
const SliverFillRemaining(
Expand Down
8 changes: 6 additions & 2 deletions lib/feed/widgets/feed_page_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ import 'package:thunder/shared/sort_picker.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';

class FeedPageAppBar extends StatelessWidget {
const FeedPageAppBar({super.key, this.showAppBarTitle = true});
const FeedPageAppBar({super.key, this.showAppBarTitle = true, this.scaffoldStateKey});

/// Whether to show the app bar title
final bool showAppBarTitle;

/// The scaffold key of the parent scaffold holding the drawer.
final GlobalKey<ScaffoldState>? scaffoldStateKey;

@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
Expand All @@ -50,7 +54,7 @@ class FeedPageAppBar extends StatelessWidget {
: Icon(Icons.menu, semanticLabel: MaterialLocalizations.of(context).openAppDrawerTooltip),
onPressed: () {
HapticFeedback.mediumImpact();
(Navigator.of(context).canPop() && feedBloc.state.feedType == FeedType.community) ? Navigator.of(context).maybePop() : Scaffold.of(context).openDrawer();
(Navigator.of(context).canPop() && feedBloc.state.feedType == FeedType.community) ? Navigator.of(context).maybePop() : scaffoldStateKey?.currentState?.openDrawer();
},
),
actions: feedState.status != FeedStatus.failureLoadingCommunity
Expand Down
247 changes: 129 additions & 118 deletions lib/thunder/pages/thunder_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class _ThunderState extends State<Thunder> {

bool reduceAnimations = false;

final GlobalKey<ScaffoldState> scaffoldStateKey = GlobalKey<ScaffoldState>();

final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();

late final StreamSubscription mediaIntentDataStreamSubscription;
Expand Down Expand Up @@ -404,129 +406,138 @@ class _ThunderState extends State<Thunder> {
// Update the variable so that it can be used in _handleBackButtonPress
_isFabOpen = thunderBlocState.isFabOpen;

return Scaffold(
return ScaffoldMessenger(
key: scaffoldMessengerKey,
drawer: selectedPageIndex == 0
? CommunityDrawer(
navigateToAccount: () {
Navigator.of(context).pop();

if (reduceAnimations) {
pageController.jumpToPage(2);
} else {
pageController.animateToPage(2, duration: const Duration(milliseconds: 500), curve: Curves.ease);
}
},
)
: null,
floatingActionButton: thunderBlocState.enableFeedsFab
? AnimatedOpacity(
opacity: selectedPageIndex == 0 ? 1.0 : 0.0,
duration: const Duration(milliseconds: 150),
curve: Curves.easeIn,
child: const FeedFAB(),
)
: null,
floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling,
bottomNavigationBar: CustomBottomNavigationBar(
selectedPageIndex: selectedPageIndex,
onPageChange: (int index) {
setState(() {
selectedPageIndex = index;

if (reduceAnimations) {
pageController.jumpToPage(index);
} else {
pageController.animateToPage(index, duration: const Duration(milliseconds: 500), curve: Curves.ease);
child: Scaffold(
key: scaffoldStateKey,
drawer: selectedPageIndex == 0
? CommunityDrawer(
navigateToAccount: () {
Navigator.of(context).pop();

if (reduceAnimations) {
pageController.jumpToPage(2);
} else {
pageController.animateToPage(2, duration: const Duration(milliseconds: 500), curve: Curves.ease);
}
},
)
: null,
floatingActionButton: thunderBlocState.enableFeedsFab
? AnimatedOpacity(
opacity: selectedPageIndex == 0 ? 1.0 : 0.0,
duration: const Duration(milliseconds: 150),
curve: Curves.easeIn,
child: const FeedFAB(),
)
: null,
floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling,
bottomNavigationBar: CustomBottomNavigationBar(
selectedPageIndex: selectedPageIndex,
onPageChange: (int index) {
setState(() {
selectedPageIndex = index;

if (reduceAnimations) {
pageController.jumpToPage(index);
} else {
pageController.animateToPage(index, duration: const Duration(milliseconds: 500), curve: Curves.ease);
}
});
},
),
body: BlocConsumer<AuthBloc, AuthState>(
listenWhen: (AuthState previous, AuthState current) {
if (previous.isLoggedIn != current.isLoggedIn || previous.status == AuthStatus.initial) return true;
return false;
},
buildWhen: (previous, current) => current.status != AuthStatus.failure && current.status != AuthStatus.loading,
listener: (context, state) {
context.read<AccountBloc>().add(GetAccountInformation());

// Add a bit of artificial delay to allow preferences to set the proper active profile
Future.delayed(const Duration(milliseconds: 500), () => context.read<InboxBloc>().add(const GetInboxEvent(reset: true)));
if (context.read<FeedBloc>().state.status != FeedStatus.initial) {
context.read<FeedBloc>().add(
FeedFetchedEvent(
feedType: FeedType.general,
postListingType: thunderBlocState.defaultListingType,
sortType: thunderBlocState.defaultSortType,
reset: true,
),
);
}
});
},
),
body: BlocConsumer<AuthBloc, AuthState>(
listenWhen: (AuthState previous, AuthState current) {
if (previous.isLoggedIn != current.isLoggedIn || previous.status == AuthStatus.initial) return true;
return false;
},
buildWhen: (previous, current) => current.status != AuthStatus.failure && current.status != AuthStatus.loading,
listener: (context, state) {
context.read<AccountBloc>().add(GetAccountInformation());

// Add a bit of artificial delay to allow preferences to set the proper active profile
Future.delayed(const Duration(milliseconds: 500), () => context.read<InboxBloc>().add(const GetInboxEvent(reset: true)));
if (context.read<FeedBloc>().state.status != FeedStatus.initial) {
context.read<FeedBloc>().add(
FeedFetchedEvent(
feedType: FeedType.general,
postListingType: thunderBlocState.defaultListingType,
sortType: thunderBlocState.defaultSortType,
reset: true,
},
builder: (context, state) {
switch (state.status) {
case AuthStatus.initial:
context.read<AuthBloc>().add(CheckAuth());
return Scaffold(
appBar: AppBar(),
body: Center(
child: Container(),
),
);
}
},
builder: (context, state) {
switch (state.status) {
case AuthStatus.initial:
context.read<AuthBloc>().add(CheckAuth());
return Scaffold(
appBar: AppBar(),
body: Center(
child: Container(),
),
);
case AuthStatus.success:
Version? version = thunderBlocState.version;
bool showInAppUpdateNotification = thunderBlocState.showInAppUpdateNotification;

if (version?.hasUpdate == true && hasShownUpdateDialog == false && showInAppUpdateNotification == true) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showUpdateNotification(context, version);
setState(() => hasShownUpdateDialog = true);
});
}
case AuthStatus.success:
Version? version = thunderBlocState.version;
bool showInAppUpdateNotification = thunderBlocState.showInAppUpdateNotification;

if (version?.hasUpdate == true && hasShownUpdateDialog == false && showInAppUpdateNotification == true) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showUpdateNotification(context, version);
setState(() => hasShownUpdateDialog = true);
});
}

return PageView(
controller: pageController,
onPageChanged: (index) => setState(() => selectedPageIndex = index),
physics: const NeverScrollableScrollPhysics(),
children: <Widget>[
Stack(
children: [
FeedPage(useGlobalFeedBloc: true, feedType: FeedType.general, postListingType: thunderBlocState.defaultListingType, sortType: thunderBlocState.defaultSortType),
AnimatedOpacity(
opacity: _isFabOpen ? 1.0 : 0.0,
duration: const Duration(milliseconds: 150),
child: _isFabOpen
? ModalBarrier(
color: theme.colorScheme.background.withOpacity(0.95),
dismissible: true,
onDismiss: () => context.read<ThunderBloc>().add(const OnFabToggle(false)),
)
: null,
),
],
),
const SearchPage(),
const AccountPage(),
const InboxPage(),
SettingsPage(),
],
);

// Should never hit these, they're handled by the login page
case AuthStatus.failure:
case AuthStatus.loading:
return Container();
case AuthStatus.failureCheckingInstance:
showSnackbar(context, state.errorMessage ?? AppLocalizations.of(context)!.missingErrorMessage);
return ErrorMessage(
title: AppLocalizations.of(context)!.unableToLoadInstance(LemmyClient.instance.lemmyApiV3.host),
message: AppLocalizations.of(context)!.internetOrInstanceIssues,
actionText: AppLocalizations.of(context)!.accountSettings,
action: () => showProfileModalSheet(context),
);
}
},
return PageView(
controller: pageController,
onPageChanged: (index) => setState(() => selectedPageIndex = index),
physics: const NeverScrollableScrollPhysics(),
children: <Widget>[
Stack(
children: [
FeedPage(
useGlobalFeedBloc: true,
feedType: FeedType.general,
postListingType: thunderBlocState.defaultListingType,
sortType: thunderBlocState.defaultSortType,
scaffoldStateKey: scaffoldStateKey,
),
AnimatedOpacity(
opacity: _isFabOpen ? 1.0 : 0.0,
duration: const Duration(milliseconds: 150),
child: _isFabOpen
? ModalBarrier(
color: theme.colorScheme.background.withOpacity(0.95),
dismissible: true,
onDismiss: () => context.read<ThunderBloc>().add(const OnFabToggle(false)),
)
: null,
),
],
),
const SearchPage(),
const AccountPage(),
const InboxPage(),
SettingsPage(),
],
);

// Should never hit these, they're handled by the login page
case AuthStatus.failure:
case AuthStatus.loading:
return Container();
case AuthStatus.failureCheckingInstance:
showSnackbar(context, state.errorMessage ?? AppLocalizations.of(context)!.missingErrorMessage);
return ErrorMessage(
title: AppLocalizations.of(context)!.unableToLoadInstance(LemmyClient.instance.lemmyApiV3.host),
message: AppLocalizations.of(context)!.internetOrInstanceIssues,
actionText: AppLocalizations.of(context)!.accountSettings,
action: () => showProfileModalSheet(context),
);
}
},
),
),
);
case ThunderStatus.failure:
Expand Down

0 comments on commit f4a8373

Please sign in to comment.