mirror of
https://github.com/johrpan/musicus_mobile.git
synced 2025-10-26 18:57:25 +01:00
Remove support for nested work parts
We will add a way to create sections as a much simpler replacement in the future.
This commit is contained in:
parent
f7f109179f
commit
18bc8eb982
3 changed files with 30 additions and 143 deletions
|
|
@ -16,8 +16,7 @@ CREATE TABLE works (
|
||||||
composer INTEGER REFERENCES persons(id),
|
composer INTEGER REFERENCES persons(id),
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
part_of INTEGER REFERENCES works(id) ON DELETE CASCADE,
|
part_of INTEGER REFERENCES works(id) ON DELETE CASCADE,
|
||||||
part_index INTEGER,
|
part_index INTEGER
|
||||||
part_level INTEGER
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE instrumentations (
|
CREATE TABLE instrumentations (
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,11 @@ import '../selectors/person.dart';
|
||||||
class PartData {
|
class PartData {
|
||||||
final titleController = TextEditingController();
|
final titleController = TextEditingController();
|
||||||
|
|
||||||
int level;
|
|
||||||
Person composer;
|
Person composer;
|
||||||
List<Instrument> instruments;
|
List<Instrument> instruments;
|
||||||
|
|
||||||
PartData({
|
PartData({
|
||||||
String title,
|
String title,
|
||||||
this.level = 0,
|
|
||||||
this.composer,
|
this.composer,
|
||||||
this.instruments = const [],
|
this.instruments = const [],
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -108,17 +106,13 @@ class WorkProperties extends StatelessWidget {
|
||||||
class PartTile extends StatefulWidget {
|
class PartTile extends StatefulWidget {
|
||||||
final PartData part;
|
final PartData part;
|
||||||
final void Function() onMore;
|
final void Function() onMore;
|
||||||
final void Function() onAdd;
|
|
||||||
final void Function() onDelete;
|
final void Function() onDelete;
|
||||||
final void Function(int levels) onMove;
|
|
||||||
|
|
||||||
PartTile({
|
PartTile({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.part,
|
@required this.part,
|
||||||
@required this.onMore,
|
@required this.onMore,
|
||||||
@required this.onAdd,
|
|
||||||
@required this.onDelete,
|
@required this.onDelete,
|
||||||
@required this.onMove,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -126,72 +120,34 @@ class PartTile extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PartTileState extends State<PartTile> {
|
class _PartTileState extends State<PartTile> {
|
||||||
static const unit = 16.0;
|
|
||||||
static const iconShrink = 4.0;
|
|
||||||
|
|
||||||
double dragStart;
|
|
||||||
double dragDelta = 0.0;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final padding = widget.part.level * unit + dragDelta;
|
return Row(
|
||||||
final iconSize = 24 - widget.part.level * iconShrink;
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
return GestureDetector(
|
padding: const EdgeInsets.only(left: 16.0, right: 8.0),
|
||||||
child: Padding(
|
child: Icon(
|
||||||
padding: EdgeInsets.only(left: padding > 0.0 ? padding : 0.0),
|
Icons.drag_handle,
|
||||||
child: Row(
|
),
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 16.0, right: 8.0),
|
|
||||||
child: Icon(
|
|
||||||
Icons.drag_handle,
|
|
||||||
size: iconSize,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
controller: widget.part.titleController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: InputBorder.none,
|
|
||||||
hintText: 'Part title',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.more_horiz),
|
|
||||||
iconSize: iconSize,
|
|
||||||
onPressed: widget.onMore,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
iconSize: iconSize,
|
|
||||||
onPressed: widget.onAdd,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.delete),
|
|
||||||
iconSize: iconSize,
|
|
||||||
onPressed: widget.onDelete,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
onHorizontalDragStart: (details) {
|
child: TextField(
|
||||||
dragStart = details.localPosition.dx;
|
controller: widget.part.titleController,
|
||||||
},
|
decoration: InputDecoration(
|
||||||
onHorizontalDragUpdate: (details) {
|
border: InputBorder.none,
|
||||||
setState(() {
|
hintText: 'Part title',
|
||||||
dragDelta = details.localPosition.dx - dragStart;
|
),
|
||||||
});
|
),
|
||||||
},
|
),
|
||||||
onHorizontalDragEnd: (details) {
|
IconButton(
|
||||||
if (dragDelta.abs() >= unit) {
|
icon: const Icon(Icons.more_horiz),
|
||||||
widget.onMove((dragDelta / unit).round());
|
onPressed: widget.onMore,
|
||||||
}
|
),
|
||||||
setState(() {
|
IconButton(
|
||||||
dragDelta = 0.0;
|
icon: const Icon(Icons.delete),
|
||||||
});
|
onPressed: widget.onDelete,
|
||||||
},
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +232,6 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
parts.add(PartData(
|
parts.add(PartData(
|
||||||
title: dbPart.title,
|
title: dbPart.title,
|
||||||
composer: partComposer,
|
composer: partComposer,
|
||||||
level: dbPart.partLevel,
|
|
||||||
instruments: partInstruments,
|
instruments: partInstruments,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
@ -285,17 +240,6 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanLevels() {
|
|
||||||
var previousLevel = -1;
|
|
||||||
for (var i = 0; i < parts.length; i++) {
|
|
||||||
final part = parts[i];
|
|
||||||
if (part.level > previousLevel + 1) {
|
|
||||||
part.level = previousLevel + 1;
|
|
||||||
}
|
|
||||||
previousLevel = part.level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final List<Widget> partTiles = [];
|
final List<Widget> partTiles = [];
|
||||||
|
|
@ -334,30 +278,11 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onAdd: () {
|
|
||||||
setState(() {
|
|
||||||
parts.insert(i + 1, PartData(level: part.level + 1));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onDelete: () {
|
onDelete: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
parts.removeAt(i);
|
parts.removeAt(i);
|
||||||
cleanLevels();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onMove: (levels) {
|
|
||||||
if (levels > 0 && i > 0 && parts[i - 1].level >= part.level) {
|
|
||||||
setState(() {
|
|
||||||
part.level++;
|
|
||||||
});
|
|
||||||
} else if (levels < 0) {
|
|
||||||
final newLevel = part.level + levels;
|
|
||||||
setState(() {
|
|
||||||
part.level = newLevel > 0 ? newLevel : 0;
|
|
||||||
cleanLevels();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,7 +314,6 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
composer: part.composer?.id,
|
composer: part.composer?.id,
|
||||||
partOf: workId,
|
partOf: workId,
|
||||||
partIndex: i,
|
partIndex: i,
|
||||||
partLevel: part.level,
|
|
||||||
),
|
),
|
||||||
instrumentIds: part.instruments.map((i) => i.id).toList(),
|
instrumentIds: part.instruments.map((i) => i.id).toList(),
|
||||||
));
|
));
|
||||||
|
|
@ -425,7 +349,7 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
padding: const EdgeInsets.only(left: 16.0, top: 16.0),
|
padding: const EdgeInsets.only(left: 16.0, top: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Parts',
|
'Parts',
|
||||||
style: Theme.of(context).textTheme.subhead,
|
style: Theme.of(context).textTheme.subtitle1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -437,8 +361,6 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
final newIndex = i2 > i1 ? i2 - 1 : i2;
|
final newIndex = i2 > i1 ? i2 - 1 : i2;
|
||||||
|
|
||||||
parts.insert(newIndex, part);
|
parts.insert(newIndex, part);
|
||||||
|
|
||||||
cleanLevels();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -447,7 +369,7 @@ class _WorkEditorState extends State<WorkEditor> {
|
||||||
label: Text('Add part'),
|
label: Text('Add part'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
parts.add(PartData(level: 0));
|
parts.add(PartData());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ class ProgramTile extends StatelessWidget {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
for (final part in item.workParts)
|
for (final part in item.workParts)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 8.0 + part.partLevel * 8.0,
|
left: 8.0,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
part.title,
|
part.title,
|
||||||
|
|
@ -162,10 +162,6 @@ class _ProgramScreenState extends State<ProgramScreen> {
|
||||||
// from the database again.
|
// from the database again.
|
||||||
int lastWorkId;
|
int lastWorkId;
|
||||||
|
|
||||||
// We need to keep track of the last work part to be able to check for the
|
|
||||||
// parent work parts that were left out between the two last tracks.
|
|
||||||
int lastPartId;
|
|
||||||
|
|
||||||
// This will always contain the parts of the current work.
|
// This will always contain the parts of the current work.
|
||||||
List<Work> workParts = [];
|
List<Work> workParts = [];
|
||||||
|
|
||||||
|
|
@ -193,40 +189,10 @@ class _ProgramScreenState extends State<ProgramScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
lastWorkId = recording.work;
|
lastWorkId = recording.work;
|
||||||
lastPartId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Search for all parent work parts of [partId] starting from the part
|
|
||||||
/// with the ID [startId] and add them to the part list.
|
|
||||||
void addParentParts(int startId, int partId) {
|
|
||||||
final level = workParts[partId].partLevel;
|
|
||||||
final List<Work> parents = List.filled(level - 1, null);
|
|
||||||
|
|
||||||
for (var i = startId; i < partId; i++) {
|
|
||||||
final part = workParts[i];
|
|
||||||
if (part.partLevel < parents.length) {
|
|
||||||
parents[part.partLevel] = part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newWorkParts.addAll(parents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final partId in partIds) {
|
for (final partId in partIds) {
|
||||||
// We will need to include all parent work parts first, if there were
|
|
||||||
// work parts left out between the last two tracks or if the current
|
|
||||||
// work part comes before the previous one.
|
|
||||||
if (lastPartId != null) {
|
|
||||||
if (partIds.first > lastPartId + 1) {
|
|
||||||
addParentParts(lastPartId + 1, partId);
|
|
||||||
}
|
|
||||||
} else if (partIds.first > 0) {
|
|
||||||
addParentParts(0, partId);
|
|
||||||
}
|
|
||||||
|
|
||||||
newWorkParts.add(workParts[partId]);
|
newWorkParts.add(workParts[partId]);
|
||||||
|
|
||||||
lastPartId = partId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newItems.add(ProgramItem(
|
newItems.add(ProgramItem(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue