diff --git a/assets/inter/OFL.txt b/assets/inter/OFL.txt new file mode 100644 index 0000000..63db4fa --- /dev/null +++ b/assets/inter/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/inter/bold.ttf b/assets/inter/bold.ttf new file mode 100644 index 0000000..fe23eeb Binary files /dev/null and b/assets/inter/bold.ttf differ diff --git a/assets/inter/regular.ttf b/assets/inter/regular.ttf new file mode 100644 index 0000000..5e4851f Binary files /dev/null and b/assets/inter/regular.ttf differ diff --git a/package.json b/package.json index e17da76..4c2fd1a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@movie-web/extension", "displayName": "movie-web extension", - "version": "1.0.3", + "version": "1.1.0", "description": "Enhance your movie-web experience with just one click", "author": "movie-web", "scripts": { @@ -44,13 +44,11 @@ "manifest": { "permissions": [ "declarativeNetRequest", - "tabs", + "activeTab", "cookies" ], - "host_permissions": [ - "", - "https://dev.movie-web.app/*", - "https://movie-web.app/*" + "optional_host_permissions": [ + "" ], "browser_specific_settings": { "gecko": { diff --git a/src/Popup.css b/src/Popup.css index ee5b928..ecfa447 100644 --- a/src/Popup.css +++ b/src/Popup.css @@ -1,15 +1,17 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap'); +@import url("./font.css"); html { min-height: 300px; min-width: 300px; + height: 100%; } body { min-height: 300px; min-width: 300px; margin: 0; - font-family: 'Inter', sans-serif; + height: 100%; + max-height: 100%; } .popup { @@ -19,3 +21,8 @@ body { justify-content: center; align-items: center; } + +#__plasmo { + height: 100%; + background-color: #0a0a10; +} diff --git a/src/components/BottomLabel.css b/src/components/BottomLabel.css index 4d467bb..e41a00d 100644 --- a/src/components/BottomLabel.css +++ b/src/components/BottomLabel.css @@ -1,6 +1,6 @@ .bottom-label { position: absolute; - bottom: .25rem; + bottom: 1rem; display: flex; align-items: center; gap: .5rem; @@ -9,9 +9,18 @@ font-size: 14px; } +.top-right-label { + position: absolute; + right: 1rem; + top: 1rem; + font-weight: normal; + color: #4A4863; + font-size: 14px; +} + .dot { - width: 2px; - height: 2px; + width: 3px; + height: 3px; background: currentColor; border-radius: 100px; -} \ No newline at end of file +} diff --git a/src/components/BottomLabel.tsx b/src/components/BottomLabel.tsx index f18d227..a864998 100644 --- a/src/components/BottomLabel.tsx +++ b/src/components/BottomLabel.tsx @@ -12,3 +12,9 @@ export function BottomLabel() { ); } + +export function TopRightLabel() { + const version = useVersion({ prefixed: true }); + + return

{version}

