Skip to content

Commit

Permalink
added swipe gesture on bottom nav bar to open drawer when in feed
Browse files Browse the repository at this point in the history
  • Loading branch information
hjiangsu committed Jun 27, 2023
1 parent 279a111 commit 3a67c95
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 127 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Removed custom-made lemmy library, and replaced lemmy library with https://github.com/liftoff-app/lemmy_api_client!
- This change will make it easier to work with future features, and also allows a chance for collaboration on a unified dart-based lemmy api
- Added ability to tap on images within comments/posts to zoom in
- Added swipe gesture on botton nav bar to open up drawer in Feed

### Changed
- Moved theming options into a separate section in settings
Expand Down
4 changes: 3 additions & 1 deletion lib/community/pages/community_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ const sortTypeItems = [
class CommunityPage extends StatefulWidget {
final int? communityId;
final String? communityName;
final GlobalKey<ScaffoldState>? scaffoldKey;

const CommunityPage({super.key, this.communityId, this.communityName});
const CommunityPage({super.key, this.communityId, this.communityName, this.scaffoldKey});

@override
State<CommunityPage> createState() => _CommunityPageState();
Expand Down Expand Up @@ -101,6 +102,7 @@ class _CommunityPageState extends State<CommunityPage> with AutomaticKeepAliveCl
},
builder: (context, state) {
return Scaffold(
key: widget.scaffoldKey,
appBar: AppBar(
title: Text(getCommunityName(state)),
centerTitle: false,
Expand Down
284 changes: 158 additions & 126 deletions lib/thunder/pages/thunder_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,104 +44,131 @@ class _ThunderState extends State<Thunder> {
super.dispose();
}

double _dragStartX = 0.0;

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

void _handleDragStart(DragStartDetails details) {
_dragStartX = details.globalPosition.dx;
}

void _handleDragUpdate(DragUpdateDetails details) {
final currentPosition = details.globalPosition.dx;
final delta = currentPosition - _dragStartX;
if (delta > 0 && selectedPageIndex == 0) {
_feedScaffoldKey.currentState?.openDrawer();
} else if (delta < 0 && selectedPageIndex == 0) {
_feedScaffoldKey.currentState?.closeDrawer();
}
}

void _handleDragEnd(DragEndDetails details) {
_dragStartX = 0.0;
}

@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (context) => ThunderBloc()),
BlocProvider(create: (context) => InboxBloc()),
],
child: BlocBuilder<ThunderBloc, ThunderState>(
builder: (context, thunderBlocState) {
FlutterNativeSplash.remove();
child: WillPopScope(
onWillPop: () async {
return false; // Disable back button press
},
child: BlocBuilder<ThunderBloc, ThunderState>(
builder: (context, thunderBlocState) {
FlutterNativeSplash.remove();

switch (thunderBlocState.status) {
case ThunderStatus.initial:
context.read<ThunderBloc>().add(InitializeAppEvent());
return const Center(child: CircularProgressIndicator());
case ThunderStatus.loading:
return const Center(child: CircularProgressIndicator());
case ThunderStatus.refreshing:
case ThunderStatus.success:
return Scaffold(
bottomNavigationBar: _getScaffoldBottomNavigationBar(context),
body: MultiBlocProvider(
providers: [
BlocProvider<AuthBloc>(create: (context) => AuthBloc()),
BlocProvider<AccountBloc>(create: (context) => AccountBloc()),
],
child: BlocConsumer<AuthBloc, AuthState>(
listenWhen: (AuthState previous, AuthState current) {
if (previous.account == null && current.account != null) return true;
return false;
},
listener: (context, state) {
context.read<AccountBloc>().add(GetAccountInformation());
context.read<InboxBloc>().add(const GetInboxEvent());
},
builder: (context, state) {
switch (state.status) {
case AuthStatus.initial:
context.read<AuthBloc>().add(CheckAuth());
return const Center(child: CircularProgressIndicator());
case AuthStatus.loading:
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() => selectedPageIndex = 0));
return const Center(child: CircularProgressIndicator());
case AuthStatus.success:
Version? version = thunderBlocState.version;
bool showInAppUpdateNotification = thunderBlocState.preferences?.getBool('setting_notifications_show_inapp_update') ?? true;
bool? enableSentryErrorTracking = thunderBlocState.preferences?.getBool('setting_error_tracking_enable_sentry');
switch (thunderBlocState.status) {
case ThunderStatus.initial:
context.read<ThunderBloc>().add(InitializeAppEvent());
return const Center(child: CircularProgressIndicator());
case ThunderStatus.loading:
return const Center(child: CircularProgressIndicator());
case ThunderStatus.refreshing:
case ThunderStatus.success:
return Scaffold(
bottomNavigationBar: _getScaffoldBottomNavigationBar(context),
body: MultiBlocProvider(
providers: [
BlocProvider<AuthBloc>(create: (context) => AuthBloc()),
BlocProvider<AccountBloc>(create: (context) => AccountBloc()),
],
child: BlocConsumer<AuthBloc, AuthState>(
listenWhen: (AuthState previous, AuthState current) {
if (previous.account == null && current.account != null) return true;
return false;
},
listener: (context, state) {
context.read<AccountBloc>().add(GetAccountInformation());
context.read<InboxBloc>().add(const GetInboxEvent());
},
builder: (context, state) {
switch (state.status) {
case AuthStatus.initial:
context.read<AuthBloc>().add(CheckAuth());
return const Center(child: CircularProgressIndicator());
case AuthStatus.loading:
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() => selectedPageIndex = 0));
return const Center(child: CircularProgressIndicator());
case AuthStatus.success:
Version? version = thunderBlocState.version;
bool showInAppUpdateNotification = thunderBlocState.preferences?.getBool('setting_notifications_show_inapp_update') ?? true;
bool? enableSentryErrorTracking = thunderBlocState.preferences?.getBool('setting_error_tracking_enable_sentry');

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

setState(() => hasShownUpdateDialog = true);
});
}
setState(() => hasShownUpdateDialog = true);
});
}

// Ask user if they want to opt-in to Sentry for the first time (based on if setting_error_tracking_enable_sentry is null)
if (enableSentryErrorTracking == null && hasShownSentryDialog == false) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showSentryNotification(context);
setState(() => hasShownSentryDialog = true);
});
}
// Ask user if they want to opt-in to Sentry for the first time (based on if setting_error_tracking_enable_sentry is null)
if (enableSentryErrorTracking == null && hasShownSentryDialog == false) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showSentryNotification(context);
setState(() => hasShownSentryDialog = true);
});
}

return PageView(
controller: pageController,
onPageChanged: (index) => setState(() => selectedPageIndex = index),
physics: const NeverScrollableScrollPhysics(),
children: <Widget>[
const CommunityPage(),
BlocProvider(
create: (context) => SearchBloc(),
child: const SearchPage(),
),
const AccountPage(),
const InboxPage(),
SettingsPage(),
],
);
case AuthStatus.failure:
return ErrorMessage(
message: state.errorMessage,
action: () => {context.read<AuthBloc>().add(CheckAuth())},
actionText: 'Refresh Content',
);
}
},
return PageView(
controller: pageController,
onPageChanged: (index) => setState(() => selectedPageIndex = index),
physics: const NeverScrollableScrollPhysics(),
children: <Widget>[
CommunityPage(scaffoldKey: _feedScaffoldKey),
BlocProvider(
create: (context) => SearchBloc(),
child: const SearchPage(),
),
const AccountPage(),
const InboxPage(),
SettingsPage(),
],
);
case AuthStatus.failure:
return ErrorMessage(
message: state.errorMessage,
action: () => {context.read<AuthBloc>().add(CheckAuth())},
actionText: 'Refresh Content',
);
}
},
),
),
),
);
case ThunderStatus.failure:
return ErrorMessage(
message: thunderBlocState.errorMessage,
action: () => {context.read<AuthBloc>().add(CheckAuth())},
actionText: 'Refresh Content',
);
}
},
);
case ThunderStatus.failure:
return ErrorMessage(
message: thunderBlocState.errorMessage,
action: () => {context.read<AuthBloc>().add(CheckAuth())},
actionText: 'Refresh Content',
);
}
},
),
),
);
}
Expand All @@ -155,48 +182,53 @@ class _ThunderState extends State<Thunder> {
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
child: BottomNavigationBar(
currentIndex: selectedPageIndex,
showSelectedLabels: false,
showUnselectedLabels: false,
selectedItemColor: theme.colorScheme.primary,
type: BottomNavigationBarType.fixed,
unselectedFontSize: 20.0,
selectedFontSize: 20.0,
elevation: 1,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard_rounded),
label: 'Feed',
),
BottomNavigationBarItem(
icon: Icon(Icons.search_rounded),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_rounded),
label: 'Account',
),
BottomNavigationBarItem(
icon: Icon(Icons.inbox_rounded),
label: 'Inbox',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings_rounded),
label: 'Settings',
),
],
onTap: (index) {
setState(() {
selectedPageIndex = index;
pageController.animateToPage(index, duration: const Duration(milliseconds: 500), curve: Curves.ease);
});
child: GestureDetector(
onHorizontalDragStart: _handleDragStart,
onHorizontalDragUpdate: _handleDragUpdate,
onHorizontalDragEnd: _handleDragEnd,
child: BottomNavigationBar(
currentIndex: selectedPageIndex,
showSelectedLabels: false,
showUnselectedLabels: false,
selectedItemColor: theme.colorScheme.primary,
type: BottomNavigationBarType.fixed,
unselectedFontSize: 20.0,
selectedFontSize: 20.0,
elevation: 1,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard_rounded),
label: 'Feed',
),
BottomNavigationBarItem(
icon: Icon(Icons.search_rounded),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_rounded),
label: 'Account',
),
BottomNavigationBarItem(
icon: Icon(Icons.inbox_rounded),
label: 'Inbox',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings_rounded),
label: 'Settings',
),
],
onTap: (index) {
setState(() {
selectedPageIndex = index;
pageController.animateToPage(index, duration: const Duration(milliseconds: 500), curve: Curves.ease);
});

// @todo Change this from integer to enum or some other type
if (index == 3) {
context.read<InboxBloc>().add(const GetInboxEvent());
}
},
// @todo Change this from integer to enum or some other type
if (index == 3) {
context.read<InboxBloc>().add(const GetInboxEvent());
}
},
),
),
);
}
Expand Down

0 comments on commit 3a67c95

Please sign in to comment.