Skip to content

Commit 1acdf79

Browse files
committed
Merge pull request #176 from taylorcox75/claude/fix-cold-launch-torrent-toast-175
Fix spurious couldnt read torrent file" toast on cold launch"
1 parent cb7c170 commit 1acdf79

3 files changed

Lines changed: 43 additions & 26 deletions

File tree

app/_layout.tsx

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ function StackNavigator() {
155155
});
156156
};
157157

158-
const dispatchDeepLink = async (incomingUrl?: string | null) => {
158+
const dispatchDeepLink = async (
159+
incomingUrl?: string | null,
160+
opts: { silentFailure?: boolean } = {},
161+
): Promise<boolean> => {
159162
const magnetLink = extractMagnetLink(incomingUrl);
160163
if (magnetLink) {
161164
const now = Date.now();
@@ -164,28 +167,28 @@ function StackNavigator() {
164167
lastHandledMagnetRef.current.value === magnetLink &&
165168
now - lastHandledMagnetRef.current.at < 1500
166169
) {
167-
return;
170+
return true;
168171
}
169172
lastHandledMagnetRef.current = { value: magnetLink, at: now };
170173

171174
if (!rootNavReadyRef.current) {
172175
pendingDeepLinkRef.current = { type: 'magnet', value: magnetLink };
173-
return;
176+
return true;
174177
}
175178
navigateToMagnet(magnetLink);
176-
return;
179+
return true;
177180
}
178181

179182
const rawTorrentFile = extractTorrentFile(incomingUrl);
180-
if (!rawTorrentFile) return;
183+
if (!rawTorrentFile) return false;
181184

182185
const now = Date.now();
183186
if (
184187
lastHandledTorrentFileRef.current &&
185188
lastHandledTorrentFileRef.current.value === rawTorrentFile.uri &&
186189
now - lastHandledTorrentFileRef.current.at < 1500
187190
) {
188-
return;
191+
return true;
189192
}
190193
lastHandledTorrentFileRef.current = { value: rawTorrentFile.uri, at: now };
191194

@@ -201,15 +204,18 @@ function StackNavigator() {
201204
const torrentFile = await persistIncomingTorrentFile(rawTorrentFile);
202205
if (!torrentFile) {
203206
clogWarn('LINK', `Could not read incoming .torrent: ${rawTorrentFile.uri}`);
204-
showToast(t('errors.couldNotReadTorrentFile'), 'error');
205-
return;
207+
if (!opts.silentFailure) {
208+
showToast(t('errors.couldNotReadTorrentFile'), 'error');
209+
}
210+
return false;
206211
}
207212

208213
if (!rootNavReadyRef.current) {
209214
pendingDeepLinkRef.current = { type: 'torrentFile', value: torrentFile };
210-
return;
215+
return true;
211216
}
212217
navigateToTorrentFile(torrentFile);
218+
return true;
213219
};
214220

215221
const subscription = Linking.addEventListener('url', ({ url }) => {
@@ -222,26 +228,35 @@ function StackNavigator() {
222228
// Two independent sources for the cold-launch URL, because neither is
223229
// reliable alone on iOS here:
224230
// - expo-linking's getLinkingURL() reads a native registry populated
225-
// by the "open url" AppDelegate callback (the one our
226-
// withNativeTorrentFileCopy patch rewrites to an app-owned copy).
231+
// by the "open url" AppDelegate callback, which can still carry the
232+
// original security-scoped file:// URI whose access has already
233+
// lapsed by the time JS reads it.
227234
// - RN core's Linking.getInitialURL() reads bridge.launchOptions,
228-
// which the New Architecture may not populate.
229-
// Try both: dispatchDeepLink de-dupes by URL, so whichever arrives
230-
// first wins and the other is a no-op. Do NOT reduce this to one
235+
// which our withNativeTorrentFileCopy patch rewrites to an
236+
// app-owned copy of an incoming .torrent — but the New Architecture
237+
// may not populate it at all.
238+
// Try the RN source first and only fall back to expo-linking's URL —
239+
// silently — when the two disagree, so a stale/expired scoped URI from
240+
// one source doesn't flash a failure toast right before the other
241+
// source's valid copy succeeds (#175). Do NOT reduce this to one
231242
// source without testing a real cold launch — cold-launch "Open In"
232243
// has regressed repeatedly on exactly this code path.
233-
const expoUrl = ExpoLinking.getLinkingURL();
234-
clogInfo('LINK', `Cold-launch expo-linking URL: ${expoUrl ?? '(none)'}`);
235-
void dispatchDeepLink(expoUrl);
244+
void (async () => {
245+
const [expoUrl, rnUrl] = await Promise.all([
246+
Promise.resolve(ExpoLinking.getLinkingURL()),
247+
Linking.getInitialURL().catch(() => null),
248+
]);
249+
clogInfo('LINK', `Cold-launch expo-linking URL: ${expoUrl ?? '(none)'}`);
250+
clogInfo('LINK', `Cold-launch RN URL: ${rnUrl ?? '(none)'}`);
236251

237-
Linking.getInitialURL()
238-
.then((rnUrl) => {
239-
clogInfo('LINK', `Cold-launch RN URL: ${rnUrl ?? '(none)'}`);
240-
return dispatchDeepLink(rnUrl);
241-
})
242-
.catch(() => {
243-
// No initial URL — safe to ignore.
244-
});
252+
const hasDistinctFallback = !!expoUrl && expoUrl !== rnUrl;
253+
const handled = rnUrl
254+
? await dispatchDeepLink(rnUrl, { silentFailure: hasDistinctFallback })
255+
: false;
256+
if (!handled && hasDistinctFallback) {
257+
await dispatchDeepLink(expoUrl);
258+
}
259+
})();
245260
}
246261

247262
if (pendingDeepLinkRef.current) {

constants/changelog.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ export const CHANGELOG: ChangelogRelease[] = [
3333
{
3434
title: 'Bugs Fixed',
3535
items: [
36-
'Fixed Transfer tab speed numbers getting cut off at higher speeds',
36+
'Fixed a false "couldn\'t read torrent file" error that could briefly flash when opening a .torrent file from a cold launch',
37+
'Fixed Transfer tab speed numbers getting cut off at higher speeds',
3738
'Fixed per-torrent speed limits sometimes applying the wrong units',
3839
'Fixed torrent cards showing "unlimited" for a ratio limit that actually follows the global limit',
3940
'Fixed the folder-path autocomplete list clipping suggestions instead of scrolling to them',

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)