💄 Better large screen optimization!
This commit is contained in:
		@@ -26,16 +26,52 @@ import 'package:solian/widgets/layouts/two_column.dart';
 | 
			
		||||
abstract class SolianRouter {
 | 
			
		||||
  static final router = GoRouter(
 | 
			
		||||
    routes: [
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/',
 | 
			
		||||
        name: 'explore',
 | 
			
		||||
        builder: (context, state) => const ExploreScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/notification',
 | 
			
		||||
        name: 'notification',
 | 
			
		||||
        builder: (context, state) => const NotificationScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
      ShellRoute(
 | 
			
		||||
        pageBuilder: (context, state, child) => defaultPageBuilder(
 | 
			
		||||
          context,
 | 
			
		||||
          state,
 | 
			
		||||
          SolianTheme.isLargeScreen(context)
 | 
			
		||||
              ? TwoColumnLayout(
 | 
			
		||||
                  sideChild: const ExplorePostScreen(),
 | 
			
		||||
                  mainChild: child,
 | 
			
		||||
                )
 | 
			
		||||
              : child,
 | 
			
		||||
        ),
 | 
			
		||||
        routes: [
 | 
			
		||||
          GoRoute(
 | 
			
		||||
            path: '/',
 | 
			
		||||
            name: 'explore',
 | 
			
		||||
            builder: (context, state) =>
 | 
			
		||||
                !SolianTheme.isLargeScreen(context) ? const ExplorePostScreen() : const PageEmptyWidget(),
 | 
			
		||||
          ),
 | 
			
		||||
          GoRoute(
 | 
			
		||||
            path: '/posts/publish/moments',
 | 
			
		||||
            name: 'posts.moments.editor',
 | 
			
		||||
            builder: (context, state) => MomentEditorScreen(editing: state.extra as Post?),
 | 
			
		||||
          ),
 | 
			
		||||
          GoRoute(
 | 
			
		||||
            path: '/posts/publish/comments',
 | 
			
		||||
            name: 'posts.comments.editor',
 | 
			
		||||
            builder: (context, state) {
 | 
			
		||||
              final args = state.extra as CommentPostArguments;
 | 
			
		||||
              return CommentEditorScreen(editing: args.editing, related: args.related);
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          GoRoute(
 | 
			
		||||
            path: '/posts/:dataset/:alias',
 | 
			
		||||
            name: 'posts.screen',
 | 
			
		||||
            builder: (context, state) => PostScreen(
 | 
			
		||||
              alias: state.pathParameters['alias'] as String,
 | 
			
		||||
              dataset: state.pathParameters['dataset'] as String,
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
      ShellRoute(
 | 
			
		||||
        pageBuilder: (context, state, child) => defaultPageBuilder(
 | 
			
		||||
          context,
 | 
			
		||||
@@ -81,31 +117,23 @@ abstract class SolianRouter {
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
      ShellRoute(
 | 
			
		||||
          pageBuilder: (context, state, child) => defaultPageBuilder(
 | 
			
		||||
                context,
 | 
			
		||||
                state,
 | 
			
		||||
                SolianTheme.isLargeScreen(context)
 | 
			
		||||
                    ? TwoColumnLayout(
 | 
			
		||||
                        sideChild: const AccountScreen(),
 | 
			
		||||
                        mainChild: child,
 | 
			
		||||
                      )
 | 
			
		||||
                    : child,
 | 
			
		||||
              ),
 | 
			
		||||
          routes: [
 | 
			
		||||
            GoRoute(
 | 
			
		||||
              path: '/account',
 | 
			
		||||
              name: 'account',
 | 
			
		||||
        builder: (context, state) => const AccountScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/posts/publish/moments',
 | 
			
		||||
        name: 'posts.moments.editor',
 | 
			
		||||
        builder: (context, state) => MomentEditorScreen(editing: state.extra as Post?),
 | 
			
		||||
      ),
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/posts/publish/comments',
 | 
			
		||||
        name: 'posts.comments.editor',
 | 
			
		||||
        builder: (context, state) {
 | 
			
		||||
          final args = state.extra as CommentPostArguments;
 | 
			
		||||
          return CommentEditorScreen(editing: args.editing, related: args.related);
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/posts/:dataset/:alias',
 | 
			
		||||
        name: 'posts.screen',
 | 
			
		||||
        builder: (context, state) => PostScreen(
 | 
			
		||||
          alias: state.pathParameters['alias'] as String,
 | 
			
		||||
          dataset: state.pathParameters['dataset'] as String,
 | 
			
		||||
        ),
 | 
			
		||||
              builder: (context, state) =>
 | 
			
		||||
                  !SolianTheme.isLargeScreen(context) ? const AccountScreen() : const PageEmptyWidget(),
 | 
			
		||||
            ),
 | 
			
		||||
            GoRoute(
 | 
			
		||||
              path: '/auth/sign-in',
 | 
			
		||||
@@ -127,6 +155,7 @@ abstract class SolianRouter {
 | 
			
		||||
              name: 'account.personalize',
 | 
			
		||||
              builder: (context, state) => const PersonalizeScreen(),
 | 
			
		||||
            ),
 | 
			
		||||
          ]),
 | 
			
		||||
    ],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,64 +2,21 @@ import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:solian/providers/auth.dart';
 | 
			
		||||
import 'package:solian/router.dart';
 | 
			
		||||
import 'package:solian/screens/account/friend.dart';
 | 
			
		||||
import 'package:solian/screens/account/personalize.dart';
 | 
			
		||||
import 'package:solian/widgets/account/account_avatar.dart';
 | 
			
		||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 | 
			
		||||
import 'package:solian/widgets/empty.dart';
 | 
			
		||||
import 'package:solian/widgets/scaffold.dart';
 | 
			
		||||
 | 
			
		||||
class AccountScreen extends StatefulWidget {
 | 
			
		||||
class AccountScreen extends StatelessWidget {
 | 
			
		||||
  const AccountScreen({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<AccountScreen> createState() => _AccountScreenState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _AccountScreenState extends State<AccountScreen> {
 | 
			
		||||
  String? _title;
 | 
			
		||||
  String? _selectedTab;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final screenWidth = MediaQuery.of(context).size.width;
 | 
			
		||||
    final isLargeScreen = screenWidth >= 600;
 | 
			
		||||
 | 
			
		||||
    Widget renderContent() {
 | 
			
		||||
      switch (_selectedTab) {
 | 
			
		||||
        case 'account.friend':
 | 
			
		||||
          return const FriendScreenWidget();
 | 
			
		||||
        case 'account.personalize':
 | 
			
		||||
          return const PersonalizeScreenWidget();
 | 
			
		||||
        default:
 | 
			
		||||
          return const PageEmptyWidget();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return IndentScaffold(
 | 
			
		||||
      title: _title ?? AppLocalizations.of(context)!.account,
 | 
			
		||||
      title: AppLocalizations.of(context)!.account,
 | 
			
		||||
      noSafeArea: true,
 | 
			
		||||
      fixedAppBarColor: true,
 | 
			
		||||
      child: isLargeScreen
 | 
			
		||||
          ? Row(
 | 
			
		||||
              children: [
 | 
			
		||||
                Flexible(
 | 
			
		||||
                  flex: 2,
 | 
			
		||||
      child: AccountScreenWidget(
 | 
			
		||||
                    onSelect: (item, title) {
 | 
			
		||||
                      setState(() {
 | 
			
		||||
                        _selectedTab = item;
 | 
			
		||||
                        _title = title;
 | 
			
		||||
                      });
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                const VerticalDivider(thickness: 0.3, width: 0.3),
 | 
			
		||||
                Flexible(flex: 4, child: renderContent()),
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          : AccountScreenWidget(
 | 
			
		||||
              onSelect: (item, _) {
 | 
			
		||||
        onSelect: (item) {
 | 
			
		||||
          SolianRouter.router.pushNamed(item);
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
@@ -68,7 +25,7 @@ class _AccountScreenState extends State<AccountScreen> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class AccountScreenWidget extends StatefulWidget {
 | 
			
		||||
  final Function(String item, String title) onSelect;
 | 
			
		||||
  final Function(String item) onSelect;
 | 
			
		||||
 | 
			
		||||
  const AccountScreenWidget({super.key, required this.onSelect});
 | 
			
		||||
 | 
			
		||||
@@ -105,7 +62,7 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> {
 | 
			
		||||
            leading: const Icon(Icons.color_lens),
 | 
			
		||||
            title: Text(AppLocalizations.of(context)!.personalize),
 | 
			
		||||
            onTap: () {
 | 
			
		||||
              widget.onSelect('account.personalize', AppLocalizations.of(context)!.personalize);
 | 
			
		||||
              widget.onSelect('account.personalize');
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          ListTile(
 | 
			
		||||
@@ -113,7 +70,7 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> {
 | 
			
		||||
            leading: const Icon(Icons.diversity_1),
 | 
			
		||||
            title: Text(AppLocalizations.of(context)!.friend),
 | 
			
		||||
            onTap: () {
 | 
			
		||||
              widget.onSelect('account.friend', AppLocalizations.of(context)!.friend);
 | 
			
		||||
              widget.onSelect('account.friend');
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          ListTile(
 | 
			
		||||
 
 | 
			
		||||
@@ -6,61 +6,26 @@ import 'package:solian/models/pagination.dart';
 | 
			
		||||
import 'package:solian/models/post.dart';
 | 
			
		||||
import 'package:solian/providers/auth.dart';
 | 
			
		||||
import 'package:solian/router.dart';
 | 
			
		||||
import 'package:solian/screens/posts/screen.dart';
 | 
			
		||||
import 'package:solian/utils/service_url.dart';
 | 
			
		||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
 | 
			
		||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 | 
			
		||||
import 'package:http/http.dart' as http;
 | 
			
		||||
import 'package:solian/widgets/empty.dart';
 | 
			
		||||
import 'package:solian/utils/theme.dart';
 | 
			
		||||
import 'package:solian/widgets/scaffold.dart';
 | 
			
		||||
import 'package:solian/widgets/notification_notifier.dart';
 | 
			
		||||
import 'package:solian/widgets/posts/post.dart';
 | 
			
		||||
 | 
			
		||||
class ExploreScreen extends StatefulWidget {
 | 
			
		||||
  const ExploreScreen({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<ExploreScreen> createState() => _ExploreScreenState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _ExploreScreenState extends State<ExploreScreen> {
 | 
			
		||||
  Post? _selectedPost;
 | 
			
		||||
class ExplorePostScreen extends StatelessWidget {
 | 
			
		||||
  const ExplorePostScreen({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final screenWidth = MediaQuery.of(context).size.width;
 | 
			
		||||
    final isLargeScreen = screenWidth >= 600;
 | 
			
		||||
 | 
			
		||||
    return IndentScaffold(
 | 
			
		||||
      noSafeArea: true,
 | 
			
		||||
      fixedAppBarColor: isLargeScreen,
 | 
			
		||||
      fixedAppBarColor: SolianTheme.isLargeScreen(context),
 | 
			
		||||
      appBarActions: const [NotificationButton()],
 | 
			
		||||
      title: AppLocalizations.of(context)!.explore,
 | 
			
		||||
      child: isLargeScreen
 | 
			
		||||
          ? Row(
 | 
			
		||||
              children: [
 | 
			
		||||
                Flexible(
 | 
			
		||||
                  flex: 2,
 | 
			
		||||
                  child: ExploreScreenWidget(
 | 
			
		||||
                    onSelect: (item) {
 | 
			
		||||
                      setState(() => _selectedPost = item);
 | 
			
		||||
                    },
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                const VerticalDivider(thickness: 0.3, width: 0.3),
 | 
			
		||||
                Flexible(
 | 
			
		||||
                  flex: 4,
 | 
			
		||||
                  child: _selectedPost == null
 | 
			
		||||
                      ? const PageEmptyWidget()
 | 
			
		||||
                      : PostScreenWidget(
 | 
			
		||||
                          key: Key('p${_selectedPost!.id}'),
 | 
			
		||||
                          dataset: _selectedPost!.dataset,
 | 
			
		||||
                          alias: _selectedPost!.alias,
 | 
			
		||||
                        ),
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          : ExploreScreenWidget(
 | 
			
		||||
      child: ExplorePostWidget(
 | 
			
		||||
        onSelect: (item) {
 | 
			
		||||
          SolianRouter.router.pushNamed(
 | 
			
		||||
            'posts.screen',
 | 
			
		||||
@@ -75,16 +40,16 @@ class _ExploreScreenState extends State<ExploreScreen> {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ExploreScreenWidget extends StatefulWidget {
 | 
			
		||||
class ExplorePostWidget extends StatefulWidget {
 | 
			
		||||
  final Function(Post item) onSelect;
 | 
			
		||||
 | 
			
		||||
  const ExploreScreenWidget({super.key, required this.onSelect});
 | 
			
		||||
  const ExplorePostWidget({super.key, required this.onSelect});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<ExploreScreenWidget> createState() => _ExploreScreenWidgetState();
 | 
			
		||||
  State<ExplorePostWidget> createState() => _ExplorePostWidgetState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _ExploreScreenWidgetState extends State<ExploreScreenWidget> {
 | 
			
		||||
class _ExplorePostWidgetState extends State<ExplorePostWidget> {
 | 
			
		||||
  final PagingController<int, Post> _pagingController = PagingController(firstPageKey: 0);
 | 
			
		||||
 | 
			
		||||
  final http.Client _client = http.Client();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
 | 
			
		||||
import 'package:solian/models/post.dart';
 | 
			
		||||
import 'package:solian/utils/theme.dart';
 | 
			
		||||
import 'package:solian/widgets/account/account_avatar.dart';
 | 
			
		||||
import 'package:solian/widgets/posts/comment_list.dart';
 | 
			
		||||
import 'package:solian/widgets/posts/content/article.dart';
 | 
			
		||||
@@ -87,16 +88,13 @@ class _PostItemState extends State<PostItem> {
 | 
			
		||||
  Widget renderAttachments() {
 | 
			
		||||
    if (widget.item.modelType == 'article') return Container();
 | 
			
		||||
 | 
			
		||||
    final screenWidth = MediaQuery.of(context).size.width;
 | 
			
		||||
    final isLargeScreen = screenWidth >= 600;
 | 
			
		||||
 | 
			
		||||
    if (widget.item.attachments != null && widget.item.attachments!.isNotEmpty) {
 | 
			
		||||
      return Padding(
 | 
			
		||||
        padding: const EdgeInsets.only(top: 8),
 | 
			
		||||
        child: AttachmentList(
 | 
			
		||||
          items: widget.item.attachments!,
 | 
			
		||||
          provider: 'interactive',
 | 
			
		||||
          noTag: isLargeScreen && widget.brief,
 | 
			
		||||
          noTag: SolianTheme.isLargeScreen(context) && widget.brief,
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user