Skip to content

feat(forum): share button on forum posts (app + public web link)#146

Merged
krazyjakee merged 3 commits into
masterfrom
feat/forum-post-share-button
Jun 15, 2026
Merged

feat(forum): share button on forum posts (app + public web link)#146
krazyjakee merged 3 commits into
masterfrom
feat/forum-post-share-button

Conversation

@krazyjakee

Copy link
Copy Markdown
Contributor

Summary

  • Adds a share button to the forum-post header with two options:
    • Share with those who have the appdaccord://navigate/{spaceId}/{channelId}?msg={postId} (opens the post in a daccord client)
    • Share with the internet{baseUrl}/s/{slug}/{channel}/{postId} — the public, crawlable URL served by accordserver's new SEO layer
  • The chosen link is copied to the clipboard with a confirmation snackbar. The button only appears for space-backed threads (forum posts), not ad-hoc DM threads.
  • The public-link half pairs with the server-side SEO work in accordserver (feat(seo): public crawlable snapshots, social cards, oEmbed & sitemap accordserver#36).

Notes for reviewers

  • Per request, this PR also bundles several unrelated in-progress changes that were already in the working tree: the inline forum-thread pane refactor (thread_view.dart, forum_view.dart), reorderable space tabs (accord_home_tabs.dart), and voice-view selector tweaks (voice_view.dart), plus a small emoji-picker change. The share button itself is the only change authored in this session.
  • flutter analyze on thread_view.dart reports no issues.

Test plan

  • Open a forum post → tap the share icon in the header
  • "Share with those who have the app" copies a daccord://navigate/...?msg=... link
  • "Share with the internet" copies a https://.../s/<slug>/<channel>/<post> link
  • Share button is hidden for non-space (DM) threads
  • flutter analyze --no-fatal-infos is clean

🤖 Generated with Claude Code

krazyjakee and others added 3 commits June 14, 2026 23:13
Reworks self-updating so the new build downloads and verifies in the
background as soon as a check finds it, then surfaces a single "Update
ready — tap to restart & install" banner. One tap applies the staged
build (desktop quits and relaunches into the new version; Android hands
the staged APK to the system installer), eliminating the previous
multi-click "view → download → install" flow.

- Add UpdatePhase.ready plus stagedArchivePath/preparedVersion to
  UpdateState (with updateReady/downloading getters).
- Split installUpdate() into prepareUpdate() (background download+verify,
  staged at ready) and applyUpdate() (apply staged, or download-then-apply
  as a fallback), sharing a _downloadAndVerify() helper. check() now fires
  prepareUpdate() automatically; guards make it safe to call on every
  hourly check and re-stage when a newer release ships.
- Banner stays hidden during background download and only appears once
  staged; platforms that can't self-install (web/iOS, or a failed
  background download) fall back to the old "tap to view" banner.
- Updates page button shows "Restart & install" with a restart icon when
  staged and reuses the staged download.

Web is unchanged (service-worker reload).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a share affordance to the forum post header offering two links:
- "Share with those who have the app" → daccord://navigate deep link
- "Share with the internet" → the public /s/<slug>/<channel>/<post> URL
  served by accordserver's SEO layer

Copies the chosen link to the clipboard with a confirmation snackbar.
Builds on the inline forum-thread pane (thread_view/forum_view).

Also bundles in-progress work on reorderable space tabs, voice view
selectors, and the emoji picker.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…y; add tests

- Add clearStagedArchive/clearPreparedVersion flags to UpdateState.copyWith
  so staged archive state can be reset after a successful Android install.
  Previously these fields could never be set back to null, causing a stale
  stagedArchivePath to persist after applyUpdate completed — meaning the
  next periodic check() would kick off a redundant re-download.
- Clear both staged fields when applyUpdate transitions to idle.
- Fix formatting artifact: ScaffoldMessenger.of(context,) across three
  lines in accord_home_tabs.dart (trailing comma from auto-format).
- Add missing unit tests:
  - UpdateState.updateReady getter (true only when ready + path set)
  - UpdateState.downloading getter (downloading + verifying, not others)
  - UpdateState.installing (ready excluded — that's what enables one-click)
  - copyWith clearStagedArchive / clearPreparedVersion flags
  - UpdateBanner: "restart & install" text when updateReady
  - UpdateBanner: shows fallback "view" banner on failed background download

https://claude.ai/code/session_013krsj92YmYwELfMzFGanzN

Copy link
Copy Markdown
Contributor Author

Code Review — findings and fixes (ranked by severity)

Fixes were pushed in commit f33592c directly to this branch.


🔴 HIGH — UpdateState.copyWith could never clear stagedArchivePath / preparedVersion (fixed)

File: lib/features/updates/controllers/update_controller.dart

copyWith used stagedArchivePath ?? this.stagedArchivePath, meaning once set, neither field could ever be reset to null. This caused a real bug on Android: after applyUpdate() completes and transitions to phase: idle, the stale stagedArchivePath (and matching preparedVersion) remained in state. The next periodic check() call triggers unawaited(prepareUpdate()), which guards against re-downloading only when phase == ready && preparedVersion == version. Since phase had just been set back to idle, this guard never fires — the controller starts a redundant full re-download of the same build the user just applied.

Fix: Added bool clearStagedArchive = false and bool clearPreparedVersion = false flags to copyWith, and used them when applyUpdate transitions to idle:

state = state.copyWith(
  phase: UpdatePhase.idle,
  clearStagedArchive: true,
  clearPreparedVersion: true,
);

🟡 MEDIUM — Missing tests for new state getters and banner states (fixed)

Files: test/features/updates/update_controller_test.dart, test/features/updates/update_banner_test.dart

The PR introduced several new computed properties (updateReady, downloading, the ready phase exclusion from installing) and new banner paths (updateReady banner, fallback on failed download) with zero test coverage.

Added:

  • UpdateState.updateReady — true only when phase == ready && stagedArchivePath != null
  • UpdateState.downloading — true for downloading and verifying only
  • UpdateState.installing — explicitly asserts that ready is excluded (the key invariant enabling the one-click UX)
  • UpdateState.copyWith clear flags — both clearStagedArchive and clearPreparedVersion, individually and combined
  • UpdateBanner — "restart & install" text when updateReady
  • UpdateBanner — fallback "update available" banner when phase is failed

🟢 LOW — Formatting artifact in accord_home_tabs.dart (fixed)

File: lib/features/spaces/views/accord_home_tabs.dart

A trailing comma inside ScaffoldMessenger.of(context,) caused the auto-formatter to split the call across three lines:

// before
ScaffoldMessenger.of(
  context,
).showSnackBar(...);

// after
ScaffoldMessenger.of(context)
    .showSnackBar(...);

ℹ️ Notes (no code change needed)

thread_view.dart — share menu silently omits the web link: When spaceControllerProvider or accordChannelsControllerProvider haven't loaded, the "Share with the internet" option is omitted without any user feedback. This is intentional graceful degradation (the app-link option always shows), but worth documenting that the web link requires both the space slug and channel name to be cached.

update_banner.dart — no loading indicator during apply: While applyUpdate is in flight the banner's onTap is null (disabled), but there's no spinner or "Installing…" text to explain why. The Updates page does show progress, so this is only a UX gap on the banner itself — out of scope for this PR but worth a follow-up.


Generated by Claude Code

@krazyjakee krazyjakee merged commit 3f67e13 into master Jun 15, 2026
3 checks passed
@krazyjakee krazyjakee deleted the feat/forum-post-share-button branch June 15, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants