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(
child: PlatformScaffold(
appBar: const PageWindowTitleBar(
leading: PlatformBackButton(),
appBar: PageWindowTitleBar(
leading: const PlatformBackButton(),
),
body: HookBuilder(
builder: (context) {

View File

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

View File

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

View File

@ -20,8 +20,8 @@ class PlaylistGenreView extends ConsumerWidget {
@override
Widget build(BuildContext context, ref) {
return Scaffold(
appBar: const PageWindowTitleBar(
leading: PlatformBackButton(),
appBar: PageWindowTitleBar(
leading: const PlatformBackButton(),
),
body: Column(
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:platform_ui/platform_ui.dart';
import 'package:spotube/utils/platform.dart';
class TitleBarActionButtons extends StatelessWidget {
final Color? color;
const TitleBarActionButtons({
Key? key,
this.color,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextButtonTheme(
data: TextButtonThemeData(
style: ButtonStyle(
splashFactory: NoSplash.splashFactory,
shape: MaterialStateProperty.all(const RoundedRectangleBorder()),
overlayColor: MaterialStateProperty.all(Colors.black12),
padding: MaterialStateProperty.all(EdgeInsets.zero),
minimumSize: MaterialStateProperty.all(const Size(50, 40)),
maximumSize: MaterialStateProperty.all(const Size(50, 40)),
),
),
child: IconTheme(
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,
)),
class PageWindowTitleBar extends PlatformAppBar {
PageWindowTitleBar({
super.backgroundColor,
List<Widget>? actions,
super.actionsIconTheme,
super.automaticallyImplyLeading = false,
super.centerTitle,
super.foregroundColor,
super.key,
super.leading,
super.leadingWidth,
Widget? center,
super.titleSpacing,
super.titleTextStyle,
super.titleWidth,
super.toolbarOpacity,
super.toolbarTextStyle,
}) : super(
actions: [
...?actions,
if (!kIsMacOS && !kIsMobile) const PlatformWindowButtons(),
],
),
),
);
}
}
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()
],
),
),
);
}
title: center,
);
}

View File

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