💄 Better bottom navigation
This commit is contained in:
		@@ -19,7 +19,6 @@ import 'package:solian/providers/content/realm.dart';
 | 
			
		||||
import 'package:solian/providers/friend.dart';
 | 
			
		||||
import 'package:solian/providers/account_status.dart';
 | 
			
		||||
import 'package:solian/router.dart';
 | 
			
		||||
import 'package:solian/shells/listener_shell.dart';
 | 
			
		||||
import 'package:solian/theme.dart';
 | 
			
		||||
import 'package:solian/translations.dart';
 | 
			
		||||
 | 
			
		||||
@@ -83,15 +82,14 @@ class SolianApp extends StatelessWidget {
 | 
			
		||||
      routerDelegate: AppRouter.instance.routerDelegate,
 | 
			
		||||
      routeInformationParser: AppRouter.instance.routeInformationParser,
 | 
			
		||||
      routeInformationProvider: AppRouter.instance.routeInformationProvider,
 | 
			
		||||
      backButtonDispatcher: AppRouter.instance.backButtonDispatcher,
 | 
			
		||||
      translations: SolianMessages(),
 | 
			
		||||
      locale: Get.deviceLocale,
 | 
			
		||||
      fallbackLocale: const Locale('en', 'US'),
 | 
			
		||||
      onInit: () => _initializeProviders(context),
 | 
			
		||||
      builder: (context, child) {
 | 
			
		||||
        return ListenerShell(
 | 
			
		||||
          child: ScaffoldMessenger(
 | 
			
		||||
            child: child ?? Container(),
 | 
			
		||||
          ),
 | 
			
		||||
        return ScaffoldMessenger(
 | 
			
		||||
          child: child ?? const SizedBox(),
 | 
			
		||||
        );
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,10 @@ import 'package:solian/screens/realms.dart';
 | 
			
		||||
import 'package:solian/screens/realms/realm_detail.dart';
 | 
			
		||||
import 'package:solian/screens/realms/realm_organize.dart';
 | 
			
		||||
import 'package:solian/screens/realms/realm_view.dart';
 | 
			
		||||
import 'package:solian/screens/social.dart';
 | 
			
		||||
import 'package:solian/screens/feed.dart';
 | 
			
		||||
import 'package:solian/screens/posts/post_publish.dart';
 | 
			
		||||
import 'package:solian/shells/basic_shell.dart';
 | 
			
		||||
import 'package:solian/shells/nav_shell.dart';
 | 
			
		||||
import 'package:solian/shells/root_shell.dart';
 | 
			
		||||
import 'package:solian/shells/title_shell.dart';
 | 
			
		||||
import 'package:solian/theme.dart';
 | 
			
		||||
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
 | 
			
		||||
@@ -25,29 +25,35 @@ abstract class AppRouter {
 | 
			
		||||
  static GoRouter instance = GoRouter(
 | 
			
		||||
    routes: [
 | 
			
		||||
      ShellRoute(
 | 
			
		||||
        builder: (context, state, child) => NavShell(
 | 
			
		||||
        builder: (context, state, child) => RootShell(
 | 
			
		||||
          state: state,
 | 
			
		||||
          showAppBar: false,
 | 
			
		||||
          showSidebar: false,
 | 
			
		||||
          child: child,
 | 
			
		||||
        ),
 | 
			
		||||
        routes: [
 | 
			
		||||
          ShellRoute(
 | 
			
		||||
          _feedRoute,
 | 
			
		||||
          _chatRoute,
 | 
			
		||||
          _realmRoute,
 | 
			
		||||
          _accountRoute,
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    ],
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  static final ShellRoute _feedRoute = ShellRoute(
 | 
			
		||||
    builder: (context, state, child) => BasicShell(
 | 
			
		||||
      state: state,
 | 
			
		||||
      sidebarFirst: true,
 | 
			
		||||
      showAppBar: false,
 | 
			
		||||
              sidebar: const SocialScreen(),
 | 
			
		||||
      sidebar: const FeedScreen(),
 | 
			
		||||
      child: child,
 | 
			
		||||
    ),
 | 
			
		||||
    routes: [
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/',
 | 
			
		||||
                name: 'social',
 | 
			
		||||
                builder: (context, state) =>
 | 
			
		||||
                    SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
        name: 'feed',
 | 
			
		||||
        builder: (context, state) => SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
            ? const EmptyPagePlaceholder()
 | 
			
		||||
                        : const SocialScreen(),
 | 
			
		||||
            : const FeedScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/posts/view/:alias',
 | 
			
		||||
@@ -73,8 +79,9 @@ abstract class AppRouter {
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
    ],
 | 
			
		||||
          ),
 | 
			
		||||
          ShellRoute(
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  static final ShellRoute _chatRoute = ShellRoute(
 | 
			
		||||
    builder: (context, state, child) => BasicShell(
 | 
			
		||||
      state: state,
 | 
			
		||||
      sidebarFirst: true,
 | 
			
		||||
@@ -86,8 +93,7 @@ abstract class AppRouter {
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/chat',
 | 
			
		||||
        name: 'chat',
 | 
			
		||||
                builder: (context, state) =>
 | 
			
		||||
                    SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
        builder: (context, state) => SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
            ? const EmptyPagePlaceholder()
 | 
			
		||||
            : const ChatScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
@@ -128,8 +134,9 @@ abstract class AppRouter {
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
    ],
 | 
			
		||||
          ),
 | 
			
		||||
          ShellRoute(
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  static final ShellRoute _realmRoute = ShellRoute(
 | 
			
		||||
    builder: (context, state, child) => BasicShell(
 | 
			
		||||
      state: state,
 | 
			
		||||
      sidebarFirst: true,
 | 
			
		||||
@@ -141,8 +148,7 @@ abstract class AppRouter {
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/realms',
 | 
			
		||||
        name: 'realms',
 | 
			
		||||
                builder: (context, state) =>
 | 
			
		||||
                    SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
        builder: (context, state) => SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
            ? const EmptyPagePlaceholder()
 | 
			
		||||
            : const RealmListScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
@@ -177,8 +183,9 @@ abstract class AppRouter {
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
    ],
 | 
			
		||||
          ),
 | 
			
		||||
          ShellRoute(
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  static final ShellRoute _accountRoute = ShellRoute(
 | 
			
		||||
    builder: (context, state, child) => BasicShell(
 | 
			
		||||
      state: state,
 | 
			
		||||
      sidebarFirst: true,
 | 
			
		||||
@@ -190,8 +197,7 @@ abstract class AppRouter {
 | 
			
		||||
      GoRoute(
 | 
			
		||||
        path: '/account',
 | 
			
		||||
        name: 'account',
 | 
			
		||||
                builder: (context, state) =>
 | 
			
		||||
                    SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
        builder: (context, state) => SolianTheme.isExtraLargeScreen(context)
 | 
			
		||||
            ? const EmptyPagePlaceholder()
 | 
			
		||||
            : const AccountScreen(),
 | 
			
		||||
      ),
 | 
			
		||||
@@ -220,9 +226,5 @@ abstract class AppRouter {
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    ],
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    ],
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:get/get.dart';
 | 
			
		||||
import 'package:protocol_handler/protocol_handler.dart';
 | 
			
		||||
import 'package:solian/exts.dart';
 | 
			
		||||
import 'package:solian/providers/account.dart';
 | 
			
		||||
import 'package:solian/providers/auth.dart';
 | 
			
		||||
import 'package:solian/services.dart';
 | 
			
		||||
import 'package:url_launcher/url_launcher.dart';
 | 
			
		||||
import 'package:url_launcher/url_launcher_string.dart';
 | 
			
		||||
 | 
			
		||||
class SignInPopup extends StatefulWidget {
 | 
			
		||||
@@ -13,13 +15,13 @@ class SignInPopup extends StatefulWidget {
 | 
			
		||||
  State<SignInPopup> createState() => _SignInPopupState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _SignInPopupState extends State<SignInPopup> {
 | 
			
		||||
class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
 | 
			
		||||
  bool _isBusy = false;
 | 
			
		||||
 | 
			
		||||
  final _usernameController = TextEditingController();
 | 
			
		||||
  final _passwordController = TextEditingController();
 | 
			
		||||
 | 
			
		||||
  void requestResetPassword(BuildContext context) async {
 | 
			
		||||
  void requestResetPassword() async {
 | 
			
		||||
    final username = _usernameController.value.text;
 | 
			
		||||
    if (username.isEmpty) {
 | 
			
		||||
      context.showErrorDialog('signinResetPasswordHint'.tr);
 | 
			
		||||
@@ -49,7 +51,7 @@ class _SignInPopupState extends State<SignInPopup> {
 | 
			
		||||
    context.showModalDialog('done'.tr, 'signinResetPasswordSent'.tr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void performAction(BuildContext context) async {
 | 
			
		||||
  void performAction() async {
 | 
			
		||||
    final AuthProvider provider = Get.find();
 | 
			
		||||
 | 
			
		||||
    final username = _usernameController.value.text;
 | 
			
		||||
@@ -96,6 +98,27 @@ class _SignInPopupState extends State<SignInPopup> {
 | 
			
		||||
    Navigator.pop(context, true);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    protocolHandler.addListener(this);
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    protocolHandler.removeListener(this);
 | 
			
		||||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void onProtocolUrlReceived(String url) {
 | 
			
		||||
    final uri = url.replaceFirst('solink://', '');
 | 
			
		||||
    if (uri == 'auth?status=done') {
 | 
			
		||||
      closeInAppWebView();
 | 
			
		||||
      performAction();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return SizedBox(
 | 
			
		||||
@@ -144,20 +167,19 @@ class _SignInPopupState extends State<SignInPopup> {
 | 
			
		||||
                ),
 | 
			
		||||
                onTapOutside: (_) =>
 | 
			
		||||
                    FocusManager.instance.primaryFocus?.unfocus(),
 | 
			
		||||
                onSubmitted: (_) => performAction(context),
 | 
			
		||||
                onSubmitted: (_) => performAction(),
 | 
			
		||||
              ),
 | 
			
		||||
              const SizedBox(height: 12),
 | 
			
		||||
              Row(
 | 
			
		||||
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                children: [
 | 
			
		||||
                  TextButton(
 | 
			
		||||
                    onPressed:
 | 
			
		||||
                        _isBusy ? null : () => requestResetPassword(context),
 | 
			
		||||
                    onPressed: _isBusy ? null : () => requestResetPassword(),
 | 
			
		||||
                    style: TextButton.styleFrom(foregroundColor: Colors.grey),
 | 
			
		||||
                    child: Text('forgotPassword'.tr),
 | 
			
		||||
                  ),
 | 
			
		||||
                  TextButton(
 | 
			
		||||
                    onPressed: _isBusy ? null : () => performAction(context),
 | 
			
		||||
                    onPressed: _isBusy ? null : () => performAction(),
 | 
			
		||||
                    child: Row(
 | 
			
		||||
                      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                      children: [
 | 
			
		||||
 
 | 
			
		||||
@@ -12,14 +12,14 @@ import 'package:solian/widgets/app_bar_title.dart';
 | 
			
		||||
import 'package:solian/widgets/current_state_action.dart';
 | 
			
		||||
import 'package:solian/widgets/posts/post_list.dart';
 | 
			
		||||
 | 
			
		||||
class SocialScreen extends StatefulWidget {
 | 
			
		||||
  const SocialScreen({super.key});
 | 
			
		||||
class FeedScreen extends StatefulWidget {
 | 
			
		||||
  const FeedScreen({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<SocialScreen> createState() => _SocialScreenState();
 | 
			
		||||
  State<FeedScreen> createState() => _FeedScreenState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _SocialScreenState extends State<SocialScreen> {
 | 
			
		||||
class _FeedScreenState extends State<FeedScreen> {
 | 
			
		||||
  final PagingController<int, Post> _pagingController =
 | 
			
		||||
      PagingController(firstPageKey: 0);
 | 
			
		||||
 | 
			
		||||
@@ -52,26 +52,7 @@ class _SocialScreenState extends State<SocialScreen> {
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final AuthProvider auth = Get.find();
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      floatingActionButton: FutureBuilder(
 | 
			
		||||
          future: auth.isAuthorized,
 | 
			
		||||
          builder: (context, snapshot) {
 | 
			
		||||
            if (snapshot.hasData && snapshot.data == true) {
 | 
			
		||||
              return FloatingActionButton(
 | 
			
		||||
                child: const Icon(Icons.add),
 | 
			
		||||
                onPressed: () async {
 | 
			
		||||
                  final value =
 | 
			
		||||
                      await AppRouter.instance.pushNamed('postPublishing');
 | 
			
		||||
                  if (value != null) {
 | 
			
		||||
                    _pagingController.refresh();
 | 
			
		||||
                  }
 | 
			
		||||
                },
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            return Container();
 | 
			
		||||
          }),
 | 
			
		||||
      body: Material(
 | 
			
		||||
        color: Theme.of(context).colorScheme.surface,
 | 
			
		||||
        child: RefreshIndicator(
 | 
			
		||||
@@ -79,7 +60,7 @@ class _SocialScreenState extends State<SocialScreen> {
 | 
			
		||||
          child: CustomScrollView(
 | 
			
		||||
            slivers: [
 | 
			
		||||
              SliverAppBar(
 | 
			
		||||
                title: AppBarTitle('social'.tr),
 | 
			
		||||
                title: AppBarTitle('feed'.tr),
 | 
			
		||||
                centerTitle: false,
 | 
			
		||||
                floating: true,
 | 
			
		||||
                titleSpacing: SolianTheme.titleSpacing(context),
 | 
			
		||||
@@ -87,6 +68,7 @@ class _SocialScreenState extends State<SocialScreen> {
 | 
			
		||||
                actions: [
 | 
			
		||||
                  const BackgroundStateWidget(),
 | 
			
		||||
                  const NotificationButton(),
 | 
			
		||||
                  const FeedCreationButton(),
 | 
			
		||||
                  SizedBox(
 | 
			
		||||
                    width: SolianTheme.isLargeScreen(context) ? 8 : 16,
 | 
			
		||||
                  ),
 | 
			
		||||
@@ -100,3 +82,26 @@ class _SocialScreenState extends State<SocialScreen> {
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FeedCreationButton extends StatelessWidget {
 | 
			
		||||
  const FeedCreationButton({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final AuthProvider auth = Get.find();
 | 
			
		||||
 | 
			
		||||
    return FutureBuilder(
 | 
			
		||||
        future: auth.isAuthorized,
 | 
			
		||||
        builder: (context, snapshot) {
 | 
			
		||||
          if (snapshot.hasData && snapshot.data == true) {
 | 
			
		||||
            return IconButton(
 | 
			
		||||
              icon: const Icon(Icons.add_circle),
 | 
			
		||||
              onPressed: () {
 | 
			
		||||
                AppRouter.instance.pushNamed('postPublishing');
 | 
			
		||||
              },
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          return const SizedBox();
 | 
			
		||||
        });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:protocol_handler/protocol_handler.dart';
 | 
			
		||||
import 'package:url_launcher/url_launcher.dart';
 | 
			
		||||
 | 
			
		||||
class ListenerShell extends StatefulWidget {
 | 
			
		||||
  final Widget child;
 | 
			
		||||
 | 
			
		||||
  const ListenerShell({super.key, required this.child});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<ListenerShell> createState() => _ListenerShellState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _ListenerShellState extends State<ListenerShell> with ProtocolListener {
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    protocolHandler.addListener(this);
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void dispose() {
 | 
			
		||||
    protocolHandler.removeListener(this);
 | 
			
		||||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return widget.child;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void onProtocolUrlReceived(String url) {
 | 
			
		||||
    final uri = url.replaceFirst('solink://', '');
 | 
			
		||||
    if (uri == 'auth?status=done') {
 | 
			
		||||
      closeInAppWebView();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:get/get.dart';
 | 
			
		||||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:solian/router.dart';
 | 
			
		||||
import 'package:solian/theme.dart';
 | 
			
		||||
import 'package:solian/widgets/navigation/app_navigation.dart';
 | 
			
		||||
@@ -14,7 +13,6 @@ class NavShell extends StatelessWidget {
 | 
			
		||||
  final bool showSidebar;
 | 
			
		||||
  final bool showNavigation;
 | 
			
		||||
  final bool? showBottomNavigation;
 | 
			
		||||
  final GoRouterState state;
 | 
			
		||||
  final Widget child;
 | 
			
		||||
 | 
			
		||||
  final bool sidebarFirst;
 | 
			
		||||
@@ -23,7 +21,6 @@ class NavShell extends StatelessWidget {
 | 
			
		||||
  const NavShell({
 | 
			
		||||
    super.key,
 | 
			
		||||
    required this.child,
 | 
			
		||||
    required this.state,
 | 
			
		||||
    this.showAppBar = true,
 | 
			
		||||
    this.showSidebar = true,
 | 
			
		||||
    this.showNavigation = true,
 | 
			
		||||
@@ -60,7 +57,7 @@ class NavShell extends StatelessWidget {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: showAppBar
 | 
			
		||||
          ? AppBar(
 | 
			
		||||
              title: Text(state.topRoute?.name?.tr ?? 'page'.tr),
 | 
			
		||||
              title: Text(routeName ?? 'page'.tr),
 | 
			
		||||
              centerTitle: false,
 | 
			
		||||
              titleSpacing: canPop ? null : 24,
 | 
			
		||||
              elevation: SolianTheme.isLargeScreen(context) ? 1 : 0,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								lib/shells/root_shell.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								lib/shells/root_shell.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter_animate/flutter_animate.dart';
 | 
			
		||||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:solian/router.dart';
 | 
			
		||||
import 'package:solian/theme.dart';
 | 
			
		||||
import 'package:solian/widgets/navigation/app_navigation.dart';
 | 
			
		||||
import 'package:solian/widgets/navigation/app_navigation_bottom_bar.dart';
 | 
			
		||||
import 'package:solian/widgets/navigation/app_navigation_rail.dart';
 | 
			
		||||
 | 
			
		||||
class RootShell extends StatelessWidget {
 | 
			
		||||
  final bool showSidebar;
 | 
			
		||||
  final bool showNavigation;
 | 
			
		||||
  final bool? showBottomNavigation;
 | 
			
		||||
  final GoRouterState state;
 | 
			
		||||
  final Widget child;
 | 
			
		||||
 | 
			
		||||
  const RootShell({
 | 
			
		||||
    super.key,
 | 
			
		||||
    required this.state,
 | 
			
		||||
    required this.child,
 | 
			
		||||
    this.showSidebar = true,
 | 
			
		||||
    this.showNavigation = true,
 | 
			
		||||
    this.showBottomNavigation,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final routeName = AppRouter
 | 
			
		||||
        .instance.routerDelegate.currentConfiguration.lastOrNull?.route.name;
 | 
			
		||||
    final showBottom = showBottomNavigation ??
 | 
			
		||||
        AppNavigation.destinationPages.contains(routeName);
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      body: SolianTheme.isLargeScreen(context)
 | 
			
		||||
          ? Row(
 | 
			
		||||
              children: [
 | 
			
		||||
                if (showNavigation) const AppNavigationRail(),
 | 
			
		||||
                if (showNavigation)
 | 
			
		||||
                  const VerticalDivider(thickness: 0.3, width: 1),
 | 
			
		||||
                Expanded(child: child),
 | 
			
		||||
              ],
 | 
			
		||||
            )
 | 
			
		||||
          : Stack(
 | 
			
		||||
              children: [
 | 
			
		||||
                child,
 | 
			
		||||
                Positioned(
 | 
			
		||||
                  bottom: 0,
 | 
			
		||||
                  left: 0,
 | 
			
		||||
                  right: 0,
 | 
			
		||||
                  child: const AppNavigationBottomBar()
 | 
			
		||||
                      .animate(target: showBottom ? 0 : 1)
 | 
			
		||||
                      .slideY(
 | 
			
		||||
                        duration: 250.ms,
 | 
			
		||||
                        begin: 0,
 | 
			
		||||
                        end: 1,
 | 
			
		||||
                        curve: Curves.easeInToLinear,
 | 
			
		||||
                      ),
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@ class SolianMessages extends Translations {
 | 
			
		||||
          'next': 'Next',
 | 
			
		||||
          'reset': 'Reset',
 | 
			
		||||
          'page': 'Page',
 | 
			
		||||
          'social': 'Social',
 | 
			
		||||
          'feed': 'Feed',
 | 
			
		||||
          'chat': 'Chat',
 | 
			
		||||
          'apply': 'Apply',
 | 
			
		||||
          'cancel': 'Cancel',
 | 
			
		||||
@@ -263,7 +263,7 @@ class SolianMessages extends Translations {
 | 
			
		||||
          'edit': '编辑',
 | 
			
		||||
          'delete': '删除',
 | 
			
		||||
          'page': '页面',
 | 
			
		||||
          'social': '社交',
 | 
			
		||||
          'feed': '资讯',
 | 
			
		||||
          'chat': '聊天',
 | 
			
		||||
          'apply': '应用',
 | 
			
		||||
          'search': '搜索',
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,9 @@ import 'package:get/utils.dart';
 | 
			
		||||
abstract class AppNavigation {
 | 
			
		||||
  static List<AppNavigationDestination> destinations = [
 | 
			
		||||
    AppNavigationDestination(
 | 
			
		||||
      icon: const Icon(Icons.public),
 | 
			
		||||
      label: 'social'.tr,
 | 
			
		||||
      page: 'social',
 | 
			
		||||
      icon: const Icon(Icons.feed),
 | 
			
		||||
      label: 'feed'.tr,
 | 
			
		||||
      page: 'feed',
 | 
			
		||||
    ),
 | 
			
		||||
    AppNavigationDestination(
 | 
			
		||||
      icon: const Icon(Icons.forum),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user