; +} diff --git a/src/components/Button.css b/src/components/Button.css new file mode 100644 index 0000000..3916c91 --- /dev/null +++ b/src/components/Button.css @@ -0,0 +1,41 @@ +.button { + padding: 1rem; + border-radius: 12px; + border: 0; + font-size: 1rem; + text-align: center; + cursor: pointer; + transition: background-color 100ms ease-in-out, color 100ms ease-in-out, transform 100ms ease-in-out; +} + +.button.full { + width: 100%; +} + +.button, .button:focus, .button:active, .button:visited { + text-decoration: none; +} + +.button:active { + transform: scale(1.05); +} + +.button.button-secondary { + background-color: #222033; + color: white; +} + +.button.button-secondary:hover { + background-color: #2c2941; + color: white; +} + +.button.button-primary { + background-color: #4F328A; + color: white; +} + +.button.button-primary:hover { + background-color: #5E3F9D; + color: white; +} \ No newline at end of file diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..16cd148 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,27 @@ +import type { ReactNode } from 'react'; + +import './Button.css'; + +export interface ButtonProps { + type?: 'primary' | 'secondary'; + href?: string; + children?: ReactNode; + onClick?: () => void; + full?: boolean; + className?: string; +} + +export function Button(props: ButtonProps) { + const classes = `button button-${props.type ?? 'primary'} ${props.className ?? ''} ${props.full ? 'full' : ''}`; + if (props.href) + return ( + + {props.children} + + ); + return ( + + ); +} diff --git a/src/components/DisabledScreen.css b/src/components/DisabledScreen.css index 15648a7..626334e 100644 --- a/src/components/DisabledScreen.css +++ b/src/components/DisabledScreen.css @@ -5,11 +5,11 @@ font-size: 16px; } -.disabled svg { - display: block; - width: 1.5rem; - height: 1.5rem; - margin: 0 auto; +.disabled .icon { + font-size: 1.5rem; + margin-bottom: 1rem; + text-align: center; + display: inline-block; color: #B44868; } @@ -19,4 +19,4 @@ .disabled strong { color: white; -} \ No newline at end of file +} diff --git a/src/components/DisabledScreen.tsx b/src/components/DisabledScreen.tsx index 426e113..4f88747 100644 --- a/src/components/DisabledScreen.tsx +++ b/src/components/DisabledScreen.tsx @@ -4,7 +4,9 @@ import { Icon } from './Icon'; export function DisabledScreen() { return (
- +
+ +

The movie-web extension can not be used on this page

diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index c3fa918..f8a0cc8 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,10 +1,24 @@ const icons = { power: ``, warningCircle: ``, + github: ``, + cookie: ``, + windows: ``, + shield: ``, + logo: ``, }; + export type Icons = keyof typeof icons; export function Icon(props: { name: Icons }) { - // eslint-disable-next-line react/no-danger - return
; + return ( +
+ ); } diff --git a/src/components/PermissionMissingScreen.tsx b/src/components/PermissionMissingScreen.tsx deleted file mode 100644 index 2d57e44..0000000 --- a/src/components/PermissionMissingScreen.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Icon } from '~components/Icon'; - -import '~tabs/PermissionGrant.css'; - -export interface PermissionMissingProps { - onGrant?: () => void; -} - -export function PermissionMissingScreen(props: PermissionMissingProps) { - return ( -
- -

The extension is missing permissions it needs to function

- -
- ); -} diff --git a/src/components/SetupScreen.css b/src/components/SetupScreen.css new file mode 100644 index 0000000..8407b79 --- /dev/null +++ b/src/components/SetupScreen.css @@ -0,0 +1,41 @@ +.setup-screen .title { + font-size: 1.5rem; + color: white; +} + +.setup-screen .paragraph { + font-size: 1rem; + color: #666485; + max-width: 220px; +} + +.setup-screen .top { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex: 1; +} + +.setup-screen { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + box-sizing: border-box; + padding: 2rem; + text-align: center; +} + +.setup-screen .icon { + background-color: #0b0b1b77; + color: #945DCC; + height: 40px; + font-size: 20px; + width: 40px; + border-radius: 9999px; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 20px; +} diff --git a/src/components/SetupScreen.tsx b/src/components/SetupScreen.tsx new file mode 100644 index 0000000..33fcbd6 --- /dev/null +++ b/src/components/SetupScreen.tsx @@ -0,0 +1,30 @@ +import { useCallback } from 'react'; + +import { Button } from '~components/Button'; +import { Icon } from '~components/Icon'; + +import './SetupScreen.css'; + +export function SetupScreen() { + const open = useCallback(() => { + const url = (chrome || browser).runtime.getURL(`/tabs/PermissionRequest.html`); + (chrome || browser).tabs.create({ url }); + }, []); + + return ( +
+
+
+ +
+

Le's get this set up!

+

+ To get started, we need to setup some things first. Click the button below to continue. +

+
+ +
+ ); +} diff --git a/src/contents/movie-web.ts b/src/contents/movie-web.ts index 263895d..aeddda5 100644 --- a/src/contents/movie-web.ts +++ b/src/contents/movie-web.ts @@ -2,8 +2,7 @@ import { relayMessage } from '@plasmohq/messaging'; import type { PlasmoCSConfig } from 'plasmo'; export const config: PlasmoCSConfig = { - // works for chrome, but not for firefox, so we add explicit domains for firefox - matches: ['', 'https://dev.movie-web.app/*', 'https://movie-web.app/*'], + matches: [''], }; relayMessage({ diff --git a/src/font.css b/src/font.css new file mode 100644 index 0000000..5c22608 --- /dev/null +++ b/src/font.css @@ -0,0 +1,28 @@ +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 400; + src: url(data-base64:~assets/inter/regular.ttf); +} + +@font-face { + font-family: "Inter"; + font-style: bold; + font-weight: 700; + src: url(data-base64:~assets/inter/bold.ttf); +} + +body, html { + font-family: "Inter", Arial, Helvetica, sans-serif; + font-size: 13px; +} + +* { + margin: 0; + padding: 0; +} + +button { + font-family: inherit; + font-size: inherit; +} diff --git a/src/popup.tsx b/src/popup.tsx index 1980551..067636c 100644 --- a/src/popup.tsx +++ b/src/popup.tsx @@ -1,28 +1,35 @@ -import { BottomLabel } from '~components/BottomLabel'; +import { BottomLabel, TopRightLabel } from '~components/BottomLabel'; import { DisabledScreen } from '~components/DisabledScreen'; import { Frame } from '~components/Frame'; -import { PermissionMissingScreen } from '~components/PermissionMissingScreen'; +import { SetupScreen } from '~components/SetupScreen'; import { ToggleButton } from '~components/ToggleButton'; import { useDomain } from '~hooks/useDomain'; import { useToggleWhitelistDomain } from '~hooks/useDomainWhitelist'; -import './Popup.css'; import { usePermission } from '~hooks/usePermission'; +import './Popup.css'; + function IndexPopup() { const domain = useDomain(); const { isWhitelisted, toggle } = useToggleWhitelistDomain(domain); - const { grantPermission, hasPermission } = usePermission(); + const { hasPermission } = usePermission(); let page = 'toggle'; if (!hasPermission) page = 'perm'; else if (!domain) page = 'disabled'; - return ( + return page === 'perm' ? ( + +
+ + +
+ + ) : (
{page === 'toggle' ? : null} {page === 'disabled' ? : null} - {page === 'perm' ? : null}
diff --git a/src/tabs/PermissionGrant.css b/src/tabs/PermissionGrant.css index df25203..be113c3 100644 --- a/src/tabs/PermissionGrant.css +++ b/src/tabs/PermissionGrant.css @@ -1,26 +1,21 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;800&display=swap'); - -* { - margin: 0; - padding: 0; -} +@import url("../font.css"); html { height: 100%; + font-size: 16px; } body { height: 100%; max-height: 100%; - font-family: 'Inter', sans-serif; } #__plasmo { height: 100%; - background-color: #0a0a10; + background-color: #0A0A10; } -.container { +.container.permission-grant { height: 100%; width: 100%; display: flex; @@ -28,76 +23,49 @@ body { justify-content: center; } -.inner-container { +.permission-grant .inner-container { width: 400px; display: flex; flex-direction: column; gap: 1rem; } -.permission-card { +.permission-grant .permission-card { display: flex; align-items: center; + flex-direction: column; justify-content: center; - background-color: #0f0f1b; - border-radius: 10px; - height: 125px; - padding-right: 40px; - padding-left: 40px; + border-radius: 20px; + padding: 40px; + padding-top: 50px; font-size: 14px; - border: 1px solid #20202d; + border: 1px solid #272A37; } -.footer { - display: flex; +.permission-grant h1 { + font-size: 1.25rem; + margin-bottom: 0.5rem; } -.color-white { +.permission-grant .permission-card > p { + font-size: 1rem; + margin-top: .5rem; + margin-bottom: 1rem; +} + +.permission-grant .color-white { color: #ffffff; } -.text-color { +.permission-grant .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; +.permission-grant .buttons { + width: 100%; + margin-top: 2rem; } -.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; +.permission-grant .buttons>*+* { + margin-top: 1rem; } diff --git a/src/tabs/PermissionGrant.tsx b/src/tabs/PermissionGrant.tsx index 5cd54fc..66305dc 100644 --- a/src/tabs/PermissionGrant.tsx +++ b/src/tabs/PermissionGrant.tsx @@ -1,19 +1,16 @@ -import { useDomainWhitelist } from '~hooks/useDomainWhitelist'; +import { Button } from '~components/Button'; import { usePermission } from '~hooks/usePermission'; import { makeUrlIntoDomain } from '~utils/domains'; import './PermissionGrant.css'; export default function PermissionGrant() { - const { domainWhitelist } = useDomainWhitelist(); - const { hasPermission, grantPermission } = usePermission(); + const { grantPermission } = usePermission(); const queryParams = new URLSearchParams(window.location.search); const redirectUrl = queryParams.get('redirectUrl') ?? 'https://movie-web.app'; const domain = makeUrlIntoDomain(redirectUrl); - const permissionsGranted = domainWhitelist.includes(domain) && hasPermission; - const redirectBack = () => { chrome.tabs.getCurrent((tab) => { chrome.tabs.update(tab.id, { url: redirectUrl }); @@ -27,30 +24,22 @@ export default function PermissionGrant() { }; return ( -
+
-

Permission

-

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

+

Permission

The website {domain} wants to
use the extension on their page. + Do you trust them?

-
-
- -
- +
+ + +
diff --git a/src/tabs/PermissionRequest.css b/src/tabs/PermissionRequest.css new file mode 100644 index 0000000..51486cc --- /dev/null +++ b/src/tabs/PermissionRequest.css @@ -0,0 +1,126 @@ +@import url("../font.css"); + +html { + font-size: 16px; +} + +body { + background-color: #0A0A10; + color: white; + padding-bottom: 50px; +} + +.permission-request.container { + width: 90%; + margin: 100px auto; + max-width: 628px; +} + +.permission-request h1 { + font-size: 2rem; + font-weight: bold; +} + +.permission-request h2 { + font-size: 1.5rem; + font-weight: bold; + margin-top: 4rem; + margin-bottom: 1rem; +} + +.permission-request .text-color { + color: #7C7C97; +} + +.permission-request .paragraph { + font-size: 1rem; + margin-top: 20px; + max-width: 500px; + line-height: 1.3; +} + +.permission-request .card-list { + margin: 1rem 0; +} + +.permission-request .card-list>*+* { + margin-top: 1rem; +} + +.permission-request .card { + padding: 25px 20px; + border: 1px solid #272A37; + display: grid; + grid-template-columns: auto 1fr auto; + gap: 1rem; + border-radius: 11px; +} + + +.permission-request .card .icon-circle { + width: 2rem; + height: 2rem; + font-size: 1rem; + background-color: rgba(39, 42, 55, 0.35); + border: 1px solid #272A37; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +.permission-request .card.purple, .permission-request .card.purple .icon-circle { + border-color: #49277C; +} + +.permission-request .card.purple .icon-circle { + background-color: rgba(51, 27, 87, .4); +} + +.permission-request .card .icon-circle > div { + display: block; + width: 1rem; + height: 1rem; +} + +.permission-request .card h3 { + font-size: 1rem; + font-weight: bold; + color: white; + margin-top: 5px; +} + +.permission-request .card .paragraph { + margin-top: 0.5rem; +} + +.permission-request .card .center-y { + display: flex; + align-items: center; +} + +.permission-request .card button { + padding: 1rem; + border-radius: 10px; + border: 0; + font-size: 1rem; + font-weight: bold; + background-color: #222033; + color: white; +} + +.permission-request .card:not(.purple) .icon-circle { + color: #7C7C97; +} + +.permission-request .footer { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + height: 100px; + background: linear-gradient(to top, #0A0A10 30%, transparent); + display: flex; + justify-content: center; + align-items: center; +} diff --git a/src/tabs/PermissionRequest.tsx b/src/tabs/PermissionRequest.tsx new file mode 100644 index 0000000..43b0dd3 --- /dev/null +++ b/src/tabs/PermissionRequest.tsx @@ -0,0 +1,92 @@ +import { useCallback } from 'react'; + +import { Button } from '~components/Button'; +import { Icon } from '~components/Icon'; +import { usePermission } from '~hooks/usePermission'; + +import './PermissionRequest.css'; + +function Card(props: { purple?: boolean; children: React.ReactNode; icon?: React.ReactNode; right?: React.ReactNode }) { + return ( +
+
+
{props.icon}
+
+
{props.children}
+ {props.right ?
{props.right}
: null} +
+ ); +} + +export default function PermissionRequest() { + const { grantPermission } = usePermission(); + + const grant = useCallback(() => { + grantPermission().then(() => window.close()); + }, [grantPermission]); + + return ( +
+
+

+ We need some
browser permissions +

+

+ We don't like it either, but the movie-web extension needs quite a few permissions to function. Listed + below is an explanation for all permissions we need. +

+ +
+ } + right={ + + } + > +

Read the source code on GitHub

+

+ Don't trust us? Read the code and choose for yourself if its safe! +

+
+
+ +

Permission list

+
+ }> +

Read & change data from all sites

+

+ To be able to gather content from the sources. We need to be able to reach those sources. Unfortunately + that requires us to request the permissions from all sites. +

+
+ }> +

Read and write cookies

+

+ Some sources use cookies for authentication. We need to be able to read and set those cookies. This + won't be prompted to you, it's included in “Read & change data from all sites”. +

+
+ }> +

Active tab

+

+ To determine which site has access to the extension or not, we need to know what tab you're currently + using. This permission is given to all extensions by default, so your browser won't prompt you for + it. +

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