Browser viewer: Allow customizing what information is displayed in the header and footer areas. Access Preferences from the viewer controls to change.

This commit is contained in:
Kovid Goyal 2018-01-03 20:15:43 +05:30
parent da032270d1
commit f4272115bf
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 90 additions and 14 deletions

View File

@ -7,13 +7,15 @@ from gettext import gettext as _
from book_list.globals import get_session_data
from dom import unique_id
from session import get_interface_data
from utils import fmt_sidx
CONTAINER = unique_id('reader-hf-prefs')
def create_item(region, label):
def sep():
return E.option('\xa0', disabled=True, style='min-height: 1pt; max-height: 1pt; font-size: 1pt; background-color: currentColor')
return E.option('\xa0', disabled=True)
def opt(label, name, selected):
return E.option(label, id=name, value=name, selected=bool(selected))
@ -26,6 +28,7 @@ def create_item(region, label):
sep(),
opt(_('Book title'), 'title'),
opt(_('Authors'), 'authors'),
opt(_('Series'), 'series'),
sep(),
opt(_('Top level section'), 'top-section'),
opt(_('Current section'), 'section'),
@ -85,6 +88,49 @@ def create_head_foot_panel(container):
def commit_head_foot(onchange, container):
sd = get_session_data()
changed = False
for which in 'header footer'.split(' '):
prev = sd.get(which) or {}
table = container.querySelector(f'table[data-which={which}]')
current = get_setting(table)
for region in 'left middle right'.split(' '):
if prev[region] is not current[region]:
changed = True
sd.set(which, get_setting(table))
if changed:
onchange()
if window.Intl?.DateTimeFormat:
date_formatter = window.Intl.DateTimeFormat(undefined, {'hour':'numeric', 'minute':'numeric'})
else:
date_formatter = {'format': def(date):
return '{}:{}'.format(date.getHours(), date.getMinutes())
}
def render_head_foot(div, which, region, progress_frac, metadata):
template = get_session_data().get(which) or {}
field = template[region] or 'empty'
interface_data = get_interface_data()
text = ''
has_clock = False
if field is 'progress':
percent = min(100, max(Math.round(progress_frac * 100), 0))
text = percent + '%'
elif field is 'title':
text = metadata.title or _('Untitled')
elif field is 'authors':
text = ' & '.join(metadata.authors or v'[]')
elif field is 'series':
if metadata.series:
ival = fmt_sidx(ival, use_roman=interface_data.use_roman_numerals_for_series_number)
text = _('{0} of {1}').format(ival, metadata.series)
elif field is 'clock':
text = date_formatter.format(Date())
has_clock = True
if text is not div.textContent:
div.textContent = text
div.style.display = 'block' if text else 'none'
return text, has_clock

View File

@ -6,7 +6,7 @@ from elementmaker import E
from gettext import gettext as _
from ajax import ajax_send
from book_list.book_details import render_metadata, CLASS_NAME as BD_CLASS_NAME
from book_list.book_details import CLASS_NAME as BD_CLASS_NAME, render_metadata
from book_list.globals import get_session_data
from book_list.router import push_state, read_book_mode
from book_list.theme import get_color
@ -19,6 +19,7 @@ from read_book.goto import get_next_section
from read_book.overlay import Overlay
from read_book.prefs.colors import resolve_color_scheme
from read_book.prefs.font_size import change_font_size_by
from read_book.prefs.head_foot import render_head_foot
from read_book.resources import load_resources
from read_book.search import SearchOverlay, find_in_spine
from read_book.toc import update_visible_toc_nodes
@ -93,10 +94,11 @@ def show_metadata_overlay(mi):
def margin_elem(sd, which, id, onclick):
sz = sd.get(which, 20)
fsz = min(max(0, sz - 6), 12)
s = '; text-overflow: ellipsis; white-space: nowrap; overflow: hidden'
ans = E.div(
style=f'height:{sz}px; overflow: hidden; font-size:{fsz}px; width:100%; padding: 0; display: flex; justify-content: space-between; align-items: center',
id=id,
E.div(), E.div()
E.div(style='margin-right: 1.5em' + s), E.div(style=s), E.div(style='margin-left: 1.5em' + s)
)
if onclick:
ans.addEventListener('click', onclick)
@ -114,6 +116,8 @@ class View:
def __init__(self, container, ui):
self.ui = ui
self.loaded_resources = {}
self.current_progress_frac = 0
self.clock_timer_id = 0
sd = get_session_data()
left_margin = E.div(svgicon('caret-left'), style='width:{}px;'.format(sd.get('margin_left', 20)), class_='book-side-margin', id='book-left-margin', onclick=self.left_margin_clicked)
set_left_margin_handler(left_margin)
@ -479,7 +483,8 @@ class View:
self.book.last_read_position[unkey] = data.cfi
self.ui.db.update_last_read_time(self.book)
lrd = {'device':get_device_uuid(), 'cfi':data.cfi, 'pos_frac':data.progress_frac}
self.update_read_percent(data.progress_frac)
self.current_progress_frac = data.progress_frac
self.update_header_footer()
key = self.book.key
if username:
ajax_send('book-set-last-read-position/{library_id}/{book_id}/{fmt}'.format(
@ -488,17 +493,41 @@ class View:
print('Failed to update last read position, AJAX call did not succeed')
)
def update_read_percent(self, pos_frac):
def update_header_footer(self):
sd = get_session_data()
has_clock = False
def render_template(div, sz_attr, name):
nonlocal has_clock
if sd.get(sz_attr, 20) > 5:
mi = self.book.metadata
texta, hca = render_head_foot(div.firstChild, name, 'left', self.current_progress_frac, mi)
textb, hcb = render_head_foot(div.firstChild.nextSibling, name, 'middle', self.current_progress_frac, mi)
textc, hcc = render_head_foot(div.lastChild, name, 'right', self.current_progress_frac, mi)
has_clock = hca or hcb or hcc
if textc and not textb and not texta:
# There is only a right, we want it to be right aligned,
# not left-aligned
div.firstChild.style.display = 'block'
div.firstChild.nextSibling.style.display = 'block'
else:
for c in div.childNodes:
c.style.display = 'none'
div = document.getElementById('book-bottom-margin')
if not div:
return
pcelem = div.lastChild
percent = min(100, max(Math.round(pos_frac * 100), 0))
text = percent + '%'
if text is not pcelem.textContent:
pcelem.textContent = text
pcelem.style.display = 'block' if sd.get('margin_bottom', 20) > 5 else 'none'
if div:
render_template(div, 'margin_bottom', 'footer')
div = document.getElementById('book-top-margin')
if div:
render_template(div, 'margin_top', 'header')
if has_clock:
if not self.clock_timer_id:
self.clock_timer_id = window.setInterval(self.update_header_footer, 60000)
else:
if self.clock_timer_id:
window.clearInterval(self.clock_timer_id)
self.clock_timer_id = 0
def on_update_toc_position(self, data):
update_visible_toc_nodes(data.visible_anchors)
@ -525,7 +554,8 @@ class View:
self.processing_spine_item_display = False
self.hide_loading()
frac = data.progress_frac or 0
self.update_read_percent(frac)
self.current_progress_frac = frac
self.update_header_footer()
window.scrollTo(0, 0) # ensure window is at 0 on mobile where the navbar causes issues
def update_font_size(self):