From 8f79c662cfc5e1d2fb714c7dcef7c3c9318a62ef Mon Sep 17 00:00:00 2001 From: poire-z Date: Mon, 11 Jan 2021 18:14:12 +0100 Subject: [PATCH] Notification: closed by any event, but not consuming it Make Notification have toast=true, and UIManager deal specifically with such widget: a "toast" widget gets closed by any event, and let the event be handled by a lower widget. This should allow us to not wait or tap to get rid of a notification, and just go on with what we're doing. Also make them have a default timeout of 2s, used with all existing ones. --- frontend/apps/reader/modules/readerback.lua | 1 - frontend/apps/reader/modules/readerfont.lua | 4 -- .../apps/reader/modules/readerhighlight.lua | 3 -- frontend/apps/reader/modules/readerlink.lua | 3 -- frontend/apps/reader/modules/readerpaging.lua | 1 - .../apps/reader/modules/readerrolling.lua | 1 - .../apps/reader/modules/readerstyletweak.lua | 2 - frontend/device/devicelistener.lua | 5 -- frontend/ui/uimanager.lua | 22 ++++++-- frontend/ui/widget/inputdialog.lua | 4 -- frontend/ui/widget/inputtext.lua | 1 - frontend/ui/widget/notification.lua | 51 +++++++++---------- plugins/texteditor.koplugin/main.lua | 1 - 13 files changed, 43 insertions(+), 56 deletions(-) diff --git a/frontend/apps/reader/modules/readerback.lua b/frontend/apps/reader/modules/readerback.lua index 3cc399f23..b3289d240 100644 --- a/frontend/apps/reader/modules/readerback.lua +++ b/frontend/apps/reader/modules/readerback.lua @@ -142,7 +142,6 @@ function ReaderBack:onBack() self.back_resist = true UIManager:show(Notification:new{ text = _("Location history is empty."), - timeout = 2, }) return true else diff --git a/frontend/apps/reader/modules/readerfont.lua b/frontend/apps/reader/modules/readerfont.lua index 5909e894a..8ff5f6c38 100644 --- a/frontend/apps/reader/modules/readerfont.lua +++ b/frontend/apps/reader/modules/readerfont.lua @@ -211,7 +211,6 @@ function ReaderFont:onSetFontSize(new_size) self.ui:handleEvent(Event:new("UpdatePos")) UIManager:show(Notification:new{ text = T( _("Font size set to %1."), self.font_size), - timeout = 2, }) return true @@ -221,7 +220,6 @@ function ReaderFont:onSetLineSpace(space) self.line_space_percent = math.min(200, math.max(50, space)) UIManager:show(Notification:new{ text = T( _("Line spacing set to %1%."), self.line_space_percent), - timeout = 2, }) self.ui.document:setInterlineSpacePercent(self.line_space_percent) self.ui:handleEvent(Event:new("UpdatePos")) @@ -269,7 +267,6 @@ function ReaderFont:onSetFontGamma(gamma) local gamma_level = self.ui.document:getGammaLevel() UIManager:show(Notification:new{ text = T( _("Font gamma set to %1."), gamma_level), - timeout = 2, }) self.ui:handleEvent(Event:new("RedrawCurrentView")) return true @@ -293,7 +290,6 @@ function ReaderFont:setFont(face) self.font_face = face UIManager:show(Notification:new{ text = T( _("Redrawing with font %1."), face), - timeout = 2, }) self.ui.document:setFontFace(face) diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 38371de3e..fe6f02384 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -1172,14 +1172,12 @@ function ReaderHighlight:onCycleHighlightAction() G_reader_settings:saveSetting("default_highlight_action", "highlight") UIManager:show(Notification:new{ text = _("Default highlight action changed to 'highlight'."), - timeout = 1, }) else local next_action = next_actions[current_action] G_reader_settings:saveSetting("default_highlight_action", next_action) UIManager:show(Notification:new{ text = T(_("Default highlight action changed to '%1'."), (next_action or "default")), - timeout = 1, }) end return true @@ -1195,7 +1193,6 @@ function ReaderHighlight:onCycleHighlightStyle() self.ui.doc_settings:saveSetting("highlight_drawer", self.view.highlight.saved_drawer) UIManager:show(Notification:new{ text = T(_("Default highlight style changed to '%1'."), self.view.highlight.saved_drawer), - timeout = 1, }) return true end diff --git a/frontend/apps/reader/modules/readerlink.lua b/frontend/apps/reader/modules/readerlink.lua index 7b55216b0..519f06643 100644 --- a/frontend/apps/reader/modules/readerlink.lua +++ b/frontend/apps/reader/modules/readerlink.lua @@ -508,7 +508,6 @@ function ReaderLink:onClearLocationStack(show_notification) if show_notification then UIManager:show(Notification:new{ text = _("Location history cleared."), - timeout = 2, }) end return true @@ -758,7 +757,6 @@ function ReaderLink:onGoBackLink(show_notification_if_empty) elseif show_notification_if_empty then UIManager:show(Notification:new{ text = _("Location history is empty."), - timeout = 2, }) end end @@ -780,7 +778,6 @@ function ReaderLink:onSwipe(arg, ges) -- so the user knows why UIManager:show(Notification:new{ text = _("Location history is empty."), - timeout = 2, }) return true end diff --git a/frontend/apps/reader/modules/readerpaging.lua b/frontend/apps/reader/modules/readerpaging.lua index a407060f3..756660b6b 100644 --- a/frontend/apps/reader/modules/readerpaging.lua +++ b/frontend/apps/reader/modules/readerpaging.lua @@ -1052,7 +1052,6 @@ function ReaderPaging:onToggleReadingOrder() end UIManager:show(Notification:new{ text = is_rtl and _("RTL page turning.") or _("LTR page turning."), - timeout = 2.5, }) return true end diff --git a/frontend/apps/reader/modules/readerrolling.lua b/frontend/apps/reader/modules/readerrolling.lua index 0ab6d44b4..e8417024d 100644 --- a/frontend/apps/reader/modules/readerrolling.lua +++ b/frontend/apps/reader/modules/readerrolling.lua @@ -1406,7 +1406,6 @@ function ReaderRolling:onToggleReadingOrder() end UIManager:show(Notification:new{ text = is_rtl and _("RTL page turning.") or _("LTR page turning."), - timeout = 2.5, }) return true end diff --git a/frontend/apps/reader/modules/readerstyletweak.lua b/frontend/apps/reader/modules/readerstyletweak.lua index 56b1c7510..6bb7218ac 100644 --- a/frontend/apps/reader/modules/readerstyletweak.lua +++ b/frontend/apps/reader/modules/readerstyletweak.lua @@ -194,7 +194,6 @@ function TweakInfoWidget:onTap(arg, ges) Device.input.setClipboardText("\n"..self.css_text.."\n") UIManager:show(Notification:new{ text = _("CSS text copied to clipboard"), - timeout = 2 }) return true elseif ges.pos:notIntersectWith(self.movable.dimen) then @@ -777,7 +776,6 @@ function ReaderStyleTweak:editBookTweak(touchmenu_instance) if not editor.save_callback_called then UIManager:show(Notification:new{ text = NOT_MODIFIED_MSG, - timeout = 2, }) -- This has to be the same message above and below: when -- discarding, we can't prevent these 2 notifications from diff --git a/frontend/device/devicelistener.lua b/frontend/device/devicelistener.lua index 5130a950a..34f331962 100644 --- a/frontend/device/devicelistener.lua +++ b/frontend/device/devicelistener.lua @@ -53,7 +53,6 @@ function DeviceListener:onShowIntensity() end UIManager:show(Notification:new{ text = new_text, - timeout = 1, }) return true end @@ -65,7 +64,6 @@ function DeviceListener:onShowWarmth(value) -- powerd.fl_warmth_max is the maximum value the hardware accepts UIManager:show(Notification:new{ text = T(_("Warmth set to %1."), math.floor(powerd.fl_warmth/100*powerd.fl_warmth_max)), - timeout = 1.0, }) end return true @@ -179,7 +177,6 @@ if Device:hasFrontlight() then if powerd.auto_warmth then UIManager:show(Notification:new{ text = _("Warmth is handled automatically."), - timeout = 1.0, }) return true end @@ -225,7 +222,6 @@ if Device:hasFrontlight() then end UIManager:show(Notification:new{ text = new_text, - timeout = 1.0, }) return true end @@ -248,7 +244,6 @@ if Device:canToggleGSensor() then end UIManager:show(Notification:new{ text = new_text, - timeout = 1.0, }) return true end diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 8851b9027..e1b1f7605 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -391,8 +391,14 @@ function UIManager:show(widget, refreshtype, refreshregion, x, y, refreshdither) -- put this window on top of the toppest non-modal window for i = #self._window_stack, 0, -1 do local top_window = self._window_stack[i] - -- skip modal window - if widget.modal or not top_window or not top_window.widget.modal then + -- toasts are stacked on top of other toasts, + -- then come modals, and then other widgets + if top_window and top_window.widget.toast then + if widget.toast then + table.insert(self._window_stack, i + 1, window) + break + end + elseif widget.modal or not top_window or not top_window.widget.modal then table.insert(self._window_stack, i + 1, window) break end @@ -876,8 +882,18 @@ function UIManager:sendEvent(event) end end + -- The top widget gets to be the first to get the event local top_widget = self._window_stack[#self._window_stack] - -- top level widget has first access to the event + + -- A toast widget gets closed by any event, and + -- lets the event be handled by a lower widget + -- (Notification is our single widget with toast=true) + while top_widget.widget.toast do -- close them all + self:close(top_widget.widget) + if #self._window_stack == 0 then return end + top_widget = self._window_stack[#self._window_stack] + end + if top_widget.widget:handleEvent(event) then return end diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index da07d770f..ebe41a427 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -605,7 +605,6 @@ function InputDialog:_addSaveCloseButtons() self._buttons_edit_callback(false) UIManager:show(Notification:new{ text = msg or _("Text reset"), - timeout = 2 }) else -- nil content, assume failure and show msg if msg ~= false then -- false allows for no InfoMessage @@ -638,7 +637,6 @@ function InputDialog:_addSaveCloseButtons() self._buttons_edit_callback(false) UIManager:show(Notification:new{ text = msg or _("Saved"), - timeout = 2 }) end end @@ -659,7 +657,6 @@ function InputDialog:_addSaveCloseButtons() UIManager:close(self) UIManager:show(Notification:new{ text = self.close_discarded_notif_text or _("Changes discarded"), - timeout = 2 }) end, choice2_text = self.close_save_button_text or _("Save"), @@ -679,7 +676,6 @@ function InputDialog:_addSaveCloseButtons() UIManager:close(self) UIManager:show(Notification:new{ text = msg or _("Saved"), - timeout = 2 }) end end) diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index 3c982ae78..d9cf41282 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -205,7 +205,6 @@ function InputText:isTextEditable(show_warning) if show_warning and not self.is_text_editable then UIManager:show(Notification:new{ text = _("Text may be binary content, and is not editable"), - timeout = 2 }) end return self.is_text_editable diff --git a/frontend/ui/widget/notification.lua b/frontend/ui/widget/notification.lua index a5a9b5193..88f4657cc 100644 --- a/frontend/ui/widget/notification.lua +++ b/frontend/ui/widget/notification.lua @@ -19,29 +19,33 @@ local Screen = Device.screen local Notification = InputContainer:new{ face = Font:getFace("x_smallinfofont"), text = "Null Message", - timeout = nil, margin = Size.margin.default, padding = Size.padding.default, + timeout = 2, -- default to 2 seconds + toast = true, -- closed on any event, and let the event propagate to next top widget } function Notification:init() - if Device:hasKeys() then - self.key_events = { - AnyKeyPressed = { { Input.group.Any }, - seqtext = "any key", doc = "close dialog" } - } - end - if Device:isTouchDevice() then - self.ges_events.TapClose = { - GestureRange:new{ - ges = "tap", - range = Geom:new{ - x = 0, y = 0, - w = Screen:getWidth(), - h = Screen:getHeight(), + if not self.toast then + -- If not toast, closing is handled in here + if Device:hasKeys() then + self.key_events = { + AnyKeyPressed = { { Input.group.Any }, + seqtext = "any key", doc = "close dialog" } + } + end + if Device:isTouchDevice() then + self.ges_events.TapClose = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight(), + } } } - } + end end -- we construct the actual content here because self.text is only available now @@ -90,22 +94,15 @@ function Notification:onShow() end function Notification:onAnyKeyPressed() - -- triggered by our defined key events + if self.toast then return end -- should not happen UIManager:close(self) - if not self.timeout then - return true - end + return true end function Notification:onTapClose() + if self.toast then return end -- should not happen UIManager:close(self) - -- If timeout (usually 1s or 2s), let it propagate so an underlying - -- widget can process the tap whether it's done at 1.9s or 2.1s - -- If no timout, don't propagate as this tap is most probably meant - -- at dismissing the notification - if not self.timeout then - return true - end + return true end return Notification diff --git a/plugins/texteditor.koplugin/main.lua b/plugins/texteditor.koplugin/main.lua index 9ef525aab..70c0ee2bf 100644 --- a/plugins/texteditor.koplugin/main.lua +++ b/plugins/texteditor.koplugin/main.lua @@ -474,7 +474,6 @@ function TextEditor:editFile(file_path, readonly) else UIManager:show(Notification:new{ text = T(_("Lua syntax OK")), - timeout = 2, }) end end,