Viewer: Allow jumping to a book position, in addition to a CFI location via Go to->Location

This commit is contained in:
Kovid Goyal 2019-10-09 11:23:22 +05:30
parent 1cdface5ad
commit 3faa52ee58
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 87 additions and 30 deletions

View File

@ -9,6 +9,7 @@ from book_list.item_list import build_list, create_item
from dom import ensure_id, set_css
from modals import error_dialog
from read_book.globals import current_book, ui_operations
from read_book.prefs.head_foot import format_pos
from read_book.toc import get_border_nodes, get_toc_maps
from widgets import create_button
@ -50,11 +51,18 @@ def create_goto_panel(current_cfi, book, container, onclick):
container.appendChild(panel)
def create_location_overlay(current_cfi, overlay, container):
def create_location_overlay(current_position_data, overlay, container):
container_id = ensure_id(container)
container.appendChild(E.div(style='margin: 0 1rem'))
container = container.lastChild
container.appendChild(E.div(
style='padding-top: 1rem',
E.h4(_('Using book location (most accurate)'))
))
current_cfi = current_position_data.cfi
if current_cfi:
container.appendChild(E.div(
style='margin: 1rem; display: flex; align-items: baseline',
container.lastChild.appendChild(E.div(
style='margin: 1rem 0; display: flex; align-items: baseline',
E.input(
type='text', readonly='readonly', value=_('Currently at: {}').format(current_cfi), name='current_location',
style='border-width: 0; background-color: transparent; outline: none; flex-grow: 10; font-family: inherit'
@ -73,20 +81,53 @@ def create_location_overlay(current_cfi, overlay, container):
)
))
container.appendChild(E.div(
style='margin: 1rem;',
def goto_loc():
src = document.querySelector(f'#{container_id} [name=newloc]')
if src.value:
if ui_operations.goto_bookpos(src.value):
overlay.hide()
else:
error_dialog(_('No such location'), _(
'No location {} found').format(src.value))
container.lastChild.appendChild(E.div(
style='margin: 1rem 0;',
E.div(
style='display: flex; align-items: baseline',
E.label(_('Go to:'), style='margin-right: 1rem'),
E.input(name='newloc', type='text', style='flex-grow: 10; margin-right: 1rem'), E.span(' '),
create_button(_('Go'), action=def():
src = document.querySelector(f'#{container_id} [name=newloc]')
if src.value:
if ui_operations.goto_bookpos(src.value):
overlay.hide()
else:
error_dialog(_('No such location'), _(
'No location {} found').format(src.value))
)
E.input(name='newloc', type='text', style='flex-grow: 10; margin-right: 1rem', onkeydown=def(ev):
if ev.key is 'Enter':
goto_loc()
),
E.span(' '),
create_button(_('Go'), action=goto_loc)
)
))
container.appendChild(E.div(
style='margin-top: 1rem; border-top: solid 1px; padding-top: 1rem',
E.h4(_('Using book position'))
))
if current_position_data.book_length > 0:
container.lastChild.appendChild(
E.div(style='margin: 1rem 0', _('Currently at: {}').format(
format_pos(current_position_data.progress_frac, current_position_data.book_length))))
def goto_pos():
src = document.querySelector(f'#{container_id} [name=newpos]')
val = max(0, min(1000 * float(src.value) / current_position_data.book_length, 1))
ui_operations.goto_frac(val)
overlay.hide()
container.lastChild.appendChild(E.div(
style='margin: 1rem 0;',
E.div(
style='display: flex; align-items: baseline',
E.label(_('Go to:'), style='margin-right: 1rem'),
E.input(name='newpos', type='number', min='0', max=str(current_position_data.book_length), step='0.1', style='flex-grow: 10; margin-right: 1rem', onkeydown=def(ev):
if ev.key is 'Enter':
goto_pos()
), E.span(' '),
create_button(_('Go'), action=goto_pos)
)
))

View File

@ -621,7 +621,7 @@ class Overlay:
def show_ask_for_location(self):
self.hide_current_panel()
self.panels.push(SimpleOverlay(
self, create_location_overlay.bind(None, self.view.currently_showing.bookpos), _('Go to location…')))
self, create_location_overlay.bind(None, self.view.current_position_data), _('Go to location…')))
self.show_current_panel()
def show_search(self):

View File

@ -144,14 +144,14 @@ def format_pos(progress_frac, length):
return f'{pos:.1f} / {pages}'
def render_head_foot(div, which, region, progress_frac, metadata, current_toc_node, current_toc_toplevel_node, book_time, chapter_time, pos):
def render_head_foot(div, which, region, metadata, current_toc_node, current_toc_toplevel_node, book_time, chapter_time, pos):
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))
percent = min(100, max(Math.round(pos.progress_frac * 100), 0))
text = percent + '%'
elif field is 'title':
text = metadata.title or _('Untitled')
@ -182,9 +182,9 @@ def render_head_foot(div, which, region, progress_frac, metadata, current_toc_no
text = '{} ({})'.format(format_time_left(chapter_time), format_time_left(book_time))
elif field.startswith('pos-'):
if field is 'pos-book':
text = format_pos(pos.current_progress_frac, pos.book_length)
text = format_pos(pos.progress_frac, pos.book_length)
else:
text = format_pos(pos.current_file_progress_frac, pos.chapter_length)
text = format_pos(pos.file_progress_frac, pos.chapter_length)
if not text:
text = '\xa0'
if text is not div.textContent:

View File

@ -66,6 +66,7 @@ class ReadUI:
ui_operations.update_color_scheme = self.update_color_scheme.bind(self)
ui_operations.update_font_size = self.update_font_size.bind(self)
ui_operations.goto_bookpos = self.goto_bookpos.bind(self)
ui_operations.goto_frac = self.goto_frac.bind(self)
ui_operations.delete_book = self.delete_book.bind(self)
ui_operations.focus_iframe = self.focus_iframe.bind(self)
ui_operations.toggle_toc = self.toggle_toc.bind(self)
@ -162,6 +163,9 @@ class ReadUI:
def goto_bookpos(self, bookpos):
return self.view.goto_bookpos(bookpos)
def goto_frac(self, frac):
return self.view.goto_frac(frac)
def delete_book(self, book, proceed):
self.db.delete_book(book, proceed)

View File

@ -777,19 +777,29 @@ class View:
print('Failed to update last read position, AJAX call did not succeed')
)
def update_header_footer(self):
sd = get_session_data()
has_clock = False
@property
def current_position_data(self):
if self.book?.manifest:
book_length = self.book.manifest.spine_length or 0
name = self.currently_showing.name
chapter_length = self.book.manifest.files[name]?.length or 0
else:
book_length = chapter_length = 0
pos = {'current_progress_frac': self.current_progress_frac, 'book_length': book_length, 'chapter_length': chapter_length, 'current_file_progress_frac': self.current_file_progress_frac}
book_length *= max(0, 1 - self.current_progress_frac)
chapter_length *= max(0, 1 - self.current_file_progress_frac)
pos = {
'progress_frac': self.current_progress_frac,
'book_length': book_length, 'chapter_length': chapter_length,
'file_progress_frac': self.current_file_progress_frac,
'cfi': self.currently_showing?.bookpos
}
return pos
def update_header_footer(self):
sd = get_session_data()
has_clock = False
pos = self.current_position_data
book_length = pos.book_length * max(0, 1 - pos.progress_frac)
chapter_length = pos.chapter_length * max(0, 1 - pos.file_progress_frac)
book_time = self.timers.time_for(book_length)
chapter_time = self.timers.time_for(chapter_length)
@ -797,9 +807,9 @@ class View:
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, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
textb, hcb = render_head_foot(div.firstChild.nextSibling, name, 'middle', self.current_progress_frac, mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
textc, hcc = render_head_foot(div.lastChild, name, 'right', self.current_progress_frac, mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
texta, hca = render_head_foot(div.firstChild, name, 'left', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
textb, hcb = render_head_foot(div.firstChild.nextSibling, name, 'middle', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
textc, hcc = render_head_foot(div.lastChild, name, 'right', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
has_clock = hca or hcb or hcc
if textc and not textb and not texta:
# Want right-aligned

View File

@ -282,6 +282,8 @@ if window is window.top:
view.focus_iframe()
ui_operations.goto_bookpos = def(cfi):
return view.goto_bookpos(cfi)
ui_operations.goto_frac = def(frac):
return view.goto_frac(frac)
ui_operations.toggle_toc = def():
to_python.toggle_toc()
ui_operations.toggle_bookmarks = def():