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:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:spotify/spotify.dart' hide Search;
@ -84,12 +85,13 @@ final router = GoRouter(
child: const BlackListPage(),
),
),
GoRoute(
path: "logs",
pageBuilder: (context, state) => SpotubeSlidePage(
child: const LogsPage(),
if (!kIsWeb)
GoRoute(
path: "logs",
pageBuilder: (context, state) => SpotubeSlidePage(
child: const LogsPage(),
),
),
),
GoRoute(
path: "about",
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:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/collections/routes.dart';
import 'package:spotube/collections/intents.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/themes/theme.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:path_provider/path_provider.dart';
import 'package:spotube/hooks/use_init_sys_tray.dart';
@ -75,11 +73,6 @@ Future<void> main(List<String> rawArgs) async {
exit(0);
}
await Supabase.initialize(
url: Env.supabaseUrl,
anonKey: Env.supabaseAnonKey,
);
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
@ -101,9 +94,13 @@ Future<void> main(List<String> rawArgs) async {
);
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(
cachePrefix: "oss.krtirtho.spotube",
@ -139,17 +136,18 @@ Future<void> main(List<String> rawArgs) async {
enableDeviceParameters: false,
enableApplicationParameters: false,
),
FileHandler(await getLogsPath(), printLogs: false),
if (!kIsWeb) FileHandler(await getLogsPath(), printLogs: false),
],
),
releaseConfig: CatcherOptions(
SilentReportMode(),
[
if (arguments["verbose"] ?? false) ConsoleHandler(),
FileHandler(
await getLogsPath(),
printLogs: false,
),
if (!kIsWeb)
FileHandler(
await getLogsPath(),
printLogs: false,
),
],
),
runAppFunction: () {

View File

@ -1,6 +1,7 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -506,19 +507,20 @@ class SettingsPage extends HookConsumerWidget {
),
],
),
SectionCardWithHeading(
heading: context.l10n.developers,
children: [
ListTile(
leading: const Icon(SpotubeIcons.logs),
title: Text(context.l10n.logs),
trailing: const Icon(SpotubeIcons.angleRight),
onTap: () {
GoRouter.of(context).push("/settings/logs");
},
)
],
),
if (!kIsWeb)
SectionCardWithHeading(
heading: context.l10n.developers,
children: [
ListTile(
leading: const Icon(SpotubeIcons.logs),
title: Text(context.l10n.logs),
trailing: const Icon(SpotubeIcons.angleRight),
onTap: () {
GoRouter.of(context).push("/settings/logs");
},
)
],
),
SectionCardWithHeading(
heading: context.l10n.about,
children: [

View File

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

View File

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

View File

@ -132,11 +132,11 @@ class MkPlayerWithState extends Player {
}
@override
FutureOr<void> dispose({int code = 0}) {
Future<void> dispose() {
for (var element in _subscriptions) {
element.cancel();
}
return super.dispose(code: code);
return super.dispose();
}
@override
@ -153,9 +153,9 @@ class MkPlayerWithState extends Player {
}
@override
FutureOr<void> next() {
Future<void> next() async {
if (_playlist == null || _playlist!.index + 1 >= _playlist!.medias.length) {
return null;
return;
}
final isLast = _playlist!.index == _playlist!.medias.length - 1;
@ -170,8 +170,8 @@ class MkPlayerWithState extends Player {
}
@override
FutureOr<void> previous() {
if (_playlist == null || _playlist!.index - 1 < 0) return null;
Future<void> previous() async {
if (_playlist == null || _playlist!.index - 1 < 0) return;
if (loopMode == PlaylistMode.loop && _playlist!.index == 0) {
playlist = _playlist!.copyWith(index: _playlist!.medias.length - 1);
@ -183,7 +183,7 @@ class MkPlayerWithState extends Player {
}
@override
FutureOr<void> jump(int index) {
Future<void> jump(int index) async {
if (_playlist == null || index < 0 || index >= _playlist!.medias.length) {
return null;
}
@ -193,10 +193,10 @@ class MkPlayerWithState extends Player {
}
@override
FutureOr<void> move(int from, int to) {
Future<void> move(int from, int to) async {
if (_playlist == null ||
from >= _playlist!.medias.length ||
to >= _playlist!.medias.length) return null;
to >= _playlist!.medias.length) return;
final active = _playlist!.medias[_playlist!.index];
final newPlaylist = _playlist!.copyWith(
@ -255,8 +255,8 @@ class MkPlayerWithState extends Player {
}
@override
FutureOr<void> add(Media media) {
if (_playlist == null) return null;
Future<void> add(Media media) async {
if (_playlist == null) return;
playlist = _playlist!.copyWith(
medias: [..._playlist!.medias, media],
@ -289,16 +289,16 @@ class MkPlayerWithState extends Player {
/// Doesn't work when active media is the one to be removed
@override
FutureOr<void> remove(int index) async {
Future<void> remove(int index) async {
if (_playlist == null ||
index < 0 ||
index > _playlist!.medias.length - 1 ||
_playlist!.index == index) {
return null;
return;
}
final targetItem = _playlist!.medias.elementAtOrNull(index);
if (targetItem == null) return null;
if (targetItem == null) return;
if (shuffled && _tempMedias != null) {
_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 '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:spotube/provider/proxy_playlist/proxy_playlist_provider.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:supabase_flutter/supabase_flutter.dart';
import 'package:supabase/supabase.dart';
class SupabaseService {
static SupabaseClient get api => Supabase.instance.client;
static final api = SupabaseClient(
Env.supabaseUrl,
Env.supabaseAnonKey,
);
Future<void> insertTrack(MatchedTrack track) async {
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:hive/hive.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/extensions/context.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);
if (boxName == null) {

View File

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

View File

@ -17,14 +17,6 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:
@ -853,10 +845,10 @@ packages:
dependency: transitive
description:
name: functions_client
sha256: "26059c5fb000ffd0986ae3144d43c2a6f54931610fd61c2584e18e308c7eaa52"
sha256: "3b157b4d3ae9e38614fd80fab76d1ef1e0e39ff3412a45de2651f27cecb9d2d2"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
version: "1.3.2"
fuzzywuzzy:
dependency: "direct main"
description:
@ -893,10 +885,10 @@ packages:
dependency: transitive
description:
name: gotrue
sha256: c08f5ac76dcae2dd06cc7f8e80a8ede12c66454fef06caac3b191c8c7a603811
sha256: "6ba95e38c06af30d4a365112b433567df70f83d5853923274cb894ea9702c5fa"
url: "https://pub.dev"
source: hosted
version: "1.7.1"
version: "1.11.2"
graphs:
dependency: transitive
description:
@ -1106,26 +1098,26 @@ packages:
dependency: "direct main"
description:
name: media_kit
sha256: d9a32b3f6eafdfbba6aff2e37045a3a80009b6dfbdeec638d51d85e8b254a6a2
sha256: "272a9f1dd77ed57b48707fdb0ec0e4a048ef958feccc0d0dd751135fe924b63a"
url: "https://pub.dev"
source: hosted
version: "0.0.7+1"
version: "1.1.1"
media_kit_libs_android_audio:
dependency: "direct main"
description:
name: media_kit_libs_android_audio
sha256: e16292bbb1d737ce026fa68154b2fcf5c6f88d6fa752bdb4c0d079c98a82b523
sha256: "304b6d4045280b11bf7b4f9a4330556dbc98d7431f2c20e9dec133ed80d3ec78"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
version: "1.3.0"
media_kit_libs_ios_audio:
dependency: "direct main"
description:
name: media_kit_libs_ios_audio
sha256: bb18ed87e8a155fc1d2ee4bf59462ca04d02a0eeb38d0b454facee6d32441ce7
sha256: "1b6f7bbaedb2914bb94bb22d5a890238dc883698b42a1a858e9c38194e6281d0"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
version: "1.0.5"
media_kit_libs_linux:
dependency: "direct main"
description:
@ -1138,26 +1130,26 @@ packages:
dependency: "direct main"
description:
name: media_kit_libs_macos_audio
sha256: b9f4a2995396fd5cc243901e618c0586d4f1781eecf2302999b77d6faee8b250
sha256: "070dc90ecf3a07dcb23d39f8473329e8e4616c36d12badd0831fef446428acc2"
url: "https://pub.dev"
source: hosted
version: "1.0.5"
version: "1.0.6"
media_kit_libs_windows_audio:
dependency: "direct main"
description:
name: media_kit_libs_windows_audio
sha256: f6ad5a1b910a6748a7350360756cd99a718fc9661a9583a7fd86a308d068dd81
sha256: "34b768e385181b2e475dd846345ed1191bde85a4c64db014d239d4c9f844c5fd"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
version: "1.0.5"
media_kit_native_event_loop:
dependency: "direct main"
description:
name: media_kit_native_event_loop
sha256: "521125e534603c3f603b93283db3938f557f33ecc383fbd62edd4beb3bf73747"
sha256: "5351f0c28124b5358756515d8619abad182cdefe967468d7fb5b274737cc2f59"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
version: "1.0.6"
meta:
dependency: transitive
description:
@ -1426,10 +1418,10 @@ packages:
dependency: transitive
description:
name: postgrest
sha256: "7b91eb7b40621d07aaae687f47f3032f30e1b86a9ccebfcfca52d001223f8b6e"
sha256: "6a0f28f33af4582a9874ce15520531280d39831f356f9740839ec142fc8deeff"
url: "https://pub.dev"
source: hosted
version: "1.2.4"
version: "1.4.0"
process:
dependency: transitive
description:
@ -1498,10 +1490,10 @@ packages:
dependency: transitive
description:
name: realtime_client
sha256: "0f2614f72e5639ddd7abc3dede336f23554f9f744d0b064d41009f9ca94a53d2"
sha256: ff743de9bb0f46fcfffcfe64ae93062702dcd0f83a2ce8adc40d5fb7f542af90
url: "https://pub.dev"
source: hosted
version: "1.0.4"
version: "1.1.3"
retry:
dependency: transitive
description:
@ -1646,30 +1638,6 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: "direct main"
description:
@ -1759,10 +1727,10 @@ packages:
dependency: transitive
description:
name: storage_client
sha256: "4ed4dc8a990d178c96962319d6d8c267c3e206fca2c2b98660bad6e001220ffc"
sha256: a3024569213b064587d616827747b766f9bc796e80cec99bd5ffb597b8aeb018
url: "https://pub.dev"
source: hosted
version: "1.3.1"
version: "1.5.1"
stream_channel:
dependency: transitive
description:
@ -1788,21 +1756,13 @@ packages:
source: hosted
version: "1.2.0"
supabase:
dependency: transitive
description:
name: supabase
sha256: "403739cdfea48ba633450e5b191ceeaae81ac10ec89166c0e109235b3e1532f3"
url: "https://pub.dev"
source: hosted
version: "1.8.1"
supabase_flutter:
dependency: "direct main"
description:
name: supabase_flutter
sha256: "7cbdd9a7264dd5b7ab5a6e2da63346054b8e5ddf358467c7f2bc23d5c14d732c"
name: supabase
sha256: "8186f7ae39b1b27d860b9a8371801ac875a7e251a77235918a1adc3129690014"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.9.9"
sync_http:
dependency: transitive
description:
@ -1907,6 +1867,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:
@ -2051,38 +2019,6 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:
@ -2144,10 +2080,10 @@ packages:
dependency: transitive
description:
name: yet_another_json_isolate
sha256: "94ba4947ac1ce44bd6a1634d9df712e07b9b5025ba12abd6750be77ba5c08f18"
sha256: "86fad76026c4241a32831d6c7febd8f9bded5019e2cd36c5b148499808d8307d"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
version: "1.1.1"
youtube_explode_dart:
dependency: "direct main"
description:

View File

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

View File

@ -1,6 +1,4 @@
<!DOCTYPE html>
<html>
<head>
<!DOCTYPE html><html><head>
<!--
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.
@ -27,12 +25,23 @@
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<link rel="icon" type="image/png" href="favicon.png">
<title>spotube</title>
<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>
<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
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
@ -100,5 +109,6 @@
loadMainDartJs();
}
</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 <app_links/app_links_plugin_c_api.h>
#include <catcher/catcher_plugin.h>
#include <connectivity_plus/connectivity_plus_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>
void RegisterPlugins(flutter::PluginRegistry* registry) {
AppLinksPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
CatcherPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("CatcherPlugin"));
ConnectivityPlusWindowsPluginRegisterWithRegistrar(

View File

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