♻️ New post explore realm design
This commit is contained in:
		@@ -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."
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -766,5 +766,6 @@
 | 
			
		||||
  "decrypting": "解密中……",
 | 
			
		||||
  "decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
 | 
			
		||||
  "messageUnablePreview": "无法预览消息",
 | 
			
		||||
  "messageUnablePreviewEncrypted": "无法预览加密消息"
 | 
			
		||||
  "messageUnablePreviewEncrypted": "无法预览加密消息",
 | 
			
		||||
  "postViewInGlobalDescription": "不查看特定领域的帖子。"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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": "不查看特定領域的帖子。"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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": "不查看特定領域的帖子。"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
                },
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user