Skip to content

Commit

Permalink
rework cue slides revive logic
Browse files Browse the repository at this point in the history
  • Loading branch information
RedyAu committed Nov 23, 2024
1 parent 570b161 commit 7354472
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 46 deletions.
35 changes: 8 additions & 27 deletions lib/data/cue/cue.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import 'dart:convert';

import 'package:drift/drift.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lyric/data/database.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:uuid/v4.dart';

import 'slide.dart';

part 'cue.g.dart';

const currentCueVersion = 1;

@UseRowClass(Cue)
@TableIndex(name: 'cues_uuid', columns: {#uuid}, unique: true)
class Cues extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get uuid => text()();
Expand All @@ -32,11 +28,14 @@ class Cue extends Insertable<Cue> {

List<Map> content;

List<Slide>? slides;
//List<Slide>? slides;

Future<List<Slide>> getRevivedSlides() async {
return await Future.wait(content.map((e) => Slide.reviveFromJson(e)));
}

Future reviveSlides() async {
slides = await Future.wait(content.map((e) => Slide.reviveFromJson(e)));
return;
static List<Map> getContentMapFromSlides(List<Slide> slides) {
return slides.map((s) => s.toJson()).toList();
}

Cue(
Expand All @@ -59,21 +58,8 @@ class Cue extends Insertable<Cue> {
content: Value(content),
).toColumns(nullToAbsent);
}

static CuesCompanion newCueToCompanion(NewCue newCue) {
return CuesCompanion(
id: Value.absent(),
uuid: Value(UuidV4().generate()),
title: Value(newCue.title),
description: newCue.description != null ? Value(newCue.description!) : Value.absent(),
cueVersion: Value(currentCueVersion),
content: Value([]),
);
}
}

typedef NewCue = ({String title, String? description});

class CueContentConverter extends TypeConverter<List<Map>, String> {
const CueContentConverter();

Expand All @@ -87,8 +73,3 @@ class CueContentConverter extends TypeConverter<List<Map>, String> {
return jsonEncode(value);
}
}

@riverpod
Future reviveSlidesForCue(Ref ref, Cue cue) async {
return await cue.reviveSlides();
}
1 change: 1 addition & 0 deletions lib/data/song/song.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class Song extends Insertable<Song> {

const List<String> mandatoryFields = ['uuid', 'title', 'lyrics'];

@TableIndex(name: 'songs_uuid', columns: {#uuid}, unique: true)
@UseRowClass(Song)
class Songs extends Table {
IntColumn get id => integer().autoIncrement()();
Expand Down
6 changes: 3 additions & 3 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ final _router = GoRouter(
},
),
GoRoute(
path: '/cue/:id',
path: '/cue/:uuid',
pageBuilder: (context, state) {
final cueId = int.parse(state.pathParameters['id']!);
final cueUuid = state.pathParameters['uuid']!;
int? slideIndex = int.tryParse(state.uri.queryParameters['index'] ?? 'ignoreMe');
return MaterialPage(
child: CuePage(
cueId,
cueUuid,
initialSlideIndex: slideIndex,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../data/cue/cue.dart';

part 'from_id.g.dart';
part 'from_uuid.g.dart';

@riverpod
Stream<Cue> watchAndReviveCueWithId(Ref ref, int id) async* {
await for (Cue cue in (db.cues.select()..where((c) => c.id.equals(id))).watchSingle()) {
await cue.reviveSlides();
Stream<Cue> watchCueWithUuid(Ref ref, String uuid) async* {
await for (Cue cue in (db.cues.select()..where((c) => c.uuid.equals(uuid))).watchSingle()) {
await cue.getRevivedSlides();
yield cue;
}
}
16 changes: 16 additions & 0 deletions lib/services/cue/slide/watch_revived.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lyric/services/cue/from_uuid.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../../data/cue/slide.dart';

part 'watch_revived.g.dart';

@riverpod
Stream<List<Slide>> watchRevivedSlidesForCueWithUuid(Ref ref, String uuid) async* {
final cue = ref.watch(watchCueWithUuidProvider(uuid));

if (cue.hasValue) {
yield await cue.requireValue.getRevivedSlides();
}
}
41 changes: 38 additions & 3 deletions lib/services/cue/write_cue.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,48 @@
import 'package:drift/drift.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:uuid/v4.dart';

import '../../data/cue/cue.dart';
import '../../data/cue/slide.dart';
import '../../data/database.dart';

part 'write_cue.g.dart';

@riverpod
Future insertNewCue(Ref ref, NewCue newCue) async {
// we ignore generated id
await db.into(db.cues).insert(Cue.newCueToCompanion(newCue));
Future insertNewCue(Ref ref, {required String title, String? description}) async {
await db.into(db.cues).insert(
CuesCompanion(
id: Value.absent(),
uuid: Value(UuidV4().generate()),
title: Value(title),
description: description != null ? Value(description) : Value.absent(),
cueVersion: Value(currentCueVersion),
content: Value([]),
),
);
}

@riverpod
Future updateCueMetadataFor(Ref ref, int id, {String? title, String? description}) async {
await (db.update(db.cues)..where((c) => c.id.equals(id))).write(
CuesCompanion(
title: Value.absentIfNull(title),
description: Value.absentIfNull(description),
),
);
}

@riverpod
Future updateSlidesOfCue(Ref ref, Cue cue) async {
//cue.updateContentJson();

throw UnimplementedError();
}

/*
@riverpod
Future updateCueWith(Ref ref, int id, CuesCompanion data) async {
await (db.update(db.cues)..where((e) => e.id.equals(id))).write(data);
}
*/
24 changes: 15 additions & 9 deletions lib/ui/cue/page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lyric/data/cue/slide.dart';
import 'package:lyric/main.dart';
import 'package:lyric/services/cue/from_id.dart';
import 'package:lyric/services/cue/from_uuid.dart';
import 'package:lyric/services/cue/slide/watch_revived.dart';
import 'package:lyric/ui/common/error.dart';
import 'package:lyric/ui/cue/slide_views/song.dart';

class CuePage extends ConsumerStatefulWidget {
const CuePage(this.cueId, {this.initialSlideIndex, super.key});
const CuePage(this.uuid, {this.initialSlideIndex, super.key});

final int cueId;
final String uuid;
final int? initialSlideIndex;

@override
Expand All @@ -27,7 +28,8 @@ class _CuePageState extends ConsumerState<CuePage> {

@override
Widget build(BuildContext context) {
final cue = ref.watch(watchAndReviveCueWithIdProvider(widget.cueId));
final cue = ref.watch(watchCueWithUuidProvider(widget.uuid));
final slides = ref.watch(watchRevivedSlidesForCueWithUuidProvider(widget.uuid));

return LayoutBuilder(builder: (context, contraints) {
return Flex(
Expand All @@ -37,11 +39,15 @@ class _CuePageState extends ConsumerState<CuePage> {
child: Scaffold(
appBar: AppBar(
title: Text(cue.value?.title ?? ''),
bottom: (cue.isLoading || slides.isLoading)
? PreferredSize(preferredSize: const Size.fromHeight(4), child: LinearProgressIndicator())
: null,
),
body: switch (cue) {
// todo show error message when cue provider returns error
body: switch (slides) {
AsyncError(:final error, :final stackTrace) => LErrorCard(
type: LErrorType.error,
title: 'Nem sikerült betölteni a listát!',
title: 'Nem sikerült betölteni a lista diáit!',
icon: Icons.error,
message: error.toString(),
stack: stackTrace.toString(),
Expand All @@ -52,7 +58,7 @@ class _CuePageState extends ConsumerState<CuePage> {
AsyncValue(:final value!) => ListTileTheme(
selectedTileColor: Theme.of(context).indicatorColor,
child: ListView(
children: value.slides!.asMap().entries.map(
children: value.asMap().entries.map(
(indexedEntry) {
callback() => setState(() {
selectedSlideIndex = indexedEntry.key;
Expand Down Expand Up @@ -96,7 +102,7 @@ class _CuePageState extends ConsumerState<CuePage> {
child: Scaffold(
backgroundColor: Theme.of(context).indicatorColor,
appBar: AppBar(
title: Text(cue.requireValue.slides![selectedSlideIndex!].comment ?? ''),
title: Text(slides.requireValue[selectedSlideIndex!].comment ?? ''),
elevation: 1,
automaticallyImplyLeading: false,
actions: [
Expand All @@ -109,7 +115,7 @@ class _CuePageState extends ConsumerState<CuePage> {
],
actionsPadding: EdgeInsets.only(right: 5),
),
body: switch (cue.requireValue.slides![selectedSlideIndex!]) {
body: switch (slides.requireValue[selectedSlideIndex!]) {
(SongSlide songSlide) => SongSlideView(songSlide),
(UnknownTypeSlide unknownSlide) => LErrorCard(
type: LErrorType.warning,
Expand Down

0 comments on commit 7354472

Please sign in to comment.