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(
|
||||
child: PlatformScaffold(
|
||||
appBar: const PageWindowTitleBar(
|
||||
leading: PlatformBackButton(),
|
||||
appBar: PageWindowTitleBar(
|
||||
leading: const PlatformBackButton(),
|
||||
),
|
||||
body: HookBuilder(
|
||||
builder: (context) {
|
||||
|
@ -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
|
||||
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
|
||||
? PageWindowTitleBar.staticPreferredSize.height
|
||||
: 0,
|
||||
height: allowedPath ? titleBar.preferredSize.height : 0,
|
||||
child: AnimatedOpacity(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
opacity: allowedPath ? 1 : 0,
|
||||
child: PageWindowTitleBar(preferredSize: preferredSize),
|
||||
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]!);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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: [
|
||||
|
@ -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(),
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
themeMode: themeMode,
|
||||
windowButtonConfig: PlatformWindowButtonConfig(
|
||||
isMaximized: appWindow.isMaximized,
|
||||
isMaximized: () => appWindow.isMaximized,
|
||||
onClose: appWindow.close,
|
||||
onRestore: appWindow.restore,
|
||||
onMaximize: appWindow.maximize,
|
||||
|
Loading…
Reference in New Issue
Block a user