diff --git a/src/background/messages/hello.ts b/src/background/messages/hello.ts index 1381b6b..84a8489 100644 --- a/src/background/messages/hello.ts +++ b/src/background/messages/hello.ts @@ -1,5 +1,6 @@ import type { PlasmoMessaging } from '@plasmohq/messaging'; +import { hasPermission } from '~hooks/usePermission'; import { getVersion } from '~hooks/useVersion'; import type { BaseRequest } from '~types/request'; import type { BaseResponse } from '~types/response'; @@ -8,16 +9,17 @@ import { isDomainWhitelisted } from '~utils/storage'; type Response = BaseResponse<{ version: string; allowed: boolean; + hasPermission: boolean; }>; const handler: PlasmoMessaging.MessageHandler = async (req, res) => { try { const version = getVersion(); - res.send({ success: true, version, allowed: await isDomainWhitelisted(req.sender.tab.url), + hasPermission: await hasPermission(), }); } catch (err) { res.send({ diff --git a/src/background/messages/openPage.ts b/src/background/messages/openPage.ts new file mode 100644 index 0000000..3b69788 --- /dev/null +++ b/src/background/messages/openPage.ts @@ -0,0 +1,37 @@ +import type { PlasmoMessaging } from '@plasmohq/messaging'; + +import type { BaseRequest } from '~types/request'; +import type { BaseResponse } from '~types/response'; +import { isChrome } from '~utils/extension'; + +type Request = BaseRequest & { + page: string; + redirectUrl: string; +}; + +const handler: PlasmoMessaging.MessageHandler = async (req, res) => { + try { + const searchParams = new URLSearchParams(); + searchParams.set('redirectUrl', req.body.redirectUrl); + const url = (chrome || browser).runtime.getURL(`/tabs/${req.body.page}.html?${searchParams.toString()}`); + + if (isChrome()) { + await chrome.tabs.update(req.sender.tab.id, { + url, + }); + } else { + await browser.tabs.update(req.sender.tab.id, { url }); + } + + res.send({ + success: true, + }); + } catch (err) { + res.send({ + success: false, + error: err.message, + }); + } +}; + +export default handler; diff --git a/src/contents/movie-web.ts b/src/contents/movie-web.ts index 051db48..aeddda5 100644 --- a/src/contents/movie-web.ts +++ b/src/contents/movie-web.ts @@ -16,3 +16,7 @@ relayMessage({ relayMessage({ name: 'prepareStream', }); + +relayMessage({ + name: 'openPage', +}); diff --git a/src/hooks/usePermission.ts b/src/hooks/usePermission.ts new file mode 100644 index 0000000..a6a4e42 --- /dev/null +++ b/src/hooks/usePermission.ts @@ -0,0 +1,28 @@ +import { useEffect, useState } from 'react'; + +export async function hasPermission() { + return chrome.permissions.contains({ + origins: [''], + }); +} + +export function usePermission() { + const [permission, setPermission] = useState(false); + + const grantPermission = async () => { + const granted = await chrome.permissions.request({ + origins: [''], + }); + setPermission(granted); + return granted; + }; + + useEffect(() => { + hasPermission().then((has) => setPermission(has)); + }, []); + + return { + hasPermission: permission, + grantPermission, + }; +} diff --git a/src/tabs/PermissionGrant.css b/src/tabs/PermissionGrant.css new file mode 100644 index 0000000..df25203 --- /dev/null +++ b/src/tabs/PermissionGrant.css @@ -0,0 +1,103 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap'); + +* { + margin: 0; + padding: 0; +} + +html { + height: 100%; +} + +body { + height: 100%; + max-height: 100%; + font-family: 'Inter', sans-serif; +} + +#__plasmo { + height: 100%; + background-color: #0a0a10; +} + +.container { + height: 100%; + width: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.inner-container { + width: 400px; + display: flex; + flex-direction: column; + gap: 1rem; +} + +.permission-card { + display: flex; + align-items: center; + justify-content: center; + background-color: #0f0f1b; + border-radius: 10px; + height: 125px; + padding-right: 40px; + padding-left: 40px; + font-size: 14px; + border: 1px solid #20202d; +} + +.footer { + display: flex; +} + +.color-white { + color: #ffffff; +} + +.text-color { + color: #73739d; +} + +.go-back-btn, +.grant-permission-btn { + color: #ffffff; + padding: 10px 20px; + border-radius: 10px; + border: 1px solid #0000; + cursor: pointer; + font-size: 14px; +} + +.go-back-btn { + background: + linear-gradient(to right, #151522, #181b2a) padding-box, + linear-gradient(50deg, #151522, #181b2a, #456b95) border-box; +} + +.grant-permission-btn { + background: + linear-gradient(to right, #482179, #8a39e6) padding-box, + linear-gradient(50deg, #482179, #4f3585, #b79ae0) border-box; +} + +.go-back-btn:hover { + background: + linear-gradient(to right, #2a334e, #2f3552) padding-box, + linear-gradient(50deg, #2a334e, #2f3552, #6086b7) border-box; +} + +.grant-permission-btn:hover { + background: + linear-gradient(to right, #603a9a, #a25ff5) padding-box, + linear-gradient(50deg, #603a9a, #653c9f, #d9aef1) border-box; +} + +.grant-permission-btn:disabled { + background: + linear-gradient(to right, #311e4b, #6b4b99) padding-box, + linear-gradient(50deg, #311e4b, #3b265b, #704fa5) border-box; + cursor: not-allowed; + opacity: 0.5; +} diff --git a/src/tabs/PermissionGrant.tsx b/src/tabs/PermissionGrant.tsx new file mode 100644 index 0000000..c7c2867 --- /dev/null +++ b/src/tabs/PermissionGrant.tsx @@ -0,0 +1,49 @@ +import { usePermission } from '~hooks/usePermission'; + +import './PermissionGrant.css'; + +export default function PermissionGrant() { + const { hasPermission, grantPermission } = usePermission(); + + const queryParams = new URLSearchParams(window.location.search); + const redirectUrl = queryParams.get('redirectUrl') ?? 'https://movie-web.app'; + const domain = new URL(redirectUrl).hostname; + + const handleGrantPermission = () => { + grantPermission().then(() => { + chrome.tabs.getCurrent((tab) => { + chrome.tabs.update(tab.id, { url: queryParams.get('redirectUrl') ?? 'https://movie-web.app' }); + }); + }); + }; + + return ( +
+
+

Permission

+

+ Websites need to ask for permission
before they can use this extension +

+
+

+ The website {domain} wants to
use the extension on their page. +

+
+
+ +
+ +
+
+
+ ); +}