🗑️ Clean up duplicate widget in explore and dashboard
This commit is contained in:
@@ -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,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user