mirror of
https://github.com/johrpan/musicus_mobile.git
synced 2025-10-26 10:47:25 +01:00
mobile: Check server errors in editors
This commit is contained in:
parent
00c31296e5
commit
9d4554b67f
6 changed files with 247 additions and 91 deletions
|
|
@ -25,6 +25,13 @@ class App extends StatelessWidget {
|
||||||
primary: Colors.amber,
|
primary: Colors.amber,
|
||||||
secondary: Colors.amber,
|
secondary: Colors.amber,
|
||||||
),
|
),
|
||||||
|
snackBarTheme: SnackBarThemeData(
|
||||||
|
backgroundColor: Colors.grey[800],
|
||||||
|
contentTextStyle: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
),
|
||||||
fontFamily: 'Libertinus Sans',
|
fontFamily: 'Libertinus Sans',
|
||||||
),
|
),
|
||||||
home: Builder(
|
home: Builder(
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ class EnsembleEditor extends StatefulWidget {
|
||||||
class _EnsembleEditorState extends State<EnsembleEditor> {
|
class _EnsembleEditorState extends State<EnsembleEditor> {
|
||||||
final nameController = TextEditingController();
|
final nameController = TextEditingController();
|
||||||
|
|
||||||
|
bool uploading = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -34,18 +36,46 @@ class _EnsembleEditorState extends State<EnsembleEditor> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Ensemble'),
|
title: Text('Ensemble'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
uploading
|
||||||
child: Text('DONE'),
|
? Padding(
|
||||||
onPressed: () async {
|
padding: const EdgeInsets.all(16.0),
|
||||||
final ensemble = Ensemble(
|
child: Center(
|
||||||
id: widget.ensemble?.id ?? generateId(),
|
child: SizedBox(
|
||||||
name: nameController.text,
|
width: 24.0,
|
||||||
);
|
height: 24.0,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: FlatButton(
|
||||||
|
child: Text('DONE'),
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
uploading = true;
|
||||||
|
});
|
||||||
|
|
||||||
await backend.client.putEnsemble(ensemble);
|
final ensemble = Ensemble(
|
||||||
Navigator.pop(context, ensemble);
|
id: widget.ensemble?.id ?? generateId(),
|
||||||
},
|
name: nameController.text,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
final success = await backend.client.putEnsemble(ensemble);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
uploading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
Navigator.pop(context, ensemble);
|
||||||
|
} else {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Failed to upload'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ class InstrumentEditor extends StatefulWidget {
|
||||||
class _InstrumentEditorState extends State<InstrumentEditor> {
|
class _InstrumentEditorState extends State<InstrumentEditor> {
|
||||||
final nameController = TextEditingController();
|
final nameController = TextEditingController();
|
||||||
|
|
||||||
|
bool uploading = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -34,18 +36,47 @@ class _InstrumentEditorState extends State<InstrumentEditor> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Instrument/Role'),
|
title: Text('Instrument/Role'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
uploading
|
||||||
child: Text('DONE'),
|
? Padding(
|
||||||
onPressed: () async {
|
padding: const EdgeInsets.all(16.0),
|
||||||
final instrument = Instrument(
|
child: Center(
|
||||||
id: widget.instrument?.id ?? generateId(),
|
child: SizedBox(
|
||||||
name: nameController.text,
|
width: 24.0,
|
||||||
);
|
height: 24.0,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: FlatButton(
|
||||||
|
child: Text('DONE'),
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
uploading = true;
|
||||||
|
});
|
||||||
|
|
||||||
await backend.client.putInstrument(instrument);
|
final instrument = Instrument(
|
||||||
Navigator.pop(context, instrument);
|
id: widget.instrument?.id ?? generateId(),
|
||||||
},
|
name: nameController.text,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
final success =
|
||||||
|
await backend.client.putInstrument(instrument);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
uploading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
Navigator.pop(context, instrument);
|
||||||
|
} else {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Failed to upload'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ class _PersonEditorState extends State<PersonEditor> {
|
||||||
final firstNameController = TextEditingController();
|
final firstNameController = TextEditingController();
|
||||||
final lastNameController = TextEditingController();
|
final lastNameController = TextEditingController();
|
||||||
|
|
||||||
|
bool uploading = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -36,19 +38,47 @@ class _PersonEditorState extends State<PersonEditor> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Person'),
|
title: Text('Person'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
uploading
|
||||||
child: Text('DONE'),
|
? Padding(
|
||||||
onPressed: () async {
|
padding: const EdgeInsets.all(16.0),
|
||||||
final person = Person(
|
child: Center(
|
||||||
id: widget.person?.id ?? generateId(),
|
child: SizedBox(
|
||||||
firstName: firstNameController.text,
|
width: 24.0,
|
||||||
lastName: lastNameController.text,
|
height: 24.0,
|
||||||
);
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: FlatButton(
|
||||||
|
child: Text('DONE'),
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
uploading = true;
|
||||||
|
});
|
||||||
|
|
||||||
await backend.client.putPerson(person);
|
final person = Person(
|
||||||
Navigator.pop(context, person);
|
id: widget.person?.id ?? generateId(),
|
||||||
},
|
firstName: firstNameController.text,
|
||||||
),
|
lastName: lastNameController.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
final success = await backend.client.putPerson(person);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
uploading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
Navigator.pop(context, person);
|
||||||
|
} else {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Failed to upload'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import '../selectors/work.dart';
|
||||||
/// navigator as a [RecordingSelectorResult] object.
|
/// navigator as a [RecordingSelectorResult] object.
|
||||||
class RecordingEditor extends StatefulWidget {
|
class RecordingEditor extends StatefulWidget {
|
||||||
/// The recording to edit.
|
/// The recording to edit.
|
||||||
///
|
///
|
||||||
/// If this is null, a new recording will be created.
|
/// If this is null, a new recording will be created.
|
||||||
final RecordingInfo recordingInfo;
|
final RecordingInfo recordingInfo;
|
||||||
|
|
||||||
|
|
@ -27,6 +27,7 @@ class RecordingEditor extends StatefulWidget {
|
||||||
class _RecordingEditorState extends State<RecordingEditor> {
|
class _RecordingEditorState extends State<RecordingEditor> {
|
||||||
final commentController = TextEditingController();
|
final commentController = TextEditingController();
|
||||||
|
|
||||||
|
bool uploading = false;
|
||||||
WorkInfo workInfo;
|
WorkInfo workInfo;
|
||||||
List<PerformanceInfo> performanceInfos = [];
|
List<PerformanceInfo> performanceInfos = [];
|
||||||
|
|
||||||
|
|
@ -103,29 +104,58 @@ class _RecordingEditorState extends State<RecordingEditor> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Recording'),
|
title: Text('Recording'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
uploading
|
||||||
child: Text('DONE'),
|
? Padding(
|
||||||
onPressed: () async {
|
padding: const EdgeInsets.all(16.0),
|
||||||
final recordingInfo = RecordingInfo(
|
child: Center(
|
||||||
recording: Recording(
|
child: SizedBox(
|
||||||
id: widget?.recordingInfo?.recording?.id ?? generateId(),
|
width: 24.0,
|
||||||
work: workInfo.work.id,
|
height: 24.0,
|
||||||
comment: commentController.text,
|
child: CircularProgressIndicator(
|
||||||
),
|
strokeWidth: 2.0,
|
||||||
performances: performanceInfos,
|
),
|
||||||
);
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: FlatButton(
|
||||||
|
child: Text('DONE'),
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
uploading = true;
|
||||||
|
});
|
||||||
|
|
||||||
await backend.client.putRecording(recordingInfo);
|
final recordingInfo = RecordingInfo(
|
||||||
|
recording: Recording(
|
||||||
|
id: widget?.recordingInfo?.recording?.id ??
|
||||||
|
generateId(),
|
||||||
|
work: workInfo.work.id,
|
||||||
|
comment: commentController.text,
|
||||||
|
),
|
||||||
|
performances: performanceInfos,
|
||||||
|
);
|
||||||
|
|
||||||
Navigator.pop(
|
final success =
|
||||||
context,
|
await backend.client.putRecording(recordingInfo);
|
||||||
RecordingSelectorResult(
|
|
||||||
workInfo: workInfo,
|
setState(() {
|
||||||
recordingInfo: recordingInfo,
|
uploading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
Navigator.pop(
|
||||||
|
context,
|
||||||
|
RecordingSelectorResult(
|
||||||
|
workInfo: workInfo,
|
||||||
|
recordingInfo: recordingInfo,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Failed to upload'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,7 @@ class WorkEditor extends StatefulWidget {
|
||||||
class _WorkEditorState extends State<WorkEditor> {
|
class _WorkEditorState extends State<WorkEditor> {
|
||||||
final titleController = TextEditingController();
|
final titleController = TextEditingController();
|
||||||
|
|
||||||
|
bool uploading = false;
|
||||||
Person composer;
|
Person composer;
|
||||||
List<Instrument> instruments = [];
|
List<Instrument> instruments = [];
|
||||||
List<PartData> parts = [];
|
List<PartData> parts = [];
|
||||||
|
|
@ -249,45 +250,72 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Work'),
|
title: Text('Work'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
uploading
|
||||||
child: Text('DONE'),
|
? Padding(
|
||||||
onPressed: () async {
|
padding: const EdgeInsets.all(16.0),
|
||||||
final workId = widget?.workInfo?.work?.id ?? generateId();
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
List<PartInfo> partInfos = [];
|
width: 24.0,
|
||||||
for (var i = 0; i < parts.length; i++) {
|
height: 24.0,
|
||||||
final part = parts[i];
|
child: CircularProgressIndicator(
|
||||||
partInfos.add(PartInfo(
|
strokeWidth: 2.0,
|
||||||
work: Work(
|
),
|
||||||
id: generateId(),
|
),
|
||||||
title: part.titleController.text,
|
|
||||||
composer: part.composer?.id,
|
|
||||||
partOf: workId,
|
|
||||||
partIndex: i,
|
|
||||||
),
|
),
|
||||||
instruments: part.instruments,
|
)
|
||||||
composer: part.composer,
|
: FlatButton(
|
||||||
));
|
child: Text('DONE'),
|
||||||
}
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
uploading = true;
|
||||||
|
});
|
||||||
|
|
||||||
final workInfo = WorkInfo(
|
final workId = widget?.workInfo?.work?.id ?? generateId();
|
||||||
work: Work(
|
|
||||||
id: workId,
|
List<PartInfo> partInfos = [];
|
||||||
title: titleController.text,
|
for (var i = 0; i < parts.length; i++) {
|
||||||
composer: composer?.id,
|
final part = parts[i];
|
||||||
|
partInfos.add(PartInfo(
|
||||||
|
work: Work(
|
||||||
|
id: generateId(),
|
||||||
|
title: part.titleController.text,
|
||||||
|
composer: part.composer?.id,
|
||||||
|
partOf: workId,
|
||||||
|
partIndex: i,
|
||||||
|
),
|
||||||
|
instruments: part.instruments,
|
||||||
|
composer: part.composer,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
final workInfo = WorkInfo(
|
||||||
|
work: Work(
|
||||||
|
id: workId,
|
||||||
|
title: titleController.text,
|
||||||
|
composer: composer?.id,
|
||||||
|
),
|
||||||
|
instruments: instruments,
|
||||||
|
// TODO: Theoretically, this should include all composers
|
||||||
|
// from the parts.
|
||||||
|
composers: [composer],
|
||||||
|
parts: partInfos,
|
||||||
|
);
|
||||||
|
|
||||||
|
final success = await backend.client.putWork(workInfo);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
uploading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
Navigator.pop(context, workInfo);
|
||||||
|
} else {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Failed to upload'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
instruments: instruments,
|
|
||||||
// TODO: Theoretically, this should include all composers from
|
|
||||||
// the parts.
|
|
||||||
composers: [composer],
|
|
||||||
parts: partInfos,
|
|
||||||
);
|
|
||||||
|
|
||||||
await backend.client.putWork(workInfo);
|
|
||||||
|
|
||||||
Navigator.pop(context, workInfo);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: ReorderableListView(
|
body: ReorderableListView(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue