Fixed statusbar color issue created by the new theme

ChooseColorSchemeDialog now scrollable
Initial FutureProvider integration
Uri launches in System Webview in android fix
This commit is contained in:
Kingkor Roy Tirtho 2022-05-28 19:16:20 +06:00
parent 066baa3745
commit 09160b1a53
9 changed files with 172 additions and 95 deletions

View File

@ -1 +1,50 @@
{"version":1,"script":["rm -rf AppDir || true","cp -r build/linux/x64/release/bundle AppDir","mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps/","cp assets/spotube-logo.png AppDir/usr/share/icons/hicolor/"],"AppDir":{"path":"AppDir","app_info":{"id":"oss.krtirtho.spotube","icon":"spotube-logo","name":"spotube","version":"2.0.0+8","exec":"spotube","exec_args":"$@"},"apt":{"arch":"amd64","allow_unauthenticated":true,"sources":[{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute main restricted"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-updates main restricted"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute universe"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-updates universe"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute multiverse"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-updates multiverse"},{"sourceline":"deb http://archive.ubuntu.com/ubuntu/ hirsute-backports main restricted universe multiverse"},{"sourceline":"deb http://security.ubuntu.com/ubuntu hirsute-security main restricted"},{"sourceline":"deb http://security.ubuntu.com/ubuntu hirsute-security universe"},{"sourceline":"deb http://security.ubuntu.com/ubuntu hirsute-security multiverse"}],"include":["libkeybinder-3.0-0"],"exclude":["libx11-6","libgtk-3-0","libglib2.0-0","libc6"]},"files":{"include":[],"exclude":[]}},"AppImage":{"arch":"x86_64","update-information":"guess"}} # appimage-builder recipe see https://appimage-builder.readthedocs.io for details
version: 1
script:
- rm -rf AppDir || true
- cp -r build/linux/x64/release/bundle AppDir
- mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps/
- cp assets/spotube-logo.png AppDir/usr/share/icons/hicolor/64x64/apps/
AppDir:
path: ./AppDir
app_info:
id: oss.krtirtho.spotube
name: Spotube
icon: spotube-logo
version: 2.0.0
exec: spotube
exec_args: $@
apt:
arch: amd64
allow_unauthenticated: true
sources:
- sourceline: deb http://bd.archive.ubuntu.com/ubuntu/ hirsute main restricted
- sourceline: deb http://bd.archive.ubuntu.com/ubuntu/ hirsute-updates main restricted
- sourceline: deb http://bd.archive.ubuntu.com/ubuntu/ hirsute universe
- sourceline: deb http://bd.archive.ubuntu.com/ubuntu/ hirsute-updates universe
- sourceline: deb http://bd.archive.ubuntu.com/ubuntu/ hirsute multiverse
- sourceline: deb http://bd.archive.ubuntu.com/ubuntu/ hirsute-updates multiverse
- sourceline:
deb http://bd.archive.ubuntu.com/ubuntu/ hirsute-backports main
restricted universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu hirsute-security main restricted
- sourceline: deb http://security.ubuntu.com/ubuntu hirsute-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu hirsute-security multiverse
include:
- libkeybinder-3.0-0
exclude:
- libx11-6
- libgtk-3-0
- libglib2.0-0
- libc6
files:
include: []
exclude:
- usr/share/man
- usr/share/doc/*/README.*
- usr/share/doc/*/changelog.*
- usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.*
AppImage:
arch: x86_64
update-information: guess

View File

