♻️ New post explore realm design
This commit is contained in:
parent
060a97f5ec
commit
a4f6e8af56
@ -768,5 +768,6 @@
|
|||||||
"decrypting": "Decrypting……",
|
"decrypting": "Decrypting……",
|
||||||
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online",
|
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online",
|
||||||
"messageUnablePreview": "Unable preview",
|
"messageUnablePreview": "Unable preview",
|
||||||
"messageUnablePreviewEncrypted": "Unable preview encrypted message"
|
"messageUnablePreviewEncrypted": "Unable preview encrypted message",
|
||||||
|
"postViewInGlobalDescription": "Do not view the post in the specific realm."
|
||||||
}
|
}
|
||||||
|
@ -766,5 +766,6 @@
|
|||||||
"decrypting": "解密中……",
|
"decrypting": "解密中……",
|
||||||
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
|
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
|
||||||
"messageUnablePreview": "无法预览消息",
|
"messageUnablePreview": "无法预览消息",
|
||||||
"messageUnablePreviewEncrypted": "无法预览加密消息"
|
"messageUnablePreviewEncrypted": "无法预览加密消息",
|
||||||
|
"postViewInGlobalDescription": "不查看特定领域的帖子。"
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,11 @@
|
|||||||
"publisherRunBy": "由 {} 管理",
|
"publisherRunBy": "由 {} 管理",
|
||||||
"fieldPublisherBelongToRealm": "所屬領域",
|
"fieldPublisherBelongToRealm": "所屬領域",
|
||||||
"fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域",
|
"fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域",
|
||||||
|
"writePost": "撰寫",
|
||||||
|
"postTypeStory": "動態",
|
||||||
|
"postTypeArticle": "文章",
|
||||||
|
"postTypeQuestion": "問題",
|
||||||
|
"postTypeVideo": "視頻",
|
||||||
"writePostTypeStory": "發動態",
|
"writePostTypeStory": "發動態",
|
||||||
"writePostTypeArticle": "寫文章",
|
"writePostTypeArticle": "寫文章",
|
||||||
"writePostTypeQuestion": "提問題",
|
"writePostTypeQuestion": "提問題",
|
||||||
@ -761,5 +766,6 @@
|
|||||||
"decrypting": "解密中……",
|
"decrypting": "解密中……",
|
||||||
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
||||||
"messageUnablePreview": "無法預覽消息",
|
"messageUnablePreview": "無法預覽消息",
|
||||||
"messageUnablePreviewEncrypted": "無法預覽加密消息"
|
"messageUnablePreviewEncrypted": "無法預覽加密消息",
|
||||||
|
"postViewInGlobalDescription": "不查看特定領域的帖子。"
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,11 @@
|
|||||||
"publisherRunBy": "由 {} 管理",
|
"publisherRunBy": "由 {} 管理",
|
||||||
"fieldPublisherBelongToRealm": "所屬領域",
|
"fieldPublisherBelongToRealm": "所屬領域",
|
||||||
"fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域",
|
"fieldPublisherBelongToRealmUnset": "未設置發佈者所屬領域",
|
||||||
|
"writePost": "撰寫",
|
||||||
|
"postTypeStory": "動態",
|
||||||
|
"postTypeArticle": "文章",
|
||||||
|
"postTypeQuestion": "問題",
|
||||||
|
"postTypeVideo": "視頻",
|
||||||
"writePostTypeStory": "發動態",
|
"writePostTypeStory": "發動態",
|
||||||
"writePostTypeArticle": "寫文章",
|
"writePostTypeArticle": "寫文章",
|
||||||
"writePostTypeQuestion": "提問題",
|
"writePostTypeQuestion": "提問題",
|
||||||
@ -761,5 +766,6 @@
|
|||||||
"decrypting": "解密中……",
|
"decrypting": "解密中……",
|
||||||
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
||||||
"messageUnablePreview": "無法預覽消息",
|
"messageUnablePreview": "無法預覽消息",
|
||||||
"messageUnablePreviewEncrypted": "無法預覽加密消息"
|
"messageUnablePreviewEncrypted": "無法預覽加密消息",
|
||||||
|
"postViewInGlobalDescription": "不查看特定領域的帖子。"
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import 'package:surface/providers/sn_network.dart';
|
|||||||
import 'package:surface/providers/sn_realm.dart';
|
import 'package:surface/providers/sn_realm.dart';
|
||||||
import 'package:surface/types/post.dart';
|
import 'package:surface/types/post.dart';
|
||||||
import 'package:surface/types/realm.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/app_bar_leading.dart';
|
||||||
import 'package:surface/widgets/dialog.dart';
|
import 'package:surface/widgets/dialog.dart';
|
||||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||||
@ -42,10 +43,13 @@ class ExploreScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _ExploreScreenState extends State<ExploreScreen>
|
class _ExploreScreenState extends State<ExploreScreen>
|
||||||
with TickerProviderStateMixin {
|
with TickerProviderStateMixin {
|
||||||
late TabController _tabController = TabController(length: 3, vsync: this);
|
late TabController _tabController = TabController(
|
||||||
|
length: kPostChannels.length,
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
|
||||||
final _fabKey = GlobalKey<ExpandableFabState>();
|
final _fabKey = GlobalKey<ExpandableFabState>();
|
||||||
final _listKeys = GlobalKey<_PostListWidgetState>();
|
final _listKey = GlobalKey<_PostListWidgetState>();
|
||||||
|
|
||||||
bool _showCategories = false;
|
bool _showCategories = false;
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
if (_showCategories) {
|
if (_showCategories) {
|
||||||
_tabController = TabController(length: _categories.length, vsync: this);
|
_tabController = TabController(length: _categories.length, vsync: this);
|
||||||
} else {
|
} else {
|
||||||
_tabController = TabController(length: 4, vsync: this);
|
_tabController = TabController(length: kPostChannels.length, vsync: this);
|
||||||
}
|
}
|
||||||
_tabListen();
|
_tabListen();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@ -98,24 +102,23 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
_tabController.addListener(() {
|
_tabController.addListener(() {
|
||||||
if (_tabController.indexIsChanging) {
|
if (_tabController.indexIsChanging) {
|
||||||
if (_showCategories) {
|
if (_showCategories) {
|
||||||
_listKeys.currentState
|
_listKey.currentState?.setCategory(_categories[_tabController.index]);
|
||||||
?.setCategory(_categories[_tabController.index]);
|
_listKey.currentState?.refreshPosts();
|
||||||
_listKeys.currentState?.refreshPosts();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (_tabController.index) {
|
switch (_tabController.index) {
|
||||||
case 0:
|
case 0:
|
||||||
case 3:
|
case 3:
|
||||||
_listKeys.currentState?.setChannel(null);
|
_listKey.currentState?.setChannel(null);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
_listKeys.currentState?.setChannel('friends');
|
_listKey.currentState?.setChannel('friends');
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_listKeys.currentState?.setChannel('following');
|
_listKey.currentState?.setChannel('following');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_listKeys.currentState?.refreshPosts();
|
_listKey.currentState?.refreshPosts();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -135,7 +138,7 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshPosts() async {
|
Future<void> refreshPosts() async {
|
||||||
await _listKeys.currentState?.refreshPosts();
|
await _listKey.currentState?.refreshPosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -198,7 +201,45 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
sliver: SliverAppBar(
|
sliver: SliverAppBar(
|
||||||
leading: AutoAppBarLeading(),
|
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,
|
floating: true,
|
||||||
snap: true,
|
snap: true,
|
||||||
actions: [
|
actions: [
|
||||||
@ -294,7 +335,7 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
];
|
];
|
||||||
},
|
},
|
||||||
body: _PostListWidget(
|
body: _PostListWidget(
|
||||||
key: _listKeys,
|
key: _listKey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -311,6 +352,8 @@ class _PostListWidget extends StatefulWidget {
|
|||||||
class _PostListWidgetState extends State<_PostListWidget> {
|
class _PostListWidgetState extends State<_PostListWidget> {
|
||||||
bool _isBusy = false;
|
bool _isBusy = false;
|
||||||
|
|
||||||
|
SnRealm? get realm => _selectedRealm;
|
||||||
|
|
||||||
final List<SnPost> _posts = List.empty(growable: true);
|
final List<SnPost> _posts = List.empty(growable: true);
|
||||||
SnRealm? _selectedRealm;
|
SnRealm? _selectedRealm;
|
||||||
String? _selectedChannel;
|
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);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user