@ -71,7 +71,7 @@ KOReader is developed and supported by volunteers all around the world. There ar
- document lesser-known features on the [wiki][link-wiki]
- help others with your knowledge on the [forum][link-forum]
Right now we only support [liberapay](https://liberapay.com/KOReader) donations.
Right now we only support [liberapay](https://liberapay.com/KOReader) donations, but you can also create a [bounty][link-bountysource] to motivate others to work on a specific bug or feature request.
@ -17,10 +17,10 @@ Each target has its own architecture and you'll need to setup a proper cross-com
A compatible version of the Android NDK and SDK will be downloaded automatically by `./kodev release android` if no NDK or SDK is provided in environment variables. For that purpose you can use:
If you want to use your own installed tools please make sure that you have the **NDKr23c** and the SDK for Android 9 (**API level 28**) already installed.
If you want to use your own installed tools please make sure that you have the **NDKr15c** and the SDK for Android 9 (**API level 28**) already installed.
text=_("Scan books in current folder and subfolders for their metadata location?"),
ok_text=_("Scan"),
ok_callback=function()
localbooks_to_move=scanPath()
localbooks_to_move_nb=#books_to_move
ifbooks_to_move_nb==0then
UIManager:show(InfoMessage:new{
text=_("No books with metadata not in your preferred location found."),
})
else
UIManager:show(ConfirmBox:new{
text=T(N_("1 book with metadata not in your preferred location found.",
"%1 books with metadata not in your preferred location found.",
books_to_move_nb),books_to_move_nb).."\n"..
_("Move book metadata to your preferred location?"),
ok_text=_("Move"),
ok_callback=function()
UIManager:close(self.menu_container)
for_,bookinipairs(books_to_move)do
DocSettings.updateLocation(book,book)
end
file_chooser:refreshPath()
end,
})
end
end,
})
end
functionBookInfo.showBooksWithHashBasedMetadata()
localheader=T(_("Hash-based metadata has been saved in %1 for the following documents. Hash-based storage may slow down file browser navigation in large directories. Thus, if not using hash-based metadata storage, it is recommended to open the associated documents in KOReader to automatically migrate their metadata to the preferred storage location, or to delete %1, which will speed up file browser navigation."),
-- We default to a flag (G2) that slightly boosts saturation,
-- but it *is* a destructive process, so we want to allow disabling it.
-- @translators CFA is a technical term for the technology behind eInk's color panels. It stands for Color Film/Filter Array, leave the abbreviation alone ;).
@ -120,10 +119,6 @@ function ReaderHandMade:onToggleHandmadeFlows()
end
functionReaderHandMade:addToMainMenu(menu_items)
-- As it's currently impossible to create custom hidden flows on non-touch, and really impractical to create a custom toc, it's better hide these features completely for now.
ifnotDevice:isTouchDevice()then
return
end
menu_items.handmade_toc={
text=_("Custom table of contents")..""..self.custom_toc_symbol,
checked_func=function()returnself.toc_enabledend,
@ -489,7 +484,6 @@ function ReaderHandMade:addOrEditPageTocItem(pageno, when_updated_callback, sele
{"font-size: 1rem !important;",_("1rem will enforce your main font size.")},
{"font-weight: normal !important;",_("Remove bold. Use 'bold' to get bold.")},
{"hyphens: none !important;",_("Disables hyphenation inside the targeted elements.")},
{"text-indent: 1.2em !important;",_("1.2em is our default text indentation.")},
{"break-before: always !important;",_("Start a new page with this element. Use 'avoid' to avoid a new page.")},
{"color: black !important;",_("Force text to be black.")},
{"background: transparent !important;",_("Remove any background color.")},
{"max-width: 50vw !important;",_("Limit an element width to 50% of your screen width (use 'max-height: 50vh' for 50% of the screen height). Can be useful with <img> to limit their size.")},
}},
{_("Private CSS properties"),{
{"-cr-hint: footnote-inpage;",_("When set on a block element containing the target id of a href, this block element will be shown as an in-page footnote.")},
{"-cr-hint: non-linear;",_("Can be set on some specific DocFragments (e.g. DocFragment[id$=_16]) to ignore them in the linear pages flow.")},
{"-cr-hint: non-linear-combining;",_("Can be set on contiguous footnote blocks to ignore them in the linear pages flow.")},
{"-cr-hint: toc-level1;",_("When set on an element, its text can be used to build the alternative table of contents. toc-level2 to toc-level6 can be used for nested chapters.")},
{"-cr-hint: toc-ignore;",_("When set on an element, it will be ignored when building the alternative table of contents.")},
{"-cr-hint: footnote;",_("Can be set on target of links (<div id='..'>) to have their link trigger as footnote popup, in case KOReader wrongly detect this target is not a footnote.")},
{"-cr-hint: noteref;",_("Can be set on links (<a href='#..'>) to have them trigger as footnote popups, in case KOReader wrongly detect the links is not to a footnote.")},
{"::before {content: ' '}",_("Insert a visible space before an element.")},
{"::before {content: '\\A0 '}",_("Insert a visible non-breakable space before an element, so it sticks to what's before.")},
{"::before {content: '\\2060'}",_("U+2060 WORD JOINER may act as a glue (like an invisible non-breakable space) before an element, so it sticks to what's before.")},
{"::before {content: '\\200B'}",_("U+200B ZERO WIDTH SPACE may allow a linebreak before an element, in case the absence of any space prevents that.")},
{"::before {content: attr(title)}",_("Insert the value of the attribute 'title' at start of an element content.")},
{"::before {content: '▶ '}",_("Prepend a visible marker.")},
{"::before {content: '● '}",_("Prepend a visible marker.")},
{"::before {content: '█ '}",_("Prepend a visible marker.")},
}},
{"-cr-hint: footnote-inpage;",_("When set on a block element containing the target id of a href, this block element will be shown as an in-page footnote.")},
{"-cr-hint: non-linear-combining;",_("Can be set on some specific DocFragments (ie. DocFragment[id*=16]) to ignore them in the linear pages flow.")},
{"-cr-hint: toc-level1;",_("When set on an element, its text can be used to build the alternative table of contents.")},
{"display: run-in !important,",_("When set on a block element, this element content will be inlined with the next block element.")},
{"font-size: 1rem !important;",_("1rem will enforce your main font size")},
{"hyphens: none !important",_("Disables hyphenation inside the targeted elements.")},
{"text-indent: 1.2em !important;",_("1.2em is our default text indentation.")},
@ -17,6 +17,7 @@ local ReaderTypeset = WidgetContainer:extend{
-- @translators This is style in the sense meant by CSS (cascading style sheets), relating to the layout and presentation of the document. See <https://en.wikipedia.org/wiki/CSS> for more information.
-- if fb2_compatible==nil, we don't know (user css file)
returntrue
end,
separator=separator,
}
end
@ -206,18 +189,8 @@ function ReaderTypeset:genStyleSheetMenu()
localstyle_table={}
localobsoleted_table={}
table.insert(style_table,getStyleMenuItem(
_("None"),
"",
_("This sets an empty User-Agent stylesheet, and expects the document stylesheet to style everything (which publishers probably don't).\nThis is mostly only interesting for testing.")
))
table.insert(style_table,getStyleMenuItem(
_("Auto"),
nil,
_("This selects the default and preferred stylesheet for the document type."),
Itmaycausesomesmallissuesonsomebooks(miscenteredtitles,headingsorseparators,orunexpectedtextindentation),aspublishersdon't expect to have our added styles at play and need to reset them; try switching to html5.css when you notice such issues.]]),
-- Add the obsoleted ones to the Obsolete sub menu
@ -267,7 +216,7 @@ This stylesheet is to be used only with FB2 and FB3 documents, which are not cla
for__,cssinipairs(OBSOLETED_CSS)do
obsoleted_css[css_files[css]]=css
ifcss_files[css]then
table.insert(obsoleted_table,getStyleMenuItem(css,css_files[css], _("This stylesheet is obsolete: don't use it. It is kept solely to be able to open documents last read years ago and to migrate their highlights.")))
timev=tev.timev,-- A ref is enough for this table, it's re-assigned to a new object on every SYN_REPORT
}
end
-- Contact object, it'll keep track of everything we need for a single contact across its lifetime
-- i.e., from this contact's down to up (or its *effective* up for double-taps, e.g., when the tap or double_tap is emitted).
-- We'll identify contacts by their slot numbers, and store 'em in GestureDetector's active_contacts table (hash).
@ -149,7 +139,7 @@ function GestureDetector:newContact(slot)
state=Contact.initialState,-- Current state function
slot=slot,-- Current ABS_MT_SLOT value (also its key in the active_contacts hash)
id=-1,-- Current ABS_MT_TRACKING_ID value
initial_tev=nil,-- Copy of the input event table at first contact (i.e., at contact down [iff the platform is sane, might be a copy of current_tev otherwise])
initial_tev=nil,-- Copy of the input event table at first contact (i.e., at contact down)
current_tev=nil,-- Pointer to the current input event table, ref is *stable*, c.f., NOTE in feedEvent below
down=false,-- Contact is down (as opposed to up, i.e., lifted). Only really happens for double-tap handling, in every other case the Contact object is destroyed on lift.
pending_double_tap_timer=false,-- Contact is pending a double_tap timer
@ -167,12 +157,6 @@ function GestureDetector:newContact(slot)
-- If we have a buddy contact, point its own buddy ref to us
-- Must be a class member, both because Input is a singleton and that state is process-wide anyway.
opened_devices={},
}
functionInput:new(o)
@ -225,10 +223,6 @@ function Input:init()
},
}
-- Always send pen data to a slot far enough away from our main finger slot that it can never be matched with a finger buddy in GestureDetector (i.e., +/- 1),
-- with an extra bit of leeway, since we don't even actually support three finger gestures ;).
self.pen_slot=self.main_finger_slot+4
self.gesture_detector=GestureDetector:new{
screen=self.device.screen,
input=self,
@ -252,9 +246,8 @@ function Input:init()
end
-- set up fake event map
self.event_map[10000]="IntoSS"-- Requested to go into screen saver
self.event_map[10001]="OutOfSS"-- Requested to go out of screen saver
self.event_map[10002]="ExitingSS"-- Specific to Kindle, SS *actually* closed
self.event_map[10000]="IntoSS"-- go into screen saver
self.event_map[10001]="OutOfSS"-- go out of screen saver
self.event_map[10010]="UsbPlugIn"
self.event_map[10011]="UsbPlugOut"
self.event_map[10020]="Charging"
@ -300,97 +293,14 @@ function Input:disableRotationMap()
@ -1171,29 +1053,29 @@ function Input:initMtSlot(slot)
end
end
functionInput:getMtSlot(slot)
returnself.ev_slots[slot]
end
functionInput:getCurrentMtSlot()
returnself.ev_slots[self.cur_slot]
end
functionInput:setMtSlot(slot,key,val)
self.ev_slots[slot][key]=val
end
functionInput:setCurrentMtSlot(key,val)
self.ev_slots[self.cur_slot][key]=val
self:setMtSlot(self.cur_slot,key,val)
end
-- Same as above, but ensures the current slot actually has a live ref first
functionInput:setCurrentMtSlotChecked(key,val)
ifnotself.active_slots[self.cur_slot]then
if#self.MTSlots==0then
self:addSlot(self.cur_slot)
end
self.ev_slots[self.cur_slot][key]=val
self:setMtSlot(self.cur_slot,key,val)
end
functionInput:getMtSlot(slot)
returnself.ev_slots[slot]
end
functionInput:getCurrentMtSlot()
returnself:getMtSlot(self.cur_slot)
end
functionInput:getCurrentMtSlotData(key)
@ -1220,13 +1102,22 @@ function Input:addSlot(value)
self.cur_slot=value
end
functionInput:addSlotIfChanged(value)
ifself.cur_slot~=valuethen
-- We've already seen that slot in this frame, don't insert a duplicate reference!
ifself.active_slots[value]then
self.cur_slot=value
else
self:addSlot(value)
end
end
end
functionInput:setupSlotData(value)
ifnotself.active_slots[value]then
if#self.MTSlots==0then
self:addSlot(value)
else
-- We've already seen that slot in this frame, don't insert a duplicate reference!
-- NOTE: May already be set to the correct value if the driver repeats ABS_MT_SLOT (e.g., our android/PB translation layers; or ABS_MT_TRACKING_ID for snow_protocol).
night_mode={category="none",event="ToggleNightMode",title=_("Toggle night mode"),screen=true},
set_night_mode={category="string",event="SetNightMode",title=_("Set night mode"),screen=true,args={true,false},toggle={_("on"),_("off")},separator=true},
set_mixed_sorting={category="string",event="SetMixedSorting",title=_("Folders and files mixed"),args={true,false},toggle={_("on"),_("off")},filemanager=true,separator=true},
title=_("Ignore tables related HTML presentational hints"),
description=_("Ignore HTML attributes that contribute to styles on the <table> element and its sub-elements (ie. align, valign, frame, rules, border, cellpadding, cellspacing…)."),
text=T(_("KOReader %1\n\nA document viewer for E Ink devices.\n\nLicensed under Affero GPL v3. All dependencies are free software.\n\nhttp://koreader.rocks"),BD.ltr(Version:getCurrentRevision())),
icon="koreader",
})
end
}
common_info.report_bug={
text_func=function()
locallabel=_("Report a bug")
ifG_reader_settings:isTrue("debug_verbose")then
label=label.."".._("(verbose logging is enabled)")
localcommon_msg=T(_("Please report bugs to \nhttps://github.com/koreader/koreader/issues\n\nVersion:\n%1\n\nDetected device:\n%2"),
Version:getCurrentRevision(),Device:info())
locallog_msg=T(_("Verbose logs will make our investigations easier. If possible, try to reproduce the issue while it's enabled, and attach %1 to your bug report."),log_path)
locallog_msg=T(_("Attach %1 to your bug report."),log_path)
text=T(_("KOReader %1\n\nA document viewer for E Ink devices.\n\nLicensed under Affero GPL v3. All dependencies are free software.\n\nhttp://koreader.rocks"),BD.ltr(Version:getCurrentRevision())),
@ -391,6 +398,7 @@ local function genGenericMenuEntry(title, setting, value, default, radiomark)
end,
}
end
common_settings.back_to_exit={
text_func=function()
localback_to_exit=G_reader_settings:readSetting("back_to_exit","prompt")-- set "back_to_exit" to "prompt"
@ -533,23 +541,23 @@ common_settings.document = {
}
localmetadata_folder_str={
["doc"]=_("book folder"),
["dir"]=DocSettings.getSidecarStorage("dir"),
["hash"]=DocSettings.getSidecarStorage("hash"),
["doc"]=_("book folder"),
["dir"]=DataStorage:getDocSettingsDir(),
["hash"]=DataStorage:getDocSettingsHashDir()
}
localmetadata_folder_help_table={
_("Book view settings, reading progress, highlights, bookmarks and notes (collectively known as metadata) are stored in a separate folder named <book-filename>.sdr (\".sdr\" meaning \"sidecar\")."),
"",
_("You can decide between three locations/methods where these will be saved:"),
_(" - alongside the book file itself (the long time default): sdr folders will be visible when you browse your library directories with another file browser or from your computer, which may clutter your vision of your library. But this allows you to move them along when you reorganize your library, and also survives any renaming of parent directories. Also, if you perform directory synchronization or backups, your settings will be part of them."),
T(_(" - all in %1: sdr folders will only be visible and used by KOReader, and won't clutter your vision of your library directories with another file browser or from your computer. But any reorganisation of your library (directories or filename moves and renamings) may result in KOReader not finding your previous settings for these books. These settings won't be part of any synchronization or backups of your library."),metadata_folder_str.dir),
T(_(" - all inside %1 as hashes: sdr folders are identified not by filepath/filename but by partial MD5 hash, allowing you to rename, move, and copy documents outside of KOReader without sdr folder clutter while keeping them linked to their metadata. However, any file modifications such as writing highlights into PDFs or downloading from calibre may change the hash, and thus lose their linked metadata. Calculating file hashes may also slow down file browser navigation. This option may suit users with multiple copies of documents across different devices and directories."),metadata_folder_str.hash),
localhash_filemod_warn=T(_("%1 requires calculating partial file hashes of documents which may slow down file browser navigation. Any file modifications (such as embedding annotations into PDF files or downloading from calibre) may change the partial hash, thereby losing track of any highlights, bookmarks, and progress data. Embedding PDF annotations is currently set to \"%s\" and can be disabled at (⚙ → Document → Save Document (write highlights into PDF))."),metadata_folder_str.hash)
localleaving_hash_sdr_warn=_("Warning: You currently have documents with hash-based metadata. Until this metadata is moved by opening those documents, or deleted, file browser navigation may remain slower.")
localmetadata_folder_help_doc=T(_(" - alongside the book file itself (the long time default): sdr folders will be visible when you browse your library directories with another file browser or from your computer, which may clutter your vision of your library. But this allows you to move them along when you reorganize your library, and also survives any renaming of parent directories. Also, if you perform directory synchronization or backups, your settings will be part of them."))
localmetadata_folder_help_dir=T(_(" - all in %1: sdr folders will only be visible and used by KOReader, and won't clutter your vision of your library directories with another file browser or from your computer. But any reorganisation of your library (directories or filename moves and renamings) may result in KOReader not finding your previous settings for these books. These settings won't be part of any synchronization or backups of your library."),DataStorage:getDocSettingsDir())
localmetadata_folder_help_hash=T(_(" - all inside %1 as hashes: sdr folders are identified not by filepath/filename but by partial MD5 hash, allowing you to rename, move, and copy documents outside of KOReader without sdr folder clutter while keeping them linked to their metadata. However, any file modifications such as writing highlights into PDFs or downloading from calibre may change the hash, and thus lose their linked metadata. Calculating file hashes may also slow down file browser navigation. This option may suit users with multiple copies of documents across different devices and directories."),DataStorage:getDocSettingsHashDir())
localhash_filemod_warn=T(_([[%1 requires calculating partial file hashes of documents which may slow down file browser navigation. Any file modifications (such as embedding annotations into PDF files or downloading from calibre) may change the partial hash, thereby losing track of any highlights, bookmarks, and progress data. Embedding PDF annotations is currently set to "%s" and can be disabled at (⚙ → Document → Save Document (write highlights into PDF)).]]),DataStorage:getDocSettingsHashDir())
localleaving_hash_sdr_warn=T(_("Warning: You currently have documents with hash-based metadata. Until this metadata is moved by opening those documents, or deleted, file browser navigation may remain slower."))
Onlyfontsnamed"Noto Sans xyz"or"Noto Sans xyz UI"(regular,notboldnoritalic,notSerif)willbeavailableinthismenu.However,boldfontswillbeusediftheircorrespondingregularfontsexist.]]),"","<EFBFBD><EFBFBD>")
Onlyfontsnamed"Noto Sans xyz"or"Noto Sans xyz UI"(regular,notboldnoritalic,notSerif)willbeavailableinthismenu.However,boldfontswillbeusediftheircorrespondingregularfontsexist.]])