feat(meditate): the instance's library in the app: Explore, its player, courses, keeping offline

Explore shows the instance's library below Meditate's practices, where it
has one: its courses and items by category (Meditate's eleven, named in
English and German, and the operator's own) and by the same search; an
instance without one shows nothing more. An item's page: its recordings
to choose, Play, a favourite (kept in the sealed settings under
library/<id>), keeping it on the device and removing it, and for a sound,
a silent sitting with it looped; its credit and licence. The player
plays, pauses and seeks; played to its end it is kept as a sitting, and
as its course's lesson done (lesson_done, sealed and synced). Settings
lists the library's credits beside About; Today shows its favourites.

The last catalogue is kept in the person's folder for offline; files are
fetched with the catalogue's access, asked for again shortly before it
ends. ADR 0038, D16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-03 16:47:28 +01:00
commit 811182b376
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 3386 additions and 22 deletions

View file

@ -171,5 +171,41 @@
"dreamStopDictating": "Diktat beenden",
"dreamListening": "Ich höre zu …",
"dreamSpeechUnavailable": "Dieses Gerät kann gerade nicht zuhören. Darf die App das Mikrofon nutzen?",
"todayDreamSpeak": "Erzählen"
"todayDreamSpeak": "Erzählen",
"exploreLibrary": "Von {server}",
"libraryCourses": "Kurse",
"libraryCourse": "Kurs",
"libraryCategoryMeditation": "Meditation",
"libraryCategorySleepStory": "Einschlafgeschichten",
"libraryCategorySound": "Klänge",
"libraryCategoryMovement": "Bewegung",
"libraryCategoryAutogenicTraining": "Autogenes Training",
"libraryCategoryProgressiveMuscleRelaxation": "Progressive Muskelentspannung",
"libraryCategoryRoutine": "Routinen",
"libraryCategoryDreamJourney": "Traumreisen",
"libraryCategoryKnowledge": "Wissen",
"libraryCategoryMorningStory": "Morgengeschichten",
"libraryCategoryOther": "Anderes",
"libraryLessons": "{count, plural, =1{1 Lektion} other{{count} Lektionen}}",
"libraryLessonsDone": "{done} von {count} erledigt",
"libraryLessonDone": "Erledigt",
"libraryWith": "Mit {speaker}",
"libraryPlay": "Abspielen",
"libraryPause": "Pause",
"libraryResume": "Weiter",
"libraryStop": "Beenden",
"libraryRecording": "Aufnahme",
"libraryKeep": "Auf dem Gerät behalten",
"libraryKeeping": "Wird geladen …",
"libraryKept": "Auf dem Gerät",
"libraryRemove": "Vom Gerät entfernen",
"libraryKeepFailed": "Das ließ sich nicht laden. Versuch es wieder, wenn du online bist.",
"libraryPlayFailed": "Das lässt sich gerade nicht abspielen. Bist du online?",
"librarySitWithSound": "Mit diesem Klang still sitzen",
"libraryCredit": "Nachweis",
"libraryLicence": "Lizenz",
"libraryCredits": "Nachweise der Bibliothek",
"libraryCreditsIntro": "Was die Bibliothek von {server} bietet, wem es jeweils zu verdanken ist und unter welcher Lizenz.",
"libraryGone": "Das ist nicht mehr in der Bibliothek.",
"libraryFromLibrary": "Aus der Bibliothek"
}

View file

