feat(keyboard): ship AI hint carousel, home library cards, and clipboard polish
Rotate AI idle suggestions with optional remote packs, move history/dictionary onto self-sizing Home preview cards, harden clipboard capture/prompting, and simplify keyboard chrome by dropping most liquid-glass shadows.
This commit is contained in:
@@ -31,8 +31,6 @@ public struct SyncedAppSettingsV2: Codable, Equatable, Sendable {
|
||||
public var aiResponseLength: SyncedField<AIResponseLength>
|
||||
public var activePolishStyleId: SyncedField<String>
|
||||
public var llmThinkingEnabled: SyncedField<Bool>
|
||||
public var clipboardHistoryEnabled: SyncedField<Bool>
|
||||
public var clipboardCandidateBarEnabled: SyncedField<Bool>
|
||||
public var flowSkipAppSwitch: SyncedField<Bool>
|
||||
public var flowInactivityDuration: SyncedField<FlowInactivityDuration>
|
||||
|
||||
@@ -90,16 +88,10 @@ public struct SyncedAppSettingsV2: Codable, Equatable, Sendable {
|
||||
)
|
||||
self.activePolishStyleId = activePolishStyleId
|
||||
self.llmThinkingEnabled = llmThinkingEnabled
|
||||
self.clipboardHistoryEnabled = clipboardHistoryEnabled ?? SyncedField(
|
||||
value: false,
|
||||
updatedAt: llmThinkingEnabled.updatedAt,
|
||||
deviceID: llmThinkingEnabled.deviceID
|
||||
)
|
||||
self.clipboardCandidateBarEnabled = clipboardCandidateBarEnabled ?? SyncedField(
|
||||
value: false,
|
||||
updatedAt: llmThinkingEnabled.updatedAt,
|
||||
deviceID: llmThinkingEnabled.deviceID
|
||||
)
|
||||
// Kept as optional parameters so old call sites and payload fixtures
|
||||
// remain source-compatible. Clipboard consent is device-local.
|
||||
_ = clipboardHistoryEnabled
|
||||
_ = clipboardCandidateBarEnabled
|
||||
self.flowSkipAppSwitch = flowSkipAppSwitch
|
||||
self.flowInactivityDuration = flowInactivityDuration
|
||||
}
|
||||
@@ -198,21 +190,13 @@ public struct SyncedAppSettingsV2: Codable, Equatable, Sendable {
|
||||
updatedAt: keyboardHapticIntensity.updatedAt,
|
||||
deviceID: keyboardHapticIntensity.deviceID
|
||||
)
|
||||
clipboardHistoryEnabled = try container.decodeIfPresent(
|
||||
_ = try container.decodeIfPresent(
|
||||
SyncedField<Bool>.self,
|
||||
forKey: .clipboardHistoryEnabled
|
||||
) ?? SyncedField(
|
||||
value: false,
|
||||
updatedAt: keyboardHapticIntensity.updatedAt,
|
||||
deviceID: keyboardHapticIntensity.deviceID
|
||||
)
|
||||
clipboardCandidateBarEnabled = try container.decodeIfPresent(
|
||||
_ = try container.decodeIfPresent(
|
||||
SyncedField<Bool>.self,
|
||||
forKey: .clipboardCandidateBarEnabled
|
||||
) ?? SyncedField(
|
||||
value: false,
|
||||
updatedAt: keyboardHapticIntensity.updatedAt,
|
||||
deviceID: keyboardHapticIntensity.deviceID
|
||||
)
|
||||
flowSkipAppSwitch = try container.decode(SyncedField<Bool>.self, forKey: .flowSkipAppSwitch)
|
||||
flowInactivityDuration = try container.decode(
|
||||
@@ -269,12 +253,36 @@ public struct SyncedAppSettingsV2: Codable, Equatable, Sendable {
|
||||
aiResponseLength.updatedAt,
|
||||
activePolishStyleId.updatedAt,
|
||||
llmThinkingEnabled.updatedAt,
|
||||
clipboardHistoryEnabled.updatedAt,
|
||||
clipboardCandidateBarEnabled.updatedAt,
|
||||
flowSkipAppSwitch.updatedAt,
|
||||
flowInactivityDuration.updatedAt,
|
||||
].max() ?? .distantPast
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(schemaVersion, forKey: .schemaVersion)
|
||||
try container.encode(providerId, forKey: .providerId)
|
||||
try container.encode(baseURL, forKey: .baseURL)
|
||||
try container.encode(model, forKey: .model)
|
||||
try container.encode(asrProviderId, forKey: .asrProviderId)
|
||||
try container.encode(asrBaseURL, forKey: .asrBaseURL)
|
||||
try container.encode(asrModel, forKey: .asrModel)
|
||||
try container.encode(modeId, forKey: .modeId)
|
||||
try container.encode(localeId, forKey: .localeId)
|
||||
try container.encode(engineMode, forKey: .engineMode)
|
||||
try container.encode(hasAcknowledgedCloudSharing, forKey: .hasAcknowledgedCloudSharing)
|
||||
try container.encode(uiLanguage, forKey: .uiLanguage)
|
||||
try container.encode(translationTargetLocaleId, forKey: .translationTargetLocaleId)
|
||||
try container.encode(handednessPreference, forKey: .handednessPreference)
|
||||
try container.encode(cursorDragNavigationEnabled, forKey: .cursorDragNavigationEnabled)
|
||||
try container.encode(keyboardHapticIntensity, forKey: .keyboardHapticIntensity)
|
||||
try container.encode(polishIntensity, forKey: .polishIntensity)
|
||||
try container.encode(aiResponseLength, forKey: .aiResponseLength)
|
||||
try container.encode(activePolishStyleId, forKey: .activePolishStyleId)
|
||||
try container.encode(llmThinkingEnabled, forKey: .llmThinkingEnabled)
|
||||
try container.encode(flowSkipAppSwitch, forKey: .flowSkipAppSwitch)
|
||||
try container.encode(flowInactivityDuration, forKey: .flowInactivityDuration)
|
||||
}
|
||||
}
|
||||
|
||||
public extension SyncedAppSettingsV2 {
|
||||
@@ -311,8 +319,6 @@ public extension SyncedAppSettingsV2 {
|
||||
aiResponseLength: field(configuration.aiResponseLength),
|
||||
activePolishStyleId: field(configuration.activePolishStyleId),
|
||||
llmThinkingEnabled: field(configuration.llmThinkingEnabled),
|
||||
clipboardHistoryEnabled: field(configuration.clipboardHistoryEnabled),
|
||||
clipboardCandidateBarEnabled: field(configuration.clipboardCandidateBarEnabled),
|
||||
flowSkipAppSwitch: field(configuration.flowSkipAppSwitch),
|
||||
flowInactivityDuration: field(configuration.flowInactivityDuration)
|
||||
)
|
||||
@@ -345,8 +351,6 @@ public extension SyncedAppSettingsV2 {
|
||||
aiResponseLength: field(AIResponseLength.default),
|
||||
activePolishStyleId: field(PolishStylePackCatalog.defaultID),
|
||||
llmThinkingEnabled: field(false),
|
||||
clipboardHistoryEnabled: field(false),
|
||||
clipboardCandidateBarEnabled: field(false),
|
||||
flowSkipAppSwitch: field(legacy.flowSkipAppSwitch),
|
||||
flowInactivityDuration: field(legacy.flowInactivityDuration)
|
||||
)
|
||||
@@ -394,14 +398,6 @@ public extension SyncedAppSettingsV2 {
|
||||
remote: remote.activePolishStyleId
|
||||
),
|
||||
llmThinkingEnabled: .merge(local: local.llmThinkingEnabled, remote: remote.llmThinkingEnabled),
|
||||
clipboardHistoryEnabled: .merge(
|
||||
local: local.clipboardHistoryEnabled,
|
||||
remote: remote.clipboardHistoryEnabled
|
||||
),
|
||||
clipboardCandidateBarEnabled: .merge(
|
||||
local: local.clipboardCandidateBarEnabled,
|
||||
remote: remote.clipboardCandidateBarEnabled
|
||||
),
|
||||
flowSkipAppSwitch: .merge(local: local.flowSkipAppSwitch, remote: remote.flowSkipAppSwitch),
|
||||
flowInactivityDuration: .merge(
|
||||
local: local.flowInactivityDuration,
|
||||
@@ -430,8 +426,6 @@ public extension SyncedAppSettingsV2 {
|
||||
configuration.aiResponseLength = aiResponseLength.value
|
||||
configuration.activePolishStyleId = activePolishStyleId.value
|
||||
configuration.llmThinkingEnabled = llmThinkingEnabled.value
|
||||
configuration.clipboardHistoryEnabled = clipboardHistoryEnabled.value
|
||||
configuration.clipboardCandidateBarEnabled = clipboardCandidateBarEnabled.value
|
||||
configuration.flowSkipAppSwitch = flowSkipAppSwitch.value
|
||||
configuration.flowInactivityDuration = flowInactivityDuration.value
|
||||
}
|
||||
@@ -462,8 +456,6 @@ public extension SyncedAppSettingsV2 {
|
||||
patch(©.aiResponseLength, value: configuration.aiResponseLength)
|
||||
patch(©.activePolishStyleId, value: configuration.activePolishStyleId)
|
||||
patch(©.llmThinkingEnabled, value: configuration.llmThinkingEnabled)
|
||||
patch(©.clipboardHistoryEnabled, value: configuration.clipboardHistoryEnabled)
|
||||
patch(©.clipboardCandidateBarEnabled, value: configuration.clipboardCandidateBarEnabled)
|
||||
patch(©.flowSkipAppSwitch, value: configuration.flowSkipAppSwitch)
|
||||
patch(©.flowInactivityDuration, value: configuration.flowInactivityDuration)
|
||||
return copy
|
||||
@@ -497,8 +489,6 @@ public extension SyncedAppSettingsV2 {
|
||||
touch(©.aiResponseLength, value: configuration.aiResponseLength)
|
||||
touch(©.activePolishStyleId, value: configuration.activePolishStyleId)
|
||||
touch(©.llmThinkingEnabled, value: configuration.llmThinkingEnabled)
|
||||
touch(©.clipboardHistoryEnabled, value: configuration.clipboardHistoryEnabled)
|
||||
touch(©.clipboardCandidateBarEnabled, value: configuration.clipboardCandidateBarEnabled)
|
||||
touch(©.flowSkipAppSwitch, value: configuration.flowSkipAppSwitch)
|
||||
touch(©.flowInactivityDuration, value: configuration.flowInactivityDuration)
|
||||
return copy
|
||||
|
||||
Reference in New Issue
Block a user