feat(app,android,ios): status, season dropdown, watched ticks

A title page now says where the show stands as a chip beside the
quality marks: Airing with the day the next episode comes out, Finished,
Upcoming, On hiatus or Cancelled. The words come from
TitleDetails::status_label, which the bridge hands the phones as
TitleRecord.status; the airing note leaves the line of facts.

A show with more than five seasons picks its season from a drop-down
rather than a row of pills that ran off the page, and a watched
episode's still carries a tick in its corner as well as the mark at the
end of its row.
This commit is contained in:
nvrl committed 2026-10-30 21:34:47 +01:00
1 parent c026f81283
commit cd9e8eea81
11 files changed
+452 -59

No files matched your search

+32
View File
@@ -299,3 +299,35 @@ final class ThemeTests: XCTestCase {
XCTAssertEqual(formatRuntime(124), "2 h 4 min")
}
}
final class StatusTextTests: XCTestCase {
private func title(status: String?, airing: Bool = false, next: (UInt32, Int64)? = nil) -> TitleRecord {
TitleRecord(
key: "k", name: "k", year: nil, kind: .series, watchedCount: 0,
episodeCount: 0, canonicalName: nil, originalName: nil, overview: nil,
metadataProvider: nil, metadataId: nil, metadataYear: nil, metadataKind: nil, posterUrl: nil,
backdropUrl: nil, rating: nil, genres: [], providerEpisodeCount: nil, externalUrl: nil,
manualMatch: false, seasons: [],
displayName: "k", wideUrl: nil, formatLabel: nil, seasonLabel: nil, studios: [],
directors: [], tags: [], airing: airing, nextEpisode: next?.0, nextAiringAt: next?.1,
franchise: [], continueIndex: nil, status: status
)
}
func testTheStatusChipNamesTheNextEpisodeWhileOneIsDue() throws {
let status = try XCTUnwrap(statusText(title(status: "Airing", airing: true, next: (8, 1_800_000_000))))
XCTAssertTrue(status.text.hasPrefix("Airing · episode 8 "), status.text)
XCTAssertTrue(status.live)
}
func testAFinishedTitleIsSaidPlainlyAndIsNotLive() throws {
let status = try XCTUnwrap(statusText(title(status: "Finished")))
XCTAssertEqual(status.text, "Finished")
XCTAssertFalse(status.live)
}
func testATitleWithNoStatusAndNothingAiringHasNoChip() {
XCTAssertNil(statusText(title(status: nil)))
XCTAssertEqual(statusText(title(status: nil, airing: true))?.text, "Airing")
}
}