feat: Player and Playbutton theme respect to platform

This commit is contained in:
Kingkor Roy Tirtho 2022-10-29 19:36:04 +06:00
parent 69739b4572
commit 512446dcab
10 changed files with 240 additions and 58 deletions

View File

@ -2,6 +2,7 @@ import 'package:fl_query_hooks/fl_query_hooks.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/Category/CategoryCard.dart';
import 'package:spotube/components/LoaderShimmers/ShimmerCategories.dart';
@ -40,7 +41,8 @@ class Genres extends HookConsumerWidget {
.toList()
];
return Scaffold(
return PlatformScaffold(
backgroundColor: PlatformProperty.all(Colors.transparent),
body: ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {

View File

@ -1,11 +1,16 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:macos_ui/macos_ui.dart';
import 'package:fluent_ui/fluent_ui.dart' as FluentUI;
import 'package:platform_ui/platform_ui.dart';
import 'package:spotube/components/Player/PlayerActions.dart';
import 'package:spotube/components/Player/PlayerOverlay.dart';
import 'package:spotube/components/Player/PlayerTrackDetails.dart';
import 'package:spotube/components/Player/PlayerControls.dart';
import 'package:spotube/hooks/useBreakpoints.dart';
import 'package:spotube/hooks/usePlatformProperty.dart';
import 'package:spotube/models/Logger.dart';
import 'package:spotube/provider/Playback.dart';
import 'package:flutter/material.dart';
@ -46,8 +51,43 @@ class Player extends HookConsumerWidget {
);
}
return Container(
color: Theme.of(context).backgroundColor,
final backgroundColor = usePlatformProperty<Color?>(
(context) => PlatformProperty(
android: Theme.of(context).backgroundColor,
ios: CupertinoTheme.of(context).scaffoldBackgroundColor,
macos: MacosTheme.of(context).brightness == Brightness.dark
? Colors.grey[800]
: Colors.blueGrey[50],
linux: Theme.of(context).backgroundColor,
windows: FluentUI.FluentTheme.maybeOf(context)?.micaBackgroundColor,
),
);
final border = usePlatformProperty<BoxBorder?>(
(context) => PlatformProperty(
android: null,
ios: Border(
top: BorderSide(
color: CupertinoTheme.of(context).barBackgroundColor,
width: 1,
),
),
macos: Border(
top: BorderSide(
color: MacosTheme.of(context).dividerColor,
width: 1,
),
),
linux: null,
windows: null,
),
);
return DecoratedBox(
decoration: BoxDecoration(
color: backgroundColor,
border: border,
),
child: Material(
type: MaterialType.transparency,
child: Row(

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:macos_ui/macos_ui.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotube/components/Settings/About.dart';
import 'package:spotube/components/Settings/ColorSchemePickerDialog.dart';
@ -467,10 +468,13 @@ class Settings extends HookConsumerWidget {
),
),
trailing: (context, update) => PlatformFilledButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red[100],
foregroundColor: Colors.pinkAccent,
padding: const EdgeInsets.all(15),
style: ButtonStyle(
backgroundColor:
MaterialStatePropertyAll(Colors.red[100]),
foregroundColor:
const MaterialStatePropertyAll(Colors.pinkAccent),
padding: const MaterialStatePropertyAll(
EdgeInsets.all(15)),
),
onPressed: () {
launchUrlString(
@ -479,8 +483,10 @@ class Settings extends HookConsumerWidget {
);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
Icon(Icons.favorite_outline_rounded),
SizedBox(width: 5),
Text("Please Sponsor/Donate"),
],
),

View File

@ -27,7 +27,7 @@ class TitleBarActionButtons extends StatelessWidget {
data: const IconThemeData(size: 16),
child: Row(
children: [
PlatformTextButton(
TextButton(
onPressed: () {
appWindow.minimize();
},
@ -39,7 +39,7 @@ class TitleBarActionButtons extends StatelessWidget {
Icons.minimize_rounded,
color: color,
)),
PlatformTextButton(
TextButton(
onPressed: () async {
appWindow.maximizeOrRestore();
},
@ -51,7 +51,7 @@ class TitleBarActionButtons extends StatelessWidget {
Icons.crop_square_rounded,
color: color,
)),
PlatformTextButton(
TextButton(
onPressed: () {
appWindow.close();
},

View File

@ -1,10 +1,15 @@
import 'package:fluent_ui/fluent_ui.dart' as FluentUI;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:macos_ui/macos_ui.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotube/components/Shared/HoverBuilder.dart';
import 'package:spotube/components/Shared/SpotubeMarqueeText.dart';
import 'package:spotube/components/Shared/UniversalImage.dart';
import 'package:spotube/hooks/usePlatformProperty.dart';
class PlaybuttonCard extends StatelessWidget {
class PlaybuttonCard extends HookWidget {
final void Function()? onTap;
final void Function()? onPlaybuttonPressed;
final String? description;
@ -27,26 +32,109 @@ class PlaybuttonCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final backgroundColor = usePlatformProperty<Color?>(
(context) => PlatformProperty(
android: Theme.of(context).backgroundColor,
ios: CupertinoTheme.of(context).scaffoldBackgroundColor,
macos: MacosTheme.of(context).brightness == Brightness.dark
? Colors.grey[800]
: Colors.blueGrey[50],
linux: Theme.of(context).backgroundColor,
windows: FluentUI.FluentTheme.maybeOf(context)?.scaffoldBackgroundColor,
),
);
final boxShadow = usePlatformProperty<BoxShadow?>(
(context) => PlatformProperty(
android: BoxShadow(
blurRadius: 10,
offset: const Offset(0, 3),
spreadRadius: 5,
color: Theme.of(context).shadowColor,
),
ios: null,
macos: null,
linux: BoxShadow(
blurRadius: 10,
offset: const Offset(0, 3),
spreadRadius: 5,
color: Theme.of(context).shadowColor,
),
windows: null,
),
);
final titleStyle = usePlatformProperty<TextStyle?>(
(context) => PlatformProperty(
android: Theme.of(context).textTheme.bodyMedium,
ios: CupertinoTheme.of(context).textTheme.textStyle,
macos: MacosTheme.of(context).typography.body,
linux: Theme.of(context).textTheme.bodyMedium,
windows: FluentUI.FluentTheme.maybeOf(context)?.typography.body,
),
);
final descriptionStyle = usePlatformProperty<TextStyle?>(
(context) => PlatformProperty(
android: Theme.of(context).textTheme.caption,
ios: CupertinoTheme.of(context)
.textTheme
.textStyle
.copyWith(fontSize: 13),
macos: MacosTheme.of(context).typography.caption1,
linux: Theme.of(context).textTheme.caption,
windows: FluentUI.FluentTheme.maybeOf(context)?.typography.caption,
),
);
final splash = usePlatformProperty<InteractiveInkFeatureFactory?>(
(context) => PlatformProperty.multiPlatformGroup({
InkRipple.splashFactory: {TargetPlatform.android, TargetPlatform.linux},
NoSplash.splashFactory: {
TargetPlatform.windows,
TargetPlatform.macOS,
TargetPlatform.iOS,
}
}),
);
final iconBgColor = usePlatformProperty<Color?>(
(context) => PlatformProperty(
android: Theme.of(context).primaryColor,
ios: CupertinoTheme.of(context).primaryColor,
macos: MacosTheme.of(context).primaryColor,
linux: Theme.of(context).primaryColor,
windows: FluentUI.FluentTheme.maybeOf(context)?.accentColor,
),
);
return Container(
margin: margin,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(8),
splashFactory: splash,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 200),
child: HoverBuilder(builder: (context, isHovering) {
return Ink(
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius: BorderRadius.circular(8),
color: backgroundColor,
borderRadius: BorderRadius.circular(
platform == TargetPlatform.windows ? 5 : 8,
),
boxShadow: [
BoxShadow(
blurRadius: 10,
offset: const Offset(0, 3),
spreadRadius: 5,
color: Theme.of(context).shadowColor,
)
if (boxShadow != null) boxShadow,
],
border: platform == TargetPlatform.windows
? Border.all(
color: FluentUI.FluentTheme.maybeOf(context)
?.micaBackgroundColor
.withOpacity(.7) ??
Colors.transparent,
width: 1,
)
: null,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
@ -54,13 +142,20 @@ class PlaybuttonCard extends StatelessWidget {
// thumbnail of the playlist
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: UniversalImage(
path: imageUrl,
width: 200,
placeholder: (context, url) =>
Image.asset("assets/placeholder.png"),
Padding(
padding: EdgeInsets.all(
platform == TargetPlatform.windows ? 5 : 0,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
platform == TargetPlatform.windows ? 5 : 8,
),
child: UniversalImage(
path: imageUrl,
width: 200,
placeholder: (context, url) =>
Image.asset("assets/placeholder.png"),
),
),
),
Positioned.directional(
@ -68,27 +163,26 @@ class PlaybuttonCard extends StatelessWidget {
bottom: 10,
end: 5,
child: Builder(builder: (context) {
return PlatformFilledButton(
onPressed: onPlaybuttonPressed,
style: ButtonStyle(
shape: MaterialStateProperty.all(
const CircleBorder(),
),
padding: MaterialStateProperty.all(
const EdgeInsets.all(16),
),
return Container(
decoration: BoxDecoration(
color: iconBgColor,
shape: BoxShape.circle,
),
child: PlatformIconButton(
onPressed: onPlaybuttonPressed,
icon: isLoading
? const SizedBox(
height: 23,
width: 23,
child: CircularProgressIndicator(),
)
: Icon(
isPlaying
? Icons.pause_rounded
: Icons.play_arrow_rounded,
color: backgroundColor,
),
),
child: isLoading
? const SizedBox(
height: 23,
width: 23,
child: CircularProgressIndicator(),
)
: Icon(
isPlaying
? Icons.pause_rounded
: Icons.play_arrow_rounded,
),
);
}),
)
@ -106,8 +200,8 @@ class PlaybuttonCard extends StatelessWidget {
height: 20,
child: SpotubeMarqueeText(
text: title,
style:
const TextStyle(fontWeight: FontWeight.bold),
style: titleStyle?.copyWith(
fontWeight: FontWeight.bold),
isHovering: isHovering,
),
),
@ -118,13 +212,7 @@ class PlaybuttonCard extends StatelessWidget {
height: 30,
child: SpotubeMarqueeText(
text: description!,
style: TextStyle(
fontSize: 13,
color: Theme.of(context)
.textTheme
.headline4
?.color,
),
style: descriptionStyle,
isHovering: isHovering,
),
),

View File

@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:platform_ui/platform_ui.dart';
T usePlatformProperty<T>(
PlatformProperty<T> Function(BuildContext context) getProperties) {
final context = useContext();
return getProperties(context).resolve(platform ?? Theme.of(context).platform);
}

View File

@ -3,11 +3,13 @@ import 'dart:convert';
import 'package:audio_service/audio_service.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:fl_query/fl_query.dart';
import 'package:fluent_ui/fluent_ui.dart' as FluentUI;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:macos_ui/macos_ui.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/components/Shared/ReplaceDownloadedFileDialog.dart';
@ -199,7 +201,7 @@ class SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
};
}, []);
platform = TargetPlatform.windows;
platform = TargetPlatform.macOS;
return PlatformApp.router(
routeInformationParser: router.routeInformationParser,
@ -215,6 +217,11 @@ class SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
accentMaterialColor: accentMaterialColor,
backgroundMaterialColor: backgroundMaterialColor,
),
iosTheme: iosTheme,
windowsTheme: windowsTheme,
windowsDarkTheme: windowsDarkTheme,
macosTheme: macosTheme,
macosDarkTheme: macosDarkTheme,
themeMode: themeMode,
shortcuts: PlatformProperty.all({
...WidgetsApp.defaultShortcuts.map((key, value) {

View File

@ -1,5 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:macos_ui/macos_ui.dart';
import 'package:spotube/extensions/ShimmerColorTheme.dart';
import 'package:fluent_ui/fluent_ui.dart' as FluentUI;
final materialWhite = MaterialColor(Colors.white.value, {
50: Colors.white,
@ -115,3 +118,27 @@ ThemeData lightTheme({
),
);
}
final windowsTheme = FluentUI.ThemeData.light().copyWith(
buttonTheme: FluentUI.ButtonThemeData(
iconButtonStyle: FluentUI.ButtonStyle(
iconSize: FluentUI.ButtonState.all(20),
),
),
);
final windowsDarkTheme = FluentUI.ThemeData.dark().copyWith(
buttonTheme: FluentUI.ButtonThemeData(
iconButtonStyle: FluentUI.ButtonStyle(
iconSize: FluentUI.ButtonState.all(20),
),
),
);
final macosTheme = MacosThemeData.light().copyWith(
pushButtonTheme: PushButtonThemeData(
secondaryColor: Colors.white,
),
iconTheme: MacosIconThemeData(size: 16),
iconButtonTheme: MacosIconButtonThemeData(),
);
final macosDarkTheme = MacosThemeData.dark();
final iosTheme = CupertinoThemeData();

View File

@ -494,7 +494,7 @@ packages:
source: hosted
version: "0.3.1"
fluent_ui:
dependency: transitive
dependency: "direct main"
description:
name: fluent_ui
url: "https://pub.dartlang.org"
@ -759,7 +759,7 @@ packages:
source: hosted
version: "1.0.2"
macos_ui:
dependency: transitive
dependency: "direct main"
description:
name: macos_ui
url: "https://pub.dartlang.org"

View File

@ -64,6 +64,8 @@ dependencies:
uuid: ^3.0.6
platform_ui:
path: ../platform_ui
fluent_ui: ^4.0.3
macos_ui: ^1.7.5
dev_dependencies:
flutter_test: