diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index f94eb1316..274a2473a 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -60,28 +60,21 @@ local function isFile(file) return lfs.attributes(file, "mode") == "file" end -function FileManager:onSetRotationMode(rotation) - if rotation ~= nil and rotation ~= Screen:getRotationMode() then - Screen:setRotationMode(rotation) - if FileManager.instance then - self:reinit(self.path, self.focused_file) - end - end - return true -end - -function FileManager:onPhysicalKeyboardConnected() - -- So that the key navigation shortcuts apply right away. - -- This will also naturally call registerKeyEvents - self:reinit(self.path, self.focused_file) -end -FileManager.onPhysicalKeyboardDisconnected = FileManager.onPhysicalKeyboardConnected - function FileManager:setRotationMode() local locked = G_reader_settings:isTrue("lock_rotation") if not locked then - local rotation_mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT - self:onSetRotationMode(rotation_mode) + local mode = G_reader_settings:readSetting("fm_rotation_mode") or Screen.DEVICE_ROTATED_UPRIGHT + self:onSetRotationMode(mode) + end +end + +function FileManager:onSetRotationMode(mode) + local old_mode = Screen:getRotationMode() + if mode ~= nil and mode ~= old_mode then + Screen:setRotationMode(mode) + if FileManager.instance then + self:rotate() + end end end @@ -728,6 +721,8 @@ function FileManager:tapPlus() end function FileManager:reinit(path, focused_file) + path = path or self.path + focused_file = focused_file or self.focused_file UIManager:flushSettings() self.dimen = Screen:getSize() -- backup the root path and path items @@ -748,6 +743,13 @@ function FileManager:reinit(path, focused_file) -- self:onRefresh() end +FileManager.rotate = FileManager.reinit + +-- So that the key navigation shortcuts apply right away. +-- This will also naturally call registerKeyEvents +FileManager.onPhysicalKeyboardConnected = FileManager.reinit +FileManager.onPhysicalKeyboardDisconnected = FileManager.reinit + function FileManager:getCurrentDir() return FileManager.instance and FileManager.instance.file_chooser.path end diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index 39c9a653f..66aaaed59 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -2454,11 +2454,11 @@ function ReaderFooter:onSwapPageTurnButtons() end ReaderFooter.onToggleReadingOrder = ReaderFooter.onSwapPageTurnButtons -function ReaderFooter:onSetRotationMode() +function ReaderFooter:onSetDimensions() self:updateFooterContainer() self:resetLayout(true) end -ReaderFooter.onScreenResize = ReaderFooter.onSetRotationMode +ReaderFooter.onScreenResize = ReaderFooter.onSetDimensions function ReaderFooter:onSetPageHorizMargins(h_margins) if self.settings.progress_margin then diff --git a/frontend/apps/reader/modules/readerrotation.lua b/frontend/apps/reader/modules/readerrotation.lua deleted file mode 100644 index b1d26d7c8..000000000 --- a/frontend/apps/reader/modules/readerrotation.lua +++ /dev/null @@ -1,47 +0,0 @@ -local InputContainer = require("ui/widget/container/inputcontainer") -local Device = require("device") -local Event = require("ui/event") -local _ = require("gettext") - -local ReaderRotation = InputContainer:extend{ - current_rotation = 0, -} - -function ReaderRotation:init() - self:registerKeyEvents() - -- NOP our own gesture handling - self.ges_events = nil -end - -function ReaderRotation:onGesture() end - -function ReaderRotation:registerKeyEvents() - if Device:hasKeyboard() then - self.key_events = { - -- these will all generate the same event, just with different arguments - RotateLeft = { - { "J" }, - event = "Rotate", - args = -90 - }, - RotateRight = { - { "K" }, - event = "Rotate", - args = 90 - }, - } - end -end - -ReaderRotation.onPhysicalKeyboardConnected = ReaderRotation.registerKeyEvents - ---- @todo Reset rotation on new document, maybe on new page? ---- @fixme: More importantly, this breaks rendering, c.f., `Document:renderPage` --- A modern implementation of this feature is available in Dispatcher via the `IterateRotation` Event. -function ReaderRotation:onRotate(rotate_by) - self.current_rotation = (self.current_rotation + rotate_by) % 360 - self.ui:handleEvent(Event:new("RotationUpdate", self.current_rotation)) - return true -end - -return ReaderRotation diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index 546cb0451..2cf9697ea 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -836,13 +836,15 @@ function ReaderView:restoreViewContext(ctx) return false end -function ReaderView:onSetRotationMode(rotation) - if rotation ~= nil then - local old_rotation = Screen:getRotationMode() - if rotation == old_rotation then - return - end +function ReaderView:onSetRotationMode(mode) + local old_mode = Screen:getRotationMode() + if mode ~= nil and mode ~= old_mode then + Screen:setRotationMode(mode) + self:rotate(mode, old_mode) + end +end +function ReaderView:rotate(mode, old_mode) -- NOTE: We cannot rely on getScreenMode, as it actually checks the screen dimensions, instead of the rotation mode. -- (i.e., it returns how the screen *looks* like, not how it's oriented relative to its native layout). -- This would horribly break if you started in Portrait (both rotation and visually), @@ -850,26 +852,18 @@ function ReaderView:onSetRotationMode(rotation) -- If you then attempted to switch to a Landscape *rotation*, it would mistakenly think the layout hadn't changed! -- So, instead, as we're concerned with *rotation* layouts, just compare the two. -- We use LinuxFB-style constants, so, Portraits are even, Landscapes are odds, making this trivial. - local matching_orientation = bit.band(rotation, 1) == bit.band(old_rotation, 1) - - if rotation ~= old_rotation and matching_orientation then - -- No layout change, just rotate & repaint with a flash - Screen:setRotationMode(rotation) - UIManager:setDirty(self.dialog, "full") - Notification:notify(T(_("Rotation mode set to: %1"), optionsutil:getOptionText("SetRotationMode", rotation))) - return - end - - Screen:setRotationMode(rotation) + local matching_orientation = bit.band(mode, 1) == bit.band(old_mode, 1) + if matching_orientation then + -- No layout change, just rotate & repaint with a flash + UIManager:setDirty(self.dialog, "full") + else + UIManager:setDirty(nil, "full") -- SetDimensions will only request a partial, we want a flash + local new_screen_size = Screen:getSize() + self.ui:handleEvent(Event:new("SetDimensions", new_screen_size)) + self.ui:onScreenResize(new_screen_size) + self.ui:handleEvent(Event:new("InitScrollPageStates")) end - - UIManager:setDirty(nil, "full") -- SetDimensions will only request a partial, we want a flash - local new_screen_size = Screen:getSize() - self.ui:handleEvent(Event:new("SetDimensions", new_screen_size)) - self.ui:onScreenResize(new_screen_size) - self.ui:handleEvent(Event:new("InitScrollPageStates")) - Notification:notify(T(_("Rotation mode set to: %1"), optionsutil:getOptionText("SetRotationMode", rotation))) - return + Notification:notify(T(_("Rotation mode set to: %1"), optionsutil:getOptionText("SetRotationMode", mode))) end function ReaderView:onSetDimensions(dimensions) @@ -975,7 +969,7 @@ function ReaderView:onBBoxUpdate(bbox) self.use_bbox = bbox and true or false end ---- @note: From ReaderRotation, which is broken and disabled. +--- @note: From ReaderRotation, which was broken, and has been removed in #12658 function ReaderView:onRotationUpdate(rotation) self.state.rotation = rotation self:recalculate() diff --git a/frontend/apps/reader/modules/readerzooming.lua b/frontend/apps/reader/modules/readerzooming.lua index cba7dbc78..3f030d693 100644 --- a/frontend/apps/reader/modules/readerzooming.lua +++ b/frontend/apps/reader/modules/readerzooming.lua @@ -322,7 +322,7 @@ function ReaderZooming:onRestoreDimensions(dimensions) self:setZoom() end ---- @note: From ReaderRotation, which is broken and disabled. +--- @note: From ReaderRotation, which was broken, and has been removed in #12658 function ReaderZooming:onRotationUpdate(rotation) self.rotation = rotation self:setZoom() diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index f6ec1b618..d0b39ed84 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -43,7 +43,6 @@ local ReaderLink = require("apps/reader/modules/readerlink") local ReaderMenu = require("apps/reader/modules/readermenu") local ReaderPageMap = require("apps/reader/modules/readerpagemap") local ReaderPanning = require("apps/reader/modules/readerpanning") ---local ReaderRotation = require("apps/reader/modules/readerrotation") local ReaderPaging = require("apps/reader/modules/readerpaging") local ReaderRolling = require("apps/reader/modules/readerrolling") local ReaderSearch = require("apps/reader/modules/readersearch") @@ -159,15 +158,6 @@ function ReaderUI:init() view = self.view, ui = self }) - -- (legacy, and defunct) rotation controller - --- @fixme: Tripping this would break rendering, c.f., `Document:renderPage` - --[[ - self:registerModule("rotation", ReaderRotation:new{ - dialog = self.dialog, - view = self.view, - ui = self - }) - --]] -- Handmade/custom ToC and hidden flows self:registerModule("handmade", ReaderHandMade:new{ dialog = self.dialog, diff --git a/frontend/document/document.lua b/frontend/document/document.lua index c90bc0156..f7b1e7e70 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -501,9 +501,9 @@ function Document:renderPage(pageno, rect, zoom, rotation, gamma, hinting) -- Make the context match the rotation, -- by pointing at the rotated origin via coordinates offsets. -- NOTE: We rotate our *Screen* bb on rotation (SetRotationMode), not the document, - -- so we hardly ever exercise this codepath... - -- AFAICT, the only thing that will *ever* (attempt to) rotate the document is ReaderRotation's key bindings (RotationUpdate). - --- @fixme: And whaddayano, it's broken ;). The aptly named key binds in question are J/K, I shit you not. + -- so we hardly ever exercize this codepath... + -- AFAICT, the only thing that *ever* (attempted to) rotate the document was ReaderRotation's key bindings (RotationUpdate). + --- @note: It was broken as all hell (it had likely never worked outside of its original implementation in KPV), and has been removed in #12658 if rotation == 90 then dc:setOffset(page_size.w, 0) elseif rotation == 180 then diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index 485ba5b82..5600910bd 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -237,6 +237,8 @@ function InputDialog:init() title_multilines = true, bottom_v_padding = self.bottom_v_padding, info_text = self.description, + left_icon = self.title_bar_left_icon, + left_icon_tap_callback = self.title_bar_left_icon_tap_callback, show_parent = self, } @@ -475,6 +477,31 @@ function InputDialog:init() end end +function InputDialog:reinit() + local visible = self:isKeyboardVisible() + self.input = self:getInputText() -- re-init with up-to-date text + self:onClose() -- will close keyboard and save view position + self._input_widget:onCloseWidget() -- proper cleanup of InputText and its keyboard + if self._added_widgets then + -- prevent these externally added widgets from being freed as :init() will re-add them + for i = 1, #self._added_widgets do + table.remove(self.vgroup, #self.vgroup-2) + end + end + self:free() + -- Restore original text_height (or reset it if none to force recomputing it) + self.text_height = self.orig_text_height or nil + + -- Same deal as in toggleKeyboard... + self.keyboard_visible = visible and true or false + self:init() + if self.keyboard_visible then + self:onShowKeyboard() + end + -- Our position on screen has probably changed, so have the full screen refreshed + UIManager:setDirty("all", "flashui") +end + function InputDialog:addWidget(widget, re_init) table.insert(self.layout, #self.layout, {widget}) if not re_init then -- backup widget for re-init @@ -677,30 +704,7 @@ function InputDialog:onKeyboardClosed() end end -function InputDialog:onKeyboardHeightChanged() - local visible = self:isKeyboardVisible() - self.input = self:getInputText() -- re-init with up-to-date text - self:onClose() -- will close keyboard and save view position - self._input_widget:onCloseWidget() -- proper cleanup of InputText and its keyboard - if self._added_widgets then - -- prevent these externally added widgets from being freed as :init() will re-add them - for i = 1, #self._added_widgets do - table.remove(self.vgroup, #self.vgroup-2) - end - end - self:free() - -- Restore original text_height (or reset it if none to force recomputing it) - self.text_height = self.orig_text_height or nil - - -- Same deal as in toggleKeyboard... - self.keyboard_visible = visible - self:init() - if self.keyboard_visible then - self:onShowKeyboard() - end - -- Our position on screen has probably changed, so have the full screen refreshed - UIManager:setDirty("all", "flashui") -end +InputDialog.onKeyboardHeightChanged = InputDialog.reinit function InputDialog:onCloseDialog() local close_button = self.button_table:getButtonById("close") @@ -724,6 +728,15 @@ function InputDialog:onClose() self:onCloseKeyboard() end +function InputDialog:onSetRotationMode(mode) + if self.rotation_enabled and mode ~= nil then -- Text editor only + self.rotation_mode_backup = self.rotation_mode_backup or Screen:getRotationMode() -- backup only initial mode + Screen:setRotationMode(mode) + self:reinit() + return true -- we are the upper widget, stop event propagation + end +end + function InputDialog:refreshButtons() -- Using what ought to be enough: -- return "ui", self.button_table.dimen diff --git a/plugins/texteditor.koplugin/main.lua b/plugins/texteditor.koplugin/main.lua index 0160f1522..cbb0ea589 100644 --- a/plugins/texteditor.koplugin/main.lua +++ b/plugins/texteditor.koplugin/main.lua @@ -1,4 +1,5 @@ local BD = require("ui/bidi") +local ButtonDialog = require("ui/widget/buttondialog") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") local Dispatcher = require("dispatcher") @@ -438,7 +439,7 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file) -- No need to warn if readonly, the user will know it when we open -- without keyboard and the Save button says "Read only". local readonly = true - local file = io.open(file_path, 'r+b') + local file = io.open(file_path, "r+b") if file then file:close() readonly = false @@ -474,18 +475,6 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file) end end -function TextEditor:readFileContent(file_path) - local file = io.open(file_path, "rb") - if not file then - -- We checked file existence before, so assume it's - -- because it's a new file - return "" - end - local file_content = file:read("*all") - file:close() - return file_content -end - function TextEditor:saveFileContent(file_path, content) local ok, err = util.writeToFile(content, file_path) if ok then @@ -514,7 +503,6 @@ function TextEditor:editFile(file_path, readonly) local directory, filename = util.splitFilePathName(file_path) -- luacheck: no unused local filename_without_suffix, filetype = util.splitFileNameSuffix(filename) -- luacheck: no unused local is_lua = filetype:lower() == "lua" - local input local para_direction_rtl = nil -- use UI language direction if self.force_ltr_para_direction then para_direction_rtl = false -- force LTR @@ -524,7 +512,7 @@ function TextEditor:editFile(file_path, readonly) table.insert(buttons_first_row, { text = _("Lua check"), callback = function() - local parse_error = util.checkLuaSyntax(input:getInputText()) + local parse_error = util.checkLuaSyntax(self.input:getInputText()) if parse_error then UIManager:show(InfoMessage:new{ text = T(_("Lua syntax check failed:\n\n%1"), parse_error) @@ -542,16 +530,16 @@ function TextEditor:editFile(file_path, readonly) text = _("QR"), callback = function() UIManager:show(QRMessage:new{ - text = input:getInputText(), + text = self.input:getInputText(), height = Screen:getHeight(), width = Screen:getWidth() }) end, }) end - input = InputDialog:new{ + self.input = InputDialog:new{ title = filename, - input = self:readFileContent(file_path), + input = util.readFromFile(file_path, "rb"), input_face = Font:getFace(self.font_face, self.font_size), para_direction_rtl = para_direction_rtl, auto_para_direction = self.auto_para_direction, @@ -561,6 +549,9 @@ function TextEditor:editFile(file_path, readonly) cursor_at_end = false, readonly = readonly, add_nav_bar = true, + title_bar_left_icon = "appbar.menu", + title_bar_left_icon_tap_callback = function() self:showMenu() end, + rotation_enabled = true, keyboard_visible = self.show_keyboard_on_start, -- InputDialog will enforce false if readonly scroll_by_pan = true, buttons = {buttons_first_row}, @@ -580,10 +571,13 @@ function TextEditor:editFile(file_path, readonly) end, -- File restoring callback reset_callback = function(content) -- Will add a Reset button - return self:readFileContent(file_path), _("Text reset to last saved content") + return util.readFromFile(file_path, "rb") or "", _("Text reset to last saved content") end, -- Close callback close_callback = function() + if self.input.rotation_mode_backup and self.input.rotation_mode_backup ~= Screen:getRotationMode() then + Screen:setRotationMode(self.input.rotation_mode_backup) + end self:execWhenDoneFunc() end, -- File saving callback @@ -656,9 +650,9 @@ Do you want to keep this file as empty, or do you prefer to delete it? end, } - UIManager:show(input) + UIManager:show(self.input) if self.show_keyboard_on_start and not readonly then - input:onShowKeyboard() + self.input:onShowKeyboard() end -- Note about readonly: -- We might have liked to still show keyboard even if readonly, just @@ -688,4 +682,32 @@ function TextEditor:quickEditFile(file_path, done_callback, possible_new_file) self:checkEditFile(file_path, possible_new_file or false) end +-- TitleBar left button tap +function TextEditor:showMenu() + local dialog + local buttons = {} + local optionsutil = require("ui/data/optionsutil") + for i, mode in ipairs(optionsutil.rotation_modes) do + buttons[i] = {{ + text = optionsutil.rotation_labels[i], + enabled_func = function() + return optionsutil.rotation_modes[i] ~= Screen:getRotationMode() + end, + callback = function() + UIManager:close(dialog) + self.input:onSetRotationMode(optionsutil.rotation_modes[i]) + end, + }} + end + dialog = ButtonDialog:new{ + shrink_unneeded_width = true, + buttons = buttons, + anchor = function() + return self.input.title_bar.left_button.image.dimen + end, + modal = true, + } + UIManager:show(dialog) +end + return TextEditor