@ -1,16 +1,21 @@
// Generated file. // Generated file.
//
// If you wish to remove Flutter's multidex support, delete this entire file. // If you wish to remove Flutter's multidex support, delete this entire file.
//
// Modifications to this file should be done in a copy under a different name
// as this file may be regenerated.
package io.flutter.app; package io.flutter.app;
import android.app.Application;
import android.content.Context; import android.content.Context;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex; import androidx.multidex.MultiDex;
/** /**
* Extension of {@link io.flutter.app.FlutterApplication}, adding multidex support. * Extension of {@link android.app.Application}, adding multidex support.
*/ */
public class FlutterMultiDexApplication extends FlutterApplication { public class FlutterMultiDexApplication extends Application {
@Override @Override
@CallSuper @CallSuper
protected void attachBaseContext(Context base) { protected void attachBaseContext(Context base) {

View File

@ -127,21 +127,19 @@ class Home extends HookConsumerWidget {
], ],
)); ));
final brightness = Theme.of(context).brightness; final backgroundColor = Theme.of(context).backgroundColor;
useEffect(() { useEffect(() {
SystemChrome.setSystemUIOverlayStyle( SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle( SystemUiOverlayStyle(
statusBarColor: brightness == Brightness.dark statusBarColor: backgroundColor, // status bar color
? Colors.blueGrey[900] statusBarIconBrightness: backgroundColor.computeLuminance() > 0.179
: Colors.white, // status bar color ? Brightness.dark
statusBarIconBrightness: brightness == Brightness.dark : Brightness.light,
? Brightness.light
: Brightness.dark,
), ),
); );
return null; return null;
}, [brightness]); }, [backgroundColor]);
return SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(

View File

@ -1,37 +1,32 @@
import 'package:flutter/material.dart' hide Image; import 'package:flutter/material.dart' hide Image;
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/Album/AlbumCard.dart'; import 'package:spotube/components/Album/AlbumCard.dart';
import 'package:spotube/helpers/simple-album-to-album.dart'; import 'package:spotube/helpers/simple-album-to-album.dart';
import 'package:spotube/provider/SpotifyDI.dart'; import 'package:spotube/provider/SpotifyRequests.dart';
class UserAlbums extends ConsumerWidget { class UserAlbums extends ConsumerWidget {
const UserAlbums({Key? key}) : super(key: key); const UserAlbums({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
SpotifyApi spotifyApi = ref.watch(spotifyProvider); final albums = ref.watch(currentUserAlbumsQuery);
return FutureBuilder<Iterable<AlbumSimple>>( return albums.when(
future: spotifyApi.me.savedAlbums().all(), data: (data) => SingleChildScrollView(
builder: (context, snapshot) { child: Padding(
if (!snapshot.hasData && snapshot.data == null) { padding: const EdgeInsets.all(8.0),
return const Center(child: CircularProgressIndicator.adaptive()); child: Wrap(
} spacing: 20, // gap between adjacent chips
return SingleChildScrollView( runSpacing: 20, // gap between lines
child: Padding( alignment: WrapAlignment.center,
padding: const EdgeInsets.all(8.0), children: data
child: Wrap( .map((album) => AlbumCard(simpleAlbumToAlbum(album)))
spacing: 20, // gap between adjacent chips .toList(),
runSpacing: 20, // gap between lines
alignment: WrapAlignment.center,
children: snapshot.data!
.map((album) => AlbumCard(simpleAlbumToAlbum(album)))
.toList(),
),
), ),
); ),
}, ),
loading: () => const Center(child: CircularProgressIndicator.adaptive()),
error: (_, __) => const Text("Failure is the pillar of success"),
); );
} }
} }

View File

@ -3,51 +3,47 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/Playlist/PlaylistCard.dart'; import 'package:spotube/components/Playlist/PlaylistCard.dart';
import 'package:spotube/components/Playlist/PlaylistCreateDialog.dart'; import 'package:spotube/components/Playlist/PlaylistCreateDialog.dart';
import 'package:spotube/provider/SpotifyDI.dart'; import 'package:spotube/provider/SpotifyRequests.dart';
class UserPlaylists extends ConsumerWidget { class UserPlaylists extends ConsumerWidget {
const UserPlaylists({Key? key}) : super(key: key); const UserPlaylists({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
SpotifyApi spotifyApi = ref.watch(spotifyProvider); final playlists = ref.watch(currentUserPlaylistsQuery);
return FutureBuilder<Iterable<PlaylistSimple>>( return playlists.when(
future: spotifyApi.playlists.me.all(), loading: () =>
builder: (context, snapshot) { const Center(child: CircularProgressIndicator.adaptive()),
if (!snapshot.hasData) { data: (data) {
return const Center(child: CircularProgressIndicator.adaptive()); Image image = Image();
} image.height = 300;
Image image = Image(); image.width = 300;
image.height = 300; PlaylistSimple likedTracksPlaylist = PlaylistSimple();
image.width = 300; likedTracksPlaylist.name = "Liked Tracks";
PlaylistSimple likedTracksPlaylist = PlaylistSimple(); likedTracksPlaylist.type = "playlist";
likedTracksPlaylist.name = "Liked Tracks"; likedTracksPlaylist.collaborative = false;
likedTracksPlaylist.type = "playlist"; likedTracksPlaylist.public = false;
likedTracksPlaylist.collaborative = false; likedTracksPlaylist.id = "user-liked-tracks";
likedTracksPlaylist.public = false; image.url =
likedTracksPlaylist.id = "user-liked-tracks"; "https://t.scdn.co/images/3099b3803ad9496896c43f22fe9be8c4.png";
image.url = likedTracksPlaylist.images = [image];
"https://t.scdn.co/images/3099b3803ad9496896c43f22fe9be8c4.png"; return SingleChildScrollView(
likedTracksPlaylist.images = [image]; child: Padding(
return SingleChildScrollView( padding: const EdgeInsets.all(8.0),
child: Padding( child: Wrap(
padding: const EdgeInsets.all(8.0), spacing: 20, // gap between adjacent chips
child: Wrap( runSpacing: 20, // gap between lines
spacing: 20, // gap between adjacent chips alignment: WrapAlignment.center,
runSpacing: 20, // gap between lines children: [
alignment: WrapAlignment.center, const PlaylistCreateDialog(),
children: [ PlaylistCard(likedTracksPlaylist),
const PlaylistCreateDialog(), ...data.map((playlist) => PlaylistCard(playlist)).toList(),
PlaylistCard(likedTracksPlaylist), ],
...snapshot.data! ),
.map((playlist) => PlaylistCard(playlist))
.toList(),
],
), ),
), );
); },
}, error: (_, __) => const Text("Failure is the pillar of success"));
);
} }
} }

