Skip to content

Commit 4f85b26

Browse files
author
jack.cowey
committed
Fix Trakt device code auth and MKV external player support
- Fixed MKV files not opening in external player in Electron app - Improved Trakt device code flow with automatic browser opening - Enhanced error handling for Trakt configuration - Reverted credential form UI, using .env configuration instead
1 parent ef0d363 commit 4f85b26

10 files changed

Lines changed: 1485 additions & 113 deletions

File tree

client/package-lock.json

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

client/src/pages/Onboarding.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@ const Onboarding = () => {
7878
setTraktVerifyUrl(data.verification_url || "");
7979
setTraktDeviceCode(data.device_code || "");
8080
try { await navigator.clipboard.writeText(data.user_code || ""); } catch {}
81-
if (data.verification_url && data.user_code) {
82-
window.open(`${data.verification_url}?code=${encodeURIComponent(data.user_code)}`, "_blank");
81+
// Always open browser with the verification URL and code
82+
if (data.verification_url) {
83+
const url = data.user_code
84+
? `${data.verification_url}?code=${encodeURIComponent(data.user_code)}`
85+
: data.verification_url;
86+
window.open(url, "_blank");
8387
}
8488
// start polling
8589
const expires = Date.now() + (Number(data.expires_in || 600) * 1000);

client/src/pages/Player.tsx

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,46 @@ const Player = () => {
5151

5252

5353

54+
// Helper function to check if a URL is an MKV file
55+
const isMkvFile = (url: string, filename?: string): boolean => {
56+
if (filename && filename.toLowerCase().endsWith('.mkv')) return true
57+
const urlLower = url.toLowerCase()
58+
// Check URL path for .mkv extension
59+
try {
60+
const urlObj = new URL(url.startsWith('/') ? `${window.location.origin}${url}` : url)
61+
if (urlObj.pathname.toLowerCase().endsWith('.mkv')) return true
62+
} catch {}
63+
// Fallback: check if URL contains .mkv
64+
return urlLower.includes('.mkv')
65+
}
66+
67+
// Helper function to check if we're in Electron
68+
const isElectron = (): boolean => {
69+
return typeof (window as any).electronAPI !== 'undefined'
70+
}
71+
72+
// Helper function to open external player
73+
const openExternalPlayer = async (url: string): Promise<boolean> => {
74+
if (!isElectron()) {
75+
console.log('Not in Electron, skipping external player')
76+
return false
77+
}
78+
try {
79+
const abs = url.startsWith('/') ? `${window.location.origin}${url}` : url
80+
const result = await (window as any).electronAPI?.openExternalPlayer(abs)
81+
if (result?.ok) {
82+
console.log(`Opened in external player: ${result.player}`)
83+
return true
84+
} else {
85+
console.error('Failed to open external player:', result?.error)
86+
return false
87+
}
88+
} catch (e) {
89+
console.error('Error opening external player:', e)
90+
return false
91+
}
92+
}
93+
5494
const pickSource = async (s: SourceItem) => {
5595
try {
5696
setResolvingId(s.id)
@@ -65,37 +105,45 @@ const Player = () => {
65105
if (r.status === 'ok' && r.directUrl) {
66106
setCompatibilityInfo(r)
67107

68-
// Handle MKV externally via system player (mpv/vlc)
69-
if (r.format === 'mkv_native' && r.directUrl.includes('/api/stream/')) {
70-
const abs = r.directUrl.startsWith('/') ? `${window.location.origin}${r.directUrl}` : r.directUrl
71-
// Ask main process to open the external player
72-
try { await (window as any).electronAPI?.openExternalPlayer(abs) } catch {}
73-
// Show overlay briefly before navigating home
74-
setExternalOpening(true)
75-
setTimeout(() => { navigate('/') }, 1500)
76-
return
77-
} else {
78-
setSelectedUrl(r.directUrl)
79-
setFallbackUrl(null)
80-
81-
// Show compatibility warning for other limited formats
82-
if (r.compatibility && r.compatibility.browserSupport === 'limited') {
83-
setShowCompatibilityAlert(true)
108+
// Handle MKV externally via system player (mpv/vlc) when in Electron
109+
// Check if it's an MKV file by format, filename, or URL
110+
const isMkv = r.format === 'mkv_native' ||
111+
isMkvFile(r.directUrl, r.filename) ||
112+
(r.compatibility?.format === 'mkv')
113+
114+
if (isMkv && isElectron()) {
115+
const opened = await openExternalPlayer(r.directUrl)
116+
if (opened) {
117+
// Show overlay briefly before navigating home
118+
setExternalOpening(true)
119+
setTimeout(() => { navigate('/') }, 1500)
120+
return
84121
}
122+
// If external player failed, fall through to try in-browser playback
123+
}
124+
125+
setSelectedUrl(r.directUrl)
126+
setFallbackUrl(r.fallbackUrl || null)
127+
128+
// Show compatibility warning for other limited formats
129+
if (r.compatibility && r.compatibility.browserSupport === 'limited') {
130+
setShowCompatibilityAlert(true)
85131
}
86132
} else {
87133
// Handle non-streamable response
88134
setVideoError(r.message || r.reason || 'This source cannot be streamed')
89135
setCompatibilityInfo(r)
90136
}
91137
} else {
92-
// Non-debrid direct link; if MKV, open externally
93-
if (s.url.toLowerCase().includes('.mkv')) {
94-
const abs = s.url.startsWith('/') ? `${window.location.origin}${s.url}` : s.url
95-
try { await (window as any).electronAPI?.openExternalPlayer(abs) } catch {}
96-
setExternalOpening(true)
97-
setTimeout(() => { navigate('/') }, 1500)
98-
return
138+
// Non-debrid direct link; if MKV and in Electron, open externally
139+
if (isMkvFile(s.url, s.name) && isElectron()) {
140+
const opened = await openExternalPlayer(s.url)
141+
if (opened) {
142+
setExternalOpening(true)
143+
setTimeout(() => { navigate('/') }, 1500)
144+
return
145+
}
146+
// If external player failed, fall through to try in-browser playback
99147
}
100148
setSelectedUrl(s.url)
101149
}

0 commit comments

Comments
 (0)