Created
September 11, 2025 19:10
-
-
Save mallomar/6a4c017ebbb30f4f5354b9271429f64c to your computer and use it in GitHub Desktop.
Advise you if file appears to have been modified since binary checksum hash was created, which could affect syncing which depends on binary hash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[[ | |
| KOReader Patch: File Modification Warning | |
| Alerts when book files may have been modified since sync hash was calculated | |
| --]] | |
| local ConfirmBox = require("ui/widget/confirmbox") | |
| local DocSettings = require("docsettings") | |
| local UIManager = require("ui/uimanager") | |
| local InfoMessage = require("ui/widget/infomessage") | |
| local lfs = require("libs/libkoreader-lfs") | |
| -- Function to get file modification time | |
| local function getFileModTime(file_path) | |
| local attr = lfs.attributes(file_path) | |
| return attr and attr.modification or 0 | |
| end | |
| -- Function to check if file appears modified since hash calculation | |
| local function checkFileModification(file_path, doc_settings) | |
| if not file_path or not lfs.attributes(file_path) then return end | |
| local stored_hash = doc_settings:readSetting("partial_md5_checksum") | |
| if not stored_hash then return end -- No stored hash, nothing to check | |
| local file_mod_time = getFileModTime(file_path) | |
| local last_check_time = doc_settings:readSetting("file_mod_last_check") or 0 | |
| local ignored_time = doc_settings:readSetting("file_mod_ignored") or 0 | |
| -- Only notify if file was modified after our last check and user hasn't recently ignored | |
| if file_mod_time <= last_check_time or (os.time() - ignored_time) < 86400 then -- 24 hour grace period | |
| return | |
| end | |
| -- Show warning about potential file modification | |
| local filename = file_path:match("([^/]+)$") or "Unknown" | |
| UIManager:show(ConfirmBox:new{ | |
| text = "Sync Warning: File Modified\n\n" .. | |
| "File: " .. filename .. "\n\n" .. | |
| "This file appears to have been modified since the sync hash was calculated. " .. | |
| "This may cause sync failures with external services.\n\n" .. | |
| "Options:\n" .. | |
| "• Keep current setup (sync may fail)\n" .. | |
| "• Wait for fingerprint-based sync solutions\n" .. | |
| "• Manually manage bookmarks if sync is critical\n\n" .. | |
| "Dismiss this warning?", | |
| ok_text = "Dismiss", | |
| cancel_text = "Remind Later", | |
| ok_callback = function() | |
| -- Mark that user dismissed this warning | |
| doc_settings:saveSetting("file_mod_ignored", os.time()) | |
| doc_settings:saveSetting("file_mod_last_check", os.time()) | |
| doc_settings:flush() | |
| end, | |
| cancel_callback = function() | |
| -- Just update check time, will remind again if file changes more | |
| doc_settings:saveSetting("file_mod_last_check", os.time()) | |
| doc_settings:flush() | |
| end, | |
| }) | |
| end | |
| -- Function to show current file status | |
| local function showFileStatus() | |
| local ReaderUI = require("apps/reader/readerui") | |
| if not (ReaderUI.instance and ReaderUI.instance.document and ReaderUI.instance.document.file) then | |
| UIManager:show(InfoMessage:new{ | |
| text = "No document currently open." | |
| }) | |
| return | |
| end | |
| local file_path = ReaderUI.instance.document.file | |
| local doc_settings = DocSettings:open(file_path) | |
| local stored_hash = doc_settings:readSetting("partial_md5_checksum") | |
| local filename = file_path:match("([^/]+)$") or "Unknown" | |
| if not stored_hash then | |
| UIManager:show(InfoMessage:new{ | |
| text = "No sync hash found for this book.\n\nHash will be calculated on first sync attempt." | |
| }) | |
| return | |
| end | |
| local file_mod_time = getFileModTime(file_path) | |
| local last_check_time = doc_settings:readSetting("file_mod_last_check") or 0 | |
| local status_text = "File Sync Status\n\n" .. | |
| "File: " .. filename .. "\n" .. | |
| "Sync Hash: " .. stored_hash:sub(1, 8) .. "...\n\n" | |
| if file_mod_time > last_check_time then | |
| status_text = status_text .. "⚠ File may have been modified since hash was calculated.\n" .. | |
| "Sync with external services may fail.\n\n" .. | |
| "Consider waiting for fingerprint-based sync solutions." | |
| else | |
| status_text = status_text .. "✓ File appears unchanged since last check.\n" .. | |
| "Sync should work normally." | |
| end | |
| UIManager:show(InfoMessage:new{ | |
| text = status_text | |
| }) | |
| end | |
| -- Create menu item | |
| local function createFileStatusMenuItem() | |
| return { | |
| text = "Check File Sync Status", | |
| callback = function() | |
| showFileStatus() | |
| end, | |
| } | |
| end | |
| -- Add menu items | |
| local function patchMenu(menu, order) | |
| if order and order.more_tools then | |
| table.insert(order.more_tools, "file_sync_status") | |
| menu.menu_items.file_sync_status = createFileStatusMenuItem() | |
| elseif order and order.tools then | |
| table.insert(order.tools, "file_sync_status") | |
| menu.menu_items.file_sync_status = createFileStatusMenuItem() | |
| else | |
| menu.menu_items.file_sync_status = createFileStatusMenuItem() | |
| end | |
| end | |
| -- Hook into ReaderMenu | |
| local ok_reader_menu, ReaderMenu = pcall(require, "apps/reader/modules/readermenu") | |
| if ok_reader_menu then | |
| local orig_ReaderMenu_setUpdateItemTable = ReaderMenu.setUpdateItemTable | |
| ReaderMenu.setUpdateItemTable = function(self) | |
| local ok_order, reader_order = pcall(require, "ui/elements/reader_menu_order") | |
| if ok_order then | |
| patchMenu(self, reader_order) | |
| end | |
| orig_ReaderMenu_setUpdateItemTable(self) | |
| end | |
| end | |
| -- Hook into document opening to check for file modifications | |
| local ReaderUI = require("apps/reader/readerui") | |
| local orig_ReaderUI_showReader = ReaderUI.showReader | |
| ReaderUI.showReader = function(self, ...) | |
| orig_ReaderUI_showReader(self, ...) | |
| -- Schedule file modification check after document is fully loaded | |
| UIManager:scheduleIn(3, function() | |
| if self.document and self.document.file then | |
| local doc_settings = DocSettings:open(self.document.file) | |
| checkFileModification(self.document.file, doc_settings) | |
| end | |
| end) | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment