1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-23 05:19:22 +00:00
comunicmobile/lib/ui/widgets/mobile_mode/mobile_appbar_widget.dart

295 lines
8.2 KiB
Dart
Raw Normal View History

import 'package:comunic/helpers/events_helper.dart';
import 'package:comunic/helpers/notifications_helper.dart';
import 'package:comunic/models/count_unread_notifications.dart';
2020-05-10 16:29:43 +00:00
import 'package:comunic/ui/routes/main_route/main_route.dart';
import 'package:comunic/ui/routes/main_route/page_info.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
2019-07-01 09:51:23 +00:00
import 'package:comunic/utils/intl_utils.dart';
2019-11-01 13:17:46 +00:00
import 'package:comunic/utils/ui_utils.dart';
2019-07-01 09:51:23 +00:00
import 'package:flutter/material.dart';
/// Navigation bar widget
///
/// @author Pierre HUBERT
typedef OnSelectMenuAction = void Function(BarCallbackActions?);
2019-07-01 09:51:23 +00:00
/// Callback actions
enum BarCallbackActions {
OPEN_NOTIFICATIONS,
2019-07-01 09:51:23 +00:00
OPEN_CONVERSATIONS,
OPEN_NEWEST_POSTS,
OPEN_FRIENDS,
OPEN_MY_PAGE,
2020-04-17 08:30:29 +00:00
OPEN_SEARCH_PAGE,
2020-04-15 10:04:19 +00:00
OPEN_GROUPS,
2020-05-12 16:40:07 +00:00
OPEN_SETTINGS,
2019-07-01 09:51:23 +00:00
ACTION_LOGOUT
}
2019-11-01 13:17:46 +00:00
Color _primaryColor() => darkTheme() ? Colors.black : Colors.blue;
2019-11-01 13:17:46 +00:00
Color _secondaryColor() => darkTheme() ? darkAccentColor : Colors.white;
2019-07-01 09:51:23 +00:00
/// Menu item information
class _MenuItem {
final String label;
final Widget icon;
final BarCallbackActions? action;
2019-07-01 09:51:23 +00:00
final bool isMenu;
final PageType? pageType;
2019-07-01 09:51:23 +00:00
2019-11-01 08:59:22 +00:00
const _MenuItem({
required this.label,
required this.icon,
required this.action,
required this.pageType,
2019-11-01 08:59:22 +00:00
this.isMenu = false,
2022-03-11 15:36:42 +00:00
}) : assert(isMenu || action != null),
2020-05-10 16:29:43 +00:00
assert(isMenu || pageType != null);
2019-07-01 09:51:23 +00:00
}
/// Item of action menu
class _ActionMenuItem {
final String label;
final BarCallbackActions action;
2022-03-11 15:36:42 +00:00
const _ActionMenuItem({required this.label, required this.action});
}
2019-07-01 09:51:23 +00:00
/// List of menu items to show
final _menuItems = <_MenuItem>[
_MenuItem(
label: tr("Notifications")!,
icon: Icon(Icons.notifications),
2020-05-10 16:29:43 +00:00
action: BarCallbackActions.OPEN_NOTIFICATIONS,
pageType: PageType.NOTIFICATIONS_PAGE),
2019-07-01 09:51:23 +00:00
_MenuItem(
label: tr("Conversations")!,
2019-07-01 09:51:23 +00:00
icon: Icon(Icons.comment),
2020-05-10 16:29:43 +00:00
action: BarCallbackActions.OPEN_CONVERSATIONS,
pageType: PageType.CONVERSATIONS_LIST_PAGE),
2019-07-01 09:51:23 +00:00
_MenuItem(
label: tr("Newest")!,
2019-07-01 09:51:23 +00:00
icon: Icon(Icons.refresh),
2020-05-10 16:29:43 +00:00
action: BarCallbackActions.OPEN_NEWEST_POSTS,
pageType: PageType.LATEST_POSTS_PAGE),
2019-07-01 09:51:23 +00:00
_MenuItem(
label: tr("Friends")!,
2019-07-01 09:51:23 +00:00
icon: Icon(Icons.group),
2020-05-10 16:29:43 +00:00
action: BarCallbackActions.OPEN_FRIENDS,
pageType: PageType.FRIENDS_LIST_PAGE),
2019-07-01 09:51:23 +00:00
_MenuItem(
label: tr("Menu")!,
2019-07-01 09:51:23 +00:00
icon: Icon(Icons.more_vert),
isMenu: true,
2020-05-10 16:29:43 +00:00
action: null,
pageType: null)
2019-07-01 09:51:23 +00:00
];
/// List of menu actions items
final _menuActionsItem = <_ActionMenuItem>[
_ActionMenuItem(
label: tr("My Page")!, action: BarCallbackActions.OPEN_MY_PAGE),
_ActionMenuItem(label: tr("Groups")!, action: BarCallbackActions.OPEN_GROUPS),
2020-04-17 08:30:29 +00:00
_ActionMenuItem(
label: tr("Search")!, action: BarCallbackActions.OPEN_SEARCH_PAGE),
2020-04-17 08:30:29 +00:00
_ActionMenuItem(
label: tr("Settings")!, action: BarCallbackActions.OPEN_SETTINGS),
_ActionMenuItem(
label: tr("Sign out")!, action: BarCallbackActions.ACTION_LOGOUT),
];
2019-07-01 09:51:23 +00:00
/// Public widget
2020-05-10 16:29:43 +00:00
class ComunicMobileAppBar extends StatefulWidget
implements PreferredSizeWidget {
final PageInfo currentPage;
const ComunicMobileAppBar({
Key? key,
required this.currentPage,
2022-03-11 15:36:42 +00:00
}) : super(key: key);
2019-07-01 09:51:23 +00:00
@override
2020-05-06 16:25:55 +00:00
_ComunicMobileAppBarState createState() => _ComunicMobileAppBarState();
@override
Size get preferredSize => Size.fromHeight(40);
}
2020-05-06 16:25:55 +00:00
class _ComunicMobileAppBarState extends SafeState<ComunicMobileAppBar> {
var _unreadNotifications =
2020-05-03 15:00:38 +00:00
CountUnreadNotifications(notifications: 0, conversations: 0);
@override
void initState() {
_refreshCountUnread();
super.initState();
// Listen to notifications number update
this.listenChangeState<NewNumberNotifsEvent>(
2020-05-03 15:00:38 +00:00
(d) => _unreadNotifications.notifications = d.newNum);
this.listenChangeState<NewNumberUnreadConversations>(
2020-05-03 15:00:38 +00:00
(d) => _unreadNotifications.conversations = d.newNum);
}
void _refreshCountUnread() async {
try {
final count = await NotificationsHelper().countUnread();
setState(() {
_unreadNotifications = count;
});
} catch (e, stack) {
print("Could not refresh the number of unread notifications: $e");
print(stack);
}
}
/// Get the number of unread notifications for the selected notice
int? getNumberUnread(BarCallbackActions? action) {
switch (action) {
case BarCallbackActions.OPEN_NOTIFICATIONS:
return _unreadNotifications.notifications;
case BarCallbackActions.OPEN_CONVERSATIONS:
return _unreadNotifications.conversations;
default:
return 0;
}
}
2019-07-01 09:51:23 +00:00
@override
Widget build(BuildContext context) {
return Material(
2019-11-01 13:17:46 +00:00
color: darkTheme() ? Colors.black : Colors.blue,
2019-07-01 09:51:23 +00:00
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: List.generate(
_menuItems.length,
2020-05-03 15:00:38 +00:00
(i) => _MenuItemWidget(
2019-11-01 08:59:22 +00:00
item: _menuItems[i],
2020-05-10 16:29:43 +00:00
onTap: _handleAction,
isSelected: _menuItems[i].pageType == widget.currentPage.type,
newNotice: getNumberUnread(_menuItems[i].action),
2019-11-01 08:59:22 +00:00
),
2019-07-01 09:51:23 +00:00
),
),
);
}
2020-05-10 16:29:43 +00:00
void _handleAction(BarCallbackActions? action) {
2020-05-10 16:29:43 +00:00
final controller = MainController.of(context);
switch (action) {
case BarCallbackActions.OPEN_NOTIFICATIONS:
controller!.openNotificationsPage();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.OPEN_CONVERSATIONS:
controller!.openConversationsPage();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.OPEN_NEWEST_POSTS:
controller!.openLatestPostsPage();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.OPEN_FRIENDS:
controller!.openFriendsList();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.OPEN_MY_PAGE:
controller!.openCurrentUserPage();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.OPEN_SEARCH_PAGE:
controller!.openSearchPage();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.OPEN_GROUPS:
controller!.openGroupsListPage();
2020-05-10 16:29:43 +00:00
break;
2020-05-12 16:40:07 +00:00
case BarCallbackActions.OPEN_SETTINGS:
controller!.openSettings();
2020-05-10 16:29:43 +00:00
break;
case BarCallbackActions.ACTION_LOGOUT:
controller!.requestLogout();
2020-05-10 16:29:43 +00:00
break;
2022-03-11 15:21:35 +00:00
default:
break;
2020-05-10 16:29:43 +00:00
}
}
2019-07-01 09:51:23 +00:00
}
/// The [Widget] part of a menu item
class _MenuItemWidget extends StatelessWidget {
final _MenuItem item;
final OnSelectMenuAction onTap;
final bool isSelected;
2020-04-17 11:29:00 +00:00
/// Notifications notice
final int? newNotice;
const _MenuItemWidget({
Key? key,
required this.item,
required this.onTap,
required this.isSelected,
this.newNotice = 0,
}) : super(key: key);
2019-07-01 09:51:23 +00:00
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
return Expanded(
child: Material(
2019-11-01 13:17:46 +00:00
color: isSelected ? _secondaryColor() : _primaryColor(),
2019-07-01 09:51:23 +00:00
child: !item.isMenu
? InkWell(
2020-05-03 15:00:38 +00:00
child: _buildIconContainer(),
onTap: () => onTap(item.action),
)
2019-07-01 09:51:23 +00:00
: _buildContextMenuPopupButton(),
),
);
}
Widget _buildIconContainer() {
return Row(
2019-07-01 09:51:23 +00:00
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
2019-07-01 09:51:23 +00:00
children: <Widget>[
2020-04-17 11:29:00 +00:00
Spacer(flex: 2),
2019-07-01 09:51:23 +00:00
IconTheme(
data: IconThemeData(
2019-11-01 13:17:46 +00:00
color: isSelected ? _primaryColor() : _secondaryColor()),
2019-07-01 09:51:23 +00:00
child: item.icon,
),
newNotice! > 0 ? Spacer() : Container(),
newNotice == 0
? Container()
: Material(
2020-05-03 15:00:38 +00:00
color: Colors.red,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Text(" $newNotice ",
style: TextStyle(color: Colors.white)),
),
borderRadius: BorderRadius.all(
Radius.circular(50.0),
)),
2020-04-17 11:29:00 +00:00
Spacer(flex: 2),
2019-07-01 09:51:23 +00:00
],
);
}
// Build context menu
Widget _buildContextMenuPopupButton() {
return PopupMenuButton<BarCallbackActions>(
child: _buildIconContainer(),
itemBuilder: (i) => _menuActionsItem
.map((f) => PopupMenuItem(
2020-05-03 15:00:38 +00:00
child: Text(f.label),
value: f.action,
))
.toList(),
2019-07-01 09:51:23 +00:00
onSelected: onTap,
);
}
}