mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-03 16:41:26 +01:00
feat(core,app,android,ios): look at shares again on their own, and say when they were last looked at
No client crawled a share unless someone pressed Refresh, so a new
episode stayed out of the library until then, and nothing said how stale
the library was.
Catalog schema v11 adds share_crawls: when each share's last crawl
finished and was attempted, how many files it stored and how many were
new, and why the last attempt failed. A failure keeps the last good
crawl's numbers.
Every client now crawls, quietly, any share not looked at for six hours:
the desktop at launch and every half hour while open, the phones at
launch and on their existing catch-up timer. A quiet crawl says only
news ("anime: 3 new files") and leaves failures on the share's row
rather than in a toast.
Share rows on all three show "120 files - crawled 2 h ago", or the last
failure until a crawl succeeds.
This commit is contained in:
1 parent
a306d02cf1
commit
5807493a4a
13 files changed
+552
-75
No files matched your search
@@ -242,7 +242,9 @@ final class AppModel {
|
||||
}
|
||||
}
|
||||
await reloadNow()
|
||||
if !failed.isEmpty {
|
||||
// A catch-up is the app's doing, not the viewer's: a failure goes on
|
||||
// the share's row rather than in their face, and only news is said.
|
||||
if !failed.isEmpty, announce {
|
||||
message = failed.joined(separator: "\n")
|
||||
return
|
||||
}
|
||||
@@ -250,6 +252,9 @@ final class AppModel {
|
||||
if announce {
|
||||
let added = Set(titles.map(\.key)).subtracting(before).count
|
||||
message = added == 1 ? "1 title added" : "\(added) titles added"
|
||||
} else {
|
||||
let files = shares.filter { ids.contains($0.id) }.reduce(UInt64(0)) { $0 + ($1.crawlAdded ?? 0) }
|
||||
if files > 0 { message = files == 1 ? "1 new file" : "\(files) new files" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,9 +435,10 @@ final class AppModel {
|
||||
}
|
||||
}
|
||||
|
||||
/// On launch and back on screen: crawl shares the catalog has nothing of —
|
||||
/// brought by a sync that ran in the background, or an add whose crawl
|
||||
/// never finished.
|
||||
/// On launch and back on screen: crawl shares due a look — ones the
|
||||
/// catalog has nothing of, brought by a sync that ran in the background or
|
||||
/// an add whose crawl never finished, and ones not crawled for six hours,
|
||||
/// so new episodes turn up without a pull to refresh.
|
||||
func enteredForeground() {
|
||||
guard !catchingUp else { return }
|
||||
catchingUp = true
|
||||
|
||||
@@ -97,6 +97,25 @@ struct SharesView: View {
|
||||
extension ShareRecord: Identifiable {}
|
||||
|
||||
/// One share: its name, how it is unlocked, and its actions behind a menu.
|
||||
/// "120 files · crawled 2 h ago", or that it has not been yet.
|
||||
func crawlLine(_ share: ShareRecord, now: Int64 = Int64(Date.now.timeIntervalSince1970)) -> String {
|
||||
guard let at = share.crawledAt else { return "Not crawled yet" }
|
||||
let files = share.crawlFiles.map { $0 == 1 ? "1 file" : "\($0) files" }
|
||||
return [files, "crawled \(ago(at, now: now))"].compactMap { $0 }.joined(separator: " · ")
|
||||
}
|
||||
|
||||
/// "just now", "5 min ago", "3 h ago", "2 days ago" — the desktop's `ui::ago`.
|
||||
func ago(_ at: Int64, now: Int64) -> String {
|
||||
let seconds = max(now - at, 0)
|
||||
switch seconds {
|
||||
case ..<60: return "just now"
|
||||
case ..<3_600: return "\(seconds / 60) min ago"
|
||||
case ..<86_400: return "\(seconds / 3_600) h ago"
|
||||
case ..<172_800: return "1 day ago"
|
||||
default: return "\(seconds / 86_400) days ago"
|
||||
}
|
||||
}
|
||||
|
||||
private struct ShareRow: View {
|
||||
let share: ShareRecord
|
||||
let onRefresh: () -> Void
|
||||
@@ -110,8 +129,14 @@ private struct ShareRow: View {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(share.name).textStyle(.bodyLarge, semibold: true).foregroundStyle(scheme.onSurface)
|
||||
Text(share.fromAccount ? "Folder of your Drive"
|
||||
: share.hasCustomPassword ? "Link and custom password, stored securely" : "Public link")
|
||||
: share.hasCustomPassword ? "Link and custom password" : "Public link")
|
||||
.textStyle(.bodyMedium).foregroundStyle(scheme.onSurfaceVariant)
|
||||
Text(crawlLine(share)).textStyle(.bodySmall).foregroundStyle(scheme.onSurfaceVariant)
|
||||
// Until a crawl succeeds: a link revoked upstream otherwise
|
||||
// just stops growing.
|
||||
if let error = share.crawlError {
|
||||
Text("Last crawl failed: \(error)").textStyle(.bodySmall).foregroundStyle(scheme.error).lineLimit(2)
|
||||
}
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
Menu {
|
||||
|
||||
Reference in new issue
Block a user