4 Commits

Author SHA1 Message Date
Tom Brow
f6f6d9a673 chore(mobile): delete dead code with no remaining UI path (#8880)
## Summary

Deletes mobile code that no longer has a user-reachable path and has no
counterpart in buzz-app, so it is unlikely to come back for parity. Net:
104 files, about 5,500 lines removed. No intended behavior change.

- **iOS native message menu and action surface:**
`NativeMessageMenu.swift` and `NativeMessageActionSurface.swift`, the
`message`/`supportsMessage` coordinator branches, and the Dart selection
hook. Dart stopped creating this view in
[#8280](https://github.com/block/buzz/pull/8280). The native reactions
sheet in the same coordinator is kept.
- **Old home quick-actions launcher and `ComposeMorphIcon`:** only
instantiated in tests since the nav-bar creation actions replaced them.
- **Retired local theme stack:** `ThemeNotifier`, `AccentNotifier`,
`SchemeNotifier`, `adaptive_theme.dart`, `AccentPickerPage`, the
appearance-mode sheet and their helpers. These predate per-community
theme sync. The legacy prefs migration in
`community_theme_preference.dart` is kept.
- **Unused widgets:** `ProfileAvatar` and `MaskedAvatarBadge`.
- **Push permission-status plumbing:** the iOS
`notificationAuthorizationStatus`/`openNotificationSettings` handlers,
plus the uncalled strict age-gate snapshot registration and its Swift
`syncAgeGatePushSnapshot` path.
- **Orphaned files** with no importer: `profile_text_edit_sheet`,
`editor_option_button`, `retained_page_transition`,
`tappable_flapping_bee`, `agent_model_info`, `community_bot_profiles`,
`sheet_divider`, `success_haptic`.
- **Uncalled helpers:** the `pickAndUpload*`/camera helpers in
`media_upload.dart`, unused `NostrFilters` builders,
`mediaGetHeadersFor*`, and about 20 other uncalled functions, providers
and styles.
- **Removed-UI leftovers:** the never-wired invite directory providers,
`AuthNotifier.signOut` and `removeActiveCommunityForSignOut` (the Sign
out row is gone), `renameCommunity`,
`HomePage.profilePageBuilder`/`SettingsPage.embedded`, and the
create-forum branches of the create-channel sheet. Forum viewing is
unchanged.

Tests that only covered deleted code are removed. Tests of surviving
code that used deleted helpers as drivers were repointed to the
surviving API.

An audit of `mobile/android` found no dead Kotlin, resources, manifest
entries or Gradle dependencies, so Android code is unchanged.

## Validation

- `flutter analyze`: no issues.
- After rebasing onto main
([93b8b8f](https://github.com/block/buzz/commit/93b8b8febc)), `just
mobile-check` is clean (format and analyze), and `just mobile-test`
passes (4,070 passed, 35 skipped, 0 failed, plus the push-unconfigured
and secp256k1 suites).
- `dart format`: clean.
- Android: `just mobile-build-android` builds the debug APK, and
`./gradlew :app:testDebugUnitTest` passes.
- iOS: `build-for-testing` succeeds and BuzzPushKit `swift test` passes
(65 tests). In RunnerTests, 97 of 98 pass.
`testNativeNavigationTitleExpandsAgainAtTop` fails, but it fails the
same way on unmodified `main` (acf56fff6f) on the same machine (Xcode
27, iPhone 17 Pro simulator), so it is not caused by this change.
- Agent review of the diff ran. Its one blocker (stale `project.pbxproj`
entries for the deleted Swift files) is fixed.
- In-app smoke run at
[66141c1](66141c10b9):
a debug build on a fresh iPhone 17 Pro simulator (iOS 27), signed in to
the internal community. The following flows all worked with no errors:
- Home: the New menu (channel, DM, workspace, chat) and the
create-channel sheet, including its channel-type options.
- A chat, with the message action sheet (reactions row, Reply, Copy
link, Remind me, Mark unread, Copy text, Edit and Delete).
  - Appearance: the previews, and cycling the System and Light modes.
- Settings: the profile header, the display name editor, and Edit photo
(Image and Emoji tabs).
  - The Agents directory.
- Search, including the Channels filter, plus opening a team channel
from the results.
- Tapping a reaction summary, which opens the native iOS Reactions
sheet.
- The recording isn't attached here because it shows internal channels
and messages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Tom Brow <tomb@squareup.com>
Co-authored-by: Tom Brow <tomb@squareup.com>
Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:09:50 -08:00
Tom Brow
dc4cdc4990 fix(mobile): reset community notification preferences (#8455)
Community notification choices now use `pushNotificationsEnabledV2`,
defaulting ON when absent. This gives every installed community a fresh
enabled preference, including communities previously disabled.
Subsequent explicit OFF choices persist per community through reloads
and reconnects. Previous values are deliberately discarded, not migrated
or preserved. There is no migration or compatibility read.

Enabled communities enter the existing APNs enrollment and active relay
lease publication path when connected to a push-capable relay. iOS still
controls notification display authorization. Notification eligibility
and lease addressing are unchanged.

Related work: [#8425](https://github.com/block/buzz/pull/8425).

### Validation

- Extended the settings integration test to load a saved community with
the previous preference OFF and no new preference and verify native
enrollment plus decrypted active lease publication, then OFF across
reconnect and ON again.
- The focused model test proves both previous values are ignored and
new-key OFF wins even when the previous key says ON. A temporary
compatibility-fallback mutation failed this test as expected; the
implementation was restored unchanged.
- Added storage coverage for independent community choices across
reloads; updated existing model round-trip coverage for the new key.
- Mobile dependency setup, formatting, analysis, and the full mobile
suite passed, including gateway-unconfigured coverage.
- Agent review found no blockers. Enrollment coverage uses the real
Flutter bootstrap, storage, signing, and lease construction with mocked
native and relay boundaries; no physical-device or live APNs delivery
test was run.

The fresh enabled preference is an intentional product exception to the
general zero-notification default in VISION.md. Subsequent user choices
and existing eligibility filters remain authoritative.

<!-- buzz-review-completed -->

---------

Signed-off-by: Tom Brow <tomb@block.xyz>
2026-10-19 10:09:25 -07:00
Wes
03ce924e32 fix(ci): restore green main after merge skew and new advisory (#8277)
Main CI has been red since c09730e87 (#8223). The Mobile and Security
checks fail on main, and Docker image fails because it requires a green
CI run for the same commit. Locally, the pre-push Rust lane also failed
on load-sensitive `buzz-acp` timing tests. This PR fixes all three so
main passes locally and on GitHub.

- **Mobile:** #8223 was tested against a base from before #8206, which
removed `buzzDevPushAppProfile` and app-profile selection. Its new
`notification_toggle_test.dart` still put `appProfile` in the native
grant map, so the merged tree doesn't compile. This removes the stale
field.
- **Security:** cargo-deny now reports
[RUSTSEC-2024-0449](https://rustsec.org/advisories/RUSTSEC-2024-0449)
(`unsafe-libyaml` is unmaintained), which comes in through `serde_yaml`.
It's an unmaintained notice, not a vulnerability. The `serde_yaml_ng`
fork depends on the same crate, so removing it means migrating YAML
parsing in five crates. Like the existing unmaintained entries, it goes
in `deny.toml` with a reason.
- **buzz-acp test flakes:** the `spawn_script` test helper returned
before bash was running, and the timing tests started their idle clock
right away. Under full-suite load, process startup took longer than the
idle windows. `keepalive_resets_idle_past_deadline`,
`idle_resets_on_stdout_activity` and
`acp_steer_request_omits_expected_run_id_and_carries_session_and_prompt`
failed this way across three pre-push runs. The helper now has the
script print a ready line and consumes it before returning. The
keepalive loops also use brace expansion instead of `$(seq)`, which
avoids an extra process launch before the first line. The keepalive test
now uses a 250ms idle window with a 750ms floor. Both tests still fail
if keepalives don't reset the idle clock.

### Validation
- `cargo-deny check advisories` passes with this `deny.toml` and fails
on main's.
- The `notification_toggle_test.dart` tests and `flutter analyze` pass.
- `cargo test -p buzz-acp --lib` passes all 1055 tests.
- The `acp::tests` suite passed 20 of 20 runs with 4 concurrent copies
over 5 rounds. Under the same load, the version without the
brace-expansion change failed every run.
- All pre-push hooks pass on 5dbaa4d32: rust-tests, mobile-checks,
desktop-tauri-checks, file-size-check, branch-skew.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 16:46:31 +00:00
Tom Brow
c09730e874 fix(mobile): keep notification toggle usable and match row height (#8223)
Turning Notifications off invalidated the relay capability provider
because it watched the entire saved community. If the redundant NIP-11
request stalled or failed, the switch became disabled and reopening
Settings did not recover it. Discovery now follows community identity
and connection status, so preference and lease bookkeeping retain the
validated capability while a real reconnect still refreshes it. Each
opt-in also starts a fresh active lease immediately instead of waiting
for the old renewal timer. Failed attempts retain their gate until the
retry delay expires, preventing rebuilds from bypassing backoff.

Notifications now has the same single-line height as Set status, with
the full switch hit area and one combined accessibility label. This
follows [#8201](https://github.com/block/buzz/pull/8201); no duplicate
open PR was found.

### Validation

Added iOS widget regressions mount the production settings page and push
bootstrap with production storage logic, signing, and lease publication.
They verify a higher-generation active replacement after off/on with
accepted, failed, and pending cleanup, plus closing/reopening Settings,
switch and row taps, 2× text, accessibility, and rediscovery on
reconnect. A gate test verifies that rebuilds cannot bypass failure
backoff. Both UI failures and the missing active replacement were
reproduced before their fixes.

Mobile dependency installation, formatting/static checks, 3,234
configured tests, and three unconfigured-build tests passed. Captures
use the real Flutter settings widget at 375pt width, with synthetic data
and mocked native/network boundaries. Native navigation is outside the
capture. No device installation or deployment was performed.

After merge, validate the candidate on iOS: compare Notifications with
Set status, toggle off then immediately on, close/reopen Settings while
off and turn on, and repeat after reconnect. Confirm delivery resumes
after opt-in.

### Layout

Flutter widget captures with synthetic data; native navigation is
excluded.

| Before | After |
| --- | --- |
| ![Notifications row
before](https://raw.githubusercontent.com/block/buzz/b2cf4b8b1f0abaa95893af0e5a4e194c6af41333/pr-8223--01-before.png)
| ![Notifications row
after](https://raw.githubusercontent.com/block/buzz/b2cf4b8b1f0abaa95893af0e5a4e194c6af41333/pr-8223--02-after.png)
|

---------

Signed-off-by: Tom Brow <tomb@block.xyz>
2026-10-12 09:39:53 -07:00