diff --git a/.ci/after_success.sh b/.ci/after_success.sh index 011b8d1be..2190d00e6 100755 --- a/.ci/after_success.sh +++ b/.ci/after_success.sh @@ -5,11 +5,6 @@ source "${CI_DIR}/common.sh" set +e -travis_retry make coverage -pushd koreader-*/koreader - luajit $(which luacov-coveralls) -v -popd - if [ ${TRAVIS_PULL_REQUEST} = false ] && [ ${TRAVIS_BRANCH} = 'master' ]; then travis_retry luarocks --local install ldoc # get deploy key for doc repo @@ -36,7 +31,12 @@ if [ ${TRAVIS_PULL_REQUEST} = false ] && [ ${TRAVIS_BRANCH} = 'master' ]; then git -c user.name="KOReader build bot" -c user.email="non-reply@koreader.rocks" \ commit -a --amend -m 'Automated documentation build from travis-ci.' git push -f --quiet origin gh-pages > /dev/null - echo -e "\n${ANSI_GREEN}Document update pushed." + echo -e "\n${ANSI_GREEN}Documentation update pushed." else - echo -e "\n${ANSI_GREEN}Not on official master branch, skip document update." + echo -e "\n${ANSI_GREEN}Not on official master branch, skip documentation update." fi + +travis_retry make coverage +pushd koreader-*/koreader + luajit $(which luacov-coveralls) +popd diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index e6025edfd..695307f0c 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -104,6 +104,7 @@ function FileManagerMenu:setUpdateItemTable() callback = function() local open_last = G_reader_settings:readSetting("open_last") or false G_reader_settings:saveSetting("open_last", not open_last) + G_reader_settings:flush() end }) if Device.isKobo() then @@ -121,6 +122,7 @@ function FileManagerMenu:setUpdateItemTable() G_reader_settings:delSetting( "use_lastfile_as_screensaver") end + G_reader_settings:flush() end }, { @@ -130,6 +132,7 @@ function FileManagerMenu:setUpdateItemTable() local function save_folder_path() G_reader_settings:saveSetting( "screensaver_folder", ss_folder_path_input:getInputText()) + G_reader_settings:flush() UIManager:close(ss_folder_path_input) end local curr_path = G_reader_settings:readSetting("screensaver_folder") diff --git a/frontend/apps/reader/modules/readerpaging.lua b/frontend/apps/reader/modules/readerpaging.lua index 69931be91..8e012adee 100644 --- a/frontend/apps/reader/modules/readerpaging.lua +++ b/frontend/apps/reader/modules/readerpaging.lua @@ -10,6 +10,20 @@ local Math = require("optmath") local DEBUG = require("dbg") local _ = require("gettext") + +local function copyPageState(page_state) + return { + page = page_state.page, + zoom = page_state.zoom, + rotation = page_state.rotation, + gamma = page_state.gamma, + offset = page_state.offset:copy(), + visible_area = page_state.visible_area:copy(), + page_area = page_state.page_area:copy(), + } +end + + local ReaderPaging = InputContainer:new{ current_page = 0, number_of_pages = 0, @@ -555,9 +569,12 @@ function ReaderPaging:getPrevPageState(blank_area, offset) end function ReaderPaging:updateTopPageState(state, blank_area, offset) - local visible_area = Geom:new{x = 0, y = 0} - visible_area.w, visible_area.h = blank_area.w, blank_area.h - visible_area.x, visible_area.y = state.visible_area.x, state.visible_area.y + local visible_area = Geom:new{ + x = state.visible_area.x, + y = state.visible_area.y, + w = blank_area.w, + h = blank_area.h, + } if state.page == self.number_of_pages then visible_area:offsetWithin(state.page_area, offset.x, offset.y) else @@ -566,14 +583,15 @@ function ReaderPaging:updateTopPageState(state, blank_area, offset) -- shrink blank area by the height of visible area blank_area.h = blank_area.h - visible_area.h state.visible_area = visible_area - return state end function ReaderPaging:updateBottomPageState(state, blank_area, offset) - local visible_area = Geom:new{x = 0, y = 0} - visible_area.w, visible_area.h = blank_area.w, blank_area.h - visible_area.x = state.page_area.x - visible_area.y = state.visible_area.y + state.visible_area.h - visible_area.h + local visible_area = Geom:new{ + x = state.page_area.x, + y = state.visible_area.y + state.visible_area.h - blank_area.h, + w = blank_area.w, + h = blank_area.h, + } if state.page == 1 then visible_area:offsetWithin(state.page_area, offset.x, offset.y) else @@ -582,7 +600,6 @@ function ReaderPaging:updateBottomPageState(state, blank_area, offset) -- shrink blank area by the height of visible area blank_area.h = blank_area.h - visible_area.h state.visible_area = visible_area - return state end function ReaderPaging:genPageStatesFromTop(top_page_state, blank_area, offset) @@ -592,16 +609,18 @@ function ReaderPaging:genPageStatesFromTop(top_page_state, blank_area, offset) -- which will trigger the drawing of next page leaving part of current -- page undrawn. This should also be true for generating from bottom. if offset.y < 0 then offset.y = 0 end - local state = self:updateTopPageState(top_page_state, blank_area, offset) + self:updateTopPageState(top_page_state, blank_area, offset) local page_states = {} - if state.visible_area.h > 0 then - table.insert(page_states, state) + if top_page_state.visible_area.h > 0 then + -- offset does not scroll pass top_page_state + table.insert(page_states, top_page_state) end - local current_page = state.page + local state + local current_page = top_page_state.page while blank_area.h > 0 do blank_area.h = blank_area.h - self.view.page_gap.height if blank_area.h > 0 then - if self.current_page == self.number_of_pages then break end + if current_page == self.number_of_pages then break end self:_gotoPage(current_page + 1, "scrolling") current_page = current_page + 1 state = self:getNextPageState(blank_area, Geom:new{}) @@ -614,16 +633,19 @@ end function ReaderPaging:genPageStatesFromBottom(bottom_page_state, blank_area, offset) -- scroll up offset should always be less than 0 if offset.y > 0 then offset.y = 0 end - local state = self:updateBottomPageState(bottom_page_state, blank_area, offset) + -- find out number of pages need to be removed from current view + self:updateBottomPageState(bottom_page_state, blank_area, offset) local page_states = {} - if state.visible_area.h > 0 then - table.insert(page_states, state) + if bottom_page_state.visible_area.h > 0 then + table.insert(page_states, bottom_page_state) end - local current_page = state.page + -- fill up current view from bottom to top + local state + local current_page = bottom_page_state.page while blank_area.h > 0 do blank_area.h = blank_area.h - self.view.page_gap.height if blank_area.h > 0 then - if self.current_page == 1 then break end + if current_page == 1 then break end self:_gotoPage(current_page - 1, "scrolling") current_page = current_page - 1 state = self:getPrevPageState(blank_area, Geom:new{}) @@ -634,29 +656,34 @@ function ReaderPaging:genPageStatesFromBottom(bottom_page_state, blank_area, off end function ReaderPaging:onScrollPanRel(diff) + if diff == 0 then return true end DEBUG("pan relative height:", diff) + local offset = Geom:new{x = 0, y = diff} local blank_area = Geom:new{} blank_area:setSizeTo(self.view.dimen) + local new_page_states if diff > 0 then - local first_page_state = table.remove(self.view.page_states, 1) - local offset = Geom:new{ - x = 0, - y = diff, - } - self.view.page_states = self:genPageStatesFromTop(first_page_state, blank_area, offset) - end - if diff < 0 then - local last_page_state = table.remove(self.view.page_states) - local offset = Geom:new{ - x = 0, - y = diff - } - self.view.page_states = self:genPageStatesFromBottom(last_page_state, blank_area, offset) + -- pan to scroll down + local first_page_state = copyPageState(self.view.page_states[1]) + new_page_states = self:genPageStatesFromTop( + first_page_state, blank_area, offset) + elseif diff < 0 then + local last_page_state = copyPageState( + self.view.page_states[#self.view.page_states]) + new_page_states = self:genPageStatesFromBottom( + last_page_state, blank_area, offset) + end + if #new_page_states == 0 then + -- if we are already at the top of first page or bottom of the last + -- page, new_page_states will be empty, in this case, nothing to update + return true end + self.view.page_states = new_page_states -- update current pageno to the very last part in current view - self:_gotoPage(self.view.page_states[#self.view.page_states].page, "scrolling") - + self:_gotoPage(self.view.page_states[#self.view.page_states].page, + "scrolling") UIManager:setDirty(self.view.dialog, "fast") + return true end function ReaderPaging:calculateOverlap() @@ -664,8 +691,10 @@ function ReaderPaging:calculateOverlap() return self.overlap + footer_height end -function ReaderPaging:onScrollPageRel(diff) - if diff > 0 then +function ReaderPaging:onScrollPageRel(page_diff) + if page_diff == 0 then return true end + if page_diff > 0 then + -- page down, last page should be moved to top local last_page_state = table.remove(self.view.page_states) local last_visible_area = last_page_state.visible_area if last_page_state.page == self.number_of_pages and @@ -683,7 +712,8 @@ function ReaderPaging:onScrollPageRel(diff) y = last_visible_area.h - overlap } self.view.page_states = self:genPageStatesFromTop(last_page_state, blank_area, offset) - elseif diff < 0 then + elseif page_diff < 0 then + -- page up, first page should be moved to bottom local blank_area = Geom:new{} blank_area:setSizeTo(self.view.dimen) local overlap = self:calculateOverlap() @@ -692,9 +722,8 @@ function ReaderPaging:onScrollPageRel(diff) x = 0, y = -first_page_state.visible_area.h + overlap } - self.view.page_states = self:genPageStatesFromBottom(first_page_state, blank_area, offset) - else - return true + self.view.page_states = self:genPageStatesFromBottom( + first_page_state, blank_area, offset) end -- update current pageno to the very last part in current view self:_gotoPage(self.view.page_states[#self.view.page_states].page, "scrolling") @@ -842,15 +871,16 @@ function ReaderPaging:onGotoPercentage(percentage) end function ReaderPaging:updateReadOrder() + local width, height = Screen:getWidth(), Screen:getHeight() if self.inverse_reading_order then self.ges_events.TapForward = { GestureRange:new{ ges = "tap", range = Geom:new{ - x = Screen:getWidth()*(1-DTAP_ZONE_FORWARD.x-DTAP_ZONE_FORWARD.w), - y = Screen:getHeight()*DTAP_ZONE_FORWARD.y, - w = Screen:getWidth()*DTAP_ZONE_FORWARD.w, - h = Screen:getHeight()*DTAP_ZONE_FORWARD.h, + x = width * (1-DTAP_ZONE_FORWARD.x - DTAP_ZONE_FORWARD.w), + y = height * DTAP_ZONE_FORWARD.y, + w = width * DTAP_ZONE_FORWARD.w, + h = height * DTAP_ZONE_FORWARD.h, } } } @@ -858,22 +888,22 @@ function ReaderPaging:updateReadOrder() GestureRange:new{ ges = "tap", range = Geom:new{ - x = Screen:getWidth()*(1-DTAP_ZONE_BACKWARD.x-DTAP_ZONE_BACKWARD.w), - y = Screen:getHeight()*DTAP_ZONE_BACKWARD.y, - w = Screen:getWidth()*DTAP_ZONE_BACKWARD.w, - h = Screen:getHeight()*DTAP_ZONE_BACKWARD.h, + x = width * (1-DTAP_ZONE_BACKWARD.x - DTAP_ZONE_BACKWARD.w), + y = height * DTAP_ZONE_BACKWARD.y, + w = width * DTAP_ZONE_BACKWARD.w, + h = height * DTAP_ZONE_BACKWARD.h, } } } else - self.ges_events.TapForward = { + self.ges_events.TapForward = { GestureRange:new{ ges = "tap", range = Geom:new{ - x = Screen:getWidth()*DTAP_ZONE_FORWARD.x, - y = Screen:getHeight()*DTAP_ZONE_FORWARD.y, - w = Screen:getWidth()*DTAP_ZONE_FORWARD.w, - h = Screen:getHeight()*DTAP_ZONE_FORWARD.h, + x = width * DTAP_ZONE_FORWARD.x, + y = height * DTAP_ZONE_FORWARD.y, + w = width * DTAP_ZONE_FORWARD.w, + h = height * DTAP_ZONE_FORWARD.h, } } } @@ -881,10 +911,10 @@ function ReaderPaging:updateReadOrder() GestureRange:new{ ges = "tap", range = Geom:new{ - x = Screen:getWidth()*DTAP_ZONE_BACKWARD.x, - y = Screen:getHeight()*DTAP_ZONE_BACKWARD.y, - w = Screen:getWidth()*DTAP_ZONE_BACKWARD.w, - h = Screen:getHeight()*DTAP_ZONE_BACKWARD.h, + x = width * DTAP_ZONE_BACKWARD.x, + y = height * DTAP_ZONE_BACKWARD.y, + w = width * DTAP_ZONE_BACKWARD.w, + h = height * DTAP_ZONE_BACKWARD.h, } } } diff --git a/spec/unit/readerpaging_spec.lua b/spec/unit/readerpaging_spec.lua index fb69a0aa8..42c94394c 100644 --- a/spec/unit/readerpaging_spec.lua +++ b/spec/unit/readerpaging_spec.lua @@ -1,18 +1,20 @@ describe("Readerpaging module", function() local sample_pdf = "spec/front/unit/data/sample.pdf" - local readerui, UIManager, Event + local readerui, UIManager, Event, DocumentRegistry, ReaderUI local paging setup(function() require("commonrequire") UIManager = require("ui/uimanager") Event = require("ui/event") + DocumentRegistry = require("document/documentregistry") + ReaderUI = require("apps/reader/readerui") end) describe("Page mode", function() setup(function() - readerui = require("apps/reader/readerui"):new{ - document = require("document/documentregistry"):openDocument(sample_pdf), + readerui = ReaderUI:new{ + document = DocumentRegistry:openDocument(sample_pdf), } paging = readerui.paging end) @@ -43,8 +45,8 @@ describe("Readerpaging module", function() purgeDir(DocSettings:getSidecarDir(sample_pdf)) os.remove(DocSettings:getHistoryPath(sample_pdf)) - readerui = require("apps/reader/readerui"):new{ - document = require("document/documentregistry"):openDocument(sample_pdf), + readerui = ReaderUI:new{ + document = DocumentRegistry:openDocument(sample_pdf), } paging = readerui.paging end) @@ -68,5 +70,25 @@ describe("Readerpaging module", function() readerui.onEndOfBook = nil UIManager:quit() end) + + it("should scroll withtout crash backward on the first page", function() + local sample_djvu = "spec/front/unit/data/djvu3spec.djvu" + local tmp_readerui = ReaderUI:new{ + document = DocumentRegistry:openDocument(sample_djvu), + } + tmp_readerui.paging:onScrollPanRel(-100) + end) + + it("should scroll withtout crash forward on the last page", function() + local sample_djvu = "spec/front/unit/data/djvu3spec.djvu" + local tmp_readerui = ReaderUI:new{ + document = DocumentRegistry:openDocument(sample_djvu), + } + local paging = tmp_readerui.paging + paging:onGotoPage(tmp_readerui.document:getPageCount()) + paging:onScrollPanRel(120) + paging:onScrollPanRel(-1) + paging:onScrollPanRel(120) + end) end) end) diff --git a/spec/unit/readhistory_spec.lua b/spec/unit/readhistory_spec.lua index 16942ecf8..11474e2db 100644 --- a/spec/unit/readhistory_spec.lua +++ b/spec/unit/readhistory_spec.lua @@ -272,7 +272,7 @@ describe("ReadHistory module", function() for i = 1, 500 do -- at most 500 items are stored assert_item_is(h, i, string.format("%04d", i)) end - + for i = 1, 1000 do rm(to_file(i)) end