@@ -0,0 +1,40 @@ +#!/usr/bin/env sh +# +# If you create/switch to a branch without a prefix (no '/'), +# automatically rename it to "feature/". +# +# Allowed prefixes (when '/' is present): +# fix/, feature/, release/, chore/ +# + +set -eu + +IS_BRANCH_CHECKOUT="${3:-0}" +if [ "$IS_BRANCH_CHECKOUT" != "1" ]; then + exit 0 +fi + +BRANCH="$(git symbolic-ref --quiet --short HEAD 2>/dev/null || true)" +if [ -z "$BRANCH" ]; then + exit 0 +fi + +case "$BRANCH" in + fix/*|feature/*|release/*|chore/*) + exit 0 + ;; +esac + +# No prefix -> default to feature/ +if ! printf "%s" "$BRANCH" | grep -q '/'; then + NEW_BRANCH="feature/$BRANCH" + if git show-ref --verify --quiet "refs/heads/$NEW_BRANCH"; then + exit 0 + fi + git branch -m "$BRANCH" "$NEW_BRANCH" 2>/dev/null || true + exit 0 +fi + +# Has a prefix but it's not allowed: cannot reliably fix here (checkout already happened). +exit 0 + @@ -0,0 +1,35 @@ +#!/usr/bin/env sh +# +# Enforce allowed branch prefixes: +# fix/, feature/, release/, chore/ +# +# If branch has no prefix (no '/'), automatically rename to feature/. +# + +set -eu + +BRANCH="$(git symbolic-ref --quiet --short HEAD 2>/dev/null || true)" +if [ -z "$BRANCH" ]; then + exit 0 +fi + +case "$BRANCH" in + fix/*|feature/*|release/*|chore/*) + exit 0 + ;; +esac + +# No slash => default to feature/ +if ! printf "%s" "$BRANCH" | grep -q '/'; then + NEW_BRANCH="feature/$BRANCH" + if ! git show-ref --verify --quiet "refs/heads/$NEW_BRANCH"; then + git branch -m "$BRANCH" "$NEW_BRANCH" + fi + exit 0 +fi + +echo >&2 "Ошибка: недопустимый префикс ветки '$BRANCH'." +echo >&2 "Разрешены только: fix/, feature/, release/, chore/." +echo >&2 "Либо используйте ветку без префикса — она будет автоматически переименована в feature/<имя>." +exit 1 + @@ -0,0 +1,65 @@ +#!/usr/bin/env sh +# +# Auto-prefix commit messages based on branch name: +# fix/..., feature/..., release/..., chore/... +# -> "refs #: " +# + +set -eu + +COMMIT_MSG_FILE="${1:-}" +COMMIT_SOURCE="${2:-}" + +if [ -z "$COMMIT_MSG_FILE" ] || [ ! -f "$COMMIT_MSG_FILE" ]; then + exit 0 +fi + +# Skip for merges/squashes/amends/templates (avoid fighting Git-generated messages). +case "$COMMIT_SOURCE" in + merge|squash|commit|template) + exit 0 + ;; +esac + +BRANCH="$(git symbolic-ref --quiet --short HEAD 2>/dev/null || true)" +TASK_NUMBER="" +if printf "%s" "$BRANCH" | grep -Eq '^(fix|feature|release|chore)/[0-9]+'; then + TASK_NUMBER="$(printf "%s" "$BRANCH" | sed -E 's#^(fix|feature|release|chore)/([0-9]+).*#\2#')" +else + exit 0 +fi + +FIRST_LINE="$(LC_ALL=C sed -n '1p' "$COMMIT_MSG_FILE" || true)" + +# Do not touch special commit subjects. +case "$FIRST_LINE" in + "Merge "*|"fixup! "*|"squash! "*|"revert! "*) + exit 0 + ;; +esac + +PREFIX="refs #${TASK_NUMBER}: " + +# Already has the right prefix (or already references the number at start) -> no-op. +case "$FIRST_LINE" in + "$PREFIX"*|"refs #${TASK_NUMBER} "*|"refs #${TASK_NUMBER}:"*) + exit 0 + ;; +esac + +# If message already starts with some refs prefix, don't double-prefix. +case "$FIRST_LINE" in + "refs #"*|"refs: #"* ) + exit 0 + ;; +esac + +TMP_FILE="${COMMIT_MSG_FILE}.tmp.$$" +{ + printf "%s%s\n" "$PREFIX" "$FIRST_LINE" + LC_ALL=C sed -n '2,$p' "$COMMIT_MSG_FILE" +} > "$TMP_FILE" + +mv "$TMP_FILE" "$COMMIT_MSG_FILE" +exit 0 + Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Black.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-BlackItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Bold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-BoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-ExtraBold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-ExtraBoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-ExtraLight.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-ExtraLightItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Italic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Light.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-LightItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Medium.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-MediumItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Regular.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-SemiBold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-SemiBoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-Thin.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_18pt-ThinItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Black.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-BlackItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Bold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-BoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-ExtraBold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-ExtraBoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-ExtraLight.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-ExtraLightItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Italic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Light.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-LightItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Medium.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-MediumItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Regular.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-SemiBold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-SemiBoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-Thin.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_24pt-ThinItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Black.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-BlackItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Bold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-BoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-ExtraBold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-ExtraBoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-ExtraLight.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-ExtraLightItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Italic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Light.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-LightItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Medium.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-MediumItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Regular.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-SemiBold.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-SemiBoldItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-Thin.ttf differ Binary files /dev/null and b/public/fonts/Inter/static/Inter_28pt-ThinItalic.ttf differ Binary files /dev/null and b/public/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf differ Binary files /dev/null and b/public/fonts/Inter/Inter-VariableFont_opsz,wght.ttf differ Binary files a/public/fonts/Raleway/static/Raleway-Black.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-BlackItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-Bold.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-BoldItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-ExtraBold.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-ExtraBoldItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-ExtraLight.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-ExtraLightItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-Italic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-Light.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-LightItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-Medium.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-MediumItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-Regular.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-SemiBold.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-SemiBoldItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-Thin.ttf and /dev/null differ Binary files a/public/fonts/Raleway/static/Raleway-ThinItalic.ttf and /dev/null differ Binary files a/public/fonts/Raleway/Raleway-Italic-VariableFont_wght.ttf and /dev/null differ Binary files a/public/fonts/Raleway/Raleway-VariableFont_wght.ttf and /dev/null differ @@ -27,19 +27,19 @@ } @font-face { - font-family: 'Raleway'; + font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap; - src: url('/fonts/Raleway/Raleway-VariableFont_wght.ttf') format('truetype'); + src: url('/fonts/Inter/Inter-VariableFont_opsz,wght.ttf') format('truetype'); } @font-face { - font-family: 'Raleway'; + font-family: 'Inter'; font-style: italic; font-weight: 100 900; font-display: swap; - src: url('/fonts/Raleway/Raleway-Italic-VariableFont_wght.ttf') format('truetype'); + src: url('/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf') format('truetype'); } * { @@ -49,7 +49,7 @@ } html { - font-family: 'Raleway', sans-serif; + font-family: 'Inter', sans-serif; } body { @@ -1,5 +1,4 @@ -import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react' -import { ImageWithState } from './types' +import { Dispatch, SetStateAction, useEffect, useMemo } from 'react' import { Message } from '#/entities/message' export const useImagesLibrary = ( @@ -7,8 +6,6 @@ export const useImagesLibrary = ( current: string | null, images: Message[] ) => { - const [initialCount, setInitialCount] = useState(0) - const esc = (e: KeyboardEvent) => { if (e.key === 'Escape') { e.preventDefault() @@ -18,7 +15,7 @@ export const useImagesLibrary = ( const currentIndex = useMemo( () => images.findIndex((item) => item.file === current), - [current] + [current, images] ) useEffect(() => { @@ -27,8 +24,6 @@ export const useImagesLibrary = ( }, []) return { - initialCount, - setInitialCount, - currentIndex, + currentIndex, } } @@ -1,7 +1,5 @@ -import { debounce } from 'lodash' -import { useCallback, useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { Swiper as SwiperCore } from 'swiper' -import { ImageWithState } from './types' export const useLibrarySwiper = (onSlideFalse: ((...args: any) => any) | undefined, reverse: boolean) => { const [swiper, setSwiper] = useState(null) @@ -41,10 +39,6 @@ export const useLibrarySwiper = (onSlideFalse: ((...args: any) => any) | undefin } }, [swiper]) - // useEffect(() => { - // swiper?.slideTo(currentImageIndex || 0) - // }, [currentImageIndex]) - return { swiper, setSwiper, @@ -0,0 +1,21 @@ +.overlay { + position: fixed; + z-index: 1201; + inset: 0; + width: 100%; + height: 100%; + display: none; +} + +.overlayVisible { + display: block; +} + +.backdrop { + position: absolute; + z-index: 101; + width: 100%; + height: 100%; + background-color: #000000; + opacity: 0.9; +} @@ -1,16 +1,15 @@ -import React, { Dispatch, SetStateAction, useEffect, useMemo, useRef, useState } from 'react' -import Image from 'next/image' +import { Dispatch, SetStateAction, useEffect, useRef } from 'react' +import overlayStyles from './full-screen-modal-overlay.module.scss' import styles from './modal-styles.module.scss' import { ArrowDropDown } from '@mui/icons-material' -import { c, Loader, TooltipCustom } from '#/shared' +import { c } from '#/shared' import { useImagesLibrary } from '../model' import { Swiper, SwiperSlide } from 'swiper/react' import 'swiper/css' import { useLibrarySwiper } from '../model/use-swiper' -import { ImageIcons, useImageIcons } from '#/widgets/messages' -import { Typography } from '@mui/material' +import { useImageIcons } from '#/widgets/messages' import { ModalImage } from './modal-image' import { Message } from '#/entities/message' @@ -32,55 +31,63 @@ export default function FullScreenModal({ onSlideFalse, reverse = false, }: IProps) { - const { initialCount, setInitialCount, currentIndex } = useImagesLibrary( + const { currentIndex } = useImagesLibrary( setModal, current, images ) - const count = useRef(0) + const prevImagesLengthRef = useRef(0) const { swiper, setSwiper, slideNext, slidePrev } = useLibrarySwiper(onSlideFalse, reverse) const { downloadFile } = useImageIcons() + useEffect(() => { - // debugger - if (reverse) - setTimeout(() => { - swiper?.slideNext() - count.current = images.length - }, 400) - else - setTimeout(() => { - swiper?.slideTo(images.length - count.current - 1) - count.current = images.length - }, 400) - }, [images]) + if (!modal) { + prevImagesLengthRef.current = 0 + return + } + if (!swiper) return + + const len = images.length + const prevLen = prevImagesLengthRef.current + + if (prevLen === 0) { + prevImagesLengthRef.current = len + return + } + + if (len === prevLen) return + + if (len < prevLen) { + prevImagesLengthRef.current = len + return + } + + const delta = len - prevLen + + const id = window.setTimeout(() => { + if (reverse) { + swiper.update() + } else { + const nextIndex = swiper.activeIndex + delta + const clamped = Math.max(0, Math.min(nextIndex, len - 1)) + swiper.slideTo(clamped, 0) + } + prevImagesLengthRef.current = len + }, 0) + + return () => clearTimeout(id) + }, [modal, images.length, reverse, swiper]) return (
setModal(false)} > -
+
= ({ successLo utm_source: cookie.utm_source, utm_medium: cookie.utm_medium, utm_campaign: cookie.utm_campaign, - utm_term: cookie.utm_campaign, - utm_content: cookie.utm_campaign, + utm_term: cookie.utm_term, + utm_content: cookie.utm_content, } if (localStorage.getItem('referral')) { @@ -275,7 +275,7 @@ const Account: NextPageWithLayout = () => { alignItems='flex-start' spacing={2} sx={{ - width: desktop ? '90%' : '100%', + width: desktop ? (scope === 'referral' ? '97%' : '90%') : '100%', height: '100%', }} > @@ -351,7 +351,7 @@ const ImageModelPage: NextPageWithLayout = () => { ) : ( <> )} - {botParams && botParams.parameters?.length > 0 && ( + {botParams && botParams.parameters?.length > 0 && Object.keys(filteredParams).length > 0 && ( { )} - {botParams && botParams.parameters?.length > 0 ? ( + {botParams && botParams.parameters?.length > 0 && Object.keys(filteredParams).length > 0 ? ( setOpenFiltersMobile(false)} reset={resetParams} /> @@ -433,7 +433,7 @@ const ImageModelPage: NextPageWithLayout = () => { ) : ( <> )} - {botParams && botParams.parameters?.length > 0 ? ( + {botParams && botParams.parameters?.length > 0 && Object.keys(filteredParams).length > 0 ? ( <> { const { query, push } = useRouter() - const [, setCookie] = useCookies() + const [cookie, setCookie] = useCookies() React.useEffect(() => { Object.entries(query).forEach(([key, value]) => setCookie(key, value)) - }, []) + }, [query]) const { showMessage } = useShowDataStore() @@ -3,23 +3,38 @@ import { useDispatch } from 'react-redux' import { Box } from '@mui/material' import CircularProgress from '@mui/material/CircularProgress' import { useRouter } from 'next/router' +import { useSession } from 'next-auth/react' import { addReferral } from '#/entities/user-account/model/user-type-slice' import { NextPageWithLayout } from '#/pages/_app' +import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' export interface ReferralRegisterProps { email: string } +const REFERRAL_BLOCKED_MESSAGE = + 'Вы не можете повторно зарегистрироваться по реферальной ссылке или стать рефералом после регистрации.' + const ReferralRegister: NextPageWithLayout = ({ email }) => { const dispatch = useDispatch() - const { push } = useRouter() + const { push, replace } = useRouter() + const { status } = useSession() + const { showMessage } = useShowDataStore() useEffect(() => { + if (status === 'loading') return + + if (status === 'authenticated') { + showMessage(REFERRAL_BLOCKED_MESSAGE, 'error') + replace('/') + return + } + localStorage.setItem('referral', email) dispatch(addReferral(email)) push('/register') - }, []) + }, [status, email, dispatch, push, replace, showMessage]) return ( @@ -1,5 +1,6 @@ import * as React from 'react' import { useEffect, useState } from 'react' +import { useCookies } from 'react-cookie' import { useDispatch } from 'react-redux' import Box from '@mui/material/Box' import Stack from '@mui/material/Stack' @@ -27,7 +28,12 @@ const Register: NextPageWithLayout = () => { const referral = useAppSelector((state) => state.user.referral) const dispatch = useDispatch() - const { push } = useRouter() + const { query, push } = useRouter() + const [, setCookie] = useCookies() + + React.useEffect(() => { + Object.entries(query).forEach(([key, value]) => setCookie(key, value)) + }, [query]) const onSuccessRegister = () => { setSuccess(true) @@ -132,7 +132,7 @@ export function BotMessage(props: any) { fontSize: '15px', marginTop: 0.5, textAlign: 'left', - fontFamily: 'Raleway,sans-serif', + fontFamily: 'Inter,sans-serif', borderRadius: '13px', '& p': { color: 'inherit', @@ -171,7 +171,7 @@ } .fontSizeDisplay { - font-family: Raleway, sans-serif; + font-family: Inter, sans-serif; width: 50px; height: 42px; background-color: #d9d9d91a; @@ -226,7 +226,7 @@ } .fontLabel { - font-family: Raleway, sans-serif; + font-family: Inter, sans-serif; font-weight: 500; font-style: normal; font-size: 15px; @@ -23,7 +23,7 @@ export const FullscreenMessageModal: React.FC = ({ modelTitle, messageContent, }) => { - const [fontFamily, setFontFamily] = useState('Raleway,sans-serif') + const [fontFamily, setFontFamily] = useState('Inter,sans-serif') const [fontSize, setFontSize] = useState(16) const contentRef = useRef(null) const markdownRef = useRef(null) @@ -213,7 +213,7 @@ export const FullscreenMessageModal: React.FC = ({ } } - const fonts = ['Raleway,sans-serif', 'Arial', 'Times New Roman', 'Courier New', 'Georgia', 'Verdana'] + const fonts = ['Inter,sans-serif', 'Arial', 'Times New Roman', 'Courier New', 'Georgia', 'Verdana'] return ( { }, [data?.access]) return ( - - + + { maxWidth: '350px', width: '100%', color: '#8280FF', + position: 'relative', }} gap={2} justifyContent={'space-between'} direction={'row'} alignItems={'center'} > - {device === 'mobile' ? url.slice(0, 35) + '...' : url.slice(0, 40) + '...'} + + {url} + { width: '20px', height: '20px', cursor: 'pointer', + position: 'absolute', + right: '10px', }} width={100} height={100} @@ -242,7 +266,7 @@ export const Referral = ({ device }: IProps) => { { color: '#A4AAB5', fontWeight: '600', letterSpacing: '0.3px', - marginBottom: '15px', + marginBottom: '16px', }} > МОИ РЕФЕРАЛЫ