293 lines
9.4 KiB
Dart
293 lines
9.4 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:get_it_mixin/get_it_mixin.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:badges/badges.dart' as badges;
|
|
import 'package:hive_flutter/hive_flutter.dart';
|
|
|
|
import '/database/box_type.dart';
|
|
import '/database/hive_database.dart';
|
|
import '/models/apply_list_model.dart';
|
|
import '/models/init_get_it.dart';
|
|
import '/models/route_state_model.dart';
|
|
import '/models/user_model.dart';
|
|
import '/notification_api.dart';
|
|
|
|
class HomeScreenWithNavBar extends StatefulWidget
|
|
with GetItStatefulWidgetMixin {
|
|
HomeScreenWithNavBar({
|
|
super.key,
|
|
required this.notificationAppLaunchDetails,
|
|
required this.initIndex,
|
|
required this.child,
|
|
this.listController,
|
|
});
|
|
|
|
final int initIndex;
|
|
final Widget child;
|
|
// used to get back to top
|
|
final ScrollController? listController;
|
|
|
|
final NotificationAppLaunchDetails? notificationAppLaunchDetails;
|
|
|
|
bool get didNotificationLanunchApp =>
|
|
notificationAppLaunchDetails?.didNotificationLaunchApp ?? false;
|
|
|
|
@override
|
|
State<HomeScreenWithNavBar> createState() => _HomeScreenWithNavBarState();
|
|
}
|
|
|
|
class _HomeScreenWithNavBarState extends State<HomeScreenWithNavBar>
|
|
with GetItStateMixin, WidgetsBindingObserver {
|
|
Future<bool> _openBox() async {
|
|
if (!getIt.get<UserProfile>().isInitialised) {
|
|
await HiveDatabase.init();
|
|
}
|
|
return Future(() => true);
|
|
}
|
|
|
|
// ignore: unused_field
|
|
bool _notificationsEnabled = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
WidgetsBinding.instance.addObserver(this);
|
|
_isAndroidPermissionGranted();
|
|
_requestPermissions();
|
|
_configureDidReceiveLocalNotificationSubject();
|
|
_configureSelectNotificationSubject();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
NotificationAPI.didReceiveNotificationStream.close();
|
|
NotificationAPI.selectNotificationStream.close();
|
|
}
|
|
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
super.didChangeAppLifecycleState(state);
|
|
switch (state) {
|
|
case AppLifecycleState.resumed:
|
|
print('应用进入前台==================');
|
|
NotificationAPI.messages.clear();
|
|
NotificationAPI.flutterLocalNotificationsPlugin.cancelAll();
|
|
getIt.get<RouteState>().changeVisibility(true);
|
|
break;
|
|
case AppLifecycleState.inactive:
|
|
print('应用处于闲置状态,切换到后台触发====================');
|
|
getIt.get<RouteState>().changeVisibility(false);
|
|
break;
|
|
case AppLifecycleState.paused:
|
|
print('应用处于不可见状态========================');
|
|
getIt.get<RouteState>().changeVisibility(false);
|
|
break;
|
|
case AppLifecycleState.detached:
|
|
print('当前页面即将退出===================');
|
|
getIt.get<RouteState>().changeVisibility(false);
|
|
break;
|
|
case AppLifecycleState.hidden:
|
|
print("当前应用被隐藏=======================");
|
|
}
|
|
}
|
|
|
|
Future<void> _isAndroidPermissionGranted() async {
|
|
if (Platform.isAndroid) {
|
|
final bool granted = await NotificationAPI.flutterLocalNotificationsPlugin
|
|
.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>()
|
|
?.areNotificationsEnabled() ??
|
|
false;
|
|
|
|
setState(() {
|
|
_notificationsEnabled = granted;
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> _requestPermissions() async {
|
|
if (Platform.isIOS || Platform.isMacOS) {
|
|
await NotificationAPI.flutterLocalNotificationsPlugin
|
|
.resolvePlatformSpecificImplementation<
|
|
IOSFlutterLocalNotificationsPlugin>()
|
|
?.requestPermissions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
await NotificationAPI.flutterLocalNotificationsPlugin
|
|
.resolvePlatformSpecificImplementation<
|
|
MacOSFlutterLocalNotificationsPlugin>()
|
|
?.requestPermissions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
);
|
|
} else if (Platform.isAndroid) {
|
|
final AndroidFlutterLocalNotificationsPlugin? androidImplementation =
|
|
NotificationAPI.flutterLocalNotificationsPlugin
|
|
.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>();
|
|
|
|
final bool? grantedNotificationPermission =
|
|
await androidImplementation?.requestNotificationsPermission();
|
|
setState(() {
|
|
_notificationsEnabled = grantedNotificationPermission ?? false;
|
|
});
|
|
}
|
|
}
|
|
|
|
void _configureDidReceiveLocalNotificationSubject() {
|
|
NotificationAPI.didReceiveNotificationStream.stream.listen(
|
|
(ReceivedNotification? receivedNotification) async {
|
|
await showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) => AlertDialog(
|
|
title: receivedNotification!.title != null
|
|
? Text(receivedNotification.title!)
|
|
: null,
|
|
content: receivedNotification.body != null
|
|
? Text(receivedNotification.body!)
|
|
: null,
|
|
actions: <Widget>[
|
|
TextButton(
|
|
onPressed: () {},
|
|
child: const Text('ok'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _configureSelectNotificationSubject() {
|
|
// this listener will be call after taps a notification
|
|
NotificationAPI.selectNotificationStream.stream
|
|
.listen((String? payload) async {
|
|
NotificationAPI.messages.clear();
|
|
if (payload != null) {
|
|
Map<String, dynamic> payloadData = json.decode(payload);
|
|
switch (payloadData['event']) {
|
|
case 'friend-message':
|
|
String friendId = payloadData['friendId']!;
|
|
context.goNamed(
|
|
'Message',
|
|
queryParameters: {
|
|
'friendId': friendId,
|
|
'type': '0',
|
|
},
|
|
);
|
|
break;
|
|
case 'group-chat-message':
|
|
String groupChatId = payloadData['groupChatId']!;
|
|
context.goNamed(
|
|
'Message',
|
|
queryParameters: {
|
|
'groupChatId': groupChatId,
|
|
'type': '1',
|
|
},
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
int applyCount = watchOnly((ApplyList applyList) => applyList.count);
|
|
|
|
return Scaffold(
|
|
body: widget.child,
|
|
bottomNavigationBar: BottomNavigationBar(
|
|
backgroundColor:
|
|
Theme.of(context).bottomNavigationBarTheme.backgroundColor,
|
|
items: [
|
|
BottomNavigationBarItem(
|
|
icon: FutureBuilder(
|
|
future: _openBox(),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasData) {
|
|
return ValueListenableBuilder(
|
|
valueListenable:
|
|
Hive.box<ChatSetting>('chat_setting').listenable(),
|
|
builder: (context, chatSettingBox, _) {
|
|
final values = chatSettingBox.values;
|
|
int unreadCount = 0;
|
|
for (var value in values) {
|
|
unreadCount += value.unreadCount;
|
|
}
|
|
return badges.Badge(
|
|
badgeContent: Text(
|
|
unreadCount > 99 ? '$unreadCount+' : '$unreadCount',
|
|
style: TextStyle(
|
|
fontSize: 11,
|
|
color: Theme.of(context).colorScheme.inversePrimary,
|
|
),
|
|
),
|
|
position:
|
|
badges.BadgePosition.topEnd(top: -8, end: -12),
|
|
showBadge: unreadCount > 0,
|
|
child: const Icon(Icons.message),
|
|
);
|
|
},
|
|
);
|
|
} else {
|
|
return const Icon(Icons.message);
|
|
}
|
|
},
|
|
),
|
|
label: '消息',
|
|
),
|
|
BottomNavigationBarItem(
|
|
icon: badges.Badge(
|
|
badgeContent: Text(
|
|
applyCount > 99 ? '$applyCount+' : '$applyCount',
|
|
style: TextStyle(
|
|
fontSize: 11,
|
|
color: Theme.of(context).colorScheme.inversePrimary,
|
|
),
|
|
),
|
|
position: badges.BadgePosition.topStart(top: -8, start: -12),
|
|
showBadge: applyCount > 0,
|
|
child: const Icon(Icons.contacts),
|
|
),
|
|
label: '通讯录',
|
|
),
|
|
const BottomNavigationBarItem(
|
|
icon: Icon(Icons.star),
|
|
label: '更多',
|
|
),
|
|
],
|
|
onTap: (int index) => _onItemTapped(index, context),
|
|
currentIndex: widget.initIndex,
|
|
),
|
|
);
|
|
}
|
|
|
|
void _onItemTapped(int index, BuildContext context) {
|
|
switch (index) {
|
|
case 0:
|
|
NotificationAPI.messages.clear();
|
|
NotificationAPI.flutterLocalNotificationsPlugin.cancelAll();
|
|
GoRouter.of(context).go('/chat');
|
|
break;
|
|
|
|
case 1:
|
|
GoRouter.of(context).go('/contact');
|
|
break;
|
|
|
|
case 2:
|
|
GoRouter.of(context).go('/more');
|
|
break;
|
|
}
|
|
}
|
|
}
|