💄 Optimize explore page styles
This commit is contained in:
@@ -626,8 +626,8 @@
|
|||||||
"chatJoin": "Join the Chat",
|
"chatJoin": "Join the Chat",
|
||||||
"realmJoin": "Join the Realm",
|
"realmJoin": "Join the Realm",
|
||||||
"realmJoinSuccess": "Successfully joined the realm.",
|
"realmJoinSuccess": "Successfully joined the realm.",
|
||||||
"discoverRealms": "Discover Realms",
|
"discoverRealms": "Discover realms",
|
||||||
"discoverPublishers": "Discover Publishers",
|
"discoverPublishers": "Discover publishers",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"publisherMembers": "Collaborators",
|
"publisherMembers": "Collaborators",
|
||||||
"developerHub": "Developer Hub",
|
"developerHub": "Developer Hub",
|
||||||
|
@@ -198,21 +198,23 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
if (isWider) {
|
if (isWider) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(flex: 3, child: bodyView),
|
Flexible(flex: 3, child: bodyView.padding(left: 8)),
|
||||||
const VerticalDivider(width: 1),
|
|
||||||
if (user.value != null)
|
if (user.value != null)
|
||||||
Flexible(
|
Flexible(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
CheckInWidget(),
|
CheckInWidget(
|
||||||
Card(
|
|
||||||
margin: EdgeInsets.only(
|
margin: EdgeInsets.only(
|
||||||
left: 16,
|
left: 8,
|
||||||
right: 16,
|
right: 16,
|
||||||
top: 8,
|
top: 16,
|
||||||
|
bottom: 8,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
Card(
|
||||||
|
margin: EdgeInsets.only(left: 8, right: 16, top: 8),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// Use the reusable EventCalendarWidget
|
// Use the reusable EventCalendarWidget
|
||||||
@@ -227,6 +229,11 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
FortuneGraphWidget(
|
FortuneGraphWidget(
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
left: 8,
|
||||||
|
right: 16,
|
||||||
|
top: 16,
|
||||||
|
),
|
||||||
events: events,
|
events: events,
|
||||||
constrainWidth: true,
|
constrainWidth: true,
|
||||||
onPointSelected: onDaySelected,
|
onPointSelected: onDaySelected,
|
||||||
@@ -306,56 +313,55 @@ class _DiscoveryActivityItem extends StatelessWidget {
|
|||||||
final items = data['items'] as List;
|
final items = data['items'] as List;
|
||||||
final type = items.firstOrNull?['type'] ?? 'unknown';
|
final type = items.firstOrNull?['type'] ?? 'unknown';
|
||||||
|
|
||||||
return Column(
|
return Card(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
children: [
|
child: Column(
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
||||||
children: [
|
Row(
|
||||||
const Icon(Symbols.explore, size: 19),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
const Gap(8),
|
children: [
|
||||||
Text(
|
const Icon(Symbols.explore, size: 19),
|
||||||
(switch (type) {
|
const Gap(8),
|
||||||
'realm' => 'discoverRealms',
|
Text(
|
||||||
'publisher' => 'discoverPublishers',
|
(switch (type) {
|
||||||
'article' => 'discoverWebArticles',
|
'realm' => 'discoverRealms',
|
||||||
_ => 'unknown',
|
'publisher' => 'discoverPublishers',
|
||||||
}).tr(),
|
'article' => 'discoverWebArticles',
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
_ => 'unknown',
|
||||||
).padding(top: 1),
|
}).tr(),
|
||||||
],
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
).padding(horizontal: 20, top: 8, bottom: 4),
|
).padding(top: 1),
|
||||||
SizedBox(
|
],
|
||||||
height: 180,
|
).padding(horizontal: 20, top: 8, bottom: 4),
|
||||||
child: ListView.builder(
|
SizedBox(
|
||||||
scrollDirection: Axis.horizontal,
|
height: 180,
|
||||||
itemCount: items.length,
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
scrollDirection: Axis.horizontal,
|
||||||
itemBuilder: (context, index) {
|
itemCount: items.length,
|
||||||
final item = items[index];
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
switch (type) {
|
itemBuilder: (context, index) {
|
||||||
case 'realm':
|
final item = items[index];
|
||||||
return RealmCard(
|
return switch (type) {
|
||||||
|
'realm' => RealmCard(
|
||||||
realm: SnRealm.fromJson(item['data']),
|
realm: SnRealm.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
);
|
),
|
||||||
case 'publisher':
|
'publisher' => PublisherCard(
|
||||||
return PublisherCard(
|
|
||||||
publisher: SnPublisher.fromJson(item['data']),
|
publisher: SnPublisher.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
);
|
),
|
||||||
case 'article':
|
'article' => WebArticleCard(
|
||||||
return WebArticleCard(
|
|
||||||
article: SnWebArticle.fromJson(item['data']),
|
article: SnWebArticle.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
);
|
),
|
||||||
default:
|
_ => Placeholder(),
|
||||||
return Placeholder();
|
};
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
).padding(bottom: 8),
|
||||||
).padding(bottom: 4),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,6 +387,7 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
|
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
|
SliverGap(12),
|
||||||
if (user.value != null && !contentOnly)
|
if (user.value != null && !contentOnly)
|
||||||
SliverToBoxAdapter(child: CheckInWidget()),
|
SliverToBoxAdapter(child: CheckInWidget()),
|
||||||
SliverList.builder(
|
SliverList.builder(
|
||||||
|
@@ -67,21 +67,16 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
CustomScrollView(
|
CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: PostItem(
|
||||||
children: [
|
item: post!,
|
||||||
PostItem(
|
isFullPost: true,
|
||||||
item: post!,
|
backgroundColor: isWide ? Colors.transparent : null,
|
||||||
isFullPost: true,
|
onUpdate: (newItem) {
|
||||||
backgroundColor: isWide ? Colors.transparent : null,
|
// Update the local state with the new post data
|
||||||
onUpdate: (newItem) {
|
ref
|
||||||
// Update the local state with the new post data
|
.read(postStateProvider(id).notifier)
|
||||||
ref
|
.updatePost(newItem);
|
||||||
.read(postStateProvider(id).notifier)
|
},
|
||||||
.updatePost(newItem);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PostRepliesList(postId: id),
|
PostRepliesList(postId: id),
|
||||||
|
@@ -5,6 +5,7 @@ import 'package:island/models/post.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
|
||||||
final postSearchNotifierProvider = StateNotifierProvider.autoDispose<
|
final postSearchNotifierProvider = StateNotifierProvider.autoDispose<
|
||||||
@@ -141,6 +142,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index >= data.items.length) {
|
if (index >= data.items.length) {
|
||||||
@@ -151,14 +153,19 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final post = data.items[index];
|
final post = data.items[index];
|
||||||
return Column(
|
return Card(
|
||||||
children: [PostItem(item: post), const Divider(height: 1)],
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: PostActionableItem(item: post, borderRadius: 8),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
error:
|
||||||
|
(error, stack) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.invalidate(postSearchNotifierProvider),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@@ -285,33 +285,31 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
).padding(horizontal: 24, top: 24),
|
).padding(horizontal: 24, top: 24),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Card(
|
||||||
children: [
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
if (badges.value?.isNotEmpty ?? false)
|
child: Column(
|
||||||
BadgeList(badges: badges.value!).padding(top: 16),
|
children: [
|
||||||
if (data.verification != null)
|
if (badges.value?.isNotEmpty ?? false)
|
||||||
VerificationStatusCard(
|
BadgeList(badges: badges.value!).padding(top: 16),
|
||||||
mark: data.verification!,
|
if (data.verification != null)
|
||||||
).padding(top: 16),
|
VerificationStatusCard(mark: data.verification!),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24),
|
),
|
||||||
|
).padding(top: 16),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: const Divider(height: 1).padding(vertical: 24),
|
child: Card(
|
||||||
),
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
SliverToBoxAdapter(
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
children: [
|
||||||
children: [
|
Text('bio').tr().bold().padding(bottom: 2),
|
||||||
Text('bio').tr().bold(),
|
Text(
|
||||||
Text(
|
data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio,
|
||||||
data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio,
|
),
|
||||||
),
|
],
|
||||||
],
|
).padding(horizontal: 20, vertical: 16),
|
||||||
).padding(horizontal: 24),
|
),
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: const Divider(height: 1).padding(top: 24),
|
|
||||||
),
|
),
|
||||||
SliverPostList(pubName: name),
|
SliverPostList(pubName: name),
|
||||||
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
||||||
|
@@ -140,30 +140,27 @@ class VerificationStatusCard extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
return Column(
|
||||||
margin: EdgeInsets.zero,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Icon(
|
||||||
children: [
|
mark.type == 4
|
||||||
Icon(
|
? Symbols.play_circle
|
||||||
mark.type == 4
|
: mark.type == 0
|
||||||
? Symbols.play_circle
|
? Symbols.build_circle
|
||||||
: mark.type == 0
|
: Symbols.verified,
|
||||||
? Symbols.build_circle
|
size: 32,
|
||||||
: Symbols.verified,
|
color: kVerificationMarkColors[mark.type],
|
||||||
size: 32,
|
fill: 1,
|
||||||
color: kVerificationMarkColors[mark.type],
|
),
|
||||||
fill: 1,
|
const Gap(8),
|
||||||
),
|
Text(mark.title ?? 'No title').bold(),
|
||||||
const Gap(8),
|
Text(mark.description ?? 'descriptionNone'.tr()),
|
||||||
Text(mark.title ?? 'No title').bold(),
|
const Gap(6),
|
||||||
Text(mark.description ?? 'descriptionNone'.tr()),
|
Text(
|
||||||
const Gap(6),
|
'Verified by\n${mark.verifiedBy ?? 'No one verified it'}',
|
||||||
Text(
|
).fontSize(11).opacity(0.8),
|
||||||
'Verified by\n${mark.verifiedBy ?? 'No one verified it'}',
|
],
|
||||||
).fontSize(11).opacity(0.8),
|
).padding(horizontal: 24, vertical: 16);
|
||||||
],
|
|
||||||
).padding(horizontal: 24, vertical: 16),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
|
|
||||||
final String? eventCalanderUser;
|
final String? eventCalanderUser;
|
||||||
|
|
||||||
|
final EdgeInsets? margin;
|
||||||
|
|
||||||
const FortuneGraphWidget({
|
const FortuneGraphWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.events,
|
required this.events,
|
||||||
@@ -34,6 +36,7 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
this.height = 180,
|
this.height = 180,
|
||||||
this.onPointSelected,
|
this.onPointSelected,
|
||||||
this.eventCalanderUser,
|
this.eventCalanderUser,
|
||||||
|
this.margin,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -249,7 +252,7 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
if (constrainWidth) {
|
if (constrainWidth) {
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||||
child: Card(margin: EdgeInsets.all(16), child: content),
|
child: Card(margin: margin ?? EdgeInsets.all(16), child: content),
|
||||||
).center();
|
).center();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,7 +35,8 @@ Future<SnCheckInResult?> checkInResultToday(Ref ref) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CheckInWidget extends HookConsumerWidget {
|
class CheckInWidget extends HookConsumerWidget {
|
||||||
const CheckInWidget({super.key});
|
final EdgeInsets? margin;
|
||||||
|
const CheckInWidget({super.key, this.margin});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -66,7 +67,8 @@ class CheckInWidget extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
margin:
|
||||||
|
margin ?? EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
|
@@ -94,9 +94,7 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
|
|
||||||
final post = data.items[index];
|
final post = data.items[index];
|
||||||
|
|
||||||
return Column(
|
return _buildPostItem(post);
|
||||||
children: [_buildPostItem(post), const Divider(height: 1)],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -114,7 +112,10 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
onUpdate: onUpdate,
|
onUpdate: onUpdate,
|
||||||
);
|
);
|
||||||
case PostItemType.regular:
|
case PostItemType.regular:
|
||||||
return PostItem(item: post);
|
return Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: PostActionableItem(item: post, borderRadius: 8),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -93,16 +93,14 @@ class PostRepliesList extends HookConsumerWidget {
|
|||||||
return endItemView;
|
return endItemView;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
return Card(
|
||||||
children: [
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
PostItem(
|
child: PostActionableItem(
|
||||||
item: data.items[index],
|
item: data.items[index],
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
backgroundColor ?? (isWide ? Colors.transparent : null),
|
backgroundColor ?? (isWide ? Colors.transparent : null),
|
||||||
isShowReference: false,
|
isShowReference: false,
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user