@ -259,5 +259,79 @@
"dreamStopDictating": "Stop dictating",
"dreamListening": "Listening…",
"dreamSpeechUnavailable": "This device can't listen now. Does the app have the microphone's permission?",
"todayDreamSpeak": "Speak it"
"todayDreamSpeak": "Speak it",
"exploreLibrary": "From {server}",
"@exploreLibrary": {
"placeholders": {
"server": {
"type": "String"
}
}
},
"libraryCourses": "Courses",
"libraryCourse": "Course",
"libraryCategoryMeditation": "Meditation",
"libraryCategorySleepStory": "Sleep stories",
"libraryCategorySound": "Sounds",
"libraryCategoryMovement": "Movement",
"libraryCategoryAutogenicTraining": "Autogenic training",
"libraryCategoryProgressiveMuscleRelaxation": "Progressive muscle relaxation",
"libraryCategoryRoutine": "Routines",
"libraryCategoryDreamJourney": "Dream journeys",
"libraryCategoryKnowledge": "Knowledge",
"libraryCategoryMorningStory": "Morning stories",
"libraryCategoryOther": "Other",
"libraryLessons": "{count, plural, =1{1 lesson} other{{count} lessons}}",
"@libraryLessons": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"libraryLessonsDone": "{done} of {count} done",
"@libraryLessonsDone": {
"placeholders": {
"done": {
"type": "int"
},
"count": {
"type": "int"
}
}
},
"libraryLessonDone": "Done",
"libraryWith": "With {speaker}",
"@libraryWith": {
"placeholders": {
"speaker": {
"type": "String"
}
}
},
"libraryPlay": "Play",
"libraryPause": "Pause",
"libraryResume": "Resume",
"libraryStop": "Stop",
"libraryRecording": "Recording",
"libraryKeep": "Keep on this device",
"libraryKeeping": "Fetching…",
"libraryKept": "On this device",
"libraryRemove": "Remove from this device",
"libraryKeepFailed": "It couldn't be fetched. Try again when you're online.",
"libraryPlayFailed": "It can't be played now. Are you online?",
"librarySitWithSound": "Sit in silence with this sound",
"libraryCredit": "Credit",
"libraryLicence": "Licence",
"libraryCredits": "Library credits",
"libraryCreditsIntro": "What the library of {server} offers, whom each is credited to and under which licence.",
"@libraryCreditsIntro": {
"placeholders": {
"server": {
"type": "String"
}
}
},
"libraryGone": "This isn't in the library any more.",
"libraryFromLibrary": "From the library"
}

View file

