mirror of
https://github.com/yattee/yattee.git
synced 2026-10-27 15:07:18 +00:00
Let a refused host count as unreachable and the switcher own every login
Residual round after the macOS fix verification, five closures:
A connection refusal or a failed DNS lookup arrived as APIError.unknown,
which no classifier reads — so an account pointed at a downed instance
never went unreachable, never fell back to local data, never armed a
retry. New APIError.connectionFailed carries the system's own sentence
and lands as unreachable/offline in AccountsManager, InstancesManager
and the credential probe; a refused host now classifies in seconds
instead of never.
Subscriptions' periodic retry armed only for networkError, while the
local fallback's yatteeServerRequired — shown exactly when the account's
server could not be reached — waited on a status expiry nothing was
watching. FeedLoadState.warrantsPeriodicRetry gates on the context's
unavailability, so that screen heals on its own too, and an account that
genuinely has no Yattee Server still never loops.
The switcher dropped every context of a switched-off source, leaving the
toolbar badge pointing at a menu its own selection had vanished from.
listedContexts keeps the rows with their status in the title ("— Source
switched off"), isSwitchable refuses the pick, and the current context
keeps its checkmark.
The sidebar footer's switcher row overflowed the 140 pt column minimum:
the width floor now sits on the menu itself and ViewThatFits drops the
caption — the part the icon already says — before the account name loses
characters.
The channel menu exposed a raw SF Symbol name as its accessibility
title; the label is now a real Label rendered iconOnly, so the AX bridge
hears "Subscription Options".
This commit is contained in:
@@ -100,9 +100,10 @@ final class DataContextValidator {
|
||||
}
|
||||
|
||||
// The account's own status says nothing about the instance being
|
||||
// switched off, and `availableContexts` already hides disabled
|
||||
// instances — a context that stayed valid here would keep sending
|
||||
// requests to a server the user has turned off.
|
||||
// switched off, and the switcher only *lists* a disabled source's
|
||||
// contexts — it refuses to switch to them — so a context that
|
||||
// stayed valid here would keep sending requests to a server the
|
||||
// user has turned off.
|
||||
guard instance.isEnabled else {
|
||||
return .temporarilyUnavailable(.instanceDisabled)
|
||||
}
|
||||
@@ -145,17 +146,62 @@ final class DataContextValidator {
|
||||
|
||||
// MARK: - Available contexts
|
||||
|
||||
/// Every context the switcher *lists*, usable or not.
|
||||
///
|
||||
/// A source the user switched off does not make its logins disappear. The
|
||||
/// switcher listing only what can be switched to meant the badge on the
|
||||
/// toolbar icon pointed at a menu the account had dropped out of — the
|
||||
/// selected account included, so the one control that explains the badge
|
||||
/// stopped naming the thing it was badging for. The rows stay, carrying
|
||||
/// their status, and `isSwitchable(_:)` decides which of them can be picked.
|
||||
///
|
||||
/// The selection is the row that may never be missing, so it is appended
|
||||
/// even when it is no longer among the selectable accounts — as long as the
|
||||
/// account still exists. A context whose account is gone is not listed:
|
||||
/// there is nothing to name it with, and correction handles deletions.
|
||||
var listedContexts: [DataContext] {
|
||||
var contexts: [DataContext] = [.local]
|
||||
contexts += accountsManager.selectableAccounts.map { DataContext.account($0.id) }
|
||||
|
||||
let current = accountsManager.currentContext
|
||||
if case let .account(id) = current,
|
||||
accountsManager.account(id: id) != nil,
|
||||
!contexts.contains(current) {
|
||||
contexts.append(current)
|
||||
}
|
||||
|
||||
return contexts
|
||||
}
|
||||
|
||||
/// Every context the user can switch to.
|
||||
///
|
||||
/// Includes accounts that are currently signed out: hiding them would make
|
||||
/// a temporarily unreachable account look deleted, and the switcher is
|
||||
/// where the user goes to fix exactly that.
|
||||
/// where the user goes to fix exactly that. A disabled source is the one
|
||||
/// exception — nothing may be read from or written to a server the user has
|
||||
/// turned off — and it is expressed by refusing the switch, not by hiding
|
||||
/// the row.
|
||||
var availableContexts: [DataContext] {
|
||||
let accountContexts = accountsManager.selectableAccounts
|
||||
.filter { accountsManager.instance(for: $0)?.isEnabled ?? false }
|
||||
.map { DataContext.account($0.id) }
|
||||
listedContexts.filter { isSwitchable($0) }
|
||||
}
|
||||
|
||||
return [.local] + accountContexts
|
||||
/// Whether picking this context would land the user somewhere usable.
|
||||
///
|
||||
/// Not the same question as `validity(of:)`: a rejected or unreachable
|
||||
/// account is still a perfectly good thing to switch *to* — that is where
|
||||
/// the user goes to fix it — while a login on a switched-off source is not.
|
||||
func isSwitchable(_ context: DataContext) -> Bool {
|
||||
switch context {
|
||||
case .local:
|
||||
return true
|
||||
|
||||
case let .account(id):
|
||||
guard accountsManager.selectableAccounts.contains(where: { $0.id == id }),
|
||||
let account = accountsManager.account(id: id) else {
|
||||
return false
|
||||
}
|
||||
return accountsManager.instance(for: account)?.isEnabled ?? false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Correction
|
||||
|
||||
Reference in New Issue
Block a user