General improvements (#316)

* Added support for right text alignment in epub reader

* Added tabs management to PDF navigation drawer

* Implemented unified selection menu placement logic

* Added reset functionality for toolbar customization

* Improved highlight filtering in epub pagination

* Migrated hardcoded UI strings to string resources

* Extracted desktop application logic from Main.kt into modular files

* Refactored Main.kt by extracting PDF and EPUB logic into specialized files

* Added Spanish language support

* Added system default option to app language selection
This commit is contained in:
Aryan 2026-05-16 16:19:31 +05:30 committed by GitHub
parent 759d4b73a0
commit 056485a140
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 9184 additions and 5947 deletions

View file

@ -207,6 +207,131 @@
};
window.setTextSelectionEnabled(true);
installReaderSelectionBridge();
}
function installReaderSelectionBridge() {
if (window.__readerSelectionBridgeInstalled) {
return;
}
window.__readerSelectionBridgeInstalled = true;
var pointerActive = false;
var lastPayloadJson = "";
function buildSelectionPayload() {
var selection = window.getSelection && window.getSelection();
if (!selection || selection.rangeCount === 0) {
return null;
}
var selectedText = selection.toString().trim();
if (!selectedText) {
return null;
}
var range = selection.getRangeAt(0);
var viewportLeft = 0;
var viewportTop = 0;
var viewportRight = window.innerWidth || document.documentElement.clientWidth || 0;
var viewportBottom = window.innerHeight || document.documentElement.clientHeight || 0;
var rects = Array.prototype.slice.call(range.getClientRects ? range.getClientRects() : []);
rects = rects.filter(function (rect) {
if (!rect || rect.width <= 0 || rect.height <= 0) return false;
return rect.right >= viewportLeft &&
rect.left <= viewportRight &&
rect.bottom >= viewportTop &&
rect.top <= viewportBottom;
});
var rect = null;
if (rects.length > 0) {
var firstRect = rects[0];
rect = rects.reduce(function (acc, item) {
return {
left: Math.min(acc.left, item.left),
top: Math.min(acc.top, item.top),
right: Math.max(acc.right, item.right),
bottom: Math.max(acc.bottom, item.bottom)
};
}, {
left: firstRect.left,
top: firstRect.top,
right: firstRect.right,
bottom: firstRect.bottom
});
rect.width = rect.right - rect.left;
rect.height = rect.bottom - rect.top;
} else {
rect = range.getBoundingClientRect ? range.getBoundingClientRect() : null;
if (!rect || rect.width <= 0 || rect.height <= 0) {
return null;
}
}
return {
text: selectedText,
left: rect.left,
top: rect.top,
right: rect.right,
bottom: rect.bottom,
width: rect.width,
height: rect.height
};
}
function reportSelectionToBridge() {
if (pointerActive) {
return;
}
if (!window.ReaderSelectionBridge || !window.ReaderSelectionBridge.onSelectionChanged) {
return;
}
var payload = buildSelectionPayload();
if (!payload) {
lastPayloadJson = "";
return;
}
var payloadJson = JSON.stringify(payload);
if (payloadJson === lastPayloadJson) {
return;
}
lastPayloadJson = payloadJson;
window.ReaderSelectionBridge.onSelectionChanged(payloadJson);
}
function scheduleSelectionReport(delay) {
setTimeout(reportSelectionToBridge, delay == null ? 160 : delay);
}
function markPointerActive() {
pointerActive = true;
}
function markPointerReleased() {
pointerActive = false;
scheduleSelectionReport(80);
scheduleSelectionReport(220);
scheduleSelectionReport(520);
}
document.addEventListener("selectionchange", function () {
if (!pointerActive) {
scheduleSelectionReport(160);
}
});
document.addEventListener("pointerdown", markPointerActive, true);
document.addEventListener("pointerup", markPointerReleased, true);
document.addEventListener("pointercancel", markPointerReleased, true);
document.addEventListener("touchstart", markPointerActive, true);
document.addEventListener("touchend", markPointerReleased, true);
document.addEventListener("touchcancel", markPointerReleased, true);
document.addEventListener("mousedown", markPointerActive, true);
document.addEventListener("mouseup", markPointerReleased, true);
document.addEventListener("keyup", function () { scheduleSelectionReport(80); });
window.addEventListener("scroll", function () { scheduleSelectionReport(80); }, false);
}
window.VIEWPORT_PADDING_TOP = 0;
@ -766,6 +891,8 @@
var alignSelector = "body, p, li, div, h1, h2, h3, h4, h5, h6";
if (textAlign === "left") {
alignCss = alignSelector + " { text-align: left !important; }";
} else if (textAlign === "right") {
alignCss = alignSelector + " { text-align: right !important; }";
} else if (textAlign === "justify") {
alignCss = alignSelector + " { text-align: justify !important; -webkit-hyphens: auto !important; hyphens: auto !important; }";
}