@ -15,9 +15,10 @@ local Size = require("ui/size")
local TextWidget = require ( " ui/widget/textwidget " )
local TextWidget = require ( " ui/widget/textwidget " )
local UIManager = require ( " ui/uimanager " )
local UIManager = require ( " ui/uimanager " )
local VerticalGroup = require ( " ui/widget/verticalgroup " )
local VerticalGroup = require ( " ui/widget/verticalgroup " )
local Input = Device.input
local time = require ( " ui/time " )
local time = require ( " ui/time " )
local _ = require ( " gettext " )
local Screen = Device.screen
local Screen = Device.screen
local Input = Device.input
local band = bit.band
local band = bit.band
@ -41,13 +42,14 @@ local SOURCE_ALL = SOURCE_BOTTOM_MENU + SOURCE_DISPATCHER + SOURCE_OTHER
local Notification = InputContainer : extend {
local Notification = InputContainer : extend {
face = Font : getFace ( " x_smallinfofont " ) ,
face = Font : getFace ( " x_smallinfofont " ) ,
text = " Null Message " ,
text = _ ( " N/A " ) ,
margin = Size.margin . default ,
margin = Size.margin . default ,
padding = Size.padding . default ,
padding = Size.padding . default ,
timeout = 2 , -- default to 2 seconds
timeout = 2 , -- default to 2 seconds
toast = true , -- closed on any event, and let the event propagate to next top widget
toast = true , -- closed on any event, and let the event propagate to next top widget
_nums_shown = { } , -- actual static class member, array of stacked notifications
_shown_list = { } , -- actual static class member, array of stacked notifications (value is show (well, init) time or false).
_shown_idx = nil , -- index of this instance in the class's _shown_list array (assumes each Notification object is only shown (well, init) once).
SOURCE_BOTTOM_MENU_ICON = SOURCE_BOTTOM_MENU_ICON ,
SOURCE_BOTTOM_MENU_ICON = SOURCE_BOTTOM_MENU_ICON ,
SOURCE_BOTTOM_MENU_TOGGLE = SOURCE_BOTTOM_MENU_TOGGLE ,
SOURCE_BOTTOM_MENU_TOGGLE = SOURCE_BOTTOM_MENU_TOGGLE ,
@ -110,8 +112,8 @@ function Notification:init()
local notif_height = self.frame : getSize ( ) . h
local notif_height = self.frame : getSize ( ) . h
self : _cleanShownStack ( )
self : _cleanShownStack ( )
table.insert ( Notification._ nums_ shown, UIManager : getTime ( ) )
table.insert ( Notification._ shown_list , UIManager : getTime ( ) )
self. num = # Notification._nums_shown
self. _shown_idx = # Notification._shown_list
self [ 1 ] = VerticalGroup : new {
self [ 1 ] = VerticalGroup : new {
align = " center " ,
align = " center " ,
@ -156,30 +158,31 @@ function Notification:notify(arg, refresh_after)
return false
return false
end
end
function Notification : _cleanShownStack ( num )
function Notification : _cleanShownStack ( )
-- Clean stack of shown notifications
-- Clean stack of shown notifications
if num then
if self._shown_idx then
-- If this field exists, this is the first time this instance was closed since its init.
-- This notification is no longer displayed
-- This notification is no longer displayed
Notification._ nums_shown[ num ] = false
Notification._ shown_list[ self._shown_idx ] = false
end
end
-- We remove from the stack tail all slots no longer displayed.
-- We remove from the stack 's tail all slots no longer displayed.
-- Even if slots at top are available, we'll keep adding new
-- Even if slots at top are available, we'll keep adding new
-- notifications only at the tail/bottom (easier for the eyes
-- notifications only at the tail/bottom (easier for the eyes
-- to follow what is happening).
-- to follow what is happening).
-- As a sanity check, we also forget those shown for
-- As a sanity check, we also forget those shown for
-- more than 30s in case no close event was received.
-- more than 30s in case no close event was received.
local expire_time = UIManager : getTime ( ) - time.s ( 30 )
local expire_time = UIManager : getTime ( ) - time.s ( 30 )
for i = #Notification._ nums_ shown, 1 , - 1 do
for i = #Notification._ shown_list , 1 , - 1 do
if Notification._ nums_ shown[ i ] and Notification._ nums_ shown[ i ] > expire_time then
if Notification._ shown_list [ i ] and Notification._ shown_list [ i ] > expire_time then
break -- still shown (or not yet expired)
break -- still shown (or not yet expired)
end
end
table.remove ( Notification._ nums_ shown, i )
table.remove ( Notification._ shown_list , i )
end
end
end
end
function Notification : onCloseWidget ( )
function Notification : onCloseWidget ( )
self : _cleanShownStack ( self.num )
self : _cleanShownStack ( )
self. num = nil -- avoid mess in case onCloseWidget is call ed multiple times
self. _shown_idx = nil -- Don't do something stupid if this same instance gets clos ed multiple times
UIManager : setDirty ( nil , function ( )
UIManager : setDirty ( nil , function ( )
return " ui " , self.frame . dimen
return " ui " , self.frame . dimen
end )
end )
@ -208,4 +211,27 @@ function Notification:onTapClose()
return true
return true
end
end
-- Toasts should go bye-bye on user input, without stopping the event's propagation.
function Notification : onKeyPress ( key )
if self.toast then
UIManager : close ( self )
return false
end
return InputContainer.onKeyPress ( self , key )
end
function Notification : onKeyRepeat ( key )
if self.toast then
UIManager : close ( self )
return false
end
return InputContainer.onKeyRepeat ( self , key )
end
function Notification : onGesture ( ev )
if self.toast then
UIManager : close ( self )
return false
end
return InputContainer.onGesture ( self , ev )
end
return Notification
return Notification