App themes (#217)
* Updated `.gitattributes` to correctly vendor all files within the `libmobi` and `woff2` directories. * Improved TTS chapter transition handling * Improved TTS stability and chapter advancement in the EPUB reader. * Implemented PDF metadata extraction for titles and authors using PdfiumCore in `MainViewModel` and `MetadataExtractionWorker`. * Implemented support for interactive footnotes in the EPUB vertical reader. * Added support for footnotes in the paginated EPUB reader. * Implemented a customizable app theming system. * Added support for app-wide contrast and text brightness customization in the "App Theme" option. * option to adjust pull-to-chapter-change drag in the EPUB vertical reader under visual options. * Updated `PdfViewerScreen` to replace the standalone full-screen toggle with a more comprehensive "Visual Options" system UI management tool.
This commit is contained in:
parent
4cb25e6abd
commit
71e3614ad6
19 changed files with 1413 additions and 287 deletions
|
|
@ -442,14 +442,70 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
function getFootnoteContent(targetId) {
|
||||
console.log("FootnoteDiag: Searching for footnote content with id: '" + targetId + "'");
|
||||
|
||||
var el = document.getElementById(targetId);
|
||||
if (el) {
|
||||
console.log("FootnoteDiag: Found element directly in DOM.");
|
||||
return el.innerHTML;
|
||||
}
|
||||
|
||||
console.log("FootnoteDiag: Element not in DOM, checking virtualized chunks.");
|
||||
if (window.virtualization && window.virtualization.chunksData) {
|
||||
for (var i = 0; i < window.virtualization.chunksData.length; i++) {
|
||||
var chunkHtml = window.virtualization.chunksData[i];
|
||||
if (chunkHtml && chunkHtml.indexOf('id="' + targetId + '"') !== -1) {
|
||||
console.log("FootnoteDiag: Found potential id match in chunk " + i);
|
||||
var tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = chunkHtml;
|
||||
var found = tempDiv.querySelector('#' + targetId);
|
||||
if (found) {
|
||||
console.log("FootnoteDiag: Successfully extracted note from chunk " + i + ".");
|
||||
return found.innerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log("FootnoteDiag: Footnote content not found anywhere.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. Handle Taps (Click)
|
||||
document.addEventListener(
|
||||
"click",
|
||||
function (e) {
|
||||
handleHighlightInteraction(e);
|
||||
},
|
||||
true
|
||||
);
|
||||
document.addEventListener("click", function (e) {
|
||||
if (handleHighlightInteraction(e)) return;
|
||||
|
||||
var target = e.target;
|
||||
var anchor = target.closest('a');
|
||||
|
||||
if (anchor) {
|
||||
var href = anchor.getAttribute('href');
|
||||
var epubType = anchor.getAttribute('epub:type');
|
||||
|
||||
console.log("FootnoteDiag: Link clicked. href: '" + href + "', epub:type: '" + epubType + "'");
|
||||
|
||||
if ((href && href.startsWith('#')) || epubType === 'noteref') {
|
||||
var targetId = href ? href.substring(1) : null;
|
||||
console.log("FootnoteDiag: Extracted targetId: '" + targetId + "'");
|
||||
|
||||
if (targetId) {
|
||||
var content = getFootnoteContent(targetId);
|
||||
if (content && window.FootnoteBridge) {
|
||||
console.log("FootnoteDiag: Content extracted, sending to Kotlin Bridge.");
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
window.FootnoteBridge.onFootnoteRequested(content);
|
||||
return;
|
||||
} else if (!content) {
|
||||
console.log("FootnoteDiag: Failed to get content. Link might just be a regular anchor.");
|
||||
} else if (!window.FootnoteBridge) {
|
||||
console.log("FootnoteDiag: window.FootnoteBridge is undefined!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
||||
window.updateReaderStyles = function (fontSizeEm, lineHeight, fontFamily, textAlign, paragraphGap) {
|
||||
var logTag = "ReaderFontDiagnosis";
|
||||
|
|
@ -1094,13 +1150,14 @@
|
|||
};
|
||||
|
||||
window.extractTextWithCfiFromTop = function () {
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: Starting extractTextWithCfiFromTop");
|
||||
try {
|
||||
const ttsNodeSelector = "p, h1, h2, h3, h4, h5, h6, li, blockquote";
|
||||
const allContentNodesRaw = Array.from(document.body.querySelectorAll(ttsNodeSelector));
|
||||
|
||||
// FIX: Filter out parents that contain matching children to prevent duplicates
|
||||
const allContentNodes = allContentNodesRaw.filter(node => node.querySelector(ttsNodeSelector) === null);
|
||||
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: Total nodes found: " + allContentNodes.length);
|
||||
|
||||
let startBlock = null;
|
||||
let startIndex = -1;
|
||||
|
||||
|
|
@ -1116,9 +1173,12 @@
|
|||
}
|
||||
|
||||
if (!startBlock) {
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: No visible start block found in viewport.");
|
||||
return window.extractTextWithCfi();
|
||||
}
|
||||
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: Starting extraction from node index: " + startIndex);
|
||||
|
||||
const nodesToProcess = allContentNodes.slice(startIndex);
|
||||
const results =[];
|
||||
|
||||
|
|
@ -1136,6 +1196,7 @@
|
|||
|
||||
return JSON.stringify(results);
|
||||
} catch (e) {
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: Error in extractTextWithCfiFromTop: " + e.message);
|
||||
return window.extractTextWithCfi();
|
||||
}
|
||||
};
|
||||
|
|
@ -1240,13 +1301,20 @@
|
|||
|
||||
window.TtsBridgeHelper = {
|
||||
extractAndRelayText: function () {
|
||||
const traceId = Date.now();
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: [" + traceId + "] extractAndRelayText invoked.");
|
||||
try {
|
||||
const structuredTextJson = window.extractTextWithCfiFromTop();
|
||||
const len = structuredTextJson ? structuredTextJson.length : 0;
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: [" + traceId + "] Relay text JSON length: " + len);
|
||||
|
||||
if (typeof TtsBridge !== "undefined" && TtsBridge.onStructuredTextExtracted) {
|
||||
TtsBridge.onStructuredTextExtracted(structuredTextJson);
|
||||
} else {
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: [" + traceId + "] Bridge missing!");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("TTS_CHAPTER_CHANGE_DIAG: [" + traceId + "] Error: " + e.message);
|
||||
if (typeof TtsBridge !== "undefined" && TtsBridge.onStructuredTextExtracted) {
|
||||
TtsBridge.onStructuredTextExtracted("[]");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue