♻️ New post explore realm design

This commit is contained in:
LittleSheep 2025-03-08 18:43:58 +08:00
parent 060a97f5ec
commit a4f6e8af56
5 changed files with 130 additions and 17 deletions

View File

@ -768,5 +768,6 @@
"decrypting": "Decrypting……",
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online",
"messageUnablePreview": "Unable preview",
"messageUnablePreviewEncrypted": "Unable preview encrypted message"
"messageUnablePreviewEncrypted": "Unable preview encrypted message",
"postViewInGlobalDescription": "Do not view the post in the specific realm."
}

View File

@ -766,5 +766,6 @@
"decrypting": "解密中……",
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
"messageUnablePreview": "无法预览消息",
"messageUnablePreviewEncrypted": "无法预览加密消息"
"messageUnablePreviewEncrypted": "无法预览加密消息",
"postViewInGlobalDescription": "不查看特定领域的帖子。"
}

View File

@ -137,6 +137,11 @@
"publisherRunBy": "由 {} 管理",
"fieldPublisherBelongToRealm": "所屬領域",
"fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域",
"writePost": "撰寫",
"postTypeStory": "動態",
"postTypeArticle": "文章",
"postTypeQuestion": "問題",
"postTypeVideo": "視頻",
"writePostTypeStory": "發動態",
"writePostTypeArticle": "寫文章",
"writePostTypeQuestion": "提問題",
@ -761,5 +766,6 @@
"decrypting": "解密中……",
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
"messageUnablePreview": "無法預覽消息",
"messageUnablePreviewEncrypted": "無法預覽加密消息"
"messageUnablePreviewEncrypted": "無法預覽加密消息",
"postViewInGlobalDescription": "不查看特定領域的帖子。"
}

View File

@ -137,6 +137,11 @@
"publisherRunBy": "由 {} 管理",
"fieldPublisherBelongToRealm": "所屬領域",
"fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域",
"writePost": "撰寫",
"postTypeStory": "動態",
"postTypeArticle": "文章",
"postTypeQuestion": "問題",
"postTypeVideo": "視頻",
"writePostTypeStory": "發動態",
"writePostTypeArticle": "寫文章",
"writePostTypeQuestion": "提問題",
@ -761,5 +766,6 @@
"decrypting": "解密中……",
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
"messageUnablePreview": "無法預覽消息",
"messageUnablePreviewEncrypted": "無法預覽加密消息"
"messageUnablePreviewEncrypted": "無法預覽加密消息",
"postViewInGlobalDescription": "不查看特定領域的帖子。"
}

View File

@ -11,6 +11,7 @@ import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/sn_realm.dart';
import 'package:surface/types/post.dart';
import 'package:surface/types/realm.dart';
import 'package:surface/widgets/account/account_image.dart';
import 'package:surface/widgets/app_bar_leading.dart';
import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
@ -42,10 +43,13 @@ class ExploreScreen extends StatefulWidget {
class _ExploreScreenState extends State<ExploreScreen>
with TickerProviderStateMixin {
late TabController _tabController = TabController(length: 3, vsync: this);
late TabController _tabController = TabController(
length: kPostChannels.length,
vsync: this,
);
final _fabKey = GlobalKey<ExpandableFabState>();
final _listKeys = GlobalKey<_PostListWidgetState>();
final _listKey = GlobalKey<_PostListWidgetState>();
bool _showCategories = false;
@ -88,7 +92,7 @@ class _ExploreScreenState extends State<ExploreScreen>
if (_showCategories) {
_tabController = TabController(length: _categories.length, vsync: this);
} else {
_tabController = TabController(length: 4, vsync: this);
_tabController = TabController(length: kPostChannels.length, vsync: this);
}
_tabListen();
setState(() {});
@ -98,24 +102,23 @@ class _ExploreScreenState extends State<ExploreScreen>
_tabController.addListener(() {
if (_tabController.indexIsChanging) {
if (_showCategories) {
_listKeys.currentState
?.setCategory(_categories[_tabController.index]);
_listKeys.currentState?.refreshPosts();
_listKey.currentState?.setCategory(_categories[_tabController.index]);
_listKey.currentState?.refreshPosts();
return;
}
switch (_tabController.index) {
case 0:
case 3:
_listKeys.currentState?.setChannel(null);
_listKey.currentState?.setChannel(null);
break;
case 1:
_listKeys.currentState?.setChannel('friends');
_listKey.currentState?.setChannel('friends');
break;
case 2:
_listKeys.currentState?.setChannel('following');
_listKey.currentState?.setChannel('following');
break;
}
_listKeys.currentState?.refreshPosts();
_listKey.currentState?.refreshPosts();
}
});
}
@ -135,7 +138,7 @@ class _ExploreScreenState extends State<ExploreScreen>
}
Future<void> refreshPosts() async {
await _listKeys.currentState?.refreshPosts();
await _listKey.currentState?.refreshPosts();
}
@override
@ -198,7 +201,45 @@ class _ExploreScreenState extends State<ExploreScreen>
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
leading: AutoAppBarLeading(),
title: Text('screenExplore').tr(),
titleSpacing: 0,
title: Row(
children: [
IconButton(
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
visualDensity: VisualDensity.compact,
icon: _listKey.currentState?.realm != null
? AccountImage(
content: _listKey.currentState!.realm!.avatar,
radius: 14,
)
: const Icon(Symbols.group),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => _PostListRealmPopup(
realms: _realms,
onUpdate: (realm) {
_listKey.currentState?.setRealm(realm);
_listKey.currentState?.refreshPosts();
Future.delayed(const Duration(milliseconds: 100),
() {
if (mounted) {
setState(() {});
}
});
},
),
);
},
),
Expanded(
child: Center(
child: Text('screenExplore').tr(),
),
),
],
),
floating: true,
snap: true,
actions: [
@ -294,7 +335,7 @@ class _ExploreScreenState extends State<ExploreScreen>
];
},
body: _PostListWidget(
key: _listKeys,
key: _listKey,
),
),
);
@ -311,6 +352,8 @@ class _PostListWidget extends StatefulWidget {
class _PostListWidgetState extends State<_PostListWidget> {
bool _isBusy = false;
SnRealm? get realm => _selectedRealm;
final List<SnPost> _posts = List.empty(growable: true);
SnRealm? _selectedRealm;
String? _selectedChannel;
@ -430,3 +473,59 @@ class _PostListWidgetState extends State<_PostListWidget> {
);
}
}
class _PostListRealmPopup extends StatelessWidget {
final List<SnRealm>? realms;
final Function(SnRealm?) onUpdate;
const _PostListRealmPopup({
required this.realms,
required this.onUpdate,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Icon(Symbols.face, size: 24),
const Gap(16),
Text('accountRealms', style: Theme.of(context).textTheme.titleLarge)
.tr(),
],
).padding(horizontal: 20, top: 16, bottom: 12),
ListTile(
leading: const Icon(Symbols.close),
title: Text('postInGlobal').tr(),
subtitle: Text('postViewInGlobalDescription').tr(),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
onTap: () {
onUpdate.call(null);
Navigator.pop(context);
},
),
const Divider(height: 1),
Expanded(
child: ListView.builder(
itemCount: realms?.length ?? 0,
itemBuilder: (context, idx) {
final realm = realms![idx];
return ListTile(
title: Text(realm.name),
subtitle: Text('@${realm.alias}'),
leading: AccountImage(content: realm.avatar, radius: 18),
onTap: () {
onUpdate.call(realm);
Navigator.pop(context);
},
);
},
),
),
],
);
}
}