fix(macos): white text color in dark mode, text field white background

This commit is contained in:
Kingkor Roy Tirtho 2022-11-01 13:08:06 +06:00
parent 46b00bafdf
commit e086b520e7
22 changed files with 311 additions and 253 deletions

View File

@ -1,12 +1,16 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:fluent_ui/fluent_ui.dart' hide Colors;
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/Shared/HoverBuilder.dart';
import 'package:spotube/components/Shared/UniversalImage.dart';
import 'package:spotube/hooks/usePlatformProperty.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
class ArtistCard extends StatelessWidget {
class ArtistCard extends HookWidget {
final Artist artist;
const ArtistCard(this.artist, {Key? key}) : super(key: key);
@ -18,28 +22,76 @@ class ArtistCard extends StatelessWidget {
placeholder: ImagePlaceholder.artist,
),
);
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 splash = usePlatformProperty<InteractiveInkFeatureFactory?>(
(context) => PlatformProperty.multiPlatformGroup({
InkRipple.splashFactory: {TargetPlatform.android, TargetPlatform.linux},
NoSplash.splashFactory: {
TargetPlatform.windows,
TargetPlatform.macOS,
TargetPlatform.iOS,
}
}),
);
return SizedBox(
height: 240,
width: 200,
child: InkWell(
splashFactory: splash,
onTap: () {
ServiceUtils.navigate(context, "/artist/${artist.id}");
},
borderRadius: BorderRadius.circular(10),
customBorder: platform == TargetPlatform.windows
? Border.all(
color: FluentTheme.maybeOf(context)
?.micaBackgroundColor
.withOpacity(.7) ??
Colors.transparent,
width: 1,
)
: null,
borderRadius: BorderRadius.circular(
platform == TargetPlatform.windows ? 5 : 8,
),
child: HoverBuilder(builder: (context, isHovering) {
return Ink(
width: 200,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius: BorderRadius.circular(8),
color: PlatformTheme.of(context).secondaryBackgroundColor,
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: [TargetPlatform.windows, TargetPlatform.macOS]
.contains(platform)
? Border.all(
color: PlatformTheme.of(context).borderColor ??
Colors.transparent,
width: 1,
)
: null,
),
child: Padding(
padding: const EdgeInsets.all(15),
@ -79,7 +131,7 @@ class ArtistCard extends StatelessWidget {
artist.name!,
maxLines: 2,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
style: PlatformTextTheme.of(context).body?.copyWith(
fontWeight: FontWeight.bold,
),
),

View File

@ -31,13 +31,13 @@ class ArtistProfile extends HookConsumerWidget {
Widget build(BuildContext context, ref) {
SpotifyApi spotify = ref.watch(spotifyProvider);
final parentScrollController = useScrollController();
final textTheme = Theme.of(context).textTheme;
final textTheme = PlatformTheme.of(context).textTheme;
final chipTextVariant = useBreakpointValue(
sm: textTheme.bodySmall,
md: textTheme.bodyMedium,
lg: textTheme.headline6,
xl: textTheme.headline6,
xxl: textTheme.headline6,
sm: textTheme!.caption,
md: textTheme.body,
lg: textTheme.subheading,
xl: textTheme.headline,
xxl: textTheme.headline,
);
final avatarWidth = useBreakpointValue(
@ -53,7 +53,7 @@ class ArtistProfile extends HookConsumerWidget {
final Playback playback = ref.watch(playbackProvider);
return SafeArea(
child: Scaffold(
child: PlatformScaffold(
appBar: const PageWindowTitleBar(
leading: BackButton(),
),
@ -68,7 +68,7 @@ class ArtistProfile extends HookConsumerWidget {
return const ShimmerArtistProfile();
} else if (artistsQuery.hasError) {
return Center(
child: Text(artistsQuery.error.toString()),
child: PlatformText(artistsQuery.error.toString()),
);
}
@ -106,21 +106,22 @@ class ArtistProfile extends HookConsumerWidget {
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(50)),
child: Text(data.type!.toUpperCase(),
child: PlatformText(data.type!.toUpperCase(),
style: chipTextVariant?.copyWith(
color: Colors.white)),
),
Text(
PlatformText(
data.name!,
style: breakpoint.isSm
? textTheme.headline4
: textTheme.headline2,
? textTheme.subheading
: textTheme.headline,
),
Text(
PlatformText(
"${PrimitiveUtils.toReadableNumber(data.followers!.total!.toDouble())} followers",
style: breakpoint.isSm
? textTheme.bodyText1
: textTheme.headline5,
? textTheme.body
: textTheme.body
?.copyWith(fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
Row(
@ -144,7 +145,7 @@ class ArtistProfile extends HookConsumerWidget {
);
}
return OutlinedButton(
return PlatformFilledButton(
onPressed: () async {
try {
isFollowingQuery.data!
@ -170,7 +171,7 @@ class ArtistProfile extends HookConsumerWidget {
]);
}
},
child: Text(
child: PlatformText(
isFollowingQuery.data!
? "Following"
: "Follow",
@ -190,7 +191,7 @@ class ArtistProfile extends HookConsumerWidget {
const SnackBar(
width: 300,
behavior: SnackBarBehavior.floating,
content: Text(
content: PlatformText(
"Artist URL copied to clipboard",
textAlign: TextAlign.center,
),
@ -218,7 +219,7 @@ class ArtistProfile extends HookConsumerWidget {
return const PlatformCircularProgressIndicator();
} else if (topTracksQuery.hasError) {
return Center(
child: Text(topTracksQuery.error.toString()),
child: PlatformText(topTracksQuery.error.toString()),
);
}
@ -252,9 +253,10 @@ class ArtistProfile extends HookConsumerWidget {
return Column(children: [
Row(
children: [
Text(
PlatformText(
"Top Tracks",
style: Theme.of(context).textTheme.headline4,
style:
PlatformTheme.of(context).textTheme?.headline,
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 5),
@ -294,16 +296,16 @@ class ArtistProfile extends HookConsumerWidget {
},
),
const SizedBox(height: 50),
Text(
PlatformText(
"Albums",
style: Theme.of(context).textTheme.headline4,
style: PlatformTheme.of(context).textTheme?.headline,
),
const SizedBox(height: 10),
ArtistAlbumList(artistId),
const SizedBox(height: 20),
Text(
PlatformText(
"Fans also likes",
style: Theme.of(context).textTheme.headline4,
style: PlatformTheme.of(context).textTheme?.headline,
),
const SizedBox(height: 10),
HookBuilder(
@ -317,7 +319,7 @@ class ArtistProfile extends HookConsumerWidget {
return const PlatformCircularProgressIndicator();
} else if (relatedArtists.hasError) {
return Center(
child: Text(relatedArtists.error.toString()),
child: PlatformText(relatedArtists.error.toString()),
);
}

View File

@ -3,6 +3,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart' hide Page;
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/LoaderShimmers/ShimmerPlaybuttonCard.dart';
import 'package:spotube/components/Playlist/PlaylistCard.dart';
@ -46,15 +47,13 @@ class CategoryCard extends HookConsumerWidget {
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
category.name ?? "Unknown",
style: Theme.of(context).textTheme.headline5,
),
PlatformText.headline(category.name ?? "Unknown"),
],
),
),
playlistQuery.hasError
? Text("Something Went Wrong\n${playlistQuery.errors.first}")
? PlatformText(
"Something Went Wrong\n${playlistQuery.errors.first}")
: SizedBox(
height: 245,
child: ScrollConfiguration(

View File

@ -42,7 +42,6 @@ class Genres extends HookConsumerWidget {
];
return PlatformScaffold(
backgroundColor: PlatformProperty.all(Colors.transparent),
body: ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {

View File

@ -1,6 +1,7 @@
import 'package:fl_query_hooks/fl_query_hooks.dart';
import 'package:flutter/material.dart' hide Image;
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotube/components/Album/AlbumCard.dart';
import 'package:spotube/components/LoaderShimmers/ShimmerPlaybuttonCard.dart';
import 'package:spotube/provider/SpotifyDI.dart';
@ -22,16 +23,21 @@ class UserAlbums extends HookConsumerWidget {
}
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 20, // gap between adjacent chips
runSpacing: 20, // gap between lines
alignment: WrapAlignment.center,
children: albumsQuery.data!
.map((album) =>
AlbumCard(TypeConversionUtils.simpleAlbum_X_Album(album)))
.toList(),
child: Material(
type: MaterialType.transparency,
color: PlatformTheme.of(context).scaffoldBackgroundColor,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 20, // gap between adjacent chips
runSpacing: 20, // gap between lines
alignment: WrapAlignment.center,
children: albumsQuery.data!
.map((album) =>
AlbumCard(TypeConversionUtils.simpleAlbum_X_Album(album)))
.toList(),
),
),
),
);

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/Artist/ArtistCard.dart';
import 'package:spotube/components/Shared/Waypoint.dart';
@ -28,26 +29,30 @@ class UserArtists extends HookConsumerWidget {
? false
: (artistQuery.pages.last?.items?.length ?? 0) == 15;
return GridView.builder(
itemCount: artists.length,
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
mainAxisExtent: 250,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
return Material(
type: MaterialType.transparency,
color: PlatformTheme.of(context).scaffoldBackgroundColor,
child: GridView.builder(
itemCount: artists.length,
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
mainAxisExtent: 250,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
),
padding: const EdgeInsets.all(10),
itemBuilder: (context, index) {
if (index == artists.length - 1 && hasNextPage) {
return Waypoint(
onEnter: () {
artistQuery.fetchNextPage();
},
child: ArtistCard(artists[index]),
);
}
return ArtistCard(artists[index]);
},
),
padding: const EdgeInsets.all(10),
itemBuilder: (context, index) {
if (index == artists.length - 1 && hasNextPage) {
return Waypoint(
onEnter: () {
artistQuery.fetchNextPage();
},
child: ArtistCard(artists[index]),
);
}
return ArtistCard(artists[index]);
},
);
}
}

View File

@ -26,7 +26,7 @@ class UserDownloads extends HookConsumerWidget {
child: AutoSizeText(
"Currently downloading (${downloader.currentlyRunning})",
maxLines: 1,
style: Theme.of(context).textTheme.headline5,
style: PlatformTextTheme.of(context).headline,
),
),
const SizedBox(width: 10),
@ -38,7 +38,8 @@ class UserDownloads extends HookConsumerWidget {
onPressed: downloader.currentlyRunning > 0
? downloader.cancelAll
: null,
child: const Text("Cancel All"),
macOSIsSecondary: true,
child: const PlatformText("Cancel All"),
),
],
),

View File

@ -34,19 +34,23 @@ class UserPlaylists extends HookConsumerWidget {
}
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 20, // gap between adjacent chips
runSpacing: 20, // gap between lines
alignment: WrapAlignment.center,
children: [
const PlaylistCreateDialog(),
PlaylistCard(likedTracksPlaylist),
...playlistsQuery.data!
.map((playlist) => PlaylistCard(playlist))
.toList(),
],
child: Material(
type: MaterialType.transparency,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 20, // gap between adjacent chips
runSpacing: 20, // gap between lines
alignment: WrapAlignment.center,
children: [
const PlaylistCreateDialog(),
PlaylistCard(likedTracksPlaylist),
...playlistsQuery.data!
.map((playlist) => PlaylistCard(playlist))
.toList(),
],
),
),
),
);

View File

@ -95,7 +95,7 @@ class PlayerControls extends HookConsumerWidget {
return Column(
children: [
Tooltip(
PlatformTooltip(
message: "Slide to seek forward or backward",
child: PlatformSlider(
focusNode: FocusNode(),
@ -123,10 +123,10 @@ class PlayerControls extends HookConsumerWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
PlatformText(
"$currentMinutes:$currentSeconds",
),
Text("$totalMinutes:$totalSeconds"),
PlatformText("$totalMinutes:$totalSeconds"),
],
),
),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:platform_ui/platform_ui.dart';
import 'package:spotube/components/Shared/UniversalImage.dart';
import 'package:spotube/hooks/useBreakpoints.dart';
import 'package:spotube/provider/Playback.dart';
@ -36,13 +37,10 @@ class PlayerTrackDetails extends HookConsumerWidget {
),
if (breakpoint.isLessThanOrEqualTo(Breakpoints.md))
Flexible(
child: Text(
child: PlatformText(
playback.track?.name ?? "Not playing",
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodyText1
?.copyWith(fontWeight: FontWeight.bold, color: color),
style: TextStyle(fontWeight: FontWeight.bold, color: color),
),
),
@ -52,13 +50,10 @@ class PlayerTrackDetails extends HookConsumerWidget {
flex: 1,
child: Column(
children: [
Text(
PlatformText(
playback.track?.name ?? "Not playing",
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodyText1
?.copyWith(fontWeight: FontWeight.bold, color: color),
style: TextStyle(fontWeight: FontWeight.bold, color: color),
),
TypeConversionUtils.artists_X_ClickableArtists(
playback.track?.artists ?? [],

View File

@ -77,7 +77,7 @@ class Search extends HookConsumerWidget {
return SafeArea(
child: Material(
color: Theme.of(context).backgroundColor,
color: PlatformTheme.of(context).scaffoldBackgroundColor,
child: Column(
children: [
Container(
@ -85,7 +85,6 @@ class Search extends HookConsumerWidget {
horizontal: 20,
vertical: 10,
),
color: Theme.of(context).backgroundColor,
child: PlatformTextField(
onChanged: (value) {
ref.read(searchTermStateProvider.notifier).state = value;
@ -136,16 +135,12 @@ class Search extends HookConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (tracks.isNotEmpty)
Text(
"Songs",
style: Theme.of(context).textTheme.headline5,
),
if (tracks.isNotEmpty) PlatformText.headline("Songs"),
if (searchTrack.isLoading &&
!searchTrack.isFetchingNextPage)
const PlatformCircularProgressIndicator()
else if (searchTrack.hasError)
Text(
PlatformText(
searchTrack.error?[searchTrack.pageParams.last])
else
...tracks.asMap().entries.map((track) {
@ -191,20 +186,17 @@ class Search extends HookConsumerWidget {
: () => searchTrack.fetchNextPage(),
child: searchTrack.isFetchingNextPage
? const PlatformCircularProgressIndicator()
: const Text("Load more"),
: const PlatformText("Load more"),
),
),
if (playlists.isNotEmpty)
Text(
"Playlists",
style: Theme.of(context).textTheme.headline5,
),
PlatformText.headline("Playlists"),
const SizedBox(height: 10),
if (searchPlaylist.isLoading &&
!searchPlaylist.isFetchingNextPage)
const PlatformCircularProgressIndicator()
else if (searchPlaylist.hasError)
Text(searchPlaylist
PlatformText(searchPlaylist
.error?[searchPlaylist.pageParams.last])
else
ScrollConfiguration(
@ -249,16 +241,13 @@ class Search extends HookConsumerWidget {
),
const SizedBox(height: 20),
if (artists.isNotEmpty)
Text(
"Artists",
style: Theme.of(context).textTheme.headline5,
),
PlatformText.headline("Artists"),
const SizedBox(height: 10),
if (searchArtist.isLoading &&
!searchArtist.isFetchingNextPage)
const PlatformCircularProgressIndicator()
else if (searchArtist.hasError)
Text(searchArtist
PlatformText(searchArtist
.error?[searchArtist.pageParams.last])
else
ScrollConfiguration(
@ -303,7 +292,7 @@ class Search extends HookConsumerWidget {
),
const SizedBox(height: 20),
if (albums.isNotEmpty)
Text(
PlatformText(
"Albums",
style: Theme.of(context).textTheme.headline5,
),
@ -312,7 +301,7 @@ class Search extends HookConsumerWidget {
!searchAlbum.isFetchingNextPage)
const PlatformCircularProgressIndicator()
else if (searchAlbum.hasError)
Text(
PlatformText(
searchAlbum.error?[searchAlbum.pageParams.last])
else
ScrollConfiguration(

View File

@ -32,7 +32,10 @@ class About extends HookWidget {
return PlatformListTile(
leading: const Icon(Icons.info_outline_rounded),
title: const Text("About Spotube"),
title: Text(
"About Spotube",
style: PlatformTextTheme.of(context).body,
),
onTap: () {
showAboutDialog(
context: context,

View File

@ -50,11 +50,11 @@ class Settings extends HookConsumerWidget {
);
return SafeArea(
child: Scaffold(
child: PlatformScaffold(
appBar: PageWindowTitleBar(
center: Text(
center: PlatformText(
"Settings",
style: Theme.of(context).textTheme.headline5,
style: PlatformTheme.of(context).textTheme?.headline,
),
),
body: Row(
@ -65,10 +65,11 @@ class Settings extends HookConsumerWidget {
constraints: const BoxConstraints(maxWidth: 1366),
child: ListView(
children: [
const Text(
PlatformText(
" Account",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
style: PlatformTextTheme.of(context)
.headline
?.copyWith(fontWeight: FontWeight.bold),
),
if (auth.isAnonymous)
AdaptiveListTile(
@ -101,7 +102,8 @@ class Settings extends HookConsumerWidget {
),
),
),
child: Text("Connect with Spotify".toUpperCase()),
child: PlatformText(
"Connect with Spotify".toUpperCase()),
),
),
if (auth.isLoggedIn)
@ -109,7 +111,7 @@ class Settings extends HookConsumerWidget {
Auth auth = ref.watch(authProvider);
return PlatformListTile(
leading: const Icon(Icons.logout_rounded),
title: const SizedBox(
title: SizedBox(
height: 50,
width: 180,
child: Align(
@ -117,6 +119,7 @@ class Settings extends HookConsumerWidget {
child: AutoSizeText(
"Log out of this account",
maxLines: 1,
style: PlatformTextTheme.of(context).body,
),
),
),
@ -131,19 +134,20 @@ class Settings extends HookConsumerWidget {
auth.logout();
GoRouter.of(context).pop();
},
child: const Text("Logout"),
child: const PlatformText("Logout"),
),
);
}),
const Text(
PlatformText(
" Appearance",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
style: PlatformTextTheme.of(context)
.headline
?.copyWith(fontWeight: FontWeight.bold),
),
AdaptiveListTile(
leading: const Icon(Icons.dashboard_rounded),
title: const Text("Layout Mode"),
subtitle: const Text(
title: const PlatformText("Layout Mode"),
subtitle: const PlatformText(
"Override responsive layout mode settings",
),
trailing: (context, update) =>
@ -152,19 +156,19 @@ class Settings extends HookConsumerWidget {
items: [
PlatformDropDownMenuItem(
value: LayoutMode.adaptive,
child: const Text(
child: const PlatformText(
"Adaptive",
),
),
PlatformDropDownMenuItem(
value: LayoutMode.compact,
child: const Text(
child: const PlatformText(
"Compact",
),
),
PlatformDropDownMenuItem(
value: LayoutMode.extended,
child: const Text("Extended"),
child: const PlatformText("Extended"),
),
],
onChanged: (value) {
@ -177,26 +181,22 @@ class Settings extends HookConsumerWidget {
),
AdaptiveListTile(
leading: const Icon(Icons.dark_mode_outlined),
title: const Text("Theme"),
title: const PlatformText("Theme"),
trailing: (context, update) =>
PlatformDropDownMenu<ThemeMode>(
value: preferences.themeMode,
items: [
PlatformDropDownMenuItem(
value: ThemeMode.dark,
child: const Text(
"Dark",
),
child: const PlatformText("Dark"),
),
PlatformDropDownMenuItem(
value: ThemeMode.light,
child: const Text(
"Light",
),
child: const PlatformText("Light"),
),
PlatformDropDownMenuItem(
value: ThemeMode.system,
child: const Text("System"),
child: const PlatformText("System"),
),
],
onChanged: (value) {
@ -209,7 +209,7 @@ class Settings extends HookConsumerWidget {
),
PlatformListTile(
leading: const Icon(Icons.palette_outlined),
title: const Text("Accent Color Scheme"),
title: const PlatformText("Accent Color Scheme"),
contentPadding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 5,
@ -223,7 +223,7 @@ class Settings extends HookConsumerWidget {
),
PlatformListTile(
leading: const Icon(Icons.format_color_fill_rounded),
title: const Text("Background Color Scheme"),
title: const PlatformText("Background Color Scheme"),
contentPadding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 5,
@ -237,7 +237,7 @@ class Settings extends HookConsumerWidget {
),
PlatformListTile(
leading: const Icon(Icons.album_rounded),
title: const Text("Rotating Album Art"),
title: const PlatformText("Rotating Album Art"),
trailing: PlatformSwitch(
value: preferences.rotatingAlbumArt,
onChanged: (state) {
@ -245,27 +245,28 @@ class Settings extends HookConsumerWidget {
},
),
),
const Text(
PlatformText(
" Playback",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
style: PlatformTextTheme.of(context)
.headline
?.copyWith(fontWeight: FontWeight.bold),
),
AdaptiveListTile(
leading: const Icon(Icons.multitrack_audio_rounded),
title: const Text("Audio Quality"),
title: const PlatformText("Audio Quality"),
trailing: (context, update) =>
PlatformDropDownMenu<AudioQuality>(
value: preferences.audioQuality,
items: [
PlatformDropDownMenuItem(
value: AudioQuality.high,
child: const Text(
child: const PlatformText(
"High",
),
),
PlatformDropDownMenuItem(
value: AudioQuality.low,
child: const Text("Low"),
child: const PlatformText("Low"),
),
],
onChanged: (value) {
@ -279,10 +280,10 @@ class Settings extends HookConsumerWidget {
if (kIsMobile)
PlatformListTile(
leading: const Icon(Icons.download_for_offline_rounded),
title: const Text(
title: const PlatformText(
"Pre download and play",
),
subtitle: const Text(
subtitle: const PlatformText(
"Instead of streaming audio, download bytes and play instead (Recommended for higher bandwidth users)",
),
trailing: PlatformSwitch(
@ -294,7 +295,7 @@ class Settings extends HookConsumerWidget {
),
PlatformListTile(
leading: const Icon(Icons.fast_forward_rounded),
title: const Text(
title: const PlatformText(
"Skip non-music segments (SponsorBlock)",
),
trailing: PlatformSwitch(
@ -304,20 +305,17 @@ class Settings extends HookConsumerWidget {
},
),
),
const Text(
PlatformText(
" Search",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
style: PlatformTextTheme.of(context)
.headline
?.copyWith(fontWeight: FontWeight.bold),
),
AdaptiveListTile(
leading: const Icon(Icons.shopping_bag_rounded),
title: Text(
"Market Place",
style: Theme.of(context).textTheme.bodyText1,
),
subtitle: Text(
title: const PlatformText("Market Place"),
subtitle: PlatformText.caption(
"Recommendation Country",
style: Theme.of(context).textTheme.caption,
),
trailing: (context, update) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 250),
@ -327,7 +325,7 @@ class Settings extends HookConsumerWidget {
.map(
(country) => (PlatformDropDownMenuItem(
value: country.first,
child: Text(country.last),
child: PlatformText(country.last),
)),
)
.toList(),
@ -343,18 +341,21 @@ class Settings extends HookConsumerWidget {
),
AdaptiveListTile(
leading: const Icon(Icons.screen_search_desktop_rounded),
title: const SizedBox(
title: SizedBox(
height: 50,
width: 200,
child: Align(
alignment: Alignment.centerLeft,
child: AutoSizeText(
"Format of the YouTube Search term",
maxLines: 2,
child: DefaultTextStyle(
style: PlatformTextTheme.of(context).body!,
child: const AutoSizeText(
"Format of the YouTube Search term",
maxLines: 2,
),
),
),
),
subtitle: const Text("(Case sensitive)"),
subtitle: const PlatformText("(Case sensitive)"),
breakOn: Breakpoints.lg,
trailing: (context, update) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 450),
@ -377,7 +378,7 @@ class Settings extends HookConsumerWidget {
),
AdaptiveListTile(
leading: const Icon(Icons.low_priority_rounded),
title: const SizedBox(
title: SizedBox(
height: 50,
width: 180,
child: Align(
@ -385,6 +386,7 @@ class Settings extends HookConsumerWidget {
child: AutoSizeText(
"Track Match Algorithm",
maxLines: 1,
style: PlatformTextTheme.of(context).body,
),
),
),
@ -394,19 +396,19 @@ class Settings extends HookConsumerWidget {
items: [
PlatformDropDownMenuItem(
value: SpotubeTrackMatchAlgorithm.authenticPopular,
child: const Text(
child: const PlatformText(
"Popular from Author",
),
),
PlatformDropDownMenuItem(
value: SpotubeTrackMatchAlgorithm.popular,
child: const Text(
child: const PlatformText(
"Accurately Popular",
),
),
PlatformDropDownMenuItem(
value: SpotubeTrackMatchAlgorithm.youtube,
child: const Text("YouTube's Top choice"),
child: const PlatformText("YouTube's Top choice"),
),
],
onChanged: (value) {
@ -417,15 +419,16 @@ class Settings extends HookConsumerWidget {
},
),
),
const Text(
PlatformText(
" Downloads",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
style: PlatformTextTheme.of(context)
.headline
?.copyWith(fontWeight: FontWeight.bold),
),
PlatformListTile(
leading: const Icon(Icons.file_download_outlined),
title: const Text("Download Location"),
subtitle: Text(preferences.downloadLocation),
title: const PlatformText("Download Location"),
subtitle: PlatformText(preferences.downloadLocation),
trailing: PlatformFilledButton(
onPressed: pickDownloadLocation,
child: const Icon(Icons.folder_rounded),
@ -434,7 +437,8 @@ class Settings extends HookConsumerWidget {
),
PlatformListTile(
leading: const Icon(Icons.lyrics_rounded),
title: const Text("Download lyrics along with the Track"),
title: const PlatformText(
"Download lyrics along with the Track"),
trailing: PlatformSwitch(
value: preferences.saveTrackLyrics,
onChanged: (state) {
@ -442,10 +446,11 @@ class Settings extends HookConsumerWidget {
},
),
),
const Text(
PlatformText(
" About",
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
style: PlatformTextTheme.of(context)
.headline
?.copyWith(fontWeight: FontWeight.bold),
),
AdaptiveListTile(
leading: const Icon(
@ -487,14 +492,14 @@ class Settings extends HookConsumerWidget {
children: const [
Icon(Icons.favorite_outline_rounded),
SizedBox(width: 5),
Text("Please Sponsor/Donate"),
PlatformText("Please Sponsor/Donate"),
],
),
),
),
PlatformListTile(
leading: const Icon(Icons.update_rounded),
title: const Text("Check for Update"),
title: const PlatformText("Check for Update"),
trailing: PlatformSwitch(
value: preferences.checkUpdate,
onChanged: (checked) =>

View File

@ -20,15 +20,15 @@ class Action extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (isExpanded != true) {
return Tooltip(
message: text.toStringShallow().split(",").last.replaceAll(
"\"",
"",
),
child: PlatformIconButton(
icon: icon,
onPressed: onPressed,
),
return PlatformIconButton(
icon: icon,
onPressed: onPressed,
tooltip: text is Text
? (text as Text).data
: text.toStringShallow().split(",").last.replaceAll(
"\"",
"",
),
);
}
return PlatformTextButton(

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:platform_ui/platform_ui.dart';
class AnchorButton<T> extends HookWidget {
final String text;
@ -28,7 +29,7 @@ class AnchorButton<T> extends HookWidget {
onTap: onTap,
child: MouseRegion(
cursor: MaterialStateMouseCursor.clickable,
child: Text(
child: PlatformText(
text,
style: style.copyWith(
decoration:

View File

@ -33,7 +33,7 @@ class TitleBarActionButtons extends StatelessWidget {
},
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
Theme.of(context).iconTheme.color),
PlatformTheme.of(context).iconTheme?.color),
),
child: Icon(
Icons.minimize_rounded,
@ -45,7 +45,7 @@ class TitleBarActionButtons extends StatelessWidget {
},
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
Theme.of(context).iconTheme.color),
PlatformTheme.of(context).iconTheme?.color),
),
child: Icon(
Icons.crop_square_rounded,
@ -57,7 +57,7 @@ class TitleBarActionButtons extends StatelessWidget {
},
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
color ?? Theme.of(context).iconTheme.color),
color ?? PlatformTheme.of(context).iconTheme?.color),
overlayColor: MaterialStateProperty.all(Colors.redAccent),
),
child: const Icon(

View File

@ -77,6 +77,7 @@ class PlaybuttonCard extends HookWidget {
onTap: onTap,
borderRadius: BorderRadius.circular(8),
splashFactory: splash,
highlightColor: Colors.black12,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 200),
child: HoverBuilder(builder: (context, isHovering) {
@ -89,11 +90,10 @@ class PlaybuttonCard extends HookWidget {
boxShadow: [
if (boxShadow != null) boxShadow,
],
border: platform == TargetPlatform.windows
border: [TargetPlatform.windows, TargetPlatform.macOS]
.contains(platform)
? Border.all(
color: FluentUI.FluentTheme.maybeOf(context)
?.micaBackgroundColor
.withOpacity(.7) ??
color: PlatformTheme.of(context).borderColor ??
Colors.transparent,
width: 1,
)

View File

@ -132,12 +132,12 @@ class TrackCollectionView<T> extends HookConsumerWidget {
primary: true,
backgroundColor: color?.color,
title: collapsed.value
? Text(
? PlatformText.headline(
title,
style: Theme.of(context).textTheme.headline4?.copyWith(
color: color?.titleTextColor,
fontWeight: FontWeight.w600,
),
style: TextStyle(
color: color?.titleTextColor,
fontWeight: FontWeight.w600,
),
)
: null,
flexibleSpace: LayoutBuilder(builder: (context, constrains) {
@ -188,25 +188,19 @@ class TrackCollectionView<T> extends HookConsumerWidget {
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
PlatformText.headline(
title,
style: Theme.of(context)
.textTheme
.headline4
?.copyWith(
color: color?.titleTextColor,
fontWeight: FontWeight.w600,
),
style: TextStyle(
color: color?.titleTextColor,
fontWeight: FontWeight.w600,
),
),
if (description != null)
Text(
PlatformText(
description!,
style: Theme.of(context)
.textTheme
.bodyLarge
?.copyWith(
color: color?.bodyTextColor,
),
style: TextStyle(
color: color?.bodyTextColor,
),
maxLines: 2,
overflow: TextOverflow.fade,
),
@ -232,7 +226,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
} else if (tracksSnapshot.hasError &&
tracksSnapshot.isError) {
return SliverToBoxAdapter(
child: Text("Error ${tracksSnapshot.error}"));
child: PlatformText("Error ${tracksSnapshot.error}"));
}
final tracks = tracksSnapshot.data!;

View File

@ -74,7 +74,7 @@ class TrackTile extends HookConsumerWidget {
SnackBar(
width: 300,
behavior: SnackBarBehavior.floating,
content: Text(
content: PlatformText(
"Copied $data to clipboard",
textAlign: TextAlign.center,
),
@ -98,7 +98,7 @@ class TrackTile extends HookConsumerWidget {
return HookBuilder(builder: (context) {
final playlistsCheck = useState(<String, bool>{});
return AlertDialog(
title: Text(
title: PlatformText(
"Add `${track.value.name}` to following Playlists"),
titleTextStyle:
Theme.of(context).textTheme.bodyText1?.copyWith(
@ -107,11 +107,11 @@ class TrackTile extends HookConsumerWidget {
),
actions: [
PlatformTextButton(
child: const Text("Cancel"),
child: const PlatformText("Cancel"),
onPressed: () => Navigator.pop(context),
),
PlatformFilledButton(
child: const Text("Add"),
child: const PlatformText("Add"),
onPressed: () async {
final selectedPlaylists = playlistsCheck
.value.entries
@ -140,7 +140,7 @@ class TrackTile extends HookConsumerWidget {
final playlist =
snapshot.data!.elementAt(index);
return CheckboxListTile(
title: Text(playlist.name!),
title: PlatformText(playlist.name!),
controlAffinity:
ListTileControlAffinity.leading,
value: playlistsCheck.value[playlist.id] ??
@ -191,7 +191,7 @@ class TrackTile extends HookConsumerWidget {
height: 20,
width: 25,
child: Center(
child: Text((track.key + 1).toString()),
child: PlatformText((track.key + 1).toString()),
),
),
Padding(
@ -221,7 +221,7 @@ class TrackTile extends HookConsumerWidget {
playback.track?.id == track.value.id
? Icons.pause_circle_rounded
: Icons.play_circle_rounded,
color: Theme.of(context).primaryColor,
color: PlatformTheme.of(context).primaryColor,
),
onPressed: () => onTrackPlayButtonPressed?.call(
track.value,
@ -231,7 +231,7 @@ class TrackTile extends HookConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
PlatformText(
track.value.name ?? "",
style: TextStyle(
fontWeight: FontWeight.bold,
@ -240,7 +240,7 @@ class TrackTile extends HookConsumerWidget {
overflow: TextOverflow.ellipsis,
),
isReallyLocal
? Text(
? PlatformText(
TypeConversionUtils.artists_X_String<Artist>(
track.value.artists ?? []),
)
@ -256,7 +256,7 @@ class TrackTile extends HookConsumerWidget {
if (breakpoint.isMoreThan(Breakpoints.md) && showAlbum)
Expanded(
child: isReallyLocal
? Text(track.value.album?.name ?? "")
? PlatformText(track.value.album?.name ?? "")
: LinkText(
track.value.album!.name!,
"/album/${track.value.album?.id}",
@ -266,7 +266,7 @@ class TrackTile extends HookConsumerWidget {
),
if (!breakpoint.isSm) ...[
const SizedBox(width: 10),
Text(duration),
PlatformText(duration),
],
const SizedBox(width: 10),
if (!isReallyLocal)
@ -280,7 +280,7 @@ class TrackTile extends HookConsumerWidget {
color: Colors.pink,
)
: const Icon(Icons.favorite_border_rounded),
text: const Text("Save as favorite"),
text: const PlatformText("Save as favorite"),
onPressed: () {
toggler.item2.mutate(Tuple2(spotify, toggler.item1));
},
@ -288,18 +288,18 @@ class TrackTile extends HookConsumerWidget {
if (auth.isLoggedIn)
Action(
icon: const Icon(Icons.add_box_rounded),
text: const Text("Add To playlist"),
text: const PlatformText("Add To playlist"),
onPressed: actionAddToPlaylist,
),
if (userPlaylist && auth.isLoggedIn)
Action(
icon: const Icon(Icons.remove_circle_outline_rounded),
text: const Text("Remove from playlist"),
text: const PlatformText("Remove from playlist"),
onPressed: actionRemoveFromPlaylist,
),
Action(
icon: const Icon(Icons.share_rounded),
text: const Text("Share"),
text: const PlatformText("Share"),
onPressed: () {
actionShare(track.value);
},

View File

@ -82,7 +82,7 @@ class TracksTableView extends HookConsumerWidget {
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
child: PlatformText(
"#",
textAlign: TextAlign.center,
style: tableHeadStyle,
@ -91,7 +91,7 @@ class TracksTableView extends HookConsumerWidget {
Expanded(
child: Row(
children: [
Text(
PlatformText(
"Title",
style: tableHeadStyle,
overflow: TextOverflow.ellipsis,
@ -105,7 +105,7 @@ class TracksTableView extends HookConsumerWidget {
Expanded(
child: Row(
children: [
Text(
PlatformText(
"Album",
overflow: TextOverflow.ellipsis,
style: tableHeadStyle,
@ -116,7 +116,7 @@ class TracksTableView extends HookConsumerWidget {
],
if (!breakpoint.isSm) ...[
const SizedBox(width: 10),
Text("Time", style: tableHeadStyle),
PlatformText("Time", style: tableHeadStyle),
const SizedBox(width: 10),
],
SortTracksDropdown(
@ -135,7 +135,7 @@ class TracksTableView extends HookConsumerWidget {
child: Row(
children: [
const Icon(Icons.file_download_outlined),
Text(
PlatformText(
"Download ${selectedTracks.isNotEmpty ? "(${selectedTracks.length})" : ""}",
),
],

View File

@ -201,7 +201,7 @@ class SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
};
}, []);
platform = TargetPlatform.windows;
platform = TargetPlatform.macOS;
return PlatformApp.router(
routeInformationParser: router.routeInformationParser,

View File

@ -134,14 +134,17 @@ final windowsDarkTheme = FluentUI.ThemeData.dark().copyWith(
),
);
final macosTheme = MacosThemeData.light().copyWith(
pushButtonTheme: PushButtonThemeData(
pushButtonTheme: const PushButtonThemeData(
secondaryColor: Colors.white,
),
iconTheme: MacosIconThemeData(size: 16),
iconButtonTheme: MacosIconButtonThemeData(),
typography: MacosTypography(color: Colors.green),
iconTheme: const MacosIconThemeData(size: 14),
typography: MacosTypography(color: Colors.grey[900]!),
);
final macosDarkTheme = MacosThemeData.dark().copyWith(
typography: MacosTypography(color: Colors.red),
pushButtonTheme: const PushButtonThemeData(
secondaryColor: Colors.white,
),
iconTheme: const MacosIconThemeData(size: 14),
typography: MacosTypography(color: MacosColors.textColor),
);
final iosTheme = CupertinoThemeData();