diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..5630304
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,25 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "spotify_downloader",
+ "request": "launch",
+ "type": "dart"
+ },
+ {
+ "name": "spotify_downloader (profile mode)",
+ "request": "launch",
+ "type": "dart",
+ "flutterMode": "profile"
+ },
+ {
+ "name": "spotify_downloader (release mode)",
+ "request": "launch",
+ "type": "dart",
+ "flutterMode": "release"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index e7cc6bd..6e43984 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -31,7 +31,9 @@
-
+
+
@@ -42,5 +44,5 @@
-
+
\ No newline at end of file
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 9625e10..40865d8 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -7,20 +7,20 @@
CFBundleExecutable
App
CFBundleIdentifier
- io.flutter.flutter.app
+ com.cdev.spotify_downloader
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- App
+ SpotifyDownloader
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 1.0
+ 1.1
CFBundleSignature
????
CFBundleVersion
- 1.0
+ 1.1
MinimumOSVersion
- 11.0
+ 12.1
diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig
index 592ceee..ec97fc6 100644
--- a/ios/Flutter/Debug.xcconfig
+++ b/ios/Flutter/Debug.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig
index 592ceee..c4855bf 100644
--- a/ios/Flutter/Release.xcconfig
+++ b/ios/Flutter/Release.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 0000000..67acc87
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,52 @@
+# Uncomment this line to define a global platform for your project
+platform :ios, '12.1'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+ target 'RunnerTests' do
+ inherit! :search_paths
+ end
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ target.build_configurations.each do |config|
+ config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
+ '$(inherited)',
+ ## dart: PermissionGroup.notification
+ 'PERMISSION_NOTIFICATIONS=1'
+ ]
+
+ end
+ end
+end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
new file mode 100644
index 0000000..3370bdd
--- /dev/null
+++ b/ios/Podfile.lock
@@ -0,0 +1,170 @@
+PODS:
+ - awesome_notifications (0.8.1):
+ - Flutter
+ - IosAwnCore (~> 0.8.0)
+ - awesome_notifications_core (0.0.1):
+ - Flutter
+ - connectivity_plus (0.0.1):
+ - Flutter
+ - ReachabilitySwift
+ - device_info_plus (0.0.1):
+ - Flutter
+ - DKImagePickerController/Core (4.3.9):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.9)
+ - DKImagePickerController/PhotoGallery (4.3.9):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.9)
+ - DKPhotoGallery (0.0.19):
+ - DKPhotoGallery/Core (= 0.0.19)
+ - DKPhotoGallery/Model (= 0.0.19)
+ - DKPhotoGallery/Preview (= 0.0.19)
+ - DKPhotoGallery/Resource (= 0.0.19)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - ffmpeg-kit-ios-full (6.0)
+ - ffmpeg_kit_flutter_full (6.0.3):
+ - ffmpeg_kit_flutter_full/full (= 6.0.3)
+ - Flutter
+ - ffmpeg_kit_flutter_full/full (6.0.3):
+ - ffmpeg-kit-ios-full (= 6.0)
+ - Flutter
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
+ - Flutter (1.0.0)
+ - flutter_secure_storage (6.0.0):
+ - Flutter
+ - flutter_web_auth_2 (1.1.1):
+ - Flutter
+ - FMDB (2.7.12):
+ - FMDB/standard (= 2.7.12)
+ - FMDB/Core (2.7.12)
+ - FMDB/standard (2.7.12):
+ - FMDB/Core
+ - IosAwnCore (0.8.0)
+ - metadata_god (0.0.1)
+ - package_info_plus (0.4.5):
+ - Flutter
+ - path_provider_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - permission_handler_apple (9.1.1):
+ - Flutter
+ - ReachabilitySwift (5.2.3)
+ - SDWebImage (5.19.4):
+ - SDWebImage/Core (= 5.19.4)
+ - SDWebImage/Core (5.19.4)
+ - sqflite (0.0.3):
+ - Flutter
+ - FMDB (>= 2.7.5)
+ - SwiftyGif (5.4.5)
+ - url_launcher_ios (0.0.1):
+ - Flutter
+
+DEPENDENCIES:
+ - awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`)
+ - awesome_notifications_core (from `.symlinks/plugins/awesome_notifications_core/ios`)
+ - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
+ - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
+ - ffmpeg_kit_flutter_full (from `.symlinks/plugins/ffmpeg_kit_flutter_full/ios`)
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
+ - Flutter (from `Flutter`)
+ - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
+ - flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
+ - metadata_god (from `.symlinks/plugins/metadata_god/ios`)
+ - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
+ - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
+ - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
+ - sqflite (from `.symlinks/plugins/sqflite/ios`)
+ - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+
+SPEC REPOS:
+ trunk:
+ - DKImagePickerController
+ - DKPhotoGallery
+ - ffmpeg-kit-ios-full
+ - FMDB
+ - IosAwnCore
+ - ReachabilitySwift
+ - SDWebImage
+ - SwiftyGif
+
+EXTERNAL SOURCES:
+ awesome_notifications:
+ :path: ".symlinks/plugins/awesome_notifications/ios"
+ awesome_notifications_core:
+ :path: ".symlinks/plugins/awesome_notifications_core/ios"
+ connectivity_plus:
+ :path: ".symlinks/plugins/connectivity_plus/ios"
+ device_info_plus:
+ :path: ".symlinks/plugins/device_info_plus/ios"
+ ffmpeg_kit_flutter_full:
+ :path: ".symlinks/plugins/ffmpeg_kit_flutter_full/ios"
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
+ Flutter:
+ :path: Flutter
+ flutter_secure_storage:
+ :path: ".symlinks/plugins/flutter_secure_storage/ios"
+ flutter_web_auth_2:
+ :path: ".symlinks/plugins/flutter_web_auth_2/ios"
+ metadata_god:
+ :path: ".symlinks/plugins/metadata_god/ios"
+ package_info_plus:
+ :path: ".symlinks/plugins/package_info_plus/ios"
+ path_provider_foundation:
+ :path: ".symlinks/plugins/path_provider_foundation/darwin"
+ permission_handler_apple:
+ :path: ".symlinks/plugins/permission_handler_apple/ios"
+ sqflite:
+ :path: ".symlinks/plugins/sqflite/ios"
+ url_launcher_ios:
+ :path: ".symlinks/plugins/url_launcher_ios/ios"
+
+SPEC CHECKSUMS:
+ awesome_notifications: db394d2e061e4583ba0f738ddea611e3986cc3fb
+ awesome_notifications_core: d02eed89738fa362d56cbd372850e9adcd2c6bef
+ connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
+ device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
+ DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
+ DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
+ ffmpeg-kit-ios-full: 0099a769d22114dde52cdc238397941c32f75d27
+ ffmpeg_kit_flutter_full: a2ad4ff5b14b7c040724edc8cd3bc293dd2d6d0f
+ file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
+ flutter_web_auth_2: a1bc00762c408a8f80b72a538cd7ff5b601c3e71
+ FMDB: 728731dd336af3936ce00f91d9d8495f5718a0e6
+ IosAwnCore: ed1b2b6d84962a758354dbacd9ce525c72ce28a9
+ metadata_god: eceae399d0020475069a5cebc35943ce8562b5d7
+ package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
+ path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+ permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
+ ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979
+ SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d
+ sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
+ SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
+ url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
+
+PODFILE CHECKSUM: 0408ca912856f5c3bf2bbf0787ea424d56bdf0ba
+
+COCOAPODS: 1.15.2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index e525f8b..b4032db 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -8,12 +8,14 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
- 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
+ CB21622087150A2FA00D37AE /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5ED311D801CE27AADAFA128B /* Pods_RunnerTests.framework */; };
+ E89C833A3B812247E594C220 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59471FCDE392A2A0309D73C1 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -42,10 +44,17 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 20C59286EA4762C02DB57A1E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
+ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 4EB9B775D7857652376C1E6A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ 59471FCDE392A2A0309D73C1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 5ED311D801CE27AADAFA128B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 8558344DC919A2A0C415CDCF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -53,21 +62,48 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
- 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9C4E5D531FB3ED6BE5231A73 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; };
+ A79BEB4CA35971A6DF43A9AB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ BAAF9E8CA93412EEA29D2F87 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 46909502815090D3923AAEB3 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CB21622087150A2FA00D37AE /* Pods_RunnerTests.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ E89C833A3B812247E594C220 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 331C8082294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXGroup;
+ children = (
+ 331C807B294A618700263BE5 /* RunnerTests.swift */,
+ );
+ path = RunnerTests;
+ sourceTree = "";
+ };
+ 69034FF875A06767DDD3CF51 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 59471FCDE392A2A0309D73C1 /* Pods_Runner.framework */,
+ 5ED311D801CE27AADAFA128B /* Pods_RunnerTests.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@@ -79,14 +115,6 @@
name = Flutter;
sourceTree = "";
};
- 331C8082294A63A400263BE5 /* RunnerTests */ = {
- isa = PBXGroup;
- children = (
- 331C807B294A618700263BE5 /* RunnerTests.swift */,
- );
- path = RunnerTests;
- sourceTree = "";
- };
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
@@ -94,6 +122,8 @@
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
+ FF95FEEADB0FA0338B8FBDEE /* Pods */,
+ 69034FF875A06767DDD3CF51 /* Frameworks */,
);
sourceTree = "";
};
@@ -121,6 +151,20 @@
path = Runner;
sourceTree = "";
};
+ FF95FEEADB0FA0338B8FBDEE /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ A79BEB4CA35971A6DF43A9AB /* Pods-Runner.debug.xcconfig */,
+ 8558344DC919A2A0C415CDCF /* Pods-Runner.release.xcconfig */,
+ 4EB9B775D7857652376C1E6A /* Pods-Runner.profile.xcconfig */,
+ 9C4E5D531FB3ED6BE5231A73 /* Pods-RunnerTests.debug.xcconfig */,
+ BAAF9E8CA93412EEA29D2F87 /* Pods-RunnerTests.release.xcconfig */,
+ 20C59286EA4762C02DB57A1E /* Pods-RunnerTests.profile.xcconfig */,
+ );
+ name = Pods;
+ path = Pods;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -128,9 +172,10 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
+ 8658F95204F4814210808BE7 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
- 331C807E294A63A400263BE5 /* Frameworks */,
331C807F294A63A400263BE5 /* Resources */,
+ 46909502815090D3923AAEB3 /* Frameworks */,
);
buildRules = (
);
@@ -146,12 +191,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
+ 3FA7C55A76915ACAA579E096 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ 903762ECFB7D4C8381C74D5B /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -169,7 +216,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
@@ -239,10 +286,71 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
+ 3FA7C55A76915ACAA579E096 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 8658F95204F4814210808BE7 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 903762ECFB7D4C8381C74D5B /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
- buildActionMask = 2147483647;
+ buildActionMask = 12;
files = (
);
inputPaths = (
@@ -252,7 +360,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -345,7 +453,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -361,13 +469,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 642R69GYA2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.example.spotifyDownloader;
+ PRODUCT_BUNDLE_IDENTIFIER = com.c0dev.spotifyDownloader;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -377,7 +486,7 @@
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */;
+ baseConfigurationReference = 9C4E5D531FB3ED6BE5231A73 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
@@ -395,7 +504,7 @@
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */;
+ baseConfigurationReference = BAAF9E8CA93412EEA29D2F87 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
@@ -411,7 +520,7 @@
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */;
+ baseConfigurationReference = 20C59286EA4762C02DB57A1E /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
@@ -472,7 +581,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -521,7 +630,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -539,13 +648,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 642R69GYA2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.example.spotifyDownloader;
+ PRODUCT_BUNDLE_IDENTIFIER = com.c0dev.spotifyDownloader;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -561,13 +671,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 642R69GYA2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.example.spotifyDownloader;
+ PRODUCT_BUNDLE_IDENTIFIER = com.c0dev.spotifyDownloader;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 87131a0..8e3ca5d 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+
+
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
index d36b1fa..c03b426 100644
--- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,122 +1,14 @@
{
"images" : [
{
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "Icon-App-20x20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "Icon-App-20x20@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "Icon-App-40x40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "Icon-App-40x40@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "Icon-App-60x60@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "Icon-App-60x60@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "Icon-App-20x20@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "Icon-App-20x20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "Icon-App-29x29@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "Icon-App-29x29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "Icon-App-40x40@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "Icon-App-40x40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-App-76x76@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-App-76x76@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "83.5x83.5",
- "idiom" : "ipad",
- "filename" : "Icon-App-83.5x83.5@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "1024x1024",
- "idiom" : "ios-marketing",
- "filename" : "Icon-App-1024x1024@1x.png",
- "scale" : "1x"
+ "filename" : "sd_iconpsd.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
}
],
"info" : {
- "version" : 1,
- "author" : "xcode"
+ "author" : "xcode",
+ "version" : 1
}
}
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
deleted file mode 100644
index dc9ada4..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
deleted file mode 100644
index 7353c41..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
deleted file mode 100644
index 797d452..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
deleted file mode 100644
index 6ed2d93..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
deleted file mode 100644
index 4cd7b00..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
deleted file mode 100644
index fe73094..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
deleted file mode 100644
index 321773c..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
deleted file mode 100644
index 797d452..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
deleted file mode 100644
index 502f463..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
deleted file mode 100644
index 0ec3034..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
deleted file mode 100644
index 0ec3034..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
deleted file mode 100644
index e9f5fea..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
deleted file mode 100644
index 84ac32a..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
deleted file mode 100644
index 8953cba..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
deleted file mode 100644
index 0467bf1..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/sd_iconpsd.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/sd_iconpsd.png
new file mode 100644
index 0000000..a668a2a
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/sd_iconpsd.png differ
diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard
index f3c2851..7232e3b 100644
--- a/ios/Runner/Base.lproj/Main.storyboard
+++ b/ios/Runner/Base.lproj/Main.storyboard
@@ -1,8 +1,10 @@
-
-
+
+
+
-
+
+
@@ -14,13 +16,14 @@
-
+
-
+
+
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 9f28833..d4bede4 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -1,51 +1,67 @@
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- Spotify Downloader
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- spotify_downloader
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
- UIStatusBarHidden
-
-
+
+ CADisableMinimumFrameDurationOnPhone
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Spotify Downloader
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ spotify_downloader
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIStatusBarHidden
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIBackgroundModes
+
+ processing
+ fetch
+ remote-notification
+
+ NSDocumentsFolderUsageDescription
+ For downloaded tracks saving
+ UISupportsDocumentBrowser
+
+ UIFileSharingEnabled
+
+ LSSupportsOpeningDocumentsInPlace
+
+ PermissionGroupNotification
+ For tracks loading notificatins
+ UIApplicationSupportsIndirectInputEvents
+
+
diff --git a/lib/core/app/colors/colors.dart b/lib/core/app/colors/colors.dart
index 2b2c2c4..69c5239 100644
--- a/lib/core/app/colors/colors.dart
+++ b/lib/core/app/colors/colors.dart
@@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
const backgroundColor = Color.fromARGB(255, 18, 18, 18);
const onBackgroundPrimaryColor = Color.fromARGB(255, 255, 255, 255);
-const onBackgroundSecondaryColor = Color.fromARGB(255, 188, 188, 188);
+const onBackgroundSecondaryColor = Color.fromARGB(255, 153, 153, 153);
const onBackgroundThirdRateColor = Color.fromARGB(255, 110, 110, 110);
-const surfaceColor = Color.fromARGB(255, 42, 42, 42);
+const surfaceColor = Color.fromARGB(255, 36, 36, 36);
const onSurfacePrimaryColor = Color.fromARGB(255, 255, 255, 255);
const onSurfaceSecondaryColor = Color.fromARGB(255, 153, 153, 153);
const onSurfaceSplashColor = Color.fromARGB(60, 153, 153, 153);
@@ -18,8 +18,10 @@ const onPrimaryColor = Color.fromARGB(255, 18, 18, 18);
const errorPrimaryColor = Color.fromARGB(255, 255, 102, 91);
const searchFieldColor = Color.fromARGB(255, 255, 255, 255);
-const onSearchFieldColor = Color.fromARGB(255, 99, 99, 99);
+const searchFieldHintColor = Color.fromARGB(255, 59, 59, 59);
const dialogColor = Color.fromARGB(255, 59, 59, 59);
-const tilePlaceholderColor = Color.fromARGB(255, 59, 59, 59);
\ No newline at end of file
+const tilePlaceholderColor = Color.fromARGB(255, 59, 59, 59);
+
+const horizontalNavigationBarColor = Color.fromARGB(255, 30, 30, 30);
diff --git a/lib/core/app/router/router.dart b/lib/core/app/router/router.dart
index 6dbdc23..e4e6d22 100644
--- a/lib/core/app/router/router.dart
+++ b/lib/core/app/router/router.dart
@@ -1,30 +1,57 @@
import 'package:auto_route/auto_route.dart';
-import 'package:flutter/foundation.dart';
-import 'package:spotify_downloader/features/domain/tracks/shared/entities/track.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/history_tracks_collectons/entities/history_tracks_collection.dart';
+import 'package:flutter/material.dart';
+import 'package:spotify_downloader/core/app/themes/themes.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/shared/domain/entities/track.dart';
+import 'package:spotify_downloader/features/data_domain/tracks_collections/history_tracks_collections/domain/entities/history_tracks_collection.dart';
import 'package:spotify_downloader/features/presentation/about_app/view/about_app_screen.dart';
import 'package:spotify_downloader/features/presentation/change_source_video/view/change_source_video_screen.dart';
import 'package:spotify_downloader/features/presentation/history/view/history_screen.dart';
import 'package:spotify_downloader/features/presentation/home/view/home_screen.dart';
import 'package:spotify_downloader/features/presentation/main/view/main_screen.dart';
import 'package:spotify_downloader/features/presentation/download_tracks_collection/view/download_tracks_collection_screen.dart';
+import 'package:spotify_downloader/features/presentation/packages_info/view/packages_info_screen.dart';
import 'package:spotify_downloader/features/presentation/settings/view/settings_screen.dart';
-part 'router.gr.dart';
-
-@AutoRouterConfig()
-class AppRouter extends _$AppRouter {
-
- @override
+part 'router.gr.dart';
+
+@AutoRouterConfig()
+class AppRouter extends _$AppRouter {
+ @override
List get routes => [
- AutoRoute(page: MainRoute.page, path: '/', children: [
- AutoRoute(page: HomeRoute.page, path: 'home'),
- AutoRoute(page: HistoryRoute.page, path: 'history'),
- ]),
- AutoRoute(page: DownloadTracksCollectionRouteWithHistoryTracksCollection.page),
- AutoRoute(page: DownloadTracksCollectionRouteWithUrl.page),
- AutoRoute(page: ChangeSourceVideoRoute.page),
- AutoRoute(page: SettingsRoute.page),
- AutoRoute(page: AboutAppRoute.page)
- ];
- }
\ No newline at end of file
+ AutoRoute(page: MainRoute.page, path: '/', children: [
+ RedirectRoute(path: '', redirectTo: 'home'),
+ CustomRoute(
+ page: HomeRoute.page,
+ path: 'home',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: HistoryRoute.page,
+ path: 'history',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: DownloadTracksCollectionRouteWithHistoryTracksCollection.page,
+ path: 'downloadTracksCollectionFromHistory',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: DownloadTracksCollectionRouteWithUrl.page,
+ path: 'downloadTracksCollectionFromUrl',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: ChangeSourceVideoRoute.page,
+ path: 'changeSourceVideo',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: SettingsRoute.page,
+ path: 'settings',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: AboutAppRoute.page,
+ path: 'about',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground),
+ CustomRoute(
+ page: PackagesInfoRoute.page,
+ path: 'packages_info',
+ transitionsBuilder: TransitionsBuildersExtension.fadeInWithBackground)
+ ]),
+ ];
+}
diff --git a/lib/core/app/router/router.gr.dart b/lib/core/app/router/router.gr.dart
index c60f571..f9be667 100644
--- a/lib/core/app/router/router.gr.dart
+++ b/lib/core/app/router/router.gr.dart
@@ -28,6 +28,7 @@ abstract class _$AppRouter extends RootStackRouter {
child: ChangeSourceVideoScreen(
key: args.key,
track: args.track,
+ oldYoutubeUrl: args.oldYoutubeUrl,
),
);
},
@@ -70,6 +71,12 @@ abstract class _$AppRouter extends RootStackRouter {
child: const MainScreen(),
);
},
+ PackagesInfoRoute.name: (routeData) {
+ return AutoRoutePage(
+ routeData: routeData,
+ child: const PackagesInfoScreen(),
+ );
+ },
SettingsRoute.name: (routeData) {
return AutoRoutePage(
routeData: routeData,
@@ -99,12 +106,14 @@ class ChangeSourceVideoRoute extends PageRouteInfo {
ChangeSourceVideoRoute({
Key? key,
required Track track,
+ String? oldYoutubeUrl,
List? children,
}) : super(
ChangeSourceVideoRoute.name,
args: ChangeSourceVideoRouteArgs(
key: key,
track: track,
+ oldYoutubeUrl: oldYoutubeUrl,
),
initialChildren: children,
);
@@ -119,15 +128,18 @@ class ChangeSourceVideoRouteArgs {
const ChangeSourceVideoRouteArgs({
this.key,
required this.track,
+ this.oldYoutubeUrl,
});
final Key? key;
final Track track;
+ final String? oldYoutubeUrl;
+
@override
String toString() {
- return 'ChangeSourceVideoRouteArgs{key: $key, track: $track}';
+ return 'ChangeSourceVideoRouteArgs{key: $key, track: $track, oldYoutubeUrl: $oldYoutubeUrl}';
}
}
@@ -255,6 +267,20 @@ class MainRoute extends PageRouteInfo {
static const PageInfo page = PageInfo(name);
}
+/// generated route for
+/// [PackagesInfoScreen]
+class PackagesInfoRoute extends PageRouteInfo {
+ const PackagesInfoRoute({List? children})
+ : super(
+ PackagesInfoRoute.name,
+ initialChildren: children,
+ );
+
+ static const String name = 'PackagesInfoRoute';
+
+ static const PageInfo page = PageInfo(name);
+}
+
/// generated route for
/// [SettingsScreen]
class SettingsRoute extends PageRouteInfo {
diff --git a/lib/core/app/spotify_downloader_app.dart b/lib/core/app/spotify_downloader_app.dart
index 60a1e4b..ad3e59e 100644
--- a/lib/core/app/spotify_downloader_app.dart
+++ b/lib/core/app/spotify_downloader_app.dart
@@ -1,14 +1,17 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:package_info_plus/package_info_plus.dart';
import 'package:spotify_downloader/core/app/router/router.dart';
import 'package:spotify_downloader/core/app/themes/themes.dart';
+import 'package:spotify_downloader/core/package_info/package_info_accessor.dart';
import 'package:spotify_downloader/generated/l10n.dart';
class SpotifyDownloaderApp extends StatefulWidget {
- const SpotifyDownloaderApp({super.key, required this.locale});
+ const SpotifyDownloaderApp({super.key, this.locale, required this.packageInfo});
- final String locale;
+ final String? locale;
+ final PackageInfo packageInfo;
static void setLanguage(BuildContext context, String newLanguage) async {
final state = context.findAncestorStateOfType<_SpotifyDownloaderAppState>();
@@ -25,8 +28,12 @@ class _SpotifyDownloaderAppState extends State {
@override
void initState() {
- _language = widget.locale;
super.initState();
+
+ if (widget.locale != null) {
+ _language = widget.locale!;
+ }
+ initTheme();
}
@override
@@ -42,6 +49,11 @@ class _SpotifyDownloaderAppState extends State {
supportedLocales: S.delegate.supportedLocales,
routerConfig: _appRouter.config(navigatorObservers: () => [AutoRouteObserver()]),
theme: mainTheme,
+ builder: (context, child) {
+ return ScrollConfiguration(
+ behavior: const ClampingScrollPhysicsBehavior().copyWith(overscroll: false),
+ child: PackageInfoAccessor(packageInfo: widget.packageInfo, child: child!));
+ },
);
}
diff --git a/lib/core/app/themes/text_themes.dart b/lib/core/app/themes/text_themes.dart
index fe06b84..e1d528c 100644
--- a/lib/core/app/themes/text_themes.dart
+++ b/lib/core/app/themes/text_themes.dart
@@ -55,3 +55,10 @@ const _labelMedium = TextStyle(
color: onBackgroundPrimaryColor,
fontSize: 12,
overflow: TextOverflow.ellipsis);
+
+const _labelSmall = TextStyle(
+ fontFamily: 'OpenSans',
+ fontWeight: FontWeight.w400,
+ color: onBackgroundPrimaryColor,
+ fontSize: 10,
+ overflow: TextOverflow.ellipsis);
diff --git a/lib/core/app/themes/theme_consts.dart b/lib/core/app/themes/theme_consts.dart
index c9dca85..ea09ffc 100644
--- a/lib/core/app/themes/theme_consts.dart
+++ b/lib/core/app/themes/theme_consts.dart
@@ -1 +1,7 @@
-const double bottomNavigationBarHeight = 50;
\ No newline at end of file
+import 'package:flutter/material.dart';
+
+const backIconSize = 25.0;
+const horizontalPadding = 15.0;
+const appBarHeight = 55.0;
+const screenWithCustomAppBarPadding = EdgeInsets.only(left: horizontalPadding, right: horizontalPadding, top: 10);
+const tappingAnimationDuration = Duration(milliseconds: 50);
\ No newline at end of file
diff --git a/lib/core/app/themes/themes.dart b/lib/core/app/themes/themes.dart
index a31da12..b5a92fd 100644
--- a/lib/core/app/themes/themes.dart
+++ b/lib/core/app/themes/themes.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
import 'package:spotify_downloader/core/app/colors/colors.dart';
part 'text_themes.dart';
@@ -7,33 +8,35 @@ final mainTheme = ThemeData(
cardTheme: const CardTheme(color: surfaceColor),
scrollbarTheme: ScrollbarThemeData(
interactive: true,
- thumbVisibility: const MaterialStatePropertyAll(true),
+ thumbVisibility: const WidgetStatePropertyAll(true),
radius: const Radius.circular(10),
crossAxisMargin: 5,
- thumbColor: MaterialStateProperty.resolveWith((states) {
- if (states.contains(MaterialState.dragged)) {
+ mainAxisMargin: 5,
+ thumbColor: WidgetStateProperty.resolveWith((states) {
+ if (states.contains(WidgetState.dragged)) {
return primaryColor;
} else {
return onBackgroundSecondaryColor;
}
})),
+ progressIndicatorTheme: const ProgressIndicatorThemeData(color: primaryColor),
switchTheme: SwitchThemeData(
- trackColor: MaterialStateProperty.resolveWith((states) {
- if (!states.contains(MaterialState.selected)) {
+ trackColor: WidgetStateProperty.resolveWith((states) {
+ if (!states.contains(WidgetState.selected)) {
return onBackgroundSecondaryColor;
} else {
return null;
}
}),
- thumbColor: MaterialStateProperty.resolveWith((states) {
- if (!states.contains(MaterialState.selected)) {
+ thumbColor: WidgetStateProperty.resolveWith((states) {
+ if (!states.contains(WidgetState.selected)) {
return onBackgroundThirdRateColor;
} else {
return null;
}
}),
- trackOutlineColor: MaterialStateProperty.resolveWith((states) {
- if (!states.contains(MaterialState.selected)) {
+ trackOutlineColor: WidgetStateProperty.resolveWith((states) {
+ if (!states.contains(WidgetState.selected)) {
return onBackgroundThirdRateColor;
} else {
return Colors.transparent;
@@ -58,9 +61,9 @@ final mainTheme = ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: primaryColor),
elevatedButtonTheme: const ElevatedButtonThemeData(
style: ButtonStyle(
- backgroundColor: MaterialStatePropertyAll(primaryColor),
- textStyle: MaterialStatePropertyAll(TextStyle()),
- foregroundColor: MaterialStatePropertyAll(onPrimaryColor))),
+ backgroundColor: WidgetStatePropertyAll(primaryColor),
+ textStyle: WidgetStatePropertyAll(TextStyle()),
+ foregroundColor: WidgetStatePropertyAll(onPrimaryColor))),
textTheme: const TextTheme(
titleLarge: _titleLarge,
titleMedium: _titleMedium,
@@ -69,13 +72,23 @@ final mainTheme = ThemeData(
bodyMedium: _bodyMedium,
bodySmall: _bodySmall,
labelLarge: _labelLarge,
- labelMedium: _labelMedium),
+ labelMedium: _labelMedium,
+ labelSmall: _labelSmall),
textSelectionTheme: const TextSelectionThemeData(
cursorColor: primaryColor,
selectionHandleColor: primaryColor,
),
);
+void initTheme() {
+ SystemChrome.setSystemUIOverlayStyle(
+ SystemUiOverlayStyle.light.copyWith(
+ statusBarColor: Colors.transparent,
+ systemNavigationBarColor: Colors.transparent,
+ ),
+ );
+}
+
void showBigTextSnackBar(String message, BuildContext context, [Duration duration = const Duration(seconds: 2)]) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Column(
@@ -106,3 +119,29 @@ void showSmallTextSnackBar(String message, BuildContext context, [Duration durat
duration: duration,
));
}
+
+class TransitionsBuildersExtension {
+ static const fadeInWithBackground = _fadeInWithBackground;
+
+ static Widget _fadeInWithBackground(
+ BuildContext context, Animation animation, Animation secondaryAnimation, Widget child) {
+ if (animation.status == AnimationStatus.reverse) {
+ return FadeTransition(
+ opacity: animation, child: Container(constraints: const BoxConstraints.expand(), color: backgroundColor));
+ } else {
+ return Container(
+ constraints: const BoxConstraints.expand(),
+ color: backgroundColor,
+ child: FadeTransition(opacity: animation, child: child),
+ );
+ }
+ }
+}
+
+class ClampingScrollPhysicsBehavior extends ScrollBehavior {
+ const ClampingScrollPhysicsBehavior();
+ @override
+ ScrollPhysics getScrollPhysics(BuildContext context) {
+ return const ClampingScrollPhysics();
+ }
+}
diff --git a/lib/core/db/local_db_impl.dart b/lib/core/db/local_db_impl.dart
index ffca4c9..cbc2e39 100644
--- a/lib/core/db/local_db_impl.dart
+++ b/lib/core/db/local_db_impl.dart
@@ -10,7 +10,7 @@ class LocalDbImpl extends LocalDb {
@override
Future cleanDb() async {
- final localDirectoryPath = (await getApplicationDocumentsDirectory()).path;
+ final localDirectoryPath = (await getApplicationSupportDirectory()).path;
final absoluteDbPath = '$localDirectoryPath$dbPath';
final dbFile = File(absoluteDbPath);
@@ -24,7 +24,7 @@ class LocalDbImpl extends LocalDb {
@override
Future initDb() async {
- final localDirectoryPath = (await getApplicationDocumentsDirectory()).path;
+ final localDirectoryPath = (await getApplicationSupportDirectory()).path;
final absoluteDbPath = '$localDirectoryPath$dbPath';
final dbFile = File(absoluteDbPath);
diff --git a/lib/core/di/injector.dart b/lib/core/di/injector.dart
index ed5a843..ace1fbd 100644
--- a/lib/core/di/injector.dart
+++ b/lib/core/di/injector.dart
@@ -1,115 +1,62 @@
+import 'package:flutter/services.dart';
import 'package:get_it/get_it.dart';
import 'package:spotify_downloader/core/db/local_db.dart';
import 'package:spotify_downloader/core/db/local_db_impl.dart';
-import 'package:spotify_downloader/core/permissions/permissions_manager.dart';
-import 'package:spotify_downloader/core/permissions/requiring_permission_services_initializer.dart';
-import 'package:spotify_downloader/features/data/auth/local_auth/data_source/local_auth_data_source.dart';
-import 'package:spotify_downloader/features/data/auth/local_auth/repository/local_auth_repository_impl.dart';
-import 'package:spotify_downloader/features/data/auth/network_auth/data_source/network_auth_data_source.dart';
-import 'package:spotify_downloader/features/data/auth/network_auth/repository/network_auth_repository_impl.dart';
-import 'package:spotify_downloader/features/data/settings/data_source/settings_data_source.dart';
-import 'package:spotify_downloader/features/data/settings/repository/settings_repository_impl.dart';
-import 'package:spotify_downloader/features/data/spotify_profile/data_source/spotify_profile_data_source.dart';
-import 'package:spotify_downloader/features/data/spotify_profile/repository/spotify_profile_repository_impl.dart';
-import 'package:spotify_downloader/features/data/tracks/local_tracks/data_sources/local_tracks_data_source.dart';
-import 'package:spotify_downloader/features/data/tracks/local_tracks/repositories/local_tracks_repository_impl.dart';
-import 'package:spotify_downloader/features/data/tracks_collections/history_tracks_collectons/data_source/tracks_collectons_history_data_source.dart';
-import 'package:spotify_downloader/features/data/tracks_collections/history_tracks_collectons/repositories/tracks_collections_history_repository_impl.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/data_sources/dowload_audio_from_youtube_data_source.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/data_sources/tools/audio_metadata_editor/audio_metadata_editor_impl.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/data_sources/tools/file_to_mp3_converter/ffmpeg_file_to_mp3_converter.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/repositories/dowload_tracks_repository_impl.dart';
-import 'package:spotify_downloader/features/data/tracks/network_tracks/data_sources/network_tracks_data_source.dart';
-import 'package:spotify_downloader/features/data/tracks/network_tracks/repositories/network_tracks_repository_impl.dart';
-import 'package:spotify_downloader/features/data/tracks/search_videos_by_track/data_sources/search_video_on_youtube_data_source.dart';
-import 'package:spotify_downloader/features/data/tracks/search_videos_by_track/repositories/search_videos_by_track_repository_impl.dart';
-import 'package:spotify_downloader/features/data/tracks_collections/network_tracks_collections/data_source/network_tracks_collections_data_source.dart';
-import 'package:spotify_downloader/features/data/tracks_collections/network_tracks_collections/repositories/tracks_collections_repository_impl.dart';
-import 'package:spotify_downloader/features/domain/auth/local_auth/repositories/local_client_auth_repository.dart';
-import 'package:spotify_downloader/features/domain/auth/local_auth/repositories/local_full_auth_repository.dart';
-import 'package:spotify_downloader/features/domain/auth/local_auth/repositories/local_user_auth_repository.dart';
-import 'package:spotify_downloader/features/domain/auth/local_auth/use_cases/clear_user_credentials.dart';
-import 'package:spotify_downloader/features/domain/auth/local_auth/use_cases/get_client_credentials.dart';
-import 'package:spotify_downloader/features/domain/auth/local_auth/use_cases/save_client_credentials.dart';
-import 'package:spotify_downloader/features/domain/auth/network_auth/repository/network_auth_repository.dart';
-import 'package:spotify_downloader/features/domain/auth/service/service/auth_service.dart';
-import 'package:spotify_downloader/features/domain/auth/service/service/auth_service_impl.dart';
-import 'package:spotify_downloader/features/domain/auth/service/use_cases/authorize_user.dart';
-import 'package:spotify_downloader/features/domain/settings/repository/download_tracks_settings_repository.dart';
-import 'package:spotify_downloader/features/domain/settings/repository/language_settings_repository.dart';
-import 'package:spotify_downloader/features/domain/settings/use_cases/get_available_languages.dart';
-import 'package:spotify_downloader/features/domain/settings/use_cases/get_download_tracks_settings.dart';
-import 'package:spotify_downloader/features/domain/settings/use_cases/get_language.dart';
-import 'package:spotify_downloader/features/domain/settings/use_cases/save_download_tracks_setting.dart';
-import 'package:spotify_downloader/features/domain/settings/use_cases/save_language.dart';
-import 'package:spotify_downloader/features/domain/spotify_profile/repository/spotify_profile_repostitory.dart';
-import 'package:spotify_downloader/features/domain/spotify_profile/service/spotify_profile_service.dart';
-import 'package:spotify_downloader/features/domain/spotify_profile/service/spotify_profile_service_impl.dart';
-import 'package:spotify_downloader/features/domain/spotify_profile/use_cases/get_spotify_profile.dart';
-import 'package:spotify_downloader/features/domain/tracks/local_tracks/repositories/local_tracks_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks/observe_tracks_loading/entities/loading_tracks_collection/loading_tracks_collection_observer.dart';
-import 'package:spotify_downloader/features/domain/tracks/observe_tracks_loading/repository/observe_tracks_loading_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks/observe_tracks_loading/repository/observe_tracks_loading_repository_impl.dart';
-import 'package:spotify_downloader/features/domain/tracks/observe_tracks_loading/use_cases/get_loading_tracks_collections_observer.dart';
-import 'package:spotify_downloader/features/domain/tracks/search_videos_by_track/use_cases/find_10_videos_by_track.dart';
-import 'package:spotify_downloader/features/domain/tracks/search_videos_by_track/use_cases/get_video_by_url.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/services/download_tracks_service/download_tracks_service.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/services/download_tracks_service/download_tracks_service_impl.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/use_cases/download_tracks_from_getting_observer.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/use_cases/download_tracks_range.dart';
-import 'package:spotify_downloader/features/domain/tracks/shared/entities/track.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/history_tracks_collectons/entities/history_tracks_collection.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/history_tracks_collectons/repositories/tracks_collections_history_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/history_tracks_collectons/use_cases/add_tracks_collection_to_history.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/history_tracks_collectons/use_cases/get_ordered_history.dart';
-import 'package:spotify_downloader/features/domain/tracks/download_tracks/repositories/dowload_tracks_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/use_cases/cancel_track_loading.dart';
-import 'package:spotify_downloader/features/domain/tracks/network_tracks/repositories/network_tracks_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks/search_videos_by_track/repositories/search_videos_by_track_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/entities/track_with_loading_observer.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/services/get_tracks_service/get_tracks_service.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/services/get_tracks_service/get_tracks_service_impl.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/use_cases/download_track.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/use_cases/get_tracks_with_loading_observer_from_tracks_collection.dart';
-import 'package:spotify_downloader/features/domain/tracks/services/use_cases/get_tracks_with_loading_observer_from_tracks_collection_with_offset.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/network_tracks_collections/repositories/network_tracks_collections_repository.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/network_tracks_collections/service/network_tracks_collections_service.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/network_tracks_collections/service/network_tracks_collections_service_impl.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/network_tracks_collections/use_cases/get_tracks_collection_by_type_and_spotify_id.dart';
-import 'package:spotify_downloader/features/domain/tracks_collections/network_tracks_collections/use_cases/get_tracks_collection_by_url.dart';
+import 'package:spotify_downloader/core/permissions/permissions.dart';
+
+import 'package:spotify_downloader/features/data_domain/auth/local_auth/local_auth.dart';
+import 'package:spotify_downloader/features/data_domain/auth/network_auth/network_auth.dart';
+import 'package:spotify_downloader/features/data_domain/auth/service/service.dart';
+import 'package:spotify_downloader/features/data_domain/settings/settings.dart';
+import 'package:spotify_downloader/features/data_domain/spotify_profile/spotify_profile.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/download_tracks/data/data_sources/tools/audio_metadata_editor/audio_metadata_editor_impl.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/download_tracks/data/data_sources/tools/file_to_mp3_converter/ffmpeg_file_to_mp3_converter.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/download_tracks/download_tracks.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/local_tracks/local_tracks.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/network_tracks/network_tracks.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/observe_tracks_loading/domain/domain.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/search_videos_by_track/search_videos_by_track.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/services/services.dart';
+import 'package:spotify_downloader/features/data_domain/tracks/shared/domain/entities/track.dart';
+import 'package:spotify_downloader/features/data_domain/tracks_collections/history_tracks_collections/history_tracks_collections.dart';
+import 'package:spotify_downloader/features/data_domain/tracks_collections/network_tracks_collections/network_tracks_collections.dart';
import 'package:spotify_downloader/features/presentation/change_source_video/bloc/change_source_video_bloc.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/widgets/download_track_info/bloc/download_track_info_bloc.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/widgets/download_track_info/widgets/download_track_info_status_tile/cubit/download_track_info_status_tile_cubit.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/widgets/track_tile/bloc/track_tile_bloc.dart';
+import 'package:spotify_downloader/features/presentation/download_tracks_collection/blocs/blocs.dart';
+import 'package:spotify_downloader/features/presentation/download_tracks_collection/widgets/shared/cubits/track_loading_observing_cubit/download_track_info_status_tile_cubit.dart';
import 'package:spotify_downloader/features/presentation/history/bloc/history_bloc.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/blocs/filter_tracks/filter_tracks_bloc.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/blocs/get_and_download_tracks/get_and_download_tracks_bloc.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/blocs/get_tracks_collection/get_tracks_collection_by_history_bloc.dart';
-import 'package:spotify_downloader/features/presentation/download_tracks_collection/blocs/get_tracks_collection/get_tracks_collection_by_url_bloc.dart';
-import 'package:spotify_downloader/features/presentation/home/widgets/loading_tracks_collections_list/bloc/loading_tracks_collections_list_bloc.dart';
+import 'package:spotify_downloader/features/presentation/home/widgets/loading_tracks_collections_list/cubit/loading_tracks_collections_list_cubit.dart';
import 'package:spotify_downloader/features/presentation/home/widgets/loading_tracks_collections_list/widgets/loading_tracks_collection_tile/cubit/loading_tracks_collection_tile_cubit.dart';
import 'package:spotify_downloader/features/presentation/settings/widgets/auth_settings/blocs/account_auth/account_auth_bloc.dart';
import 'package:spotify_downloader/features/presentation/settings/widgets/auth_settings/blocs/client_auth/client_auth_bloc.dart';
import 'package:spotify_downloader/features/presentation/settings/widgets/download_tracks_settings/bloc/download_tracks_settings_bloc.dart';
import 'package:spotify_downloader/features/presentation/settings/widgets/language_setting/bloc/language_setting_bloc.dart';
import 'package:spotify_downloader/features/presentation/tracks_collections_loading_notifications/bloc/tracks_collections_loading_notifications_bloc.dart';
+import 'package:spotify_downloader/features/presentation/tracks_collections_loading_notifications/view/tracks_collections_loading_notifications_sender.dart';
final injector = GetIt.instance;
-Future initInjector() async {
- await _initCore();
+Future initInjector(TargetPlatform platform) async {
+ await _initCore(platform);
await _provideDataSources();
_provideRepositories();
_provideUseCases();
_provideBlocs();
+ _providePresentation();
+ await _initLateCore();
}
-Future _initCore() async {
+Future _initLateCore() async {
+ await injector.get().init();
+}
+
+Future _initCore(TargetPlatform platform) async {
injector.registerSingleton(LocalDbImpl());
await injector.get().initDb();
- injector.registerSingleton(PermissionsManager());
- injector.registerSingleton(
- RequiringPermissionServicesInitializer(permissionsManager: injector.get()));
+
+ injector.registerSingleton(PermissionsAbstractFactory.create(platform));
+ injector.registerSingleton(injector.get().getPermissionsManager());
+ injector.registerSingleton(
+ injector.get().getPermissionServicesInitializer());
}
Future _provideDataSources() async {
@@ -238,8 +185,8 @@ void _provideUseCases() {
}
void _provideBlocs() {
- injector.registerFactory(
- () => LoadingTracksCollectionsListBloc(injector.get()));
+ injector.registerFactory(
+ () => LoadingTracksCollectionsListCubit(injector.get()));
injector.registerFactoryParam(
(loadingTracksCollection, _) => LoadingTracksCollectionTileCubit(loadingTracksCollection));
@@ -254,23 +201,18 @@ void _provideBlocs() {
addTracksCollectionToHistory: injector.get(),
getTracksCollection: injector.get(),
historyTracksCollection: historyCollection));
- injector.registerFactory(() => GetAndDownloadTracksBloc(
- downloadTracksRange: injector.get(),
- downloadTracksFromGettingObserver: injector.get(),
+ injector.registerFactory(() => GetTracksBloc(
getTracksFromTracksCollection: injector.get(),
getTracksWithOffset: injector.get()));
+
+ injector.registerFactory(() => DownloadTracksCubit(
+ downloadTracksRange: injector.get(),
+ downloadTracksFromGettingObserver: injector.get(),
+ downloadTrack: injector.get(),
+ cancelTrackLoading: injector.get()));
injector.registerFactory(() => FilterTracksBloc());
- injector.registerFactoryParam((trackwithLoadingObserver, _) =>
- TrackTileBloc(
- trackWithLoadingObserver: trackwithLoadingObserver,
- downloadTrack: injector.get(),
- cancelTrackLoading: injector.get()));
- injector.registerFactoryParam((trackwithLoadingObserver, _) =>
- DownloadTrackInfoBloc(
- trackWithLoadingObserver: trackwithLoadingObserver, cancelTrackLoading: injector.get()));
- injector.registerFactoryParam(
- (trackwithLoadingObserver, _) => DownloadTrackInfoStatusTileCubit(trackwithLoadingObserver));
+ injector.registerFactory(() => TrackLoadingObservingCubit());
injector.registerFactoryParam((track, _) => ChangeSourceVideoBloc(
sourceTrack: track,
find10VideosByTrack: injector.get(),
@@ -296,3 +238,8 @@ void _provideBlocs() {
saveLanguage: injector.get(),
getAvailableLanguages: injector.get()));
}
+
+void _providePresentation() {
+ injector
+ .registerSingleton(TracksCollectionsLoadingNotificationsSender());
+}
diff --git a/lib/core/notifications/notifications.dart b/lib/core/notifications/notifications.dart
index 957eaed..11b547a 100644
--- a/lib/core/notifications/notifications.dart
+++ b/lib/core/notifications/notifications.dart
@@ -2,24 +2,21 @@ import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:spotify_downloader/core/app/colors/colors.dart';
const String mainChannelKey = 'main_channel';
+const String mainChannelGroupKey = 'main_channel_group';
-Future initAwesomeNotifications() async {
- await AwesomeNotifications().initialize(
+Future initAwesomeNotifications() async {
+ return await AwesomeNotifications().initialize(
'resource://drawable/notifications_icon',
[
NotificationChannel(
- channelGroupKey: 'main_channel_group',
- channelKey: 'main_channel',
- channelName: 'Main notifications',
- channelDescription: ']',
+ channelGroupKey: mainChannelGroupKey,
+ channelKey: mainChannelKey,
+ channelName: 'Main Notifications',
+ channelDescription: 'Main Notifications of Spotify Downloader',
defaultColor: primaryColor)
],
- channelGroups: [NotificationChannelGroup(channelGroupKey: 'main_channel_group', channelGroupName: 'Main group')],
+ channelGroups: [
+ NotificationChannelGroup(channelGroupKey: mainChannelGroupKey, channelGroupName: 'Main Notifications Group')
+ ],
debug: true);
-
- AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
- if (!isAllowed) {
- AwesomeNotifications().requestPermissionToSendNotifications();
- }
- });
}
diff --git a/lib/core/package_info/package_info_accessor.dart b/lib/core/package_info/package_info_accessor.dart
new file mode 100644
index 0000000..d95a1f7
--- /dev/null
+++ b/lib/core/package_info/package_info_accessor.dart
@@ -0,0 +1,17 @@
+import 'package:flutter/material.dart';
+import 'package:package_info_plus/package_info_plus.dart';
+
+class PackageInfoAccessor extends InheritedWidget {
+ const PackageInfoAccessor({super.key, required super.child, required this.packageInfo});
+
+ final PackageInfo packageInfo;
+
+ static PackageInfoAccessor? maybeOf(BuildContext context) {
+ return context.dependOnInheritedWidgetOfExactType();
+ }
+
+ @override
+ bool updateShouldNotify(PackageInfoAccessor oldWidget) {
+ return oldWidget.packageInfo != packageInfo;
+ }
+}
diff --git a/lib/core/permissions/requiring_permission_services_initializer.dart b/lib/core/permissions/permission_services_initializer/android_permission_services_initializer.dart
similarity index 58%
rename from lib/core/permissions/requiring_permission_services_initializer.dart
rename to lib/core/permissions/permission_services_initializer/android_permission_services_initializer.dart
index 7c2de1f..77aa530 100644
--- a/lib/core/permissions/requiring_permission_services_initializer.dart
+++ b/lib/core/permissions/permission_services_initializer/android_permission_services_initializer.dart
@@ -1,23 +1,26 @@
import 'package:flutter_background/flutter_background.dart';
import 'package:spotify_downloader/core/background/background.dart';
+import 'package:spotify_downloader/core/di/injector.dart';
import 'package:spotify_downloader/core/notifications/notifications.dart';
-import 'package:spotify_downloader/core/permissions/permissions_manager.dart';
+import 'package:spotify_downloader/core/permissions/permission_services_initializer/permission_services_initializer_class.dart';
+import 'package:spotify_downloader/core/permissions/permissions_manager/android_permissions_manager.dart';
import 'package:spotify_downloader/features/presentation/tracks_collections_loading_notifications/view/tracks_collections_loading_notifications_sender.dart';
-class RequiringPermissionServicesInitializer {
- RequiringPermissionServicesInitializer({required this.permissionsManager});
+class AndroidPermissionServicesInitializer extends PermissionServicesInitializer {
+ AndroidPermissionServicesInitializer({required this.permissionsManager});
- final PermissionsManager permissionsManager;
+ AndroidPermissionsManager permissionsManager;
bool _isNotificationsInitialized = false;
bool _isBackgroundInitialized = false;
- Future initialize() async {
+ @override
+ Future init() async {
if (!_isNotificationsInitialized && await permissionsManager.isNotificationsPermissionGranted()) {
_isNotificationsInitialized = true;
await initAwesomeNotifications();
- await TracksCollectionsLoadingNotificationsSender().startSendNotifications();
+ await injector.get().startSendNotifications();
}
if (!_isBackgroundInitialized && await FlutterBackground.hasPermissions) {
@@ -26,5 +29,7 @@ class RequiringPermissionServicesInitializer {
await initBackground();
await FlutterBackground.enableBackgroundExecution();
}
+
+ return _isNotificationsInitialized && _isBackgroundInitialized;
}
}
diff --git a/lib/core/permissions/permission_services_initializer/ios_permission_services_initializer.dart b/lib/core/permissions/permission_services_initializer/ios_permission_services_initializer.dart
new file mode 100644
index 0000000..86b8609
--- /dev/null
+++ b/lib/core/permissions/permission_services_initializer/ios_permission_services_initializer.dart
@@ -0,0 +1,25 @@
+import 'package:spotify_downloader/core/di/injector.dart';
+import 'package:spotify_downloader/core/notifications/notifications.dart';
+import 'package:spotify_downloader/core/permissions/permission_services_initializer/permission_services_initializer_class.dart';
+import 'package:spotify_downloader/core/permissions/permissions_manager/ios_permissions_manager.dart';
+import 'package:spotify_downloader/features/presentation/tracks_collections_loading_notifications/view/tracks_collections_loading_notifications_sender.dart';
+
+class IOSPermissionServicesInitializer extends PermissionServicesInitializer {
+ IOSPermissionServicesInitializer({required this.permissionsManager});
+
+ IOSPermissionsManager permissionsManager;
+
+ bool _isNotificationsInitialized = false;
+
+ @override
+ Future init() async {
+ if (!_isNotificationsInitialized && await permissionsManager.isNotificationsPermissionGranted()) {
+ _isNotificationsInitialized = true;
+
+ await initAwesomeNotifications();
+ await injector.get().startSendNotifications();
+ }
+
+ return _isNotificationsInitialized;
+ }
+}
diff --git a/lib/core/permissions/permission_services_initializer/mock_permission_services_initializer.dart b/lib/core/permissions/permission_services_initializer/mock_permission_services_initializer.dart
new file mode 100644
index 0000000..34fe363
--- /dev/null
+++ b/lib/core/permissions/permission_services_initializer/mock_permission_services_initializer.dart
@@ -0,0 +1,8 @@
+import 'package:spotify_downloader/core/permissions/permission_services_initializer/permission_services_initializer_class.dart';
+
+class MockPermissionServicesInitializer extends PermissionServicesInitializer {
+ @override
+ Future init() async {
+ return false;
+ }
+}
diff --git a/lib/core/permissions/permission_services_initializer/permission_services_initializer.dart b/lib/core/permissions/permission_services_initializer/permission_services_initializer.dart
new file mode 100644
index 0000000..db22223
--- /dev/null
+++ b/lib/core/permissions/permission_services_initializer/permission_services_initializer.dart
@@ -0,0 +1,4 @@
+export 'android_permission_services_initializer.dart';
+export 'ios_permission_services_initializer.dart';
+export 'mock_permission_services_initializer.dart';
+export 'permission_services_initializer_class.dart';
diff --git a/lib/core/permissions/permission_services_initializer/permission_services_initializer_class.dart b/lib/core/permissions/permission_services_initializer/permission_services_initializer_class.dart
new file mode 100644
index 0000000..d143d85
--- /dev/null
+++ b/lib/core/permissions/permission_services_initializer/permission_services_initializer_class.dart
@@ -0,0 +1,4 @@
+
+abstract class PermissionServicesInitializer {
+ Future init();
+}
diff --git a/lib/core/permissions/permissions.dart b/lib/core/permissions/permissions.dart
new file mode 100644
index 0000000..0b9ea6d
--- /dev/null
+++ b/lib/core/permissions/permissions.dart
@@ -0,0 +1,3 @@
+export 'permission_services_initializer/permission_services_initializer.dart';
+export 'permissions_factory/permissions_factory.dart';
+export 'permissions_manager/permissions_manager.dart';
diff --git a/lib/core/permissions/permissions_factory/android_permissions_factory.dart b/lib/core/permissions/permissions_factory/android_permissions_factory.dart
new file mode 100644
index 0000000..60ba6bc
--- /dev/null
+++ b/lib/core/permissions/permissions_factory/android_permissions_factory.dart
@@ -0,0 +1,14 @@
+import 'package:spotify_downloader/core/permissions/permissions.dart';
+
+
+class AndroidPermissionsFactory extends PermissionsAbstractFactory {
+ @override
+ AndroidPermissionServicesInitializer getPermissionServicesInitializer() {
+ return AndroidPermissionServicesInitializer(permissionsManager: getPermissionsManager());
+ }
+
+ @override
+ AndroidPermissionsManager getPermissionsManager() {
+ return AndroidPermissionsManager();
+ }
+}
diff --git a/lib/core/permissions/permissions_factory/ios_permissions_factory.dart b/lib/core/permissions/permissions_factory/ios_permissions_factory.dart
new file mode 100644
index 0000000..d0834ee
--- /dev/null
+++ b/lib/core/permissions/permissions_factory/ios_permissions_factory.dart
@@ -0,0 +1,14 @@
+import 'package:spotify_downloader/core/permissions/permissions.dart';
+
+
+class IOSPermissionsFactory extends PermissionsAbstractFactory {
+ @override
+ IOSPermissionServicesInitializer getPermissionServicesInitializer() {
+ return IOSPermissionServicesInitializer(permissionsManager: getPermissionsManager());
+ }
+
+ @override
+ IOSPermissionsManager getPermissionsManager() {
+ return IOSPermissionsManager();
+ }
+}
diff --git a/lib/core/permissions/permissions_factory/mock_permissions_factory.dart b/lib/core/permissions/permissions_factory/mock_permissions_factory.dart
new file mode 100644
index 0000000..8314177
--- /dev/null
+++ b/lib/core/permissions/permissions_factory/mock_permissions_factory.dart
@@ -0,0 +1,15 @@
+
+
+import 'package:spotify_downloader/core/permissions/permissions.dart';
+
+class MockPermissionsFactory extends PermissionsAbstractFactory {
+ @override
+ MockPermissionServicesInitializer getPermissionServicesInitializer() {
+ return MockPermissionServicesInitializer();
+ }
+
+ @override
+ MockPermissionsManager getPermissionsManager() {
+ return MockPermissionsManager();
+ }
+}
diff --git a/lib/core/permissions/permissions_factory/permissions_abstract_factory_class.dart b/lib/core/permissions/permissions_factory/permissions_abstract_factory_class.dart
new file mode 100644
index 0000000..f9c6168
--- /dev/null
+++ b/lib/core/permissions/permissions_factory/permissions_abstract_factory_class.dart
@@ -0,0 +1,23 @@
+
+
+import 'package:flutter/foundation.dart';
+import 'package:spotify_downloader/core/permissions/permissions.dart';
+
+abstract class PermissionsAbstractFactory {
+ PermissionsAbstractFactory();
+
+ factory PermissionsAbstractFactory.create(TargetPlatform platform) {
+ switch (platform) {
+ case TargetPlatform.android:
+ return AndroidPermissionsFactory();
+ case TargetPlatform.iOS:
+ return IOSPermissionsFactory();
+ default:
+ return MockPermissionsFactory();
+ }
+ }
+
+ PermissionServicesInitializer getPermissionServicesInitializer();
+
+ PermissionsManager getPermissionsManager();
+}
diff --git a/lib/core/permissions/permissions_factory/permissions_factory.dart b/lib/core/permissions/permissions_factory/permissions_factory.dart
new file mode 100644
index 0000000..1c44a5d
--- /dev/null
+++ b/lib/core/permissions/permissions_factory/permissions_factory.dart
@@ -0,0 +1,4 @@
+export 'android_permissions_factory.dart';
+export 'ios_permissions_factory.dart';
+export 'mock_permissions_factory.dart';
+export 'permissions_abstract_factory_class.dart';
diff --git a/lib/core/permissions/permissions_manager.dart b/lib/core/permissions/permissions_manager/android_permissions_manager.dart
similarity index 90%
rename from lib/core/permissions/permissions_manager.dart
rename to lib/core/permissions/permissions_manager/android_permissions_manager.dart
index 7ca78a7..080b0d2 100644
--- a/lib/core/permissions/permissions_manager.dart
+++ b/lib/core/permissions/permissions_manager/android_permissions_manager.dart
@@ -1,7 +1,9 @@
import 'package:device_info_plus/device_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
+import 'package:spotify_downloader/core/permissions/permissions_manager/permissions_manager_class.dart';
-class PermissionsManager {
+class AndroidPermissionsManager extends PermissionsManager {
+ @override
Future requestPermissions() async {
final androidVersion = await _getAndroidVersion();
late final List permissions;
@@ -22,6 +24,7 @@ class PermissionsManager {
return Permission.notification.isGranted;
}
+ @override
Future isPermissionsGranted() async {
final androidVersion = await _getAndroidVersion();
late final List permissions;
diff --git a/lib/core/permissions/permissions_manager/ios_permissions_manager.dart b/lib/core/permissions/permissions_manager/ios_permissions_manager.dart
new file mode 100644
index 0000000..50fdedf
--- /dev/null
+++ b/lib/core/permissions/permissions_manager/ios_permissions_manager.dart
@@ -0,0 +1,35 @@
+import 'package:permission_handler/permission_handler.dart';
+import 'package:spotify_downloader/core/permissions/permissions_manager/permissions_manager_class.dart';
+
+class IOSPermissionsManager extends PermissionsManager {
+ @override
+ Future requestPermissions() async {
+ final permissions = _getPermissionsForIOS();
+ for (var permission in permissions) {
+ await permission.request();
+ }
+
+ return await isPermissionsGranted();
+ }
+
+ @override
+ Future isPermissionsGranted() async {
+ final permissions = _getPermissionsForIOS();
+
+ for (var permission in permissions) {
+ if (!(await permission.isGranted)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ Future isNotificationsPermissionGranted() {
+ return Permission.notification.isGranted;
+ }
+
+ List _getPermissionsForIOS() {
+ return [Permission.storage, Permission.notification];
+ }
+}
diff --git a/lib/core/permissions/permissions_manager/mock_permissions_manager.dart b/lib/core/permissions/permissions_manager/mock_permissions_manager.dart
new file mode 100644
index 0000000..0809f00
--- /dev/null
+++ b/lib/core/permissions/permissions_manager/mock_permissions_manager.dart
@@ -0,0 +1,14 @@
+import 'package:spotify_downloader/core/permissions/permissions_manager/permissions_manager_class.dart';
+
+class MockPermissionsManager extends PermissionsManager {
+
+ @override
+ Future isPermissionsGranted() async {
+ return false;
+ }
+
+ @override
+ Future requestPermissions() async {
+ return false;
+ }
+}
diff --git a/lib/core/permissions/permissions_manager/permissions_manager.dart b/lib/core/permissions/permissions_manager/permissions_manager.dart
new file mode 100644
index 0000000..95ea904
--- /dev/null
+++ b/lib/core/permissions/permissions_manager/permissions_manager.dart
@@ -0,0 +1,4 @@
+export 'android_permissions_manager.dart';
+export 'ios_permissions_manager.dart';
+export 'mock_permissions_manager.dart';
+export 'permissions_manager_class.dart';
diff --git a/lib/core/permissions/permissions_manager/permissions_manager_class.dart b/lib/core/permissions/permissions_manager/permissions_manager_class.dart
new file mode 100644
index 0000000..a1369d5
--- /dev/null
+++ b/lib/core/permissions/permissions_manager/permissions_manager_class.dart
@@ -0,0 +1,6 @@
+abstract class PermissionsManager {
+
+ Future requestPermissions();
+
+ Future isPermissionsGranted();
+}
diff --git a/lib/core/util/cancellation_token/cancellation_token_source.dart b/lib/core/util/cancellation_token/cancellation_token_source.dart
deleted file mode 100644
index d7a6353..0000000
--- a/lib/core/util/cancellation_token/cancellation_token_source.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-import 'cancellation_token.dart';
-
-class CancellationTokenSource {
- bool _isCancelled = false;
- bool get isCancelled => _isCancelled;
- CancellationToken get token => CancellationToken(source: this);
-
- void cancel() {
- _isCancelled = true;
- }
-}
diff --git a/lib/core/util/converters/converter_with_parameter.dart b/lib/core/util/converters/converter_with_parameter.dart
deleted file mode 100644
index 066aa55..0000000
--- a/lib/core/util/converters/converter_with_parameter.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import 'package:spotify_downloader/core/util/converters/base_value_converter.dart/base_value_converter.dart';
-
-abstract class ConverterWithParameter extends BaseValueConverter {
-
-}
\ No newline at end of file
diff --git a/lib/core/util/converters/result_converters/result_value_converter.dart b/lib/core/util/converters/result_converters/result_value_converter.dart
deleted file mode 100644
index a76f01b..0000000
--- a/lib/core/util/converters/result_converters/result_value_converter.dart
+++ /dev/null
@@ -1,6 +0,0 @@
-import 'package:spotify_downloader/core/util/converters/base_value_converter.dart/base_value_converter.dart';
-import 'package:spotify_downloader/core/util/failures/failures.dart';
-import 'package:spotify_downloader/core/util/result/result.dart';
-
-abstract class ResultValueConverter
- implements BaseValueConverter, T2, Result, T1> {}
diff --git a/lib/core/util/converters/simple_converters/async_value_converter.dart b/lib/core/util/converters/simple_converters/async_value_converter.dart
deleted file mode 100644
index 5087f5d..0000000
--- a/lib/core/util/converters/simple_converters/async_value_converter.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'package:spotify_downloader/core/util/converters/base_value_converter.dart/base_value_converter.dart';
-
-abstract class AsyncValueConverter implements BaseValueConverter, T2, Future, T1> {}
diff --git a/lib/core/util/converters/simple_converters/value_converter.dart b/lib/core/util/converters/simple_converters/value_converter.dart
deleted file mode 100644
index 04b1d48..0000000
--- a/lib/core/util/converters/simple_converters/value_converter.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'package:spotify_downloader/core/util/converters/base_value_converter.dart/base_value_converter.dart';
-
-abstract class ValueConverter implements BaseValueConverter { }
\ No newline at end of file
diff --git a/lib/core/utils/cancellation_token/cancellation_token.dart b/lib/core/utils/cancellation_token/cancellation_token.dart
new file mode 100644
index 0000000..0c3729f
--- /dev/null
+++ b/lib/core/utils/cancellation_token/cancellation_token.dart
@@ -0,0 +1,2 @@
+export 'cancellation_token_class.dart';
+export 'cancellation_token_source.dart';
diff --git a/lib/core/util/cancellation_token/cancellation_token.dart b/lib/core/utils/cancellation_token/cancellation_token_class.dart
similarity index 66%
rename from lib/core/util/cancellation_token/cancellation_token.dart
rename to lib/core/utils/cancellation_token/cancellation_token_class.dart
index 3c4a8f0..e892e28 100644
--- a/lib/core/util/cancellation_token/cancellation_token.dart
+++ b/lib/core/utils/cancellation_token/cancellation_token_class.dart
@@ -1,10 +1,11 @@
-import 'package:spotify_downloader/core/util/cancellation_token/cancellation_token_source.dart';
+import 'package:spotify_downloader/core/utils/cancellation_token/cancellation_token_source.dart';
class CancellationToken {
CancellationToken({required this.source});
CancellationTokenSource source;
bool get isCancelled => source.isCancelled;
+ Stream get cancelationStream => source.cancellationStream;
@override
int get hashCode => source.hashCode;
diff --git a/lib/core/utils/cancellation_token/cancellation_token_source.dart b/lib/core/utils/cancellation_token/cancellation_token_source.dart
new file mode 100644
index 0000000..fa7f609
--- /dev/null
+++ b/lib/core/utils/cancellation_token/cancellation_token_source.dart
@@ -0,0 +1,25 @@
+import 'dart:async';
+
+import 'package:spotify_downloader/core/utils/cancellation_token/cancellation_token_class.dart';
+
+class CancellationTokenSource {
+ final StreamController _cancellationStreamController = StreamController();
+ late final Stream _cancellationStream;
+ Stream get cancellationStream => _cancellationStream;
+
+ bool _isCancelled = false;
+ bool get isCancelled => _isCancelled;
+
+ CancellationToken get token => CancellationToken(source: this);
+
+ CancellationTokenSource() {
+ _cancellationStream = _cancellationStreamController.stream.asBroadcastStream();
+ }
+
+ void cancel() {
+ if (!_isCancelled) {
+ _cancellationStreamController.add(null);
+ }
+ _isCancelled = true;
+ }
+}
diff --git a/lib/core/utils/converters/abstract/abstract.dart b/lib/core/utils/converters/abstract/abstract.dart
new file mode 100644
index 0000000..083c5a9
--- /dev/null
+++ b/lib/core/utils/converters/abstract/abstract.dart
@@ -0,0 +1 @@
+export 'converter_with_parameter.dart';
diff --git a/lib/core/util/converters/abstract/converter_with_parameter.dart b/lib/core/utils/converters/abstract/converter_with_parameter.dart
similarity index 50%
rename from lib/core/util/converters/abstract/converter_with_parameter.dart
rename to lib/core/utils/converters/abstract/converter_with_parameter.dart
index 066aa55..a48772e 100644
--- a/lib/core/util/converters/abstract/converter_with_parameter.dart
+++ b/lib/core/utils/converters/abstract/converter_with_parameter.dart
@@ -1,4 +1,4 @@
-import 'package:spotify_downloader/core/util/converters/base_value_converter.dart/base_value_converter.dart';
+import 'package:spotify_downloader/core/utils/converters/base_value_converter.dart/base_value_converter.dart';
abstract class ConverterWithParameter extends BaseValueConverter {
diff --git a/lib/core/util/converters/base_value_converter.dart/base_value_converter.dart b/lib/core/utils/converters/base_value_converter.dart/base_value_converter.dart
similarity index 100%
rename from lib/core/util/converters/base_value_converter.dart/base_value_converter.dart
rename to lib/core/utils/converters/base_value_converter.dart/base_value_converter.dart
diff --git a/lib/core/utils/converters/base_value_converter.dart/base_value_converter.dart.dart b/lib/core/utils/converters/base_value_converter.dart/base_value_converter.dart.dart
new file mode 100644
index 0000000..42769a9
--- /dev/null
+++ b/lib/core/utils/converters/base_value_converter.dart/base_value_converter.dart.dart
@@ -0,0 +1 @@
+export 'base_value_converter.dart';
diff --git a/lib/core/utils/converters/converters.dart b/lib/core/utils/converters/converters.dart
new file mode 100644
index 0000000..8cc452d
--- /dev/null
+++ b/lib/core/utils/converters/converters.dart
@@ -0,0 +1,4 @@
+export 'abstract/abstract.dart';
+export 'base_value_converter.dart/base_value_converter.dart.dart';
+export 'result_converters/result_converters.dart';
+export 'simple_converters/simple_converters.dart';
diff --git a/lib/core/utils/converters/result_converters/result_converters.dart b/lib/core/utils/converters/result_converters/result_converters.dart
new file mode 100644
index 0000000..682dcd6
--- /dev/null
+++ b/lib/core/utils/converters/result_converters/result_converters.dart
@@ -0,0 +1 @@
+export 'result_value_converter.dart';
diff --git a/lib/core/utils/converters/result_converters/result_value_converter.dart b/lib/core/utils/converters/result_converters/result_value_converter.dart
new file mode 100644
index 0000000..2d2ae78
--- /dev/null
+++ b/lib/core/utils/converters/result_converters/result_value_converter.dart
@@ -0,0 +1,6 @@
+import 'package:spotify_downloader/core/utils/converters/base_value_converter.dart/base_value_converter.dart';
+import 'package:spotify_downloader/core/utils/failures/failures.dart';
+import 'package:spotify_downloader/core/utils/result/result.dart';
+
+abstract class ResultValueConverter
+ implements BaseValueConverter, T2, Result, T1> {}
diff --git a/lib/core/utils/converters/simple_converters/async_value_converter.dart b/lib/core/utils/converters/simple_converters/async_value_converter.dart
new file mode 100644
index 0000000..5d2d609
--- /dev/null
+++ b/lib/core/utils/converters/simple_converters/async_value_converter.dart
@@ -0,0 +1,3 @@
+import 'package:spotify_downloader/core/utils/converters/base_value_converter.dart/base_value_converter.dart';
+
+abstract class AsyncValueConverter implements BaseValueConverter, T2, Future, T1> {}
diff --git a/lib/core/utils/converters/simple_converters/simple_converters.dart b/lib/core/utils/converters/simple_converters/simple_converters.dart
new file mode 100644
index 0000000..2933ec3
--- /dev/null
+++ b/lib/core/utils/converters/simple_converters/simple_converters.dart
@@ -0,0 +1,2 @@
+export 'async_value_converter.dart';
+export 'value_converter.dart';
diff --git a/lib/core/utils/converters/simple_converters/value_converter.dart b/lib/core/utils/converters/simple_converters/value_converter.dart
new file mode 100644
index 0000000..ad8935a
--- /dev/null
+++ b/lib/core/utils/converters/simple_converters/value_converter.dart
@@ -0,0 +1,3 @@
+import 'package:spotify_downloader/core/utils/converters/base_value_converter.dart/base_value_converter.dart';
+
+abstract class ValueConverter implements BaseValueConverter { }
\ No newline at end of file
diff --git a/lib/core/util/failures/failures.dart b/lib/core/utils/failures/custom_failures.dart
similarity index 82%
rename from lib/core/util/failures/failures.dart
rename to lib/core/utils/failures/custom_failures.dart
index 4cfac49..b7edf81 100644
--- a/lib/core/util/failures/failures.dart
+++ b/lib/core/utils/failures/custom_failures.dart
@@ -1,4 +1,4 @@
-import 'package:spotify_downloader/core/util/failures/failure.dart';
+import 'package:spotify_downloader/core/utils/failures/failure.dart';
final class NotFoundFailure extends Failure {
const NotFoundFailure({super.message = 'not found failure'});
@@ -26,4 +26,8 @@ final class InvalidAccountCredentialsFailure extends Failure {
final class NotAuthorizedFailure extends Failure {
NotAuthorizedFailure({super.message = 'User not authorized'});
+}
+
+final class ForbiddenFailure extends Failure {
+ ForbiddenFailure({super.message = 'Access Forbidden'});
}
\ No newline at end of file
diff --git a/lib/core/util/failures/failure.dart b/lib/core/utils/failures/failure.dart
similarity index 100%
rename from lib/core/util/failures/failure.dart
rename to lib/core/utils/failures/failure.dart
diff --git a/lib/core/utils/failures/failures.dart b/lib/core/utils/failures/failures.dart
new file mode 100644
index 0000000..62716d4
--- /dev/null
+++ b/lib/core/utils/failures/failures.dart
@@ -0,0 +1,2 @@
+export 'custom_failures.dart';
+export 'failure.dart';
diff --git a/lib/core/util/isolate_pool/cancellable_compute.dart b/lib/core/utils/isolate_pool/cancellable_compute.dart
similarity index 100%
rename from lib/core/util/isolate_pool/cancellable_compute.dart
rename to lib/core/utils/isolate_pool/cancellable_compute.dart
diff --git a/lib/core/util/isolate_pool/cancellable_stream.dart b/lib/core/utils/isolate_pool/cancellable_stream.dart
similarity index 100%
rename from lib/core/util/isolate_pool/cancellable_stream.dart
rename to lib/core/utils/isolate_pool/cancellable_stream.dart
diff --git a/lib/core/utils/isolate_pool/isolate_pool.dart b/lib/core/utils/isolate_pool/isolate_pool.dart
new file mode 100644
index 0000000..c7cbdc0
--- /dev/null
+++ b/lib/core/utils/isolate_pool/isolate_pool.dart
@@ -0,0 +1,4 @@
+export 'cancellable_compute.dart';
+export 'cancellable_stream.dart';
+export 'isolate_pool_class.dart';
+export 'isolate_pool_was_closed_exception.dart';
diff --git a/lib/core/util/isolate_pool/isolate_pool.dart b/lib/core/utils/isolate_pool/isolate_pool_class.dart
similarity index 88%
rename from lib/core/util/isolate_pool/isolate_pool.dart
rename to lib/core/utils/isolate_pool/isolate_pool_class.dart
index e13ba3c..9f5f82c 100644
--- a/lib/core/util/isolate_pool/isolate_pool.dart
+++ b/lib/core/utils/isolate_pool/isolate_pool_class.dart
@@ -1,11 +1,5 @@
import 'dart:isolate';
-
-import 'package:spotify_downloader/core/util/cancellation_token/cancellation_token.dart';
-import 'package:spotify_downloader/core/util/cancellation_token/cancellation_token_source.dart';
-import 'package:spotify_downloader/core/util/isolate_pool/cancellable_compute.dart';
-import 'package:spotify_downloader/core/util/isolate_pool/isolate_pool_was_closed_exception.dart';
-
-import 'cancellable_stream.dart';
+import 'package:spotify_downloader/core/utils/utils.dart';
class IsolatePool {
IsolatePool._(Isolate mainIsolate, SendPort addSendPort)
diff --git a/lib/core/util/isolate_pool/isolate_pool_was_closed_exception.dart b/lib/core/utils/isolate_pool/isolate_pool_was_closed_exception.dart
similarity index 100%
rename from lib/core/util/isolate_pool/isolate_pool_was_closed_exception.dart
rename to lib/core/utils/isolate_pool/isolate_pool_was_closed_exception.dart
diff --git a/lib/core/util/result/cancellable_result.dart b/lib/core/utils/result/cancellable_result.dart
similarity index 100%
rename from lib/core/util/result/cancellable_result.dart
rename to lib/core/utils/result/cancellable_result.dart
diff --git a/lib/core/utils/result/result.dart b/lib/core/utils/result/result.dart
new file mode 100644
index 0000000..6076b20
--- /dev/null
+++ b/lib/core/utils/result/result.dart
@@ -0,0 +1,2 @@
+export 'cancellable_result.dart';
+export 'result_class.dart';
diff --git a/lib/core/util/result/result.dart b/lib/core/utils/result/result_class.dart
similarity index 99%
rename from lib/core/util/result/result.dart
rename to lib/core/utils/result/result_class.dart
index a11b945..6212f66 100644
--- a/lib/core/util/result/result.dart
+++ b/lib/core/utils/result/result_class.dart
@@ -6,4 +6,4 @@ class Result {
final bool isSuccessful;
final Type? result;
final Failure? failure;
-}
+}
\ No newline at end of file
diff --git a/lib/core/util/use_case/use_case.dart b/lib/core/utils/use_case/use_case.dart
similarity index 60%
rename from lib/core/util/use_case/use_case.dart
rename to lib/core/utils/use_case/use_case.dart
index 2c38d1f..6960b01 100644
--- a/lib/core/util/use_case/use_case.dart
+++ b/lib/core/utils/use_case/use_case.dart
@@ -1,4 +1,4 @@
-import 'package:spotify_downloader/core/util/result/result.dart';
+import 'package:spotify_downloader/core/utils/result/result.dart';
abstract class UseCase {
Future> call(Params params);
diff --git a/lib/core/util/util_methods.dart b/lib/core/utils/util_methods.dart
similarity index 64%
rename from lib/core/util/util_methods.dart
rename to lib/core/utils/util_methods.dart
index 0ff0b6b..5f52f9c 100644
--- a/lib/core/util/util_methods.dart
+++ b/lib/core/utils/util_methods.dart
@@ -1,12 +1,11 @@
+import 'dart:async';
import 'dart:io';
import 'dart:ui';
import 'package:http/http.dart';
import 'package:spotify/spotify.dart';
import 'package:spotify_downloader/core/app/colors/colors.dart';
-import 'package:spotify_downloader/core/util/failures/failure.dart';
-import 'package:spotify_downloader/core/util/failures/failures.dart';
-import 'package:spotify_downloader/core/util/result/result.dart';
+import 'package:spotify_downloader/core/utils/utils.dart';
Color getIntermediateColor(Color color1, Color color2, double ratio) {
return Color.fromARGB(
@@ -24,11 +23,14 @@ Future> handleSpotifyClientExceptions(Future> handleSpotifyClientExceptions(Future', '|'];
+String? formatStringToFileFormat(String? string) {
+ final forbiddenChars = ['/', '\\', ':', '*', '?', '<', '>', '|'];
- String? formattedString = string;
- for (var char in forbiddenChars) {
- formattedString = formattedString?.replaceAll(char, '');
- }
+ String? formattedString = string;
+ for (var char in forbiddenChars) {
+ formattedString = formattedString?.replaceAll(char, '');
+ }
+
+ return formattedString;
+}
- return formattedString;
+double normalize(double value, double min, double max) {
+ if (min >= max) {
+ throw ArgumentError('Min must be less than max');
}
+
+ return (value - min) / (max - min);
+}
+
+double closest(double value, double num1, double num2) {
+ double diff1 = (value - num1).abs();
+ double diff2 = (value - num2).abs();
+
+ return (diff1 < diff2) ? num1 : num2;
+}
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
new file mode 100644
index 0000000..a90e369
--- /dev/null
+++ b/lib/core/utils/utils.dart
@@ -0,0 +1,7 @@
+export 'cancellation_token/cancellation_token.dart';
+export 'converters/converters.dart';
+export 'failures/failures.dart';
+export 'isolate_pool/isolate_pool.dart';
+export 'result/result.dart';
+export 'util_methods.dart';
+export 'use_case/use_case.dart';
diff --git a/lib/features/data/settings/data_source/settings_data_source.dart b/lib/features/data/settings/data_source/settings_data_source.dart
deleted file mode 100644
index 4ee1bf5..0000000
--- a/lib/features/data/settings/data_source/settings_data_source.dart
+++ /dev/null
@@ -1,46 +0,0 @@
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:path_provider/path_provider.dart';
-import 'package:spotify_downloader/core/consts/local_paths.dart';
-import 'package:spotify_downloader/core/util/failures/failure.dart';
-import 'package:spotify_downloader/core/util/result/result.dart';
-import 'package:spotify_downloader/features/data/settings/models/app_settings.dart';
-
-class SettingsDataSource {
- Future saveSettings(AppSettings appSettings) async {
- final localDirectoryPath = (await getApplicationDocumentsDirectory()).path;
- final absoluteAuthFilePath = '$localDirectoryPath$settingsPath';
-
- final authFile = File(absoluteAuthFilePath);
- await authFile.writeAsString(_appSettingsToJson(appSettings));
- }
-
- Future> getSettings() async {
- final localDirectoryPath = (await getApplicationDocumentsDirectory()).path;
- final absoluteAuthFilePath = '$localDirectoryPath$settingsPath';
-
- final authFile = File(absoluteAuthFilePath);
- if (await authFile.exists()) {
- final json = await authFile.readAsString();
- return _appSettingsFromJson(json);
- }
-
- return const Result.isSuccessful(null);
- }
-
- String _appSettingsToJson(AppSettings appSettings) {
- return jsonEncode(
- {'saveMode': appSettings.saveMode, 'savePath': appSettings.savePath, 'language': appSettings.language});
- }
-
- Result _appSettingsFromJson(String jsonData) {
- final decodedData = jsonDecode(jsonData);
- try {
- return Result.isSuccessful(AppSettings(
- saveMode: decodedData['saveMode'], savePath: decodedData['savePath'], language: decodedData['language']));
- } catch (e) {
- return Result.notSuccessful(Failure(message: e));
- }
- }
-}
diff --git a/lib/features/data/tracks/dowload_tracks/data_sources/dowload_audio_from_youtube_data_source.dart b/lib/features/data/tracks/dowload_tracks/data_sources/dowload_audio_from_youtube_data_source.dart
deleted file mode 100644
index f65f4dc..0000000
--- a/lib/features/data/tracks/dowload_tracks/data_sources/dowload_audio_from_youtube_data_source.dart
+++ /dev/null
@@ -1,245 +0,0 @@
-import 'dart:async';
-import 'dart:ffi';
-import 'dart:io';
-
-import 'package:connectivity_plus/connectivity_plus.dart';
-import 'package:http/http.dart';
-import 'package:path/path.dart' as p;
-import 'package:spotify_downloader/core/util/cancellation_token/cancellation_token.dart';
-import 'package:spotify_downloader/core/util/cancellation_token/cancellation_token_source.dart';
-import 'package:spotify_downloader/core/util/isolate_pool/isolate_pool.dart';
-import 'package:spotify_downloader/core/util/result/cancellable_result.dart';
-import 'package:youtube_explode_dart/youtube_explode_dart.dart';
-
-import 'package:spotify_downloader/core/util/failures/failure.dart';
-import 'package:spotify_downloader/core/util/failures/failures.dart';
-
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/data_sources/tools/audio_metadata_editor/audio_metadata_editor.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/data_sources/tools/file_to_mp3_converter/file_to_mp3_converter.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/models/dowload_audio_from_youtube_args.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/models/loading_stream/audio_loading_stream.dart';
-
-class DownloadAudioFromYoutubeDataSource {
- DownloadAudioFromYoutubeDataSource(
- {required AudioMetadataEditor audioMetadataEditor, required FileToMp3Converter fileToMp3Converter})
- : _audioMetadataEditor = audioMetadataEditor,
- _fileToMp3Converter = fileToMp3Converter;
-
- final AudioMetadataEditor _audioMetadataEditor;
- final FileToMp3Converter _fileToMp3Converter;
-
- late final IsolatePool _isolatePool;
-
- Future init() async {
- _isolatePool = await IsolatePool.create();
- }
-
- Future dowloadAudioFromYoutube(DownloadAudioFromYoutubeArgs args) async {
- void Function() cancelFunction = () {};
-
- return AudioLoadingStream(streamFunction: (setLoadingPercent) async {
- try {
- CancellationTokenSource cancellationTokenSource = CancellationTokenSource();
- final token = cancellationTokenSource.token;
- cancelFunction = cancellationTokenSource.cancel;
-
- final getDownloadStreamInfoCompute = await _isolatePool.compute(_getDownloadStreamInfo, args);
- if (token.isCancelled) {
- getDownloadStreamInfoCompute.cancel();
- return const CancellableResult.isCancelled();
- }
-
- cancelFunction = getDownloadStreamInfoCompute.cancel;
- final getDownloadStreamInfoResult = await Future.any([
- getDownloadStreamInfoCompute.future,
- Future(() async {
- await Connectivity().onConnectivityChanged.firstWhere((connectivityResult) =>
- connectivityResult == ConnectivityResult.none || connectivityResult == ConnectivityResult.other);
- return const CancellableResult.notSuccessful(NetworkFailure());
- })
- ]);
-
- if (getDownloadStreamInfoResult.isCancelled) {
- return const CancellableResult.isCancelled();
- } else if (!getDownloadStreamInfoResult.isSuccessful) {
- return CancellableResult.notSuccessful(getDownloadStreamInfoResult.failure);
- }
-
- final downloadStreamInfo = getDownloadStreamInfoResult.result!;
-
- final videoPath =
- p.join(args.saveDirectoryPath, '${args.audioMetadata.name}.${downloadStreamInfo.container.name}');
- final audioPath = p.join(args.saveDirectoryPath, '${args.audioMetadata.name}.mp3');
-
- cancelFunction = cancellationTokenSource.cancel;
-
- await Directory(args.saveDirectoryPath).create(recursive: true);
-
- final downloadVideoResult =
- await _downloadVideoFromYoutube(downloadStreamInfo, videoPath, setLoadingPercent, token);
-
- if (downloadVideoResult.isCancelled) {
- return const CancellableResult.isCancelled();
- } else if (!downloadVideoResult.isSuccessful) {
- return CancellableResult.notSuccessful(downloadVideoResult.failure);
- }
-
- await _convertFileToMp3(videoPath, audioPath);
-
- setLoadingPercent.call(95);
- await File(videoPath).delete();
-
- if (token.isCancelled) {
- await File(audioPath).delete();
- return const CancellableResult.isCancelled();
- }
-
- final changeMetadataResult =
- await _audioMetadataEditor.changeAudioMetadata(audioPath: audioPath, audioMetadata: args.audioMetadata);
- if (!changeMetadataResult.isSuccessful) {
- await File(audioPath).delete();
- return CancellableResult.notSuccessful(changeMetadataResult.failure);
- }
-
- if (token.isCancelled) {
- await File(audioPath).delete();
- return const CancellableResult.isCancelled();
- }
-
- setLoadingPercent.call(100);
- return CancellableResult.isSuccessful(audioPath);
- } catch (e) {
- return CancellableResult.notSuccessful(Failure(message: e));
- }
- }, cancelFunction: () {
- cancelFunction();
- });
- }
-
- Future> _getDownloadStreamInfo(
- DownloadAudioFromYoutubeArgs args, CancellationToken token) async {
- final yt = YoutubeExplode();
- if (token.isCancelled) return const CancellableResult.isCancelled();
-
- late final Video video;
- late final AudioOnlyStreamInfo downloadStreamInfo;
-
- try {
- video = await yt.videos.get(VideoId.parseVideoId(args.youtubeUrl));
- if (token.isCancelled) return const CancellableResult.isCancelled();
-
- final manifest = await yt.videos.streamsClient.getManifest(video.id);
- if (token.isCancelled) return const CancellableResult.isCancelled();
-
- downloadStreamInfo = manifest.audioOnly.withHighestBitrate();
- } catch (e) {
- yt.close();
- if (e is ClientException || e is SocketException) {
- return const CancellableResult.notSuccessful(NetworkFailure());
- }
-
- if (e is ArgumentError) {
- return CancellableResult.notSuccessful(
- NotFoundFailure(message: 'video with this url not found: ${args.youtubeUrl}'));
- }
-
- return CancellableResult.notSuccessful(Failure(message: e));
- }
-
- yt.close();
- return CancellableResult.isSuccessful(downloadStreamInfo);
- }
-
- Future> _downloadVideoFromYoutube(AudioOnlyStreamInfo downloadStreamInfo,
- String savePath, void Function(double percent) setLoadingPercent, CancellationToken token) async {
- try {
- final yt = YoutubeExplode();
- final downloadStream = yt.videos.streamsClient.get(downloadStreamInfo);
- final videoFile = File(savePath);
-
- if (await videoFile.exists()) {
- await videoFile.delete();
- }
-
- await videoFile.create();
- final videoFileStream = videoFile.openWrite();
-
- late final StreamSubscription> downloadStreamListener;
-
- final videoFileSize = downloadStreamInfo.size.totalBytes;
- int loadedBytesCount = 0;
-
- final cancellationTokenCompleter = Completer();
- final failureCompleter = Completer();
-
- downloadStreamListener = downloadStream.listen((chunk) async {
- if (token.isCancelled) {
- if (!cancellationTokenCompleter.isCompleted) {
- cancellationTokenCompleter.complete(null);
- }
- return;
- }
-
- try {
- videoFileStream.add(chunk);
- } catch (e) {
- if (!failureCompleter.isCompleted) {
- failureCompleter.complete(Failure(message: e));
- }
- }
-
- loadedBytesCount += chunk.length;
- setLoadingPercent.call((loadedBytesCount / videoFileSize) * 90);
- })
- ..onError((e) {
- if (!failureCompleter.isCompleted) {
- failureCompleter.complete(Failure(message: e));
- }
- });
-
- Failure failure = const Failure(message: '');
-
- Connectivity()
- .onConnectivityChanged
- .firstWhere((result) => result == ConnectivityResult.none || result == ConnectivityResult.other)
- .then((value) {
- if (!failureCompleter.isCompleted) {
- failureCompleter.complete(const NetworkFailure());
- }
- });
-
- await Future.any([
- downloadStreamListener.asFuture(),
- cancellationTokenCompleter.future,
- (() async {
- failure = await failureCompleter.future;
- }).call(),
- ]);
-
- await videoFileStream.flush();
- await videoFileStream.close();
- yt.close();
-
- if (failureCompleter.isCompleted) {
- return CancellableResult.notSuccessful(failure);
- }
-
- if (cancellationTokenCompleter.isCompleted) {
- await videoFile.delete();
- return const CancellableResult.isCancelled();
- }
-
- return const CancellableResult.isSuccessful(null);
- } catch (e) {
- return CancellableResult.notSuccessful(Failure(message: e));
- }
- }
-
- Future _convertFileToMp3(String rawPath, String audioPath) async {
- final audioFile = File(audioPath);
- if (await audioFile.exists()) {
- await audioFile.delete();
- }
- await _fileToMp3Converter.convertFileToMp3(rawPath, audioPath);
- }
-}
diff --git a/lib/features/data/tracks/dowload_tracks/data_sources/tools/audio_metadata_editor/audio_metadata_editor.dart b/lib/features/data/tracks/dowload_tracks/data_sources/tools/audio_metadata_editor/audio_metadata_editor.dart
deleted file mode 100644
index e70a3d8..0000000
--- a/lib/features/data/tracks/dowload_tracks/data_sources/tools/audio_metadata_editor/audio_metadata_editor.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'package:spotify_downloader/core/util/failures/failure.dart';
-import 'package:spotify_downloader/core/util/result/result.dart';
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/models/metadata/audio_metadata.dart';
-
-abstract class AudioMetadataEditor {
- Future> changeAudioMetadata({required String audioPath, required AudioMetadata audioMetadata});
-}
\ No newline at end of file
diff --git a/lib/features/data/tracks/dowload_tracks/repositories/repository_impl_classes/loading_track_info.dart b/lib/features/data/tracks/dowload_tracks/repositories/repository_impl_classes/loading_track_info.dart
deleted file mode 100644
index c5a6a5f..0000000
--- a/lib/features/data/tracks/dowload_tracks/repositories/repository_impl_classes/loading_track_info.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:spotify_downloader/features/data/tracks/dowload_tracks/models/loading_stream/audio_loading_stream.dart';
-import 'package:spotify_downloader/features/domain/tracks/download_tracks/entities/loading_track_id.dart';
-import 'package:spotify_downloader/features/domain/tracks/download_tracks/entities/track_loading_notifier.dart';
-
-class LoadingTrackInfo {
- LoadingTrackInfo(
- {required this.loadingTrackId, required this.audioLoadingStream, required this.trackLoadingNotifier});
-
- final LoadingTrackId loadingTrackId;
- AudioLoadingStream? audioLoadingStream;
- TrackLoadingNotifier trackLoadingNotifier;
-}
diff --git a/lib/features/data/tracks/network_tracks/models/tracks_getting_stream.dart b/lib/features/data/tracks/network_tracks/models/tracks_getting_stream.dart
deleted file mode 100644
index 2d0c72c..0000000
--- a/lib/features/data/tracks/network_tracks/models/tracks_getting_stream.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-import 'package:spotify/spotify.dart';
-import 'package:spotify_downloader/core/util/failures/failure.dart';
-import 'package:spotify_downloader/core/util/result/result.dart';
-import 'package:spotify_downloader/features/data/tracks/network_tracks/models/tracks_dto_getting_ended_status.dart';
-
-class TracksGettingStream {
- Function(Result)? onEnded;
- Function(List