mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-05-08 16:24:36 +00:00
feat: add one additional library folder
This folder just doesn't get downloaded to. I think I'm going to rework it so that it can be multiple folders, but I'm going to commit my progress so far anyway. Signed-off-by: Blake Leonard <me@blakes.dev>
This commit is contained in:
parent
2b01e4fb4d
commit
f423c20063
@ -71,7 +71,20 @@ final localTracksProvider = FutureProvider<List<LocalTrack>>((ref) async {
|
|||||||
await downloadDir.create(recursive: true);
|
await downloadDir.create(recursive: true);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
final entities = downloadDir.listSync(recursive: true);
|
final downloadEntities = downloadDir.listSync(recursive: true);
|
||||||
|
|
||||||
|
final localLibraryLocation = ref.watch(
|
||||||
|
userPreferencesProvider.select((s) => s.localLibraryLocation),
|
||||||
|
);
|
||||||
|
if (localLibraryLocation.isEmpty) return [];
|
||||||
|
final localLibraryDir = Directory(localLibraryLocation);
|
||||||
|
if (!await localLibraryDir.exists()) {
|
||||||
|
await localLibraryDir.create(recursive: true);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
final localLibraryEntities = localLibraryDir.listSync(recursive: true);
|
||||||
|
|
||||||
|
final entities = [...downloadEntities, ...localLibraryEntities];
|
||||||
|
|
||||||
final filesWithMetadata = (await Future.wait(
|
final filesWithMetadata = (await Future.wait(
|
||||||
entities.map((e) => File(e.path)).where((file) {
|
entities.map((e) => File(e.path)).where((file) {
|
||||||
|
|||||||
@ -107,6 +107,7 @@
|
|||||||
"always_on_top": "Always on top",
|
"always_on_top": "Always on top",
|
||||||
"exit_mini_player": "Exit Mini player",
|
"exit_mini_player": "Exit Mini player",
|
||||||
"download_location": "Download location",
|
"download_location": "Download location",
|
||||||
|
"local_library_location": "Local library location",
|
||||||
"account": "Account",
|
"account": "Account",
|
||||||
"login_with_spotify": "Login with your Spotify account",
|
"login_with_spotify": "Login with your Spotify account",
|
||||||
"connect_with_spotify": "Connect with Spotify",
|
"connect_with_spotify": "Connect with Spotify",
|
||||||
@ -321,4 +322,4 @@
|
|||||||
"connect_client_alert": "You're being controlled by {client}",
|
"connect_client_alert": "You're being controlled by {client}",
|
||||||
"this_device": "This Device",
|
"this_device": "This Device",
|
||||||
"remote": "Remote"
|
"remote": "Remote"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,22 @@ class SettingsDownloadsSection extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}, [preferences.downloadLocation]);
|
}, [preferences.downloadLocation]);
|
||||||
|
|
||||||
|
final pickLocalLibraryLocation = useCallback(() async {
|
||||||
|
if (DesktopTools.platform.isMobile || DesktopTools.platform.isMacOS) {
|
||||||
|
final dirStr = await FilePicker.platform.getDirectoryPath(
|
||||||
|
initialDirectory: preferences.localLibraryLocation,
|
||||||
|
);
|
||||||
|
if (dirStr == null) return;
|
||||||
|
preferencesNotifier.setLocalLibraryLocation(dirStr);
|
||||||
|
} else {
|
||||||
|
String? dirStr = await getDirectoryPath(
|
||||||
|
initialDirectory: preferences.localLibraryLocation,
|
||||||
|
);
|
||||||
|
if (dirStr == null) return;
|
||||||
|
preferencesNotifier.setLocalLibraryLocation(dirStr);
|
||||||
|
}
|
||||||
|
}, [preferences.localLibraryLocation]);
|
||||||
|
|
||||||
return SectionCardWithHeading(
|
return SectionCardWithHeading(
|
||||||
heading: context.l10n.downloads,
|
heading: context.l10n.downloads,
|
||||||
children: [
|
children: [
|
||||||
@ -46,6 +62,16 @@ class SettingsDownloadsSection extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
onTap: pickDownloadLocation,
|
onTap: pickDownloadLocation,
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(SpotubeIcons.folder),
|
||||||
|
title: Text(context.l10n.local_library_location),
|
||||||
|
subtitle: Text(preferences.localLibraryLocation),
|
||||||
|
trailing: FilledButton(
|
||||||
|
onPressed: pickLocalLibraryLocation,
|
||||||
|
child: const Icon(SpotubeIcons.folder),
|
||||||
|
),
|
||||||
|
onTap: pickLocalLibraryLocation,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,11 @@ class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
|
|||||||
state = state.copyWith(downloadLocation: downloadDir);
|
state = state.copyWith(downloadLocation: downloadDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLocalLibraryLocation(String localLibraryDir) {
|
||||||
|
if (localLibraryDir.isEmpty) return;
|
||||||
|
state = state.copyWith(localLibraryLocation: localLibraryDir);
|
||||||
|
}
|
||||||
|
|
||||||
void setLayoutMode(LayoutMode mode) {
|
void setLayoutMode(LayoutMode mode) {
|
||||||
state = state.copyWith(layoutMode: mode);
|
state = state.copyWith(layoutMode: mode);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,6 +84,7 @@ class UserPreferences with _$UserPreferences {
|
|||||||
@Default(Market.US) Market recommendationMarket,
|
@Default(Market.US) Market recommendationMarket,
|
||||||
@Default(SearchMode.youtube) SearchMode searchMode,
|
@Default(SearchMode.youtube) SearchMode searchMode,
|
||||||
@Default("") String downloadLocation,
|
@Default("") String downloadLocation,
|
||||||
|
@Default("") String localLibraryLocation,
|
||||||
@Default("https://pipedapi.kavin.rocks") String pipedInstance,
|
@Default("https://pipedapi.kavin.rocks") String pipedInstance,
|
||||||
@Default(ThemeMode.system) ThemeMode themeMode,
|
@Default(ThemeMode.system) ThemeMode themeMode,
|
||||||
@Default(AudioSource.youtube) AudioSource audioSource,
|
@Default(AudioSource.youtube) AudioSource audioSource,
|
||||||
|
|||||||
@ -43,6 +43,7 @@ mixin _$UserPreferences {
|
|||||||
Market get recommendationMarket => throw _privateConstructorUsedError;
|
Market get recommendationMarket => throw _privateConstructorUsedError;
|
||||||
SearchMode get searchMode => throw _privateConstructorUsedError;
|
SearchMode get searchMode => throw _privateConstructorUsedError;
|
||||||
String get downloadLocation => throw _privateConstructorUsedError;
|
String get downloadLocation => throw _privateConstructorUsedError;
|
||||||
|
String get localLibraryLocation => throw _privateConstructorUsedError;
|
||||||
String get pipedInstance => throw _privateConstructorUsedError;
|
String get pipedInstance => throw _privateConstructorUsedError;
|
||||||
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
||||||
AudioSource get audioSource => throw _privateConstructorUsedError;
|
AudioSource get audioSource => throw _privateConstructorUsedError;
|
||||||
@ -88,6 +89,7 @@ abstract class $UserPreferencesCopyWith<$Res> {
|
|||||||
Market recommendationMarket,
|
Market recommendationMarket,
|
||||||
SearchMode searchMode,
|
SearchMode searchMode,
|
||||||
String downloadLocation,
|
String downloadLocation,
|
||||||
|
String localLibraryLocation,
|
||||||
String pipedInstance,
|
String pipedInstance,
|
||||||
ThemeMode themeMode,
|
ThemeMode themeMode,
|
||||||
AudioSource audioSource,
|
AudioSource audioSource,
|
||||||
@ -126,6 +128,7 @@ class _$UserPreferencesCopyWithImpl<$Res, $Val extends UserPreferences>
|
|||||||
Object? recommendationMarket = null,
|
Object? recommendationMarket = null,
|
||||||
Object? searchMode = null,
|
Object? searchMode = null,
|
||||||
Object? downloadLocation = null,
|
Object? downloadLocation = null,
|
||||||
|
Object? localLibraryLocation = null,
|
||||||
Object? pipedInstance = null,
|
Object? pipedInstance = null,
|
||||||
Object? themeMode = null,
|
Object? themeMode = null,
|
||||||
Object? audioSource = null,
|
Object? audioSource = null,
|
||||||
@ -196,6 +199,10 @@ class _$UserPreferencesCopyWithImpl<$Res, $Val extends UserPreferences>
|
|||||||
? _value.downloadLocation
|
? _value.downloadLocation
|
||||||
: downloadLocation // ignore: cast_nullable_to_non_nullable
|
: downloadLocation // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
|
localLibraryLocation: null == localLibraryLocation
|
||||||
|
? _value.localLibraryLocation
|
||||||
|
: localLibraryLocation // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
pipedInstance: null == pipedInstance
|
pipedInstance: null == pipedInstance
|
||||||
? _value.pipedInstance
|
? _value.pipedInstance
|
||||||
: pipedInstance // ignore: cast_nullable_to_non_nullable
|
: pipedInstance // ignore: cast_nullable_to_non_nullable
|
||||||
@ -264,6 +271,7 @@ abstract class _$$UserPreferencesImplCopyWith<$Res>
|
|||||||
Market recommendationMarket,
|
Market recommendationMarket,
|
||||||
SearchMode searchMode,
|
SearchMode searchMode,
|
||||||
String downloadLocation,
|
String downloadLocation,
|
||||||
|
String localLibraryLocation,
|
||||||
String pipedInstance,
|
String pipedInstance,
|
||||||
ThemeMode themeMode,
|
ThemeMode themeMode,
|
||||||
AudioSource audioSource,
|
AudioSource audioSource,
|
||||||
@ -300,6 +308,7 @@ class __$$UserPreferencesImplCopyWithImpl<$Res>
|
|||||||
Object? recommendationMarket = null,
|
Object? recommendationMarket = null,
|
||||||
Object? searchMode = null,
|
Object? searchMode = null,
|
||||||
Object? downloadLocation = null,
|
Object? downloadLocation = null,
|
||||||
|
Object? localLibraryLocation = null,
|
||||||
Object? pipedInstance = null,
|
Object? pipedInstance = null,
|
||||||
Object? themeMode = null,
|
Object? themeMode = null,
|
||||||
Object? audioSource = null,
|
Object? audioSource = null,
|
||||||
@ -370,6 +379,10 @@ class __$$UserPreferencesImplCopyWithImpl<$Res>
|
|||||||
? _value.downloadLocation
|
? _value.downloadLocation
|
||||||
: downloadLocation // ignore: cast_nullable_to_non_nullable
|
: downloadLocation // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
|
localLibraryLocation: null == localLibraryLocation
|
||||||
|
? _value.localLibraryLocation
|
||||||
|
: localLibraryLocation // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
pipedInstance: null == pipedInstance
|
pipedInstance: null == pipedInstance
|
||||||
? _value.pipedInstance
|
? _value.pipedInstance
|
||||||
: pipedInstance // ignore: cast_nullable_to_non_nullable
|
: pipedInstance // ignore: cast_nullable_to_non_nullable
|
||||||
@ -433,6 +446,7 @@ class _$UserPreferencesImpl implements _UserPreferences {
|
|||||||
this.recommendationMarket = Market.US,
|
this.recommendationMarket = Market.US,
|
||||||
this.searchMode = SearchMode.youtube,
|
this.searchMode = SearchMode.youtube,
|
||||||
this.downloadLocation = "",
|
this.downloadLocation = "",
|
||||||
|
this.localLibraryLocation = "",
|
||||||
this.pipedInstance = "https://pipedapi.kavin.rocks",
|
this.pipedInstance = "https://pipedapi.kavin.rocks",
|
||||||
this.themeMode = ThemeMode.system,
|
this.themeMode = ThemeMode.system,
|
||||||
this.audioSource = AudioSource.youtube,
|
this.audioSource = AudioSource.youtube,
|
||||||
@ -498,6 +512,9 @@ class _$UserPreferencesImpl implements _UserPreferences {
|
|||||||
final String downloadLocation;
|
final String downloadLocation;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
|
final String localLibraryLocation;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
final String pipedInstance;
|
final String pipedInstance;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
@ -523,7 +540,7 @@ class _$UserPreferencesImpl implements _UserPreferences {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'UserPreferences(audioQuality: $audioQuality, albumColorSync: $albumColorSync, amoledDarkTheme: $amoledDarkTheme, checkUpdate: $checkUpdate, normalizeAudio: $normalizeAudio, showSystemTrayIcon: $showSystemTrayIcon, skipNonMusic: $skipNonMusic, systemTitleBar: $systemTitleBar, closeBehavior: $closeBehavior, accentColorScheme: $accentColorScheme, layoutMode: $layoutMode, locale: $locale, recommendationMarket: $recommendationMarket, searchMode: $searchMode, downloadLocation: $downloadLocation, pipedInstance: $pipedInstance, themeMode: $themeMode, audioSource: $audioSource, streamMusicCodec: $streamMusicCodec, downloadMusicCodec: $downloadMusicCodec, discordPresence: $discordPresence, endlessPlayback: $endlessPlayback, enableConnect: $enableConnect)';
|
return 'UserPreferences(audioQuality: $audioQuality, albumColorSync: $albumColorSync, amoledDarkTheme: $amoledDarkTheme, checkUpdate: $checkUpdate, normalizeAudio: $normalizeAudio, showSystemTrayIcon: $showSystemTrayIcon, skipNonMusic: $skipNonMusic, systemTitleBar: $systemTitleBar, closeBehavior: $closeBehavior, accentColorScheme: $accentColorScheme, layoutMode: $layoutMode, locale: $locale, recommendationMarket: $recommendationMarket, searchMode: $searchMode, downloadLocation: $downloadLocation, localLibraryLocation: $localLibraryLocation, pipedInstance: $pipedInstance, themeMode: $themeMode, audioSource: $audioSource, streamMusicCodec: $streamMusicCodec, downloadMusicCodec: $downloadMusicCodec, discordPresence: $discordPresence, endlessPlayback: $endlessPlayback, enableConnect: $enableConnect)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -560,6 +577,8 @@ class _$UserPreferencesImpl implements _UserPreferences {
|
|||||||
other.searchMode == searchMode) &&
|
other.searchMode == searchMode) &&
|
||||||
(identical(other.downloadLocation, downloadLocation) ||
|
(identical(other.downloadLocation, downloadLocation) ||
|
||||||
other.downloadLocation == downloadLocation) &&
|
other.downloadLocation == downloadLocation) &&
|
||||||
|
(identical(other.localLibraryLocation, localLibraryLocation) ||
|
||||||
|
other.localLibraryLocation == localLibraryLocation) &&
|
||||||
(identical(other.pipedInstance, pipedInstance) ||
|
(identical(other.pipedInstance, pipedInstance) ||
|
||||||
other.pipedInstance == pipedInstance) &&
|
other.pipedInstance == pipedInstance) &&
|
||||||
(identical(other.themeMode, themeMode) ||
|
(identical(other.themeMode, themeMode) ||
|
||||||
@ -597,6 +616,7 @@ class _$UserPreferencesImpl implements _UserPreferences {
|
|||||||
recommendationMarket,
|
recommendationMarket,
|
||||||
searchMode,
|
searchMode,
|
||||||
downloadLocation,
|
downloadLocation,
|
||||||
|
localLibraryLocation,
|
||||||
pipedInstance,
|
pipedInstance,
|
||||||
themeMode,
|
themeMode,
|
||||||
audioSource,
|
audioSource,
|
||||||
@ -647,6 +667,7 @@ abstract class _UserPreferences implements UserPreferences {
|
|||||||
final Market recommendationMarket,
|
final Market recommendationMarket,
|
||||||
final SearchMode searchMode,
|
final SearchMode searchMode,
|
||||||
final String downloadLocation,
|
final String downloadLocation,
|
||||||
|
final String localLibraryLocation,
|
||||||
final String pipedInstance,
|
final String pipedInstance,
|
||||||
final ThemeMode themeMode,
|
final ThemeMode themeMode,
|
||||||
final AudioSource audioSource,
|
final AudioSource audioSource,
|
||||||
@ -698,6 +719,8 @@ abstract class _UserPreferences implements UserPreferences {
|
|||||||
@override
|
@override
|
||||||
String get downloadLocation;
|
String get downloadLocation;
|
||||||
@override
|
@override
|
||||||
|
String get localLibraryLocation;
|
||||||
|
@override
|
||||||
String get pipedInstance;
|
String get pipedInstance;
|
||||||
@override
|
@override
|
||||||
ThemeMode get themeMode;
|
ThemeMode get themeMode;
|
||||||
|
|||||||
@ -44,6 +44,7 @@ _$UserPreferencesImpl _$$UserPreferencesImplFromJson(
|
|||||||
$enumDecodeNullable(_$SearchModeEnumMap, json['searchMode']) ??
|
$enumDecodeNullable(_$SearchModeEnumMap, json['searchMode']) ??
|
||||||
SearchMode.youtube,
|
SearchMode.youtube,
|
||||||
downloadLocation: json['downloadLocation'] as String? ?? "",
|
downloadLocation: json['downloadLocation'] as String? ?? "",
|
||||||
|
localLibraryLocation: json['localLibraryLocation'] as String? ?? "",
|
||||||
pipedInstance:
|
pipedInstance:
|
||||||
json['pipedInstance'] as String? ?? "https://pipedapi.kavin.rocks",
|
json['pipedInstance'] as String? ?? "https://pipedapi.kavin.rocks",
|
||||||
themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ??
|
themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ??
|
||||||
@ -81,6 +82,7 @@ Map<String, dynamic> _$$UserPreferencesImplToJson(
|
|||||||
'recommendationMarket': _$MarketEnumMap[instance.recommendationMarket]!,
|
'recommendationMarket': _$MarketEnumMap[instance.recommendationMarket]!,
|
||||||
'searchMode': _$SearchModeEnumMap[instance.searchMode]!,
|
'searchMode': _$SearchModeEnumMap[instance.searchMode]!,
|
||||||
'downloadLocation': instance.downloadLocation,
|
'downloadLocation': instance.downloadLocation,
|
||||||
|
'localLibraryLocation': instance.localLibraryLocation,
|
||||||
'pipedInstance': instance.pipedInstance,
|
'pipedInstance': instance.pipedInstance,
|
||||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||||
'audioSource': _$AudioSourceEnumMap[instance.audioSource]!,
|
'audioSource': _$AudioSourceEnumMap[instance.audioSource]!,
|
||||||
|
|||||||
@ -1 +1,89 @@
|
|||||||
{}
|
{
|
||||||
|
"ar": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"bn": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ca": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"cs": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"de": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"es": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"fa": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"fr": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"hi": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"it": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ja": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ko": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ne": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"nl": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pl": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pt": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ru": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"th": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"tr": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"uk": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"vi": [
|
||||||
|
"local_library_location"
|
||||||
|
],
|
||||||
|
|
||||||
|
"zh": [
|
||||||
|
"local_library_location"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user