Files
buzz/mobile/lib/shared/widgets/ios_text_editor.dart
klopez4212 7e8aac4403 fix(mobile): polish channel management and iOS Settings (#8171)
## Summary

Use native iOS sheets for channel editing and Add Members, with profile
avatars, matching search, and destructive removal dialogs. Canvas
content becomes a tappable preview with Add/Remove actions.

Fix the Settings availability menu and clipped copy confirmation. Align
channel action messages with chat styling and keep agent identities
distinguishable across selection, attribution, and profile surfaces.

### Related issue

No duplicate found in the existing mobile Settings/channel issues and
PRs.

### Testing

- Flutter analysis, formatting, file-size checks, focused collision
regressions, and the full mobile test suite passed.
- Production UIKit picker simulator check passed: distinct
visible/accessibility labels, avatar updates, selected rows, and pubkey
callbacks. Wired into Mobile Swift CI.
- Original UI was built and tested on the physical iPhone with author
confirmation; profile/community data preserved.
- Review fixes await renewed author device confirmation before restoring
`buzz-review-completed` and ready-for-review status.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
2026-10-08 14:32:55 -04:00

79 lines
2.5 KiB
Dart

import 'package:flutter/services.dart';
import '../theme/theme.dart';
/// Opens the native iOS form used to edit a single text field.
class IosTextEditor {
IosTextEditor._();
static const _channel = MethodChannel('buzz/profile_text_editor');
/// Presents the native editor and returns its submitted value, or null when
/// the user cancels.
static Future<String?> present({
required String title,
required String initialValue,
required String placeholder,
required bool multiline,
required Brightness brightness,
required Color pageBackgroundColor,
required Color containerBackgroundColor,
bool allowUnchangedSubmission = false,
}) => _channel.invokeMethod<String>('present', {
'title': title,
'initialValue': initialValue,
'placeholder': placeholder,
'multiline': multiline,
'brightness': brightness.name,
'pageBackgroundArgb': pageBackgroundColor.toARGB32(),
'containerBackgroundArgb': containerBackgroundColor.toARGB32(),
'containerCornerRadius': Radii.container,
'allowUnchangedSubmission': allowUnchangedSubmission,
});
/// Keeps the native editor's latest value available until it saves or the
/// user cancels, so a transient publish failure never discards their text.
static Future<void> presentUntilSaved({
required String title,
required String initialValue,
required String placeholder,
required bool multiline,
required Brightness brightness,
required Color pageBackgroundColor,
required Color containerBackgroundColor,
required Future<void> Function(String value) onSave,
required void Function() onSaveError,
bool Function(Object error)? shouldRetryOnError,
bool Function()? canPresent,
}) async {
var draft = initialValue;
var isRetry = false;
while (true) {
if (canPresent?.call() == false) return;
final value = await present(
title: title,
initialValue: draft,
placeholder: placeholder,
multiline: multiline,
brightness: brightness,
pageBackgroundColor: pageBackgroundColor,
containerBackgroundColor: containerBackgroundColor,
allowUnchangedSubmission: isRetry,
);
if (value == null) return;
try {
await onSave(value);
return;
} catch (error) {
if (shouldRetryOnError?.call(error) == false ||
canPresent?.call() == false) {
return;
}
draft = value;
isRetry = true;
onSaveError();
}
}
}
}