Skip to content

Commit 8ca2115

Browse files
authored
feat: track caching and cached track export support (#2117)
* feat: add caching support with track metadata * feat(settings): add cache music toggle * fix(mobile): cache dir not open-able * feat(local folder): add cache export/clear actions and size of the folder * chore: ios deps upgrades * chore: upgrade lint flutter version * chore: lint secrets causing error * cd: invalid value for env var
1 parent 499ecfb commit 8ca2115

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+5223
-324
lines changed

.env.example

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# The format:
22
# SPOTIFY_SECRETS=clintId1:clientSecret1,clientId2:clientSecret2
3-
SPOTIFY_SECRETS=
3+
SPOTIFY_SECRETS=$SPOTIFY_SECRETS
44

55
# 0 or 1
66
# 0 = disable
77
# 1 = enable
8-
ENABLE_UPDATE_CHECK=
8+
ENABLE_UPDATE_CHECK=$ENABLE_UPDATE_CHECK
99

10-
LASTFM_API_KEY=
11-
LASTFM_API_SECRET=
10+
LASTFM_API_KEY=$LASTFM_API_KEY
11+
LASTFM_API_SECRET=$LASTFM_API_SECRET
1212

1313
# Release channel. Can be: nightly, stable
14-
RELEASE_CHANNEL=
14+
RELEASE_CHANNEL=$RELEASE_CHANNEL
1515

16-
HIDE_DONATIONS=
16+
HIDE_DONATIONS=$HIDE_DONATIONS

.github/workflows/pr-lint.yml

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
pull_request:
55

66
env:
7-
FLUTTER_VERSION: 3.22.2
7+
FLUTTER_VERSION: 3.24.5
88

99
jobs:
1010
lint:
@@ -17,18 +17,23 @@ jobs:
1717
with:
1818
flutter-version: ${{ env.FLUTTER_VERSION }}
1919

20+
- name: Dummy Envs
21+
run: |
22+
envsubst < .env.example > .env
23+
env:
24+
SPOTIFY_SECRETS: xxx:xxx
25+
ENABLE_UPDATE_CHECK: true
26+
LASTFM_API_KEY: xxx
27+
LASTFM_API_SECRET: xxx
28+
RELEASE_CHANNEL: nightly
29+
HIDE_DONATIONS: 0
30+
31+
2032
- name: Configure repo
2133
run: |
2234
flutter pub get
23-
echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
2435
dart run build_runner build --delete-conflicting-outputs
2536
2637
- name: Lint Dart files
2738
run: |
28-
dart analyze --no-fatal-warnings
29-
30-
- name: Lint translations & config files
31-
run: |
32-
npm install -g @prantlf/jsonlint
33-
jsonlint -q -D --enforce-double-quotes ./lib/l10n/*.arb
34-
jsonlint -q -D --enforce-double-quotes -T .vscode/*.json
39+
dart analyze --no-fatal-warnings

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,7 @@ apk:
4242
mv build/app/outputs/apk/release/app-release.apk build/Spotube-android-all-arch.apk
4343

4444
gensums:
45-
sh -c scripts/gensums.sh
45+
sh -c scripts/gensums.sh
46+
47+
migrate:
48+
dart run drift_dev make-migrations

analysis_options.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ analyzer:
3939
- "**.g.dart"
4040
- "**.gr.dart"
4141
- "**/generated_plugin_registrant.dart"
42+
- test/**/*.dart

drift_schemas/app_db/drift_schema_v3.json

+1
Large diffs are not rendered by default.

ios/Podfile.lock

+33-24
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ PODS:
5858
- flutter_inappwebview_ios/Core (0.0.1):
5959
- Flutter
6060
- OrderedSet (~> 6.0.3)
61-
- flutter_native_splash (0.0.1):
61+
- flutter_native_splash (2.4.3):
6262
- Flutter
6363
- flutter_secure_storage (6.0.0):
6464
- Flutter
@@ -74,6 +74,8 @@ PODS:
7474
- Flutter
7575
- metadata_god (0.0.1):
7676
- Flutter
77+
- open_file_ios (0.0.1):
78+
- Flutter
7779
- OrderedSet (6.0.3)
7880
- package_info_plus (0.4.5):
7981
- Flutter
@@ -88,21 +90,24 @@ PODS:
8890
- shared_preferences_foundation (0.0.1):
8991
- Flutter
9092
- FlutterMacOS
91-
- sqflite (0.0.3):
93+
- sqflite_darwin (0.0.4):
9294
- Flutter
9395
- FlutterMacOS
94-
- "sqlite3 (3.46.0+1)":
95-
- "sqlite3/common (= 3.46.0+1)"
96-
- "sqlite3/common (3.46.0+1)"
97-
- "sqlite3/fts5 (3.46.0+1)":
96+
- sqlite3 (3.47.1):
97+
- sqlite3/common (= 3.47.1)
98+
- sqlite3/common (3.47.1)
99+
- sqlite3/dbstatvtab (3.47.1):
100+
- sqlite3/common
101+
- sqlite3/fts5 (3.47.1):
98102
- sqlite3/common
99-
- "sqlite3/perf-threadsafe (3.46.0+1)":
103+
- sqlite3/perf-threadsafe (3.47.1):
100104
- sqlite3/common
101-
- "sqlite3/rtree (3.46.0+1)":
105+
- sqlite3/rtree (3.47.1):
102106
- sqlite3/common
103107
- sqlite3_flutter_libs (0.0.1):
104108
- Flutter
105-
- sqlite3 (~> 3.46.0)
109+
- sqlite3 (~> 3.47.0)
110+
- sqlite3/dbstatvtab
106111
- sqlite3/fts5
107112
- sqlite3/perf-threadsafe
108113
- sqlite3/rtree
@@ -130,11 +135,12 @@ DEPENDENCIES:
130135
- media_kit_libs_ios_audio (from `.symlinks/plugins/media_kit_libs_ios_audio/ios`)
131136
- media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
132137
- metadata_god (from `.symlinks/plugins/metadata_god/ios`)
138+
- open_file_ios (from `.symlinks/plugins/open_file_ios/ios`)
133139
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
134140
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
135141
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
136142
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
137-
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
143+
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
138144
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/ios`)
139145
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
140146

@@ -186,6 +192,8 @@ EXTERNAL SOURCES:
186192
:path: ".symlinks/plugins/media_kit_native_event_loop/ios"
187193
metadata_god:
188194
:path: ".symlinks/plugins/metadata_god/ios"
195+
open_file_ios:
196+
:path: ".symlinks/plugins/open_file_ios/ios"
189197
package_info_plus:
190198
:path: ".symlinks/plugins/package_info_plus/ios"
191199
path_provider_foundation:
@@ -194,8 +202,8 @@ EXTERNAL SOURCES:
194202
:path: ".symlinks/plugins/permission_handler_apple/ios"
195203
shared_preferences_foundation:
196204
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
197-
sqflite:
198-
:path: ".symlinks/plugins/sqflite/darwin"
205+
sqflite_darwin:
206+
:path: ".symlinks/plugins/sqflite_darwin/darwin"
199207
sqlite3_flutter_libs:
200208
:path: ".symlinks/plugins/sqlite3_flutter_libs/ios"
201209
url_launcher_ios:
@@ -206,35 +214,36 @@ SPEC CHECKSUMS:
206214
audio_service: f509d65da41b9521a61f1c404dd58651f265a567
207215
audio_session: 088d2483ebd1dc43f51d253d4a1c517d9a2e7207
208216
bonsoir_darwin: e3b8526c42ca46a885142df84229131dfabea842
209-
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
217+
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
210218
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
211219
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
212220
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
213-
file_selector_ios: 78baf21d03f1e37a7df97bb2494f9cd86de8fa5d
221+
file_selector_ios: f0670c1064a8c8450e38145d8043160105d0b97c
214222
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
215223
flutter_broadcasts: 3ece15b27d8ccbe2132c3df303e7c3401feab882
216224
flutter_discord_rpc: e1c342f29ceb9dd76cdc01db59a70c93bb4d9ec5
217225
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
218-
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
219-
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
226+
flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a
227+
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
220228
flutter_sharing_intent: e35380d0e1501d7111dbb7e46d5ac6339da6da98
221-
image_picker_ios: b545a5f16c0fa88e3ecbbce3ed4de45567a8ec18
229+
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
222230
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
223231
media_kit_libs_ios_audio: 8f39d96a9c630685dfb844c289bd1d114c486fb3
224232
media_kit_native_event_loop: 99111eded5acbdc9c2738021ea6550dd36ca8837
225233
metadata_god: 4bbd8523cdb5d42c5e59d2fabad01ff8f4bc53f9
234+
open_file_ios: 461db5853723763573e140de3193656f91990d9e
226235
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
227236
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
228-
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
237+
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
229238
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
230239
SDWebImage: a81bbb3ba4ea5f810f4069c68727cb118467a04a
231-
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
232-
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
233-
sqlite3: 292c3e1bfe89f64e51ea7fc7dab9182a017c8630
234-
sqlite3_flutter_libs: 0d611efdf6d1c9297d5ab03dab21b75aeebdae31
240+
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
241+
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
242+
sqlite3: 1e522f0938463e44b7faf50393b40bdc1e1e456d
243+
sqlite3_flutter_libs: b55ef23cfafea5318ae5081e0bf3fbbce8417c94
235244
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
236-
url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
245+
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
237246

238247
PODFILE CHECKSUM: 0659b64ac6e9e96b61d8550decffa8bff51a957e
239248

240-
COCOAPODS: 1.15.2
249+
COCOAPODS: 1.16.2

ios/Runner/AppDelegate.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import UIKit
22
import Flutter
33

4-
@UIApplicationMain
4+
@main
55
@objc class AppDelegate: FlutterAppDelegate {
66
override func application(
77
_ application: UIApplication,

lib/collections/assets.gen.dart

+11-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/collections/routes.dart

+6-3
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,12 @@ final routerProvider = Provider((ref) {
128128
pageBuilder: (context, state) {
129129
assert(state.extra is String);
130130
return SpotubePage(
131-
child: LocalLibraryPage(state.extra as String,
132-
isDownloads:
133-
state.uri.queryParameters["downloads"] != null),
131+
child: LocalLibraryPage(
132+
state.extra as String,
133+
isDownloads:
134+
state.uri.queryParameters["downloads"] != null,
135+
isCache: state.uri.queryParameters["cache"] != null,
136+
),
134137
);
135138
},
136139
),

lib/collections/spotube_icons.dart

+3
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,7 @@ abstract class SpotubeIcons {
124124
static const chart = FeatherIcons.barChart2;
125125
static const folderAdd = FeatherIcons.folderPlus;
126126
static const folderRemove = FeatherIcons.folderMinus;
127+
static const cache = FeatherIcons.hardDrive;
128+
static const export = Icons.file_open_outlined;
129+
static const delete = FeatherIcons.trash2;
127130
}

lib/extensions/track.dart

+28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:io';
2+
import 'dart:typed_data';
23

34
import 'package:metadata_god/metadata_god.dart';
45
import 'package:path/path.dart';
@@ -37,6 +38,33 @@ extension TrackExtensions on Track {
3738

3839
return this;
3940
}
41+
42+
Metadata toMetadata({
43+
required int fileLength,
44+
Uint8List? imageBytes,
45+
}) {
46+
return Metadata(
47+
title: name,
48+
artist: artists?.map((a) => a.name).join(", "),
49+
album: album?.name,
50+
albumArtist: artists?.map((a) => a.name).join(", "),
51+
year: album?.releaseDate != null
52+
? int.tryParse(album!.releaseDate!.split("-").first) ?? 1969
53+
: 1969,
54+
trackNumber: trackNumber,
55+
discNumber: discNumber,
56+
durationMs: durationMs?.toDouble() ?? 0.0,
57+
fileSize: BigInt.from(fileLength),
58+
trackTotal: album?.tracks?.length ?? 0,
59+
picture: imageBytes != null
60+
? Picture(
61+
data: imageBytes,
62+
// Spotify images are always JPEGs
63+
mimeType: 'image/jpeg',
64+
)
65+
: null,
66+
);
67+
}
4068
}
4169

4270
extension TrackSimpleExtensions on TrackSimple {

lib/hooks/utils/use_custom_status_bar_color.dart

+16-9
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@ import 'package:flutter/material.dart';
22
import 'package:flutter/services.dart';
33
import 'package:flutter_hooks/flutter_hooks.dart';
44

5-
void useCustomStatusBarColor(
5+
VoidCallback useCustomStatusBarColor(
66
Color color,
77
bool isCurrentRoute, {
88
bool noSetBGColor = false,
99
bool? automaticSystemUiAdjustment,
1010
}) {
1111
final context = useContext();
1212
final backgroundColor = Theme.of(context).scaffoldBackgroundColor;
13-
resetStatusbar() => SystemChrome.setSystemUIOverlayStyle(
14-
SystemUiOverlayStyle(
15-
statusBarColor: backgroundColor, // status bar color
16-
statusBarIconBrightness: backgroundColor.computeLuminance() > 0.179
17-
? Brightness.dark
18-
: Brightness.light,
19-
),
20-
);
13+
// ignore: invalid_use_of_visible_for_testing_member
14+
final previousState = SystemChrome.latestStyle;
15+
16+
void resetStatusbar() => previousState != null
17+
? SystemChrome.setSystemUIOverlayStyle(previousState)
18+
: SystemChrome.setSystemUIOverlayStyle(
19+
SystemUiOverlayStyle(
20+
statusBarColor: backgroundColor, // status bar color
21+
statusBarIconBrightness: backgroundColor.computeLuminance() > 0.179
22+
? Brightness.dark
23+
: Brightness.light,
24+
),
25+
);
2126

2227
// ignore: invalid_use_of_visible_for_testing_member
2328
final statusBarColor = SystemChrome.latestStyle?.statusBarColor;
@@ -54,4 +59,6 @@ void useCustomStatusBarColor(
5459
useEffect(() {
5560
return resetStatusbar;
5661
}, []);
62+
63+
return resetStatusbar;
5764
}

lib/l10n/app_en.arb

+11-1
Original file line numberDiff line numberDiff line change
@@ -391,5 +391,15 @@
391391
"total_money": "Total {money}",
392392
"webview_not_found": "Webview not found",
393393
"webview_not_found_description": "No webview runtime is installed in your device.\nIf it's installed make sure it's in the Environment PATH\n\nAfter installing, restart the app",
394-
"unsupported_platform": "Unsupported platform"
394+
"unsupported_platform": "Unsupported platform",
395+
"cache_music": "Cache music",
396+
"open": "Open",
397+
"cache_folder": "Cache folder",
398+
"export": "Export",
399+
"clear_cache": "Clear cache",
400+
"clear_cache_confirmation": "Do you want to clear the cache?",
401+
"export_cache_files": "Export Cached Files",
402+
"found_n_files": "Found {count} files",
403+
"export_cache_confirmation": "Do you want to export these files to",
404+
"exported_n_out_of_m_files": "Exported {filesExported} out of {files} files"
395405
}

0 commit comments

Comments
 (0)