Skip to content

Commit 8e00571

Browse files
authored
feat(web): add IINA support and refine Apple players options (#626)
* feat: add IINA support for macOS in torrent player options - introduce a new setting for IINA in the MobileAppSettings component, allowing users to toggle its usage - update the DialogTorrentDetailsContent Table component to conditionally display an IINA button for macOS users. - add corresponding translations for IINA prompts in multiple languages - implement a utility function to detect macOS for better compatibility Signed-off-by: Pavel Pikta <devops@pavelpikta.com> * feat: enhance Apple device detection and update settings for Infuse usage - add isAppleDevice utility function to detect Apple devices (macOS and iOS) - update DialogTorrentDetailsContent Table component to conditionally show Infuse button for Apple users - modify MobileAppSettings to display Infuse toggle only for Apple devices Signed-off-by: Pavel Pikta <devops@pavelpikta.com> --------- Signed-off-by: Pavel Pikta <devops@pavelpikta.com>
1 parent 59fc9d1 commit 8e00571

File tree

11 files changed

+100
-11
lines changed

11 files changed

+100
-11
lines changed

web/src/components/DialogTorrentDetailsContent/Table/index.jsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { streamHost } from 'utils/Hosts'
22
import isEqual from 'lodash/isEqual'
3-
import { humanizeSize, detectStandaloneApp } from 'utils/Utils'
3+
import { humanizeSize, detectStandaloneApp, isMacOS, isAppleDevice } from 'utils/Utils'
44
import ptt from 'parse-torrent-title'
55
import { Button } from '@material-ui/core'
66
import CopyToClipboard from 'react-copy-to-clipboard'
@@ -32,8 +32,11 @@ const Table = memo(
3232

3333
const isVlcUsed = JSON.parse(localStorage.getItem('isVlcUsed')) ?? false
3434
const isInfuseUsed = JSON.parse(localStorage.getItem('isInfuseUsed')) ?? false
35+
const isIinaUsed = JSON.parse(localStorage.getItem('isIinaUsed')) ?? false
3536
const isStandalone = detectStandaloneApp()
36-
const shouldShowOpenLink = !isStandalone || (!isInfuseUsed && !isVlcUsed)
37+
const isMac = isMacOS()
38+
const isApple = isAppleDevice()
39+
const shouldShowOpenLink = !isStandalone || (!(isApple && isInfuseUsed) && !isVlcUsed && !(isMac && isIinaUsed))
3740

3841
return !playableFileList?.length ? (
3942
'No playable files in this torrent'
@@ -59,6 +62,7 @@ const Table = memo(
5962
const link = getFileLink(path, id)
6063
const fullLink = new URL(link, window.location.href)
6164
const infuseLink = `infuse://x-callback-url/play?url=${encodeURIComponent(fullLink)}`
65+
const iinaLink = `iina://weblink?url=${encodeURIComponent(fullLink)}`
6266

6367
return (
6468
(season === selectedSeason || !seasonAmount?.length) && (
@@ -74,7 +78,7 @@ const Table = memo(
7478
<Button onClick={() => preloadBuffer(id)} variant='outlined' color='primary' size='small'>
7579
{t('Preload')}
7680
</Button>
77-
{isStandalone && isInfuseUsed && (
81+
{isStandalone && isApple && isInfuseUsed && (
7882
<a style={{ textDecoration: 'none' }} href={infuseLink}>
7983
<Button style={{ width: '100%' }} variant='outlined' color='primary' size='small'>
8084
{t('Infuse')}
@@ -88,6 +92,13 @@ const Table = memo(
8892
</Button>
8993
</a>
9094
)}
95+
{isStandalone && isMac && isIinaUsed && (
96+
<a style={{ textDecoration: 'none' }} href={iinaLink}>
97+
<Button style={{ width: '100%' }} variant='outlined' color='primary' size='small'>
98+
IINA
99+
</Button>
100+
</a>
101+
)}
91102
{isSupported ? (
92103
<VideoPlayer title={title} videoSrc={link} onNotSupported={() => setIsSupported(false)} />
93104
) : (
@@ -127,6 +138,7 @@ const Table = memo(
127138
const link = getFileLink(path, id)
128139
const fullLink = new URL(link, window.location.href)
129140
const infuseLink = `infuse://x-callback-url/play?url=${encodeURIComponent(fullLink)}`
141+
const iinaLink = `iina://weblink?url=${encodeURIComponent(fullLink)}`
130142

131143
return (
132144
(season === selectedSeason || !seasonAmount?.length) && (
@@ -169,7 +181,7 @@ const Table = memo(
169181
{t('Preload')}
170182
</Button>
171183

172-
{isStandalone && isInfuseUsed && (
184+
{isStandalone && isApple && isInfuseUsed && (
173185
<a style={{ textDecoration: 'none' }} href={infuseLink}>
174186
<Button style={{ width: '100%' }} variant='outlined' color='primary' size='small'>
175187
{t('Infuse')}
@@ -185,6 +197,14 @@ const Table = memo(
185197
</a>
186198
)}
187199

200+
{isStandalone && isMac && isIinaUsed && (
201+
<a style={{ textDecoration: 'none' }} href={iinaLink}>
202+
<Button style={{ width: '100%' }} variant='outlined' color='primary' size='small'>
203+
IINA
204+
</Button>
205+
</a>
206+
)}
207+
188208
{shouldShowOpenLink && (
189209
<a style={{ textDecoration: 'none' }} href={link} target='_blank' rel='noreferrer'>
190210
<Button style={{ width: '100%' }} variant='outlined' color='primary' size='small'>

web/src/components/Settings/MobileAppSettings.jsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
import { FormControlLabel, FormGroup, FormHelperText, Switch } from '@material-ui/core'
2+
import { isMacOS, isAppleDevice } from 'utils/Utils'
23
import { useTranslation } from 'react-i18next'
34

45
import { SecondarySettingsContent, SettingSectionLabel } from './style'
56

6-
export default function MobileAppSettings({ isVlcUsed, setIsVlcUsed, isInfuseUsed, setIsInfuseUsed }) {
7+
export default function MobileAppSettings({
8+
isVlcUsed,
9+
setIsVlcUsed,
10+
isInfuseUsed,
11+
setIsInfuseUsed,
12+
isIinaUsed,
13+
setIsIinaUsed,
14+
}) {
715
const { t } = useTranslation()
16+
const isMac = isMacOS()
17+
const isApple = isAppleDevice()
818

919
return (
1020
<SecondarySettingsContent>
@@ -16,12 +26,28 @@ export default function MobileAppSettings({ isVlcUsed, setIsVlcUsed, isInfuseUse
1626
labelPlacement='start'
1727
/>
1828
<FormHelperText margin='none'>{t('SettingsDialog.UseVLCHint')}</FormHelperText>
19-
<FormControlLabel
20-
control={<Switch checked={isInfuseUsed} onChange={() => setIsInfuseUsed(prev => !prev)} color='secondary' />}
21-
label={t('SettingsDialog.UseInfuse')}
22-
labelPlacement='start'
23-
/>
24-
<FormHelperText margin='none'>{t('SettingsDialog.UseInfuseHint')}</FormHelperText>
29+
{isApple && (
30+
<>
31+
<FormControlLabel
32+
control={
33+
<Switch checked={isInfuseUsed} onChange={() => setIsInfuseUsed(prev => !prev)} color='secondary' />
34+
}
35+
label={t('SettingsDialog.UseInfuse')}
36+
labelPlacement='start'
37+
/>
38+
<FormHelperText margin='none'>{t('SettingsDialog.UseInfuseHint')}</FormHelperText>
39+
</>
40+
)}
41+
{isMac && (
42+
<>
43+
<FormControlLabel
44+
control={<Switch checked={isIinaUsed} onChange={() => setIsIinaUsed(prev => !prev)} color='secondary' />}
45+
label={t('SettingsDialog.UseIINA')}
46+
labelPlacement='start'
47+
/>
48+
<FormHelperText margin='none'>{t('SettingsDialog.UseIINAHint')}</FormHelperText>
49+
</>
50+
)}
2551
</FormGroup>
2652
</SecondarySettingsContent>
2753
)

web/src/components/Settings/SettingsDialog.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default function SettingsDialog({ handleClose }) {
3535
const [isProMode, setIsProMode] = useState(JSON.parse(localStorage.getItem('isProMode')) || false)
3636
const [isVlcUsed, setIsVlcUsed] = useState(JSON.parse(localStorage.getItem('isVlcUsed')) ?? false)
3737
const [isInfuseUsed, setIsInfuseUsed] = useState(JSON.parse(localStorage.getItem('isInfuseUsed')) ?? false)
38+
const [isIinaUsed, setIsIinaUsed] = useState(JSON.parse(localStorage.getItem('isIinaUsed')) ?? false)
3839

3940
useEffect(() => {
4041
axios.post(settingsHost(), { action: 'get' }).then(({ data }) => {
@@ -53,6 +54,7 @@ export default function SettingsDialog({ handleClose }) {
5354
axios.post(settingsHost(), { action: 'set', sets })
5455
localStorage.setItem('isVlcUsed', isVlcUsed)
5556
localStorage.setItem('isInfuseUsed', isInfuseUsed)
57+
localStorage.setItem('isIinaUsed', isIinaUsed)
5658
}
5759

5860
const inputForm = ({ target: { type, value, checked, id } }) => {
@@ -177,6 +179,8 @@ export default function SettingsDialog({ handleClose }) {
177179
setIsVlcUsed={setIsVlcUsed}
178180
isInfuseUsed={isInfuseUsed}
179181
setIsInfuseUsed={setIsInfuseUsed}
182+
isIinaUsed={isIinaUsed}
183+
setIsIinaUsed={setIsIinaUsed}
180184
/>
181185
</TabPanel>
182186
)}

web/src/locales/bg/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UseVLCHint": "Добави бутон към VLC плеъра за списъка с торенти",
201201
"UseInfuse": "Подкана за отваряне на видео в Infuse",
202202
"UseInfuseHint": "Добави бутон към Infuse плеъра за списъка с торенти",
203+
"UseIINA": "Подкана за отваряне на видео в IINA",
204+
"UseIINAHint": "Добави бутон към IINA плеъра за списъка с торенти (само macOS)",
203205
"ViewedHistoryStorage": "Съхранение на историята на прегледите:",
204206
"ViewedStorageHint": "Изберете къде да съхранявате историята на прегледите"
205207
},

web/src/locales/en/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UseInfuseHint": "Add Infuse player button to torrent content list",
201201
"UseVLC": "Prompt to open video in VLC",
202202
"UseVLCHint": "Add VLC player button to torrent content list",
203+
"UseIINA": "Prompt to open video in IINA",
204+
"UseIINAHint": "Add IINA player button to torrent content list (macOS only)",
203205
"ViewedHistoryStorage": "Viewed History Storage:",
204206
"ViewedStorageHint": "Choose where to store viewed history"
205207
},

web/src/locales/fr/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@
199199
"UseInfuseHint": "Ajouter un bouton de lecteur Infuse à la liste de contenu du torrent",
200200
"UseVLC": "Demander d'ouvrir la vidéo dans VLC",
201201
"UseVLCHint": "Ajouter un bouton de lecteur VLC à la liste de contenu du torrent",
202+
"UseIINA": "Demander d'ouvrir la vidéo dans IINA",
203+
"UseIINAHint": "Ajouter un bouton de lecteur IINA à la liste de contenu du torrent (macOS uniquement)",
202204
"ViewedHistoryStorage": "Stockage de l'historique des vues :",
203205
"ViewedStorageHint": "Choisissez où stocker l'historique des vues"
204206
},

web/src/locales/ro/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UseInfuseHint": "Adăugați butonul Infuse player la lista de conținut torrent",
201201
"UseVLC": "Solicitare pentru deschiderea videoclipului în VLC",
202202
"UseVLCHint": "Adăugați butonul VLC player la lista de conținut torrent",
203+
"UseIINA": "Solicitare pentru deschiderea videoclipului în IINA",
204+
"UseIINAHint": "Adăugați butonul IINA player la lista de conținut torrent (doar macOS)",
203205
"ViewedHistoryStorage": "Istoricul vizualizărilor stocate:",
204206
"ViewedStorageHint": "Alegeți unde să stocați istoricul vizualizat"
205207
},

web/src/locales/ru/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UseInfuseHint": "Добавить кнопку проигрывателя Infuse в список торрент-контента",
201201
"UseVLC": "Предлагать открыть видео в VLC",
202202
"UseVLCHint": "Добавить кнопку проигрывателя VLC в список торрент-контента",
203+
"UseIINA": "Предлагать открыть видео в IINA",
204+
"UseIINAHint": "Добавить кнопку проигрывателя IINA в список торрент-контента (только macOS)",
203205
"ViewedHistoryStorage": "Хранилище истории просмотров:",
204206
"ViewedStorageHint": "Выберите, где хранить историю просмотренного."
205207
},

web/src/locales/ua/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UseInfuseHint": "Додати кнопку програвача Infuse до списку торрент-контенту",
201201
"UseVLC": "Пропонувати відкрити відео у VLC",
202202
"UseVLCHint": "Додати кнопку програвача VLC до списку торрент-контенту",
203+
"UseIINA": "Пропонувати відкрити відео в IINA",
204+
"UseIINAHint": "Додати кнопку програвача IINA до списку торрент-контенту (тільки macOS)",
203205
"ViewedHistoryStorage": "Збереження історії переглядів:",
204206
"ViewedStorageHint": "Виберіть місце збереження історії переглядів серій"
205207
},

web/src/locales/zh/translation.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UseInfuseHint": "将 Infuse 播放器按钮添加到种子内容列表",
201201
"UseVLC": "提示在VLC中打开视频",
202202
"UseVLCHint": "将VLC播放器按钮添加到种子内容列表",
203+
"UseIINA": "提示在 IINA 中打开视频",
204+
"UseIINAHint": "将 IINA 播放器按钮添加到种子内容列表(仅 macOS)",
203205
"ViewedHistoryStorage": "查看历史存储:",
204206
"ViewedStorageHint": "存储查看历史记录的位置"
205207
},

0 commit comments

Comments
 (0)