View File

@ -46,7 +46,7 @@ class PlayerView extends HookConsumerWidget {
final PaletteColor paletteColor = usePaletteColor(context, albumArt); final PaletteColor paletteColor = usePaletteColor(context, albumArt);
final brightness = Theme.of(context).brightness; final backgroundColor = Theme.of(context).backgroundColor;
useEffect(() { useEffect(() {
SystemChrome.setSystemUIOverlayStyle( SystemChrome.setSystemUIOverlayStyle(
@ -61,12 +61,10 @@ class PlayerView extends HookConsumerWidget {
return () { return () {
SystemChrome.setSystemUIOverlayStyle( SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle( SystemUiOverlayStyle(
statusBarColor: brightness == Brightness.dark statusBarColor: backgroundColor, // status bar color
? Colors.blueGrey[900] statusBarIconBrightness: backgroundColor.computeLuminance() > 0.179
: Colors.white, // status bar color ? Brightness.dark
statusBarIconBrightness: brightness == Brightness.dark : Brightness.light,
? Brightness.light
: Brightness.dark,
), ),
); );
}; };

View File

@ -75,22 +75,24 @@ class ColorSchemePickerDialog extends HookConsumerWidget {
content: SizedBox( content: SizedBox(
height: 200, height: 200,
width: 400, width: 400,
child: Center( child: SingleChildScrollView(
child: Wrap( child: Center(
spacing: 10, child: Wrap(
runSpacing: 10, spacing: 10,
children: colorsMap.entries runSpacing: 10,
.map( children: colorsMap.entries
(e) => ColorTile( .map(
color: e.value, (e) => ColorTile(
isActive: active.value == e.key, color: e.value,
tooltip: e.key, isActive: active.value == e.key,
onPressed: () { tooltip: e.key,
active.value = e.key; onPressed: () {
}, active.value = e.key;
), },
) ),
.toList(), )
.toList(),
),
), ),
), ),
), ),

View File

@ -8,7 +8,10 @@ final logger = getLogger("ServerIPC");
Future<String?> connectIpc(String authUri, String redirectUri) async { Future<String?> connectIpc(String authUri, String redirectUri) async {
try { try {
logger.i("[Launching]: $authUri"); logger.i("[Launching]: $authUri");
await launchUrl(Uri.parse(authUri)); await launchUrl(
Uri.parse(authUri),
mode: LaunchMode.externalApplication,
);
HttpServer server = HttpServer server =
await HttpServer.bind(InternetAddress.loopbackIPv4, 4304); await HttpServer.bind(InternetAddress.loopbackIPv4, 4304);
@ -37,4 +40,5 @@ Future<String?> connectIpc(String authUri, String redirectUri) async {
logger.e("connectIpc", e, stack); logger.e("connectIpc", e, stack);
rethrow; rethrow;
} }
return null;
} }

View File

@ -0,0 +1,30 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotube/provider/SpotifyDI.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/provider/UserPreferences.dart';
final categoriesQuery = FutureProvider.family<Page<Category>, int>(
(ref, pageKey) {
final spotify = ref.watch(spotifyProvider);
final recommendationMarket = ref.watch(
userPreferencesProvider.select((s) => s.recommendationMarket),
);
return spotify.categories
.list(country: recommendationMarket)
.getPage(15, pageKey);
},
);
final currentUserPlaylistsQuery = FutureProvider<Iterable<PlaylistSimple>>(
(ref) {
final spotify = ref.watch(spotifyProvider);
return spotify.playlists.me.all();
},
);
final currentUserAlbumsQuery = FutureProvider<Iterable<AlbumSimple>>(
(ref) {
final spotify = ref.watch(spotifyProvider);
return spotify.me.savedAlbums().all();
},
);