mirror of
https://github.com/johrpan/musicus_mobile.git
synced 2025-10-26 18:57:25 +01:00
Remove seperate role repesentation
The role and instrument tables have been merged into one (the instrument table). There are not that many roles that aren't instruments and it is much simpler to mange this way. The role editor and role selector have been removed and the instrument related UI parts have been modified accordingly.
This commit is contained in:
parent
24f2022930
commit
99e4711cfc
8 changed files with 57 additions and 172 deletions
|
|
@ -20,7 +20,7 @@ class WorkModel {
|
||||||
class PerformanceModel {
|
class PerformanceModel {
|
||||||
final Person person;
|
final Person person;
|
||||||
final Ensemble ensemble;
|
final Ensemble ensemble;
|
||||||
final Role role;
|
final Instrument role;
|
||||||
|
|
||||||
PerformanceModel({
|
PerformanceModel({
|
||||||
this.person,
|
this.person,
|
||||||
|
|
@ -42,10 +42,11 @@ class Database extends _$Database {
|
||||||
int get schemaVersion => 1;
|
int get schemaVersion => 1;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration =>
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
MigrationStrategy(beforeOpen: (details) async {
|
beforeOpen: (details) async {
|
||||||
await customStatement('PRAGMA foreign_keys = ON');
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> updatePerson(Person person) async {
|
Future<void> updatePerson(Person person) async {
|
||||||
await into(persons).insert(person, orReplace: true);
|
await into(persons).insert(person, orReplace: true);
|
||||||
|
|
@ -82,10 +83,6 @@ class Database extends _$Database {
|
||||||
await into(ensembles).insert(ensemble, orReplace: true);
|
await into(ensembles).insert(ensemble, orReplace: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateRole(Role role) async {
|
|
||||||
await into(roles).insert(role, orReplace: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> updateRecording(
|
Future<void> updateRecording(
|
||||||
Recording recording, List<PerformanceModel> models) async {
|
Recording recording, List<PerformanceModel> models) async {
|
||||||
await transaction(() async {
|
await transaction(() async {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ CREATE TABLE persons (
|
||||||
last_name TEXT NOT NULL
|
last_name TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- This represents real instruments as well as other roles that can be played
|
||||||
|
-- in a recording.
|
||||||
CREATE TABLE instruments (
|
CREATE TABLE instruments (
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
name TEXT NOT NULL
|
name TEXT NOT NULL
|
||||||
|
|
@ -28,11 +30,6 @@ CREATE TABLE ensembles (
|
||||||
name TEXT NOT NULL
|
name TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE roles (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE recordings (
|
CREATE TABLE recordings (
|
||||||
id INTEGER NOT NULL PRIMARY KEY,
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
work INTEGER REFERENCES works(id)
|
work INTEGER REFERENCES works(id)
|
||||||
|
|
@ -42,7 +39,7 @@ CREATE TABLE performances (
|
||||||
recording INTEGER NOT NULL REFERENCES recordings(id) ON DELETE CASCADE,
|
recording INTEGER NOT NULL REFERENCES recordings(id) ON DELETE CASCADE,
|
||||||
person INTEGER REFERENCES persons(id) ON DELETE CASCADE,
|
person INTEGER REFERENCES persons(id) ON DELETE CASCADE,
|
||||||
ensemble INTEGER REFERENCES ensembles(id) ON DELETE CASCADE,
|
ensemble INTEGER REFERENCES ensembles(id) ON DELETE CASCADE,
|
||||||
role INTEGER REFERENCES roles(id)
|
role INTEGER REFERENCES instruments(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
allPersons:
|
allPersons:
|
||||||
|
|
@ -84,12 +81,6 @@ SELECT * FROM ensembles ORDER BY name;
|
||||||
ensembleById:
|
ensembleById:
|
||||||
SELECT * FROM ensembles WHERE id = :id LIMIT 1;
|
SELECT * FROM ensembles WHERE id = :id LIMIT 1;
|
||||||
|
|
||||||
allRoles:
|
|
||||||
SELECT * FROM roles ORDER BY name;
|
|
||||||
|
|
||||||
roleById:
|
|
||||||
SELECT * FROM roles WHERE id = :id LIMIT 1;
|
|
||||||
|
|
||||||
recordingById:
|
recordingById:
|
||||||
SELECT * FROM recordings WHERE id = :id;
|
SELECT * FROM recordings WHERE id = :id;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class _InstrumentEditorState extends State<InstrumentEditor> {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Instrument'),
|
title: Text('Instrument/Role'),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text('DONE'),
|
child: Text('DONE'),
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../backend.dart';
|
|
||||||
import '../database.dart';
|
|
||||||
|
|
||||||
class RoleEditor extends StatefulWidget {
|
|
||||||
final Role role;
|
|
||||||
|
|
||||||
RoleEditor({
|
|
||||||
this.role,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
_RoleEditorState createState() => _RoleEditorState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _RoleEditorState extends State<RoleEditor> {
|
|
||||||
final nameController = TextEditingController();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
if (widget.role != null) {
|
|
||||||
nameController.text = widget.role.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final backend = Backend.of(context);
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Role'),
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
child: Text('DONE'),
|
|
||||||
onPressed: () async {
|
|
||||||
final role = Role(
|
|
||||||
id: widget.role?.id ?? generateId(),
|
|
||||||
name: nameController.text,
|
|
||||||
);
|
|
||||||
|
|
||||||
await backend.db.updateRole(role);
|
|
||||||
Navigator.pop(context, role);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: ListView(
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: TextField(
|
|
||||||
controller: nameController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'Name',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -89,6 +89,7 @@ class WorkProperties extends StatelessWidget {
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => InstrumentsSelector(
|
builder: (context) => InstrumentsSelector(
|
||||||
|
multiple: true,
|
||||||
selection: instruments,
|
selection: instruments,
|
||||||
),
|
),
|
||||||
fullscreenDialog: true,
|
fullscreenDialog: true,
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,11 @@ import '../database.dart';
|
||||||
import '../editors/instrument.dart';
|
import '../editors/instrument.dart';
|
||||||
|
|
||||||
class InstrumentsSelector extends StatefulWidget {
|
class InstrumentsSelector extends StatefulWidget {
|
||||||
|
final bool multiple;
|
||||||
final List<Instrument> selection;
|
final List<Instrument> selection;
|
||||||
|
|
||||||
InstrumentsSelector({
|
InstrumentsSelector({
|
||||||
|
this.multiple = false,
|
||||||
this.selection,
|
this.selection,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -33,13 +35,15 @@ class _InstrumentsSelectorState extends State<InstrumentsSelector> {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('Select instruments'),
|
title: Text(widget.multiple ? 'Select instruments/roles' : 'Select instrument/role'),
|
||||||
actions: <Widget>[
|
actions: widget.multiple
|
||||||
|
? <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text('DONE'),
|
child: Text('DONE'),
|
||||||
onPressed: () => Navigator.pop(context, selection.toList()),
|
onPressed: () => Navigator.pop(context, selection.toList()),
|
||||||
),
|
),
|
||||||
],
|
]
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
body: StreamBuilder(
|
body: StreamBuilder(
|
||||||
stream: backend.db.allInstruments().watch(),
|
stream: backend.db.allInstruments().watch(),
|
||||||
|
|
@ -50,6 +54,7 @@ class _InstrumentsSelectorState extends State<InstrumentsSelector> {
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final instrument = snapshot.data[index];
|
final instrument = snapshot.data[index];
|
||||||
|
|
||||||
|
if (widget.multiple) {
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
title: Text(instrument.name),
|
title: Text(instrument.name),
|
||||||
value: selection.contains(instrument),
|
value: selection.contains(instrument),
|
||||||
|
|
@ -64,6 +69,12 @@ class _InstrumentsSelectorState extends State<InstrumentsSelector> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(instrument.name),
|
||||||
|
onTap: () => Navigator.pop(context, instrument),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -82,9 +93,13 @@ class _InstrumentsSelectorState extends State<InstrumentsSelector> {
|
||||||
));
|
));
|
||||||
|
|
||||||
if (instrument != null) {
|
if (instrument != null) {
|
||||||
|
if (widget.multiple) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selection.add(instrument);
|
selection.add(instrument);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
Navigator.pop(context, instrument);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,17 @@ import 'package:flutter/material.dart';
|
||||||
import '../backend.dart';
|
import '../backend.dart';
|
||||||
import '../database.dart';
|
import '../database.dart';
|
||||||
import '../editors/person.dart';
|
import '../editors/person.dart';
|
||||||
import '../selectors/role.dart';
|
|
||||||
|
import 'instruments.dart';
|
||||||
|
|
||||||
// TODO: Allow selecting and adding ensembles.
|
// TODO: Allow selecting and adding ensembles.
|
||||||
// TODO: Allow selecting instruments as roles.
|
|
||||||
class PerformerSelector extends StatefulWidget {
|
class PerformerSelector extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_PerformerSelectorState createState() => _PerformerSelectorState();
|
_PerformerSelectorState createState() => _PerformerSelectorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PerformerSelectorState extends State<PerformerSelector> {
|
class _PerformerSelectorState extends State<PerformerSelector> {
|
||||||
Role role;
|
Instrument role;
|
||||||
Person person;
|
Person person;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -41,9 +41,9 @@ class _PerformerSelectorState extends State<PerformerSelector> {
|
||||||
Material(
|
Material(
|
||||||
elevation: 2.0,
|
elevation: 2.0,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text('Role'),
|
title: Text('Instrument/Role'),
|
||||||
subtitle:
|
subtitle:
|
||||||
Text(role != null ? role.name : 'Select role or instrument'),
|
Text(role != null ? role.name : 'Select instrument/role'),
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|
@ -53,10 +53,10 @@ class _PerformerSelectorState extends State<PerformerSelector> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final Role newRole = await Navigator.push(
|
final Instrument newRole = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => RoleSelector(),
|
builder: (context) => InstrumentsSelector(),
|
||||||
fullscreenDialog: true,
|
fullscreenDialog: true,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../backend.dart';
|
|
||||||
import '../database.dart';
|
|
||||||
import '../editors/role.dart';
|
|
||||||
|
|
||||||
class RoleSelector extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final backend = Backend.of(context);
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Select role'),
|
|
||||||
),
|
|
||||||
body: StreamBuilder<List<Role>>(
|
|
||||||
stream: backend.db.allRoles().watch(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: snapshot.data.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final role = snapshot.data[index];
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
title: Text(role.name),
|
|
||||||
onTap: () => Navigator.pop(context, role),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
child: const Icon(Icons.add),
|
|
||||||
onPressed: () async {
|
|
||||||
final Role role = await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => RoleEditor(),
|
|
||||||
fullscreenDialog: true,
|
|
||||||
));
|
|
||||||
|
|
||||||
if (role != null) {
|
|
||||||
Navigator.pop(context, role);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue