Custom Window Titlebar support

This commit is contained in:
Kingkor Roy Tirtho 2022-01-05 19:17:11 +06:00
parent 619aa4af1a
commit 4d41b037e4
12 changed files with 219 additions and 110 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -1,3 +1,4 @@
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart' hide Page; import 'package:flutter/material.dart' hide Page;
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
@ -122,6 +123,27 @@ class _HomeState extends State<Home> {
return Scaffold( return Scaffold(
body: Column( body: Column(
children: [ children: [
WindowTitleBarBox(
child: Row(
children: [
Expanded(
child: Row(
children: [
Container(
constraints: const BoxConstraints(maxWidth: 256),
color:
Theme.of(context).navigationRailTheme.backgroundColor,
child: MoveWindow(),
),
Expanded(child: MoveWindow())
],
)),
MinimizeWindowButton(animate: true),
MaximizeWindowButton(animate: true),
CloseWindowButton(animate: true),
],
),
),
Expanded( Expanded(
child: Row( child: Row(
children: [ children: [
@ -165,21 +187,25 @@ class _HomeState extends State<Home> {
builder: (context, snapshot) { builder: (context, snapshot) {
var avatarImg = snapshot.data?.images?.last.url; var avatarImg = snapshot.data?.images?.last.url;
return Padding( return Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(16),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
if (avatarImg != null) Row(
CircleAvatar( children: [
child: CachedNetworkImage( if (avatarImg != null)
imageUrl: avatarImg, CircleAvatar(
backgroundImage:
CachedNetworkImageProvider(avatarImg),
),
const SizedBox(width: 10),
Text(
snapshot.data?.displayName ?? "User's name",
style: const TextStyle(
fontWeight: FontWeight.bold,
),
), ),
), ],
Text(
snapshot.data?.displayName ?? "User's name",
style: const TextStyle(
fontWeight: FontWeight.bold,
),
), ),
IconButton( IconButton(
icon: const Icon(Icons.settings_outlined), icon: const Icon(Icons.settings_outlined),
@ -202,12 +228,15 @@ class _HomeState extends State<Home> {
if (_selectedIndex == 0) if (_selectedIndex == 0)
Expanded( Expanded(
child: Scrollbar( child: Scrollbar(
child: PagedListView( child: Padding(
pagingController: _pagingController, padding: const EdgeInsets.all(8.0),
builderDelegate: PagedChildBuilderDelegate<Category>( child: PagedListView(
itemBuilder: (context, item, index) { pagingController: _pagingController,
return CategoryCard(item); builderDelegate: PagedChildBuilderDelegate<Category>(
}, itemBuilder: (context, item, index) {
return CategoryCard(item);
},
),
), ),
), ),
), ),

View File

@ -0,0 +1,23 @@
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/material.dart';
class PageWindowTitleBar extends StatelessWidget {
final Widget? leading;
final Widget? center;
const PageWindowTitleBar({Key? key, this.leading, this.center})
: super(key: key);
@override
Widget build(BuildContext context) {
return WindowTitleBarBox(
child: Row(
children: [
if (leading != null) leading!,
Expanded(child: MoveWindow(child: Center(child: center))),
MinimizeWindowButton(animate: true),
MaximizeWindowButton(animate: true),
CloseWindowButton(animate: true),
],
),
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/PageWindowTitleBar.dart';
import 'package:spotube/components/PlaylistCard.dart'; import 'package:spotube/components/PlaylistCard.dart';
import 'package:spotube/provider/SpotifyDI.dart'; import 'package:spotube/provider/SpotifyDI.dart';
@ -24,19 +25,13 @@ class _PlaylistGenreViewState extends State<PlaylistGenreView> {
return Scaffold( return Scaffold(
body: Column( body: Column(
children: [ children: [
Row( const PageWindowTitleBar(
// mainAxisAlignment: MainAxisAlignment.center, leading: BackButton(),
children: [ ),
const BackButton(), Text(
// genre name widget.genreName,
Expanded( style: Theme.of(context).textTheme.headline4,
child: Text( textAlign: TextAlign.center,
widget.genreName,
style: Theme.of(context).textTheme.headline4,
textAlign: TextAlign.center,
),
),
],
), ),
Consumer<SpotifyDI>( Consumer<SpotifyDI>(
builder: (context, data, child) => Expanded( builder: (context, data, child) => Expanded(

View File

@ -1,6 +1,5 @@
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:spotube/components/PageWindowTitleBar.dart';
import 'package:spotube/helpers/zero-pad-num-str.dart'; import 'package:spotube/helpers/zero-pad-num-str.dart';
import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/Playback.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -98,42 +97,49 @@ class _PlaylistViewState extends State<PlaylistView> {
const TextStyle(fontWeight: FontWeight.bold, fontSize: 16); const TextStyle(fontWeight: FontWeight.bold, fontSize: 16);
return Column( return Column(
children: [ children: [
Row( PageWindowTitleBar(
children: [ leading: Row(
// nav back children: [
const BackButton(), // nav back
// heart playlist const BackButton(),
IconButton( // heart playlist
icon: const Icon(Icons.favorite_outline_rounded), IconButton(
onPressed: () {}, icon: const Icon(Icons.favorite_outline_rounded),
), onPressed: () {},
// play playlist ),
Consumer<Playback>(builder: (context, playback, widget) { // play playlist
var isPlaylistPlaying = playback.currentPlaylist?.id == Consumer<Playback>(
this.widget.playlist.id; builder: (context, playback, widget) {
return IconButton( var isPlaylistPlaying =
icon: Icon( playback.currentPlaylist?.id ==
isPlaylistPlaying this.widget.playlist.id;
? Icons.stop_rounded return IconButton(
: Icons.play_arrow_rounded, icon: Icon(
), isPlaylistPlaying
onPressed: snapshot.hasData ? Icons.stop_rounded
? () { : Icons.play_arrow_rounded,
if (!isPlaylistPlaying) { ),
playback.setCurrentPlaylist = onPressed: snapshot.hasData
CurrentPlaylist( ? () {
tracks: tracks, if (!isPlaylistPlaying) {
id: this.widget.playlist.id!, playback.setCurrentPlaylist =
name: this.widget.playlist.name!, CurrentPlaylist(
thumbnail: tracks: tracks,
this.widget.playlist.images![0].url!, id: this.widget.playlist.id!,
); name: this.widget.playlist.name!,
thumbnail: this
.widget
.playlist
.images![0]
.url!,
);
}
} }
} : null,
: null, );
); }),
}), ],
], ),
), ),
Center( Center(
child: Text(widget.playlist.name!, child: Text(widget.playlist.name!,

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/components/PageWindowTitleBar.dart';
import 'package:spotube/provider/Auth.dart'; import 'package:spotube/provider/Auth.dart';
class Settings extends StatefulWidget { class Settings extends StatefulWidget {
@ -14,18 +15,16 @@ class _SettingsState extends State<Settings> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
iconTheme: Theme.of(context).iconTheme,
title: const Text(
"Settings",
),
centerTitle: true,
titleTextStyle: Theme.of(context).textTheme.headline4,
),
body: Column( body: Column(
children: [ children: [
PageWindowTitleBar(
leading: const BackButton(),
center: Text(
"Settings",
style: Theme.of(context).textTheme.headline5,
),
),
const SizedBox(height: 10),
Builder(builder: (context) { Builder(builder: (context) {
var auth = context.read<Auth>(); var auth = context.read<Auth>();
return ElevatedButton( return ElevatedButton(

View File

@ -1,3 +1,4 @@
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -10,6 +11,12 @@ import 'package:spotube/provider/SpotifyDI.dart';
void main() { void main() {
runApp(MyApp()); runApp(MyApp());
doWhenWindowReady(() {
appWindow.minSize = const Size(900, 700);
appWindow.alignment = Alignment.center;
appWindow.maximize();
appWindow.show();
});
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@ -57,40 +64,46 @@ class MyApp extends StatelessWidget {
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
title: 'Spotube', title: 'Spotube',
theme: ThemeData( theme: ThemeData(
primaryColor: Colors.greenAccent[400], primaryColor: Colors.greenAccent[400],
primarySwatch: Colors.green, primarySwatch: Colors.green,
buttonTheme: const ButtonThemeData( buttonTheme: const ButtonThemeData(
buttonColor: Colors.green, buttonColor: Colors.green,
), ),
textTheme: TextTheme( textTheme: TextTheme(
bodyText1: TextStyle(color: Colors.grey[850]), bodyText1: TextStyle(color: Colors.grey[850]),
headline1: TextStyle(color: Colors.grey[850]), headline1: TextStyle(color: Colors.grey[850]),
headline2: TextStyle(color: Colors.grey[850]), headline2: TextStyle(color: Colors.grey[850]),
headline3: TextStyle(color: Colors.grey[850]), headline3: TextStyle(color: Colors.grey[850]),
headline4: TextStyle(color: Colors.grey[850]), headline4: TextStyle(color: Colors.grey[850]),
headline5: TextStyle(color: Colors.grey[850]), headline5: TextStyle(color: Colors.grey[850]),
headline6: TextStyle(color: Colors.grey[850]), headline6: TextStyle(color: Colors.grey[850]),
), ),
listTileTheme: ListTileThemeData( listTileTheme: ListTileThemeData(
iconColor: Colors.grey[850], iconColor: Colors.grey[850],
horizontalTitleGap: 0, horizontalTitleGap: 0,
), ),
inputDecorationTheme: InputDecorationTheme( inputDecorationTheme: InputDecorationTheme(
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.green[400]!, color: Colors.green[400]!,
width: 2.0, width: 2.0,
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey[800]!,
),
), ),
), ),
navigationRailTheme: NavigationRailThemeData( enabledBorder: OutlineInputBorder(
backgroundColor: Colors.blueGrey[50], borderSide: BorderSide(
)), color: Colors.grey[800]!,
),
),
),
navigationRailTheme: NavigationRailThemeData(
backgroundColor: Colors.blueGrey[50],
unselectedIconTheme:
IconThemeData(color: Colors.grey[850], opacity: 1),
unselectedLabelTextStyle: TextStyle(
color: Colors.grey[850],
),
),
),
home: const Home(), home: const Home(),
), ),
); );

View File

@ -6,9 +6,13 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin");
bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View File

@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
bitsdojo_window_linux
url_launcher_linux url_launcher_linux
) )

View File

@ -1,3 +1,4 @@
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
#include "my_application.h" #include "my_application.h"
#include <flutter_linux/flutter_linux.h> #include <flutter_linux/flutter_linux.h>
@ -47,7 +48,9 @@ static void my_application_activate(GApplication* application) {
gtk_window_set_title(window, "spotube"); gtk_window_set_title(window, "spotube");
} }
gtk_window_set_default_size(window, 1280, 720); auto bdw = bitsdojo_window_from(window);
bdw->setCustomFrame(true);
// gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window)); gtk_widget_show(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlDartProject) project = fl_dart_project_new();

View File

@ -8,6 +8,41 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.8.2" version: "2.8.2"
bitsdojo_window:
dependency: "direct main"
description:
name: bitsdojo_window
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1+1"
bitsdojo_window_linux:
dependency: transitive
description:
name: bitsdojo_window_linux
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1"
bitsdojo_window_macos:
dependency: transitive
description:
name: bitsdojo_window_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
bitsdojo_window_platform_interface:
dependency: transitive
description:
name: bitsdojo_window_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
bitsdojo_window_windows:
dependency: transitive
description:
name: bitsdojo_window_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:

View File

@ -44,6 +44,7 @@ dependencies:
youtube_explode_dart: ^1.10.8 youtube_explode_dart: ^1.10.8
mpv_dart: ^0.0.1 mpv_dart: ^0.0.1
infinite_scroll_pagination: ^3.1.0 infinite_scroll_pagination: ^3.1.0
bitsdojo_window: ^0.1.1+1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: