@ -23,18 +23,41 @@ local _ = require("gettext")
local Screen = Device.screen
local T = require ( " ffi/util " ) . template
local screensaver_provider = {
[ " jpg " ] = true ,
[ " jpeg " ] = true ,
[ " png " ] = true ,
[ " gif " ] = true ,
[ " tif " ] = true ,
[ " tiff " ] = true ,
-- Migrate old settings from 2021.02 or older.
if G_reader_settings : readSetting ( " screensaver_type " , " disable " ) == " message " then
G_reader_settings : saveSetting ( " screensaver_type " , " disable " )
G_reader_settings : makeTrue ( " screensaver_show_message " )
end
if G_reader_settings : has ( " screensaver_no_background " ) then
if G_reader_settings : isTrue ( " screensaver_no_background " ) then
G_reader_settings : saveSetting ( " screensaver_background " , " none " )
end
G_reader_settings : delSetting ( " screensaver_no_background " )
end
if G_reader_settings : has ( " screensaver_white_background " ) then
if G_reader_settings : isTrue ( " screensaver_white_background " ) then
G_reader_settings : saveSetting ( " screensaver_background " , " white " )
end
G_reader_settings : delSetting ( " screensaver_white_background " )
end
local Screensaver = {
screensaver_provider = {
jpg = true ,
jpeg = true ,
png = true ,
gif = true ,
tif = true ,
tiff = true ,
} ,
default_screensaver_message = _ ( " Sleeping " ) ,
}
local default_screensaver_message = _ ( " Sleeping " )
local Screensaver = { }
local function getRandomImage ( dir )
function Screensaver : _getRandomImage ( dir )
if not dir then
return nil
end
if string.sub ( dir , string.len ( dir ) ) ~= " / " then
dir = dir .. " / "
end
@ -46,7 +69,7 @@ local function getRandomImage(dir)
for entry in iter , dir_obj do
if lfs.attributes ( dir .. entry , " mode " ) == " file " then
local extension = string.lower ( string.match ( entry , " .+%.([^.]+) " ) or " " )
if s creensaver_provider[ extension ] then
if s elf.s creensaver_provider[ extension ] then
i = i + 1
pics [ i ] = entry
end
@ -61,6 +84,114 @@ local function getRandomImage(dir)
return dir .. pics [ math.random ( i ) ]
end
local function expandSpecial ( message , fallback )
-- Expand special character sequences in given message.
-- %p percentage read
-- %c current page
-- %t total pages
-- %T document title
-- %A document authors
-- %S document series
if G_reader_settings : hasNot ( " lastfile " ) then
return fallback
end
local ret = message
local lastfile = G_reader_settings : readSetting ( " lastfile " )
local totalpages = 0
local percent = 0
local currentpage = 0
local title = _ ( " N/A " )
local authors = _ ( " N/A " )
local series = _ ( " N/A " )
local instance = require ( " apps/reader/readerui " ) : _getRunningInstance ( )
if instance == nil and DocSettings : hasSidecarFile ( lastfile ) then
-- If there's no ReaderUI instance, but the file has sidecar data, use that
local docinfo = DocSettings : open ( lastfile )
totalpages = docinfo.data . doc_pages or totalpages
percent = docinfo.data . percent_finished or percent
currentpage = Math.round ( percent * totalpages )
percent = Math.round ( percent * 100 )
if docinfo.data . doc_props then
title = docinfo.data . doc_props.title and docinfo.data . doc_props.title ~= " " and docinfo.data . doc_props.title or title
authors = docinfo.data . doc_props.authors and docinfo.data . doc_props.authors ~= " " and docinfo.data . doc_props.authors or authors
series = docinfo.data . doc_props.series and docinfo.data . doc_props.series ~= " " and docinfo.data . doc_props.series or series
end
docinfo : close ( )
elseif instance ~= nil and lfs.attributes ( lastfile , " mode " ) == " file " then
-- But if we have a ReaderUI instance, and the file stil exists, open it
local doc = DocumentRegistry : openDocument ( lastfile )
currentpage = instance.view . state.page or currentpage
totalpages = doc : getPageCount ( ) or totalpages
percent = Math.round ( ( currentpage * 100 ) / totalpages )
local props = doc : getProps ( )
if props then
title = props.title and props.title ~= " " and props.title or title
authors = props.authors and props.authors ~= " " and props.authors or authors
series = props.series and props.series ~= " " and props.series or series
end
doc : close ( )
end
ret = string.gsub ( ret , " %%c " , currentpage )
ret = string.gsub ( ret , " %%t " , totalpages )
ret = string.gsub ( ret , " %%p " , percent )
ret = string.gsub ( ret , " %%T " , title )
ret = string.gsub ( ret , " %%A " , authors )
ret = string.gsub ( ret , " %%S " , series )
return ret
end
local function addOverlayMessage ( widget , text )
local FrameContainer = require ( " ui/widget/container/framecontainer " )
local RightContainer = require ( " ui/widget/container/rightcontainer " )
local Size = require ( " ui/size " )
local TextWidget = require ( " ui/widget/textwidget " )
local face = Font : getFace ( " infofont " )
local screen_w , screen_h = Screen : getWidth ( ) , Screen : getHeight ( )
local textw = TextWidget : new {
text = text ,
face = face ,
}
-- Don't make our message reach full screen width
if textw : getWidth ( ) > screen_w * 0.9 then
-- Text too wide: use TextBoxWidget for multi lines display
textw = TextBoxWidget : new {
text = text ,
face = face ,
width = math.floor ( screen_w * 0.9 )
}
end
textw = FrameContainer : new {
background = Blitbuffer.COLOR_WHITE ,
bordersize = Size.border . default ,
margin = 0 ,
textw ,
}
textw = RightContainer : new {
dimen = {
w = screen_w ,
h = textw : getSize ( ) . h ,
} ,
textw ,
}
widget = OverlapGroup : new {
dimen = {
h = screen_w ,
w = screen_h ,
} ,
widget ,
textw ,
}
return widget
end
function Screensaver : chooseFolder ( )
local buttons = { }
table.insert ( buttons , {
@ -90,9 +221,7 @@ function Screensaver:chooseFolder()
}
} )
local screensaver_dir = G_reader_settings : readSetting ( " screensaver_dir " )
if screensaver_dir == nil then
screensaver_dir = DataStorage : getDataDir ( ) .. " /screenshots/ "
end
or DataStorage : getDataDir ( ) .. " /screenshots/ "
self.choose_dialog = ButtonDialogTitle : new {
title = T ( _ ( " Current screensaver image folder: \n %1 " ) , BD.dirpath ( screensaver_dir ) ) ,
buttons = buttons
@ -117,7 +246,7 @@ function Screensaver:chooseFile(document_cover)
local suffix = util.getFileNameSuffix ( filename )
if document_cover and DocumentRegistry : hasProvider ( filename ) then
return true
elseif s creensaver_provider[ suffix ] then
elseif s elf.s creensaver_provider[ suffix ] then
return true
end
end ,
@ -152,10 +281,8 @@ function Screensaver:chooseFile(document_cover)
}
} )
local screensaver_image = G_reader_settings : readSetting ( " screensaver_image " )
or DataStorage : getDataDir ( ) .. " /resources/koreader.png "
local screensaver_document_cover = G_reader_settings : readSetting ( " screensaver_document_cover " )
if screensaver_image == nil then
screensaver_image = DataStorage : getDataDir ( ) .. " /resources/koreader.png "
end
local title = document_cover and T ( _ ( " Current screensaver document cover: \n %1 " ) , BD.filepath ( screensaver_document_cover ) )
or T ( _ ( " Current screensaver image: \n %1 " ) , BD.filepath ( screensaver_image ) )
self.choose_dialog = ButtonDialogTitle : new {
@ -165,38 +292,25 @@ function Screensaver:chooseFile(document_cover)
UIManager : show ( self.choose_dialog )
end
function Screensaver : stretchImages ( )
return G_reader_settings : isTrue ( " screensaver_stretch_images " )
end
function Screensaver : whiteBackground ( )
return G_reader_settings : isTrue ( " screensaver_white_background " )
end
function Screensaver : noBackground ( )
return G_reader_settings : isTrue ( " screensaver_no_background " )
end
function Screensaver : showMessage ( )
return G_reader_settings : isTrue ( " screensaver_show_message " )
end
function Screensaver : isExcluded ( )
if G_reader_settings : hasNot ( " lastfile " ) then
return false
end
function Screensaver : excluded ( )
local lastfile = G_reader_settings : readSetting ( " lastfile " )
local exclude_ss = false -- consider it not excluded if there's no docsetting
if DocSettings : hasSidecarFile ( lastfile ) then
local doc_settings = DocSettings : open ( lastfile )
exclude_ss = doc_settings : readSetting ( " exclude_screensaver " )
return doc_settings : isTrue ( " exclude_screensaver " )
else
-- No DocSetting, not excluded
return false
end
return exclude_ss or false
end
function Screensaver : setMessage ( )
local InputDialog = require ( " ui/widget/inputdialog " )
local screensaver_message = G_reader_settings : readSetting ( " screensaver_message " )
if screensaver_message == nil then
screensaver_message = default_screensaver_message
end
or self.default_screensaver_message
self.input_dialog = InputDialog : new {
title = " Screensaver message " ,
description = _ ( " Enter the message to be displayed by the screensaver. The following escape sequences can be used: \n %p percentage read \n %c current page number \n %t total number of pages \n %T title \n %A authors \n %S series " ) ,
@ -224,203 +338,245 @@ function Screensaver:setMessage()
self.input_dialog : onShowKeyboard ( )
end
function Screensaver : show ( event , fallback_message )
-- These 2 (optional) parameters are to support poweroff and reboot actions
-- on Kobo (see uimanager.lua)
if self.left_msg then
UIManager : close ( self.left_msg )
self.left_msg = nil
end
local covers_fullscreen = true -- hint for UIManager:_repaint()
local overlay_message
local prefix = event and event .. " _ " or " " -- "", "poweroff_" or "reboot_"
local screensaver_type = G_reader_settings : readSetting ( prefix .. " screensaver_type " )
if prefix and not screensaver_type then
-- No manually added setting for poweroff/reboot, fallback to using the
-- same settings as for suspend that could be set via menus
screensaver_type = G_reader_settings : readSetting ( " screensaver_type " )
prefix = " "
-- And display fallback_message over the common screensaver,
-- so user can distinguish between suspend (no message) and
-- poweroff (overlay message)
overlay_message = fallback_message
end
-- When called after setup(), may not match the saved settings, because it accounts for fallbacks that might have kicked in.
function Screensaver : getMode ( )
return self.screensaver_type
end
local show_message = self : showMessage ( )
function Screensaver : modeExpectsPortrait ( )
return self.screensaver_type ~= " message "
and self.screensaver_type ~= " disable "
and self.screensaver_type ~= " readingprogress "
and self.screensaver_type ~= " bookstatus "
end
if screensaver_type == nil then
show_message = true
end
function Screensaver : modeIsImage ( )
return self.screensaver_type == " cover "
or self.screensaver_type == " random_image "
or self.screensaver_type == " image_file "
end
if screensaver_type == " message " then
-- obsolete screensaver_type: migrate to new show_message = true
screensaver_type = " disable "
G_reader_settings : saveSetting ( " screensaver_type " , " disable " )
G_reader_settings : saveSetting ( " screensaver_show_message " , true )
end
function Screensaver : withBackground ( )
return self.screensaver_background ~= " none "
end
-- messages can still be shown over "as-is" screensaver
if screensaver_type == " disable " and show_message == false then
return
function Screensaver : setup ( event , fallback_message )
-- Handle user settings & defaults
if G_reader_settings : has ( " screensaver_show_message " ) then
self.show_message = G_reader_settings : isTrue ( " screensaver_show_message " )
else
self.screensaver_type = " disable "
self.show_message = true
end
local widget = nil
local no_background = false
local background = Blitbuffer.COLOR_BLACK
if self : whiteBackground ( ) then
background = Blitbuffer.COLOR_WHITE
elseif self : noBackground ( ) then
background = nil
no_background = true
if G_reader_settings : has ( " screensaver_type " ) then
self.screensaver_type = G_reader_settings : readSetting ( " screensaver_type " )
else
self.screensaver_type = " disable "
self.show_message = true
end
if G_reader_settings : has ( " screensaver_background " ) then
self.screensaver_background = G_reader_settings : readSetting ( " screensaver_background " )
else
self.screensaver_background = " black "
end
-- "as-is" mode obviously requires not mangling the background ;).
if screensaver_type == " disable " then
-- NOTE: Ideally, "disable" mode should *honor* all the "background" options.
-- Unfortunately, the no background option is much more recent than the "disable" mode,
-- and as such, the default assumes that in "disable" mode, the default background is nil instead of black.
-- This implies that, for the same legacy reasons, we have to honor the *white* background setting here...
-- (Which means that you can have no background, a white background, but *NOT* a black background in this mode :/).
if not self : whiteBackground ( ) then
background = nil
no_background = true
-- These 2 (optional) parameters are to support poweroff and reboot actions on Kobo (c.f., UIManager)
self.prefix = event and event .. " _ " or " " -- "", "poweroff_" or "reboot_"
self.fallback_message = fallback_message
self.overlay_message = nil
if G_reader_settings : has ( self.prefix .. " screensaver_type " ) then
self.screensaver_type = G_reader_settings : readSetting ( self.prefix .. " screensaver_type " )
else
if event then
-- Display the provided fallback_message over the screensaver,
-- so the user can distinguish between suspend (no overlay),
-- and reboot/poweroff (overlaid message).
self.overlay_message = self.fallback_message
end
end
local lastfile = G_reader_settings : readSetting ( " lastfile " )
if screensaver_type == " document_cover " then
-- Reset state
self.lastfile = nil
self.image = nil
self.image_file = nil
-- Check lastfile and setup the requested mode's resources, or a fallback mode if the required resources are unavailable.
self.lastfile = G_reader_settings : readSetting ( " lastfile " )
if self.screensaver_type == " document_cover " then
-- Set lastfile to the document of which we want to show the cover.
lastfile = G_reader_settings : readSetting ( " screensaver_document_cover " )
screensaver_type = " cover "
self. lastfile = G_reader_settings : readSetting ( " screensaver_document_cover " )
s elf.s creensaver_type = " cover "
end
if screensaver_type == " cover " then
lastfile = lastfile ~= nil and lastfile or G_reader_settings : readSetting ( " lastfile " )
local exclude = false -- consider it not excluded if there's no docsetting
if DocSettings : hasSidecarFile ( lastfile ) then
local doc_settings = DocSettings : open ( lastfile )
exclude = doc_settings : readSetting ( " exclude_screensaver " )
if self.screensaver_type == " cover " then
self.lastfile = self.lastfile ~= nil and self.lastfile or G_reader_settings : readSetting ( " lastfile " )
local excluded
if DocSettings : hasSidecarFile ( self.lastfile ) then
local doc_settings = DocSettings : open ( self.lastfile )
excluded = doc_settings : isTrue ( " exclude_screensaver " )
else
-- No DocSetting, not excluded
excluded = false
end
if exclude ~= true then
if lastfile and lfs.attributes ( lastfile , " mode " ) == " file " then
local doc = DocumentRegistry : openDocument ( lastfile)
if not excluded then
if self. lastfile and lfs.attributes ( self. lastfile, " mode " ) == " file " then
local doc = DocumentRegistry : openDocument ( self. lastfile)
if doc.loadDocument then -- CreDocument
doc : loadDocument ( false ) -- load only metadata
end
local image = doc : getCoverPageImage ( )
self. image = doc : getCoverPageImage ( )
doc : close ( )
if image ~= nil then
widget = ImageWidget : new {
image = image ,
image_disposable = true ,
height = Screen : getHeight ( ) ,
width = Screen : getWidth ( ) ,
scale_factor = not self : stretchImages ( ) and 0 or nil ,
}
else
screensaver_type = " random_image "
if self.image == nil then
self.screensaver_type = " random_image "
end
else
s creensaver_type = " random_image "
self.screensaver_type = " random_image "
end
else --fallback to random images if this book cover is excluded
screensaver_type = " random_image "
else
-- Fallback to random images if this book cover is excluded
self.screensaver_type = " random_image "
end
end
if screensaver_type == " bookstatus " then
if lastfile and lfs.attributes ( lastfile , " mode " ) == " file " then
local doc = DocumentRegistry : openDocument ( lastfile )
local doc_settings = DocSettings : open ( lastfile )
if self.screensaver_type == " bookstatus " then
if self.lastfile and lfs.attributes ( self.lastfile , " mode " ) == " file " then
local instance = require ( " apps/reader/readerui " ) : _getRunningInstance ( )
if instance ~= nil then
widget = BookStatusWidget : new {
thumbnail = doc : getCoverPageImage ( ) ,
props = doc : getProps ( ) ,
document = doc ,
settings = doc_settings ,
view = instance.view ,
readonly = true ,
}
else
show_message = true
if instance == nil then
self.screensaver_type = " disable "
self.show_message = true
end
doc : close ( )
else
show_message = true
self.screensaver_type = " disable "
self.show_message = true
end
end
if screensaver_type == " random_image " then
local screensaver_dir = G_reader_settings : readSetting ( prefix .. " screensaver_dir " )
if screensaver_dir == nil and prefix ~= " " then
screensaver_dir = G_reader_settings : readSetting ( " screensaver_dir " )
end
if screensaver_dir == nil then
screensaver_dir = DataStorage : getDataDir ( ) .. " /screenshots/ "
end
local image_file = getRandomImage ( screensaver_dir )
if image_file == nil then
show_message = true
else
widget = ImageWidget : new {
file = image_file ,
file_do_cache = false ,
alpha = true ,
height = Screen : getHeight ( ) ,
width = Screen : getWidth ( ) ,
scale_factor = not self : stretchImages ( ) and 0 or nil ,
}
if self.screensaver_type == " random_image " then
local screensaver_dir = G_reader_settings : readSetting ( self.prefix .. " screensaver_dir " )
or G_reader_settings : readSetting ( " screensaver_dir " )
self.image_file = self : _getRandomImage ( screensaver_dir )
if self.image_file == nil then
self.screensaver_type = " disable "
self.show_message = true
end
end
if screensaver_type == " image_file " then
local screensaver_image = G_reader_settings : readSetting ( prefix .. " screensaver_image " )
if screensaver_image == nil and prefix ~= " " then
screensaver_image = G_reader_settings : readSetting ( " screensaver_image " )
end
if screensaver_image == nil then
screensaver_image = DataStorage : getDataDir ( ) .. " /resources/koreader.png "
end
if lfs.attributes ( screensaver_image , " mode " ) ~= " file " then
show_message = true
else
widget = ImageWidget : new {
file = screensaver_image ,
file_do_cache = false ,
alpha = true ,
height = Screen : getHeight ( ) ,
width = Screen : getWidth ( ) ,
scale_factor = not self : stretchImages ( ) and 0 or nil ,
}
if self.screensaver_type == " image_file " then
self.image_file = G_reader_settings : readSetting ( self.prefix .. " screensaver_image " )
or G_reader_settings : readSetting ( " screensaver_image " )
if self.image_file == nil or lfs.attributes ( self.image_file , " mode " ) ~= " file " then
self.screensaver_type = " disable "
self.show_message = true
end
end
if s creensaver_type == " readingprogress " then
if Screensaver.getReaderProgress ~= nil the n
widget = Screensaver.getReaderProgress ( )
else
s how_message = true
if self.screensaver_type == " readingprogress " then
-- This is implemented by the Statistics plugin
if Screensaver.getReaderProgress == nil then
self.screensaver_type = " disable "
self.show_message = true
end
end
if show_message == true then
local screensaver_message = G_reader_settings : readSetting ( prefix .. " screensaver_message " )
local message_pos = G_reader_settings : readSetting ( prefix .. " screensaver_message_position " )
if no_background and widget == nil then
covers_fullscreen = false
-- Now that the fallbacks are in place, we know the *effective* screensaver mode.
-- For non-image modes, make black (which is also the default) synonymous with none.
-- The reasoning is that disable + show_message, which is our default and fallback,
-- looks *terrible* with a black background, which is also our default and fallback ;).
if not self : modeIsImage ( ) and self.screensaver_background == " black " then
self.screensaver_background = " none "
end
end
function Screensaver : show ( )
if self.screensaver_widget then
UIManager : close ( self.screensaver_widget )
self.screensaver_widget = nil
end
-- In as-is mode with no message and no overlay, we've got nothing to show :)
if self.screensaver_type == " disable " and not self.show_message and not self.overlay_message then
return
end
-- Build the main widget for the effective mode, all the sanity checks were handled in setup
local widget = nil
if self.screensaver_type == " cover " then
widget = ImageWidget : new {
image = self.image ,
image_disposable = true ,
height = Screen : getHeight ( ) ,
width = Screen : getWidth ( ) ,
scale_factor = G_reader_settings : isTrue ( " screensaver_stretch_images " ) and nil or 0 ,
}
elseif self.screensaver_type == " bookstatus " then
local doc = DocumentRegistry : openDocument ( self.lastfile )
local doc_settings = DocSettings : open ( self.lastfile )
local instance = require ( " apps/reader/readerui " ) : _getRunningInstance ( )
widget = BookStatusWidget : new {
thumbnail = doc : getCoverPageImage ( ) ,
props = doc : getProps ( ) ,
document = doc ,
settings = doc_settings ,
view = instance.view ,
readonly = true ,
}
doc : close ( )
elseif self.screensaver_type == " random_image " or self.screensaver_type == " image_file " then
widget = ImageWidget : new {
file = self.image_file ,
file_do_cache = false ,
alpha = true ,
height = Screen : getHeight ( ) ,
width = Screen : getWidth ( ) ,
scale_factor = G_reader_settings : isTrue ( " screensaver_stretch_images " ) and nil or 0 ,
}
elseif self.screensaver_type == " readingprogress " then
widget = Screensaver.getReaderProgress ( )
end
-- Assume that we'll be covering the full-screen by default (either because of a widget, or a background fill).
local covers_fullscreen = true
-- Speaking of, set that background fill up...
local background
if self.screensaver_background == " black " then
background = Blitbuffer.COLOR_BLACK
elseif self.screensaver_background == " white " then
background = Blitbuffer.COLOR_WHITE
elseif self.screensaver_background == " none " then
background = nil
end
if self.show_message then
-- Handle user settings & fallbacks, with that prefix mess on top...
local screensaver_message
if G_reader_settings : has ( self.prefix .. " screensaver_message " ) then
screensaver_message = G_reader_settings : readSetting ( self.prefix .. " screensaver_message " )
else
if G_reader_settings : has ( " screensaver_message " ) then
-- We prefer the global user setting to the event's fallback message.
screensaver_message = G_reader_settings : readSetting ( " screensaver_message " )
else
screensaver_message = self.fallback_message or self.default_screensaver_message
end
end
if screensaver_message == nil and prefix ~= " " then
screensaver_message = G_reader_settings : readSetting ( " screensaver_message " )
-- NOTE: Only attempt to expand if there are special characters in the message.
if screensaver_message : find ( " %% " ) then
screensaver_message = expandSpecial ( screensaver_message , self.fallback_message or self.default_screensaver_message )
end
local fallback = fallback_message or default_screensaver_message
if screensaver_message == nil then
screensaver_message = fallback
local message_pos
if G_reader_settings: has ( self.prefix .. " screensaver_message_position " ) then
message_pos = G_reader_settings : readSetting ( self.prefix .. " screensaver_message_position " )
else
-- NOTE: Only attempt to expand if there are special characters in the message.
if screensaver_message : find ( " %% " ) then
screensaver_message = self : expandSpecial ( screensaver_message , fallback )
if G_reader_settings : has ( " screensaver_message_position " ) then
message_pos = G_reader_settings : readSetting ( " screensaver_message_position " )
else
message_pos = " middle "
end
end
-- The only case where we *won't* cover the full-screen is when we only display a message and no background.
if widget == nil and self.screensaver_background == " none " then
covers_fullscreen = false
end
local message_widget
if message_pos == " middle " or message_pos == nil then
if message_pos == " middle " then
message_widget = InfoMessage : new {
text = screensaver_message ,
readonly = true ,
@ -449,13 +605,13 @@ function Screensaver:show(event, fallback_message)
}
end
-- No overlay needed as we just displayed the message
overlay_message = nil
-- No overlay needed as we just displayed *a* message (not necessarily the event's, though).
self. overlay_message = nil
-- c heck if message_widget should be overlaid on another widget
-- C heck if message_widget should be overlaid on another widget
if message_widget then
if widget then -- we have a s creensaver widget
-- s how message_widget on top of previously created widget
if widget then -- We have a S creensaver widget
-- S how message_widget on top of previously created widget
local screen_w , screen_h = Screen : getWidth ( ) , Screen : getHeight ( )
widget = OverlapGroup : new {
dimen = {
@ -466,158 +622,52 @@ function Screensaver:show(event, fallback_message)
message_widget ,
}
else
-- no prevously created widget so just show message widget
-- No prevously created widget, so just show message widget
widget = message_widget
end
end
end
if overlay_message then
widget = self: addOverlayMessage( widget , overlay_message)
if self. overlay_message then
widget = addOverlayMessage( widget , self. overlay_message)
end
if widget then
self. left_msg = ScreenSaverWidget : new {
self. screensaver_widget = ScreenSaverWidget : new {
widget = widget ,
background = background ,
covers_fullscreen = covers_fullscreen ,
}
self.left_msg . modal = true
-- Refresh whole screen for other types
self.left_msg . dithered = true
UIManager : show ( self.left_msg , " full " )
self.screensaver_widget . modal = true
self.screensaver_widget . dithered = true
UIManager : show ( self.screensaver_widget , " full " )
end
end
function Screensaver : expandSpecial ( message , fallback )
-- Expand special character sequences in given message.
-- %p percentage read
-- %c current page
-- %t total pages
-- %T document title
-- %A document authors
-- %S document series
local ret = message
local lastfile = G_reader_settings : readSetting ( " lastfile " )
if not lastfile then
return fallback
end
local totalpages = 0
local percent = 0
local currentpage = 0
local title = " N/A "
local authors = " N/A "
local series = " N/A "
local instance = require ( " apps/reader/readerui " ) : _getRunningInstance ( )
if instance == nil and DocSettings : hasSidecarFile ( lastfile ) then
-- If there's no ReaderUI instance, but the file has sidecar data, use that
local docinfo = DocSettings : open ( lastfile )
totalpages = docinfo.data . doc_pages or totalpages
percent = docinfo.data . percent_finished or percent
currentpage = Math.round ( percent * totalpages )
percent = Math.round ( percent * 100 )
if docinfo.data . doc_props then
title = docinfo.data . doc_props.title and docinfo.data . doc_props.title ~= " " and docinfo.data . doc_props.title or title
authors = docinfo.data . doc_props.authors and docinfo.data . doc_props.authors ~= " " and docinfo.data . doc_props.authors or authors
series = docinfo.data . doc_props.series and docinfo.data . doc_props.series ~= " " and docinfo.data . doc_props.series or series
end
docinfo : close ( )
elseif instance ~= nil and lfs.attributes ( lastfile , " mode " ) == " file " then
-- But if we have a ReaderUI instance, and the file stil exists, open it
local doc = DocumentRegistry : openDocument ( lastfile )
currentpage = instance.view . state.page or currentpage
totalpages = doc : getPageCount ( ) or totalpages
percent = Math.round ( ( currentpage * 100 ) / totalpages )
local props = doc : getProps ( )
if props then
title = props.title and props.title ~= " " and props.title or title
authors = props.authors and props.authors ~= " " and props.authors or authors
series = props.series and props.series ~= " " and props.series or series
end
doc : close ( )
function Screensaver : close ( )
if self.screensaver_widget == nil then
return
end
ret = string.gsub ( ret , " %%c " , currentpage )
ret = string.gsub ( ret , " %%t " , totalpages )
ret = string.gsub ( ret , " %%p " , percent )
ret = string.gsub ( ret , " %%T " , title )
ret = string.gsub ( ret , " %%A " , authors )
ret = string.gsub ( ret , " %%S " , series )
return ret
end
function Screensaver : close ( )
if self.left_msg == nil then return end
local screensaver_delay = G_reader_settings : readSetting ( " screensaver_delay " )
local screensaver_delay_number = tonumber ( screensaver_delay )
if screensaver_delay_number then
UIManager : scheduleIn ( screensaver_delay_number , function ( )
logger.dbg ( " close screensaver " )
if self. left_msg then
UIManager : close ( self. left_msg , " full " )
self. left_msg = nil
if self.screensaver_widget then
UIManager : close ( self.screensaver_widget , " full " )
self.screensaver_widget = nil
end
end )
elseif screensaver_delay == " disable " or screensaver_delay == nil then
logger.dbg ( " close screensaver " )
if self. left_msg then
UIManager : close ( self. left_msg , " full " )
self. left_msg = nil
if self.screensaver_widget then
UIManager : close ( self.screensaver_widget , " full " )
self.screensaver_widget = nil
end
else
logger.dbg ( " tap to exit from screensaver " )
end
end
function Screensaver : addOverlayMessage ( widget , text )
local FrameContainer = require ( " ui/widget/container/framecontainer " )
local RightContainer = require ( " ui/widget/container/rightcontainer " )
local Size = require ( " ui/size " )
local TextWidget = require ( " ui/widget/textwidget " )
local face = Font : getFace ( " infofont " )
local screen_w , screen_h = Screen : getWidth ( ) , Screen : getHeight ( )
local textw = TextWidget : new {
text = text ,
face = face ,
}
-- Don't make our message reach full screen width
if textw : getWidth ( ) > screen_w * 0.9 then
-- Text too wide: use TextBoxWidget for multi lines display
textw = TextBoxWidget : new {
text = text ,
face = face ,
width = math.floor ( screen_w * 0.9 )
}
end
textw = FrameContainer : new {
background = Blitbuffer.COLOR_WHITE ,
bordersize = Size.border . default ,
margin = 0 ,
textw ,
}
textw = RightContainer : new {
dimen = {
w = screen_w ,
h = textw : getSize ( ) . h ,
} ,
textw ,
}
widget = OverlapGroup : new {
dimen = {
h = screen_w ,
w = screen_h ,
} ,
widget ,
textw ,
}
return widget
end
return Screensaver