@ -1131,6 +1131,222 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Speak it'**
String get todayDreamSpeak;
/// No description provided for @exploreLibrary.
///
/// In en, this message translates to:
/// **'From {server}'**
String exploreLibrary(String server);
/// No description provided for @libraryCourses.
///
/// In en, this message translates to:
/// **'Courses'**
String get libraryCourses;
/// No description provided for @libraryCourse.
///
/// In en, this message translates to:
/// **'Course'**
String get libraryCourse;
/// No description provided for @libraryCategoryMeditation.
///
/// In en, this message translates to:
/// **'Meditation'**
String get libraryCategoryMeditation;
/// No description provided for @libraryCategorySleepStory.
///
/// In en, this message translates to:
/// **'Sleep stories'**
String get libraryCategorySleepStory;
/// No description provided for @libraryCategorySound.
///
/// In en, this message translates to:
/// **'Sounds'**
String get libraryCategorySound;
/// No description provided for @libraryCategoryMovement.
///
/// In en, this message translates to:
/// **'Movement'**
String get libraryCategoryMovement;
/// No description provided for @libraryCategoryAutogenicTraining.
///
/// In en, this message translates to:
/// **'Autogenic training'**
String get libraryCategoryAutogenicTraining;
/// No description provided for @libraryCategoryProgressiveMuscleRelaxation.
///
/// In en, this message translates to:
/// **'Progressive muscle relaxation'**
String get libraryCategoryProgressiveMuscleRelaxation;
/// No description provided for @libraryCategoryRoutine.
///
/// In en, this message translates to:
/// **'Routines'**
String get libraryCategoryRoutine;
/// No description provided for @libraryCategoryDreamJourney.
///
/// In en, this message translates to:
/// **'Dream journeys'**
String get libraryCategoryDreamJourney;
/// No description provided for @libraryCategoryKnowledge.
///
/// In en, this message translates to:
/// **'Knowledge'**
String get libraryCategoryKnowledge;
/// No description provided for @libraryCategoryMorningStory.
///
/// In en, this message translates to:
/// **'Morning stories'**
String get libraryCategoryMorningStory;
/// No description provided for @libraryCategoryOther.
///
/// In en, this message translates to:
/// **'Other'**
String get libraryCategoryOther;
/// No description provided for @libraryLessons.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 lesson} other{{count} lessons}}'**
String libraryLessons(int count);
/// No description provided for @libraryLessonsDone.
///
/// In en, this message translates to:
/// **'{done} of {count} done'**
String libraryLessonsDone(int done, int count);
/// No description provided for @libraryLessonDone.
///
/// In en, this message translates to:
/// **'Done'**
String get libraryLessonDone;
/// No description provided for @libraryWith.
///
/// In en, this message translates to:
/// **'With {speaker}'**
String libraryWith(String speaker);
/// No description provided for @libraryPlay.
///
/// In en, this message translates to:
/// **'Play'**
String get libraryPlay;
/// No description provided for @libraryPause.
///
/// In en, this message translates to:
/// **'Pause'**
String get libraryPause;
/// No description provided for @libraryResume.
///
/// In en, this message translates to:
/// **'Resume'**
String get libraryResume;
/// No description provided for @libraryStop.
///
/// In en, this message translates to:
/// **'Stop'**
String get libraryStop;
/// No description provided for @libraryRecording.
///
/// In en, this message translates to:
/// **'Recording'**
String get libraryRecording;
/// No description provided for @libraryKeep.
///
/// In en, this message translates to:
/// **'Keep on this device'**
String get libraryKeep;
/// No description provided for @libraryKeeping.
///
/// In en, this message translates to:
/// **'Fetching…'**
String get libraryKeeping;
/// No description provided for @libraryKept.
///
/// In en, this message translates to:
/// **'On this device'**
String get libraryKept;
/// No description provided for @libraryRemove.
///
/// In en, this message translates to:
/// **'Remove from this device'**
String get libraryRemove;
/// No description provided for @libraryKeepFailed.
///
/// In en, this message translates to:
/// **'It couldn\'t be fetched. Try again when you\'re online.'**
String get libraryKeepFailed;
/// No description provided for @libraryPlayFailed.
///
/// In en, this message translates to:
/// **'It can\'t be played now. Are you online?'**
String get libraryPlayFailed;
/// No description provided for @librarySitWithSound.
///
/// In en, this message translates to:
/// **'Sit in silence with this sound'**
String get librarySitWithSound;
/// No description provided for @libraryCredit.
///
/// In en, this message translates to:
/// **'Credit'**
String get libraryCredit;
/// No description provided for @libraryLicence.
///
/// In en, this message translates to:
/// **'Licence'**
String get libraryLicence;
/// No description provided for @libraryCredits.
///
/// In en, this message translates to:
/// **'Library credits'**
String get libraryCredits;
/// No description provided for @libraryCreditsIntro.
///
/// In en, this message translates to:
/// **'What the library of {server} offers, whom each is credited to and under which licence.'**
String libraryCreditsIntro(String server);
/// No description provided for @libraryGone.
///
/// In en, this message translates to:
/// **'This isn\'t in the library any more.'**
String get libraryGone;
/// No description provided for @libraryFromLibrary.
///
/// In en, this message translates to:
/// **'From the library'**
String get libraryFromLibrary;
}
class _AppLocalizationsDelegate

View file

