Compare commits

..

2 Commits

Author SHA1 Message Date
8352ce8b5b New explore screen on wide device 2025-07-21 20:03:06 +08:00
c06abf6e42 Remove the two column in the explore 2025-07-21 19:35:52 +08:00
6 changed files with 125 additions and 79 deletions

View File

@@ -310,42 +310,36 @@ final routerProvider = Provider<GoRouter>((ref) {
},
routes: [
// Explore tab
ShellRoute(
builder:
(context, state, child) => ExploreShellScreen(child: child),
routes: [
GoRoute(
name: 'explore',
path: '/',
builder: (context, state) => const ExploreScreen(),
),
GoRoute(
name: 'postSearch',
path: '/posts/search',
builder: (context, state) => const PostSearchScreen(),
),
GoRoute(
name: 'postDetail',
path: '/posts/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return PostDetailScreen(id: id);
},
),
GoRoute(
name: 'publisherProfile',
path: '/publishers/:name',
builder: (context, state) {
final name = state.pathParameters['name']!;
return PublisherProfileScreen(name: name);
},
),
GoRoute(
name: 'discoveryRealms',
path: '/discovery/realms',
builder: (context, state) => const DiscoveryRealmsScreen(),
),
],
GoRoute(
name: 'explore',
path: '/',
builder: (context, state) => const ExploreScreen(),
),
GoRoute(
name: 'postSearch',
path: '/posts/search',
builder: (context, state) => const PostSearchScreen(),
),
GoRoute(
name: 'postDetail',
path: '/posts/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return PostDetailScreen(id: id);
},
),
GoRoute(
name: 'publisherProfile',
path: '/publishers/:name',
builder: (context, state) {
final name = state.pathParameters['name']!;
return PublisherProfileScreen(name: name);
},
),
GoRoute(
name: 'discoveryRealms',
path: '/discovery/realms',
builder: (context, state) => const DiscoveryRealmsScreen(),
),
// Chat tab

View File

@@ -17,6 +17,7 @@ class DiscoveryRealmsScreen extends HookConsumerWidget {
final currentQuery = useState<String?>(null);
return AppScaffold(
noBackground: false,
appBar: AppBar(title: Text('discoverRealms'.tr())),
body: Stack(
children: [

View File

@@ -9,8 +9,11 @@ import 'package:island/models/activity.dart';
import 'package:island/models/publisher.dart';
import 'package:island/models/realm.dart';
import 'package:island/models/webfeed.dart';
import 'package:island/pods/event_calendar.dart';
import 'package:island/pods/userinfo.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/account/event_calendar.dart';
import 'package:island/widgets/account/fortune_graph.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/models/post.dart';
import 'package:island/widgets/check_in.dart';
@@ -27,42 +30,11 @@ import 'package:styled_widget/styled_widget.dart';
part 'explore.g.dart';
class ExploreShellScreen extends HookConsumerWidget {
final Widget child;
const ExploreShellScreen({super.key, required this.child});
@override
Widget build(BuildContext context, WidgetRef ref) {
final isWide = MediaQuery.of(context).size.width > 640;
if (isWide) {
return AppBackground(
isRoot: true,
child: Row(
children: [
Flexible(flex: 2, child: ExploreScreen(isAside: true)),
VerticalDivider(width: 1),
Flexible(flex: 3, child: child),
],
),
);
}
return AppBackground(isRoot: true, child: child);
}
}
class ExploreScreen extends HookConsumerWidget {
final bool isAside;
const ExploreScreen({super.key, this.isAside = false});
const ExploreScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final isWide = isWideScreen(context);
if (isWide && !isAside) {
return const EmptyPageHolder();
}
final tabController = useTabController(initialLength: 3);
final currentFilter = useState<String?>(null);
@@ -89,8 +61,31 @@ class ExploreScreen extends HookConsumerWidget {
activityListNotifierProvider(currentFilter.value).notifier,
);
final now = DateTime.now();
final query = useState(
EventCalendarQuery(uname: 'me', year: now.year, month: now.month),
);
final events = ref.watch(eventCalendarProvider(query.value));
final selectedDay = useState(now);
void onMonthChanged(int year, int month) {
query.value = EventCalendarQuery(
uname: query.value.uname,
year: year,
month: month,
);
}
// Function to handle day selection for synchronizing between widgets
void onDaySelected(DateTime day) {
selectedDay.value = day;
}
return AppScaffold(
extendBody: false, // Prevent conflicts with tabs navigation
noBackground: false,
appBar: AppBar(
toolbarHeight: 0,
bottom: PreferredSize(
@@ -184,23 +179,76 @@ class ExploreScreen extends HookConsumerWidget {
child: const Icon(Symbols.edit),
),
floatingActionButtonLocation: TabbedFabLocation(context),
body: TabBarView(
controller: tabController,
physics: const NeverScrollableScrollPhysics(),
children: [
_buildActivityList(ref, null),
_buildActivityList(ref, 'subscriptions'),
_buildActivityList(ref, 'friends'),
],
body: Builder(
builder: (context) {
final isWider = isWiderScreen(context);
final bodyView = TabBarView(
controller: tabController,
physics: const NeverScrollableScrollPhysics(),
children: [
_buildActivityList(context, ref, null),
_buildActivityList(context, ref, 'subscriptions'),
_buildActivityList(context, ref, 'friends'),
],
);
if (isWider) {
return Row(
children: [
Flexible(flex: 3, child: bodyView),
const VerticalDivider(width: 1),
Flexible(
flex: 2,
child: SingleChildScrollView(
child: Column(
children: [
CheckInWidget(),
Card(
margin: EdgeInsets.only(left: 16, right: 16, top: 8),
child: Column(
children: [
// Use the reusable EventCalendarWidget
EventCalendarWidget(
events: events,
initialDate: now,
showEventDetails: true,
onMonthChanged: onMonthChanged,
onDaySelected: onDaySelected,
),
],
),
),
FortuneGraphWidget(
events: events,
constrainWidth: true,
onPointSelected: onDaySelected,
),
],
),
),
),
],
);
}
return bodyView;
},
),
);
}
Widget _buildActivityList(WidgetRef ref, String? filter) {
Widget _buildActivityList(
BuildContext context,
WidgetRef ref,
String? filter,
) {
final activitiesNotifier = ref.watch(
activityListNotifierProvider(filter).notifier,
);
final isWider = isWiderScreen(context);
return RefreshIndicator(
onRefresh: () => Future.sync(activitiesNotifier.forceRefresh),
child: PagingHelperView(
@@ -214,7 +262,7 @@ class ExploreScreen extends HookConsumerWidget {
widgetCount: widgetCount,
endItemView: endItemView,
activitiesNotifier: activitiesNotifier,
contentOnly: filter != null,
contentOnly: isWider || filter != null,
),
),
),

View File

@@ -57,6 +57,7 @@ class PostDetailScreen extends HookConsumerWidget {
final isWide = isWideScreen(context);
return AppScaffold(
noBackground: false,
appBar: AppBar(title: const Text('Post')),
body: postState.when(
data: (post) {

View File

@@ -109,6 +109,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
@override
Widget build(BuildContext context) {
return AppScaffold(
noBackground: false,
appBar: AppBar(
title: TextField(
controller: _searchController,

View File

@@ -124,6 +124,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
return publisher.when(
data:
(data) => AppScaffold(
noBackground: false,
body: CustomScrollView(
slivers: [
SliverAppBar(