feat: web compatibility

This commit is contained in:
Kingkor Roy Tirtho 2023-08-05 10:49:53 +06:00
parent 7053d8fd7a
commit cf7b849cdd
35 changed files with 462 additions and 176 deletions

View File

@ -1,4 +1,5 @@
import 'package:catcher/catcher.dart'; import 'package:catcher/catcher.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:spotify/spotify.dart' hide Search; import 'package:spotify/spotify.dart' hide Search;
@ -84,6 +85,7 @@ final router = GoRouter(
child: const BlackListPage(), child: const BlackListPage(),
), ),
), ),
if (!kIsWeb)
GoRoute( GoRoute(
path: "logs", path: "logs",
pageBuilder: (context, state) => SpotubeSlidePage( pageBuilder: (context, state) => SpotubeSlidePage(

View File

@ -17,7 +17,6 @@ import 'package:media_kit/media_kit.dart';
import 'package:metadata_god/metadata_god.dart'; import 'package:metadata_god/metadata_god.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/collections/routes.dart'; import 'package:spotube/collections/routes.dart';
import 'package:spotube/collections/intents.dart'; import 'package:spotube/collections/intents.dart';
import 'package:spotube/hooks/use_disable_battery_optimizations.dart'; import 'package:spotube/hooks/use_disable_battery_optimizations.dart';
@ -30,7 +29,6 @@ import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/themes/theme.dart'; import 'package:spotube/themes/theme.dart';
import 'package:spotube/utils/persisted_state_notifier.dart'; import 'package:spotube/utils/persisted_state_notifier.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:system_theme/system_theme.dart'; import 'package:system_theme/system_theme.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:spotube/hooks/use_init_sys_tray.dart'; import 'package:spotube/hooks/use_init_sys_tray.dart';
@ -75,11 +73,6 @@ Future<void> main(List<String> rawArgs) async {
exit(0); exit(0);
} }
await Supabase.initialize(
url: Env.supabaseUrl,
anonKey: Env.supabaseAnonKey,
);
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
@ -101,9 +94,13 @@ Future<void> main(List<String> rawArgs) async {
); );
await SystemTheme.accentColor.load(); await SystemTheme.accentColor.load();
MetadataGod.initialize();
final hiveCacheDir = (await getApplicationSupportDirectory()).path; if (!kIsWeb) {
MetadataGod.initialize();
}
final hiveCacheDir =
kIsWeb ? null : (await getApplicationSupportDirectory()).path;
await QueryClient.initialize( await QueryClient.initialize(
cachePrefix: "oss.krtirtho.spotube", cachePrefix: "oss.krtirtho.spotube",
@ -139,13 +136,14 @@ Future<void> main(List<String> rawArgs) async {
enableDeviceParameters: false, enableDeviceParameters: false,
enableApplicationParameters: false, enableApplicationParameters: false,
), ),
FileHandler(await getLogsPath(), printLogs: false), if (!kIsWeb) FileHandler(await getLogsPath(), printLogs: false),
], ],
), ),
releaseConfig: CatcherOptions( releaseConfig: CatcherOptions(
SilentReportMode(), SilentReportMode(),
[ [
if (arguments["verbose"] ?? false) ConsoleHandler(), if (arguments["verbose"] ?? false) ConsoleHandler(),
if (!kIsWeb)
FileHandler( FileHandler(
await getLogsPath(), await getLogsPath(),
printLogs: false, printLogs: false,

View File

@ -1,6 +1,7 @@
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart'; import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
@ -506,6 +507,7 @@ class SettingsPage extends HookConsumerWidget {
), ),
], ],
), ),
if (!kIsWeb)
SectionCardWithHeading( SectionCardWithHeading(
heading: context.l10n.developers, heading: context.l10n.developers,
children: [ children: [

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:background_downloader/background_downloader.dart'; import 'package:background_downloader/background_downloader.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:metadata_god/metadata_god.dart'; import 'package:metadata_god/metadata_god.dart';
@ -30,6 +31,8 @@ class DownloadManagerProvider extends StateNotifier<List<SpotubeTrack>> {
: activeDownloadProgress = StreamController.broadcast(), : activeDownloadProgress = StreamController.broadcast(),
failedDownloads = StreamController.broadcast(), failedDownloads = StreamController.broadcast(),
super([]) { super([]) {
if (kIsWeb) return;
FileDownloader().registerCallbacks( FileDownloader().registerCallbacks(
group: FileDownloader.defaultGroup, group: FileDownloader.defaultGroup,
taskNotificationTapCallback: (task, notificationType) { taskNotificationTapCallback: (task, notificationType) {

View File

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -85,7 +86,7 @@ class UserPreferences extends PersistedChangeNotifier {
this.skipNonMusic = true, this.skipNonMusic = true,
this.youtubeApiType = YoutubeApiType.piped, this.youtubeApiType = YoutubeApiType.piped,
}) : super() { }) : super() {
if (downloadLocation.isEmpty) { if (downloadLocation.isEmpty && !kIsWeb) {
_getDefaultDownloadDirectory().then( _getDefaultDownloadDirectory().then(
(value) { (value) {
downloadLocation = value; downloadLocation = value;
@ -222,8 +223,11 @@ class UserPreferences extends PersistedChangeNotifier {
audioQuality = map["audioQuality"] != null audioQuality = map["audioQuality"] != null
? AudioQuality.values[map["audioQuality"]] ? AudioQuality.values[map["audioQuality"]]
: audioQuality; : audioQuality;
if (!kIsWeb) {
downloadLocation = downloadLocation =
map["downloadLocation"] ?? await _getDefaultDownloadDirectory(); map["downloadLocation"] ?? await _getDefaultDownloadDirectory();
}
layoutMode = LayoutMode.values.firstWhere( layoutMode = LayoutMode.values.firstWhere(
(mode) => mode.name == map["layoutMode"], (mode) => mode.name == map["layoutMode"],

View File

@ -132,11 +132,11 @@ class MkPlayerWithState extends Player {
} }
@override @override
FutureOr<void> dispose({int code = 0}) { Future<void> dispose() {
for (var element in _subscriptions) { for (var element in _subscriptions) {
element.cancel(); element.cancel();
} }
return super.dispose(code: code); return super.dispose();
} }
@override @override
@ -153,9 +153,9 @@ class MkPlayerWithState extends Player {
} }
@override @override
FutureOr<void> next() { Future<void> next() async {
if (_playlist == null || _playlist!.index + 1 >= _playlist!.medias.length) { if (_playlist == null || _playlist!.index + 1 >= _playlist!.medias.length) {
return null; return;
} }
final isLast = _playlist!.index == _playlist!.medias.length - 1; final isLast = _playlist!.index == _playlist!.medias.length - 1;
@ -170,8 +170,8 @@ class MkPlayerWithState extends Player {
} }
@override @override
FutureOr<void> previous() { Future<void> previous() async {
if (_playlist == null || _playlist!.index - 1 < 0) return null; if (_playlist == null || _playlist!.index - 1 < 0) return;
if (loopMode == PlaylistMode.loop && _playlist!.index == 0) { if (loopMode == PlaylistMode.loop && _playlist!.index == 0) {
playlist = _playlist!.copyWith(index: _playlist!.medias.length - 1); playlist = _playlist!.copyWith(index: _playlist!.medias.length - 1);
@ -183,7 +183,7 @@ class MkPlayerWithState extends Player {
} }
@override @override
FutureOr<void> jump(int index) { Future<void> jump(int index) async {
if (_playlist == null || index < 0 || index >= _playlist!.medias.length) { if (_playlist == null || index < 0 || index >= _playlist!.medias.length) {
return null; return null;
} }
@ -193,10 +193,10 @@ class MkPlayerWithState extends Player {
} }
@override @override
FutureOr<void> move(int from, int to) { Future<void> move(int from, int to) async {
if (_playlist == null || if (_playlist == null ||
from >= _playlist!.medias.length || from >= _playlist!.medias.length ||
to >= _playlist!.medias.length) return null; to >= _playlist!.medias.length) return;
final active = _playlist!.medias[_playlist!.index]; final active = _playlist!.medias[_playlist!.index];
final newPlaylist = _playlist!.copyWith( final newPlaylist = _playlist!.copyWith(
@ -255,8 +255,8 @@ class MkPlayerWithState extends Player {
} }
@override @override
FutureOr<void> add(Media media) { Future<void> add(Media media) async {
if (_playlist == null) return null; if (_playlist == null) return;
playlist = _playlist!.copyWith( playlist = _playlist!.copyWith(
medias: [..._playlist!.medias, media], medias: [..._playlist!.medias, media],
@ -289,16 +289,16 @@ class MkPlayerWithState extends Player {
/// Doesn't work when active media is the one to be removed /// Doesn't work when active media is the one to be removed
@override @override
FutureOr<void> remove(int index) async { Future<void> remove(int index) async {
if (_playlist == null || if (_playlist == null ||
index < 0 || index < 0 ||
index > _playlist!.medias.length - 1 || index > _playlist!.medias.length - 1 ||
_playlist!.index == index) { _playlist!.index == index) {
return null; return;
} }
final targetItem = _playlist!.medias.elementAtOrNull(index); final targetItem = _playlist!.medias.elementAtOrNull(index);
if (targetItem == null) return null; if (targetItem == null) return;
if (shuffled && _tempMedias != null) { if (shuffled && _tempMedias != null) {
_tempMedias!.remove(targetItem); _tempMedias!.remove(targetItem);

View File

@ -0,0 +1,274 @@
class MusicMetadata {
final String? title;
final String? artist;
final String? album;
final String? albumArtist;
final String? thumbnail;
const MusicMetadata({
this.title,
this.artist,
this.album,
this.albumArtist,
this.thumbnail,
});
}
enum PlaybackStatus {
Closed,
Changing,
Stopped,
Playing,
Paused,
}
enum PressedButton {
play,
pause,
next,
previous,
fastForward,
rewind,
stop,
record,
channelUp,
channelDown;
static PressedButton fromString(String button) {
switch (button) {
case 'play':
return PressedButton.play;
case 'pause':
return PressedButton.pause;
case 'next':
return PressedButton.next;
case 'previous':
return PressedButton.previous;
case 'fast_forward':
return PressedButton.fastForward;
case 'rewind':
return PressedButton.rewind;
case 'stop':
return PressedButton.stop;
case 'record':
return PressedButton.record;
case 'channel_up':
return PressedButton.channelUp;
case 'channel_down':
return PressedButton.channelDown;
default:
throw Exception('Unknown button: $button');
}
}
}
class SMTCConfig {
final bool playEnabled;
final bool pauseEnabled;
final bool stopEnabled;
final bool nextEnabled;
final bool prevEnabled;
final bool fastForwardEnabled;
final bool rewindEnabled;
const SMTCConfig({
required this.playEnabled,
required this.pauseEnabled,
required this.stopEnabled,
required this.nextEnabled,
required this.prevEnabled,
required this.fastForwardEnabled,
required this.rewindEnabled,
});
}
enum RepeatMode {
none,
track,
list;
static RepeatMode fromString(String value) {
switch (value) {
case 'none':
return none;
case 'track':
return track;
case 'list':
return list;
default:
throw Exception('Unknown repeat mode: $value');
}
}
String get asString => toString().split('.').last;
}
class PlaybackTimeline {
final int startTimeMs;
final int endTimeMs;
final int positionMs;
final int? minSeekTimeMs;
final int? maxSeekTimeMs;
const PlaybackTimeline({
required this.startTimeMs,
required this.endTimeMs,
required this.positionMs,
this.minSeekTimeMs,
this.maxSeekTimeMs,
});
}
class SMTCWindows {
SMTCWindows({
SMTCConfig? config,
PlaybackTimeline? timeline,
MusicMetadata? metadata,
PlaybackStatus? status,
bool? shuffleEnabled,
RepeatMode? repeatMode,
bool? enabled,
});
SMTCConfig get config => throw UnimplementedError();
PlaybackTimeline get timeline => throw UnimplementedError();
MusicMetadata get metadata => throw UnimplementedError();
PlaybackStatus? get status => throw UnimplementedError();
Stream<PressedButton> get buttonPressStream => throw UnimplementedError();
Stream<bool> get shuffleChangeStream => throw UnimplementedError();
Stream<RepeatMode> get repeatModeChangeStream => throw UnimplementedError();
bool get isPlayEnabled => config.playEnabled;
bool get isPauseEnabled => config.pauseEnabled;
bool get isStopEnabled => config.stopEnabled;
bool get isNextEnabled => config.nextEnabled;
bool get isPrevEnabled => config.prevEnabled;
bool get isFastForwardEnabled => config.fastForwardEnabled;
bool get isRewindEnabled => config.rewindEnabled;
bool get isShuffleEnabled => throw UnimplementedError();
RepeatMode get repeatMode => throw UnimplementedError();
bool get enabled => throw UnimplementedError();
Duration? get startTime => Duration(milliseconds: timeline.startTimeMs);
Duration? get endTime => Duration(milliseconds: timeline.endTimeMs);
Duration? get position => Duration(milliseconds: timeline.positionMs);
Duration? get minSeekTime => timeline.minSeekTimeMs == null
? null
: Duration(milliseconds: timeline.minSeekTimeMs!);
Duration? get maxSeekTime => timeline.maxSeekTimeMs == null
? null
: Duration(milliseconds: timeline.maxSeekTimeMs!);
Future<void> updateConfig(SMTCConfig config) {
throw UnimplementedError();
}
Future<void> updateTimeline(PlaybackTimeline timeline) {
throw UnimplementedError();
}
Future<void> updateMetadata(MusicMetadata metadata) {
throw UnimplementedError();
}
Future<void> clearMetadata() {
throw UnimplementedError();
}
Future<void> dispose() async {
throw UnimplementedError();
}
Future<void> disableSmtc() {
throw UnimplementedError();
}
Future<void> enableSmtc() {
throw UnimplementedError();
}
Future<void> setPlaybackStatus(PlaybackStatus status) async {
throw UnimplementedError();
}
Future<void> setIsPlayEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setIsPauseEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setIsStopEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setIsNextEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setIsPrevEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setIsFastForwardEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setIsRewindEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setTimeline(PlaybackTimeline timeline) {
return updateTimeline(timeline);
}
Future<void> setTitle(String title) {
throw UnimplementedError();
}
Future<void> setArtist(String artist) {
throw UnimplementedError();
}
Future<void> setAlbum(String album) {
throw UnimplementedError();
}
Future<void> setAlbumArtist(String albumArtist) {
throw UnimplementedError();
}
Future<void> setThumbnail(String thumbnail) {
throw UnimplementedError();
}
Future<void> setPosition(Duration position) {
throw UnimplementedError();
}
Future<void> setStartTime(Duration startTime) {
throw UnimplementedError();
}
Future<void> setEndTime(Duration endTime) {
throw UnimplementedError();
}
Future<void> setMaxSeekTime(Duration maxSeekTime) {
throw UnimplementedError();
}
Future<void> setMinSeekTime(Duration minSeekTime) {
throw UnimplementedError();
}
Future<void> setShuffleEnabled(bool enabled) {
throw UnimplementedError();
}
Future<void> setRepeatMode(RepeatMode repeatMode) {
throw UnimplementedError();
}
}

View File

@ -1,7 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:smtc_windows/smtc_windows.dart'; import 'package:spotube/services/audio_services/smtc_windows_web.dart'
if (dart.library.io) 'package:smtc_windows/smtc_windows.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';

View File

@ -1,8 +1,12 @@
import 'package:spotube/collections/env.dart';
import 'package:spotube/models/matched_track.dart'; import 'package:spotube/models/matched_track.dart';
import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:supabase/supabase.dart';
class SupabaseService { class SupabaseService {
static SupabaseClient get api => Supabase.instance.client; static final api = SupabaseClient(
Env.supabaseUrl,
Env.supabaseAnonKey,
);
Future<void> insertTrack(MatchedTrack track) async { Future<void> insertTrack(MatchedTrack track) async {
await api.from("tracks").insert(track.toJson()); await api.from("tracks").insert(track.toJson());

View File

@ -6,7 +6,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/routes.dart';
import 'package:spotube/components/shared/dialogs/prompt_dialog.dart'; import 'package:spotube/components/shared/dialogs/prompt_dialog.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
@ -89,7 +88,7 @@ abstract class PersistedStateNotifier<T> extends StateNotifier<T> {
} }
} }
static Future<void> initializeBoxes({required String path}) async { static Future<void> initializeBoxes({required String? path}) async {
String? boxName = await read(kKeyBoxName); String? boxName = await read(kKeyBoxName);
if (boxName == null) { if (boxName == null) {

View File

@ -5,7 +5,6 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import app_links
import audio_service import audio_service
import audio_session import audio_session
import catcher import catcher
@ -18,7 +17,6 @@ import package_info_plus
import path_provider_foundation import path_provider_foundation
import screen_retriever import screen_retriever
import shared_preferences_foundation import shared_preferences_foundation
import sign_in_with_apple
import sqflite import sqflite
import system_theme import system_theme
import system_tray import system_tray
@ -27,7 +25,6 @@ import window_manager
import window_size import window_size
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin")) AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
CatcherPlugin.register(with: registry.registrar(forPlugin: "CatcherPlugin")) CatcherPlugin.register(with: registry.registrar(forPlugin: "CatcherPlugin"))
@ -40,7 +37,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SystemThemePlugin.register(with: registry.registrar(forPlugin: "SystemThemePlugin")) SystemThemePlugin.register(with: registry.registrar(forPlugin: "SystemThemePlugin"))
SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin")) SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin"))

View File

@ -17,14 +17,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.4.0" version: "5.4.0"
app_links:
dependency: transitive
description:
name: app_links
sha256: d572dcdff49c4cfcfa6f315e2683e518ec6eb54e084d01e51d9631a4dcc1b5e8
url: "https://pub.dev"
source: hosted
version: "3.4.2"
app_package_maker: app_package_maker:
dependency: transitive dependency: transitive
description: description:
@ -853,10 +845,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: functions_client name: functions_client
sha256: "26059c5fb000ffd0986ae3144d43c2a6f54931610fd61c2584e18e308c7eaa52" sha256: "3b157b4d3ae9e38614fd80fab76d1ef1e0e39ff3412a45de2651f27cecb9d2d2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.3.2"
fuzzywuzzy: fuzzywuzzy:
dependency: "direct main" dependency: "direct main"
description: description:
@ -893,10 +885,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: gotrue name: gotrue
sha256: c08f5ac76dcae2dd06cc7f8e80a8ede12c66454fef06caac3b191c8c7a603811 sha256: "6ba95e38c06af30d4a365112b433567df70f83d5853923274cb894ea9702c5fa"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.7.1" version: "1.11.2"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
@ -1106,26 +1098,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit name: media_kit
sha256: d9a32b3f6eafdfbba6aff2e37045a3a80009b6dfbdeec638d51d85e8b254a6a2 sha256: "272a9f1dd77ed57b48707fdb0ec0e4a048ef958feccc0d0dd751135fe924b63a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.0.7+1" version: "1.1.1"
media_kit_libs_android_audio: media_kit_libs_android_audio:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_libs_android_audio name: media_kit_libs_android_audio
sha256: e16292bbb1d737ce026fa68154b2fcf5c6f88d6fa752bdb4c0d079c98a82b523 sha256: "304b6d4045280b11bf7b4f9a4330556dbc98d7431f2c20e9dec133ed80d3ec78"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.3.0"
media_kit_libs_ios_audio: media_kit_libs_ios_audio:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_libs_ios_audio name: media_kit_libs_ios_audio
sha256: bb18ed87e8a155fc1d2ee4bf59462ca04d02a0eeb38d0b454facee6d32441ce7 sha256: "1b6f7bbaedb2914bb94bb22d5a890238dc883698b42a1a858e9c38194e6281d0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
media_kit_libs_linux: media_kit_libs_linux:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1138,26 +1130,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_libs_macos_audio name: media_kit_libs_macos_audio
sha256: b9f4a2995396fd5cc243901e618c0586d4f1781eecf2302999b77d6faee8b250 sha256: "070dc90ecf3a07dcb23d39f8473329e8e4616c36d12badd0831fef446428acc2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "1.0.6"
media_kit_libs_windows_audio: media_kit_libs_windows_audio:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_libs_windows_audio name: media_kit_libs_windows_audio
sha256: f6ad5a1b910a6748a7350360756cd99a718fc9661a9583a7fd86a308d068dd81 sha256: "34b768e385181b2e475dd846345ed1191bde85a4c64db014d239d4c9f844c5fd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.3" version: "1.0.5"
media_kit_native_event_loop: media_kit_native_event_loop:
dependency: "direct main" dependency: "direct main"
description: description:
name: media_kit_native_event_loop name: media_kit_native_event_loop
sha256: "521125e534603c3f603b93283db3938f557f33ecc383fbd62edd4beb3bf73747" sha256: "5351f0c28124b5358756515d8619abad182cdefe967468d7fb5b274737cc2f59"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.6"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@ -1426,10 +1418,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: postgrest name: postgrest
sha256: "7b91eb7b40621d07aaae687f47f3032f30e1b86a9ccebfcfca52d001223f8b6e" sha256: "6a0f28f33af4582a9874ce15520531280d39831f356f9740839ec142fc8deeff"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.4" version: "1.4.0"
process: process:
dependency: transitive dependency: transitive
description: description:
@ -1498,10 +1490,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: realtime_client name: realtime_client
sha256: "0f2614f72e5639ddd7abc3dede336f23554f9f744d0b064d41009f9ca94a53d2" sha256: ff743de9bb0f46fcfffcfe64ae93062702dcd0f83a2ce8adc40d5fb7f542af90
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.1.3"
retry: retry:
dependency: transitive dependency: transitive
description: description:
@ -1646,30 +1638,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.15.0" version: "0.15.0"
sign_in_with_apple:
dependency: transitive
description:
name: sign_in_with_apple
sha256: ac3b113767dfdd765078c507dad9d4d9fe96b669cc7bd88fc36fc15376fb3400
url: "https://pub.dev"
source: hosted
version: "4.3.0"
sign_in_with_apple_platform_interface:
dependency: transitive
description:
name: sign_in_with_apple_platform_interface
sha256: a5883edee09ed6be19de19e7d9f618a617fe41a6fa03f76d082dfb787e9ea18d
url: "https://pub.dev"
source: hosted
version: "1.0.0"
sign_in_with_apple_web:
dependency: transitive
description:
name: sign_in_with_apple_web
sha256: "44b66528f576e77847c14999d5e881e17e7223b7b0625a185417829e5306f47a"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
skeleton_text: skeleton_text:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1759,10 +1727,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: storage_client name: storage_client
sha256: "4ed4dc8a990d178c96962319d6d8c267c3e206fca2c2b98660bad6e001220ffc" sha256: a3024569213b064587d616827747b766f9bc796e80cec99bd5ffb597b8aeb018
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.5.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
@ -1788,21 +1756,13 @@ packages:
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
supabase: supabase:
dependency: transitive
description:
name: supabase
sha256: "403739cdfea48ba633450e5b191ceeaae81ac10ec89166c0e109235b3e1532f3"
url: "https://pub.dev"
source: hosted
version: "1.8.1"
supabase_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
name: supabase_flutter name: supabase
sha256: "7cbdd9a7264dd5b7ab5a6e2da63346054b8e5ddf358467c7f2bc23d5c14d732c" sha256: "8186f7ae39b1b27d860b9a8371801ac875a7e251a77235918a1adc3129690014"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.9"
sync_http: sync_http:
dependency: transitive dependency: transitive
description: description:
@ -1907,6 +1867,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
universal_platform:
dependency: transitive
description:
name: universal_platform
sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc
url: "https://pub.dev"
source: hosted
version: "1.0.0+1"
uri: uri:
dependency: transitive dependency: transitive
description: description:
@ -2051,38 +2019,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.0.2"
webview_flutter:
dependency: transitive
description:
name: webview_flutter
sha256: "1a37bdbaaf5fbe09ad8579ab09ecfd473284ce482f900b5aea27cf834386a567"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
sha256: "1acea8def62592123e2fbbca164ed8681a98a890bdcbb88f916d5b4a22687759"
url: "https://pub.dev"
source: hosted
version: "3.7.0"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "78715dc442b7849dbde74e92bb67de1cecf5addf95531c5fb474e72f5fe9a507"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: "4646bb68297803bdbb96d46853e8fcb560d6cb5e04153fa64581535767875dfe"
url: "https://pub.dev"
source: hosted
version: "3.4.3"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@ -2144,10 +2080,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: yet_another_json_isolate name: yet_another_json_isolate
sha256: "94ba4947ac1ce44bd6a1634d9df712e07b9b5025ba12abd6750be77ba5c08f18" sha256: "86fad76026c4241a32831d6c7febd8f9bded5019e2cd36c5b148499808d8307d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.1.1"
youtube_explode_dart: youtube_explode_dart:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -59,12 +59,13 @@ dependencies:
introduction_screen: ^3.0.2 introduction_screen: ^3.0.2
json_annotation: ^4.8.1 json_annotation: ^4.8.1
logger: ^1.1.0 logger: ^1.1.0
media_kit: ^0.0.7+1 media_kit: ^1.1.1
media_kit_libs_android_audio: ^1.0.4 media_kit_native_event_loop: ^1.0.6
media_kit_libs_ios_audio: ^1.0.4 media_kit_libs_android_audio: ^1.3.0
media_kit_libs_ios_audio: ^1.0.5
media_kit_libs_macos_audio: ^1.0.6
media_kit_libs_windows_audio: ^1.0.5
media_kit_libs_linux: ^1.0.2 media_kit_libs_linux: ^1.0.2
media_kit_libs_macos_audio: ^1.0.5
media_kit_libs_windows_audio: ^1.0.3
metadata_god: ^0.5.0 metadata_god: ^0.5.0
mime: ^1.0.2 mime: ^1.0.2
package_info_plus: ^3.0.2 package_info_plus: ^3.0.2
@ -92,9 +93,7 @@ dependencies:
ref: a738913c8ce2c9f47515382d40827e794a334274 ref: a738913c8ce2c9f47515382d40827e794a334274
path: plugins/window_size path: plugins/window_size
piped_client: ^0.1.0 piped_client: ^0.1.0
supabase_flutter: ^1.9.1
device_preview: ^1.1.0 device_preview: ^1.1.0
media_kit_native_event_loop: ^1.0.4
dbus: ^0.7.8 dbus: ^0.7.8
background_downloader: ^7.4.0 background_downloader: ^7.4.0
duration: ^3.0.12 duration: ^3.0.12
@ -102,6 +101,7 @@ dependencies:
youtube_explode_dart: ^1.12.4 youtube_explode_dart: ^1.12.4
flutter_displaymode: ^0.6.0 flutter_displaymode: ^0.6.0
google_fonts: ^4.0.4 google_fonts: ^4.0.4
supabase: ^1.9.9
dev_dependencies: dev_dependencies:
build_runner: ^2.3.2 build_runner: ^2.3.2
@ -155,4 +155,3 @@ flutter_native_splash:
branding: assets/branding.png branding: assets/branding.png
color: "#000000" color: "#000000"
icon_background_color: "#000000" icon_background_color: "#000000"
web: false

View File

@ -1,6 +1,4 @@
<!DOCTYPE html> <!DOCTYPE html><html><head>
<html>
<head>
<!-- <!--
If you are serving your web app in a path other than the root, change the If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from. href value below to reflect the base path you are serving from.
@ -27,12 +25,23 @@
<link rel="apple-touch-icon" href="icons/Icon-192.png"> <link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/> <link rel="icon" type="image/png" href="favicon.png">
<title>spotube</title> <title>spotube</title>
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
<link rel="stylesheet" type="text/css" href="splash/style.css">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<script src="splash/splash.js"></script>
</head> </head>
<body> <body> <picture id="splash-branding">
<source srcset="splash/img/branding-1x.png 1x, splash/img/branding-2x.png 2x, splash/img/branding-3x.png 3x, splash/img/branding-4x.png 4x" media="(prefers-color-scheme: light)">
<source srcset="splash/img/branding-dark-1x.png 1x, splash/img/branding-dark-2x.png 2x, splash/img/branding-dark-3x.png 3x, splash/img/branding-dark-4x.png 4x" media="(prefers-color-scheme: dark)">
<img class="bottom" aria-hidden="true" src="splash/img/branding-1x.png" alt="">
</picture> <picture id="splash">
<source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)">
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)">
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt="">
</picture>
<!-- This script installs service_worker.js to provide PWA functionality to <!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see: application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers --> https://developers.google.com/web/fundamentals/primers/service-workers -->
@ -100,5 +109,6 @@
loadMainDartJs(); loadMainDartJs();
} }
</script> </script>
</body>
</html>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
web/splash/img/dark-1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
web/splash/img/dark-2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
web/splash/img/dark-3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
web/splash/img/dark-4x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
web/splash/img/light-1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
web/splash/img/light-2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
web/splash/img/light-3x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
web/splash/img/light-4x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

5
web/splash/splash.js Normal file
View File

@ -0,0 +1,5 @@
function removeSplashFromWeb() {
document.getElementById("splash")?.remove();
document.getElementById("splash-branding")?.remove();
document.body.style.background = "transparent";
}

57
web/splash/style.css Normal file
View File

@ -0,0 +1,57 @@
html {
height: 100%
}
body {
margin: 0;
min-height: 100%;
background-color: #ffffff;
background-image: url("img/light-background.png");
background-size: 100% 100%;
}
.center {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.contain {
display:block;
width:100%; height:100%;
object-fit: contain;
}
.stretch {
display:block;
width:100%; height:100%;
}
.cover {
display:block;
width:100%; height:100%;
object-fit: cover;
}
.bottom {
position: absolute;
bottom: 0;
left: 50%;
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
.bottomLeft {
position: absolute;
bottom: 0;
left: 0;
}
.bottomRight {
position: absolute;
bottom: 0;
right: 0;
}

View File

@ -6,7 +6,6 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <app_links/app_links_plugin_c_api.h>
#include <catcher/catcher_plugin.h> #include <catcher/catcher_plugin.h>
#include <connectivity_plus/connectivity_plus_windows_plugin.h> #include <connectivity_plus/connectivity_plus_windows_plugin.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h> #include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
@ -21,8 +20,6 @@
#include <window_size/window_size_plugin.h> #include <window_size/window_size_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
AppLinksPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
CatcherPluginRegisterWithRegistrar( CatcherPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("CatcherPlugin")); registry->GetRegistrarForPlugin("CatcherPlugin"));
ConnectivityPlusWindowsPluginRegisterWithRegistrar( ConnectivityPlusWindowsPluginRegisterWithRegistrar(

View File

@ -3,7 +3,6 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
app_links
catcher catcher
connectivity_plus connectivity_plus
flutter_secure_storage_windows flutter_secure_storage_windows