diff --git a/src/pyj/read_book/globals.pyj b/src/pyj/read_book/globals.pyj index c69de4c776..4401a56103 100644 --- a/src/pyj/read_book/globals.pyj +++ b/src/pyj/read_book/globals.pyj @@ -4,6 +4,7 @@ from __python__ import hash_literals from aes import GCM, random_bytes from encodings import hexlify +from gettext import gettext as _, register_callback, gettext as gt _boss = None @@ -49,3 +50,18 @@ def current_spine_item(): def set_current_spine_item(val): nonlocal _current_spine_item _current_spine_item = val + + +default_color_schemes = { + 'white':{'foreground':'black', 'background':'white', 'name':_('White')}, + 'black':{'foreground':'white', 'background':'black', 'name':_('Black')}, + 'sepia-light':{'foreground':'#643b0f', 'background':'#2a2c05', 'name':_('Sepia Light')}, + 'sepia-dark':{'background':'#643b0f', 'foreground':'#2a2c05', 'name':_('Sepia Dark')}, +} + +register_callback(def(): + # Ensure the color scheme names are translated + for key in default_color_schemes: + scheme = default_color_schemes[key] + scheme.name = gt(scheme.name) +) diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index 45388e0ba6..b0c4ef2015 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -4,6 +4,7 @@ from __python__ import bound_methods, hash_literals import traceback from aes import GCM +from elementmaker import E from gettext import install, gettext as _ from read_book.cfi import at_current, scroll_to as scroll_to_cfi from read_book.globals import set_boss, set_current_spine_item, current_layout_mode, current_spine_item, set_layout_mode @@ -19,7 +20,7 @@ from read_book.paged_mode import ( jump_to_cfi as paged_jump_to_cfi, handle_gesture as paged_handle_gesture, scroll_by_page as paged_scroll_by_page ) -from read_book.settings import apply_settings +from read_book.settings import apply_settings, opts from read_book.touch import create_handlers as create_touch_handlers from utils import debounce @@ -75,6 +76,7 @@ class IframeBoss: install(data.translations) window.onerror = self.onerror create_touch_handlers() + self.color_scheme = data.color_scheme def onerror(self, msg, script_url, line_number, column_number, error_object): console.log(error_object) @@ -135,6 +137,9 @@ class IframeBoss: def content_loaded(self): document.documentElement.style.overflow = 'hidden' + document.body.appendChild( + E.style(str.format('html, body {{ color: {} !important; background-color: {} !important }}', opts.color_scheme.foreground, opts.color_scheme.background)) + ) self.do_layout() if self.mathjax: return apply_mathjax(self.mathjax, self.book.manifest.link_uid, self.content_loaded_stage2) diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index 7fa311674e..922c6b9d7c 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -168,7 +168,7 @@ class MainOverlay: add_button('search', _('Search for text in this book')) add_button() add_button('Aa', _('Change text size'), text_button=True) - add_button('cogs', _('Configure the book reader')) + add_button('cogs', _('Configure the book reader'), self.overlay.show_prefs) add_button() def update_time(self): @@ -209,6 +209,20 @@ class TOCOverlay: # {{{ self.overlay.view.goto_named_destination(dest, frag) # }}} +class PrefsOverlay: # {{{ + + def __init__(self, overlay): + self.overlay = overlay + + def on_container_click(self, evt): + pass # Dont allow panel to be closed by a click + + def show(self, container): + container.style.backgroundColor = get_color('window-background') + create_prefs_panel(container, self.overlay.hide_current_panel) + +# }}} + class Overlay: def __init__(self, view): @@ -281,3 +295,7 @@ class Overlay: def show_toc(self): self.panels.push(TOCOverlay(self)) self.show_current_panel() + + def show_prefs(self): + self.panels.push(PrefsOverlay(self)) + self.show_current_panel() diff --git a/src/pyj/read_book/settings.pyj b/src/pyj/read_book/settings.pyj index d3ef78ecda..e37a9e499b 100644 --- a/src/pyj/read_book/settings.pyj +++ b/src/pyj/read_book/settings.pyj @@ -9,5 +9,6 @@ def apply_settings(settings): opts.cols_per_screen = max(1, settings.cols_per_screen or 1) opts.margin_left = max(0, settings.margin_left or 0) opts.margin_right = max(0, settings.margin_right or 0) + opts.color_scheme = settings.color_scheme apply_settings() diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 31eb1d9e76..ea90c3bd54 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -6,7 +6,7 @@ from book_list.globals import get_session_data, get_boss from dom import set_css, add_extra_css, build_rule, svgicon from elementmaker import E from gettext import gettext as _ -from read_book.globals import messenger, iframe_id +from read_book.globals import messenger, iframe_id, default_color_schemes from read_book.resources import load_resources from read_book.overlay import Overlay from book_list.theme import get_color @@ -34,7 +34,7 @@ __BS__ add_extra_css(def(): sel = '.book-side-margin' ans = build_rule(sel, cursor='pointer', color='rgba(0, 0, 0, 0)', text_align='center', height='100vh', user_select='none', display='flex', align_items='center', justify_content='center') - ans += build_rule(sel + ':hover', background_color=get_color('window-background'), color=get_color('window-foreground')) + ans += build_rule(sel + ':hover', background_color=get_color('window-background') + ' !important', color=get_color('window-foreground') + ' !important') ans += build_rule(sel + ':active > svg', color='red', transform='scale(2)') return ans ) @@ -176,6 +176,23 @@ class View: def on_iframe_error(self, data): self.ui.show_error((data.title or _('There was an error processing the book')), data.msg, data.details) + def get_color_scheme(self, apply_to_margins): + sd = get_session_data() + cs = sd.current_color_scheme or 'white' + if default_color_schemes[cs]: + ans = default_color_schemes[cs] + elif sd.user_color_schemes[cs] and sd.user_color_schemes[cs].foreground and sd.user_color_schemes[cs].background: + ans = sd.user_color_schemes[cs] + else: + ans = default_color_schemes['white'] + if apply_to_margins: + for which in 'left top right bottom'.split(' '): + s = document.getElementById('book-{}-margin'.format(which)).style + if which is 'top' or which is 'bottom': + s.color = ans.foreground # Setting a color for the side margins causes the hover arrow to become visible + s.backgroundColor = ans.background + return ans + def on_resize(self): pass @@ -222,6 +239,7 @@ class View: 'margin_right': 0 if name is self.book.manifest.title_page_name else sd.get('margin_right'), 'read_mode': sd.get('read_mode'), 'cols_per_screen': sd.get('cols_per_screen'), + 'color_scheme': self.get_color_scheme(True), } initial_position = initial_position or {'replace_history':False} self.currently_showing = {'name':name, 'settings':settings, 'initial_position':initial_position, 'loading':True} diff --git a/src/pyj/session.pyj b/src/pyj/session.pyj index 543a22f2fb..ab9ac181ab 100644 --- a/src/pyj/session.pyj +++ b/src/pyj/session.pyj @@ -26,6 +26,20 @@ defaults = { 'max_text_height': 0, 'max_text_width': 0, 'cols_per_screen': 1, + 'current_color_scheme': 'white', + 'user_color_schemes': {}, +} + +is_local_setting = { + 'margin_right': True, + 'margin_left': True, + 'margin_top': True, + 'margin_bottom': True, + 'read_mode': 'paged', + 'max_text_height': True, + 'max_text_width': True, + 'cols_per_screen': True, + 'current_color_scheme': True, } def storage_available(which): @@ -132,7 +146,8 @@ class UserSessionData(SessionData): self.push_timer_id = None if saved_data: for key in saved_data: - self.set(key, saved_data[key]) + if not is_local_setting[key]: + self.set(key, saved_data[key]) self.echo_changes = True def defval(self, key): @@ -152,7 +167,7 @@ class UserSessionData(SessionData): return self.get(lkey, defval) def set(self, key, value): - if self.echo_changes and self.has_user: + if self.echo_changes and self.has_user and not is_local_setting[key]: self.changes[key] = value self.has_changes = True if self.push_timer_id is not None: