Files
buzz/mobile/ios/NativeControlTests/SettingMenuSelectionTests.swift
klopez4212 a12ad1cdd2 feat(mobile): refine agent profiles and model selection (#8773)
## Summary
- Simplify agent profiles with Message/Bestie actions, relay-authored
published instructions (unavailable without a config channel),
management details, public-key copying, and a separate final Delete
section.
- Sort the Agents directory by name and mark the selected Bestie with a
muted filled star.
- Place Model and Thinking together below Name. Use native iOS Liquid
Glass menus and preserve selection callbacks as controls become enabled.

Related: #8685.

## Validation
Full mobile checks passed. Regression coverage includes relay-author
filtering, unavailable instructions, metadata retry, resizing native
pickers, accurate deletion state, selection after loading, and Bestie
switching. Real iOS simulator taps verified both pickers; the user
confirmed the earlier iPhone build works. Review fixes were checked with
widget journeys and the native UIKit resize/selection probe.

<details>
<summary>Previews</summary>

Synthetic fixture renders:

| Profile | Create agent | Bestie card |
| --- | --- | --- |
| ![Profile with separate Delete
section](https://github.com/user-attachments/assets/4b6e7cf5-b152-43a3-99d9-7c1ee65d0c70)
| ![Model and Thinking
settings](https://github.com/user-attachments/assets/c81dc138-d5d3-43bb-873b-a64171155a7d)
| ![Muted Bestie
star](https://github.com/user-attachments/assets/5ce95e3b-2403-41c5-b6d6-52b8b60cc7d6)
|

Native iOS simulator interaction with a synthetic catalog:

![Both picker values updated after native menu
selections](https://github.com/user-attachments/assets/a3ee6d4d-91e0-4df6-b4cf-b66d5c1a2e87)

</details>

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
2026-10-31 11:28:14 -06:00

65 lines
2.6 KiB
Swift

import Flutter
import UIKit
private final class SettingMenuMessenger: NSObject, FlutterBinaryMessenger {
var selections: [Int] = []
func send(onChannel channel: String, message: Data?) {
guard let message else { return }
let call = FlutterStandardMethodCodec.sharedInstance().decodeMethodCall(message)
if call.method == "menuAction", let index = call.arguments as? Int {
selections.append(index)
}
}
func send(onChannel channel: String, message: Data?, binaryReply callback: FlutterBinaryReply?) {
send(onChannel: channel, message: message)
callback?(nil)
}
func setMessageHandlerOnChannel(
_ channel: String, binaryMessageHandler handler: FlutterBinaryMessageHandler?
) -> FlutterBinaryMessengerConnection { 1 }
func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) {}
}
@main
struct SettingMenuSelectionTests {
@MainActor static func main() {
for deferred in [false, true] {
let messenger = SettingMenuMessenger()
let view = NavigationGlassButtonPlatformView(
frame: CGRect(x: 0, y: 0, width: 340, height: 56),
viewIdentifier: 1,
arguments: [
"fillWidth": true, "plain": true, "label": "", "enabled": true,
"deferMenuActions": deferred,
"menu": [
["id": 0, "label": "Low", "enabled": true, "checked": false],
["id": 1, "label": "High", "enabled": true, "checked": true],
],
],
messenger: messenger
)
let button = view.view().subviews.compactMap { $0 as? NavigationGlassButton }.first!
view.view().layoutIfNeeded()
view.view().frame.size.width = 600
view.view().layoutIfNeeded()
precondition(button.bounds.width == 600)
precondition(button.point(inside: CGPoint(x: 570, y: 28), with: nil))
let group = button.menu!.children.first as! UIMenu
let choices = group.children.compactMap { $0 as? UIAction }
precondition(choices[0].state == .off && choices[1].state == .on)
// Invoke the actual menu UIAction through UIKit, without synthesizing a
// Flutter method-channel message or depending on dismissal callback order.
let selection = UIButton(primaryAction: choices[0])
selection.sendActions(for: .touchUpInside)
precondition(messenger.selections == (deferred ? [] : [0]))
if deferred {
precondition(button.pendingMenuAction != nil)
button.pendingMenuAction?()
button.pendingMenuAction = nil
precondition(messenger.selections == [0])
}
}
print("Native setting menu selection checks passed")
}
}