♻️ Refactor the bottom nav display

This commit is contained in:
2025-10-01 16:35:41 +08:00
parent ac2951479b
commit 3bfc0b8181
12 changed files with 47 additions and 103 deletions

View File

@@ -100,10 +100,6 @@ Future<ThemeData> createAppTheme(
opticalSize: 20, opticalSize: 20,
color: colorScheme.onSurface, color: colorScheme.onSurface,
), ),
snackBarTheme: SnackBarThemeData(
behavior: useM3 ? SnackBarBehavior.floating : SnackBarBehavior.fixed,
width: 480,
),
appBarTheme: AppBarTheme( appBarTheme: AppBarTheme(
centerTitle: true, centerTitle: true,
elevation: hasAppBarTransparent ? 0 : null, elevation: hasAppBarTransparent ? 0 : null,

View File

@@ -66,7 +66,6 @@ class AccountScreen extends HookConsumerWidget {
isNoBackground: isWide, isNoBackground: isWide,
appBar: AppBar(backgroundColor: Colors.transparent, toolbarHeight: 0), appBar: AppBar(backgroundColor: Colors.transparent, toolbarHeight: 0),
body: SingleChildScrollView( body: SingleChildScrollView(
padding: getTabbedPadding(context),
child: Column( child: Column(
spacing: 4, spacing: 4,
children: <Widget>[ children: <Widget>[

View File

@@ -10,7 +10,6 @@ import 'package:island/models/wallet.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/screens/account/credits.dart'; import 'package:island/screens/account/credits.dart';
import 'package:island/services/responsive.dart';
import 'package:island/services/time.dart'; import 'package:island/services/time.dart';
import 'package:island/widgets/account/leveling_progress.dart'; import 'package:island/widgets/account/leveling_progress.dart';
import 'package:island/widgets/account/restore_purchase_sheet.dart'; import 'package:island/widgets/account/restore_purchase_sheet.dart';
@@ -259,7 +258,7 @@ class LevelingScreen extends HookConsumerWidget {
), ),
), ),
SliverGap(getTabbedPadding(context, vertical: 20).vertical), SliverGap(20),
], ],
), ),
), ),
@@ -270,7 +269,7 @@ class LevelingScreen extends HookConsumerWidget {
final stellarSubscription = ref.watch(accountStellarSubscriptionProvider); final stellarSubscription = ref.watch(accountStellarSubscriptionProvider);
return SingleChildScrollView( return SingleChildScrollView(
padding: getTabbedPadding(context, horizontal: 20, vertical: 20), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [

View File

@@ -25,7 +25,6 @@ import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/content/sheet.dart'; import 'package:island/widgets/content/sheet.dart';
import 'package:island/widgets/realm/realm_selection_dropdown.dart'; import 'package:island/widgets/realm/realm_selection_dropdown.dart';
import 'package:island/widgets/response.dart'; import 'package:island/widgets/response.dart';
import 'package:island/screens/tabs.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:relative_time/relative_time.dart'; import 'package:relative_time/relative_time.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -219,9 +218,8 @@ class ChatListBodyWidget extends HookConsumerWidget {
ref.invalidate(chatroomsJoinedProvider); ref.invalidate(chatroomsJoinedProvider);
}), }),
child: ListView.builder( child: ListView.builder(
padding: getTabbedPadding( padding: EdgeInsets.only(
context, bottom: callState.isConnected ? 96 : 0,
bottom: callState.isConnected ? 96 : null,
), ),
itemCount: itemCount:
items items
@@ -531,7 +529,6 @@ class ChatListScreen extends HookConsumerWidget {
}, },
child: const Icon(Symbols.add), child: const Icon(Symbols.add),
), ),
floatingActionButtonLocation: TabbedFabLocation(context),
body: ChatListBodyWidget( body: ChatListBodyWidget(
isFloating: false, isFloating: false,
tabController: tabController, tabController: tabController,

View File

@@ -15,7 +15,6 @@ import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/screens/realm/realms.dart'; import 'package:island/screens/realm/realms.dart';
import 'package:island/services/file.dart'; import 'package:island/services/file.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/cloud_files.dart';
@@ -191,7 +190,7 @@ class EditPublisherScreen extends HookConsumerWidget {
leading: const PageBackButton(), leading: const PageBackButton(),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
padding: getTabbedPadding(context, bottom: 16), padding: EdgeInsets.only(bottom: 16),
child: Column( child: Column(
children: [ children: [
RealmSelectionDropdown( RealmSelectionDropdown(

View File

@@ -13,7 +13,6 @@ import 'package:island/pods/event_calendar.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/screens/notification.dart'; import 'package:island/screens/notification.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/app_scaffold.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
import 'package:island/widgets/check_in.dart'; import 'package:island/widgets/check_in.dart';
@@ -21,7 +20,6 @@ import 'package:island/widgets/post/post_featured.dart';
import 'package:island/widgets/post/post_item.dart'; import 'package:island/widgets/post/post_item.dart';
import 'package:island/widgets/post/compose_card.dart'; import 'package:island/widgets/post/compose_card.dart';
import 'package:island/widgets/post/compose_dialog.dart'; import 'package:island/widgets/post/compose_dialog.dart';
import 'package:island/screens/tabs.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
@@ -231,7 +229,6 @@ class ExploreScreen extends HookConsumerWidget {
child: const Icon(Symbols.edit), child: const Icon(Symbols.edit),
), ),
), ),
floatingActionButtonLocation: isWide ? null : TabbedFabLocation(context),
body: body:
isWide isWide
? _buildWideBody( ? _buildWideBody(
@@ -415,7 +412,6 @@ class ExploreScreen extends HookConsumerWidget {
), ),
), ),
bodyView, bodyView,
SliverGap(getTabbedPadding(context).bottom),
], ],
), ),
).padding(horizontal: 8), ).padding(horizontal: 8),

