Skip to content

Commit

Permalink
feat: rework the bottom bar for mobile (#1073)
Browse files Browse the repository at this point in the history
  • Loading branch information
Feichtmeier authored Dec 1, 2024
1 parent 474ab9c commit 0e2a40c
Show file tree
Hide file tree
Showing 46 changed files with 322 additions and 247 deletions.
4 changes: 2 additions & 2 deletions lib/app/app_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import 'package:flutter/widgets.dart';
import 'package:github/github.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:safe_change_notifier/safe_change_notifier.dart';
import 'package:yaru/theme.dart';

import '../app_config.dart';
import '../constants.dart';
import '../expose/expose_service.dart';
import '../settings/settings_service.dart';
Expand Down Expand Up @@ -67,7 +67,7 @@ class AppModel extends SafeChangeNotifier {
if (value == null || value == _fullWindowMode) return;
_fullWindowMode = value;

if (isMobile) {
if (isMobilePlatform) {
if (_fullWindowMode == true) {
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
} else {
Expand Down
3 changes: 2 additions & 1 deletion lib/app/view/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:system_theme/system_theme.dart';
import 'package:yaru/yaru.dart';

import '../../app_config.dart';
import '../../common/view/theme.dart';
import 'desktop_musicpod_app.dart';
import 'mobile_musicpod_app.dart';
Expand All @@ -28,7 +29,7 @@ class MaterialMusicPodApp extends StatelessWidget {
@override
Widget build(BuildContext context) => SystemThemeBuilder(
builder: (context, accent) {
return isMobile
return isMobilePlatform
? MobileMusicPodApp(accent: accent.accent)
: DesktopMusicPodApp(accent: accent.accent);
},
Expand Down
2 changes: 1 addition & 1 deletion lib/app/view/desktop_scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class _DesktopScaffoldState extends State<DesktopScaffold> {
child: Column(
children: [
const Expanded(child: MasterDetailPage()),
if (!playerToTheRight || isMobile)
if (!playerToTheRight || isMobilePlatform)
const PlayerView(position: PlayerPosition.bottom),
],
),
Expand Down
3 changes: 2 additions & 1 deletion lib/app/view/master_detail_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:watch_it/watch_it.dart';
import 'package:yaru/yaru.dart';

import '../../app_config.dart';
import '../../common/view/back_gesture.dart';
import '../../common/view/global_keys.dart';
import '../../common/view/header_bar.dart';
Expand Down Expand Up @@ -49,7 +50,7 @@ class MasterDetailPage extends StatelessWidget with WatchItMixin {
);

return Scaffold(
resizeToAvoidBottomInset: isMobile ? false : null,
resizeToAvoidBottomInset: isMobilePlatform ? false : null,
key: masterScaffoldKey,
endDrawer: Platform.isMacOS ? drawer : null,
drawer: Platform.isMacOS ? null : drawer,
Expand Down
4 changes: 2 additions & 2 deletions lib/app/view/master_items.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:yaru/yaru.dart';

import '../../app_config.dart';
import '../../common/data/audio_type.dart';
import '../../common/view/icons.dart';
import '../../common/view/side_bar_fall_back_image.dart';
Expand Down Expand Up @@ -75,7 +75,7 @@ List<MasterItem> createMasterItems({required LibraryModel libraryModel}) {
),
pageId: kPodcastsPageId,
),
if (isMobile)
if (isMobilePlatform)
MasterItem(
titleBuilder: (context) => Text(context.l10n.settings),
iconBuilder: (selected) =>
Expand Down
88 changes: 17 additions & 71 deletions lib/app/view/mobile_bottom_bar.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
import 'package:flutter/material.dart';
import 'package:watch_it/watch_it.dart';

import '../../common/data/audio_type.dart';
import '../../common/view/icons.dart';
import '../../common/view/theme.dart';
import '../../common/view/ui_constants.dart';
import '../../constants.dart';
import '../../extensions/build_context_x.dart';
import '../../l10n/l10n.dart';
import '../../library/library_model.dart';
import '../../player/player_model.dart';
import '../../player/view/bottom_player.dart';
import '../app_model.dart';
import 'main_page_icon.dart';
import 'mobile_navigation_bar.dart';

class MobileBottomBar extends StatelessWidget with WatchItMixin {
const MobileBottomBar({
super.key,
});
const MobileBottomBar({super.key});

@override
Widget build(BuildContext context) {
final fullWindowMode =
watchPropertyValue((AppModel m) => m.fullWindowMode) ?? false;
return SizedBox(
width: context.mediaQuerySize.width,
child: RepaintBoundary(
Expand All @@ -30,68 +20,24 @@ class MobileBottomBar extends StatelessWidget with WatchItMixin {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: bottomPlayerHeight, child: const BottomPlayer()),
const SizedBox(height: kMediumSpace),
if (!fullWindowMode) const MobileNavigationBar(),
GestureDetector(
onVerticalDragUpdate: (details) {
di<PlayerModel>().bottomPlayerHeight =
context.mediaQuerySize.height - details.globalPosition.dy;
},
onVerticalDragEnd: (details) {
if (details.primaryVelocity != null &&
details.primaryVelocity! < 150) {
di<AppModel>().setFullWindowMode(true);
}
},
child: const BottomPlayer(),
),
const MobileNavigationBar(),
],
),
),
),
);
}
}

class MobileNavigationBar extends StatelessWidget with WatchItMixin {
const MobileNavigationBar({super.key});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

final selectedPageId =
watchPropertyValue((LibraryModel m) => m.selectedPageId);

final destinations = <String, IconButton>{
kLocalAudioPageId: IconButton(
isSelected: selectedPageId == kLocalAudioPageId,
selectedIcon:
const MainPageIcon(selected: true, audioType: AudioType.local),
icon: const MainPageIcon(selected: false, audioType: AudioType.local),
tooltip: l10n.local,
onPressed: () => di<LibraryModel>().push(pageId: kLocalAudioPageId),
),
kRadioPageId: IconButton(
isSelected: selectedPageId == kRadioPageId,
selectedIcon:
const MainPageIcon(selected: true, audioType: AudioType.radio),
icon: const MainPageIcon(selected: false, audioType: AudioType.radio),
tooltip: l10n.radio,
onPressed: () => di<LibraryModel>().push(pageId: kRadioPageId),
),
kPodcastsPageId: IconButton(
isSelected: selectedPageId == kPodcastsPageId,
selectedIcon:
const MainPageIcon(selected: true, audioType: AudioType.podcast),
icon: const MainPageIcon(selected: false, audioType: AudioType.podcast),
tooltip: l10n.podcasts,
onPressed: () => di<LibraryModel>().push(pageId: kPodcastsPageId),
),
kSettingsPageId: IconButton(
isSelected: selectedPageId == kSettingsPageId,
selectedIcon: Icon(Iconz.settingsFilled),
icon: Icon(Iconz.settings),
tooltip: l10n.settings,
onPressed: () => di<LibraryModel>().push(pageId: kSettingsPageId),
),
};

return SizedBox(
height: navigationBarHeight,
width: context.mediaQuerySize.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: destinations.values.toList(),
),
);
}
}
29 changes: 15 additions & 14 deletions lib/app/view/mobile_musicpod_app.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import 'dart:ui';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:phoenix_theme/phoenix_theme.dart';
import 'package:watch_it/watch_it.dart';

import '../../app_config.dart';
import '../../common/view/theme.dart';
import '../../constants.dart';
import '../../external_path/external_path_service.dart';
Expand All @@ -6,14 +14,8 @@ import '../../library/library_model.dart';
import '../../radio/radio_model.dart';
import '../../settings/settings_model.dart';
import '../connectivity_model.dart';
import 'dart:ui';
import 'master_items.dart';
import 'mobile_page_with_player.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:phoenix_theme/phoenix_theme.dart';
import 'package:watch_it/watch_it.dart';
import 'package:yaru/yaru.dart';
import 'mobile_page.dart';
import 'splash_screen.dart';

class MobileMusicPodApp extends StatefulWidget with WatchItStatefulWidgetMixin {
Expand Down Expand Up @@ -54,8 +56,9 @@ class _MobileMusicPodAppState extends State<MobileMusicPodApp> {
return MaterialApp(
navigatorKey: libraryModel.masterNavigatorKey,
navigatorObservers: [libraryModel],
initialRoute:
isMobile ? (libraryModel.selectedPageId ?? kLocalAudioPageId) : null,
initialRoute: isMobilePlatform
? (libraryModel.selectedPageId ?? kLocalAudioPageId)
: null,
onGenerateRoute: (settings) {
final page = (masterItems.firstWhereOrNull(
(e) => e.pageId == settings.name,
Expand All @@ -67,11 +70,9 @@ class _MobileMusicPodAppState extends State<MobileMusicPodApp> {
settings: settings,
pageBuilder: (_, __, ___) => FutureBuilder(
future: _initFuture,
builder: (context, snapshot) {
return snapshot.data == true
? MobilePageWithPlayer(page: page)
: const SplashScreen();
},
builder: (context, snapshot) => snapshot.data == true
? MobilePage(page: page)
: const SplashScreen(),
),
transitionsBuilder: (_, a, __, c) =>
FadeTransition(opacity: a, child: c),
Expand Down
89 changes: 89 additions & 0 deletions lib/app/view/mobile_navigation_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import '../../common/data/audio_type.dart';
import '../../common/view/icons.dart';
import '../../common/view/theme.dart';
import '../../common/view/ui_constants.dart';
import '../../constants.dart';
import '../../l10n/l10n.dart';
import '../../library/library_model.dart';
import 'main_page_icon.dart';
import 'package:flutter/material.dart';
import 'package:watch_it/watch_it.dart';

class MobileNavigationBar extends StatelessWidget with WatchItMixin {
const MobileNavigationBar({super.key});

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

final selectedPageId =
watchPropertyValue((LibraryModel m) => m.selectedPageId);

return SizedBox(
height: navigationBarHeight,
child: Padding(
padding: const EdgeInsets.only(top: kMediumSpace),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
isSelected: selectedPageId == kLikedAudiosPageId,
selectedIcon: Icon(Iconz.heartFilled),
icon: Icon(Iconz.heart),
tooltip: l10n.local,
onPressed: () =>
di<LibraryModel>().push(pageId: kLikedAudiosPageId),
),
IconButton(
isSelected: selectedPageId == kLocalAudioPageId,
selectedIcon: const MainPageIcon(
selected: true,
audioType: AudioType.local,
),
icon: const MainPageIcon(
selected: false,
audioType: AudioType.local,
),
tooltip: l10n.local,
onPressed: () =>
di<LibraryModel>().push(pageId: kLocalAudioPageId),
),
IconButton(
isSelected: selectedPageId == kRadioPageId,
selectedIcon: const MainPageIcon(
selected: true,
audioType: AudioType.radio,
),
icon: const MainPageIcon(
selected: false,
audioType: AudioType.radio,
),
tooltip: l10n.radio,
onPressed: () => di<LibraryModel>().push(pageId: kRadioPageId),
),
IconButton(
isSelected: selectedPageId == kPodcastsPageId,
selectedIcon: const MainPageIcon(
selected: true,
audioType: AudioType.podcast,
),
icon: const MainPageIcon(
selected: false,
audioType: AudioType.podcast,
),
tooltip: l10n.podcasts,
onPressed: () => di<LibraryModel>().push(pageId: kPodcastsPageId),
),
IconButton(
isSelected: selectedPageId == kSettingsPageId,
selectedIcon: Icon(Iconz.settingsFilled),
icon: Icon(Iconz.settings),
tooltip: l10n.settings,
onPressed: () => di<LibraryModel>().push(pageId: kSettingsPageId),
),
],
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import '../../player/view/player_view.dart';
import '../app_model.dart';
import 'mobile_bottom_bar.dart';

class MobilePageWithPlayer extends StatelessWidget with WatchItMixin {
const MobilePageWithPlayer({
class MobilePage extends StatelessWidget with WatchItMixin {
const MobilePage({
super.key,
required this.page,
});
Expand All @@ -27,11 +27,14 @@ class MobilePageWithPlayer extends StatelessWidget with WatchItMixin {
children: [
page,
if (fullWindowMode)
const Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
body: FullHeightPlayer(
playerPosition: PlayerPosition.fullWindow,
const Hero(
tag: 'full_height_player',
child: Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
body: FullHeightPlayer(
playerPosition: PlayerPosition.fullWindow,
),
),
)
else
Expand Down
Loading

0 comments on commit 0e2a40c

Please sign in to comment.