151 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:io';
 | 
						|
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:permission_handler/permission_handler.dart';
 | 
						|
import 'package:shared_preferences/shared_preferences.dart';
 | 
						|
import 'package:file_picker/file_picker.dart';
 | 
						|
import 'package:sense_the_rhythm/utils/esense_input.dart';
 | 
						|
import 'package:sense_the_rhythm/utils/simfile.dart';
 | 
						|
import 'package:sense_the_rhythm/widgets/connection_status_button.dart';
 | 
						|
import 'package:sense_the_rhythm/widgets/level_list_entry.dart';
 | 
						|
 | 
						|
class LevelSelection extends StatefulWidget {
 | 
						|
  const LevelSelection({super.key});
 | 
						|
 | 
						|
  @override
 | 
						|
  State<LevelSelection> createState() => _LevelSelectionState();
 | 
						|
}
 | 
						|
 | 
						|
class _LevelSelectionState extends State<LevelSelection> {
 | 
						|
  String? stepmaniaCoursesPath;
 | 
						|
  List<Simfile> stepmaniaCoursesFolders = [];
 | 
						|
  List<Simfile> stepmaniaCoursesFoldersFiltered = [];
 | 
						|
  String searchString = '';
 | 
						|
 | 
						|
  @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;
 | 
						|
    List<Simfile> stepmaniaCoursesFoldersFuture =
 | 
						|
        await listFilesAndFolders(stepmaniaCoursesPathSetting);
 | 
						|
 | 
						|
    setState(() {
 | 
						|
      stepmaniaCoursesPath = stepmaniaCoursesPathSetting;
 | 
						|
      stepmaniaCoursesFolders = stepmaniaCoursesFoldersFuture;
 | 
						|
      stepmaniaCoursesFoldersFiltered = stepmaniaCoursesFoldersFuture;
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> selectFolder() async {
 | 
						|
    await Permission.manageExternalStorage.request();
 | 
						|
    String? selectedFolder = await FilePicker.platform.getDirectoryPath();
 | 
						|
 | 
						|
    if (selectedFolder != null) {
 | 
						|
      // Save the selected folder path
 | 
						|
      SharedPreferences prefs = await SharedPreferences.getInstance();
 | 
						|
      await prefs.setString('stepmania_courses', selectedFolder);
 | 
						|
 | 
						|
      loadFolderPath();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<List<Simfile>> listFilesAndFolders(String directoryPath) async {
 | 
						|
    final directory = Directory(directoryPath);
 | 
						|
    try {
 | 
						|
      // List all files and folders in the directory
 | 
						|
      List<Simfile> simfiles = directory
 | 
						|
          .listSync()
 | 
						|
          .where((entity) => FileSystemEntity.isDirectorySync(entity.path))
 | 
						|
          .map((entity) {
 | 
						|
        Simfile simfile = Simfile(entity.path);
 | 
						|
        simfile.load();
 | 
						|
        return simfile;
 | 
						|
      }).toList();
 | 
						|
      simfiles.sort((a, b) => a.tags['TITLE']!.compareTo(b.tags['TITLE']!));
 | 
						|
 | 
						|
      return simfiles;
 | 
						|
    } catch (e) {
 | 
						|
      print("Error reading directory: $e");
 | 
						|
      return [];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void filterLevels(String input) {
 | 
						|
    setState(() {
 | 
						|
      stepmaniaCoursesFoldersFiltered = stepmaniaCoursesFolders
 | 
						|
          .where((simfile) => simfile.tags["TITLE"]!
 | 
						|
              .toLowerCase()
 | 
						|
              .contains(input.toLowerCase()))
 | 
						|
          .toList();
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    return Scaffold(
 | 
						|
      appBar: AppBar(
 | 
						|
        title: const Text('Sense the Rhythm'),
 | 
						|
        actions: [
 | 
						|
          Padding(
 | 
						|
            padding: const EdgeInsets.symmetric(horizontal: 8.0),
 | 
						|
            child: ValueListenableBuilder(
 | 
						|
              valueListenable: ESenseInput.instance.deviceStatus,
 | 
						|
              builder:
 | 
						|
                  (BuildContext context, String deviceStatus, Widget? child) {
 | 
						|
                return ConnectionStatusButton(deviceStatus);
 | 
						|
              },
 | 
						|
            ),
 | 
						|
          )
 | 
						|
        ],
 | 
						|
      ),
 | 
						|
      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 Column(
 | 
						|
            children: [
 | 
						|
              Padding(
 | 
						|
                padding:
 | 
						|
                    const EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0),
 | 
						|
                child: TextField(
 | 
						|
                  onChanged: filterLevels,
 | 
						|
                  decoration: InputDecoration(
 | 
						|
                      // icon: Icon(Icons.search),
 | 
						|
                      hintText: 'Search'),
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
              Expanded(
 | 
						|
                child: ListView.separated(
 | 
						|
                  itemCount: stepmaniaCoursesFoldersFiltered.length,
 | 
						|
                  separatorBuilder: (BuildContext context, int index) =>
 | 
						|
                      const Divider(),
 | 
						|
                  itemBuilder: (context, index) {
 | 
						|
                    Simfile simfile = stepmaniaCoursesFoldersFiltered[index];
 | 
						|
                    return LevelListEntry(simfile: simfile);
 | 
						|
                  },
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
          );
 | 
						|
        }
 | 
						|
      }),
 | 
						|
      floatingActionButton: FloatingActionButton(
 | 
						|
          onPressed: () {
 | 
						|
            selectFolder();
 | 
						|
          },
 | 
						|
          child: Icon(Icons.add)),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |