Skip to content

Commit ed11c8d

Browse files
klopez4212Princess Donut
andauthored
Refresh mobile utility surfaces and theme picker (#6944)
## Summary - invert mobile utility surfaces so pages and sheets use the softer page background with raised containers - rebuild the community theme picker around swipeable Home/Chat previews, accent and appearance controls, and native iOS glass interactions - align shared sheet/profile spacing and radii, and move Theme into the Community settings card ### Related issue None found. ### Testing - `just mobile-check` - `just mobile-test` (1,871 tests) - signed iOS Release build installed on a physical iPhone --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Kenny Lopez <klopez4212@gmail.com> Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz> Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
1 parent a89f5df commit ed11c8d

47 files changed

Lines changed: 3714 additions & 580 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

mobile/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
4A71C0172F40C00100A17E01 /* HuddleAudioEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A71C0182F40C00100A17E01 /* HuddleAudioEngine.swift */; };
2525
4A71C0192F40D00100A17E01 /* NativeProfileTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A71C01A2F40D00100A17E01 /* NativeProfileTextEditor.swift */; };
2626
4A71C01B2F40E00100A17E01 /* NativeSkinToneControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A71C01C2F40E00100A17E01 /* NativeSkinToneControl.swift */; };
27+
4A71C01D2F40F00100A17E01 /* ThemePaginationGlassControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A71C01E2F40F00100A17E01 /* ThemePaginationGlassControl.swift */; };
2728
331C809D294A63AB00263BE5 /* UIKitEncoded.png in Resources */ = {isa = PBXBuildFile; fileRef = 331C809C294A618700263BE5 /* UIKitEncoded.png */; };
2829
331C809F294A63AB00263BE5 /* UIKitEncoded.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 331C809E294A618700263BE5 /* UIKitEncoded.jpg */; };
2930
33ADD70AB275E0EC81295559 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8906419FB4E98B4B12B7A56F /* Pods_Runner.framework */; };
@@ -79,6 +80,7 @@
7980
4A71C0182F40C00100A17E01 /* HuddleAudioEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HuddleAudioEngine.swift; sourceTree = "<group>"; };
8081
4A71C01A2F40D00100A17E01 /* NativeProfileTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeProfileTextEditor.swift; sourceTree = "<group>"; };
8182
4A71C01C2F40E00100A17E01 /* NativeSkinToneControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeSkinToneControl.swift; sourceTree = "<group>"; };
83+
4A71C01E2F40F00100A17E01 /* ThemePaginationGlassControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemePaginationGlassControl.swift; sourceTree = "<group>"; };
8284
331C809C294A618700263BE5 /* UIKitEncoded.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = UIKitEncoded.png; sourceTree = "<group>"; };
8385
331C809E294A618700263BE5 /* UIKitEncoded.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = UIKitEncoded.jpg; sourceTree = "<group>"; };
8486
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -212,6 +214,7 @@
212214
4A71C0182F40C00100A17E01 /* HuddleAudioEngine.swift */,
213215
4A71C01A2F40D00100A17E01 /* NativeProfileTextEditor.swift */,
214216
4A71C01C2F40E00100A17E01 /* NativeSkinToneControl.swift */,
217+
4A71C01E2F40F00100A17E01 /* ThemePaginationGlassControl.swift */,
215218
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
216219
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
217220
);
@@ -475,6 +478,7 @@
475478
4A71C0172F40C00100A17E01 /* HuddleAudioEngine.swift in Sources */,
476479
4A71C0192F40D00100A17E01 /* NativeProfileTextEditor.swift in Sources */,
477480
4A71C01B2F40E00100A17E01 /* NativeSkinToneControl.swift in Sources */,
481+
4A71C01D2F40F00100A17E01 /* ThemePaginationGlassControl.swift in Sources */,
478482
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
479483
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */,
480484
);

mobile/ios/Runner/AppDelegate.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ import UserNotifications
138138
)
139139
}
140140

141+
if let themePaginationGlassRegistrar = engineBridge.pluginRegistry.registrar(
142+
forPlugin: "BuzzThemePaginationGlassControl"
143+
) {
144+
themePaginationGlassRegistrar.register(
145+
ThemePaginationGlassControlFactory(messenger: messenger),
146+
withId: "buzz/theme_pagination_glass"
147+
)
148+
}
149+
141150
let nativeAttachmentRegistrar = engineBridge.pluginRegistry.registrar(
142151
forPlugin: "BuzzNativeAttachmentPopover"
143152
)

mobile/ios/Runner/JumpToLatestGlassButton.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ final class NavigationGlassButtonPlatformView: NSObject, FlutterPlatformView {
175175
private let channel: FlutterMethodChannel
176176
private let button = NavigationGlassButton(type: .system)
177177
private let activityIndicator = UIActivityIndicatorView(style: .medium)
178+
private let swatchView = UIView()
178179
private var buttonLabel: String?
179180
private var buttonIconName = "chevron.backward"
180181
private var contentIcon = "back"
@@ -248,6 +249,20 @@ final class NavigationGlassButtonPlatformView: NSObject, FlutterPlatformView {
248249
activityIndicator.heightAnchor.constraint(equalToConstant: 24),
249250
])
250251

