diff --git a/src/pyj/read_book/goto.pyj b/src/pyj/read_book/goto.pyj index 884fec5a01..b0611d50e2 100644 --- a/src/pyj/read_book/goto.pyj +++ b/src/pyj/read_book/goto.pyj @@ -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) ) )) diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index ef7764c9da..53f9418d9e 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -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): diff --git a/src/pyj/read_book/prefs/head_foot.pyj b/src/pyj/read_book/prefs/head_foot.pyj index 45d2b193d0..4da855222e 100644 --- a/src/pyj/read_book/prefs/head_foot.pyj +++ b/src/pyj/read_book/prefs/head_foot.pyj @@ -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: diff --git a/src/pyj/read_book/ui.pyj b/src/pyj/read_book/ui.pyj index bc5914ce4e..0ca4101d0b 100644 --- a/src/pyj/read_book/ui.pyj +++ b/src/pyj/read_book/ui.pyj @@ -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) diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 1b7982cfac..06f001163e 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -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 diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 3714f9fdbf..53b82b0a23 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -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():