feat: web compatibility
@ -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,12 +85,13 @@ final router = GoRouter(
|
|||||||
child: const BlackListPage(),
|
child: const BlackListPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
if (!kIsWeb)
|
||||||
path: "logs",
|
GoRoute(
|
||||||
pageBuilder: (context, state) => SpotubeSlidePage(
|
path: "logs",
|
||||||
child: const LogsPage(),
|
pageBuilder: (context, state) => SpotubeSlidePage(
|
||||||
|
child: const LogsPage(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: "about",
|
path: "about",
|
||||||
pageBuilder: (context, state) => SpotubeSlidePage(
|
pageBuilder: (context, state) => SpotubeSlidePage(
|
||||||
|
@ -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,17 +136,18 @@ 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(),
|
||||||
FileHandler(
|
if (!kIsWeb)
|
||||||
await getLogsPath(),
|
FileHandler(
|
||||||
printLogs: false,
|
await getLogsPath(),
|
||||||
),
|
printLogs: false,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
runAppFunction: () {
|
runAppFunction: () {
|
||||||
|
@ -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,19 +507,20 @@ class SettingsPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SectionCardWithHeading(
|
if (!kIsWeb)
|
||||||
heading: context.l10n.developers,
|
SectionCardWithHeading(
|
||||||
children: [
|
heading: context.l10n.developers,
|
||||||
ListTile(
|
children: [
|
||||||
leading: const Icon(SpotubeIcons.logs),
|
ListTile(
|
||||||
title: Text(context.l10n.logs),
|
leading: const Icon(SpotubeIcons.logs),
|
||||||
trailing: const Icon(SpotubeIcons.angleRight),
|
title: Text(context.l10n.logs),
|
||||||
onTap: () {
|
trailing: const Icon(SpotubeIcons.angleRight),
|
||||||
GoRouter.of(context).push("/settings/logs");
|
onTap: () {
|
||||||
},
|
GoRouter.of(context).push("/settings/logs");
|
||||||
)
|
},
|
||||||
],
|
)
|
||||||
),
|
],
|
||||||
|
),
|
||||||
SectionCardWithHeading(
|
SectionCardWithHeading(
|
||||||
heading: context.l10n.about,
|
heading: context.l10n.about,
|
||||||
children: [
|
children: [
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
downloadLocation =
|
|
||||||
map["downloadLocation"] ?? await _getDefaultDownloadDirectory();
|
if (!kIsWeb) {
|
||||||
|
downloadLocation =
|
||||||
|
map["downloadLocation"] ?? await _getDefaultDownloadDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
layoutMode = LayoutMode.values.firstWhere(
|
layoutMode = LayoutMode.values.firstWhere(
|
||||||
(mode) => mode.name == map["layoutMode"],
|
(mode) => mode.name == map["layoutMode"],
|
||||||
|
@ -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);
|
||||||
|
274
lib/services/audio_services/smtc_windows_web.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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';
|
||||||
|
@ -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());
|
||||||
|
@ -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) {
|
||||||
|
@ -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"))
|
||||||
|
134
pubspec.lock
@ -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:
|
||||||
|
15
pubspec.yaml
@ -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
|
|
||||||
|
@ -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>
|
BIN
web/splash/img/branding-1x.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
web/splash/img/branding-2x.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
web/splash/img/branding-3x.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
web/splash/img/branding-4x.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
web/splash/img/branding-dark-1x.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
web/splash/img/branding-dark-2x.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
web/splash/img/branding-dark-3x.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
web/splash/img/branding-dark-4x.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
web/splash/img/dark-1x.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
web/splash/img/dark-2x.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
web/splash/img/dark-3x.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
web/splash/img/dark-4x.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
web/splash/img/light-1x.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
web/splash/img/light-2x.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
web/splash/img/light-3x.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
web/splash/img/light-4x.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
web/splash/img/light-background.png
Normal file
After Width: | Height: | Size: 3.1 MiB |
5
web/splash/splash.js
Normal 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
@ -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;
|
||||||
|
}
|
@ -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(
|
||||||
|
@ -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
|
||||||
|