Skip to content

Commit

Permalink
Merge pull request #695 from Stremio/refactor/platform-device
Browse files Browse the repository at this point in the history
refactor: platform device logic
  • Loading branch information
tymmesyde authored Sep 27, 2024
2 parents d474ec6 + 0a2ad7b commit 3a9646c
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 50 deletions.
49 changes: 4 additions & 45 deletions src/common/Platform/Platform.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { createContext, useContext } from 'react';
import { WHITELISTED_HOSTS } from 'stremio/common/CONSTANTS';
import useShell from './useShell';
import Bowser from 'bowser';
import { name, isMobile } from './device';

interface PlatformContext {
name: string;
isMobile: () => boolean;
isMobile: boolean;
openExternal: (url: string) => void;
}

Expand All @@ -18,52 +18,11 @@ type Props = {
const PlatformProvider = ({ children }: Props) => {
const shell = useShell();

// this detects ipad properly in safari
// while bowser does not
const iOS = () => {
return (
[
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod',
].includes(navigator.platform) ||
(navigator.userAgent.includes('Mac') && 'ontouchend' in document)
);
};

// Edge case: iPad is included in this function
// Keep in mind maxTouchPoints for Vision Pro might change in the future
const isVisionProUser = () => {
const isMacintosh = navigator.userAgent.includes('Macintosh');
const hasFiveTouchPoints = navigator.maxTouchPoints === 5;
return isMacintosh && hasFiveTouchPoints;
};

const browser = Bowser.getParser(window.navigator?.userAgent || '');
const osName = browser.getOSName().toLowerCase();

const name = isVisionProUser()
? 'visionos'
: iOS()
? 'ios'
: osName || 'unknown';

const isMobile = () => {
return name === 'ios' || name === 'android';
};

const openExternal = (url: string) => {
try {
const { hostname } = new URL(url);
const isWhitelisted = WHITELISTED_HOSTS.some((host: string) =>
hostname.endsWith(host)
);
const finalUrl = !isWhitelisted
? 'https://www.stremio.com/warning#' + encodeURIComponent(url)
: url;
const isWhitelisted = WHITELISTED_HOSTS.some((host: string) => hostname.endsWith(host));
const finalUrl = !isWhitelisted ? `https://www.stremio.com/warning#${encodeURIComponent(url)}` : url;

if (shell.active) {
shell.send('open-external', finalUrl);
Expand Down
31 changes: 31 additions & 0 deletions src/common/Platform/device.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Bowser from 'bowser';

const APPLE_MOBILE_DEVICES = [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod',
];

const { userAgent, platform, maxTouchPoints } = globalThis.navigator;

// this detects ipad properly in safari
// while bowser does not
const isIOS = APPLE_MOBILE_DEVICES.includes(platform) || (userAgent.includes('Mac') && 'ontouchend' in document);

// Edge case: iPad is included in this function
// Keep in mind maxTouchPoints for Vision Pro might change in the future
const isVisionOS = userAgent.includes('Macintosh') || maxTouchPoints === 5;

const bowser = Bowser.getParser(userAgent);
const os = bowser.getOSName().toLowerCase();

const name = isVisionOS ? 'visionos' : isIOS ? 'ios' : os || 'unknown';
const isMobile = ['ios', 'android'].includes(name);

export {
name,
isMobile,
};
2 changes: 0 additions & 2 deletions src/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ const useProfile = require('./useProfile');
const useStreamingServer = require('./useStreamingServer');
const useTorrent = require('./useTorrent');
const useTranslate = require('./useTranslate');
const platform = require('./platform');
const EventModal = require('./EventModal');

module.exports = {
Expand Down Expand Up @@ -101,6 +100,5 @@ module.exports = {
useStreamingServer,
useTorrent,
useTranslate,
platform,
EventModal,
};
3 changes: 2 additions & 1 deletion src/routes/MetaDetails/StreamsList/Stream/Stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const PropTypes = require('prop-types');
const classnames = require('classnames');
const { default: Icon } = require('@stremio/stremio-icons/react');
const { t } = require('i18next');
const { Button, Image, useProfile, platform, useToast, Popup, useBinaryState } = require('stremio/common');
const { Button, Image, useProfile, usePlatform, useToast, Popup, useBinaryState } = require('stremio/common');
const { useServices } = require('stremio/services');
const { useRouteFocused } = require('stremio-router');
const StreamPlaceholder = require('./StreamPlaceholder');
Expand All @@ -14,6 +14,7 @@ const styles = require('./styles');
const Stream = ({ className, videoId, videoReleased, addonName, name, description, thumbnail, progress, deepLinks, ...props }) => {
const profile = useProfile();
const toast = useToast();
const platform = usePlatform();
const { core } = useServices();
const routeFocused = useRouteFocused();

Expand Down
4 changes: 3 additions & 1 deletion src/routes/Settings/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ const Settings = () => {
}
}, [isTraktAuthenticated, profile.auth]);
const subscribeCalendarOnClick = React.useCallback(() => {
if (!profile.auth) return;

const protocol = platform.name === 'ios' ? 'webcal' : 'https';
const url = `${protocol}://www.strem.io/calendar/${profile.auth.user._id}.ics`;
platform.openExternal(url);
Expand All @@ -112,7 +114,7 @@ const Settings = () => {
timeout: 25000
});
// Stremio 4 emits not documented event subscribeCalendar
}, [profile.auth.user._id]);
}, [profile.auth]);
const exportDataOnClick = React.useCallback(() => {
loadDataExport();
}, []);
Expand Down
3 changes: 2 additions & 1 deletion src/routes/Settings/useProfileSettingsInputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
const React = require('react');
const { useTranslation } = require('react-i18next');
const { useServices } = require('stremio/services');
const { CONSTANTS, interfaceLanguages, languageNames, platform } = require('stremio/common');
const { CONSTANTS, usePlatform, interfaceLanguages, languageNames } = require('stremio/common');

const useProfileSettingsInputs = (profile) => {
const { t } = useTranslation();
const { core } = useServices();
const platform = usePlatform();
// TODO combine those useMemo in one
const interfaceLanguageSelect = React.useMemo(() => ({
options: interfaceLanguages.map(({ name, codes }) => ({
Expand Down

0 comments on commit 3a9646c

Please sign in to comment.