2020-03-27 17:33:47 +01:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
2020-04-11 21:59:23 +02:00
|
|
|
import '../backend.dart';
|
2020-04-18 20:34:03 +02:00
|
|
|
import '../platform.dart';
|
2020-03-27 17:44:04 +01:00
|
|
|
|
2020-04-18 21:23:24 +02:00
|
|
|
/// Result of the user's interaction with the files selector.
|
|
|
|
|
///
|
|
|
|
|
/// This will be given back when popping the navigator.
|
|
|
|
|
class FilesSelectorResult {
|
|
|
|
|
/// Document ID of the parent directory of the selected files.
|
|
|
|
|
///
|
|
|
|
|
/// This will be null, if they are in the toplevel directory.
|
|
|
|
|
final String parentId;
|
|
|
|
|
|
|
|
|
|
/// Document IDs of the selected files.
|
|
|
|
|
final List<String> trackIds;
|
|
|
|
|
|
|
|
|
|
FilesSelectorResult(this.parentId, this.trackIds);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-11 21:59:23 +02:00
|
|
|
class FilesSelector extends StatefulWidget {
|
2020-03-27 17:33:47 +01:00
|
|
|
@override
|
|
|
|
|
_FilesSelectorState createState() => _FilesSelectorState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _FilesSelectorState extends State<FilesSelector> {
|
2020-04-11 21:59:23 +02:00
|
|
|
BackendState backend;
|
|
|
|
|
List<Document> history = [];
|
|
|
|
|
List<Document> children = [];
|
|
|
|
|
Set<String> selectedIds = {};
|
2020-03-27 17:33:47 +01:00
|
|
|
|
|
|
|
|
@override
|
2020-04-11 21:59:23 +02:00
|
|
|
void didChangeDependencies() {
|
|
|
|
|
super.didChangeDependencies();
|
|
|
|
|
|
|
|
|
|
backend = Backend.of(context);
|
|
|
|
|
loadChildren();
|
2020-03-27 17:33:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
return WillPopScope(
|
|
|
|
|
child: Scaffold(
|
|
|
|
|
appBar: AppBar(
|
|
|
|
|
title: Text('Choose files'),
|
2020-03-28 12:30:19 +01:00
|
|
|
leading: IconButton(
|
|
|
|
|
icon: const Icon(Icons.close),
|
|
|
|
|
onPressed: () {
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
),
|
2020-03-27 17:33:47 +01:00
|
|
|
actions: <Widget>[
|
|
|
|
|
FlatButton(
|
2020-04-11 21:59:23 +02:00
|
|
|
child: Text('DONE'),
|
2020-03-27 17:33:47 +01:00
|
|
|
onPressed: () {
|
2020-04-18 21:23:24 +02:00
|
|
|
Navigator.pop(
|
|
|
|
|
context,
|
|
|
|
|
FilesSelectorResult(
|
|
|
|
|
history.isNotEmpty ? history.last.id : null,
|
|
|
|
|
selectedIds.toList(),
|
|
|
|
|
),
|
|
|
|
|
);
|
2020-03-27 17:33:47 +01:00
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
body: Column(
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
Material(
|
|
|
|
|
elevation: 2.0,
|
|
|
|
|
child: ListTile(
|
2020-04-11 21:59:23 +02:00
|
|
|
leading: IconButton(
|
|
|
|
|
icon: const Icon(Icons.arrow_upward),
|
|
|
|
|
onPressed: history.isNotEmpty ? up : null,
|
|
|
|
|
),
|
|
|
|
|
title: Text(
|
|
|
|
|
history.isNotEmpty ? history.last.name : 'Music library'),
|
2020-03-27 17:33:47 +01:00
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
Expanded(
|
2020-04-11 21:59:23 +02:00
|
|
|
child: ListView.builder(
|
|
|
|
|
itemCount: children.length,
|
|
|
|
|
itemBuilder: (context, index) {
|
|
|
|
|
final document = children[index];
|
|
|
|
|
|
|
|
|
|
if (document.isDirectory) {
|
|
|
|
|
return ListTile(
|
|
|
|
|
leading: const Icon(Icons.folder),
|
|
|
|
|
title: Text(document.name),
|
|
|
|
|
onTap: () {
|
|
|
|
|
setState(() {
|
|
|
|
|
history.add(document);
|
|
|
|
|
});
|
|
|
|
|
loadChildren();
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return CheckboxListTile(
|
|
|
|
|
controlAffinity: ListTileControlAffinity.trailing,
|
|
|
|
|
secondary: const Icon(Icons.insert_drive_file),
|
|
|
|
|
title: Text(document.name),
|
|
|
|
|
value: selectedIds.contains(document.id),
|
|
|
|
|
onChanged: (selected) {
|
|
|
|
|
setState(() {
|
|
|
|
|
if (selected) {
|
|
|
|
|
selectedIds.add(document.id);
|
|
|
|
|
} else {
|
|
|
|
|
selectedIds.remove(document.id);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
),
|
2020-03-27 17:33:47 +01:00
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
2020-04-11 21:59:23 +02:00
|
|
|
onWillPop: () => Future.value(up()),
|
2020-03-27 17:33:47 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-11 21:59:23 +02:00
|
|
|
Future<void> loadChildren() async {
|
2020-03-27 17:33:47 +01:00
|
|
|
setState(() {
|
2020-04-11 21:59:23 +02:00
|
|
|
children = [];
|
2020-03-27 17:33:47 +01:00
|
|
|
});
|
|
|
|
|
|
2020-04-18 20:34:03 +02:00
|
|
|
final newChildren = await Platform.getChildren(
|
|
|
|
|
backend.musicLibraryUri, history.isNotEmpty ? history.last.id : null);
|
2020-04-11 21:59:23 +02:00
|
|
|
|
|
|
|
|
newChildren.sort((d1, d2) {
|
|
|
|
|
if (d1.isDirectory != d2.isDirectory) {
|
|
|
|
|
return d1.isDirectory ? -1 : 1;
|
2020-03-27 17:33:47 +01:00
|
|
|
} else {
|
2020-04-11 21:59:23 +02:00
|
|
|
return d1.name.compareTo(d2.name);
|
2020-03-27 17:33:47 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
setState(() {
|
2020-04-11 21:59:23 +02:00
|
|
|
children = newChildren;
|
2020-03-27 17:33:47 +01:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-11 21:59:23 +02:00
|
|
|
bool up() {
|
|
|
|
|
if (history.isNotEmpty) {
|
2020-03-27 17:33:47 +01:00
|
|
|
setState(() {
|
2020-04-11 21:59:23 +02:00
|
|
|
history.removeLast();
|
2020-03-27 17:33:47 +01:00
|
|
|
});
|
|
|
|
|
|
2020-04-11 21:59:23 +02:00
|
|
|
loadChildren();
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
return true;
|
2020-03-27 17:33:47 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|