Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: PR Preview

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
create-update:
name: Create EAS Update
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: "yarn"
cache-dependency-path: yarn.lock
env:
SKIP_YARN_COREPACK_CHECK: "1"

- run: corepack enable

- name: Install dependencies
run: yarn install

- name: Setup EAS
uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
packager: yarn
eas-cache: true
patch-watchers: true

- name: Create PR preview update
uses: expo/expo-github-action/preview@v8
with:
command: eas update --channel=preview --branch=pr-${{ github.event.number }}
env:
EXPO_ENV: preview
15 changes: 14 additions & 1 deletion app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type EnvironmentConfig = {
backgroundColor: string
}
}
updates: {
disableAntiBrickingMeasures: boolean
}
}

export type IExpoAppConfigExtra = {
Expand Down Expand Up @@ -71,6 +74,9 @@ const settings: Record<Environment, EnvironmentConfig> = {
webDomain: "preview.convos.org",
appName: "Convos Dev",
icon: "./assets/icon-light.png",
updates: {
disableAntiBrickingMeasures: true,
},
},
preview: {
scheme: "convos-preview",
Expand Down Expand Up @@ -100,6 +106,9 @@ const settings: Record<Environment, EnvironmentConfig> = {
webDomain: "preview.convos.org",
appName: "Convos Preview",
icon: "./assets/icon-light.png",
updates: {
disableAntiBrickingMeasures: true,
},
},
production: {
scheme: "convos",
Expand Down Expand Up @@ -129,6 +138,10 @@ const settings: Record<Environment, EnvironmentConfig> = {
webDomain: "convos.org",
appName: "Convos",
icon: "./assets/icon-light.png",
updates: {
// NEVER in production app for now https://docs.expo.dev/eas-update/override/
disableAntiBrickingMeasures: false,
},
},
}

Expand All @@ -147,7 +160,7 @@ export default () => {
version: version,
assetBundlePatterns: ["**/*"],
runtimeVersion: {
policy: "nativeVersion",
policy: "fingerprint",
},
updates: {
url: "https://u.expo.dev/f9089dfa-8871-4aff-93ea-da08af0370d2",
Expand Down
228 changes: 227 additions & 1 deletion components/debug-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,223 @@ function useShowDebugMenu() {
})
}, [])

const showUpdatesMenu = useCallback(() => {
const currentEnv = getEnv()
const currentChannel = currentEnv // Channel matches environment

const updatesMethods = {
"Current Update Info": () => {
Alert.alert(
"Current Update Info",
[
`Environment: ${currentEnv}`,
`Channel: ${currentChannel}`,
`Update ID: ${currentlyRunning.updateId || "embedded"}`,
`Created: ${currentlyRunning.createdAt?.toLocaleString() || "N/A"}`,
`Runtime Version: ${currentlyRunning.runtimeVersion}`,
`Is Embedded: ${currentlyRunning.isEmbeddedLaunch}`,
].join("\n"),
[
{ text: "OK" },
{
text: "Copy Info",
onPress: () => {
const info = [
`Environment: ${currentEnv}`,
`Channel: ${currentChannel}`,
`Update ID: ${currentlyRunning.updateId || "embedded"}`,
`Runtime Version: ${currentlyRunning.runtimeVersion}`,
].join("\n")
Clipboard.setString(info)
},
},
],
)
},
"List Available Branches": async () => {
Alert.alert(
"Available Branches",
`This will show branches available for the "${currentChannel}" channel.\n\nRun this command in your terminal:`,
[
{
text: "Copy Command",
onPress: () => {
Clipboard.setString("eas branch:list")
Alert.alert("Copied", "Command copied to clipboard")
},
},
{ text: "OK" },
],
)
},
...(currentEnv === "preview"
? {
"Switch to PR Branch (Runtime Override)": async () => {
Alert.prompt(
"Switch to PR Branch",
"Enter the PR number to temporarily switch to that branch.",
[
{
text: "Cancel",
style: "cancel",
},
{
text: "Switch",
onPress: async (prNumber) => {
if (!prNumber || isNaN(Number(prNumber))) {
Alert.alert("Invalid Input", "Please enter a valid PR number")
return
}

try {
await Updates.setUpdateURLAndRequestHeadersOverride({
updateUrl: "https://u.expo.dev/f9089dfa-8871-4aff-93ea-da08af0370d2",
requestHeaders: {
"expo-channel-name": currentChannel,
"expo-branch-name": `pr-${prNumber}`,
},
})

Alert.alert(
"Branch Override Set",
`Temporarily switched to PR #${prNumber} branch while staying on "${currentChannel}" channel.\n\nClose and reopen the app to load the update.`,
[
{
text: "Reload Now",
onPress: () => Updates.reloadAsync(),
},
{
text: "Later",
style: "cancel",
},
],
)
} catch (error) {
captureErrorWithToast(
new GenericError({
error,
additionalMessage: "Error switching to PR branch",
}),
{ message: "Failed to switch to PR branch" },
)
}
},
},
],
"plain-text",
)
},
"Reset Branch Override": async () => {
try {
await Updates.setUpdateURLAndRequestHeadersOverride({
updateUrl: "https://u.expo.dev/f9089dfa-8871-4aff-93ea-da08af0370d2",
requestHeaders: {
"expo-channel-name": currentChannel,
},
})

Alert.alert(
"Override Reset",
`Reset to default "${currentChannel}" channel behavior.\n\nClose and reopen the app to apply.`,
[
{
text: "Reload Now",
onPress: () => Updates.reloadAsync(),
},
{
text: "Later",
style: "cancel",
},
],
)
} catch (error) {
captureErrorWithToast(
new GenericError({
error,
additionalMessage: "Error resetting branch override",
}),
{ message: "Failed to reset branch override" },
)
}
},
}
: {}),
"Check for Updates": async () => {
try {
const update = await Updates.checkForUpdateAsync()
if (update.isAvailable) {
Alert.alert(
"Update Available",
`A new update is available on the "${currentChannel}" channel.\n\nWould you like to download and install it?`,
[
{
text: "Cancel",
style: "cancel",
},
{
text: "Update",
onPress: async () => {
try {
const fetchResult = await Updates.fetchUpdateAsync()
if (fetchResult.isNew) {
await Updates.reloadAsync()
}
} catch (error) {
captureErrorWithToast(
new GenericError({
error,
additionalMessage: "Error fetching update",
}),
{ message: "Failed to fetch update" },
)
}
},
},
],
)
} else {
Alert.alert(
"No Updates",
`No new updates available on the "${currentChannel}" channel.`,
)
}
} catch (error) {
captureErrorWithToast(
new GenericError({
error,
additionalMessage: "Error checking for updates",
}),
{ message: "Failed to check for updates" },
)
}
},
Cancel: undefined,
}

const options = Object.keys(updatesMethods)

showActionSheet({
options: {
title: `Updates Debug (${currentEnv.toUpperCase()})`,
options,
cancelButtonIndex: options.indexOf("Cancel"),
},
callback: async (selectedIndex?: number) => {
if (selectedIndex === undefined) {
return
}
const method = updatesMethods[options[selectedIndex] as keyof typeof updatesMethods]
if (method) {
try {
await method()
} catch (error) {
captureError(new GenericError({ error, additionalMessage: "Error in Updates menu" }))
}
}
},
})
}, [currentlyRunning])

const primaryMethods = useMemo(() => {
return {
Logout: async () => {
Expand Down Expand Up @@ -1207,9 +1424,18 @@ function useShowDebugMenu() {
"Notifications Menu": () => showNotificationsMenu(),
"Logs Menu": () => showLogsMenu(),
"XMTP Menu": () => showXmtpMenu(),
"Updates Menu": () => showUpdatesMenu(),
Cancel: undefined,
}
}, [logout, currentlyRunning, showLogsMenu, showNotificationsMenu, showXmtpMenu, showCacheMenu])
}, [
logout,
currentlyRunning,
showLogsMenu,
showNotificationsMenu,
showXmtpMenu,
showCacheMenu,
showUpdatesMenu,
])

const showDebugMenu = useCallback(() => {
const options = Object.keys(primaryMethods)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ const conversationMessagesInfiniteQueryFn = async (
direction: "next",
}

const isFirstPage = !cursorNs

const resolvedLimit = argLimit || DEFAULT_PAGE_SIZE

if (!clientInboxId) {
Expand All @@ -84,11 +86,13 @@ const conversationMessagesInfiniteQueryFn = async (
throw new Error("xmtpConversationId is required")
}

await syncOneXmtpConversation({
clientInboxId,
xmtpConversationId,
caller: "conversationMessagesInfiniteQueryFn",
})
if (isFirstPage) {
await syncOneXmtpConversation({
clientInboxId,
xmtpConversationId,
caller: "conversationMessagesInfiniteQueryFn",
})
}

const disappearingMessagesSettings = await ensureDisappearingMessageSettings({
clientInboxId,
Expand Down Expand Up @@ -117,7 +121,7 @@ const conversationMessagesInfiniteQueryFn = async (
let combinedMessagesForPage: IConversationMessage[] = [...convosMessagesFromServer]

// Only if we're fetching the first page
if (direction === "next" && !cursorNs) {
if (isFirstPage) {
const currentInfiniteData = getConversationMessagesInfiniteQueryData({
clientInboxId,
xmtpConversationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,11 @@ const ConversationMessagesListItem = memo(function ConversationMessagesListItem(
nextMessage={nextMessage ?? undefined}
>
<ConversationNewMessageAnimationWrapper
animateEntering={isNewestMessage && message.senderInboxId === currentSender.inboxId}
animateEntering={
isNewestMessage &&
message.senderInboxId === currentSender.inboxId &&
message.status === "sending"
}
>
<ConversationMessageTimestamp />
<ConversationMessageRepliableWrapper messageType={message.type}>
Expand Down
Loading