Folder shortcuts: new markers, buttons (#11108)

Buttons to add/remove folder shortcut from Plus menu and from folder popup dialog.
A marker ("empty star") for folders with shortcuts.
reviewable/pr11126/r1
hius07 6 months ago committed by GitHub
parent ed46dca886
commit 88d6613fed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -109,6 +109,15 @@ function FileManager:onSetDimensions(dimen)
end end
end end
function FileManager:updateTitleBarPath(path)
path = path or self.file_chooser.path
local text = BD.directory(filemanagerutil.abbreviate(path))
if FileManagerShortcuts:hasFolderShortcut(path) then
text = "" .. text
end
self.title_bar:setSubTitle(text)
end
function FileManager:setupLayout() function FileManager:setupLayout()
self.show_parent = self.show_parent or self self.show_parent = self.show_parent or self
self.title_bar = TitleBar:new{ self.title_bar = TitleBar:new{
@ -116,7 +125,7 @@ function FileManager:setupLayout()
align = "center", align = "center",
title = self.title, title = self.title,
title_top_padding = Screen:scaleBySize(6), title_top_padding = Screen:scaleBySize(6),
subtitle = BD.directory(filemanagerutil.abbreviate(self.root_path)), subtitle = "",
subtitle_truncate_left = true, subtitle_truncate_left = true,
subtitle_fullwidth = true, subtitle_fullwidth = true,
button_padding = Screen:scaleBySize(5), button_padding = Screen:scaleBySize(5),
@ -129,6 +138,7 @@ function FileManager:setupLayout()
right_icon_tap_callback = function() self:onShowPlusMenu() end, right_icon_tap_callback = function() self:onShowPlusMenu() end,
right_icon_hold_callback = false, -- propagate long-press to dispatcher right_icon_hold_callback = false, -- propagate long-press to dispatcher
} }
self:updateTitleBarPath(self.root_path)
local file_chooser = FileChooser:new{ local file_chooser = FileChooser:new{
-- remember to adjust the height when new item is added to the group -- remember to adjust the height when new item is added to the group
@ -153,7 +163,7 @@ function FileManager:setupLayout()
local file_manager = self local file_manager = self
function file_chooser:onPathChanged(path) -- luacheck: ignore function file_chooser:onPathChanged(path) -- luacheck: ignore
file_manager.title_bar:setSubTitle(BD.directory(filemanagerutil.abbreviate(path))) file_manager:updateTitleBarPath(path)
return true return true
end end
@ -183,6 +193,18 @@ function FileManager:setupLayout()
local is_file = lfs.attributes(file, "mode") == "file" local is_file = lfs.attributes(file, "mode") == "file"
local is_folder = lfs.attributes(file, "mode") == "directory" local is_folder = lfs.attributes(file, "mode") == "directory"
local is_not_parent_folder = BaseUtil.basename(file) ~= ".." local is_not_parent_folder = BaseUtil.basename(file) ~= ".."
local function close_dialog_callback()
UIManager:close(self.file_dialog)
end
local function refresh_callback()
self:refreshPath()
end
local function close_dialog_refresh_callback()
UIManager:close(self.file_dialog)
self:refreshPath()
end
local buttons = { local buttons = {
{ {
{ {
@ -227,10 +249,7 @@ function FileManager:setupLayout()
enabled = is_not_parent_folder, enabled = is_not_parent_folder,
callback = function() callback = function()
UIManager:close(self.file_dialog) UIManager:close(self.file_dialog)
local function post_delete_callback() file_manager:showDeleteFileDialog(file, refresh_callback)
self:refreshPath()
end
file_manager:showDeleteFileDialog(file, post_delete_callback)
end, end,
}, },
{ {
@ -246,19 +265,12 @@ function FileManager:setupLayout()
} }
if is_file then if is_file then
local function close_dialog_callback()
UIManager:close(self.file_dialog)
end
local function status_button_callback()
UIManager:close(self.file_dialog)
self:refreshPath() -- sidecar folder may be created/deleted
end
local has_provider = DocumentRegistry:hasProvider(file) local has_provider = DocumentRegistry:hasProvider(file)
if has_provider or DocSettings:hasSidecarFile(file) then if has_provider or DocSettings:hasSidecarFile(file) then
table.insert(buttons, filemanagerutil.genStatusButtonsRow(file, status_button_callback)) table.insert(buttons, filemanagerutil.genStatusButtonsRow(file, close_dialog_refresh_callback))
table.insert(buttons, {}) -- separator table.insert(buttons, {}) -- separator
table.insert(buttons, { table.insert(buttons, {
filemanagerutil.genResetSettingsButton(file, status_button_callback), filemanagerutil.genResetSettingsButton(file, close_dialog_refresh_callback),
filemanagerutil.genAddRemoveFavoritesButton(file, close_dialog_callback), filemanagerutil.genAddRemoveFavoritesButton(file, close_dialog_callback),
}) })
end end
@ -297,15 +309,19 @@ function FileManager:setupLayout()
end end
if is_folder then if is_folder then
local folder = BaseUtil.realpath(file)
table.insert(buttons, { table.insert(buttons, {
{ {
text = _("Set as HOME folder"), text = _("Set as HOME folder"),
callback = function() callback = function()
UIManager:close(self.file_dialog) UIManager:close(self.file_dialog)
file_manager:setHome(BaseUtil.realpath(file)) file_manager:setHome(folder)
end end
}, },
}) })
table.insert(buttons, {
file_manager.folder_shortcuts:genAddRemoveShortcutButton(folder, close_dialog_callback, refresh_callback)
})
end end
self.file_dialog = ButtonDialog:new{ self.file_dialog = ButtonDialog:new{
@ -471,6 +487,13 @@ function FileManager:onToggleSelectMode(no_refresh)
end end
function FileManager:tapPlus() function FileManager:tapPlus()
local function close_dialog_callback()
UIManager:close(self.file_dialog)
end
local function refresh_titlebar_callback()
self:updateTitleBarPath()
end
local title, buttons local title, buttons
if self.select_mode then if self.select_mode then
local select_count = util.tableSize(self.selected_files) local select_count = util.tableSize(self.selected_files)
@ -589,13 +612,7 @@ function FileManager:tapPlus()
self:createFolder() self:createFolder()
end, end,
}, },
{ self.folder_shortcuts:genShowFolderShortcutsButton(close_dialog_callback),
text = _("Folder shortcuts"),
callback = function()
UIManager:close(self.file_dialog)
self:handleEvent(Event:new("ShowFolderShortcutsDialog"))
end
},
}, },
} }
else else
@ -636,7 +653,7 @@ function FileManager:tapPlus()
UIManager:close(self.file_dialog) UIManager:close(self.file_dialog)
self:setHome(self.file_chooser.path) self:setHome(self.file_chooser.path)
end end
} },
}, },
{ {
{ {
@ -645,7 +662,7 @@ function FileManager:tapPlus()
UIManager:close(self.file_dialog) UIManager:close(self.file_dialog)
self:goHome() self:goHome()
end end
} },
}, },
{ {
{ {
@ -654,17 +671,14 @@ function FileManager:tapPlus()
UIManager:close(self.file_dialog) UIManager:close(self.file_dialog)
self:openRandomFile(self.file_chooser.path) self:openRandomFile(self.file_chooser.path)
end end
} },
}, },
{ {
{ self.folder_shortcuts:genShowFolderShortcutsButton(close_dialog_callback),
text = _("Folder shortcuts"), },
callback = function() {
UIManager:close(self.file_dialog) self.folder_shortcuts:genAddRemoveShortcutButton(self.file_chooser.path, close_dialog_callback, refresh_titlebar_callback),
self:handleEvent(Event:new("ShowFolderShortcutsDialog")) },
end
}
}
} }
if Device:hasExternalSD() then if Device:hasExternalSD() then

