Android SafeArea issues fixed

configurations for different plugin for android added
adjusted platform bound opertations
This commit is contained in:
Kingkor Roy Tirtho 2022-03-15 19:47:29 +06:00
parent 39a92a56f3
commit c64f329c42
19 changed files with 793 additions and 736 deletions

View File

@ -1,34 +1,30 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="oss.krtirtho.spotube">
<application
android:label="spotube"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="oss.krtirtho.spotube">
<uses-permission android:name="android.permission.INTERNET" />
<queries>
<!-- If your app opens https URLs -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
<application android:label="spotube" android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true">
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data android:name="flutterEmbedding" android:value="2" />
</application>
</manifest>

View File

@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()

View File

@ -37,5 +37,11 @@ end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'AUDIO_SESSION_MICROPHONE=0'
]
end
end
end

View File

@ -43,5 +43,12 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true />
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true />
<key>NSAllowsArbitraryLoadsForMedia</key>
<true />
</dict>
</dict>
</plist>

View File

@ -38,7 +38,8 @@ class AlbumView extends ConsumerWidget {
var isPlaylistPlaying = playback.currentPlaylist?.id == album.id;
SpotifyApi spotify = ref.watch(spotifyProvider);
return Scaffold(
return SafeArea(
child: Scaffold(
body: FutureBuilder<Iterable<TrackSimple>>(
future: spotify.albums.getTracks(album.id!).all(),
builder: (context, snapshot) {
@ -95,6 +96,7 @@ class AlbumView extends ConsumerWidget {
],
);
}),
),
);
}
}

View File

@ -59,7 +59,8 @@ class _ArtistAlbumViewState extends ConsumerState<ArtistAlbumView> {
@override
Widget build(BuildContext context) {
return Scaffold(
return SafeArea(
child: Scaffold(
appBar: const PageWindowTitleBar(leading: BackButton()),
body: Column(
children: [
@ -86,6 +87,7 @@ class _ArtistAlbumViewState extends ConsumerState<ArtistAlbumView> {
),
],
),
),
);
}
}

View File

@ -45,7 +45,8 @@ class ArtistProfile extends HookConsumerWidget {
final breakpoint = useBreakpoints();
return Scaffold(
return SafeArea(
child: Scaffold(
appBar: const PageWindowTitleBar(
leading: BackButton(),
),
@ -128,7 +129,8 @@ class ArtistProfile extends HookConsumerWidget {
text: snapshot
.data?.externalUrls?.spotify),
).then((val) {
ScaffoldMessenger.of(context).showSnackBar(
ScaffoldMessenger.of(context)
.showSnackBar(
const SnackBar(
width: 300,
behavior: SnackBarBehavior.floating,
@ -198,8 +200,8 @@ class ArtistProfile extends HookConsumerWidget {
: Icons.play_arrow_rounded),
color: Colors.white,
onPressed: trackSnapshot.hasData
? () =>
playPlaylist(trackSnapshot.data!.toList())
? () => playPlaylist(
trackSnapshot.data!.toList())
: null,
),
)
@ -310,6 +312,7 @@ class ArtistProfile extends HookConsumerWidget {
);
},
),
),
);
}
}

View File

@ -152,7 +152,8 @@ class Home extends HookConsumerWidget {
return const Login();
}
return Scaffold(
return SafeArea(
child: Scaffold(
body: Column(
children: [
WindowTitleBarBox(
@ -165,8 +166,9 @@ class Home extends HookConsumerWidget {
constraints: BoxConstraints(
maxWidth: titleBarDragMaxWidth.toDouble(),
),
color:
Theme.of(context).navigationRailTheme.backgroundColor,
color: Theme.of(context)
.navigationRailTheme
.backgroundColor,
child: MoveWindow(),
),
Expanded(child: MoveWindow()),
@ -212,6 +214,7 @@ class Home extends HookConsumerWidget {
),
],
),
),
);
}
}

View File

@ -42,7 +42,8 @@ class PlayerView extends HookConsumerWidget {
[currentTrack?.album?.images],
);
return Scaffold(
return SafeArea(
child: Scaffold(
appBar: const PageWindowTitleBar(
leading: BackButton(),
),
@ -94,6 +95,7 @@ class PlayerView extends HookConsumerWidget {
PlayerControls(iconColor: paletteColor.bodyTextColor),
],
),
),
);
}
}

View File

@ -38,7 +38,8 @@ class PlaylistView extends ConsumerWidget {
SpotifyApi spotifyApi = ref.watch(spotifyProvider);
var isPlaylistPlaying = playback.currentPlaylist?.id != null &&
playback.currentPlaylist?.id == playlist.id;
return Scaffold(
return SafeArea(
child: Scaffold(
body: FutureBuilder<Iterable<Track>>(
future: playlist.id != "user-liked-tracks"
? spotifyApi.playlists.getTracksByPlaylistId(playlist.id).all()
@ -96,6 +97,7 @@ class PlaylistView extends ConsumerWidget {
],
);
}),
),
);
}
}

View File

