mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
feat(title_bar): platform specific title bar
This commit is contained in:
parent
54048cbfc3
commit
e659e3c56f
@ -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) {
|
||||||
|
@ -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]!);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -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,
|
||||||
|
@ -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(
|
||||||
|
@ -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: [
|
||||||
|
@ -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()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user