✨ Account status on sidebar
This commit is contained in:
parent
3b1b6ec8d6
commit
48b76ed574
@ -19,7 +19,6 @@ import 'package:solian/providers/content/realm.dart';
|
||||
import 'package:solian/providers/friend.dart';
|
||||
import 'package:solian/providers/account_status.dart';
|
||||
import 'package:solian/router.dart';
|
||||
import 'package:solian/shells/root_shell.dart';
|
||||
import 'package:solian/shells/system_shell.dart';
|
||||
import 'package:solian/theme.dart';
|
||||
import 'package:solian/translations.dart';
|
||||
@ -88,10 +87,8 @@ class SolianApp extends StatelessWidget {
|
||||
onInit: () => _initializeProviders(context),
|
||||
builder: (context, child) {
|
||||
return SystemShell(
|
||||
child: RootShell(
|
||||
child: ScaffoldMessenger(
|
||||
child: child ?? const SizedBox(),
|
||||
),
|
||||
child: ScaffoldMessenger(
|
||||
child: child ?? const SizedBox(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -94,9 +94,10 @@ class StatusProvider extends GetConnect {
|
||||
return resp;
|
||||
}
|
||||
|
||||
static (Widget, String) determineStatus(AccountStatus status,
|
||||
static (Widget, Color, String) determineStatus(AccountStatus status,
|
||||
{double size = 14}) {
|
||||
Widget icon;
|
||||
Color color;
|
||||
String? text;
|
||||
|
||||
if (!presetStatuses.keys.contains(status.status?.type)) {
|
||||
@ -104,15 +105,18 @@ class StatusProvider extends GetConnect {
|
||||
}
|
||||
|
||||
if (status.isDisturbable && status.isOnline) {
|
||||
icon = Icon(Icons.circle, color: Colors.green, size: size);
|
||||
color = Colors.green;
|
||||
icon = Icon(Icons.circle, color: color, size: size);
|
||||
text ??= 'accountStatusOnline'.tr;
|
||||
} else if (!status.isDisturbable && status.isOnline) {
|
||||
icon = Icon(Icons.do_not_disturb_on, color: Colors.red, size: size);
|
||||
color = Colors.red;
|
||||
icon = Icon(Icons.do_not_disturb_on, color: color, size: size);
|
||||
text ??= 'accountStatusSilent'.tr;
|
||||
} else {
|
||||
icon = Icon(Icons.circle, color: Colors.grey, size: size);
|
||||
color = Colors.grey;
|
||||
icon = Icon(Icons.circle, color: color, size: size);
|
||||
text ??= 'accountStatusOffline'.tr;
|
||||
}
|
||||
return (icon, text);
|
||||
return (icon, color, text);
|
||||
}
|
||||
}
|
||||
|
@ -218,4 +218,10 @@ class AuthProvider extends GetConnect {
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
Future<Response?> getProfileWithCheck({noCache = false}) async {
|
||||
if (!await isAuthorized) return null;
|
||||
|
||||
return await getProfile(noCache: noCache);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import 'package:solian/screens/realms/realm_view.dart';
|
||||
import 'package:solian/screens/feed.dart';
|
||||
import 'package:solian/screens/posts/post_editor.dart';
|
||||
import 'package:solian/shells/basic_shell.dart';
|
||||
import 'package:solian/shells/root_shell.dart';
|
||||
import 'package:solian/shells/title_shell.dart';
|
||||
import 'package:solian/theme.dart';
|
||||
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
|
||||
@ -27,10 +28,18 @@ import 'package:solian/widgets/sidebar/empty_placeholder.dart';
|
||||
abstract class AppRouter {
|
||||
static GoRouter instance = GoRouter(
|
||||
routes: [
|
||||
_feedRoute,
|
||||
_chatRoute,
|
||||
_realmRoute,
|
||||
_accountRoute,
|
||||
ShellRoute(
|
||||
builder: (context, state, child) => RootShell(
|
||||
state: state,
|
||||
child: child,
|
||||
),
|
||||
routes: [
|
||||
_feedRoute,
|
||||
_chatRoute,
|
||||
_realmRoute,
|
||||
_accountRoute,
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:solian/theme.dart';
|
||||
import 'package:solian/widgets/navigation/app_navigation_drawer.dart';
|
||||
import 'package:solian/widgets/navigation/app_navigation_rail.dart';
|
||||
@ -9,10 +10,12 @@ class RootShell extends StatelessWidget {
|
||||
final bool showSidebar;
|
||||
final bool showNavigation;
|
||||
final bool? showBottomNavigation;
|
||||
final GoRouterState state;
|
||||
final Widget child;
|
||||
|
||||
const RootShell({
|
||||
super.key,
|
||||
required this.state,
|
||||
required this.child,
|
||||
this.showSidebar = true,
|
||||
this.showNavigation = true,
|
||||
@ -25,9 +28,14 @@ class RootShell extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final routeName = state.topRoute?.name;
|
||||
|
||||
return Scaffold(
|
||||
key: rootScaffoldKey,
|
||||
drawer: const AppNavigationDrawer(),
|
||||
drawer: AppNavigationDrawer(
|
||||
key: const ValueKey('navigation-drawer'),
|
||||
routeName: routeName,
|
||||
),
|
||||
body: SolianTheme.isLargeScreen(context)
|
||||
? Row(
|
||||
children: [
|
||||
|
@ -124,7 +124,7 @@ class AccountHeadingWidget extends StatelessWidget {
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(info.$2),
|
||||
Text(info.$3),
|
||||
if (!status.isOnline && status.lastSeenAt != null)
|
||||
Opacity(
|
||||
opacity: 0.75,
|
||||
|
@ -1,36 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:solian/router.dart';
|
||||
import 'package:solian/widgets/navigation/app_navigation.dart';
|
||||
|
||||
class AppNavigationBottomBar extends StatefulWidget {
|
||||
const AppNavigationBottomBar({super.key});
|
||||
|
||||
@override
|
||||
State<AppNavigationBottomBar> createState() => _AppNavigationBottomBarState();
|
||||
}
|
||||
|
||||
class _AppNavigationBottomBarState extends State<AppNavigationBottomBar> {
|
||||
int _selectedIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BottomNavigationBar(
|
||||
items: AppNavigation.destinations
|
||||
.map(
|
||||
(e) => BottomNavigationBarItem(
|
||||
icon: e.icon,
|
||||
label: e.label,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
type: BottomNavigationBarType.fixed,
|
||||
landscapeLayout: BottomNavigationBarLandscapeLayout.centered,
|
||||
currentIndex: _selectedIndex,
|
||||
showUnselectedLabels: false,
|
||||
onTap: (idx) {
|
||||
setState(() => _selectedIndex = idx);
|
||||
AppRouter.instance.goNamed(AppNavigation.destinations[idx].page);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -1,10 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:solian/models/account_status.dart';
|
||||
import 'package:solian/providers/account_status.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/router.dart';
|
||||
import 'package:solian/shells/root_shell.dart';
|
||||
import 'package:solian/widgets/account/account_avatar.dart';
|
||||
import 'package:solian/widgets/account/account_status_action.dart';
|
||||
import 'package:solian/widgets/navigation/app_navigation.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
|
||||
class AppNavigationDrawer extends StatefulWidget {
|
||||
const AppNavigationDrawer({super.key});
|
||||
final String? routeName;
|
||||
|
||||
const AppNavigationDrawer({super.key, this.routeName});
|
||||
|
||||
@override
|
||||
State<AppNavigationDrawer> createState() => _AppNavigationDrawerState();
|
||||
@ -12,9 +21,45 @@ class AppNavigationDrawer extends StatefulWidget {
|
||||
|
||||
class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
||||
int _selectedIndex = 0;
|
||||
AccountStatus? _accountStatus;
|
||||
|
||||
void getStatus() async {
|
||||
final StatusProvider provider = Get.find();
|
||||
|
||||
final resp = await provider.getCurrentStatus();
|
||||
final status = AccountStatus.fromJson(resp.body);
|
||||
|
||||
setState(() {
|
||||
_accountStatus = status;
|
||||
});
|
||||
}
|
||||
|
||||
void detectSelectedIndex() {
|
||||
if (widget.routeName == null) return;
|
||||
|
||||
final nameList = AppNavigation.destinations.map((x) => x.page).toList();
|
||||
final idx = nameList.indexOf(widget.routeName!);
|
||||
|
||||
_selectedIndex = idx != -1 ? idx : 0;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
detectSelectedIndex();
|
||||
getStatus();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
detectSelectedIndex();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AuthProvider auth = Get.find();
|
||||
|
||||
return NavigationDrawer(
|
||||
selectedIndex: _selectedIndex,
|
||||
onDestinationSelected: (idx) {
|
||||
@ -23,6 +68,68 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
||||
rootScaffoldKey.currentState!.closeDrawer();
|
||||
},
|
||||
children: [
|
||||
FutureBuilder(
|
||||
future: auth.getProfileWithCheck(),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData || snapshot.data == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text(snapshot.data!.body['nick']),
|
||||
subtitle: Builder(
|
||||
builder: (context) {
|
||||
if (_accountStatus == null) {
|
||||
return Text('loading'.tr);
|
||||
}
|
||||
final info = StatusProvider.determineStatus(
|
||||
_accountStatus!,
|
||||
);
|
||||
return Text(info.$3);
|
||||
},
|
||||
),
|
||||
leading: Builder(builder: (context) {
|
||||
final badgeColor = _accountStatus != null
|
||||
? StatusProvider.determineStatus(
|
||||
_accountStatus!,
|
||||
).$2
|
||||
: Colors.grey;
|
||||
|
||||
return badges.Badge(
|
||||
showBadge: _accountStatus != null,
|
||||
badgeStyle: badges.BadgeStyle(badgeColor: badgeColor),
|
||||
position: badges.BadgePosition.bottomEnd(
|
||||
bottom: 0,
|
||||
end: -2,
|
||||
),
|
||||
child: AccountAvatar(
|
||||
content: snapshot.data!.body['avatar'],
|
||||
),
|
||||
);
|
||||
}),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
context: context,
|
||||
builder: (context) => AccountStatusAction(
|
||||
currentStatus: _accountStatus!.status,
|
||||
),
|
||||
).then((val) {
|
||||
if (val == true) getStatus();
|
||||
});
|
||||
},
|
||||
),
|
||||
const Divider(thickness: 0.3, height: 1).paddingOnly(
|
||||
bottom: 16,
|
||||
top: 8,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
...AppNavigation.destinations.map(
|
||||
(e) => NavigationDrawerDestination(
|
||||
icon: e.icon,
|
||||
|
Loading…
Reference in New Issue
Block a user