@ -2,7 +2,6 @@ local BD = require("ui/bidi")
local CenterContainer = require("ui/widget/container/centercontainer") local CenterContainer = require("ui/widget/container/centercontainer")
local ConfirmBox = require("ui/widget/confirmbox") local ConfirmBox = require("ui/widget/confirmbox")
local Device = require("device") local Device = require("device")
local Event = require("ui/event")
local FFIUtil = require("ffi/util") local FFIUtil = require("ffi/util")
local InputContainer = require("ui/widget/container/inputcontainer") local InputContainer = require("ui/widget/container/inputcontainer")
local PluginLoader = require("pluginloader") local PluginLoader = require("pluginloader")
@ -359,8 +358,7 @@ function FileManagerMenu:setUpdateItemTable()
end, end,
callback = function() callback = function()
G_reader_settings:flipNilOrTrue("shorten_home_dir") G_reader_settings:flipNilOrTrue("shorten_home_dir")
local FileManager = require("apps/filemanager/filemanager") self.ui:updateTitleBarPath()
if FileManager.instance then FileManager.instance:reinit() end
end, end,
help_text = _([[ help_text = _([[
"Shorten home folder" will display the home folder itself as "Home" instead of its full path. "Shorten home folder" will display the home folder itself as "Home" instead of its full path.
@ -786,7 +784,7 @@ The sorting order is the same as in filemanager.
Tap a book in the search results to open it.]]), Tap a book in the search results to open it.]]),
callback = function() callback = function()
self.ui:handleEvent(Event:new("ShowFileSearch")) self.ui.filesearcher:onShowFileSearch()
end end
} }

@ -7,199 +7,210 @@ local Screen = require("device").screen
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer") local WidgetContainer = require("ui/widget/container/widgetcontainer")
local lfs = require("libs/libkoreader-lfs") local lfs = require("libs/libkoreader-lfs")
local util = require("ffi/util")
local _ = require("gettext") local _ = require("gettext")
local T = util.template
local FileManagerShortcuts = WidgetContainer:extend{ local FileManagerShortcuts = WidgetContainer:extend{
title = _("Folder shortcuts"),
folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts", {}), folder_shortcuts = G_reader_settings:readSetting("folder_shortcuts", {}),
} }
function FileManagerShortcuts:updateItemTable(select_callback) function FileManagerShortcuts:updateItemTable()
local item_table = {} local item_table = {}
for _, item in ipairs(self.folder_shortcuts) do for _, item in ipairs(self.folder_shortcuts) do
table.insert(item_table, { table.insert(item_table, {
text = string.format("%s (%s)", item.text, item.folder), text = string.format("%s (%s)", item.text, item.folder),
folder = item.folder, folder = item.folder,
friendly_name = item.text, name = item.text,
deletable = true,
editable = true,
callback = function()
UIManager:close(self.fm_bookmark)
local folder = item.folder
if folder ~= nil and lfs.attributes(folder, "mode") == "directory" then
if select_callback then
select_callback(folder)
else
if self.ui.file_chooser then
self.ui.file_chooser:changeToPath(folder)
else -- called from Reader
self.ui:onClose()
self.ui:showFileManager(folder .. "/")
end
end
end
end,
}) })
end end
table.sort(item_table, function(l, r) table.sort(item_table, function(l, r)
return l.text < r.text return l.text < r.text
end) end)
-- try to stay on current page -- try to stay on current page
local select_number local select_number
if self.shortcuts_menu.page and self.shortcuts_menu.perpage and self.shortcuts_menu.page > 0 then
if self.fm_bookmark.page and self.fm_bookmark.perpage and self.fm_bookmark.page > 0 then select_number = (self.shortcuts_menu.page - 1) * self.shortcuts_menu.perpage + 1
select_number = (self.fm_bookmark.page - 1) * self.fm_bookmark.perpage + 1
end end
self.shortcuts_menu:switchItemTable(nil, item_table, select_number)
self.fm_bookmark:switchItemTable(nil,
item_table, select_number)
end end
function FileManagerShortcuts:addNewFolder() function FileManagerShortcuts:_getIndex(folder)
local PathChooser = require("ui/widget/pathchooser") for i, v in ipairs(self.folder_shortcuts) do
local path_chooser = PathChooser:new{ if v.folder == folder then
select_directory = true, return i
select_file = false,
path = self.fm_bookmark.curr_path,
onConfirm = function(path)
local add_folder_input
local friendly_name = util.basename(path) or _("my folder")
add_folder_input = InputDialog:new{
title = _("Enter friendly name"),
input = friendly_name,
description = T(_("Title for selected folder:\n%1"), BD.dirpath(path)),
buttons = {
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(add_folder_input)
end,
},
{
text = _("Add"),
is_enter_default = true,
callback = function()
self:addFolderFromInput(add_folder_input:getInputValue(), path)
UIManager:close(add_folder_input)
end,
},
}
},
}
UIManager:show(add_folder_input)
add_folder_input:onShowKeyboard()
end end
} end
UIManager:show(path_chooser) end
function FileManagerShortcuts:hasFolderShortcut(folder)
return self:_getIndex(folder) and true or false
end end
function FileManagerShortcuts:addFolderFromInput(friendly_name, folder) function FileManagerShortcuts:onMenuChoice(item)
for __, item in ipairs(self.folder_shortcuts) do local folder = item.folder
if item.text == friendly_name and item.folder == folder then if lfs.attributes(folder, "mode") ~= "directory" then return end
UIManager:show(InfoMessage:new{ if self.select_callback then
text = _("A shortcut to this folder already exists."), self.select_callback(folder)
}) else
return if self._manager.ui.file_chooser then
self._manager.ui.file_chooser:changeToPath(folder)
else -- called from Reader
self._manager.ui:onClose()
self._manager.ui:showFileManager(folder .. "/")
end end
end end
table.insert(self.folder_shortcuts, {
text = friendly_name,
folder = folder,
})
self:updateItemTable()
end end
function FileManagerShortcuts:onMenuHold(item) function FileManagerShortcuts:onMenuHold(item)
if item.deletable or item.editable then local dialog
local folder_shortcuts_dialog local buttons = {
folder_shortcuts_dialog = ButtonDialog:new{ {
buttons = { {
{ text = _("Remove shortcut"),
{ callback = function()
text = _("Paste file"), UIManager:close(dialog)
enabled = (self._manager.ui.file_chooser and self._manager.ui.clipboard) and true or false, self._manager:removeShortcut(item.folder)
callback = function() end
UIManager:close(folder_shortcuts_dialog) },
self._manager.ui:pasteHere(item.folder) {
end text = _("Rename shortcut"),
}, callback = function()
{ UIManager:close(dialog)
text = _("Edit"), self._manager:editShortcut(item.folder)
enabled = item.editable, end
callback = function() },
UIManager:close(folder_shortcuts_dialog) },
self._manager:editFolderShortcut(item) }
end if self._manager.ui.file_chooser and self._manager.ui.clipboard then
}, table.insert(buttons, {
{ {
text = _("Delete"), text = _("Paste to folder"),
enabled = item.deletable, callback = function()
callback = function() UIManager:close(dialog)
UIManager:close(folder_shortcuts_dialog) self._manager.ui:pasteHere(item.folder)
self._manager:deleteFolderShortcut(item) end
end },
}, })
},
}
}
UIManager:show(folder_shortcuts_dialog)
return true
end end
dialog = ButtonDialog:new{
title = item.name .. "\n" .. BD.dirpath(item.folder),
title_align = "center",
buttons = buttons,
}
UIManager:show(dialog)
return true
end end
function FileManagerShortcuts:editFolderShortcut(item) function FileManagerShortcuts:removeShortcut(folder)
local edit_folder_input local index = self:_getIndex(folder)
edit_folder_input = InputDialog:new { table.remove(self.folder_shortcuts, index)
title = _("Edit friendly name"), if self.shortcuts_menu then
input = item.friendly_name, self.fm_updated = true
description = T(_("Rename title for selected folder:\n%1"), BD.dirpath(item.folder)), self:updateItemTable()
buttons = { end
end
function FileManagerShortcuts:editShortcut(folder, post_callback)
local index = self:_getIndex(folder)
local item, name
if index then -- rename
item = self.folder_shortcuts[index]
name = item.text
end
local input_dialog
input_dialog = InputDialog:new {
title = _("Enter folder shortcut name"),
input = name,
description = BD.dirpath(folder),
buttons = {{
{ {
{ text = _("Cancel"),
text = _("Cancel"), id = "close",
id = "close", callback = function()
callback = function() UIManager:close(input_dialog)
UIManager:close(edit_folder_input) end,
end, },
}, {
{ text = _("Save"),
text = _("Apply"), is_enter_default = true,
is_enter_default = true, callback = function()
callback = function() local new_name = input_dialog:getInputText()
self:renameFolderShortcut(item, edit_folder_input:getInputText()) if new_name == "" or new_name == name then return end
UIManager:close(edit_folder_input) UIManager:close(input_dialog)
end, if item then
}, item.text = new_name
} else
}, table.insert(self.folder_shortcuts, {
text = new_name,
folder = folder,
})
if post_callback then
post_callback()
end
end
if self.shortcuts_menu then
self.fm_updated = true
self:updateItemTable()
end
end,
},
}},
} }
UIManager:show(edit_folder_input) UIManager:show(input_dialog)
edit_folder_input:onShowKeyboard() input_dialog:onShowKeyboard()
end end
function FileManagerShortcuts:renameFolderShortcut(item, new_name) function FileManagerShortcuts:addShortcut()
for _, element in ipairs(self.folder_shortcuts) do local PathChooser = require("ui/widget/pathchooser")
if element.text == item.friendly_name and element.folder == item.folder then local path_chooser = PathChooser:new{
element.text = new_name select_directory = true,
end select_file = false,
end path = self.ui.file_chooser and self.ui.file_chooser.path or self.ui:getLastDirFile(),
self:updateItemTable() onConfirm = function(path)
if self:hasFolderShortcut(path) then
UIManager:show(InfoMessage:new{
text = _("Shortcut already exists."),
})
else
self:editShortcut(path)
end
end,
}
UIManager:show(path_chooser)
end end
function FileManagerShortcuts:deleteFolderShortcut(item) function FileManagerShortcuts:genShowFolderShortcutsButton(pre_callback)
for i = #self.folder_shortcuts, 1, -1 do return {
local element = self.folder_shortcuts[i] text = self.title,
if element.text == item.friendly_name and element.folder == item.folder then callback = function()
table.remove(self.folder_shortcuts, i) pre_callback()
end self:onShowFolderShortcutsDialog()
end,
}
end
function FileManagerShortcuts:genAddRemoveShortcutButton(folder, pre_callback, post_callback)
if self:hasFolderShortcut(folder) then
return {
text = _("Remove from folder shortcuts"),
callback = function()
pre_callback()
self:removeShortcut(folder)
post_callback()
end,
}
else
return {
text = _("Add to folder shortcuts"),
callback = function()
pre_callback()
self:editShortcut(folder, post_callback)
end,
}
end end
self:updateItemTable()
end end
function FileManagerShortcuts:onSetDimensions(dimen) function FileManagerShortcuts:onSetDimensions(dimen)
@ -208,7 +219,7 @@ end
function FileManagerShortcuts:MenuSetRotationModeHandler(rotation) function FileManagerShortcuts:MenuSetRotationModeHandler(rotation)
if rotation ~= nil and rotation ~= Screen:getRotationMode() then if rotation ~= nil and rotation ~= Screen:getRotationMode() then
UIManager:close(self._manager.fm_bookmark) UIManager:close(self._manager.shortcuts_menu)
if self._manager.ui.view and self._manager.ui.view.onSetRotationMode then if self._manager.ui.view and self._manager.ui.view.onSetRotationMode then
self._manager.ui.view:onSetRotationMode(rotation) self._manager.ui.view:onSetRotationMode(rotation)
elseif self._manager.ui.onSetRotationMode then elseif self._manager.ui.onSetRotationMode then
@ -222,23 +233,33 @@ function FileManagerShortcuts:MenuSetRotationModeHandler(rotation)
end end
function FileManagerShortcuts:onShowFolderShortcutsDialog(select_callback) function FileManagerShortcuts:onShowFolderShortcutsDialog(select_callback)
self.fm_bookmark = Menu:new{ self.shortcuts_menu = Menu:new{
title = _("Folder shortcuts"), title = self.title,
show_parent = self.ui, show_parent = self.ui,
no_title = false, covers_fullscreen = true,
parent = nil,
is_popout = false,
is_borderless = true, is_borderless = true,
curr_path = self.ui.file_chooser and self.ui.file_chooser.path or self.ui:getLastDirFile(), is_popout = false,
select_callback = select_callback, -- called from PathChooser titlebar left button
title_bar_left_icon = not select_callback and "plus" or nil,
onLeftButtonTap = function() self:addShortcut() end,
onMenuChoice = self.onMenuChoice,
onMenuHold = not select_callback and self.onMenuHold or nil, onMenuHold = not select_callback and self.onMenuHold or nil,
onSetRotationMode = self.MenuSetRotationModeHandler, onSetRotationMode = self.MenuSetRotationModeHandler,
title_bar_left_icon = not select_callback and "plus" or nil,
onLeftButtonTap = function() self:addNewFolder() end,
_manager = self, _manager = self,
} }
self.shortcuts_menu.close_callback = function()
self:updateItemTable(select_callback) UIManager:close(self.shortcuts_menu)
UIManager:show(self.fm_bookmark) if self.fm_updated then
if self.ui.file_chooser then
self.ui.file_chooser:refreshPath()
self.ui:updateTitleBarPath()
end
self.fm_updated = nil
end
self.shortcuts_menu = nil
end
self:updateItemTable()
UIManager:show(self.shortcuts_menu)
end end
return FileManagerShortcuts return FileManagerShortcuts

@ -3,6 +3,7 @@ local datetime = require("datetime")
local Device = require("device") local Device = require("device")
local DocSettings = require("docsettings") local DocSettings = require("docsettings")
local DocumentRegistry = require("document/documentregistry") local DocumentRegistry = require("document/documentregistry")
local FileManagerShortcuts = require("apps/filemanager/filemanagershortcuts")
local filemanagerutil = require("apps/filemanager/filemanagerutil") local filemanagerutil = require("apps/filemanager/filemanagerutil")
local Menu = require("ui/widget/menu") local Menu = require("ui/widget/menu")
local UIManager = require("ui/uimanager") local UIManager = require("ui/uimanager")
@ -362,6 +363,9 @@ function FileChooser:getMenuItemMandatory(item, collate)
if #sub_dirs > 0 then if #sub_dirs > 0 then
text = T("%1 \u{F114} ", #sub_dirs) .. text text = T("%1 \u{F114} ", #sub_dirs) .. text
end end
if FileManagerShortcuts:hasFolderShortcut(item.fullpath) then
text = "" .. text
end
end end
return text return text
end end

Loading…
Cancel
Save