feat(pdf): paragraph-precise bookmarks
Some checks failed
CI / Windows build (push) Has been cancelled
Some checks failed
CI / Windows build (push) Has been cancelled
Add a bookmark tool to the PDF editor. A bookmark anchors to a precise location: when text is selected it captures the selection's normalized rect + the start char index in the page text (the true paragraph anchor); with no selection it falls back to the tapped page + point. - Bookmark model gains optional normalized anchor rect + charIndex + label (all absent from JSON when null, so old sidecars still load). - Bookmarks persist in the sidecar (scheduleBookmarkUpsert) and load on open; a bookmarks panel lists them and tapping one jumps to its page. Delete is persisted. Scoped to the PDF editor (note bookmarks later); scroll-to-anchor is page-level for now. analyze clean, 391 tests green.
This commit is contained in:
@@ -93,6 +93,20 @@
|
||||
"toolPlaceScratchLink": "Place scratch link",
|
||||
"scratchLinkDeleteTitle": "Delete scratch link?",
|
||||
"scratchLinkDeleteBody": "This removes the anchor and its private scratchpad.",
|
||||
"toolAddBookmark": "Add bookmark (here or at selection)",
|
||||
"toolBookmarks": "Bookmarks",
|
||||
"bookmarksTitle": "Bookmarks",
|
||||
"bookmarksEmpty": "No bookmarks yet.",
|
||||
"bookmarkDefaultLabel": "Page {page}",
|
||||
"@bookmarkDefaultLabel": {
|
||||
"placeholders": { "page": { "type": "int" } }
|
||||
},
|
||||
"bookmarkPageLabel": "Page {page}",
|
||||
"@bookmarkPageLabel": {
|
||||
"placeholders": { "page": { "type": "int" } }
|
||||
},
|
||||
"bookmarkDeleteTitle": "Delete bookmark?",
|
||||
"bookmarkDeleteBody": "This removes the saved location.",
|
||||
"failedToOpenPdf": "Failed to open PDF:\n{error}",
|
||||
"@failedToOpenPdf": {
|
||||
"placeholders": { "error": { "type": "String" } }
|
||||
|
||||
@@ -566,6 +566,54 @@ abstract class AppLocalizations {
|
||||
/// **'This removes the anchor and its private scratchpad.'**
|
||||
String get scratchLinkDeleteBody;
|
||||
|
||||
/// No description provided for @toolAddBookmark.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add bookmark (here or at selection)'**
|
||||
String get toolAddBookmark;
|
||||
|
||||
/// No description provided for @toolBookmarks.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Bookmarks'**
|
||||
String get toolBookmarks;
|
||||
|
||||
/// No description provided for @bookmarksTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Bookmarks'**
|
||||
String get bookmarksTitle;
|
||||
|
||||
/// No description provided for @bookmarksEmpty.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No bookmarks yet.'**
|
||||
String get bookmarksEmpty;
|
||||
|
||||
/// No description provided for @bookmarkDefaultLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Page {page}'**
|
||||
String bookmarkDefaultLabel(int page);
|
||||
|
||||
/// No description provided for @bookmarkPageLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Page {page}'**
|
||||
String bookmarkPageLabel(int page);
|
||||
|
||||
/// No description provided for @bookmarkDeleteTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Delete bookmark?'**
|
||||
String get bookmarkDeleteTitle;
|
||||
|
||||
/// No description provided for @bookmarkDeleteBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'This removes the saved location.'**
|
||||
String get bookmarkDeleteBody;
|
||||
|
||||
/// No description provided for @failedToOpenPdf.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -254,6 +254,34 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get scratchLinkDeleteBody =>
|
||||
'This removes the anchor and its private scratchpad.';
|
||||
|
||||
@override
|
||||
String get toolAddBookmark => 'Add bookmark (here or at selection)';
|
||||
|
||||
@override
|
||||
String get toolBookmarks => 'Bookmarks';
|
||||
|
||||
@override
|
||||
String get bookmarksTitle => 'Bookmarks';
|
||||
|
||||
@override
|
||||
String get bookmarksEmpty => 'No bookmarks yet.';
|
||||
|
||||
@override
|
||||
String bookmarkDefaultLabel(int page) {
|
||||
return 'Page $page';
|
||||
}
|
||||
|
||||
@override
|
||||
String bookmarkPageLabel(int page) {
|
||||
return 'Page $page';
|
||||
}
|
||||
|
||||
@override
|
||||
String get bookmarkDeleteTitle => 'Delete bookmark?';
|
||||
|
||||
@override
|
||||
String get bookmarkDeleteBody => 'This removes the saved location.';
|
||||
|
||||
@override
|
||||
String failedToOpenPdf(String error) {
|
||||
return 'Failed to open PDF:\n$error';
|
||||
|
||||
@@ -253,6 +253,34 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get scratchLinkDeleteBody => '这会移除锚点及其专属草稿纸。';
|
||||
|
||||
@override
|
||||
String get toolAddBookmark => '添加书签(当前位置或所选段落)';
|
||||
|
||||
@override
|
||||
String get toolBookmarks => '书签';
|
||||
|
||||
@override
|
||||
String get bookmarksTitle => '书签';
|
||||
|
||||
@override
|
||||
String get bookmarksEmpty => '还没有书签。';
|
||||
|
||||
@override
|
||||
String bookmarkDefaultLabel(int page) {
|
||||
return '第 $page 页';
|
||||
}
|
||||
|
||||
@override
|
||||
String bookmarkPageLabel(int page) {
|
||||
return '第 $page 页';
|
||||
}
|
||||
|
||||
@override
|
||||
String get bookmarkDeleteTitle => '删除书签?';
|
||||
|
||||
@override
|
||||
String get bookmarkDeleteBody => '这会移除保存的位置。';
|
||||
|
||||
@override
|
||||
String failedToOpenPdf(String error) {
|
||||
return '打开 PDF 失败:\n$error';
|
||||
|
||||
@@ -78,6 +78,20 @@
|
||||
"toolPlaceScratchLink": "放置便签链接",
|
||||
"scratchLinkDeleteTitle": "删除便签链接?",
|
||||
"scratchLinkDeleteBody": "这会移除锚点及其专属草稿纸。",
|
||||
"toolAddBookmark": "添加书签(当前位置或所选段落)",
|
||||
"toolBookmarks": "书签",
|
||||
"bookmarksTitle": "书签",
|
||||
"bookmarksEmpty": "还没有书签。",
|
||||
"bookmarkDefaultLabel": "第 {page} 页",
|
||||
"@bookmarkDefaultLabel": {
|
||||
"placeholders": { "page": { "type": "int" } }
|
||||
},
|
||||
"bookmarkPageLabel": "第 {page} 页",
|
||||
"@bookmarkPageLabel": {
|
||||
"placeholders": { "page": { "type": "int" } }
|
||||
},
|
||||
"bookmarkDeleteTitle": "删除书签?",
|
||||
"bookmarkDeleteBody": "这会移除保存的位置。",
|
||||
"failedToOpenPdf": "打开 PDF 失败:\n{error}",
|
||||
"pdfNoPages": "PDF 没有任何页面。",
|
||||
"pageOfPages": "{current} / {total}",
|
||||
|
||||
Reference in New Issue
Block a user