mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-07 01:21:37 +00:00
The API wrappers existed but iOS had no UI for these actions, while web and Android did. The session row's context menu and the chat's … menu now offer Rename for every session. Active sessions keep Archive. Inactive sessions get Reopen and a confirmed Delete instead of Archive, which the hub rejects with 409 for them. The store applies renames and deletes optimistically. A failed rename refetches server state; a failed delete restores the row and the cached detail. Reopen marks the returned session active right away. When reopen returns a superseding id, the chat seeds the new window, moves the draft and navigates to it, as send-resume already does. A reopen from the list also moves the draft and opens the session. A 422 shows the hub's message with the missing fields. On iPhone, an authoritative removal (delete, or archive elsewhere) now pops that chat, matching the iPad split, which already clears the selection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
2.9 KiB
Swift
68 lines
2.9 KiB
Swift
import Foundation
|
|
|
|
/// Display-point localization for user-facing strings emitted by HapiKit
|
|
/// (the package layer stays language-free, A-M5): a known package-produced
|
|
/// notice maps to its `Localizable.xcstrings` entry, everything else
|
|
/// (server-originated errors, dynamic content) passes through verbatim.
|
|
///
|
|
/// Covered sources: `ChatInteractor` notices, `DictationController` errors,
|
|
/// `MessageWindowController` tail-sync warnings, and the files models'
|
|
/// fallback errors. Low-value/debug package strings are deliberately not
|
|
/// mapped.
|
|
enum LocalizedNoticeMapper {
|
|
static func map(_ message: String) -> String {
|
|
guard knownMessages.contains(message) else { return message }
|
|
return String(localized: String.LocalizationValue(message))
|
|
}
|
|
|
|
/// Exact strings the package can emit — each is a key in
|
|
/// `Localizable.xcstrings` (hand-authored; runtime-built keys are not
|
|
/// extracted by the compiler).
|
|
private static let knownMessages: Set<String> = [
|
|
// ChatInteractor
|
|
"Attachments are still uploading — wait, or retry/remove the failed ones",
|
|
"Failed to abort",
|
|
"Session is inactive and could not be resumed",
|
|
"Failed to cancel queued message",
|
|
"Message cancelled — kept your current draft",
|
|
"Already delivered to the agent",
|
|
"Failed to steer message",
|
|
"Request was already handled",
|
|
"Request failed",
|
|
"Failed to load models",
|
|
"Failed to update session",
|
|
"Failed to rename session",
|
|
"Failed to delete session",
|
|
"Active sessions can't be deleted — archive first",
|
|
"Failed to reopen session",
|
|
"Draft parked to scratchlist",
|
|
"Scratchlist is full (200 entries)",
|
|
"Couldn't park the draft — check the hub connection",
|
|
"Drafts can contain at most 10,000 characters — shorten the text before saving",
|
|
"Couldn't prepare the attachments — retry or remove the failed files",
|
|
"The attachments exceed the scratchlist limits — remove a file or choose a smaller one",
|
|
"Your input changed — review it and try again",
|
|
"Couldn't queue the draft — retry",
|
|
"Draft added to the send queue",
|
|
"Already queued — couldn't remove the draft. Retry removal only.",
|
|
// DictationController
|
|
"Could not start recording",
|
|
"Could not reach the hub",
|
|
"Audio recording failed",
|
|
"No audio was recorded",
|
|
"Transcription failed",
|
|
// NewSessionLogic
|
|
"Name needs at least one letter or digit",
|
|
"Path is outside workspace roots",
|
|
// MessageWindowController (degraded-sync banner)
|
|
"Failed to synchronize messages",
|
|
"Failed to load older messages",
|
|
// FilesModel / FileViewerModel fallbacks
|
|
"Git status unavailable",
|
|
"Failed to list directory",
|
|
"Failed to search files",
|
|
"Failed to read file",
|
|
"Failed to load diff",
|
|
]
|
|
}
|