🗑️ Clean up duplicate widget in explore and dashboard

This commit is contained in:
2025-12-21 13:37:35 +08:00
parent cb7eef943c
commit e6338e8a5a
2 changed files with 17 additions and 190 deletions

View File

@@ -16,15 +16,11 @@ import 'package:island/pods/userinfo.dart';
import 'package:island/screens/auth/login_modal.dart'; import 'package:island/screens/auth/login_modal.dart';
import 'package:island/screens/notification.dart'; import 'package:island/screens/notification.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:island/widgets/account/account_name.dart';
import 'package:island/widgets/account/friends_overview.dart';
import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/app_scaffold.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
import 'package:island/widgets/check_in.dart';
import 'package:island/widgets/extended_refresh_indicator.dart'; import 'package:island/widgets/extended_refresh_indicator.dart';
import 'package:island/widgets/navigation/fab_menu.dart'; import 'package:island/widgets/navigation/fab_menu.dart';
import 'package:island/widgets/paging/pagination_list.dart'; import 'package:island/widgets/paging/pagination_list.dart';
import 'package:island/widgets/post/post_featured.dart';
import 'package:island/widgets/post/post_item.dart'; import 'package:island/widgets/post/post_item.dart';
import 'package:island/widgets/post/post_item_skeleton.dart'; import 'package:island/widgets/post/post_item_skeleton.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
@@ -36,38 +32,6 @@ import 'package:island/widgets/share/share_sheet.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:super_sliver_list/super_sliver_list.dart'; import 'package:super_sliver_list/super_sliver_list.dart';
Widget notificationIndicatorWidget(
BuildContext context, {
required int count,
EdgeInsets? margin,
}) => Card(
margin: margin,
child: ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
minTileHeight: 48,
leading: const Icon(Symbols.notifications),
title: Row(
children: [
Text('notifications').tr().fontSize(14),
const Gap(8),
Badge(label: Text(count.toString())),
],
),
trailing: const Icon(Symbols.chevron_right),
contentPadding: EdgeInsets.only(left: 16, right: 15),
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder: (context) => const NotificationSheet(),
);
},
),
);
class ExploreScreen extends HookConsumerWidget { class ExploreScreen extends HookConsumerWidget {
const ExploreScreen({super.key}); const ExploreScreen({super.key});
@@ -502,9 +466,6 @@ class ExploreScreen extends HookConsumerWidget {
WidgetRef ref, WidgetRef ref,
String? currentFilter, String? currentFilter,
) { ) {
final user = ref.watch(userInfoProvider);
final notificationCount = ref.watch(notificationUnreadCountProvider);
final bodyView = _buildActivityList(context, ref); final bodyView = _buildActivityList(context, ref);
final notifier = ref.watch(activityListProvider.notifier); final notifier = ref.watch(activityListProvider.notifier);
@@ -516,38 +477,7 @@ class ExploreScreen extends HookConsumerWidget {
onRefresh: notifier.refresh, onRefresh: notifier.refresh,
child: CustomScrollView( child: CustomScrollView(
slivers: [ slivers: [
const SliverGap(8), SliverGap(8 + MediaQuery.paddingOf(context).top),
if (user.value?.activatedAt == null)
SliverToBoxAdapter(
child: AccountUnactivatedCard().padding(bottom: 8),
),
if (user.value != null)
SliverToBoxAdapter(
child: CheckInWidget(
margin: const EdgeInsets.only(bottom: 8),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: PostFeaturedList(),
),
),
SliverToBoxAdapter(
child: FriendsOverviewWidget(
padding: const EdgeInsets.only(bottom: 8),
hideWhenEmpty: true,
),
),
if (notificationCount.value != null &&
notificationCount.value! > 0)
SliverToBoxAdapter(
child: notificationIndicatorWidget(
context,
count: notificationCount.value ?? 0,
margin: const EdgeInsets.only(bottom: 8),
),
),
bodyView, bodyView,
], ],
), ),

View File

@@ -17,7 +17,6 @@ import 'package:island/widgets/content/sheet.dart';
import 'package:island/widgets/account/event_calendar_content.dart'; import 'package:island/widgets/account/event_calendar_content.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:slide_countdown/slide_countdown.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
part 'check_in.g.dart'; part 'check_in.g.dart';
@@ -52,18 +51,11 @@ Future<SnNotableDay?> nextNotableDay(Ref ref) async {
class CheckInWidget extends HookConsumerWidget { class CheckInWidget extends HookConsumerWidget {
final EdgeInsets? margin; final EdgeInsets? margin;
final VoidCallback? onChecked; final VoidCallback? onChecked;
final bool checkInOnly; const CheckInWidget({super.key, this.margin, this.onChecked});
const CheckInWidget({
super.key,
this.margin,
this.onChecked,
this.checkInOnly = false,
});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final todayResult = ref.watch(checkInResultTodayProvider); final todayResult = ref.watch(checkInResultTodayProvider);
final nextNotableDay = ref.watch(nextNotableDayProvider);
// Update time every second for live progress // Update time every second for live progress
final currentTime = useState(DateTime.now()); final currentTime = useState(DateTime.now());
@@ -74,28 +66,6 @@ class CheckInWidget extends HookConsumerWidget {
return timer.cancel; return timer.cancel;
}, []); }, []);
final now = currentTime.value;
final userinfo = ref.watch(userInfoProvider);
final isAdult = useMemoized(() {
final birthday = userinfo.value?.profile.birthday;
if (birthday == null) return false;
final age =
now.year -
birthday.year -
((now.month < birthday.month ||
(now.month == birthday.month && now.day < birthday.day))
? 1
: 0);
return age >= 18;
}, [userinfo]);
final progress = (now.hour * 60.0 + now.minute) / (24 * 60);
final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59);
final timeLeft = endOfDay.difference(now);
final timeLeftFormatted =
'${timeLeft.inHours.toString().padLeft(2, '0')}:${(timeLeft.inMinutes % 60).toString().padLeft(2, '0')}:${(timeLeft.inSeconds % 60).toString().padLeft(2, '0')}';
Future<void> checkIn({String? captchatTk}) async { Future<void> checkIn({String? captchatTk}) async {
final client = ref.read(apiClientProvider); final client = ref.read(apiClientProvider);
try { try {
@@ -128,78 +98,22 @@ class CheckInWidget extends HookConsumerWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (checkInOnly) AnimatedSwitcher(
AnimatedSwitcher( duration: const Duration(milliseconds: 300),
duration: const Duration(milliseconds: 300), child: todayResult.when(
child: todayResult.when( data: (result) {
data: (result) { return Text(
return Text( result == null
result == null ? 'checkInNone'
? 'checkInNone' : 'checkInResultLevel${result.level}',
: 'checkInResultLevel${result.level}', textAlign: TextAlign.start,
textAlign: TextAlign.start, ).tr().fontSize(15).bold();
).tr().fontSize(15).bold(); },
}, loading: () => Text('checkInNone').tr().fontSize(15).bold(),
loading: () => error: (err, stack) =>
Text('checkInNone').tr().fontSize(15).bold(), Text('error').tr().fontSize(15).bold(),
error: (err, stack) =>
Text('error').tr().fontSize(15).bold(),
),
).padding(right: 4),
if (!checkInOnly)
Row(
spacing: 6,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
switch (DateTime.now().weekday) {
6 || 7 => Symbols.weekend,
_ => isAdult ? Symbols.work : Symbols.school,
},
fill: 1,
size: 16,
).padding(right: 2),
Text(
DateFormat('EEE').format(DateTime.now()),
).fontSize(16).bold(),
Text(
DateFormat('MM/dd').format(DateTime.now()),
).fontSize(16),
Tooltip(
message: timeLeftFormatted,
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
trackGap: 0,
value: progress,
strokeWidth: 2,
),
),
),
],
), ),
if (!checkInOnly) ).padding(right: 4),
Row(
spacing: 5,
children: [
Text('notableDayNext')
.tr(args: [nextNotableDay.value?.localName ?? 'idk'])
.fontSize(12),
if (nextNotableDay.value != null)
SlideCountdown(
decoration: const BoxDecoration(),
style: const TextStyle(fontSize: 12),
separatorStyle: const TextStyle(fontSize: 12),
padding: EdgeInsets.zero,
duration: nextNotableDay.value?.date.difference(
DateTime.now(),
),
),
],
),
const Gap(2),
AnimatedSwitcher( AnimatedSwitcher(
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
child: todayResult.when( child: todayResult.when(
@@ -256,23 +170,6 @@ class CheckInWidget extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
spacing: 4, spacing: 4,
children: [ children: [
if (!checkInOnly)
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(
data: (result) {
return Text(
result == null
? 'checkInNone'
: 'checkInResultLevel${result.level}',
textAlign: TextAlign.start,
).tr().fontSize(15).bold();
},
loading: () => Text('checkInNone').tr().fontSize(15).bold(),
error: (err, stack) =>
Text('error').tr().fontSize(15).bold(),
),
).padding(right: 4),
IconButton.outlined( IconButton.outlined(
iconSize: 16, iconSize: 16,
visualDensity: const VisualDensity( visualDensity: const VisualDensity(