diff options
author | Orangerot <purple@orangerot.dev> | 2024-12-23 02:08:45 +0100 |
---|---|---|
committer | Orangerot <purple@orangerot.dev> | 2024-12-23 02:08:45 +0100 |
commit | d397b62b5b6f6db45a2cc0ae6ca4e03ff04c54b2 (patch) | |
tree | 4874d7b28bdc051a83af24cfa4a9ed947b147213 | |
parent | 9aaf00e6275616f4ff3086b0fb4ae98c2036c4fb (diff) |
feat: import song directory and display them with banner
-rw-r--r-- | android/settings.gradle | 2 | ||||
-rw-r--r-- | lib/level_selection.dart | 121 | ||||
-rw-r--r-- | pubspec.lock | 167 | ||||
-rw-r--r-- | pubspec.yaml | 69 |
4 files changed, 264 insertions, 95 deletions
diff --git a/android/settings.gradle b/android/settings.gradle index b9e43bd..a42444d 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.1.0" apply false + id "com.android.application" version "8.2.1" apply false id "org.jetbrains.kotlin.android" version "1.8.22" apply false } diff --git a/lib/level_selection.dart b/lib/level_selection.dart index a5a9c32..cc79911 100644 --- a/lib/level_selection.dart +++ b/lib/level_selection.dart @@ -1,40 +1,109 @@ +import 'dart:io'; + +import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'level.dart'; -class LevelSelection extends StatelessWidget { - final List<String> _musicList = [ - "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", - "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3", - "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3", - ]; +class LevelSelection extends StatefulWidget { + const LevelSelection({super.key}); + + @override + State<LevelSelection> createState() => _LevelSelectionState(); +} + +class _LevelSelectionState extends State<LevelSelection> { + String? stepmaniaCoursesPath; + List<FileSystemEntity> stepmaniaCoursesFolders = []; + + @override + void initState() { + super.initState(); + loadFolderPath(); + } + + Future<void> loadFolderPath() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String? stepmaniaCoursesPathSetting = + prefs.getString('stepmania_courses'); + + if (stepmaniaCoursesPathSetting == null) return; + setState(() { + stepmaniaCoursesPath = stepmaniaCoursesPathSetting; + }); + setState(() async { + stepmaniaCoursesFolders = + await listFilesAndFolders(stepmaniaCoursesPathSetting); + }); + } + + Future<void> selectFolder() async { + String? selectedFolder = await FilePicker.platform.getDirectoryPath(); - final List<String> _coverArtList = [ - "https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg", - "https://cdn.pixabay.com/photo/2020/05/19/13/35/cartoon-5190860_960_720.jpg", - "https://cdn.pixabay.com/photo/2020/10/23/17/52/fox-5679446_960_720.png", - ]; + if (selectedFolder != null) { + // Save the selected folder path + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('stepmania_courses', selectedFolder); + + loadFolderPath(); + } + } + + Future<List<FileSystemEntity>> listFilesAndFolders( + String directoryPath) async { + final directory = Directory(directoryPath); + try { + // List all files and folders in the directory + return directory + .listSync() + .where((entity) => FileSystemEntity.isDirectorySync(entity.path)) + .toList(); + } catch (e) { + print("Error reading directory: $e"); + return []; + } + } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Sense the Rhythm')), - body: ListView.separated( - itemCount: _musicList.length, - separatorBuilder: (BuildContext context, int index) => const Divider(), - itemBuilder: (context, index) { - return ListTile( - leading: Image.network(_coverArtList[index]), - trailing: Icon(Icons.play_arrow), - title: Text('Track ${index + 1}'), - subtitle: Text('3:45'), - onTap: () => Navigator.push(context, - MaterialPageRoute(builder: (BuildContext context) => Level())), + body: Builder(builder: (context) { + if (stepmaniaCoursesPath == null) { + return Text('Add a Directory with Stepmania Songs on \'+\''); + } else if (stepmaniaCoursesFolders.isEmpty) { + return Text( + 'Folder empty. Add Stepmania Songs to Folder or select a different folder on \'+\''); + } else { + return ListView.separated( + itemCount: stepmaniaCoursesFolders.length, + separatorBuilder: (BuildContext context, int index) => + const Divider(), + itemBuilder: (context, index) { + String thumbnailPath = + Directory(stepmaniaCoursesFolders[index].path) + .listSync() + .firstWhere((file) => file.path.toLowerCase().endsWith('banner.png'), + orElse: () => File('')) + .path; + return ListTile( + leading: Image.file(File(thumbnailPath)), + trailing: Icon(Icons.play_arrow), + title: + Text(stepmaniaCoursesFolders[index].path.split('/').last), + subtitle: Text('3:45'), + onTap: () => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => Level())), + ); + }, ); - }, - ), - floatingActionButton: - FloatingActionButton(onPressed: () => {}, child: Icon(Icons.add)), + } + }), + floatingActionButton: FloatingActionButton( + onPressed: () => {selectFolder()}, child: Icon(Icons.add)), ); } } diff --git a/pubspec.lock b/pubspec.lock index 538c560..2dcd104 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" cupertino_icons: dependency: "direct main" description: @@ -57,6 +65,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: c2376a6aae82358a9f9ccdd7d1f4006d08faa39a2767cce01031d9f593a8bd3b + url: "https://pub.dev" + source: hosted + version: "8.1.6" flutter: dependency: "direct main" description: flutter @@ -70,11 +102,24 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "615a505aef59b151b46bbeef55b36ce2b6ed299d160c51d84281946f0aa0ce0e" + url: "https://pub.dev" + source: hosted + version: "2.0.24" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" leak_tracker: dependency: transitive description: @@ -139,6 +184,102 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "3c7e73920c694a436afaf65ab60ce3453d91f84208d761fbd83fc21182134d93" + url: "https://pub.dev" + source: hosted + version: "2.3.4" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -208,6 +349,30 @@ packages: url: "https://pub.dev" source: hosted version: "14.3.0" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69" + url: "https://pub.dev" + source: hosted + version: "5.9.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" sdks: dart: ">=3.6.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 00137d4..b364c4c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,89 +1,24 @@ name: sense_the_rhythm description: "A new Flutter project." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. version: 1.0.0+1 environment: sdk: ^3.6.0 -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + shared_preferences: ^2.3.4 + file_picker: ^8.1.6 dev_dependencies: flutter_test: sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. flutter_lints: ^5.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package |