diff --git a/src/screens/StarterPack/StarterPackScreen.tsx b/src/screens/StarterPack/StarterPackScreen.tsx
index d73e9b6b1e..111272c3b3 100644
--- a/src/screens/StarterPack/StarterPackScreen.tsx
+++ b/src/screens/StarterPack/StarterPackScreen.tsx
@@ -665,22 +665,24 @@ function OverflowMenu({
- optOutDialogControl.open()}>
-
- {referenceListOptOut ? (
- Undo opt-out
- ) : (
- Opt out of starter pack
- )}
-
-
+ {starterPack.list ? (
+ optOutDialogControl.open()}>
+
+ {referenceListOptOut ? (
+ Undo opt-out
+ ) : (
+ Opt out of starter pack
+ )}
+
+
+ ) : null}
>
)}
@@ -740,51 +742,53 @@ function OverflowMenu({
-
-
- {referenceListOptOut ? (
- Undo opt-out?
- ) : (
- Opt out of this starter pack?
- )}
-
-
- {referenceListOptOut ? (
- You will appear in this starter pack again.
- ) : (
-
- You will no longer appear in this starter pack. The creator can
- still remove you from its member list.
-
- )}
-
-
-
-
-
-
+ {starterPack.list ? (
+
+
+ {referenceListOptOut ? (
+ Undo opt-out?
+ ) : (
+ Opt out of this starter pack?
+ )}
+
+
+ {referenceListOptOut ? (
+ You will appear in this starter pack again.
+ ) : (
+
+ You will no longer appear in this starter pack. The creator can
+ still remove you from its member list.
+
+ )}
+
+
+
+
+
+
+ ) : null}
- !error &&
- value.starterPack.list?.viewer?.referenceListOptOut === nextOptOut,
+ (value, error) => {
+ if (error) return false
+
+ didReadViewerState = true
+ nextOptOut = value.starterPack.list?.viewer?.referenceListOptOut
+
+ // AppView ignores duplicate records and continues to expose the URI
+ // of the record it indexed first. Treat that viewer state as the
+ // source of truth instead of waiting for the newly-created URI.
+ return referenceListOptOut ? !nextOptOut : Boolean(nextOptOut)
+ },
async () =>
await appviewClient.call(app.bsky.graph.getStarterPack, {
starterPack: starterPack.uri,
}),
)
+
+ if (!didReadViewerState) {
+ throw new Error('Unable to read starter pack opt-out state')
+ }
return nextOptOut
},
onMutate: async ({referenceListOptOut}) => {