diff --git a/src/library.cr b/src/library.cr index a5639c0..335a3e2 100644 --- a/src/library.cr +++ b/src/library.cr @@ -477,4 +477,54 @@ class Library end @logger.debug "Scan completed" end + + def get_continue_reading_entries(username) + # map: get the continue-reading entry or nil for each Title + # select: select only entries (and ignore Nil's) from the array + # produced by map + continue_reading_entries = titles.map { |t| + get_continue_reading_entry username, t + }.select Entry + + continue_reading = continue_reading_entries.map_with_index { |e, i| + { + entry: e, + percentage: e.book.load_percentage(username, e.title), + last_read: get_relevant_last_read(username, e) + } + } + + # Sort by by last_read, most recent first (nils at the end) + continue_reading.sort! do |a, b| + next 0 if a[:last_read].nil? && b[:last_read].nil? + next 1 if a[:last_read].nil? + next -1 if b[:last_read].nil? + b[:last_read].not_nil! <=> a[:last_read].not_nil! + end + end + + + private def get_continue_reading_entry(username, title) + in_progress_entries = title.entries.select do |e| + title.load_progress(username, e.title) > 0 + end + return nil if in_progress_entries.empty? + + latest_read_entry = in_progress_entries[-1] + if title.load_progress(username, latest_read_entry.title) == + latest_read_entry.pages + title.next_entry latest_read_entry + else + latest_read_entry + end + end + + private def get_relevant_last_read(username, entry_obj) + last_read = entry_obj.book.load_last_read username, entry_obj.title + if last_read.nil? # grab from previous entry if current entry hasn't been started yet + previous_entry = entry_obj.book.previous_entry(entry_obj) + return entry_obj.book.load_last_read username, previous_entry.title if previous_entry + end + last_read + end end diff --git a/src/routes/main.cr b/src/routes/main.cr index ed9df4d..c2f3f1f 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -65,51 +65,8 @@ class MainRouter < Router get "/" do |env| begin - titles = @context.library.titles username = get_username env - - # map: get the on-deck entry or nil for each Title - # select: select only entries (and ignore Nil's) from the array - # produced by map - continue_reading_entries = titles.map { |t| - t.get_continue_reading_entry username - }.select Entry - - percentage = continue_reading_entries.map { |e| - e.book.load_percentage username, e.title - } - - last_read = continue_reading_entries.map { |e| - e.book.get_last_read_for_continue_reading username, e - } - - # Group values in a NamedTuple for easier sorting - cr_entries = continue_reading_entries.map_with_index { |e, i| - { - entry: e, - percentage: percentage[i], - # if you're ok with the NamedTuple approach we could remove the - # percentage and last_read vars above and just call the methods - # here eg. - # perecentage: e.book.load_percentage username, e.title - last_read: last_read[i] - } - } - # I couldn't get the sort to work where last_read type is `Time | Nil` - # so I'm creating a new variable with just the entries that have last_read - # even still, I have to do another workaround within the sort below :/ - cr_entries_not_nil = cr_entries.select { |e| e[:last_read] } - cr_entries_not_nil.sort! { |a, b| - # 'if' ensures values aren't nil otherwise the compiler errors - # because it still thinks the NamedTuple `last_read` can be nil - # even though we only 'select'ed the objects which have last_read - # there's probably a better way to do this - if (a_time = a[:last_read]) && (b_time = b[:last_read]) - b_time <=> a_time - end - } - # add `last_read == nil` entries AFTER sorted entries - continue_reading = cr_entries_not_nil + cr_entries.select { |e| e[:last_read].nil? } + continue_reading = @context.library.get_continue_reading_entries username layout "home" rescue e diff --git a/src/views/home.ecr b/src/views/home.ecr index e610440..bbd8541 100644 --- a/src/views/home.ecr +++ b/src/views/home.ecr @@ -1,4 +1,4 @@ -<%- unless continue_reading_entries.empty? -%> +<%- unless continue_reading.empty? -%>