From 4fd521a88b2445fee0ee2e26058f46e1f0fed144 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 29 Nov 2020 08:44:13 +0530 Subject: [PATCH] Start work on Read aloud mode --- src/pyj/read_book/read_aloud.pyj | 79 ++++++++++++++++++++++++++++++++ src/pyj/read_book/view.pyj | 7 +++ 2 files changed, 86 insertions(+) create mode 100644 src/pyj/read_book/read_aloud.pyj diff --git a/src/pyj/read_book/read_aloud.pyj b/src/pyj/read_book/read_aloud.pyj new file mode 100644 index 0000000000..7df1a0a415 --- /dev/null +++ b/src/pyj/read_book/read_aloud.pyj @@ -0,0 +1,79 @@ +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2020, Kovid Goyal +from __python__ import bound_methods, hash_literals + +from elementmaker import E + +from book_list.theme import get_color +from dom import clear, unique_id +from read_book.globals import runtime + +HIDDEN = 0 +PAUSED = 1 +PLAYING = 2 + + +class ReadAloud: + + def __init__(self, view): + self.view = view + self.state = HIDDEN + self.bar_id = unique_id('bar') + container = self.container + container.setAttribute('tabindex', '0') + container.style.overflow = 'hidden' + container.appendChild(E.div( + id=self.bar_id, + style='position: fixed; border: solid 1px currentColor; border-radius: 5px;' + 'right: 95vw; top: 0; display: flex; flex-direction: column;' + )) + + @property + def container(self): + return document.getElementById('book-read-aloud-overlay') + + @property + def supports_css_min_max(self): + return not runtime.is_standalone_viewer or runtime.QT_VERSION >= 0x050f00 + + @property + def bar(self): + return document.getElementById(self.bar_id) + + @property + def is_visible(self): + return self.container.style.display is not 'none' + + def hide(self): + self.state = HIDDEN + self.container.style.display = 'none' + self.view.focus_iframe() + + def show(self): + if self.state is HIDDEN: + self.container.style.display = 'block' + self.state = PAUSED + self.focus() + + def focus(self): + self.container.focus() + + def build_bar(self, annot_id): + bar_container = self.bar + clear(bar_container) + bar_container.style.maxWidth = 'min(50rem, 90vw)' if self.supports_css_min_max else '50rem' + bar_container.style.backgroundColor = get_color("window-background") + notes_container = E.div() + for x in [ + E.div(style='height: 4ex; display: flex; align-items: center; padding: 5px; justify-content: center'), + + E.hr(style='border-top: solid 1px; margin: 0; padding: 0; display: none'), + + E.div( + style='display: none; padding: 5px;', + notes_container, + ) + ]: + bar_container.appendChild(x) + bar = bar_container.firstChild + bar diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 46d943039b..d8136599ae 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -34,6 +34,7 @@ from read_book.resources import load_resources from read_book.scrollbar import BookScrollbar from read_book.search import SearchOverlay, find_in_spine from read_book.selection_bar import SelectionBar +from read_book.read_aloud import ReadAloud from read_book.shortcuts import create_shortcut_map from read_book.timers import Timers from read_book.toc import get_current_toc_nodes, update_visible_toc_nodes @@ -243,6 +244,7 @@ class View: right_margin, self.book_scrollbar.create(), E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-selection-bar-overlay'), # selection bar overlay + E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-read-aloud-overlay'), # read aloud overlay E.div(style='position: absolute; top:0; left:0; width: 100%; pointer-events:none; display:none', id='book-search-overlay'), # search overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='book-content-popup-overlay'), # content popup overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; overflow: auto; display:none', id='book-overlay'), # main overlay @@ -313,6 +315,7 @@ class View: self.content_popup_overlay = ContentPopupOverlay(self) self.overlay = Overlay(self) self.selection_bar = SelectionBar(self) + self.read_aloud = ReadAloud(self) self.processing_spine_item_display = False self.pending_load = None self.currently_showing = {'selection': {'empty': True}} @@ -444,6 +447,7 @@ class View: ui_operations.overlay_visibility_changed(visible) if visible: self.selection_bar.hide() + self.read_aloud.hide() else: self.selection_bar.update_position() @@ -659,6 +663,8 @@ class View: def focus_iframe(self): if self.selection_bar.is_visible: self.selection_bar.focus() + elif self.read_aloud.is_visible: + self.read_aloud.focus() else: self.iframe.contentWindow.focus() @@ -1256,6 +1262,7 @@ class View: def on_content_loaded(self, data): self.selection_bar.hide() + self.read_aloud.hide() self.processing_spine_item_display = False self.currently_showing.loading = False self.hide_loading()