mirror of
https://github.com/johrpan/musicus_mobile.git
synced 2025-10-26 18:57:25 +01:00
Rename top level directories
This commit is contained in:
parent
256bda1b72
commit
674ce19414
90 changed files with 0 additions and 0 deletions
59
mobile/lib/widgets/play_pause_button.dart
Normal file
59
mobile/lib/widgets/play_pause_button.dart
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../backend.dart';
|
||||
|
||||
class PlayPauseButton extends StatefulWidget {
|
||||
@override
|
||||
_PlayPauseButtonState createState() => _PlayPauseButtonState();
|
||||
}
|
||||
|
||||
class _PlayPauseButtonState extends State<PlayPauseButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
AnimationController playPauseAnimation;
|
||||
BackendState backend;
|
||||
StreamSubscription<bool> playingSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
playPauseAnimation = AnimationController(
|
||||
vsync: this,
|
||||
duration: Duration(milliseconds: 300),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
backend = Backend.of(context);
|
||||
playPauseAnimation.value = backend.player.playing.value ? 1.0 : 0.0;
|
||||
|
||||
if (playingSubscription != null) {
|
||||
playingSubscription.cancel();
|
||||
}
|
||||
|
||||
playingSubscription = backend.player.playing.listen((playing) =>
|
||||
playing ? playPauseAnimation.forward() : playPauseAnimation.reverse());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: AnimatedIcon(
|
||||
icon: AnimatedIcons.play_pause,
|
||||
progress: playPauseAnimation,
|
||||
),
|
||||
onPressed: backend.player.playPause,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
playingSubscription.cancel();
|
||||
}
|
||||
}
|
||||
83
mobile/lib/widgets/player_bar.dart
Normal file
83
mobile/lib/widgets/player_bar.dart
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:musicus/database.dart';
|
||||
|
||||
import '../backend.dart';
|
||||
import '../music_library.dart';
|
||||
import '../screens/program.dart';
|
||||
|
||||
import 'play_pause_button.dart';
|
||||
import 'texts.dart';
|
||||
|
||||
class PlayerBar extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
|
||||
return BottomAppBar(
|
||||
child: InkWell(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
StreamBuilder(
|
||||
stream: backend.player.normalizedPosition,
|
||||
builder: (context, snapshot) => LinearProgressIndicator(
|
||||
value: snapshot.data,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(Icons.keyboard_arrow_up),
|
||||
),
|
||||
Expanded(
|
||||
child: StreamBuilder<InternalTrack>(
|
||||
stream: backend.player.currentTrack,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data != null) {
|
||||
final recordingId = snapshot.data.track.recordingId;
|
||||
|
||||
return FutureBuilder<Recording>(
|
||||
future:
|
||||
backend.db.recordingById(recordingId).getSingle(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final workId = snapshot.data.work;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
DefaultTextStyle.merge(
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold),
|
||||
child: ComposersText(workId),
|
||||
),
|
||||
WorkText(workId),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
PlayPauseButton(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ProgramScreen(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
51
mobile/lib/widgets/recording_tile.dart
Normal file
51
mobile/lib/widgets/recording_tile.dart
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../backend.dart';
|
||||
import '../database.dart';
|
||||
|
||||
import 'texts.dart';
|
||||
|
||||
class RecordingTile extends StatelessWidget {
|
||||
final int recordingId;
|
||||
|
||||
RecordingTile({
|
||||
this.recordingId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
|
||||
return StreamBuilder<Recording>(
|
||||
stream: backend.db.recordingById(recordingId).watchSingle(),
|
||||
builder: (context, snapshot) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
if (snapshot.hasData) ...[
|
||||
DefaultTextStyle(
|
||||
style: textTheme.subtitle1,
|
||||
child: ComposersText(snapshot.data.work),
|
||||
),
|
||||
DefaultTextStyle(
|
||||
style: textTheme.headline6,
|
||||
child: WorkText(snapshot.data.work),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 4.0,
|
||||
),
|
||||
DefaultTextStyle(
|
||||
style: textTheme.bodyText1,
|
||||
child: PerformancesText(recordingId),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
153
mobile/lib/widgets/texts.dart
Normal file
153
mobile/lib/widgets/texts.dart
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../backend.dart';
|
||||
import '../database.dart';
|
||||
|
||||
class EnsembleText extends StatelessWidget {
|
||||
final int ensembleId;
|
||||
|
||||
EnsembleText(this.ensembleId);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
|
||||
return StreamBuilder<Ensemble>(
|
||||
stream: backend.db.ensembleById(ensembleId).watchSingle(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Text(snapshot.data.name);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PersonText extends StatelessWidget {
|
||||
final int personId;
|
||||
|
||||
PersonText(this.personId);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
|
||||
return StreamBuilder<Person>(
|
||||
stream: backend.db.personById(personId).watchSingle(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Text('${snapshot.data.firstName} ${snapshot.data.lastName}');
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PerformancesText extends StatefulWidget {
|
||||
final int recordingId;
|
||||
|
||||
PerformancesText(this.recordingId);
|
||||
|
||||
@override
|
||||
_PerformancesTextState createState() => _PerformancesTextState();
|
||||
}
|
||||
|
||||
class _PerformancesTextState extends State<PerformancesText> {
|
||||
BackendState backend;
|
||||
StreamSubscription<List<Performance>> performancesSubscription;
|
||||
String text = '...';
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
performancesSubscription?.cancel();
|
||||
backend = Backend.of(context);
|
||||
|
||||
performancesSubscription = backend.db
|
||||
.performancesByRecording(widget.recordingId)
|
||||
.watch()
|
||||
.listen((performances) async {
|
||||
final List<String> texts = [];
|
||||
|
||||
for (final performance in performances) {
|
||||
final buffer = StringBuffer();
|
||||
|
||||
if (performance.person != null) {
|
||||
final person =
|
||||
await backend.db.personById(performance.person).getSingle();
|
||||
buffer.write('${person.firstName} ${person.lastName}');
|
||||
} else if (performance.ensemble != null) {
|
||||
final ensemble =
|
||||
await backend.db.ensembleById(performance.ensemble).getSingle();
|
||||
buffer.write(ensemble.name);
|
||||
} else {
|
||||
buffer.write('Unknown');
|
||||
}
|
||||
|
||||
if (performance.role != null) {
|
||||
final role =
|
||||
await backend.db.instrumentById(performance.role).getSingle();
|
||||
buffer.write(' (${role.name})');
|
||||
}
|
||||
|
||||
texts.add(buffer.toString());
|
||||
}
|
||||
|
||||
setState(() {
|
||||
text = texts.join(', ');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(text);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
performancesSubscription?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
class WorkText extends StatelessWidget {
|
||||
final int workId;
|
||||
|
||||
WorkText(this.workId);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
|
||||
return StreamBuilder<Work>(
|
||||
stream: backend.db.workById(workId).watchSingle(),
|
||||
builder: (context, snapshot) => Text(snapshot.data?.title ?? '...'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ComposersText extends StatelessWidget {
|
||||
final int workId;
|
||||
|
||||
ComposersText(this.workId);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
|
||||
return StreamBuilder<List<Person>>(
|
||||
stream: backend.db.composersByWork(workId).watch(),
|
||||
builder: (context, snapshot) => Text(snapshot.hasData
|
||||
? snapshot.data.map((p) => '${p.firstName} ${p.lastName}').join(', ')
|
||||
: '...'),
|
||||
);
|
||||
}
|
||||
}
|
||||
39
mobile/lib/widgets/works_by_composer.dart
Normal file
39
mobile/lib/widgets/works_by_composer.dart
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../backend.dart';
|
||||
import '../database.dart';
|
||||
|
||||
class WorksByComposer extends StatelessWidget {
|
||||
final int personId;
|
||||
final void Function(Work work) onTap;
|
||||
|
||||
WorksByComposer({
|
||||
this.personId,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backend = Backend.of(context);
|
||||
|
||||
return StreamBuilder<List<Work>>(
|
||||
stream: backend.db.worksByComposer(personId).watch(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return ListView.builder(
|
||||
itemCount: snapshot.data.length,
|
||||
itemBuilder: (context, index) {
|
||||
final work = snapshot.data[index];
|
||||
return ListTile(
|
||||
title: Text(work.title),
|
||||
onTap: () => onTap(work),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue