💄 Optimized featured post
This commit is contained in:
@@ -1508,7 +1508,7 @@
|
|||||||
"createAccountAgreeTerms": "I've read these terms and agree to the terms of service.",
|
"createAccountAgreeTerms": "I've read these terms and agree to the terms of service.",
|
||||||
"createAccountProfile": "Create your profile",
|
"createAccountProfile": "Create your profile",
|
||||||
"createAccountToS": "Review Terms & Conditions",
|
"createAccountToS": "Review Terms & Conditions",
|
||||||
"accountActivationAlert": "Remember to activate your account",
|
"accountActivationAlert": "Activate your account",
|
||||||
"accountActivationAlertHint": "Unactivated account may leads to various of permission issues, activate your account by clicking the link we sent to your email inbox.",
|
"accountActivationAlertHint": "Unactivated account may leads to various of permission issues, activate your account by clicking the link we sent to your email inbox.",
|
||||||
"accountActivationResendHint": "Didn't see it? Try click the button below to resend one. If you need to update your email while your account was unactivated, feel free to contact our customer service.",
|
"accountActivationResendHint": "Didn't see it? Try click the button below to resend one. If you need to update your email while your account was unactivated, feel free to contact our customer service.",
|
||||||
"accountActivationResend": "Resend",
|
"accountActivationResend": "Resend",
|
||||||
|
|||||||
@@ -1486,7 +1486,7 @@
|
|||||||
"createAccountAgreeTerms": "我已阅读并同意服务条款。",
|
"createAccountAgreeTerms": "我已阅读并同意服务条款。",
|
||||||
"createAccountProfile": "创建您的个人资料",
|
"createAccountProfile": "创建您的个人资料",
|
||||||
"createAccountToS": "查看条款与条件",
|
"createAccountToS": "查看条款与条件",
|
||||||
"accountActivationAlert": "请记住激活您的账户",
|
"accountActivationAlert": "激活您的账户",
|
||||||
"accountActivationAlertHint": "未激活的账户可能会导致各种权限问题,请点击我们发送到您邮箱收件箱的链接来激活您的账户。",
|
"accountActivationAlertHint": "未激活的账户可能会导致各种权限问题,请点击我们发送到您邮箱收件箱的链接来激活您的账户。",
|
||||||
"accountActivationResendHint": "没收到?请尝试点击下方按钮重新发送。如果您在账户未激活期间需要更新邮箱,请随时联系我们的客服。",
|
"accountActivationResendHint": "没收到?请尝试点击下方按钮重新发送。如果您在账户未激活期间需要更新邮箱,请随时联系我们的客服。",
|
||||||
"accountActivationResend": "重新发送",
|
"accountActivationResend": "重新发送",
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import 'package:island/pods/userinfo.dart';
|
|||||||
import 'package:island/screens/chat/chat.dart';
|
import 'package:island/screens/chat/chat.dart';
|
||||||
import 'package:island/services/event_bus.dart';
|
import 'package:island/services/event_bus.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/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';
|
||||||
import 'package:island/widgets/notification_tile.dart';
|
import 'package:island/widgets/notification_tile.dart';
|
||||||
import 'package:island/widgets/post/post_featured.dart';
|
import 'package:island/widgets/post/post_featured.dart';
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
|
||||||
import 'package:island/widgets/check_in.dart';
|
import 'package:island/widgets/check_in.dart';
|
||||||
import 'package:island/screens/notification.dart';
|
import 'package:island/screens/notification.dart';
|
||||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
@@ -124,9 +124,13 @@ class _DashboardGridWide extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final userInfo = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
|
if (userInfo.value != null && userInfo.value?.activatedAt == null)
|
||||||
|
SizedBox(width: 400, child: AccountUnactivatedCard()),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 400,
|
width: 400,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -151,7 +155,7 @@ class _DashboardGridWide extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 400, child: FeaturedPostCard()),
|
SizedBox(width: 400, child: PostFeaturedList(collapsable: false)),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 400,
|
width: 400,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -179,12 +183,19 @@ class _DashboardGridNarrow extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final userInfo = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
|
if (userInfo.value != null && userInfo.value?.activatedAt == null)
|
||||||
|
AccountUnactivatedCard(),
|
||||||
CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true),
|
CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true),
|
||||||
FortuneCard(),
|
FortuneCard(),
|
||||||
SizedBox(height: 400, child: FeaturedPostCard()),
|
ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxHeight: 400),
|
||||||
|
child: PostFeaturedList(),
|
||||||
|
),
|
||||||
FriendsOverviewWidget(),
|
FriendsOverviewWidget(),
|
||||||
NotificationsCard(),
|
NotificationsCard(),
|
||||||
ChatListCard(),
|
ChatListCard(),
|
||||||
@@ -318,65 +329,6 @@ class ClockCard extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FeaturedPostCard extends HookConsumerWidget {
|
|
||||||
const FeaturedPostCard({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final featuredPostsAsync = ref.watch(featuredPostsProvider);
|
|
||||||
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
|
||||||
child: Card(
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 48,
|
|
||||||
child: Row(
|
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.highlight),
|
|
||||||
Text('highlightPost').tr(),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 16, vertical: 8),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: featuredPostsAsync.when(
|
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
|
||||||
data: (posts) {
|
|
||||||
if (posts.isEmpty) {
|
|
||||||
return Padding(
|
|
||||||
padding: EdgeInsets.all(16),
|
|
||||||
child: Center(
|
|
||||||
child: Text('noFeaturedPostsAvailable').tr(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return PageView.builder(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
itemCount: posts.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return SingleChildScrollView(
|
|
||||||
child: PostActionableItem(
|
|
||||||
item: posts[index],
|
|
||||||
borderRadius: 8,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationsCard extends HookConsumerWidget {
|
class NotificationsCard extends HookConsumerWidget {
|
||||||
const NotificationsCard({super.key});
|
const NotificationsCard({super.key});
|
||||||
|
|
||||||
|
|||||||
@@ -346,29 +346,7 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(spacing: 8, children: [const Gap(4)]),
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
const Gap(4),
|
|
||||||
if (user.value?.activatedAt == null)
|
|
||||||
AccountUnactivatedCard(),
|
|
||||||
CheckInWidget(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
onChecked: () {
|
|
||||||
ref.invalidate(eventCalendarProvider(query.value));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (notificationCount.value != null &&
|
|
||||||
notificationCount.value! > 0)
|
|
||||||
notificationIndicatorWidget(
|
|
||||||
context,
|
|
||||||
count: notificationCount.value ?? 0,
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
),
|
|
||||||
PostFeaturedList(),
|
|
||||||
FriendsOverviewWidget(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -219,20 +219,20 @@ class AccountName extends StatelessWidget {
|
|||||||
if (account.automatedId != null)
|
if (account.automatedId != null)
|
||||||
hideOverlay
|
hideOverlay
|
||||||
? Icon(
|
? Icon(
|
||||||
Symbols.smart_toy,
|
|
||||||
size: 16,
|
|
||||||
color: nameStyle.color,
|
|
||||||
fill: 1,
|
|
||||||
)
|
|
||||||
: Tooltip(
|
|
||||||
message: 'accountAutomated'.tr(),
|
|
||||||
child: Icon(
|
|
||||||
Symbols.smart_toy,
|
Symbols.smart_toy,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: nameStyle.color,
|
color: nameStyle.color,
|
||||||
fill: 1,
|
fill: 1,
|
||||||
|
)
|
||||||
|
: Tooltip(
|
||||||
|
message: 'accountAutomated'.tr(),
|
||||||
|
child: Icon(
|
||||||
|
Symbols.smart_toy,
|
||||||
|
size: 16,
|
||||||
|
color: nameStyle.color,
|
||||||
|
fill: 1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -275,20 +275,20 @@ class AccountName extends StatelessWidget {
|
|||||||
if (account.automatedId != null)
|
if (account.automatedId != null)
|
||||||
hideOverlay
|
hideOverlay
|
||||||
? Icon(
|
? Icon(
|
||||||
Symbols.smart_toy,
|
|
||||||
size: 16,
|
|
||||||
color: nameStyle.color,
|
|
||||||
fill: 1,
|
|
||||||
)
|
|
||||||
: Tooltip(
|
|
||||||
message: 'accountAutomated'.tr(),
|
|
||||||
child: Icon(
|
|
||||||
Symbols.smart_toy,
|
Symbols.smart_toy,
|
||||||
size: 16,
|
size: 16,
|
||||||
color: nameStyle.color,
|
color: nameStyle.color,
|
||||||
fill: 1,
|
fill: 1,
|
||||||
|
)
|
||||||
|
: Tooltip(
|
||||||
|
message: 'accountAutomated'.tr(),
|
||||||
|
child: Icon(
|
||||||
|
Symbols.smart_toy,
|
||||||
|
size: 16,
|
||||||
|
color: nameStyle.color,
|
||||||
|
fill: 1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -310,29 +310,28 @@ class VerificationMark extends StatelessWidget {
|
|||||||
? kVerificationMarkIcons[mark.type]
|
? kVerificationMarkIcons[mark.type]
|
||||||
: Symbols.verified,
|
: Symbols.verified,
|
||||||
size: 16,
|
size: 16,
|
||||||
color:
|
color: (kVerificationMarkColors.length > mark.type && mark.type >= 0)
|
||||||
(kVerificationMarkColors.length > mark.type && mark.type >= 0)
|
? kVerificationMarkColors[mark.type]
|
||||||
? kVerificationMarkColors[mark.type]
|
: Colors.blue,
|
||||||
: Colors.blue,
|
|
||||||
fill: 1,
|
fill: 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
return hideOverlay
|
return hideOverlay
|
||||||
? icon
|
? icon
|
||||||
: Tooltip(
|
: Tooltip(
|
||||||
richMessage: TextSpan(
|
richMessage: TextSpan(
|
||||||
text: mark.title ?? 'No title',
|
text: mark.title ?? 'No title',
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: '\n'),
|
TextSpan(text: '\n'),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: mark.description ?? 'descriptionNone'.tr(),
|
text: mark.description ?? 'descriptionNone'.tr(),
|
||||||
style: TextStyle(fontWeight: FontWeight.normal),
|
style: TextStyle(fontWeight: FontWeight.normal),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
child: icon,
|
child: icon,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,19 +383,19 @@ class StellarMembershipMark extends StatelessWidget {
|
|||||||
return hideOverlay
|
return hideOverlay
|
||||||
? icon
|
? icon
|
||||||
: Tooltip(
|
: Tooltip(
|
||||||
richMessage: TextSpan(
|
richMessage: TextSpan(
|
||||||
text: 'stellarMembership'.tr(),
|
text: 'stellarMembership'.tr(),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: '\n'),
|
TextSpan(text: '\n'),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'currentMembershipMember'.tr(args: [tierName]),
|
text: 'currentMembershipMember'.tr(args: [tierName]),
|
||||||
style: TextStyle(fontWeight: FontWeight.normal),
|
style: TextStyle(fontWeight: FontWeight.normal),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
child: icon,
|
child: icon,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,10 +413,9 @@ class VerificationStatusCard extends StatelessWidget {
|
|||||||
? kVerificationMarkIcons[mark.type]
|
? kVerificationMarkIcons[mark.type]
|
||||||
: Symbols.verified,
|
: Symbols.verified,
|
||||||
size: 32,
|
size: 32,
|
||||||
color:
|
color: (kVerificationMarkColors.length > mark.type && mark.type >= 0)
|
||||||
(kVerificationMarkColors.length > mark.type && mark.type >= 0)
|
? kVerificationMarkColors[mark.type]
|
||||||
? kVerificationMarkColors[mark.type]
|
: Colors.blue,
|
||||||
: Colors.blue,
|
|
||||||
fill: 1,
|
fill: 1,
|
||||||
).alignment(Alignment.centerLeft),
|
).alignment(Alignment.centerLeft),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ Future<List<SnPost>> featuredPosts(Ref ref) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PostFeaturedList extends HookConsumerWidget {
|
class PostFeaturedList extends HookConsumerWidget {
|
||||||
const PostFeaturedList({super.key});
|
final bool collapsable;
|
||||||
|
const PostFeaturedList({super.key, this.collapsable = true});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -86,6 +87,7 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 48,
|
height: 48,
|
||||||
@@ -121,36 +123,37 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Symbols.arrow_right),
|
icon: const Icon(Symbols.arrow_right),
|
||||||
),
|
),
|
||||||
IconButton(
|
if (collapsable)
|
||||||
padding: EdgeInsets.zero,
|
IconButton(
|
||||||
visualDensity: VisualDensity.compact,
|
padding: EdgeInsets.zero,
|
||||||
constraints: const BoxConstraints(),
|
visualDensity: VisualDensity.compact,
|
||||||
onPressed: () {
|
constraints: const BoxConstraints(),
|
||||||
isCollapsed.value = !isCollapsed.value;
|
onPressed: () {
|
||||||
talker.info(
|
isCollapsed.value = !isCollapsed.value;
|
||||||
'Manual toggle. isCollapsed set to ${isCollapsed.value}',
|
|
||||||
);
|
|
||||||
if (isCollapsed.value &&
|
|
||||||
featuredPostsAsync.hasValue &&
|
|
||||||
featuredPostsAsync.value!.isNotEmpty) {
|
|
||||||
prefs.setString(
|
|
||||||
kFeaturedPostsCollapsedId,
|
|
||||||
featuredPostsAsync.value!.first.id,
|
|
||||||
);
|
|
||||||
talker.info(
|
talker.info(
|
||||||
'Stored collapsed ID: ${featuredPostsAsync.value!.first.id}',
|
'Manual toggle. isCollapsed set to ${isCollapsed.value}',
|
||||||
);
|
);
|
||||||
} else {
|
if (isCollapsed.value &&
|
||||||
prefs.remove(kFeaturedPostsCollapsedId);
|
featuredPostsAsync.hasValue &&
|
||||||
talker.info('Removed stored collapsed ID.');
|
featuredPostsAsync.value!.isNotEmpty) {
|
||||||
}
|
prefs.setString(
|
||||||
},
|
kFeaturedPostsCollapsedId,
|
||||||
icon: Icon(
|
featuredPostsAsync.value!.first.id,
|
||||||
isCollapsed.value
|
);
|
||||||
? Symbols.expand_more
|
talker.info(
|
||||||
: Symbols.expand_less,
|
'Stored collapsed ID: ${featuredPostsAsync.value!.first.id}',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
prefs.remove(kFeaturedPostsCollapsedId);
|
||||||
|
talker.info('Removed stored collapsed ID.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
isCollapsed.value
|
||||||
|
? Symbols.expand_more
|
||||||
|
: Symbols.expand_less,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 8),
|
).padding(horizontal: 16, vertical: 8),
|
||||||
),
|
),
|
||||||
@@ -158,14 +161,14 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
child: Visibility(
|
child: Visibility(
|
||||||
visible: !isCollapsed.value,
|
visible: collapsable ? !isCollapsed.value : true,
|
||||||
child: featuredPostsAsync.when(
|
child: featuredPostsAsync.when(
|
||||||
loading:
|
loading: () =>
|
||||||
() => const Center(child: CircularProgressIndicator()),
|
const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
data: (posts) {
|
data: (posts) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 320,
|
height: 344,
|
||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
controller: pageViewController,
|
controller: pageViewController,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
|
|||||||
Reference in New Issue
Block a user