feat(app): editor blocks: callout, spoiler, formulas, files, video, study button
Blocks beyond the editor's own, each built once for editor and view: - callout: eight kinds in theme colours, kind, title and "folded at first" from its header; written in place, left with Enter on its empty last line; never inside another - spoiler: written in plain sight, hidden behind Reveal read-only - formula on its own line, written on its own screen with a preview and snippet buttons, and formulas within a line (Σ in the format bar); set by flutter_math_fork behind MathView, LaTeX's numbered environments read as their aligned forms - image and sound picked from the device, kept as synced files - YouTube video from its link, with its start and a caption: a card until played, nothing fetched before; played in place where a web view exists (youtube_player_iframe, privacy-enhanced), else opened in the browser, behind YoutubeVideos in Dependencies - study button: a studyset, a tag or all cards, with or without its topics, back first; its StudyFocus rides on the study route and narrows that session only - tables, already in the editor, now insertable everywhere An Insert button opens on the format bar, so blocks can be inserted on phones too; the desktop's / menu lists the same blocks, translated. Card faces now dock the format bar while written, so cards get blocks and formatting on phones as well. The blocks are listed in EditorBlocks: the core's, plus the features' through EditorBlocksScope. Blocks of a type the app doesn't know say they need a newer version and stay as they are, so formatVersion stays 1. Their types and keys are in content_blocks.dart, which RichContent reads: a block's text counts as text, and a video or study button isn't blank. The path import now makes formulas real ones. integration_test/youtube_player_test.dart plays a real video through the app's player on a device, which no widget test can: YouTube refuses embeds that don't say where they are embedded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
9324432f61
commit
ec34bb2334
1 changed files with 5602 additions and 284 deletions
|
|
@ -1683,6 +1683,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get commonCancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get commonSave => 'Save';
|
||||
|
||||
@override
|
||||
String get commonClose => 'Close';
|
||||
|
||||
|
|
@ -1730,6 +1733,278 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get fileSoundUnplayable =>
|
||||
'This sound can\'t be played. Its file may be damaged, or in a format this device can\'t play.';
|
||||
|
||||
@override
|
||||
String get fileImages => 'Images';
|
||||
|
||||
@override
|
||||
String get fileSounds => 'Sounds';
|
||||
|
||||
@override
|
||||
String get fileNotAnImage => 'This file isn\'t an image the app can show.';
|
||||
|
||||
@override
|
||||
String get fileNotASound => 'This file isn\'t a sound the app can play.';
|
||||
|
||||
@override
|
||||
String fileTooLarge(int megabytes) {
|
||||
return 'This file is larger than $megabytes MB.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get fileNotKept => 'The file couldn\'t be kept on this device.';
|
||||
|
||||
@override
|
||||
String get fileRemoveImage => 'Remove image';
|
||||
|
||||
@override
|
||||
String get fileRemoveSound => 'Remove sound';
|
||||
|
||||
@override
|
||||
String get editorInsert => 'Insert';
|
||||
|
||||
@override
|
||||
String get blockGroupText => 'Text';
|
||||
|
||||
@override
|
||||
String get blockGroupBlocks => 'Blocks';
|
||||
|
||||
@override
|
||||
String get blockGroupMedia => 'Media';
|
||||
|
||||
@override
|
||||
String blockHeading(int level) {
|
||||
return 'Heading $level';
|
||||
}
|
||||
|
||||
@override
|
||||
String get blockBulletedList => 'Bulleted list';
|
||||
|
||||
@override
|
||||
String get blockNumberedList => 'Numbered list';
|
||||
|
||||
@override
|
||||
String get blockChecklist => 'Checklist';
|
||||
|
||||
@override
|
||||
String get blockQuote => 'Quote';
|
||||
|
||||
@override
|
||||
String get blockDivider => 'Divider';
|
||||
|
||||
@override
|
||||
String get blockTable => 'Table';
|
||||
|
||||
@override
|
||||
String get blockRemove => 'Remove';
|
||||
|
||||
@override
|
||||
String get blockUnknown => 'This part needs a newer version of the app.';
|
||||
|
||||
@override
|
||||
String get blockCallout => 'Callout';
|
||||
|
||||
@override
|
||||
String get blockSpoiler => 'Spoiler';
|
||||
|
||||
@override
|
||||
String get calloutNote => 'Note';
|
||||
|
||||
@override
|
||||
String get calloutInfo => 'Info';
|
||||
|
||||
@override
|
||||
String get calloutTip => 'Tip';
|
||||
|
||||
@override
|
||||
String get calloutSuccess => 'Success';
|
||||
|
||||
@override
|
||||
String get calloutQuestion => 'Question';
|
||||
|
||||
@override
|
||||
String get calloutWarning => 'Warning';
|
||||
|
||||
@override
|
||||
String get calloutDanger => 'Danger';
|
||||
|
||||
@override
|
||||
String get calloutQuote => 'Quote';
|
||||
|
||||
@override
|
||||
String get calloutOptions => 'Callout options';
|
||||
|
||||
@override
|
||||
String get calloutEditTitle => 'Edit title…';
|
||||
|
||||
@override
|
||||
String get calloutFoldedAtFirst => 'Folded at first';
|
||||
|
||||
@override
|
||||
String get calloutRemove => 'Remove callout';
|
||||
|
||||
@override
|
||||
String get calloutShow => 'Show';
|
||||
|
||||
@override
|
||||
String get calloutHide => 'Hide';
|
||||
|
||||
@override
|
||||
String get calloutWriteInside => 'Write inside';
|
||||
|
||||
@override
|
||||
String get calloutTitleDialog => 'Callout title';
|
||||
|
||||
@override
|
||||
String get calloutTitleLabel => 'Title';
|
||||
|
||||
@override
|
||||
String get calloutTitleHelper => 'Leave it empty to show the kind\'s name.';
|
||||
|
||||
@override
|
||||
String get spoilerReveal => 'Reveal';
|
||||
|
||||
@override
|
||||
String get spoilerPlaceholder => 'Hidden text, revealed on a tap';
|
||||
|
||||
@override
|
||||
String get blockFormula => 'Formula';
|
||||
|
||||
@override
|
||||
String get formatInlineMath => 'Formula in the line';
|
||||
|
||||
@override
|
||||
String get formulaTitle => 'Formula';
|
||||
|
||||
@override
|
||||
String get formulaInLineTitle => 'Formula in the line';
|
||||
|
||||
@override
|
||||
String get formulaPreview => 'Preview';
|
||||
|
||||
@override
|
||||
String get formulaPreviewEmpty => 'The formula shows here';
|
||||
|
||||
@override
|
||||
String get formulaLatex => 'LaTeX';
|
||||
|
||||
@override
|
||||
String get formulaLatexHelper =>
|
||||
'\\\\ starts a new line in aligned, cases or a matrix.';
|
||||
|
||||
@override
|
||||
String get formulaEmpty => 'An empty formula. Tap to write it.';
|
||||
|
||||
@override
|
||||
String get formulaEdit => 'Edit formula';
|
||||
|
||||
@override
|
||||
String get formulaRemove => 'Remove formula';
|
||||
|
||||
@override
|
||||
String get blockYoutube => 'YouTube video';
|
||||
|
||||
@override
|
||||
String get youtubeLink => 'YouTube link';
|
||||
|
||||
@override
|
||||
String get youtubeLinkHelper => 'Paste a link from YouTube.';
|
||||
|
||||
@override
|
||||
String get youtubeNotFound => 'No YouTube video in this link.';
|
||||
|
||||
@override
|
||||
String get youtubeFound => 'Found the video.';
|
||||
|
||||
@override
|
||||
String youtubeFoundFrom(String time) {
|
||||
return 'Found the video, starting at $time.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get youtubeCaption => 'Caption';
|
||||
|
||||
@override
|
||||
String get youtubeCaptionHelper =>
|
||||
'Shown in place of the video until it plays.';
|
||||
|
||||
@override
|
||||
String get youtubeVideo => 'YouTube video';
|
||||
|
||||
@override
|
||||
String get youtubeSource => 'YouTube';
|
||||
|
||||
@override
|
||||
String youtubeFrom(String time) {
|
||||
return 'YouTube · from $time';
|
||||
}
|
||||
|
||||
@override
|
||||
String get youtubeEdit => 'Edit video';
|
||||
|
||||
@override
|
||||
String get youtubePlay => 'Play video';
|
||||
|
||||
@override
|
||||
String get youtubeOpen => 'Open on YouTube';
|
||||
|
||||
@override
|
||||
String get youtubeRemove => 'Remove video';
|
||||
|
||||
@override
|
||||
String get youtubeBroken => 'This video\'s link can\'t be read.';
|
||||
|
||||
@override
|
||||
String get youtubeNotOpened => 'Couldn\'t open YouTube.';
|
||||
|
||||
@override
|
||||
String get blockStudyButton => 'Study button';
|
||||
|
||||
@override
|
||||
String get studyButtonDefaultLabel => 'Study';
|
||||
|
||||
@override
|
||||
String get studyButtonStudyset => 'Studyset to study';
|
||||
|
||||
@override
|
||||
String get studyButtonTag => 'Cards';
|
||||
|
||||
@override
|
||||
String get studyButtonAllCards => 'All cards';
|
||||
|
||||
@override
|
||||
String get studyButtonLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get studyButtonTopics => 'With its topics';
|
||||
|
||||
@override
|
||||
String get studyButtonBackFirst => 'Back first';
|
||||
|
||||
@override
|
||||
String get studyButtonBackFirstHelper =>
|
||||
'Front/back and vocabulary cards ask their back.';
|
||||
|
||||
@override
|
||||
String studyButtonWithTag(String tag) {
|
||||
return 'Tagged $tag';
|
||||
}
|
||||
|
||||
@override
|
||||
String get studyButtonAlone => 'Without its topics';
|
||||
|
||||
@override
|
||||
String get studyButtonEdit => 'Edit study button';
|
||||
|
||||
@override
|
||||
String get studyButtonRemove => 'Remove study button';
|
||||
|
||||
@override
|
||||
String get studyButtonBroken =>
|
||||
'This study button doesn\'t say what to study.';
|
||||
|
||||
@override
|
||||
String get studyButtonGone => 'That studyset no longer exists.';
|
||||
|
||||
@override
|
||||
String get ankiImportMenu => 'Import from Anki';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue