@@ -34,6 +34,7 @@ local cloneParams = CatalogUtil.cloneParams
local CatalogLists = { }
CatalogLists.CAPABILITY = " catalogListsV2 "
CatalogLists.PUBLISHED_SORT_CAPABILITY = " catalogPublishedSort "
local DUMP_DIR = os.getenv ( " BO_LIST_DUMP " )
local SECTION_PAGED = { authors = true , series = true }
@@ -508,8 +509,32 @@ end
-- ----------------------------------------------------------------- sheets
local SORT_IDS = { " title " , " author " , " series " , " recently_added " , " recently_read " }
local SERIES_SORTS = {
{ id = " series " , label = _ ( " Series order " ) } ,
{ id = " published " , label = _ ( " Publication date " ) , capability = CatalogLists.PUBLISHED_SORT_CAPABILITY } ,
{ id = " title " , label = _ ( " Title " ) } ,
{ id = " recently_read " , label = _ ( " Last read " ) } ,
{ id = " recently_added " , label = _ ( " Added to library " ) } ,
}
local SHOW_IDS = { false , " unread " , " reading " , " finished " }
local function seriesSorts ( self )
local known = Capabilities.cached ( self.client ) or { }
local sorts = { }
for _i , sort in ipairs ( SERIES_SORTS ) do
if not sort.capability or known [ sort.capability ] == true then table.insert ( sorts , sort ) end
end
return sorts
end
local function seriesOrder ( sort )
if sort == " series " then return { _ ( " First to last " ) , _ ( " Last to first " ) } , " asc " end
if sort == " published " then return { _ ( " Oldest " ) , _ ( " Newest " ) } , " asc " end
if sort == " title " then return { _ ( " A– Z " ) , _ ( " Z– A " ) } , " asc " end
if sort == " recently_read " then return { _ ( " Recent first " ) , _ ( " Oldest first " ) } , " desc " end
return { _ ( " Newest " ) , _ ( " Oldest " ) } , " desc "
end
function CatalogLists : listSheetState ( context )
context = context or self.current_context or { }
local sheet = context.list_sheet
@@ -522,15 +547,20 @@ function CatalogLists:listOpenSheet(kind, focus)
local list_kind = self : listKind ( context )
if kind == " sort " then
local staged = { }
if list_kind == " books " or list_kind == " reading " then
if list_kind == " books " or list_kind == " reading " or list_kind == " seriespage " then
local params = context.params or { }
local sort = params.sort or ( list_kind == " seriespage " and " series " or " title " )
if list_kind == " seriespage " and sort == " published " then
local known = Capabilities.cached ( self.client ) or { }
if known [ CatalogLists.PUBLISHED_SORT_CAPABILITY ] ~= true then sort = " series " end
end
staged = {
sort = params.sort or " title " ,
order = self : effectiveOrder ( params ) ,
sort = sort ,
order = params.order or CatalogUtil.NATURAL_ORDER [ sort ] or " asc " ,
readStatus = params.readStatus ,
libraryId = params.libraryId ,
format = params.format ,
on_device = context.on_device_filter == true ,
libraryId = list_kind ~= " seriespage " and params.libraryId or nil ,
format = list_kind ~= " seriespage " and params.format or nil ,
on_device = list_kind ~= " seriespage " and context.on_device_filter == true ,
}
else
staged = { sort = context.sort or " name " , filter = context.filter }
@@ -595,6 +625,16 @@ function CatalogLists:listApplySheet()
end )
return
end
if kind == " seriespage " then
local params = cloneParams ( context.params or { } )
params.sort = s.sort
params.order = s.order ~= ( CatalogUtil.NATURAL_ORDER [ s.sort ] or " asc " ) and s.order or nil
params.readStatus = s.readStatus or nil
params.page = 1
params.size = nil
self : runConnected ( function ( ) self : fetchBookPage ( params , context.title , false ) end )
return
end
if kind == " authors " or kind == " series " then
self : reloadSection ( context.section , { page = 1 , sort = s.sort , filter = s.filter or false } )
end
@@ -606,6 +646,8 @@ function CatalogLists:listResetSheet()
local kind = self : listKind ( )
if kind == " books " or kind == " reading " then
sheet.staged = { sort = " title " , order = " asc " , on_device = false }
elseif kind == " seriespage " then
sheet.staged = { sort = " series " , order = " asc " }
else
sheet.staged = { sort = " name " }
end
@@ -617,6 +659,25 @@ end
function CatalogLists : listSortSheetModel ( sheet )
local s = sheet.staged
local kind = self : listKind ( )
if kind == " seriespage " then
local sorts = seriesSorts ( self )
local labels , sort_index = { } , 1
for i , sort in ipairs ( sorts ) do
labels [ i ] = sort.label
if sort.id == s.sort then sort_index = i end
end
local order_labels , first_order = seriesOrder ( s.sort )
local show_index = 1
for i , id in ipairs ( SHOW_IDS ) do if ( id or nil ) == s.readStatus then show_index = i end end
return {
title = _ ( " Sort and filter " ) ,
sorts = { labels = labels , selected = sort_index } ,
order = { labels = order_labels , selected = ( s.order or first_order ) == first_order and 1 or 2 } ,
shows = { labels = { _ ( " All " ) , _ ( " Unread " ) , _ ( " Reading " ) , _ ( " Finished " ) } , selected = show_index } ,
rows = { } ,
note = _ ( " Saved for this list " ) ,
}
end
if kind == " books " or kind == " reading " then
local sort_index = 1
for i , id in ipairs ( SORT_IDS ) do if id == s.sort then sort_index = i end end
@@ -705,6 +766,10 @@ function CatalogLists:listRun(action, region, hold)
if lk == " books " or lk == " reading " then
sheet.staged . sort = SORT_IDS [ action.index ] or " title "
sheet.staged . order = CatalogUtil.NATURAL_ORDER [ sheet.staged . sort ] or " asc "
elseif lk == " seriespage " then
local sort = seriesSorts ( self ) [ action.index ] or seriesSorts ( self ) [ 1 ]
sheet.staged . sort = sort and sort.id or " series "
sheet.staged . order = CatalogUtil.NATURAL_ORDER [ sheet.staged . sort ] or " asc "
else
sheet.staged . sort = action.index == 2 and " books " or " name "
end
@@ -715,13 +780,16 @@ function CatalogLists:listRun(action, region, hold)
local time_sort = CatalogUtil.SORT_KIND [ sheet.staged . sort ] == " time "
local first = time_sort and " desc " or " asc "
sheet.staged . order = action.index == 1 and first or ( first == " asc " and " desc " or " asc " )
elseif lk == " seriespage " then
local _labels , first = seriesOrder ( sheet.staged . sort )
sheet.staged . order = action.index == 1 and first or ( first == " asc " and " desc " or " asc " )
else
sheet.staged . sort = action.index == 2 and " name_desc " or " name "
end
return self : updateItems ( nil , true )
elseif kind == " sheet-show " and sheet then
local lk = self : listKind ( )
if lk == " books " or lk == " reading " then
if lk == " books " or lk == " reading " or lk == " seriespage " then
sheet.staged . readStatus = SHOW_IDS [ action.index ] or nil
else
sheet.staged . filter = action.index == 2 and " reading " or action.index == 3 and " finished " or nil
@@ -1027,17 +1095,19 @@ end
local SORT_SHORT = {
title = _ ( " Title A– Z " ) , author = _ ( " Author A– Z " ) , series = _ ( " Series order " ) , recently_added = _ ( " Recently added " ) ,
recently_updated = _ ( " Recently updated " ) , recently_read = _ ( " Last read " ) ,
published = _ ( " Publication date " ) , recently_updated = _ ( " Recently updated " ) , recently_read = _ ( " Last read " ) ,
}
function CatalogLists : listSortLabel ( params )
local sort = params.sort or " title "
local order = self : effectiveOrder ( params )
local order = params.order or CatalogUtil.NATURAL_ORDER [ sort ] or " asc "
local label = SORT_SHORT [ sort ] or _ ( " Title A– Z " )
if CatalogUtil.SORT_KIND [ sort ] == " alpha " and order == " desc " then
label = sort == " title " and _ ( " Title Z– A " ) or sort == " author " and _ ( " Author Z– A " ) or label
label = sort == " title " and _ ( " Title Z– A " ) or sort == " author " and _ ( " Author Z– A " ) or sort == " series " and _ ( " Reverse series order " ) or label
elseif CatalogUtil.SORT_KIND [ sort ] == " time " and order == " asc " then
label = label .. " " .. _ ( " (oldest) " )
label = sort == " published " and _ ( " Publication date (oldest) " ) or label .. " " .. _ ( " (oldest) " )
elseif sort == " published " then
label = _ ( " Publication date (newest) " )
end
return label
end
@@ -1060,6 +1130,15 @@ function CatalogLists:listToolbar(kind, context)
{ icon = " library " , label = lib_label , on = params.libraryId ~= nil , action = { kind = " sort-sheet " , focus = " library " } , key = " tb-library " } ,
}
end
if kind == " seriespage " then
if not self : listsSupported ( ) then return { } end
local show = params.readStatus
local show_label = show == " unread " and _ ( " Unread " ) or show == " reading " and _ ( " Reading " ) or show == " finished " and _ ( " Finished " ) or _ ( " All books " )
return {
{ icon = " arrow-up-down " , label = self : listSortLabel ( params ) , action = { kind = " sort-sheet " , focus = " sort " } , key = " tb-sort " } ,
{ icon = " list-filter " , label = show_label , on = show ~= nil , action = { kind = " sort-sheet " , focus = " show " } , key = " tb-show " } ,
}
end
if not self : listsSupported ( ) then return { } end
local sort = context.sort or " name "
local sort_label = sort == " books " and _ ( " Most books " ) or sort == " name_desc " and _ ( " Name Z– A " ) or _ ( " Name A– Z " )
@@ -1212,7 +1291,8 @@ function CatalogLists:listBody(kind, context)
if not next_book then for i , b in ipairs ( books ) do if states [ i ] ~= " finished " then next_book , cur = b , i ; break end end end
local finished , reading = 0 , 0
for _i , s in ipairs ( states ) do if s == " finished " then finished = finished + 1 elseif s == " reading " then reading = reading + 1 end end
local layout = ListPages.seriesLayout ( sw , sh , self : listView ( kind ) , # books , context.list_offline = = true )
local toolbar = context.list_offline ~ = true
local layout = ListPages.seriesLayout ( sw , sh , self : listView ( kind ) , # books , context.list_offline == true , toolbar )
context.local_pages = layout.pages
context.local_page = math.min ( context.local_page or 1 , layout.pages )
local lp = context.local_page
@@ -1220,10 +1300,10 @@ function CatalogLists:listBody(kind, context)
local last = math.min ( # books , lp == 1 and layout.first or ( first + layout.rest - 1 ) )
local m = {
entries = books , view = self : listView ( kind ) , screen_w = sw , screen_h = sh , local_page = context.local_page ,
offline = context.list_offline and { } or nil ,
offline = context.list_offline and { } or nil , toolbar = toolbar ,
select = self : isBulkSelectionActive ( ) ,
selected = function ( b ) return self.bulk_select_all or self : bulkIsBookSelected ( b ) end ,
order_label = ( context.params or { } ) . sort == " title " and _ ( " Title A– Z " ) or _ ( " Reading order " ) ,
order_label = self : listSortLabel ( context.params or { } ) ,
states = states , indexes = indexes , current_index = cur , next_book = next_book ,
range = # books > 0 and T ( _ ( " Books %1 – %2 " ) , first , last ) or nil ,
next_minutes = next_book and self : listMinutesLeft ( next_book ) ,
@@ -1289,7 +1369,8 @@ function CatalogLists:updateListPage(select_number, no_recalculate_dimen)
local body , m = self : listBody ( kind , context )
-- Offline the band stands in for the toolbar: sorting, filtering and the
-- view all need the server.
local has_toolbar = ( kind == " books " or kind == " reading " or kind == " authors " or kind == " series " ) and not context.list_offline
local has_toolbar = ( kind == " books " or kind == " reading " or kind == " authors " or kind == " series " or kind == " seriespage " )
and not context.list_offline
local toolbar = nil
if has_toolbar then
local buttons = self : listToolbar ( kind , context )