feat(ios): surface gateway talk defaults and refresh icon assets (#22530)
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: 54f3a40e22
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Co-authored-by: ngutman <1540134+ngutman@users.noreply.github.com>
Reviewed-by: @ngutman
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/100.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/102.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/1024.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/108.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/114.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/120.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/172.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/180.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/196.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/216.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/234.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/258.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/29.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/40.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/48.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/55.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/57.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/58.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/60.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/66.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/80.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/87.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/88.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/92.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
@@ -1,31 +1 @@
|
||||
{
|
||||
"images" : [
|
||||
{ "filename" : "icon-20@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "20x20" },
|
||||
{ "filename" : "icon-20@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "20x20" },
|
||||
{ "filename" : "icon-20@2x.png", "idiom" : "iphone","scale" : "2x", "size" : "20x20" },
|
||||
{ "filename" : "icon-20@3x.png", "idiom" : "iphone","scale" : "3x", "size" : "20x20" },
|
||||
|
||||
{ "filename" : "icon-29@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "29x29" },
|
||||
{ "filename" : "icon-29@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "29x29" },
|
||||
{ "filename" : "icon-29@2x.png", "idiom" : "iphone","scale" : "2x", "size" : "29x29" },
|
||||
{ "filename" : "icon-29@3x.png", "idiom" : "iphone","scale" : "3x", "size" : "29x29" },
|
||||
|
||||
{ "filename" : "icon-40@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "40x40" },
|
||||
{ "filename" : "icon-40@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "40x40" },
|
||||
{ "filename" : "icon-40@2x.png", "idiom" : "iphone","scale" : "2x", "size" : "40x40" },
|
||||
{ "filename" : "icon-40@3x.png", "idiom" : "iphone","scale" : "3x", "size" : "40x40" },
|
||||
|
||||
{ "filename" : "icon-60@2x.png", "idiom" : "iphone","scale" : "2x", "size" : "60x60" },
|
||||
{ "filename" : "icon-60@3x.png", "idiom" : "iphone","scale" : "3x", "size" : "60x60" },
|
||||
|
||||
{ "filename" : "icon-76@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "76x76" },
|
||||
|
||||
{ "filename" : "icon-83.5@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "83.5x83.5" },
|
||||
|
||||
{ "filename" : "icon-1024.png", "idiom" : "ios-marketing", "scale" : "1x", "size" : "1024x1024" }
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"idiom":"watch","filename":"172.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"86x86","expected-size":"172","role":"quickLook"},{"idiom":"watch","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"40x40","expected-size":"80","role":"appLauncher"},{"idiom":"watch","filename":"88.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"40mm","scale":"2x","size":"44x44","expected-size":"88","role":"appLauncher"},{"idiom":"watch","filename":"102.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"51x51","expected-size":"102","role":"appLauncher"},{"idiom":"watch","filename":"108.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"49mm","scale":"2x","size":"54x54","expected-size":"108","role":"appLauncher"},{"idiom":"watch","filename":"92.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"41mm","scale":"2x","size":"46x46","expected-size":"92","role":"appLauncher"},{"idiom":"watch","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"50x50","expected-size":"100","role":"appLauncher"},{"idiom":"watch","filename":"196.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"98x98","expected-size":"196","role":"quickLook"},{"idiom":"watch","filename":"216.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"108x108","expected-size":"216","role":"quickLook"},{"idiom":"watch","filename":"234.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"117x117","expected-size":"234","role":"quickLook"},{"idiom":"watch","filename":"258.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"49mm","scale":"2x","size":"129x129","expected-size":"258","role":"quickLook"},{"idiom":"watch","filename":"48.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"24x24","expected-size":"48","role":"notificationCenter"},{"idiom":"watch","filename":"55.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"27.5x27.5","expected-size":"55","role":"notificationCenter"},{"idiom":"watch","filename":"66.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"33x33","expected-size":"66","role":"notificationCenter"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"3x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"2x"},{"size":"1024x1024","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch-marketing","scale":"1x"}]}
|
||||
|
Before Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 878 B |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1904,6 +1904,7 @@ private extension NodeAppModel {
|
||||
}
|
||||
GatewayDiagnostics.log(
|
||||
"operator gateway connected host=\(url.host ?? "?") scheme=\(url.scheme ?? "?")")
|
||||
await self.talkMode.reloadConfig()
|
||||
await self.refreshBrandingFromGateway()
|
||||
await self.refreshAgentsFromGateway()
|
||||
await self.refreshShareRouteFromGateway()
|
||||
|
||||
@@ -306,6 +306,26 @@ struct SettingsTab: View {
|
||||
help: "Keeps the screen awake while OpenClaw is open.")
|
||||
|
||||
DisclosureGroup("Advanced") {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("Talk Voice (Gateway)")
|
||||
.font(.footnote.weight(.semibold))
|
||||
.foregroundStyle(.secondary)
|
||||
LabeledContent("Provider", value: "ElevenLabs")
|
||||
LabeledContent(
|
||||
"API Key",
|
||||
value: self.appModel.talkMode.gatewayTalkConfigLoaded
|
||||
? (self.appModel.talkMode.gatewayTalkApiKeyConfigured ? "Configured" : "Not configured")
|
||||
: "Not loaded")
|
||||
LabeledContent(
|
||||
"Default Model",
|
||||
value: self.appModel.talkMode.gatewayTalkDefaultModelId ?? "eleven_v3 (fallback)")
|
||||
LabeledContent(
|
||||
"Default Voice",
|
||||
value: self.appModel.talkMode.gatewayTalkDefaultVoiceId ?? "auto (first available)")
|
||||
Text("Configured on gateway via talk.apiKey, talk.modelId, and talk.voiceId.")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
self.featureToggle(
|
||||
"Voice Directive Hint",
|
||||
isOn: self.$talkVoiceDirectiveHintEnabled,
|
||||
@@ -399,6 +419,9 @@ struct SettingsTab: View {
|
||||
// Keep setup front-and-center when disconnected; keep things compact once connected.
|
||||
self.gatewayExpanded = !self.isGatewayConnected
|
||||
self.selectedAgentPickerId = self.appModel.selectedAgentId ?? ""
|
||||
if self.isGatewayConnected {
|
||||
self.appModel.reloadTalkConfig()
|
||||
}
|
||||
}
|
||||
.onChange(of: self.selectedAgentPickerId) { _, newValue in
|
||||
let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
@@ -24,6 +24,10 @@ final class TalkModeManager: NSObject {
|
||||
var statusText: String = "Off"
|
||||
/// 0..1-ish (not calibrated). Intended for UI feedback only.
|
||||
var micLevel: Double = 0
|
||||
var gatewayTalkConfigLoaded: Bool = false
|
||||
var gatewayTalkApiKeyConfigured: Bool = false
|
||||
var gatewayTalkDefaultModelId: String?
|
||||
var gatewayTalkDefaultVoiceId: String?
|
||||
|
||||
private enum CaptureMode {
|
||||
case idle
|
||||
@@ -1733,6 +1737,10 @@ extension TalkModeManager {
|
||||
} else {
|
||||
self.apiKey = (localApiKey?.isEmpty == false) ? localApiKey : configApiKey
|
||||
}
|
||||
self.gatewayTalkDefaultVoiceId = self.defaultVoiceId
|
||||
self.gatewayTalkDefaultModelId = self.defaultModelId
|
||||
self.gatewayTalkApiKeyConfigured = (self.apiKey?.isEmpty == false)
|
||||
self.gatewayTalkConfigLoaded = true
|
||||
if let interrupt = talk?["interruptOnSpeech"] as? Bool {
|
||||
self.interruptOnSpeech = interrupt
|
||||
}
|
||||
@@ -1741,6 +1749,10 @@ extension TalkModeManager {
|
||||
if !self.modelOverrideActive {
|
||||
self.currentModelId = self.defaultModelId
|
||||
}
|
||||
self.gatewayTalkDefaultVoiceId = nil
|
||||
self.gatewayTalkDefaultModelId = nil
|
||||
self.gatewayTalkApiKeyConfigured = false
|
||||
self.gatewayTalkConfigLoaded = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||