diff --git a/src/pyj/read_book/flow_mode.pyj b/src/pyj/read_book/flow_mode.pyj index e6a26b7894..11a2ada306 100644 --- a/src/pyj/read_book/flow_mode.pyj +++ b/src/pyj/read_book/flow_mode.pyj @@ -99,3 +99,5 @@ def flow_onkeydown(evt): def layout(is_single_page): set_css(document.body, margin='0', border_width='0', padding='0') +def handle_gesture(gesture): + pass diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index 7637078eb1..3b559611b5 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -10,12 +10,12 @@ from read_book.globals import set_boss, set_current_spine_item, current_layout_m from read_book.mathjax import apply_mathjax from read_book.resources import finalize_resources, unserialize_html from read_book.flow_mode import ( - flow_to_scroll_fraction, flow_onwheel, flow_onkeydown, layout as flow_layout + flow_to_scroll_fraction, flow_onwheel, flow_onkeydown, layout as flow_layout, handle_gesture as flow_handle_gesture ) from read_book.paged_mode import ( layout as paged_layout, scroll_to_fraction as paged_scroll_to_fraction, onwheel as paged_onwheel, onkeydown as paged_onkeydown, scroll_to_elem, - jump_to_cfi as paged_jump_to_cfi + jump_to_cfi as paged_jump_to_cfi, handle_gesture as paged_handle_gesture ) from read_book.settings import apply_settings from read_book.touch import create_handlers as create_touch_handlers @@ -94,6 +94,7 @@ class IframeBoss: self.do_layout = flow_layout self.handle_wheel = flow_onwheel self.handle_keydown = flow_onkeydown + self.handle_gesture = flow_handle_gesture self.to_scroll_fraction = flow_to_scroll_fraction self.jump_to_cfi = scroll_to_cfi else: @@ -102,6 +103,7 @@ class IframeBoss: self.handle_keydown = paged_onkeydown self.to_scroll_fraction = paged_scroll_to_fraction self.jump_to_cfi = paged_jump_to_cfi + self.handle_gesture = paged_handle_gesture apply_settings(data.settings) set_current_spine_item({'name':data.name, 'is_first':index is 0, 'is_last':index is spine.length - 1, 'initial_position':data.initial_position}) self.last_cfi = None diff --git a/src/pyj/read_book/paged_mode.pyj b/src/pyj/read_book/paged_mode.pyj index 50ba10bcc9..f071c67cb5 100644 --- a/src/pyj/read_book/paged_mode.pyj +++ b/src/pyj/read_book/paged_mode.pyj @@ -492,3 +492,11 @@ def onkeydown(evt): scroll_by_page(key is 'pageup', True) if handled: evt.preventDefault() + +def handle_gesture(gesture): + if gesture.type is 'swipe': + if not gesture.active: + if gesture.axis is 'vertical': + pass # TODO: next/prev section + else: + scroll_by_page(gesture.direction is 'right', False) diff --git a/src/pyj/read_book/touch.pyj b/src/pyj/read_book/touch.pyj index 6322de4f71..9d09fc11db 100644 --- a/src/pyj/read_book/touch.pyj +++ b/src/pyj/read_book/touch.pyj @@ -2,10 +2,44 @@ # License: GPL v3 Copyright: 2016, Kovid Goyal from __python__ import hash_literals, bound_methods +from read_book.globals import get_boss def copy_touch(t): + now = window.performance.now() return {'identifier':t.identifier, 'page_x':v'[t.pageX]', 'page_y':v'[t.pageY]', 'viewport_x':v'[t.clientX]', 'viewport_y':v'[t.clientY]', - 'active':True, 'mtime':window.performance.now()} + 'active':True, 'mtime':now, 'ctime':now} + +def max_displacement(points): + ans = 0 + first = points[0] + if not first?: + return ans + for p in points: + delta = abs(p - first) + if delta > ans: + ans = delta + return ans + +def interpret_single_gesture(touch): + max_x_displacement = max_displacement(touch.viewport_x) + max_y_displacement = max_displacement(touch.viewport_y) + if max(max_x_displacement, max_y_displacement) < 25: + return {'type':'tap'} + if touch.viewport_y.length < 2: + return {} + delta_x = abs(touch.viewport_x[-1] - touch.viewport_x[0]) + delta_y = abs(touch.viewport_y[-1] - touch.viewport_y[0]) + if max(delta_y, delta_x) > 30 and min(delta_x, delta_y)/max(delta_y, delta_x) < 0.35: + ans = {'type':'swipe'} + ans.axis = 'vertical' if delta_y > delta_x else 'horizontal' + pts = touch.viewport_y if ans.axis is 'vertical' else touch.viewport_x + positive = pts[-1] > pts[0] + if ans.axis is 'vertical': + ans.direction = 'down' if positive else 'up' + else: + ans.direction = 'right' if positive else 'left' + return ans + return {} class TouchHandler: @@ -43,6 +77,12 @@ class TouchHandler: t = self.ongoing_touches[touch.identifier] if t: self.update_touch(t, touch) + if len(self.ongoing_touches) is 1: + gesture = interpret_single_gesture(t) + if gesture?.type is 'swipe': + gesture.active = True + get_boss().handle_gesture(gesture) + def handle_touchend(self, ev): ev.preventDefault(), ev.stopPropagation() @@ -61,7 +101,18 @@ class TouchHandler: v'delete self.ongoing_touches[touch.identifier]' def interpret_gesture(self, touches): - print(1111111, touches) + num = len(touches) + gesture = {} + if num is 1: + gesture = interpret_single_gesture(touches[Object.keys(touches)[0]]) + if not gesture?.type: + return + if gesture.type is 'tap': + # TODO: Check for tap on link. Also convert the tap gesture into + # semantic gestures based on position of tap (next page/previous + # page/show ui) as these are common to both paged and flow mode. + pass + get_boss().handle_gesture(gesture) touch_handler = TouchHandler()