@ -25,7 +25,8 @@ class Settings extends HookConsumerWidget {
geniusAccessToken.value = textEditingController.value.text;
});
return Scaffold(
return SafeArea(
child: Scaffold(
appBar: PageWindowTitleBar(
leading: const BackButton(),
center: Text(
@ -62,8 +63,8 @@ class Settings extends HookConsumerWidget {
? () async {
SharedPreferences localStorage =
await SharedPreferences.getInstance();
preferences
.setGeniusAccessToken(geniusAccessToken.value);
preferences.setGeniusAccessToken(
geniusAccessToken.value);
localStorage.setString(
LocalStorageKeys.geniusAccessToken,
geniusAccessToken.value ?? "");
@ -193,6 +194,7 @@ class Settings extends HookConsumerWidget {
],
),
),
),
);
}
}

View File

@ -52,10 +52,23 @@ class PageWindowTitleBar extends StatelessWidget
const PageWindowTitleBar({Key? key, this.leading, this.center})
: super(key: key);
@override
Size get preferredSize => Size.fromHeight(appWindow.titleBarHeight);
Size get preferredSize => Size.fromHeight(
!Platform.isIOS && !Platform.isAndroid ? appWindow.titleBarHeight : 0,
);
@override
Widget build(BuildContext context) {
if (Platform.isIOS || Platform.isAndroid) {
return PreferredSize(
preferredSize: const Size.fromHeight(70),
child: Row(
children: [
if (leading != null) leading!,
Expanded(child: Center(child: center)),
],
),
);
}
return WindowTitleBarBox(
child: Row(
children: [

View File

@ -28,7 +28,6 @@ Future<void> Function() usePreviousTrack(Playback playback) {
Future<void> Function([dynamic]) useTogglePlayPause(Playback playback) {
return ([key]) async {
print("CLICK CLICK");
try {
if (playback.currentTrack == null) return;
playback.isPlaying

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hotkey_manager/hotkey_manager.dart';
@ -18,6 +20,7 @@ useHotKeys(WidgetRef ref) {
final _playOrPause = useTogglePlayPause(playback);
useEffect(() {
if (Platform.isIOS || Platform.isAndroid) return null;
_hotKeys = [
GlobalKeyActions(
HotKey(KeyCode.space, scope: HotKeyScope.inapp),

View File

@ -14,9 +14,9 @@ import 'package:spotube/provider/ThemeProvider.dart';
import 'package:spotube/provider/YouTube.dart';
void main() async {
if (!Platform.isAndroid && !Platform.isIOS) {
WidgetsFlutterBinding.ensureInitialized();
await hotKeyManager.unregisterAll();
runApp(ProviderScope(child: MyApp()));
doWhenWindowReady(() {
appWindow.minSize =
Size(Platform.isAndroid || Platform.isIOS ? 280 : 359, 700);
@ -26,9 +26,13 @@ void main() async {
appWindow.show();
});
}
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends HookConsumerWidget {
final GoRouter _router = createGoRouter();
MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
var themeMode = ref.watch(themeProvider);

View File

@ -5,7 +5,6 @@ import 'package:spotube/components/Album/AlbumView.dart';
import 'package:spotube/components/Artist/ArtistAlbumView.dart';
import 'package:spotube/components/Artist/ArtistProfile.dart';
import 'package:spotube/components/Home/Home.dart';
import 'package:spotube/components/Player/PlayerControls.dart';
import 'package:spotube/components/Player/PlayerView.dart';
import 'package:spotube/components/Playlist/PlaylistView.dart';
import 'package:spotube/components/Settings.dart';

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:just_audio/just_audio.dart';
@ -60,9 +61,11 @@ class Playback extends ChangeNotifier {
StreamSubscription<bool>? _playingStreamListener;
StreamSubscription<Duration?>? _durationStreamListener;
StreamSubscription<ProcessingState>? _processingStateStreamListener;
StreamSubscription<AudioInterruptionEvent>? _audioInterruptionEventListener;
AudioPlayer player;
YoutubeExplode youtube;
AudioSession? _audioSession;
Playback({
required this.player,
required this.youtube,
@ -107,6 +110,14 @@ class Playback extends ChangeNotifier {
print(stack);
}
});
AudioSession.instance.then((session) async {
_audioSession = session;
await session.configure(const AudioSessionConfiguration.music());
_audioInterruptionEventListener = session.interruptionEventStream.listen(
(AudioInterruptionEvent event) {},
);
});
}
CurrentPlaylist? get currentPlaylist => _currentPlaylist;
@ -175,6 +186,8 @@ class Playback extends ChangeNotifier {
_processingStateStreamListener?.cancel();
_durationStreamListener?.cancel();
_playingStreamListener?.cancel();
_audioInterruptionEventListener?.cancel();
_audioSession?.setActive(false);
super.dispose();
}
@ -206,7 +219,7 @@ class Playback extends ChangeNotifier {
// the track is already playing so no need to change that
if (track != null && track.id == _currentTrack?.id) return;
track ??= _currentTrack;
if (track != null) {
if (track != null && await _audioSession?.setActive(true) == true) {
Uri? parsedUri = Uri.tryParse(track.uri ?? "");
if (parsedUri != null && parsedUri.hasAbsolutePath) {
await player

View File

@ -30,7 +30,7 @@ packages:
source: hosted
version: "2.8.2"
audio_session:
dependency: transitive
dependency: "direct main"
description:
name: audio_session
url: "https://pub.dartlang.org"
@ -323,7 +323,7 @@ packages:
name: just_audio_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.4"
version: "0.4.7"
libwinmedia:
dependency: transitive
description:

View File

@ -54,6 +54,7 @@ dependencies:
hooks_riverpod: ^1.0.3
go_router: ^3.0.4
palette_generator: ^0.3.3
audio_session: ^0.1.6+1
dev_dependencies:
flutter_test: