v0.2/features #68
|
@ -22,7 +22,10 @@
|
|||
"Settings": {
|
||||
"lang_title": "Please select language",
|
||||
"lang_it": "Italian",
|
||||
"lang_en": "English"
|
||||
"lang_en": "English",
|
||||
"settings_title": "Settings",
|
||||
"platform_title": "Platform:",
|
||||
"orientation_title": "Orientation:"
|
||||
},
|
||||
"Results": {
|
||||
"query": "Search results for: {{ query }}",
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
"Settings": {
|
||||
"lang_title": "Seleziona la lingua",
|
||||
"lang_it": "Italiano",
|
||||
"lang_en": "Inglese"
|
||||
"lang_en": "Inglese",
|
||||
"settings_title": "Impostazioni",
|
||||
"platform_title": "Piattaforma:",
|
||||
"orientation_title": "Orientamento:"
|
||||
},
|
||||
"Results": {
|
||||
"query": "Risultati della ricerca per: {{ query }}",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"next-intl": "^3.11.3",
|
||||
"next-nprogress-bar": "^2.3.11",
|
||||
"react": "^18",
|
||||
"react-cookie": "^7.1.4",
|
||||
"react-dom": "^18",
|
||||
"react-icons": "^5.1.0",
|
||||
"react-image": "^4.1.0",
|
||||
|
@ -519,6 +520,20 @@
|
|||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
|
||||
},
|
||||
"node_modules/@types/hoist-non-react-statics": {
|
||||
"version": "3.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
|
||||
"integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
|
@ -537,14 +552,12 @@
|
|||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
|
||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.79",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz",
|
||||
"integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
|
@ -1339,6 +1352,14 @@
|
|||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
@ -1382,8 +1403,7 @@
|
|||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
|
@ -2711,6 +2731,14 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"dependencies": {
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
|
@ -4087,6 +4115,19 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-cookie": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.1.4.tgz",
|
||||
"integrity": "sha512-wDxxa/HYaSXSMlyWJvJ5uZTzIVtQTPf1gMksFgwAz/2/W3lCtY8r4OChCXMPE7wax0PAdMY97UkNJedGv7KnDw==",
|
||||
"dependencies": {
|
||||
"@types/hoist-non-react-statics": "^3.3.5",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"universal-cookie": "^7.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
||||
|
@ -4120,8 +4161,7 @@
|
|||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "9.1.1",
|
||||
|
@ -4964,6 +5004,15 @@
|
|||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/universal-cookie": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.1.4.tgz",
|
||||
"integrity": "sha512-Q+DVJsdykStWRMtXr2Pdj3EF98qZHUH/fXv/gwFz/unyToy1Ek1w5GsWt53Pf38tT8Gbcy5QNsj61Xe9TggP4g==",
|
||||
"dependencies": {
|
||||
"@types/cookie": "^0.6.0",
|
||||
"cookie": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"next-intl": "^3.11.3",
|
||||
"next-nprogress-bar": "^2.3.11",
|
||||
"react": "^18",
|
||||
"react-cookie": "^7.1.4",
|
||||
"react-dom": "^18",
|
||||
"react-icons": "^5.1.0",
|
||||
"react-image": "^4.1.0",
|
||||
|
|
|
@ -9,6 +9,6 @@ export default async function SearchPage({ params }: { params: { query: string }
|
|||
const data = await fetchGalleryData({ query: params.query })
|
||||
|
||||
return <Layout>
|
||||
<Search data={data} query={params.query} />
|
||||
<Search data={data} query={decodeURIComponent(params.query)} />
|
||||
</Layout>
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
'use client'
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { AppProgressBar as ProgressBar } from 'next-nprogress-bar';
|
||||
|
||||
import { LAYOUT_COLORS_PINK, LAYOUT_COLORS_YELLOW } from '@/constants/colors';
|
||||
import { Themes } from '@/meta/settings';
|
||||
|
||||
interface Props {
|
||||
theme?: Themes
|
||||
}
|
||||
|
||||
const Body: React.FC<Props & React.PropsWithChildren> = (props) => {
|
||||
|
||||
const { theme, children } = props;
|
||||
|
||||
return (
|
||||
<body>
|
||||
<main className="container">{children}</main>
|
||||
<ProgressBar
|
||||
height="4px"
|
||||
color={theme == Themes.dark ? LAYOUT_COLORS_YELLOW : LAYOUT_COLORS_PINK}
|
||||
options={{ showSpinner: false }}
|
||||
shallowRouting
|
||||
/>
|
||||
</body>
|
||||
);
|
||||
};
|
||||
|
||||
export default Body;
|
|
@ -1,36 +1,26 @@
|
|||
'use client'
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Head from 'next/head';
|
||||
|
||||
import { AppProgressBar as ProgressBar } from 'next-nprogress-bar';
|
||||
|
||||
import { useAppSelector } from '@/store/store';
|
||||
import { LAYOUT_COLORS_PINK, LAYOUT_COLORS_YELLOW } from '@/constants/colors';
|
||||
import { Themes } from '@/meta/settings';
|
||||
|
||||
const Content: React.FC<React.PropsWithChildren> = (props) => {
|
||||
import Body from './Body';
|
||||
|
||||
const { children } = props;
|
||||
interface Props {
|
||||
theme?: Themes
|
||||
}
|
||||
|
||||
const theme = useAppSelector((state) => state.settings.theme);
|
||||
const Content: React.FC<Props & React.PropsWithChildren> = (props) => {
|
||||
|
||||
const { theme, children } = props;
|
||||
|
||||
return (
|
||||
<html data-theme={theme} /*lang={locale}*/>
|
||||
<html data-theme={theme}>
|
||||
<Head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</Head>
|
||||
<body>
|
||||
<main className="container">{children}</main>
|
||||
<ProgressBar
|
||||
height="4px"
|
||||
color={theme == Themes.dark ? LAYOUT_COLORS_YELLOW : LAYOUT_COLORS_PINK}
|
||||
options={{ showSpinner: false }}
|
||||
shallowRouting
|
||||
/>
|
||||
</body>
|
||||
<Body theme={theme}>{children}</Body>
|
||||
</html>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
@import 'spacing';
|
||||
|
||||
.container {
|
||||
|
||||
overflow: visible !important;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.close {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
@import 'fontsize';
|
||||
@import 'spacing';
|
||||
|
||||
|
||||
.container {
|
||||
|
||||
.title {
|
||||
margin-bottom: $spacing_16;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
'use client'
|
||||
|
||||
import { Cookies, XVideosOrientations } from '@/meta/settings';
|
||||
|
||||
import css from './Orientation.module.scss'
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { setCookie } from '@/utils/cookies/write';
|
||||
import { useCookies } from 'react-cookie';
|
||||
|
||||
interface Props {
|
||||
labels: {
|
||||
title: string,
|
||||
}
|
||||
}
|
||||
|
||||
const Orientation: React.FC<Props> = (props) => {
|
||||
|
||||
const { labels } = props
|
||||
|
||||
const [cookies] = useCookies([Cookies.orientation]);
|
||||
|
||||
const handleChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const value = event.target.value;
|
||||
|
||||
await setCookie(Cookies.orientation, value)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={css.container}>
|
||||
<div className={css.title}>{labels.title}</div>
|
||||
<select defaultValue={ cookies.orientation ?? XVideosOrientations.etero } onChange={handleChange} name={'orientation'} aria-label={labels.title}>
|
||||
{Object.keys(XVideosOrientations).map((elem, key) => {
|
||||
return <option className={css.option} key={key} value={elem}>{elem.toUpperCase()}</option>
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Orientation;
|
|
@ -0,0 +1,11 @@
|
|||
@import 'fontsize';
|
||||
@import 'spacing';
|
||||
|
||||
|
||||
.container {
|
||||
|
||||
.title {
|
||||
margin-bottom: $spacing_16;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
'use client'
|
||||
|
||||
import { Cookies, Platforms } from '@/meta/settings';
|
||||
|
||||
import css from './Platform.module.scss'
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { setCookie } from '@/utils/cookies/write';
|
||||
import { useCookies } from 'react-cookie';
|
||||
|
||||
interface Props {
|
||||
labels: {
|
||||
title: string,
|
||||
}
|
||||
}
|
||||
|
||||
const Platform: React.FC<Props> = (props) => {
|
||||
|
||||
const { labels } = props
|
||||
|
||||
const [cookies] = useCookies([Cookies.platform]);
|
||||
|
||||
const handleChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const value = event.target.value;
|
||||
|
||||
await setCookie(Cookies.platform, value)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={css.container}>
|
||||
<div className={css.title}>{labels.title}</div>
|
||||
<select defaultValue={ cookies.platform ?? Platforms.xvideos } onChange={handleChange} name={'platform'} aria-label={labels.title}>
|
||||
{Object.keys(Platforms).map((elem, key) => {
|
||||
return <option className={css.option} key={key} value={elem}>{elem.toUpperCase()}</option>
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Platform;
|
|
@ -0,0 +1,41 @@
|
|||
'use client'
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { IoCloseCircleOutline } from "react-icons/io5";
|
||||
|
||||
import style from './Modal.module.scss'
|
||||
import Platform from './Platform';
|
||||
import Orientation from './Orientation';
|
||||
|
||||
interface Props {
|
||||
handleClose(): void
|
||||
labels: {
|
||||
title: string
|
||||
platform: any
|
||||
orientation: any
|
||||
}
|
||||
}
|
||||
|
||||
const LangSwitcher: React.FC<Props> = (props) => {
|
||||
|
||||
const { labels, handleClose } = props
|
||||
|
||||
return (
|
||||
<dialog open>
|
||||
<article className={style.container}>
|
||||
<header className={style.header}>
|
||||
<div className={style.title}>{labels.title}</div>
|
||||
<div className={style.close} onClick={() => { handleClose() }}><IoCloseCircleOutline size={24} /></div>
|
||||
</header>
|
||||
<div className={style.content}>
|
||||
<Platform labels={{ title: labels.platform.title }} />
|
||||
<Orientation labels={{ title: labels.orientation.title }} />
|
||||
</div>
|
||||
</article>
|
||||
</dialog >
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default LangSwitcher;
|
|
@ -0,0 +1,31 @@
|
|||
'use client'
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { IoSettingsOutline } from 'react-icons/io5';
|
||||
|
||||
import Icon from '../Icon';
|
||||
import Modal from './Modal';
|
||||
|
||||
interface Props {
|
||||
labels: any
|
||||
}
|
||||
|
||||
const Settings: React.FC<Props> = (props) => {
|
||||
|
||||
const { labels } = props
|
||||
|
||||
const [showModal, setShowModal] = useState<boolean>(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Icon handleClick={() => setShowModal(true)}>
|
||||
{<IoSettingsOutline size={24} />}
|
||||
</Icon>
|
||||
|
||||
{showModal && <Modal handleClose={() => setShowModal(false)} labels={labels} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
|
@ -3,23 +3,29 @@
|
|||
import React from 'react';
|
||||
|
||||
import { TbMoon, TbSun } from 'react-icons/tb';
|
||||
import { useAppDispatch, useAppSelector } from '@/store/store';
|
||||
import { Themes } from '@/meta/settings';
|
||||
import { setCurrentTheme } from '@/store/settingsSlice';
|
||||
import { Cookies, DEFAULT_THEME, Themes } from '@/meta/settings';
|
||||
|
||||
import Icon from '../Icon';
|
||||
import { setCookie } from '@/utils/cookies/write';
|
||||
import { useCookies } from 'react-cookie';
|
||||
|
||||
const Menu: React.FC = () => {
|
||||
const Theme: React.FC = () => {
|
||||
|
||||
const theme = useAppSelector((state) => state.settings.theme);
|
||||
const dispatch = useAppDispatch();
|
||||
const [cookies] = useCookies([Cookies.theme]);
|
||||
|
||||
const theme = cookies.theme ?? DEFAULT_THEME
|
||||
|
||||
const handleClick = async () => {
|
||||
const newTheme = theme == Themes.dark ? Themes.light : Themes.dark
|
||||
await setCookie(Cookies.theme, newTheme)
|
||||
}
|
||||
|
||||
return (
|
||||
<Icon handleClick={() => dispatch(setCurrentTheme(theme == Themes.dark ? Themes.light : Themes.dark))}>
|
||||
<Icon handleClick={handleClick}>
|
||||
{theme == Themes.dark && <TbMoon size={24} />}
|
||||
{theme == Themes.light && <TbSun size={24} />}
|
||||
</Icon>
|
||||
);
|
||||
};
|
||||
|
||||
export default Menu;
|
||||
export default Theme;
|
|
@ -8,6 +8,7 @@ import Theme from './Theme';
|
|||
import Repo from './Repo';
|
||||
import Language from './Language';
|
||||
import { LangOption } from '@/meta/settings';
|
||||
import Settings from './Settings';
|
||||
|
||||
const Menu: React.FC = () => {
|
||||
|
||||
|
@ -23,11 +24,22 @@ const Menu: React.FC = () => {
|
|||
langs: options
|
||||
}
|
||||
|
||||
const settingsLabels = {
|
||||
title: t('settings_title'),
|
||||
platform: {
|
||||
title: t('platform_title')
|
||||
},
|
||||
orientation: {
|
||||
title: t('orientation_title')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={style.container}>
|
||||
<Repo />
|
||||
<Language labels={languageLabels} />
|
||||
<Theme />
|
||||
<Settings labels={settingsLabels} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -2,15 +2,17 @@ import React from 'react';
|
|||
|
||||
import style from './Title.module.scss'
|
||||
|
||||
import {useTranslations} from 'next-intl';
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
const Title: React.FC = () => {
|
||||
|
||||
const t = useTranslations('Header');
|
||||
const locale = useLocale()
|
||||
|
||||
return (
|
||||
<Link href={'/'}><h1 className={style.title}>{t('title')}</h1></Link>
|
||||
<Link href={`/${locale}`}><h1 className={style.title}>{t('title')}</h1></Link>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import React from 'react';
|
||||
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
import WithRedux from '@/store/withRedux';
|
||||
import Content from './Content';
|
||||
import { DEFAULT_THEME, Themes } from '@/meta/settings';
|
||||
|
||||
const Layout: React.FC<React.PropsWithChildren> = (props) => {
|
||||
|
||||
const { children } = props;
|
||||
|
||||
const cookieStore = cookies()
|
||||
|
||||
const theme = cookieStore.get('theme')
|
||||
|
||||
return (
|
||||
<WithRedux>
|
||||
<Content>
|
||||
<Content theme={theme ? theme?.value as Themes : DEFAULT_THEME}>
|
||||
{children}
|
||||
</Content>
|
||||
</WithRedux>
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
export const XVIDEOS_BASE_URL: string = "https://www.xvideos.com"
|
||||
export const XVIDEOS_BASE_URL: string = "https://www.xvideos.com"
|
||||
export const XVIDEOS_BASE_URL_GAY: string = "https://www.xvideos.com/gay"
|
||||
export const XVIDEOS_BASE_URL_TRANS: string = "https://www.xvideos.com/shemale"
|
|
@ -1,8 +1,33 @@
|
|||
export enum Cookies {
|
||||
theme= 'theme',
|
||||
orientation= 'orientation',
|
||||
platform= 'platform'
|
||||
}
|
||||
|
||||
export enum Platforms {
|
||||
xvideos= 'xvideos',
|
||||
xnxx= 'xnxx'
|
||||
}
|
||||
|
||||
export enum XVideosCatQueryMap {
|
||||
etero= 'straight',
|
||||
gay= 'gay',
|
||||
trans= 'shemale'
|
||||
}
|
||||
|
||||
export enum XVideosOrientations {
|
||||
etero= 'etero',
|
||||
gay= 'gay',
|
||||
trans= 'trans'
|
||||
}
|
||||
|
||||
export enum Themes {
|
||||
light= 'light',
|
||||
dark= 'dark'
|
||||
dark= 'dark',
|
||||
}
|
||||
|
||||
export const DEFAULT_THEME = Themes.light
|
||||
|
||||
export interface LangOption {
|
||||
label: string;
|
||||
code: string;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
'use server'
|
||||
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export async function getCookie(name: string) {
|
||||
return cookies().get(name);
|
||||
}
|
||||
|
||||
export async function hasCookie(name: string):Promise<boolean> {
|
||||
return cookies().has(name)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
'use server'
|
||||
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export async function deleteCookie(name: string) {
|
||||
cookies().delete(name)
|
||||
}
|
||||
|
||||
export async function setCookie(name: string, value: string) {
|
||||
cookies().set(name, value, {
|
||||
sameSite: 'lax',
|
||||
secure: false
|
||||
})
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import { XVIDEOS_BASE_URL } from '@/constants/urls';
|
||||
import { GalleryData } from '@/meta/data';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
|
||||
import * as cheerio from "cheerio";
|
||||
import { getHeaders } from '../headers';
|
||||
import { getXVideosQueryUrl } from './url';
|
||||
|
||||
interface FetchParams {
|
||||
baseUrl?: string
|
||||
|
@ -16,7 +16,7 @@ export const fetchGalleryData = async (params?: FetchParams): Promise<GalleryDat
|
|||
|
||||
const reqHeaders = getHeaders()
|
||||
|
||||
const queryUrl = `${(params && params.baseUrl) ?? XVIDEOS_BASE_URL}${params && params.query ? '/?k=' + params.query : ''}`
|
||||
const queryUrl = await getXVideosQueryUrl(params?.query)
|
||||
|
||||
await axios.get(queryUrl, reqHeaders)
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import { XVIDEOS_BASE_URL, XVIDEOS_BASE_URL_GAY, XVIDEOS_BASE_URL_TRANS } from '@/constants/urls';
|
||||
import { Cookies, XVideosCatQueryMap, XVideosOrientations } from '@/meta/settings';
|
||||
import { getCookie } from '@/utils/cookies/read';
|
||||
|
||||
export const getXVideosQueryUrl = async (query?: string) => {
|
||||
|
||||
const category = await getCookie(Cookies.orientation)
|
||||
|
||||
if (!category && !query) {
|
||||
return XVIDEOS_BASE_URL
|
||||
}
|
||||
|
||||
if (!category && query) {
|
||||
return `${XVIDEOS_BASE_URL}/?k=${query}`
|
||||
}
|
||||
|
||||
if (category && !Object.values(XVideosOrientations).includes(category.value as XVideosOrientations)) {
|
||||
return XVIDEOS_BASE_URL
|
||||
}
|
||||
|
||||
if (category && !query) {
|
||||
switch (category.value) {
|
||||
case XVideosOrientations.etero:
|
||||
return XVIDEOS_BASE_URL
|
||||
case XVideosOrientations.gay:
|
||||
return XVIDEOS_BASE_URL_GAY
|
||||
case XVideosOrientations.trans:
|
||||
return XVIDEOS_BASE_URL_TRANS
|
||||
default:
|
||||
return XVIDEOS_BASE_URL;
|
||||
}
|
||||
}
|
||||
|
||||
if (category && query) {
|
||||
return `${XVIDEOS_BASE_URL}/?k=${query}&typef=${XVideosCatQueryMap[category.value as XVideosOrientations]}`
|
||||
}
|
||||
|
||||
return XVIDEOS_BASE_URL
|
||||
|
||||
}
|
Loading…
Reference in New Issue