Files
openclaw-openclaw/apps/ios/Sources/Design/SessionGroupStore.swift
Peter Steinberger 4c97aa1311 feat(mobile): rename, delete, and create session groups on iOS and Android (#101234)
* feat(mobile): rename, delete, and create sidebar session groups on iOS and Android

Group section headers on the iOS Command Center sessions screen and the
Android sessions screen gain Rename/New/Delete group actions. Bulk ops
enumerate every member (active + archived, explicit high list limit since
the gateway caps an absent limit at 100 rows) and patch category per
session; delete keeps sessions and moves them to Ungrouped. Known custom
groups persist client-side (iOS UserDefaults, Android SharedPreferences)
so empty groups stay visible as move targets.

* chore(i18n): refresh native string inventory after rebase onto main
2026-07-07 01:09:57 +01:00

46 lines
1.8 KiB
Swift

import Foundation
/// Persists custom session group names so a group without members survives
/// refreshes and stays usable as a move target. Mirrors the web sidebar's
/// localStorage-backed list; assigned groups still persist server-side via
/// the session category field.
enum SessionGroupStore {
static let defaultsKey = "openclaw:sessions:custom-groups"
static func load(defaults: UserDefaults = .standard) -> [String] {
self.normalized(defaults.stringArray(forKey: self.defaultsKey) ?? [])
}
static func save(_ groups: [String], defaults: UserDefaults = .standard) {
defaults.set(self.normalized(groups), forKey: self.defaultsKey)
}
static func remember(_ name: String, defaults: UserDefaults = .standard) {
self.save(self.adding(self.load(defaults: defaults), name), defaults: defaults)
}
static func normalized(_ groups: [String]) -> [String] {
var seen = Set<String>()
return groups
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty && seen.insert($0).inserted }
}
static func adding(_ groups: [String], _ name: String) -> [String] {
self.normalized(groups + [name])
}
/// Web parity: replace the old name in place when stored; otherwise append
/// the new name so renaming a live-only group still persists it.
static func renaming(_ groups: [String], from oldName: String, to newName: String) -> [String] {
let renamed = groups.contains(oldName)
? groups.map { $0 == oldName ? newName : $0 }
: groups + [newName]
return self.normalized(renamed)
}
static func removing(_ groups: [String], _ name: String) -> [String] {
self.normalized(groups.filter { $0 != name })
}
}