diff --git a/lib/components/connect/connect_device.dart b/lib/components/connect/connect_device.dart index 8ece074f..14243fa8 100644 --- a/lib/components/connect/connect_device.dart +++ b/lib/components/connect/connect_device.dart @@ -7,7 +7,9 @@ import 'package:spotube/provider/connect/clients.dart'; import 'package:spotube/utils/service_utils.dart'; class ConnectDeviceButton extends HookConsumerWidget { - const ConnectDeviceButton({super.key}); + final bool _sidebar; + const ConnectDeviceButton({super.key}) : _sidebar = false; + const ConnectDeviceButton.sidebar({super.key}) : _sidebar = true; @override Widget build(BuildContext context, ref) { @@ -15,6 +17,35 @@ class ConnectDeviceButton extends HookConsumerWidget { final pixelRatio = MediaQuery.of(context).devicePixelRatio; final connectClients = ref.watch(connectClientsProvider); + if (_sidebar) { + return SizedBox( + width: double.infinity, + child: TextButton( + onPressed: () { + ServiceUtils.push(context, "/connect"); + }, + style: FilledButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.all(5), + ), + child: Row( + children: [ + Text(context.l10n.devices), + if (connectClients.asData?.value.services.isNotEmpty == true) + Text( + " (${connectClients.asData?.value.services.length})", + ), + const Spacer(), + const Icon(SpotubeIcons.speaker), + const Gap(5), + ], + ), + ), + ); + } + return SizedBox( height: 40 * pixelRatio, child: Stack( diff --git a/lib/components/root/sidebar.dart b/lib/components/root/sidebar.dart index 2a9e3af8..f49a9c0d 100644 --- a/lib/components/root/sidebar.dart +++ b/lib/components/root/sidebar.dart @@ -1,5 +1,6 @@ import 'package:collection/collection.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:flutter/material.dart'; @@ -8,6 +9,7 @@ import 'package:sidebarx/sidebarx.dart'; import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/collections/side_bar_tiles.dart'; import 'package:spotube/collections/spotube_icons.dart'; +import 'package:spotube/components/connect/connect_device.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; @@ -261,43 +263,50 @@ class SidebarFooter extends HookConsumerWidget { return Container( padding: const EdgeInsets.only(left: 12), width: 250, - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: Column( children: [ - if (auth != null && data == null) - const CircularProgressIndicator() - else if (data != null) - Flexible( - child: Row( - children: [ - CircleAvatar( - backgroundImage: UniversalImage.imageProvider(avatarImg), - onBackgroundImageError: (exception, stackTrace) => - Assets.userPlaceholder.image( - height: 16, - width: 16, - ), + const ConnectDeviceButton.sidebar(), + const Gap(10), + Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (auth != null && data == null) + const CircularProgressIndicator() + else if (data != null) + Flexible( + child: Row( + children: [ + CircleAvatar( + backgroundImage: + UniversalImage.imageProvider(avatarImg), + onBackgroundImageError: (exception, stackTrace) => + Assets.userPlaceholder.image( + height: 16, + width: 16, + ), + ), + const SizedBox(width: 10), + Flexible( + child: Text( + data.displayName ?? context.l10n.guest, + maxLines: 1, + softWrap: false, + overflow: TextOverflow.fade, + style: theme.textTheme.bodyMedium + ?.copyWith(fontWeight: FontWeight.bold), + ), + ), + ], ), - const SizedBox(width: 10), - Flexible( - child: Text( - data.displayName ?? context.l10n.guest, - maxLines: 1, - softWrap: false, - overflow: TextOverflow.fade, - style: theme.textTheme.bodyMedium - ?.copyWith(fontWeight: FontWeight.bold), - ), - ), - ], + ), + IconButton( + icon: const Icon(SpotubeIcons.settings), + onPressed: () { + Sidebar.goToSettings(context); + }, ), - ), - IconButton( - icon: const Icon(SpotubeIcons.settings), - onPressed: () { - Sidebar.goToSettings(context); - }, + ], ), ], ), diff --git a/lib/main.dart b/lib/main.dart index d6df20ea..95724c79 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -230,7 +230,7 @@ class SpotubeState extends ConsumerState { builder: (context, child) { return DevicePreview.appBuilder( context, - DesktopTools.platform.isDesktop + DesktopTools.platform.isDesktop && !DesktopTools.platform.isMacOS ? DragToResizeArea(child: child!) : child, ); diff --git a/lib/pages/home/home.dart b/lib/pages/home/home.dart index 487ceb4c..7b70794d 100644 --- a/lib/pages/home/home.dart +++ b/lib/pages/home/home.dart @@ -11,6 +11,8 @@ import 'package:spotube/components/home/sections/genres.dart'; import 'package:spotube/components/home/sections/made_for_user.dart'; import 'package:spotube/components/home/sections/new_releases.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; +import 'package:spotube/extensions/constrains.dart'; +import 'package:spotube/utils/platform.dart'; class HomePage extends HookConsumerWidget { const HomePage({super.key}); @@ -18,6 +20,7 @@ class HomePage extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { final controller = useScrollController(); + final mediaQuery = MediaQuery.of(context); return SafeArea( bottom: false, @@ -25,18 +28,21 @@ class HomePage extends HookConsumerWidget { body: CustomScrollView( controller: controller, slivers: [ - PageWindowTitleBar.sliver( - pinned: DesktopTools.platform.isDesktop, - actions: [ - const ConnectDeviceButton(), - const Gap(10), - IconButton.filledTonal( - icon: const Icon(SpotubeIcons.user), - onPressed: () {}, - ), - const Gap(10), - ], - ), + if (mediaQuery.mdAndDown) + PageWindowTitleBar.sliver( + pinned: DesktopTools.platform.isDesktop, + actions: [ + const ConnectDeviceButton(), + const Gap(10), + IconButton.filledTonal( + icon: const Icon(SpotubeIcons.user), + onPressed: () {}, + ), + const Gap(10), + ], + ) + else if (kIsMacOS) + const SliverGap(10), const HomeGenresSection(), const SliverToBoxAdapter(child: HomeFeaturedSection()), const HomePageFriendsSection(),