2020-03-22 16:49:20 +01:00
|
|
|
import 'package:flutter/material.dart';
|
2020-04-24 22:41:52 +02:00
|
|
|
import 'package:musicus_database/musicus_database.dart';
|
2020-03-22 16:49:20 +01:00
|
|
|
|
|
|
|
|
import '../backend.dart';
|
2020-04-26 15:35:45 +02:00
|
|
|
import '../editors/performance.dart';
|
|
|
|
|
import '../selectors/recording.dart';
|
2020-03-22 16:49:20 +01:00
|
|
|
import '../selectors/work.dart';
|
|
|
|
|
|
2020-04-26 15:35:45 +02:00
|
|
|
/// Screen for editing a recording.
|
|
|
|
|
///
|
|
|
|
|
/// If the user has finished editing, the result will be returned using the
|
|
|
|
|
/// navigator as a [RecordingSelectorResult] object.
|
2020-03-22 16:49:20 +01:00
|
|
|
class RecordingEditor extends StatefulWidget {
|
2020-04-26 17:12:34 +02:00
|
|
|
/// The recording to edit.
|
2020-04-26 18:29:21 +02:00
|
|
|
///
|
2020-04-26 17:12:34 +02:00
|
|
|
/// If this is null, a new recording will be created.
|
|
|
|
|
final RecordingInfo recordingInfo;
|
2020-03-22 16:49:20 +01:00
|
|
|
|
|
|
|
|
RecordingEditor({
|
2020-04-26 17:12:34 +02:00
|
|
|
this.recordingInfo,
|
2020-03-22 16:49:20 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
_RecordingEditorState createState() => _RecordingEditorState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _RecordingEditorState extends State<RecordingEditor> {
|
2020-04-12 11:50:32 +02:00
|
|
|
final commentController = TextEditingController();
|
|
|
|
|
|
2020-04-26 18:29:21 +02:00
|
|
|
bool uploading = false;
|
2020-04-26 15:35:45 +02:00
|
|
|
WorkInfo workInfo;
|
|
|
|
|
List<PerformanceInfo> performanceInfos = [];
|
2020-03-22 16:49:20 +01:00
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
|
2020-04-26 17:12:34 +02:00
|
|
|
if (widget.recordingInfo != null) {
|
|
|
|
|
final backend = Backend.of(context);
|
|
|
|
|
|
|
|
|
|
() async {
|
|
|
|
|
workInfo = await backend.db.getWork(widget.recordingInfo.recording.id);
|
|
|
|
|
performanceInfos = List.from(widget.recordingInfo.performances);
|
|
|
|
|
}();
|
2020-03-22 16:49:20 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
final backend = Backend.of(context);
|
|
|
|
|
|
|
|
|
|
Future<void> selectWork() async {
|
2020-04-26 15:35:45 +02:00
|
|
|
final WorkInfo newWorkInfo = await Navigator.push(
|
2020-03-22 16:49:20 +01:00
|
|
|
context,
|
|
|
|
|
MaterialPageRoute(
|
|
|
|
|
builder: (context) => WorkSelector(),
|
|
|
|
|
fullscreenDialog: true,
|
|
|
|
|
));
|
|
|
|
|
|
2020-04-26 15:35:45 +02:00
|
|
|
if (newWorkInfo != null) {
|
2020-03-22 16:49:20 +01:00
|
|
|
setState(() {
|
2020-04-26 15:35:45 +02:00
|
|
|
workInfo = newWorkInfo;
|
2020-03-22 16:49:20 +01:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-26 15:35:45 +02:00
|
|
|
final List<Widget> performanceTiles = [];
|
|
|
|
|
for (var i = 0; i < performanceInfos.length; i++) {
|
|
|
|
|
final p = performanceInfos[i];
|
|
|
|
|
|
|
|
|
|
performanceTiles.add(ListTile(
|
|
|
|
|
title: Text(p.person != null
|
|
|
|
|
? '${p.person.firstName} ${p.person.lastName}'
|
|
|
|
|
: p.ensemble.name),
|
|
|
|
|
subtitle: p.role != null ? Text(p.role.name) : null,
|
|
|
|
|
trailing: IconButton(
|
|
|
|
|
icon: const Icon(Icons.delete),
|
|
|
|
|
onPressed: () {
|
|
|
|
|
setState(() {
|
|
|
|
|
performanceInfos.remove(p);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
onTap: () async {
|
|
|
|
|
final PerformanceInfo performanceInfo = await Navigator.push(
|
|
|
|
|
context,
|
|
|
|
|
MaterialPageRoute(
|
|
|
|
|
builder: (context) => PerformanceEditor(
|
|
|
|
|
performanceInfo: p,
|
|
|
|
|
),
|
|
|
|
|
fullscreenDialog: true,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
if (performanceInfo != null) {
|
|
|
|
|
setState(() {
|
|
|
|
|
performanceInfos[i] = performanceInfo;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 16:49:20 +01:00
|
|
|
return Scaffold(
|
|
|
|
|
appBar: AppBar(
|
|
|
|
|
title: Text('Recording'),
|
|
|
|
|
actions: <Widget>[
|
2020-04-26 18:29:21 +02:00
|
|
|
uploading
|
|
|
|
|
? Padding(
|
|
|
|
|
padding: const EdgeInsets.all(16.0),
|
|
|
|
|
child: Center(
|
|
|
|
|
child: SizedBox(
|
|
|
|
|
width: 24.0,
|
|
|
|
|
height: 24.0,
|
|
|
|
|
child: CircularProgressIndicator(
|
|
|
|
|
strokeWidth: 2.0,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
: FlatButton(
|
|
|
|
|
child: Text('DONE'),
|
|
|
|
|
onPressed: () async {
|
|
|
|
|
setState(() {
|
|
|
|
|
uploading = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
final recordingInfo = RecordingInfo(
|
|
|
|
|
recording: Recording(
|
|
|
|
|
id: widget?.recordingInfo?.recording?.id ??
|
|
|
|
|
generateId(),
|
|
|
|
|
work: workInfo.work.id,
|
|
|
|
|
comment: commentController.text,
|
|
|
|
|
),
|
|
|
|
|
performances: performanceInfos,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
final success =
|
|
|
|
|
await backend.client.putRecording(recordingInfo);
|
|
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
uploading = false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
Navigator.pop(
|
|
|
|
|
context,
|
|
|
|
|
RecordingSelectorResult(
|
|
|
|
|
workInfo: workInfo,
|
|
|
|
|
recordingInfo: recordingInfo,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
Scaffold.of(context).showSnackBar(SnackBar(
|
|
|
|
|
content: Text('Failed to upload'),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
},
|
2020-04-26 16:48:05 +02:00
|
|
|
),
|
2020-03-22 16:49:20 +01:00
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
body: ListView(
|
|
|
|
|
children: <Widget>[
|
2020-04-26 15:35:45 +02:00
|
|
|
workInfo != null
|
2020-04-06 11:29:55 +02:00
|
|
|
? ListTile(
|
2020-04-26 15:35:45 +02:00
|
|
|
title: Text(workInfo.work.title),
|
|
|
|
|
subtitle: Text(workInfo.composers
|
|
|
|
|
.map((p) => '${p.firstName} ${p.lastName}')
|
|
|
|
|
.join(', ')),
|
2020-04-25 10:36:19 +02:00
|
|
|
onTap: selectWork,
|
|
|
|
|
)
|
2020-03-22 16:49:20 +01:00
|
|
|
: ListTile(
|
|
|
|
|
title: Text('Work'),
|
|
|
|
|
subtitle: Text('Select work'),
|
|
|
|
|
onTap: selectWork,
|
|
|
|
|
),
|
2020-04-12 11:50:32 +02:00
|
|
|
Padding(
|
|
|
|
|
padding: const EdgeInsets.only(
|
|
|
|
|
left: 16.0,
|
|
|
|
|
right: 16.0,
|
|
|
|
|
top: 0.0,
|
|
|
|
|
bottom: 16.0,
|
|
|
|
|
),
|
|
|
|
|
child: TextField(
|
|
|
|
|
controller: commentController,
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
labelText: 'Comment',
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
2020-03-22 16:49:20 +01:00
|
|
|
ListTile(
|
|
|
|
|
title: Text('Performers'),
|
|
|
|
|
trailing: IconButton(
|
|
|
|
|
icon: const Icon(Icons.add),
|
|
|
|
|
onPressed: () async {
|
2020-04-26 15:35:45 +02:00
|
|
|
final PerformanceInfo model = await Navigator.push(
|
2020-03-22 16:49:20 +01:00
|
|
|
context,
|
|
|
|
|
MaterialPageRoute(
|
2020-04-26 15:35:45 +02:00
|
|
|
builder: (context) => PerformanceEditor(),
|
2020-03-22 16:49:20 +01:00
|
|
|
fullscreenDialog: true,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
if (model != null) {
|
|
|
|
|
setState(() {
|
2020-04-26 15:35:45 +02:00
|
|
|
performanceInfos.add(model);
|
2020-03-22 16:49:20 +01:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
),
|
2020-04-26 15:35:45 +02:00
|
|
|
...performanceTiles,
|
2020-03-22 16:49:20 +01:00
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|