1# vim:fileencoding=utf-8 2# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net> 3from __python__ import bound_methods, hash_literals 4 5from elementmaker import E 6from gettext import gettext as _ 7 8from book_list.constants import book_list_container_id, read_book_container_id 9from book_list.globals import get_current_query, get_session_data 10from book_list.library_data import current_library_id 11from modals import close_all_modals 12from utils import ( 13 encode_query_with_path, parse_url_params, request_full_screen, 14 safe_set_inner_html 15) 16 17mode_handlers = {} 18default_mode_handler = None 19read_book_mode = 'read_book' 20 21 22def set_mode_handler(mode, handler): 23 mode_handlers[mode] = handler 24 25 26def set_default_mode_handler(handler): 27 nonlocal default_mode_handler 28 default_mode_handler = handler 29 30 31def update_window_title(subtitle, title='calibre', sep=' :: '): 32 extra = (sep + subtitle) if subtitle else '' 33 document.title = title + extra 34 35 36def is_reading_book(): 37 cq = get_current_query() 38 return cq and cq.mode is read_book_mode 39 40 41def apply_mode(): 42 divid = read_book_container_id if is_reading_book() else book_list_container_id 43 for div in document.getElementById(divid).parentNode.childNodes: 44 div.style.display = 'block' if div.id is divid else 'none' 45 46 47def apply_url(ignore_handler): 48 close_all_modals() # needed to close any error dialogs, etc when clicking back or forward in the browser or using push_state() to go to a new page 49 data = parse_url_params() 50 data.mode = data.mode or 'book_list' 51 get_current_query(data) 52 apply_mode() 53 if not ignore_handler: 54 handler = mode_handlers[data.mode] or default_mode_handler 55 handler(data) 56 57 58def open_book(book_id, fmt, library_id=None, replace=False): 59 opt = get_session_data().get('fullscreen_when_opening') 60 has_touch = v'"ontouchstart" in window' 61 at_left = window.screenLeft is 0 62 likely_wants_fullscreen = has_touch and at_left 63 if (opt is 'auto' and likely_wants_fullscreen) or opt is 'always': 64 # Note that full screen requests only succeed if they are in response to a 65 # user action like clicking/tapping a button 66 request_full_screen() 67 library_id = library_id or current_library_id() 68 push_state({'book_id':book_id, 'fmt':fmt, 'library_id':library_id}, replace=replace, mode=read_book_mode) 69 70 71 72def push_state(query, replace=False, mode='book_list', call_handler=True): 73 query = {k:query[k] for k in query if query[k]} 74 if mode is not 'book_list': 75 query.mode = mode 76 query = encode_query_with_path(query) 77 if replace: 78 window.history.replaceState(None, '', query) 79 else: 80 window.history.pushState(None, '', query) 81 push_state.history_count += 1 82 apply_url(not call_handler) 83 84push_state.history_count = 0 85 86def on_pop_state(ev): 87 push_state.history_count = max(0, push_state.history_count - 1) 88 apply_url() 89 90 91def back(): 92 if push_state.history_count > 0: 93 window.history.back() 94 else: 95 cq = get_current_query() 96 handler = mode_handlers[cq.mode] or default_mode_handler 97 if handler.back_from_current: 98 q = handler.back_from_current(cq) 99 else: 100 q = {} 101 push_state(q, replace=True) 102 103 104def home(replace=False): 105 push_state({}) 106 107 108def report_a_load_failure(container, msg, error_html): 109 err = E.div() 110 safe_set_inner_html(err, error_html) 111 container.appendChild(E.div( 112 style='margin: 1ex 1em', 113 E.div(msg), 114 err, 115 E.div( 116 style='margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1ex;', 117 E.a(onclick=def(): home(replace=True);, href='javascript: void(0)', class_='blue-link', _('Go back to the home page'))) 118 ), 119 ) 120