mirror of
https://github.com/koreader/koreader.git
synced 2025-12-18 12:02:09 +01:00
Notifications: stack them instead of overdrawing them
This commit is contained in:
@@ -10,9 +10,11 @@ local FrameContainer = require("ui/widget/container/framecontainer")
|
||||
local Geom = require("ui/geometry")
|
||||
local GestureRange = require("ui/gesturerange")
|
||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||
local RectSpan = require("ui/widget/rectspan")
|
||||
local Size = require("ui/size")
|
||||
local TextWidget = require("ui/widget/textwidget")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local VerticalGroup = require("ui/widget/verticalgroup")
|
||||
local Input = Device.input
|
||||
local Screen = Device.screen
|
||||
|
||||
@@ -23,6 +25,8 @@ local Notification = InputContainer:new{
|
||||
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
|
||||
|
||||
_nums_shown = {}, -- array of stacked notifications
|
||||
}
|
||||
|
||||
function Notification:init()
|
||||
@@ -48,18 +52,12 @@ function Notification:init()
|
||||
end
|
||||
end
|
||||
|
||||
-- we construct the actual content here because self.text is only available now
|
||||
local text_widget = TextWidget:new{
|
||||
text = self.text,
|
||||
face = self.face,
|
||||
}
|
||||
local widget_size = text_widget:getSize()
|
||||
self[1] = CenterContainer:new{
|
||||
dimen = Geom:new{
|
||||
w = Screen:getWidth(),
|
||||
h = math.floor(Screen:getHeight() / 10),
|
||||
},
|
||||
FrameContainer:new{
|
||||
self.frame = FrameContainer:new{
|
||||
background = Blitbuffer.COLOR_WHITE,
|
||||
radius = 0,
|
||||
margin = self.margin,
|
||||
@@ -72,12 +70,51 @@ function Notification:init()
|
||||
text_widget,
|
||||
}
|
||||
}
|
||||
local notif_height = self.frame:getSize().h
|
||||
|
||||
self:_cleanShownStack()
|
||||
table.insert(Notification._nums_shown, os.time())
|
||||
self.num = #Notification._nums_shown
|
||||
|
||||
self[1] = VerticalGroup:new{
|
||||
align = "center",
|
||||
-- We use a span to properly position this notification:
|
||||
RectSpan:new{
|
||||
-- have this VerticalGroup full width, to ensure centering
|
||||
width = Screen:getWidth(),
|
||||
-- push this frame at its y=self.num position
|
||||
height = notif_height * (self.num - 1),
|
||||
},
|
||||
self.frame,
|
||||
}
|
||||
end
|
||||
|
||||
function Notification:_cleanShownStack(num)
|
||||
-- Clean stack of shown notifications
|
||||
if num then
|
||||
-- This notification is no longer displayed
|
||||
Notification._nums_shown[num] = false
|
||||
end
|
||||
-- We remove from the stack tail all slots no longer displayed.
|
||||
-- Even if slots at top are available, we'll keep adding new
|
||||
-- notifications only at the tail/bottom (easier for the eyes
|
||||
-- to follow what is happening).
|
||||
-- As a sanity check, we also forget those shown for
|
||||
-- more than 30s in case no close event was received.
|
||||
local expire_ts = os.time() - 30
|
||||
for i=#Notification._nums_shown, 1, -1 do
|
||||
if Notification._nums_shown[i] and Notification._nums_shown[i] > expire_ts then
|
||||
break -- still shown (or not yet expired)
|
||||
end
|
||||
table.remove(Notification._nums_shown, i)
|
||||
end
|
||||
end
|
||||
|
||||
function Notification:onCloseWidget()
|
||||
self:_cleanShownStack(self.num)
|
||||
self.num = nil -- avoid mess in case onCloseWidget is called multiple times
|
||||
UIManager:setDirty(nil, function()
|
||||
return "ui", self[1][1].dimen
|
||||
return "ui", self.frame.dimen
|
||||
end)
|
||||
return true
|
||||
end
|
||||
@@ -85,7 +122,7 @@ end
|
||||
function Notification:onShow()
|
||||
-- triggered by the UIManager after we got successfully shown (not yet painted)
|
||||
UIManager:setDirty(self, function()
|
||||
return "ui", self[1][1].dimen
|
||||
return "ui", self.frame.dimen
|
||||
end)
|
||||
if self.timeout then
|
||||
UIManager:scheduleIn(self.timeout, function() UIManager:close(self) end)
|
||||
|
||||
Reference in New Issue
Block a user