252+
swatchView.translatesAutoresizingMaskIntoConstraints = false
253+
swatchView.isUserInteractionEnabled = false
254+
swatchView.isHidden = true
255+
swatchView.layer.cornerCurve = .continuous
256+
button.addSubview(swatchView)
257+
let swatchSize = max(0, controlSize - 8)
258+
NSLayoutConstraint.activate([
259+
swatchView.centerXAnchor.constraint(equalTo: button.centerXAnchor),
260+
swatchView.centerYAnchor.constraint(equalTo: button.centerYAnchor),
261+
swatchView.widthAnchor.constraint(equalToConstant: swatchSize),
262+
swatchView.heightAnchor.constraint(equalToConstant: swatchSize),
263+
])
264+
swatchView.layer.cornerRadius = swatchSize / 2
265+
251266
applyAppearance(from: args)
252267
channel.setMethodCallHandler { [weak self] call, result in
253268
if call.method == "setContent" {
@@ -342,6 +357,7 @@ final class NavigationGlassButtonPlatformView: NSObject, FlutterPlatformView {
342357
let enabled = arguments?["enabled"] as? Bool ?? true
343358
let busy = arguments?["busy"] as? Bool ?? false
344359
let selected = arguments?["selected"] as? Bool ?? false
360+
let swatchColorValue = (arguments?["swatchColor"] as? NSNumber)?.uint32Value
345361

346362
containerView.overrideUserInterfaceStyle = interfaceStyle
347363
button.overrideUserInterfaceStyle = interfaceStyle
@@ -361,6 +377,9 @@ final class NavigationGlassButtonPlatformView: NSObject, FlutterPlatformView {
361377
button.configuration?.baseForegroundColor = foregroundColor
362378
activityIndicator.color = foregroundColor
363379
}
380+
if let swatchColorValue {
381+
swatchView.backgroundColor = Self.color(from: swatchColorValue)
382+
}
364383
if #unavailable(iOS 26.0) {
365384
button.configuration?.baseBackgroundColor = Self.fallbackBackgroundColor(
366385
foregroundColor: foregroundColor,
@@ -384,11 +403,16 @@ final class NavigationGlassButtonPlatformView: NSObject, FlutterPlatformView {
384403
case "camera": buttonIconName = "camera"
385404
case "photoLibrary": buttonIconName = "photo.on.rectangle.angled"
386405
case "palette": buttonIconName = "paintpalette"
406+
case "droplet": buttonIconName = "drop.fill"
387407
case "emoji": buttonIconName = "face.smiling"
388408
case "person": buttonIconName = "person"
389409
case "frame": buttonIconName = "rectangle.stack"
390410
case "rotateCamera": buttonIconName = "arrow.triangle.2.circlepath.camera"
391411
case "shutter": buttonIconName = "circle.fill"
412+
case "sun": buttonIconName = "sun.max"
413+
case "moon": buttonIconName = "moon"
414+
case "systemAppearance": buttonIconName = "circle.lefthalf.filled"
415+
case "colorSwatch": buttonIconName = "circle.fill"
392416
default: buttonIconName = "chevron.backward"
393417
}
394418
if buttonLabel != nil {
@@ -457,10 +481,13 @@ final class NavigationGlassButtonPlatformView: NSObject, FlutterPlatformView {
457481
if isBusy {
458482
button.configuration?.title = nil
459483
button.configuration?.image = nil
484+
swatchView.isHidden = true
460485
activityIndicator.startAnimating()
461486
} else {
462-
button.configuration?.title = buttonLabel
463-
button.configuration?.image = buttonLabel == nil ? buttonImage : nil
487+
let displaysSwatch = contentIcon == "colorSwatch"
488+
button.configuration?.title = displaysSwatch ? nil : buttonLabel
489+
button.configuration?.image = displaysSwatch || buttonLabel != nil ? nil : buttonImage
490+
swatchView.isHidden = !displaysSwatch
464491
activityIndicator.stopAnimating()
465492
}
466493
}

mobile/ios/Runner/NativeProfileTextEditor.swift

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ final class NativeProfileTextEditorCoordinator: NSObject,
3838
let initialValue = arguments["initialValue"] as? String,
3939
let placeholder = arguments["placeholder"] as? String,
4040
let multiline = arguments["multiline"] as? Bool,
41-
let brightness = arguments["brightness"] as? String
41+
let brightness = arguments["brightness"] as? String,
42+
let pageBackgroundArgb = arguments["pageBackgroundArgb"] as? NSNumber,
43+
let containerBackgroundArgb = arguments["containerBackgroundArgb"] as? NSNumber,
44+
let containerCornerRadius = arguments["containerCornerRadius"] as? NSNumber
4245
else {
4346
result(
4447
FlutterError(
@@ -59,6 +62,9 @@ final class NativeProfileTextEditorCoordinator: NSObject,
5962
placeholder: placeholder,
6063
multiline: multiline,
6164
brightness: brightness,
65+
pageBackgroundColor: UIColor(argb: pageBackgroundArgb.uint32Value),
66+
containerBackgroundColor: UIColor(argb: containerBackgroundArgb.uint32Value),
67+
containerCornerRadius: CGFloat(containerCornerRadius.doubleValue),
6268
allowUnchangedSubmission: allowUnchangedSubmission,
6369
result: result
6470
)
@@ -72,6 +78,9 @@ final class NativeProfileTextEditorCoordinator: NSObject,
7278
placeholder: String,
7379
multiline: Bool,
7480
brightness: String,
81+
pageBackgroundColor: UIColor,
82+
containerBackgroundColor: UIColor,
83+
containerCornerRadius: CGFloat,
7584
allowUnchangedSubmission: Bool,
7685
result: @escaping FlutterResult
7786
) {
@@ -105,6 +114,9 @@ final class NativeProfileTextEditorCoordinator: NSObject,
105114
initialValue: initialValue,
106115
placeholder: placeholder,
107116
multiline: multiline,
117+
pageBackgroundColor: pageBackgroundColor,
118+
containerBackgroundColor: containerBackgroundColor,
119+
containerCornerRadius: containerCornerRadius,
108120
allowUnchangedSubmission: allowUnchangedSubmission,
109121
onCancel: { [weak self] in self?.finish(value: nil) },
110122
onSet: { [weak self] value in self?.finish(value: value) }
@@ -184,6 +196,9 @@ private final class NativeProfileTextEditorViewController:
184196
private let initialValue: String
185197
private let placeholder: String
186198
private let multiline: Bool
199+
private let pageBackgroundColor: UIColor
200+
private let containerBackgroundColor: UIColor
201+
private let containerCornerRadius: CGFloat
187202
private let allowUnchangedSubmission: Bool
188203
private let onCancel: () -> Void
189204
private let onSet: (String) -> Void
@@ -233,13 +248,19 @@ private final class NativeProfileTextEditorViewController:
233248
initialValue: String,
234249
placeholder: String,
235250
multiline: Bool,
251+
pageBackgroundColor: UIColor,
252+
containerBackgroundColor: UIColor,
253+
containerCornerRadius: CGFloat,
236254
allowUnchangedSubmission: Bool,
237255
onCancel: @escaping () -> Void,
238256
onSet: @escaping (String) -> Void
239257
) {
240258
self.initialValue = initialValue
241259
self.placeholder = placeholder
242260
self.multiline = multiline
261+
self.pageBackgroundColor = pageBackgroundColor
262+
self.containerBackgroundColor = containerBackgroundColor
263+
self.containerCornerRadius = containerCornerRadius
243264
self.allowUnchangedSubmission = allowUnchangedSubmission
244265
self.onCancel = onCancel
245266
self.onSet = onSet
@@ -254,8 +275,22 @@ private final class NativeProfileTextEditorViewController:
254275

255276
override func viewDidLoad() {
256277
super.viewDidLoad()
278+
view.backgroundColor = pageBackgroundColor
279+
tableView.backgroundColor = pageBackgroundColor
257280
tableView.keyboardDismissMode = .interactive
258281
tableView.alwaysBounceVertical = false
282+
let navigationAppearance = UINavigationBarAppearance()
283+
navigationAppearance.configureWithOpaqueBackground()
284+
navigationAppearance.backgroundColor = pageBackgroundColor
285+
navigationAppearance.shadowColor = UIColor.separator.withAlphaComponent(0.2)
286+
let scrollEdgeAppearance = UINavigationBarAppearance()
287+
scrollEdgeAppearance.configureWithOpaqueBackground()
288+
scrollEdgeAppearance.backgroundColor = pageBackgroundColor
289+
scrollEdgeAppearance.shadowColor = .clear
290+
navigationItem.standardAppearance = navigationAppearance
291+
navigationItem.scrollEdgeAppearance = scrollEdgeAppearance
292+
navigationItem.compactAppearance = navigationAppearance
293+
navigationItem.compactScrollEdgeAppearance = scrollEdgeAppearance
259294
navigationItem.leftBarButtonItem = UIBarButtonItem(
260295
barButtonSystemItem: .cancel,
261296
target: self,
@@ -360,6 +395,10 @@ private final class NativeProfileTextEditorViewController:
360395
) -> UITableViewCell {
361396
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
362397
cell.selectionStyle = .none
398+
cell.backgroundColor = containerBackgroundColor
399+
cell.layer.cornerRadius = containerCornerRadius
400+
cell.layer.cornerCurve = .continuous
401+
cell.clipsToBounds = true
363402
if multiline {
364403
cell.contentView.addSubview(textView)
365404
textView.addSubview(placeholderLabel)
@@ -385,3 +424,14 @@ private final class NativeProfileTextEditorViewController:
385424
return cell
386425
}
387426
}
427+
428+
private extension UIColor {
429+
convenience init(argb: UInt32) {
430+
self.init(
431+
red: CGFloat((argb >> 16) & 0xff) / 255,
432+
green: CGFloat((argb >> 8) & 0xff) / 255,
433+
blue: CGFloat(argb & 0xff) / 255,
434+
alpha: CGFloat((argb >> 24) & 0xff) / 255
435+
)
436+
}
437+
}

0 commit comments

Comments
 (0)