View File

@@ -12,13 +12,11 @@ import 'package:island/models/realm.dart';
import 'package:island/pods/config.dart'; import 'package:island/pods/config.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/services/file.dart'; import 'package:island/services/file.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/content/sheet.dart'; import 'package:island/widgets/content/sheet.dart';
import 'package:island/widgets/response.dart'; import 'package:island/widgets/response.dart';
import 'package:island/screens/tabs.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
@@ -90,7 +88,6 @@ class RealmListScreen extends HookConsumerWidget {
}); });
}, },
), ),
floatingActionButtonLocation: TabbedFabLocation(context),
body: ExtendedRefreshIndicator( body: ExtendedRefreshIndicator(
child: realms.when( child: realms.when(
data: data:
@@ -100,7 +97,7 @@ class RealmListScreen extends HookConsumerWidget {
child: ListView.separated( child: ListView.separated(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: 8, top: 8,
bottom: getTabbedPadding(context).bottom + 8, bottom: MediaQuery.of(context).padding.bottom + 8,
), ),
itemCount: value.length, itemCount: value.length,
itemBuilder: (context, item) { itemBuilder: (context, item) {

View File

@@ -99,57 +99,44 @@ class TabsScreen extends HookConsumerWidget {
); );
} }
return Container( return Scaffold(
color: Theme.of(context).colorScheme.surfaceContainer, backgroundColor: Colors.transparent,
child: Stack( extendBody: true,
children: [ body: ClipRRect(
Positioned.fill( borderRadius: const BorderRadius.only(
child: ClipRRect( topLeft: Radius.circular(16),
borderRadius: const BorderRadius.only( topRight: Radius.circular(16),
topLeft: Radius.circular(16), ),
topRight: Radius.circular(16), child: child ?? const SizedBox.shrink(),
),
bottomNavigationBar: ConditionalBottomNav(
child: ClipRRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.8),
), ),
child: child ?? const SizedBox.shrink(), child: MediaQuery.removePadding(
), context: context,
), removeTop: true,
Positioned( child: NavigationBar(
left: 0, backgroundColor: Colors.transparent,
right: 0, shadowColor: Colors.transparent,
bottom: 0, overlayColor: const WidgetStatePropertyAll(
child: ConditionalBottomNav( Colors.transparent,
child: ClipRRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
decoration: BoxDecoration(
color: Theme.of(
context,
).colorScheme.surface.withOpacity(0.8),
),
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: NavigationBar(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
overlayColor: const WidgetStatePropertyAll(
Colors.transparent,
),
surfaceTintColor: Colors.transparent,
height: 56,
labelBehavior:
NavigationDestinationLabelBehavior.alwaysHide,
selectedIndex: currentIndex,
onDestinationSelected: onDestinationSelected,
destinations: destinations,
),
),
), ),
surfaceTintColor: Colors.transparent,
height: 56,
labelBehavior: NavigationDestinationLabelBehavior.alwaysHide,
selectedIndex: currentIndex,
onDestinationSelected: onDestinationSelected,
destinations: destinations,
), ),
), ),
), ),
), ),
], ),
), ),
); );
} }
@@ -178,7 +165,6 @@ class TabbedFabLocation extends FloatingActionButtonLocation {
scaffoldGeometry.floatingActionButtonSize.height - scaffoldGeometry.floatingActionButtonSize.height -
scaffoldGeometry.bottomSheetSize.height - scaffoldGeometry.bottomSheetSize.height -
safeAreaPadding.bottom - safeAreaPadding.bottom -
(isWideScreen(context) ? 32 : 80) +
16; 16;
return Offset(fabX, fabY); return Offset(fabX, fabY);

View File

@@ -15,32 +15,3 @@ bool isWiderScreen(BuildContext context) {
bool isWidestScreen(BuildContext context) { bool isWidestScreen(BuildContext context) {
return MediaQuery.of(context).size.width > kWidescreenWidth; return MediaQuery.of(context).size.width > kWidescreenWidth;
} }
EdgeInsets getTabbedPadding(
BuildContext context, {
double? horizontal,
double? vertical,
double? left,
double? right,
double? top,
double? bottom,
}) {
if (isWideScreen(context)) {
return EdgeInsets.only(
left: left ?? horizontal ?? 0,
right: right ?? horizontal ?? 0,
top: top ?? vertical ?? 0,
bottom: bottom ?? vertical ?? 0,
);
}
final effectiveBottom = bottom ?? vertical;
return EdgeInsets.only(
left: left ?? horizontal ?? 0,
right: right ?? horizontal ?? 0,
top: top ?? vertical ?? 0,
bottom:
effectiveBottom != null
? effectiveBottom + MediaQuery.of(context).padding.bottom + 56
: MediaQuery.of(context).padding.bottom + 56,
);
}

View File

@@ -4,7 +4,6 @@ import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/screens/account/me/settings_connections.dart'; import 'package:island/screens/account/me/settings_connections.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/content/sheet.dart'; import 'package:island/widgets/content/sheet.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@@ -50,7 +49,6 @@ class RestorePurchaseSheet extends HookConsumerWidget {
return SheetScaffold( return SheetScaffold(
titleText: 'restorePurchase'.tr(), titleText: 'restorePurchase'.tr(),
child: SingleChildScrollView( child: SingleChildScrollView(
padding: getTabbedPadding(context),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [

View File

@@ -10,6 +10,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/config.dart'; import 'package:island/pods/config.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/pods/websocket.dart'; import 'package:island/pods/websocket.dart';
import 'package:island/screens/tabs.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@@ -292,7 +293,7 @@ class AppScaffold extends HookConsumerWidget {
endDrawer: endDrawer, endDrawer: endDrawer,
floatingActionButton: floatingActionButton, floatingActionButton: floatingActionButton,
floatingActionButtonAnimator: floatingActionButtonAnimator, floatingActionButtonAnimator: floatingActionButtonAnimator,
floatingActionButtonLocation: floatingActionButtonLocation, floatingActionButtonLocation: TabbedFabLocation(context),
onDrawerChanged: onDrawerChanged, onDrawerChanged: onDrawerChanged,
onEndDrawerChanged: onEndDrawerChanged, onEndDrawerChanged: onEndDrawerChanged,
), ),

View File

@@ -5,6 +5,7 @@ import 'package:island/models/file.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
import 'package:island/screens/posts/compose.dart'; import 'package:island/screens/posts/compose.dart';
import 'package:island/services/compose_storage_db.dart'; import 'package:island/services/compose_storage_db.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/post/compose_card.dart'; import 'package:island/widgets/post/compose_card.dart';
/// A dialog that wraps PostComposeCard for easy use in dialogs. /// A dialog that wraps PostComposeCard for easy use in dialogs.
@@ -36,6 +37,7 @@ class PostComposeDialog extends HookConsumerWidget {
final drafts = ref.watch(composeStorageNotifierProvider); final drafts = ref.watch(composeStorageNotifierProvider);
final restoredInitialState = useState<PostComposeInitialState?>(null); final restoredInitialState = useState<PostComposeInitialState?>(null);
final prompted = useState(false); final prompted = useState(false);
final isWide = isWideScreen(context);
useEffect(() { useEffect(() {
if (!prompted.value && originalPost == null && drafts.isNotEmpty) { if (!prompted.value && originalPost == null && drafts.isNotEmpty) {
@@ -48,9 +50,12 @@ class PostComposeDialog extends HookConsumerWidget {
}, [drafts, prompted.value]); }, [drafts, prompted.value]);
return Dialog( return Dialog(
insetPadding: const EdgeInsets.all(16), insetPadding: isWide ? const EdgeInsets.all(16) : EdgeInsets.zero,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 600, maxHeight: 700), constraints:
isWide
? const BoxConstraints(maxWidth: 600)
: const BoxConstraints.expand(),
child: PostComposeCard( child: PostComposeCard(
originalPost: originalPost, originalPost: originalPost,
initialState: restoredInitialState.value ?? initialState, initialState: restoredInitialState.value ?? initialState,