📱 Dashboard supports mobile

This commit is contained in:
2025-12-20 22:19:36 +08:00
parent 53137aed3f
commit 18c81503f1

View File

@@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/chat/chat_room.dart'; import 'package:island/pods/chat/chat_room.dart';
import 'package:island/pods/event_calendar.dart'; import 'package:island/pods/event_calendar.dart';
import 'package:island/screens/chat/chat.dart'; import 'package:island/screens/chat/chat.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/account/fortune_graph.dart'; import 'package:island/widgets/account/fortune_graph.dart';
import 'package:island/widgets/account/friends_overview.dart'; import 'package:island/widgets/account/friends_overview.dart';
import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/app_scaffold.dart';
@@ -36,10 +37,15 @@ class DashboardGrid extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final isWide = isWideScreen(context);
return Container( return Container(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: math.min(640, MediaQuery.sizeOf(context).height * 0.65), maxHeight: isWide
? math.min(640, MediaQuery.sizeOf(context).height * 0.65)
: MediaQuery.sizeOf(context).height,
), ),
padding: isWide ? null : EdgeInsets.only(top: 24),
child: Column( child: Column(
spacing: 16, spacing: 16,
children: [ children: [
@@ -56,66 +62,104 @@ class DashboardGrid extends HookConsumerWidget {
), ),
), ),
Expanded( Expanded(
child: Align( child: SingleChildScrollView(
alignment: Alignment.centerLeft, padding: isWide
child: SingleChildScrollView( ? const EdgeInsets.symmetric(horizontal: 24)
padding: const EdgeInsets.symmetric(horizontal: 24), : const EdgeInsets.only(bottom: 64),
scrollDirection: Axis.horizontal, scrollDirection: isWide ? Axis.horizontal : Axis.vertical,
child: Row( child: isWide ? _DashboardGridWide() : _DashboardGridNarrow(),
spacing: 16, ).clipRRect(topLeft: 12, topRight: 12).padding(horizontal: 24),
children: [ ),
SizedBox( ],
width: 400, ),
child: Column( );
spacing: 16, }
children: [ }
CheckInWidget(
margin: EdgeInsets.zero, class _DashboardGridWide extends HookConsumerWidget {
checkInOnly: true, const _DashboardGridWide();
),
Card( @override
margin: EdgeInsets.zero, Widget build(BuildContext context, WidgetRef ref) {
child: FortuneGraphWidget( return Row(
events: ref.watch( spacing: 16,
eventCalendarProvider( children: [
EventCalendarQuery( SizedBox(
uname: 'me', width: 400,
year: DateTime.now().year, child: Column(
month: DateTime.now().month, spacing: 16,
), children: [
), CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true),
), Card(
), margin: EdgeInsets.zero,
), child: FortuneGraphWidget(
Expanded(child: FortuneCard()), events: ref.watch(
], eventCalendarProvider(
EventCalendarQuery(
uname: 'me',
year: DateTime.now().year,
month: DateTime.now().month,
), ),
), ),
SizedBox(width: 400, child: FeaturedPostCard()), ),
SizedBox( ),
width: 400, ),
child: Column( Expanded(child: FortuneCard()),
spacing: 16, ],
children: [ ),
FriendsOverviewWidget(), ),
Expanded(child: NotificationsCard()), SizedBox(width: 400, child: FeaturedPostCard()),
], SizedBox(
), width: 400,
), child: Column(
SizedBox( spacing: 16,
width: 400, children: [
child: Column( FriendsOverviewWidget(),
spacing: 16, Expanded(child: NotificationsCard()),
children: [Expanded(child: ChatListCard())], ],
), ),
), ),
], SizedBox(
width: 400,
child: Column(
spacing: 16,
children: [Expanded(child: ChatListCard())],
),
),
],
);
}
}
class _DashboardGridNarrow extends HookConsumerWidget {
const _DashboardGridNarrow();
@override
Widget build(BuildContext context, WidgetRef ref) {
return Column(
spacing: 16,
children: [
CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true),
FortuneCard(),
SizedBox(height: 400, child: FeaturedPostCard()),
FriendsOverviewWidget(),
NotificationsCard(),
ChatListCard(),
Card(
margin: EdgeInsets.zero,
child: FortuneGraphWidget(
events: ref.watch(
eventCalendarProvider(
EventCalendarQuery(
uname: 'me',
year: DateTime.now().year,
month: DateTime.now().month,
), ),
), ),
), ),
), ),
], ),
), ],
); );
} }
} }
@@ -344,37 +388,35 @@ class NotificationsCard extends HookConsumerWidget {
), ),
], ],
).padding(horizontal: 16, vertical: 12), ).padding(horizontal: 16, vertical: 12),
Expanded( notifications.when(
child: notifications.when( loading: () => const SkeletonNotificationTile(),
loading: () => const SkeletonNotificationTile(), error: (error, stack) => Center(child: Text('Error: $error')),
error: (error, stack) => Center(child: Text('Error: $error')), data: (notificationList) {
data: (notificationList) { if (notificationList.isEmpty) {
if (notificationList.isEmpty) { return const Center(child: Text('No notifications yet'));
return const Center(child: Text('No notifications yet')); }
} // Get the most recent notification (first in the list)
// Get the most recent notification (first in the list) final recentNotification = notificationList.first;
final recentNotification = notificationList.first;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Most Recent', 'Most Recent',
style: Theme.of(context).textTheme.bodySmall?.copyWith( style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant, color: Theme.of(context).colorScheme.onSurfaceVariant,
),
).padding(horizontal: 16),
const SizedBox(height: 8),
NotificationTile(
notification: recentNotification,
compact: true,
contentPadding: EdgeInsets.symmetric(horizontal: 16),
avatarRadius: 16.0,
), ),
], ).padding(horizontal: 16),
); const SizedBox(height: 8),
}, NotificationTile(
), notification: recentNotification,
compact: true,
contentPadding: EdgeInsets.symmetric(horizontal: 16),
avatarRadius: 16.0,
),
],
);
},
), ),
Text( Text(
'Tap to view all notifications', 'Tap to view all notifications',
@@ -424,34 +466,33 @@ class ChatListCard extends HookConsumerWidget {
), ),
], ],
).padding(horizontal: 16, vertical: 16), ).padding(horizontal: 16, vertical: 16),
Expanded( chatRooms.when(
child: chatRooms.when( loading: () => const Center(child: CircularProgressIndicator()),
loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) => Center(child: Text('Error: $error')),
error: (error, stack) => Center(child: Text('Error: $error')), data: (rooms) {
data: (rooms) { if (rooms.isEmpty) {
if (rooms.isEmpty) { return const Center(child: Text('No chat rooms available'));
return const Center(child: Text('No chat rooms available')); }
} // Take only the first 5 rooms
// Take only the first 5 rooms final recentRooms = rooms.take(5).toList();
final recentRooms = rooms.take(5).toList(); return ListView.builder(
return ListView.builder( shrinkWrap: true,
itemCount: recentRooms.length, itemCount: recentRooms.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final room = recentRooms[index]; final room = recentRooms[index];
return ChatRoomListTile( return ChatRoomListTile(
room: room, room: room,
isDirect: room.type == 1, isDirect: room.type == 1,
onTap: () { onTap: () {
context.pushNamed( context.pushNamed(
'chatRoom', 'chatRoom',
pathParameters: {'id': room.id}, pathParameters: {'id': room.id},
); );
}, },
); );
}, },
); );
}, },
),
), ),
], ],
), ),
@@ -514,6 +555,6 @@ class FortuneCard extends HookWidget {
Text(fortune['author']!).bold(), Text(fortune['author']!).bold(),
], ],
).padding(horizontal: 24), ).padding(horizontal: 24),
); ).height(48);
} }
} }