mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
commit
8b498ef036
11 changed files with 46 additions and 13 deletions
|
@ -16,6 +16,7 @@
|
|||
"title": "Login to your account",
|
||||
"description": "Please enter your passphrase to login to your account",
|
||||
"validationError": "Invalid or incomplete passphrase",
|
||||
"deviceLengthError": "Please enter a device name",
|
||||
"submit": "Login",
|
||||
"passphraseLabel": "12-Word passphrase",
|
||||
"passphrasePlaceholder": "Passphrase"
|
||||
|
|
|
@ -21,7 +21,7 @@ export function Dropdown(props: DropdownProps) {
|
|||
<Listbox value={props.selectedItem} onChange={props.setSelectedItem}>
|
||||
{() => (
|
||||
<>
|
||||
<Listbox.Button className="relative w-full rounded-lg bg-dropdown-background py-3 pl-3 pr-10 text-left text-white shadow-md focus:outline-none tabbable cursor-pointer">
|
||||
<Listbox.Button className="relative w-full rounded-lg bg-dropdown-background hover:bg-dropdown-hoverBackground py-3 pl-3 pr-10 text-left text-white shadow-md focus:outline-none tabbable cursor-pointer">
|
||||
<span className="flex gap-4 items-center truncate">
|
||||
{props.selectedItem.leftIcon
|
||||
? props.selectedItem.leftIcon
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useHistory } from "react-router-dom";
|
|||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { BrandPill } from "@/components/layout/BrandPill";
|
||||
import { WideContainer } from "@/components/layout/WideContainer";
|
||||
import { shouldHaveDmcaPage } from "@/pages/Dmca";
|
||||
import { conf } from "@/setup/config";
|
||||
|
||||
function FooterLink(props: {
|
||||
|
@ -30,6 +31,8 @@ function Dmca() {
|
|||
const { t } = useTranslation();
|
||||
const history = useHistory();
|
||||
|
||||
if (!shouldHaveDmcaPage()) return null;
|
||||
|
||||
return (
|
||||
<FooterLink icon={Icons.DRAGON} onClick={() => history.push("/dmca")}>
|
||||
{t("footer.links.dmca")}
|
||||
|
|
|
@ -130,10 +130,12 @@ export function CaptionsView({ id }: { id: string }) {
|
|||
[selectLanguage, setCurrentlyDownloading]
|
||||
);
|
||||
|
||||
const content = subtitleList.map((v) => {
|
||||
const content = subtitleList.map((v, i) => {
|
||||
return (
|
||||
<CaptionOption
|
||||
key={v.language}
|
||||
// key must use index to prevent url collisions
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
key={`${i}-${v.url}`}
|
||||
countryCode={v.language}
|
||||
selected={lang === v.language}
|
||||
loading={v.language === currentlyDownloading && downloadReq.loading}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
export function handleBuffered(time: number, buffered: TimeRanges): number {
|
||||
// TODO normalize the buffer sections into one section. they can be stitched together
|
||||
for (let i = 0; i < buffered.length; i += 1) {
|
||||
if (buffered.start(buffered.length - 1 - i) < time) {
|
||||
return buffered.end(buffered.length - 1 - i);
|
||||
|
|
|
@ -4,10 +4,14 @@ import { Icon, Icons } from "@/components/Icon";
|
|||
import { ThinContainer } from "@/components/layout/ThinContainer";
|
||||
import { Heading1, Paragraph } from "@/components/utils/Text";
|
||||
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||
import { conf } from "@/setup/config";
|
||||
|
||||
import { SubPageLayout } from "./layouts/SubPageLayout";
|
||||
|
||||
// TODO make email a constant
|
||||
export function shouldHaveDmcaPage() {
|
||||
return !!conf().DMCA_EMAIL;
|
||||
}
|
||||
|
||||
export function DmcaPage() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -19,7 +23,7 @@ export function DmcaPage() {
|
|||
<Paragraph>{t("screens.dmca.text")}</Paragraph>
|
||||
<Paragraph className="flex space-x-3 items-center">
|
||||
<Icon icon={Icons.MAIL} />
|
||||
<span>dmca@movie-web.app</span>
|
||||
<span>{conf().DMCA_EMAIL ?? ""}</span>
|
||||
</Paragraph>
|
||||
</ThinContainer>
|
||||
</SubPageLayout>
|
||||
|
|
|
@ -32,11 +32,18 @@ export function AccountCreatePart(props: AccountCreatePartProps) {
|
|||
const [colorB, setColorB] = useState("#2E65CF");
|
||||
const [userIcon, setUserIcon] = useState<UserIcons>(UserIcons.USER);
|
||||
const { t } = useTranslation();
|
||||
// TODO validate device and account before next step
|
||||
const [hasDeviceError, setHasDeviceError] = useState(false);
|
||||
|
||||
const nextStep = useCallback(() => {
|
||||
setHasDeviceError(false);
|
||||
const validatedDevice = device.trim();
|
||||
if (validatedDevice.length === 0) {
|
||||
setHasDeviceError(true);
|
||||
return;
|
||||
}
|
||||
|
||||
props.onNext?.({
|
||||
device,
|
||||
device: validatedDevice,
|
||||
profile: {
|
||||
colorA,
|
||||
colorB,
|
||||
|
@ -75,6 +82,11 @@ export function AccountCreatePart(props: AccountCreatePartProps) {
|
|||
value={userIcon}
|
||||
onInput={setUserIcon}
|
||||
/>
|
||||
{hasDeviceError ? (
|
||||
<p className="text-authentication-errorText">
|
||||
{t("auth.login.deviceLengthError")}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
<LargeCardButtons>
|
||||
<Button theme="purple" onClick={() => nextStep()}>
|
||||
|
|
|
@ -29,14 +29,17 @@ export function LoginFormPart(props: LoginFormPartProps) {
|
|||
|
||||
const [result, execute] = useAsyncFn(
|
||||
async (inputMnemonic: string, inputdevice: string) => {
|
||||
// TODO verify valid device input
|
||||
if (!verifyValidMnemonic(inputMnemonic))
|
||||
throw new Error(t("auth.login.validationError") ?? undefined);
|
||||
|
||||
const validatedDevice = inputdevice.trim();
|
||||
if (validatedDevice.length === 0)
|
||||
throw new Error(t("auth.login.deviceLengthError") ?? undefined);
|
||||
|
||||
const account = await login({
|
||||
mnemonic: inputMnemonic,
|
||||
userData: {
|
||||
device: inputdevice,
|
||||
device: validatedDevice,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -46,7 +49,7 @@ export function LoginFormPart(props: LoginFormPartProps) {
|
|||
|
||||
props.onLogin?.();
|
||||
},
|
||||
[props, login, restore]
|
||||
[props, login, restore, t]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -14,7 +14,7 @@ import { useOnlineListener } from "@/hooks/usePing";
|
|||
import { AboutPage } from "@/pages/About";
|
||||
import { AdminPage } from "@/pages/admin/AdminPage";
|
||||
import VideoTesterView from "@/pages/developer/VideoTesterView";
|
||||
import { DmcaPage } from "@/pages/Dmca";
|
||||
import { DmcaPage, shouldHaveDmcaPage } from "@/pages/Dmca";
|
||||
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
|
||||
import { HomePage } from "@/pages/HomePage";
|
||||
import { LoginPage } from "@/pages/Login";
|
||||
|
@ -93,7 +93,10 @@ function App() {
|
|||
<Route exact path="/register" component={RegisterPage} />
|
||||
<Route exact path="/login" component={LoginPage} />
|
||||
<Route exact path="/faq" component={AboutPage} />
|
||||
<Route exact path="/dmca" component={DmcaPage} />
|
||||
|
||||
{shouldHaveDmcaPage() ? (
|
||||
<Route exact path="/dmca" component={DmcaPage} />
|
||||
) : null}
|
||||
|
||||
{/* Settings page */}
|
||||
<Route exact path="/settings" component={SettingsPage} />
|
||||
|
|
|
@ -10,6 +10,7 @@ interface Config {
|
|||
GITHUB_LINK: string;
|
||||
DONATION_LINK: string;
|
||||
DISCORD_LINK: string;
|
||||
DMCA_EMAIL: string;
|
||||
TMDB_READ_API_KEY: string;
|
||||
CORS_PROXY_URL: string;
|
||||
NORMAL_ROUTER: boolean;
|
||||
|
@ -22,6 +23,7 @@ export interface RuntimeConfig {
|
|||
GITHUB_LINK: string;
|
||||
DONATION_LINK: string;
|
||||
DISCORD_LINK: string;
|
||||
DMCA_EMAIL: string | null;
|
||||
TMDB_READ_API_KEY: string;
|
||||
NORMAL_ROUTER: boolean;
|
||||
PROXY_URLS: string[];
|
||||
|
@ -35,6 +37,7 @@ const env: Record<keyof Config, undefined | string> = {
|
|||
GITHUB_LINK: undefined,
|
||||
DONATION_LINK: undefined,
|
||||
DISCORD_LINK: undefined,
|
||||
DMCA_EMAIL: import.meta.env.VITE_DMCA_EMAIL,
|
||||
CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL,
|
||||
NORMAL_ROUTER: import.meta.env.VITE_NORMAL_ROUTER,
|
||||
BACKEND_URL: import.meta.env.VITE_BACKEND_URL,
|
||||
|
@ -54,11 +57,13 @@ function getKey(key: keyof Config, defaultString?: string): string {
|
|||
}
|
||||
|
||||
export function conf(): RuntimeConfig {
|
||||
const dmcaEmail = getKey("DMCA_EMAIL");
|
||||
return {
|
||||
APP_VERSION,
|
||||
GITHUB_LINK,
|
||||
DONATION_LINK,
|
||||
DISCORD_LINK,
|
||||
DMCA_EMAIL: dmcaEmail.length > 0 ? dmcaEmail : null,
|
||||
BACKEND_URL: getKey("BACKEND_URL"),
|
||||
TMDB_READ_API_KEY: getKey("TMDB_READ_API_KEY"),
|
||||
PROXY_URLS: getKey("CORS_PROXY_URL")
|
||||
|
|
|
@ -97,6 +97,7 @@ export const defaultTheme = {
|
|||
dropdown: {
|
||||
background: "#171728",
|
||||
altBackground: "#151525",
|
||||
hoverBackground: "#202036",
|
||||
highlight: "#afa349",
|
||||
highlightHover: "#FCEC61",
|
||||
text: "#846D95",
|
||||
|
|
Loading…
Reference in a new issue