@ -607,4 +607,131 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get todayDreamSpeak => 'Erzählen';
@override
String exploreLibrary(String server) {
return 'Von $server';
}
@override
String get libraryCourses => 'Kurse';
@override
String get libraryCourse => 'Kurs';
@override
String get libraryCategoryMeditation => 'Meditation';
@override
String get libraryCategorySleepStory => 'Einschlafgeschichten';
@override
String get libraryCategorySound => 'Klänge';
@override
String get libraryCategoryMovement => 'Bewegung';
@override
String get libraryCategoryAutogenicTraining => 'Autogenes Training';
@override
String get libraryCategoryProgressiveMuscleRelaxation =>
'Progressive Muskelentspannung';
@override
String get libraryCategoryRoutine => 'Routinen';
@override
String get libraryCategoryDreamJourney => 'Traumreisen';
@override
String get libraryCategoryKnowledge => 'Wissen';
@override
String get libraryCategoryMorningStory => 'Morgengeschichten';
@override
String get libraryCategoryOther => 'Anderes';
@override
String libraryLessons(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Lektionen',
one: '1 Lektion',
);
return '$_temp0';
}
@override
String libraryLessonsDone(int done, int count) {
return '$done von $count erledigt';
}
@override
String get libraryLessonDone => 'Erledigt';
@override
String libraryWith(String speaker) {
return 'Mit $speaker';
}
@override
String get libraryPlay => 'Abspielen';
@override
String get libraryPause => 'Pause';
@override
String get libraryResume => 'Weiter';
@override
String get libraryStop => 'Beenden';
@override
String get libraryRecording => 'Aufnahme';
@override
String get libraryKeep => 'Auf dem Gerät behalten';
@override
String get libraryKeeping => 'Wird geladen …';
@override
String get libraryKept => 'Auf dem Gerät';
@override
String get libraryRemove => 'Vom Gerät entfernen';
@override
String get libraryKeepFailed =>
'Das ließ sich nicht laden. Versuch es wieder, wenn du online bist.';
@override
String get libraryPlayFailed =>
'Das lässt sich gerade nicht abspielen. Bist du online?';
@override
String get librarySitWithSound => 'Mit diesem Klang still sitzen';
@override
String get libraryCredit => 'Nachweis';
@override
String get libraryLicence => 'Lizenz';
@override
String get libraryCredits => 'Nachweise der Bibliothek';
@override
String libraryCreditsIntro(String server) {
return 'Was die Bibliothek von $server bietet, wem es jeweils zu verdanken ist und unter welcher Lizenz.';
}
@override
String get libraryGone => 'Das ist nicht mehr in der Bibliothek.';
@override
String get libraryFromLibrary => 'Aus der Bibliothek';
}

View file

@ -603,6 +603,132 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get todayDreamSpeak => 'Speak it';
@override
String exploreLibrary(String server) {
return 'From $server';
}
@override
String get libraryCourses => 'Courses';
@override
String get libraryCourse => 'Course';
@override
String get libraryCategoryMeditation => 'Meditation';
@override
String get libraryCategorySleepStory => 'Sleep stories';
@override
String get libraryCategorySound => 'Sounds';
@override
String get libraryCategoryMovement => 'Movement';
@override
String get libraryCategoryAutogenicTraining => 'Autogenic training';
@override
String get libraryCategoryProgressiveMuscleRelaxation =>
'Progressive muscle relaxation';
@override
String get libraryCategoryRoutine => 'Routines';
@override
String get libraryCategoryDreamJourney => 'Dream journeys';
@override
String get libraryCategoryKnowledge => 'Knowledge';
@override
String get libraryCategoryMorningStory => 'Morning stories';
@override
String get libraryCategoryOther => 'Other';
@override
String libraryLessons(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count lessons',
one: '1 lesson',
);
return '$_temp0';
}
@override
String libraryLessonsDone(int done, int count) {
return '$done of $count done';
}
@override
String get libraryLessonDone => 'Done';
@override
String libraryWith(String speaker) {
return 'With $speaker';
}
@override
String get libraryPlay => 'Play';
@override
String get libraryPause => 'Pause';
@override
String get libraryResume => 'Resume';
@override
String get libraryStop => 'Stop';
@override
String get libraryRecording => 'Recording';
@override
String get libraryKeep => 'Keep on this device';
@override
String get libraryKeeping => 'Fetching…';
@override
String get libraryKept => 'On this device';
@override
String get libraryRemove => 'Remove from this device';
@override
String get libraryKeepFailed =>
'It couldn\'t be fetched. Try again when you\'re online.';
@override
String get libraryPlayFailed => 'It can\'t be played now. Are you online?';
@override
String get librarySitWithSound => 'Sit in silence with this sound';
@override
String get libraryCredit => 'Credit';
@override
String get libraryLicence => 'Licence';
@override
String get libraryCredits => 'Library credits';
@override
String libraryCreditsIntro(String server) {
return 'What the library of $server offers, whom each is credited to and under which licence.';
}
@override
String get libraryGone => 'This isn\'t in the library any more.';
@override
String get libraryFromLibrary => 'From the library';
}
/// The translations for English, as used in the United Kingdom (`en_GB`).