feat(title_bar): platform specific title bar

This commit is contained in:
Kingkor Roy Tirtho 2022-11-11 13:01:23 +06:00
parent 54048cbfc3
commit e659e3c56f
7 changed files with 59 additions and 156 deletions

View File

@ -54,8 +54,8 @@ class ArtistProfile extends HookConsumerWidget {
return SafeArea( return SafeArea(
child: PlatformScaffold( child: PlatformScaffold(
appBar: const PageWindowTitleBar( appBar: PageWindowTitleBar(
leading: PlatformBackButton(), leading: const PlatformBackButton(),
), ),
body: HookBuilder( body: HookBuilder(
builder: (context) { builder: (context) {

View File

@ -13,7 +13,7 @@ import 'package:spotube/hooks/useUpdateChecker.dart';
import 'package:spotube/provider/Downloader.dart'; import 'package:spotube/provider/Downloader.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
const _path = { const rootPaths = {
0: "/", 0: "/",
1: "/search", 1: "/search",
2: "/library", 2: "/library",
@ -64,34 +64,40 @@ class Shell extends HookConsumerWidget {
return null; return null;
}, [backgroundColor]); }, [backgroundColor]);
final allowedPath = _path.values.contains(GoRouter.of(context).location); final allowedPath =
final preferredSize = rootPaths.values.contains(GoRouter.of(context).location);
allowedPath ? PageWindowTitleBar.staticPreferredSize : Size.zero; final titleBar = PageWindowTitleBar(
return Scaffold( backgroundColor:
appBar: kIsDesktop platform == TargetPlatform.android ? Colors.transparent : null,
);
final preferredSize = allowedPath ? titleBar.preferredSize : Size.zero;
var appBar = kIsDesktop
? PreferredSize( ? PreferredSize(
preferredSize: preferredSize, preferredSize: preferredSize,
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
height: allowedPath height: allowedPath ? titleBar.preferredSize.height : 0,
? PageWindowTitleBar.staticPreferredSize.height
: 0,
child: AnimatedOpacity( child: AnimatedOpacity(
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
opacity: allowedPath ? 1 : 0, opacity: allowedPath ? 1 : 0,
child: PageWindowTitleBar(preferredSize: preferredSize), child: titleBar,
), ),
), ),
) )
: null, : null;
extendBodyBehindAppBar: true, return PlatformScaffold(
appBar: platform == TargetPlatform.windows ? appBar : null,
extendBodyBehindAppBar: false,
body: Sidebar( body: Sidebar(
selectedIndex: index.value, selectedIndex: index.value,
onSelectedIndexChanged: (i) { onSelectedIndexChanged: (i) {
index.value = i; index.value = i;
GoRouter.of(context).go(_path[index.value]!); GoRouter.of(context).go(rootPaths[index.value]!);
}, },
child: child, child: PlatformScaffold(
appBar: platform != TargetPlatform.windows ? appBar : null,
body: child,
),
), ),
extendBody: true, extendBody: true,
bottomNavigationBar: Column( bottomNavigationBar: Column(
@ -102,7 +108,7 @@ class Shell extends HookConsumerWidget {
selectedIndex: index.value, selectedIndex: index.value,
onSelectedIndexChanged: (selectedIndex) { onSelectedIndexChanged: (selectedIndex) {
index.value = selectedIndex; index.value = selectedIndex;
GoRouter.of(context).go(_path[selectedIndex]!); GoRouter.of(context).go(rootPaths[selectedIndex]!);
}, },
), ),
], ],

View File

@ -110,7 +110,7 @@ class Sidebar extends HookConsumerWidget {
expanded: extended.value, expanded: extended.value,
header: Column( header: Column(
children: [ children: [
if (kIsDesktop) if (kIsMacOS)
SizedBox( SizedBox(
height: appWindow.titleBarHeight, height: appWindow.titleBarHeight,
width: extended.value ? 256 : 80, width: extended.value ? 256 : 80,

View File

@ -16,7 +16,7 @@ class TokenLogin extends HookConsumerWidget {
return SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(
appBar: const PageWindowTitleBar(leading: PlatformBackButton()), appBar: PageWindowTitleBar(leading: PlatformBackButton()),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Center( child: Center(
child: Container( child: Container(

View File

@ -20,8 +20,8 @@ class PlaylistGenreView extends ConsumerWidget {
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
return Scaffold( return Scaffold(
appBar: const PageWindowTitleBar( appBar: PageWindowTitleBar(
leading: PlatformBackButton(), leading: const PlatformBackButton(),
), ),
body: Column( body: Column(
children: [ children: [

View File

@ -1,132 +1,29 @@
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:fluent_ui/fluent_ui.dart' show FluentTheme;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:platform_ui/platform_ui.dart'; import 'package:platform_ui/platform_ui.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
class TitleBarActionButtons extends StatelessWidget { class PageWindowTitleBar extends PlatformAppBar {
final Color? color; PageWindowTitleBar({
const TitleBarActionButtons({ super.backgroundColor,
Key? key, List<Widget>? actions,
this.color, super.actionsIconTheme,
}) : super(key: key); super.automaticallyImplyLeading = false,
super.centerTitle,
@override super.foregroundColor,
Widget build(BuildContext context) { super.key,
return TextButtonTheme( super.leading,
data: TextButtonThemeData( super.leadingWidth,
style: ButtonStyle( Widget? center,
splashFactory: NoSplash.splashFactory, super.titleSpacing,
shape: MaterialStateProperty.all(const RoundedRectangleBorder()), super.titleTextStyle,
overlayColor: MaterialStateProperty.all(Colors.black12), super.titleWidth,
padding: MaterialStateProperty.all(EdgeInsets.zero), super.toolbarOpacity,
minimumSize: MaterialStateProperty.all(const Size(50, 40)), super.toolbarTextStyle,
maximumSize: MaterialStateProperty.all(const Size(50, 40)), }) : super(
), actions: [
), ...?actions,
child: IconTheme( if (!kIsMacOS && !kIsMobile) const PlatformWindowButtons(),
data: const IconThemeData(size: 16),
child: Row(
children: [
TextButton(
onPressed: () {
appWindow.minimize();
},
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
PlatformTheme.of(context).iconTheme?.color),
),
child: Icon(
Icons.minimize_rounded,
color: color,
)),
TextButton(
onPressed: () async {
appWindow.maximizeOrRestore();
},
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
PlatformTheme.of(context).iconTheme?.color),
),
child: Icon(
Icons.crop_square_rounded,
color: color,
)),
TextButton(
onPressed: () {
appWindow.close();
},
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
color ?? PlatformTheme.of(context).iconTheme?.color),
overlayColor: MaterialStateProperty.all(Colors.redAccent),
),
child: const Icon(
Icons.close_rounded,
)),
], ],
), title: center,
),
); );
} }
}
class PageWindowTitleBar extends StatelessWidget
implements PreferredSizeWidget {
final Widget? leading;
final Widget? center;
final Color? backgroundColor;
final Color? foregroundColor;
final Size? _preferredSize;
const PageWindowTitleBar({
Key? key,
Size? preferredSize,
this.leading,
this.center,
this.backgroundColor,
this.foregroundColor,
}) : _preferredSize = preferredSize,
super(key: key);
static Size get staticPreferredSize => Size.fromHeight(
(kIsDesktop ? appWindow.titleBarHeight : 35),
);
@override
Size get preferredSize => _preferredSize ?? staticPreferredSize;
@override
Widget build(BuildContext context) {
if (kIsMobile) {
return PreferredSize(
preferredSize: const Size.fromHeight(300),
child: Container(
color: backgroundColor,
child: Row(
children: [
if (leading != null) leading!,
Expanded(child: Center(child: center)),
],
),
),
);
}
return WindowTitleBarBox(
child: Container(
color: backgroundColor ??
FluentTheme.maybeOf(context)?.micaBackgroundColor,
child: Row(
children: [
if (kIsMacOS)
SizedBox(
width: MediaQuery.of(context).size.width * 0.045,
),
if (leading != null) leading!,
Expanded(child: MoveWindow(child: Center(child: center))),
if (!kIsMacOS && !kIsMobile) const PlatformWindowButtons()
],
),
),
);
}
}

View File

@ -236,7 +236,7 @@ class SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
macosDarkTheme: macosDarkTheme, macosDarkTheme: macosDarkTheme,
themeMode: themeMode, themeMode: themeMode,
windowButtonConfig: PlatformWindowButtonConfig( windowButtonConfig: PlatformWindowButtonConfig(
isMaximized: appWindow.isMaximized, isMaximized: () => appWindow.isMaximized,
onClose: appWindow.close, onClose: appWindow.close,
onRestore: appWindow.restore, onRestore: appWindow.restore,
onMaximize: appWindow.maximize, onMaximize: appWindow.maximize,