1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

Добавил тему "Веспера"

This commit is contained in:
muerwre 2022-08-14 15:19:54 +07:00 committed by GitHub
parent 5d34090238
commit aee4b662d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
148 changed files with 1331 additions and 1338 deletions

View file

@ -1,55 +0,0 @@
import React, { VFC } from 'react';
import { observer } from 'mobx-react-lite';
import { BrowserRouter } from 'react-router-dom';
import { PageCoverProvider } from '~/components/containers/PageCoverProvider';
import { Modal } from '~/containers/dialogs/Modal';
import { BottomContainer } from '~/containers/main/BottomContainer';
import { MainRouter } from '~/containers/main/MainRouter';
import { DragDetectorProvider } from '~/hooks/dom/useDragDetector';
import { useGlobalLoader } from '~/hooks/dom/useGlobalLoader';
import { MainLayout } from '~/layouts/MainLayout';
import { Sprites } from '~/sprites/Sprites';
import { UserContextProvider } from '~/utils/context/UserContextProvider';
import { AudioPlayerProvider } from '~/utils/providers/AudioPlayerProvider';
import { AuthProvider } from '~/utils/providers/AuthProvider';
import { MetadataProvider } from '~/utils/providers/MetadataProvider';
import { SWRConfigProvider } from '~/utils/providers/SWRConfigProvider';
import { SearchProvider } from '~/utils/providers/SearchProvider';
import { ToastProvider } from '~/utils/providers/ToastProvider';
const App: VFC = observer(() => {
useGlobalLoader();
return (
<BrowserRouter>
<SWRConfigProvider>
<UserContextProvider>
<DragDetectorProvider>
<PageCoverProvider>
<SearchProvider>
<AudioPlayerProvider>
<MetadataProvider>
<AuthProvider>
<MainLayout>
<ToastProvider />
<Modal />
<Sprites />
<MainRouter />
</MainLayout>
<BottomContainer />
</AuthProvider>
</MetadataProvider>
</AudioPlayerProvider>
</SearchProvider>
</PageCoverProvider>
</DragDetectorProvider>
</UserContextProvider>
</SWRConfigProvider>
</BrowserRouter>
);
});
export { App };

View file

@ -4,9 +4,10 @@ import { BorisContacts } from '~/components/boris/BorisContacts';
import { BorisStats } from '~/components/boris/BorisStats';
import { Group } from '~/components/containers/Group';
import { SuperPowersToggle } from '~/containers/auth/SuperPowersToggle';
import styles from '~/layouts/BorisLayout/styles.module.scss';
import { BorisUsageStats } from '~/types/boris';
import styles from './styles.module.scss';
interface Props {
isUser: boolean;
stats: BorisUsageStats;
@ -14,14 +15,14 @@ interface Props {
}
const BorisSidebar: FC<Props> = ({ isUser, stats, isLoading }) => (
<Group className={styles.stats__container}>
<Group className={styles.container}>
<div className={styles.super_powers}>
<SuperPowersToggle />
</div>
<BorisContacts />
<div className={styles.stats__wrap}>
<div className={styles.wrap}>
<BorisStats stats={stats} isLoading={isLoading} />
</div>
</Group>

View file

@ -0,0 +1,23 @@
@import 'src/styles/variables';
.wrap {
@include tablet {
display: none;
}
}
.container {
background: $content_bg_dark;
border-radius: 0 $radius $radius 0;
padding: $gap;
box-sizing: border-box;
flex: 0 0 auto;
@include tablet {
border-radius: 0;
}
}
.super_powers {
padding: $gap * 2 0;
}

View file

@ -1,10 +1,4 @@
@import "src/styles/variables";
$secondary_color: darken(desaturate($blue, 100%), 30%);
$vk_color: $secondary_color;
.dialog {
}
@import 'src/styles/variables';
.wrap {
display: flex;
@ -17,32 +11,6 @@ $vk_color: $secondary_color;
}
}
.secondary_button {
background: $content_bg;
box-shadow: inset $vk_color 0 0 0 2px;
color: $vk_color;
svg {
fill: $vk_color;
margin-right: $gap;
}
}
.forgot_button {
opacity: 0.5;
}
.buttons {
margin: $gap * 2 0 0 0 !important;
padding: $gap * 2 0 0 0;
border-top: 1px solid black;
}
.links {
font: $font_14_regular;
text-align: center;
a {
color: lighten($content_bg, 40%);
}
}

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrap {
padding: $login_dialog_padding;
@ -13,6 +13,6 @@
span {
padding-left: $gap;
color: darken(white, 50%);
color: $gray_50;
}
}

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrap {
padding: $gap $gap $gap * 4;
@ -11,7 +11,7 @@
.text {
font: $font_14_regular;
padding: $gap;
color: darken(white, 50%);
color: $gray_50;
}
.shade,
@ -34,18 +34,18 @@
text-transform: uppercase;
font: $font_18_semibold;
text-align: center;
color: $wisegreen;
color: $color_primary;
svg {
fill: $wisegreen;
fill: $color_primary;
}
}
.error_shade {
color: $red;
color: $color_danger;
svg {
fill: $red;
fill: $color_danger;
}
}

View file

@ -15,24 +15,24 @@ import styles from './styles.module.scss';
interface RestoreRequestDialogProps extends DialogComponentProps {}
const RestoreRequestDialog: VFC<RestoreRequestDialogProps> = ({ onRequestClose }) => {
const RestoreRequestDialog: VFC<RestoreRequestDialogProps> = ({
onRequestClose,
}) => {
useCloseOnEscape(onRequestClose);
const [isSent, setIsSent] = useState(false);
const onSent = useCallback(() => setIsSent(true), [setIsSent]);
const { isSubmitting, handleSubmit, handleChange, errors, values } = useRestoreRequestForm(
apiRequestRestoreCode,
onSent
);
const { isSubmitting, handleSubmit, handleChange, errors, values } =
useRestoreRequestForm(apiRequestRestoreCode, onSent);
const buttons = useMemo(
() => (
<Group className={styles.buttons}>
<Button color="secondary">Восстановить</Button>
<Button>Восстановить</Button>
</Group>
),
[]
[],
);
const header = useMemo(() => <div className={styles.illustration} />, []);
@ -58,7 +58,8 @@ const RestoreRequestDialog: VFC<RestoreRequestDialogProps> = ({ onRequestClose }
/>
<div className={styles.text}>
Введите имя пользователя или адрес почты. Мы пришлем ссылку для сброса пароля.
Введите имя пользователя или адрес почты. Мы пришлем ссылку для
сброса пароля.
</div>
</Group>
</div>

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrap {
padding: $gap $gap $gap * 4;
@ -11,7 +11,7 @@
.text {
font: $font_14_regular;
padding: $gap;
color: darken(white, 50%);
color: $gray_50;
}
.illustration {

View file

@ -1,4 +1,4 @@
@import "../../../styles/variables";
@import '../../../styles/variables';
.wrap {
display: flex;
@ -25,7 +25,7 @@
left: 0;
height: 60px;
width: 100%;
background: linear-gradient(transparentize($content_bg, 1), $content_bg 90%);
background: linear-gradient(transparent, $content_bg 90%);
pointer-events: none;
touch-action: none;
@ -73,7 +73,7 @@
.search {
@include outer_shadow();
background: lighten($content_bg, 3%);
background: $content_bg_lighter;
padding: $gap;
border-radius: $radius;
}
@ -91,7 +91,6 @@
}
.toggles {
& > div {
padding: $gap;
font: $font_14_semibold;

View file

@ -1,4 +1,4 @@
@import "src/styles/variables.scss";
@import 'src/styles/variables.scss';
.title {
padding-bottom: $gap;
@ -16,7 +16,7 @@
@include outer_shadow;
border-radius: $radius;
background: $comment_bg;
background: $content_bg_light;
padding: $gap;
}

View file

@ -52,9 +52,10 @@ const Header: FC<HeaderProps> = observer(() => {
[borisCommentedAt, isUser, user.last_seen_boris],
);
const hasLabUpdates = useMemo(() => labStats.updates.length > 0, [
labStats.updates,
]);
const hasLabUpdates = useMemo(
() => labStats.updates.length > 0,
[labStats.updates],
);
const hasFlowUpdates = useMemo(() => flowUpdates.length > 0, [flowUpdates]);
// Needed for SSR
@ -113,12 +114,7 @@ const Header: FC<HeaderProps> = observer(() => {
)}
{!isUser && (
<Button
className={styles.user_button}
onClick={onLogin}
round
color="secondary"
>
<Button className={styles.user_button} onClick={onLogin} round>
ВДОХ
</Button>
)}

View file

@ -1,4 +1,4 @@
@import "../../../styles/variables";
@import '../../../styles/variables';
@keyframes appear {
from {
@ -28,7 +28,7 @@
}
&.is_scrolled {
@include blur();
@include blur;
}
}
@ -86,7 +86,7 @@
white-space: nowrap;
&:hover {
color: $red;
color: $color_link;
}
&::before {
@ -109,7 +109,7 @@
width: 6px;
height: 6px;
border-radius: 4px;
background: lighten($red, 10%);
background: $color_link;
right: 12px;
top: 6px;
transition: opacity 0.5s;
@ -123,11 +123,11 @@
}
&.lab::after {
background: lighten($blue, 10%);
background: $color_lab;
}
&.boris::after {
background: lighten($wisegreen, 10%);
background: $color_primary;
}
@include tablet {

View file

@ -1,4 +1,4 @@
@import "src/styles/variables.scss";
@import 'src/styles/variables.scss';
.sticky {
width: 100%;
@ -22,7 +22,6 @@
}
}
.panel {
flex: 1 3;
display: flex;
@ -38,13 +37,6 @@
}
}
.buttons {
background: $node_buttons_bg;
flex: 1;
border-radius: $panel_radius;
box-shadow: $comment_shadow;
}
.left {
flex: 1;
min-width: 0;

View file

@ -1,11 +1,11 @@
@import "../../../styles/variables";
@import '../../../styles/variables';
.wrap {
}
.list {
border-radius: $radius;
background: transparentize(white, 0.95);
background: $gray_90;
}
.buttons {
@ -38,7 +38,7 @@
grid-template-columns: 20px auto 20px;
grid-column-gap: $gap * 1.5;
align-items: center;
border-bottom: 1px solid transparentize(white, 0.9);
border-bottom: 1px solid $gray_90;
padding: $gap;
&:last-child {
@ -70,7 +70,7 @@
cursor: pointer;
opacity: 0.5;
transition: opacity 0.25s;
fill: $red;
fill: $color_danger;
display: flex;
align-items: center;

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrap {
justify-content: flex-start;
@ -25,6 +25,6 @@
}
.description {
color: transparentize($color: white, $amount: 0.7);
color: $gray_25;
font: $font_14_regular;
}

View file

@ -1,54 +0,0 @@
import React, { FC } from 'react';
import { Anchor } from '~/components/common/Anchor';
import { NodeNoComments } from '~/components/node/NodeNoComments';
import { Message } from '~/components/profile/Message';
import { useUser } from '~/hooks/auth/useUser';
import { useMessages } from '~/hooks/messages/useMessages';
import { useProfileContext } from '~/utils/providers/ProfileProvider';
import styles from './styles.module.scss';
const ProfileMessages: FC = () => {
const { profile, isLoading: isLoadingProfile } = useProfileContext();
const { user } = useUser();
const { messages, isLoading: isLoadingMessages } = useMessages(profile?.username || '');
if (!messages.length || isLoadingProfile)
return <NodeNoComments is_loading={isLoadingMessages || isLoadingProfile} />;
if (messages.length <= 0) {
return null;
}
return (
<div className={styles.messages}>
<div className={styles.warning}>
<p>В будущем мы собираемся убрать сообщения, превратив их в заметки.</p>
<p>
Вся твоя история сообщений, написанных себе, сохранится. Исчезнут только сообщения другим
участникам.
</p>
<p>
Давай обсудим это в <Anchor href="/boris">Борисе</Anchor>, если это так важно.
</p>
</div>
{messages
.filter(message => !!message.text)
.map((
message // TODO: show files / memo
) => (
<Message message={message} incoming={user.id !== message.from.id} key={message.id} />
))}
{!isLoadingMessages && messages.length > 0 && (
<div className={styles.placeholder}>Когда-нибудь здесь будут еще сообщения</div>
)}
</div>
);
};
export { ProfileMessages };

View file

@ -1,43 +0,0 @@
@import "src/styles/variables";
.messages {
padding: $gap;
background: $node_bg;
display: flex;
flex-direction: column !important;
overflow: auto;
& > * {
margin: $gap * 0.5 0;
&:last-child {
margin-top: 0;
}
&:first-child {
margin-bottom: 0;
}
}
}
.placeholder {
font: $font_12_regular;
padding: $gap;
text-align: center;
}
div.warning.warning {
padding: $gap;
box-shadow: $red 0 0 0 2px;
border-radius: $radius;
font: $font_14_semibold;
margin-bottom: $gap * 2;
p {
margin-bottom: $gap;
&:last-child {
margin-bottom: 0;
}
}
}

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrap {
@include outer_shadow;
@ -9,7 +9,7 @@
align-items: stretch;
justify-content: stretch;
flex-direction: column;
background: $comment_bg;
background: $content_bg_light;
height: 100%;
border-radius: $radius;
}
@ -39,7 +39,7 @@
font: $font_14_regular;
box-sizing: border-box;
width: 100%;
color: transparentize(white, 0.5);
color: $gray_50;
}
.description {

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrapper {
@include outer_shadow;
@ -35,10 +35,10 @@ div.top.top {
.status {
font: $font_12_regular;
margin-top: $gap;
color: darken(white, 50%);
color: $gray_50;
&.active {
color: $olive;
color: $color_online;
}
&::before {

View file

@ -4,13 +4,12 @@ import classNames from 'classnames';
import { Filler } from '~/components/containers/Filler';
import { Group } from '~/components/containers/Group';
import { Button } from '~/components/input/Button';
import { Icon } from '~/components/input/Icon';
import { MenuButton, MenuItemWithIcon } from '~/components/menu';
import { Zone } from '~/components/containers/Zone';
import { VerticalMenu } from '~/components/menu/VerticalMenu';
import { useStackContext } from '~/components/sidebar/SidebarStack';
import { ProfileSidebarHead } from '~/containers/profile/ProfileSidebarHead';
import { ProfileStats } from '~/containers/profile/ProfileStats';
import { ThemeSwitcher } from '~/containers/settings/ThemeSwitcher';
import { useAuth } from '~/hooks/auth/useAuth';
import markdown from '~/styles/common/markdown.module.scss';
@ -50,9 +49,15 @@ const ProfileSidebarMenu: VFC<ProfileSidebarMenuProps> = ({ onClose }) => {
</VerticalMenu.Item>
</VerticalMenu>
<div className={styles.toggles}>
<ProfileToggles />
</div>
<Group className={styles.toggles}>
<Zone>
<ProfileToggles />
</Zone>
<Zone>
<ThemeSwitcher />
</Zone>
</Group>
<div className={styles.stats}>
<ProfileStats />

View file

@ -7,11 +7,9 @@ import { SuperPowersToggle } from '~/containers/auth/SuperPowersToggle';
interface ProfileTogglesProps {}
const ProfileToggles: FC<ProfileTogglesProps> = () => (
<Zone>
<Group>
<SuperPowersToggle />
</Group>
</Zone>
<Group>
<SuperPowersToggle />
</Group>
);
export { ProfileToggles };

View file

@ -25,7 +25,7 @@ const List = () => {
return (
<>
{notes.map(note => (
{notes.map((note) => (
<NoteCard
remove={() => onRemove(note.id)}
update={(text, callback) => update(note.id, text, callback)}
@ -59,7 +59,6 @@ const SettingsNotes: VFC<SettingsNotesProps> = () => {
onClick={() => setFormIsShown(true)}
size="mini"
iconRight="plus"
color="secondary"
>
Добавить
</Button>

View file

@ -0,0 +1,47 @@
import React, { FC } from 'react';
import classNames from 'classnames';
import { Card } from '~/components/containers/Card';
import { Group } from '~/components/containers/Group';
import { Theme, themeColors } from '~/constants/themes';
import { useTheme } from '~/utils/providers/ThemeProvider';
import styles from './styles.module.scss';
interface ThemeSwitcherProps {}
const ThemeSwitcher: FC<ThemeSwitcherProps> = () => {
const { theme, setTheme } = useTheme();
return (
<Group horizontal>
{Object.entries(themeColors).map(([id, item]) => (
<Card
key={id}
className={classNames(styles.card, {
[styles.active]: theme === id,
})}
style={{ background: item.background }}
role="button"
onClick={() => setTheme(id as Theme)}
>
<Group>
<Group horizontal>
{item.colors.map((color) => (
<div
key={color}
className={styles.sample}
style={{ background: color }}
/>
))}
</Group>
<div className={styles.title}>{item.name}</div>
</Group>
</Card>
))}
</Group>
);
};
export { ThemeSwitcher };

View file

@ -0,0 +1,30 @@
@import 'src/styles/variables';
.button {
flex: 1;
}
.card {
padding: $gap;
flex: 1;
cursor: pointer;
&.active {
outline: 1px solid $color_primary;
}
}
.title {
font: $font_12_semibold;
text-align: left;
text-transform: uppercase;
color: $gray_50;
}
.sample {
@include outer_shadow;
border-radius: 100%;
flex: 0 1 20px;
height: 20px;
}

View file

@ -1,7 +1,4 @@
@import "src/styles/variables";
$pad_danger: mix($red, $content_bg, 70%);
$pad_usual: mix(white, $content_bg, 10%);
@import 'src/styles/variables';
.about {
flex: 4;
@ -17,9 +14,6 @@ $pad_usual: mix(white, $content_bg, 10%);
padding: 0 $gap 0;
}
.grid {
}
div.base_info.base_info {
align-items: stretch;
}

View file

@ -1,4 +1,4 @@
@import "src/styles/variables";
@import 'src/styles/variables';
.wrap {
@include sidebar_content(400px);
@ -56,7 +56,7 @@
padding-left: $gap * 2;
svg {
fill: transparentize(white, 0.5);
fill: $gray_50;
}
}
@ -65,28 +65,20 @@
bottom: 0;
left: 0;
width: 100%;
background: darken($content_bg, 2%);
background: $content_bg_dark;
height: 2px;
z-index: 2;
pointer-events: none;
touch-action: none;
}
.bar {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: lighten($content_bg, 20%);
}
.none {
padding: 40px $gap;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: transparentize(white, 0.9);
color: $gray_90;
fill: currentColor;
font: $font_18_semibold;
stroke: none;

View file

@ -19,13 +19,8 @@ const placeholder = 'Добавить';
const prepareInput = (input: string): string[] => {
return input
.split(',')
.map((title: string) =>
title
.trim()
.substring(0, 64)
.toLowerCase(),
)
.filter(el => el.length > 0);
.map((title: string) => title.trim().substring(0, 64).toLowerCase())
.filter((el) => el.length > 0);
};
interface IProps {
@ -88,7 +83,7 @@ const TagInput: FC<IProps> = ({ exclude, onAppend, onClearTag, onSubmit }) => {
const onFocus = useCallback(() => setFocused(true), []);
const onBlur = useCallback(
event => {
(event) => {
if (!wrapper.current || !ref.current) {
return;
}
@ -122,9 +117,7 @@ const TagInput: FC<IProps> = ({ exclude, onAppend, onClearTag, onSubmit }) => {
[onAppend, setInput],
);
const feature = useMemo(() => (input?.substr(0, 1) === '/' ? 'green' : ''), [
input,
]);
const isAlbumTag = useMemo(() => input?.substr(0, 1) === '/', [input]);
useEffect(() => {
if (!focused) return;
@ -138,7 +131,7 @@ const TagInput: FC<IProps> = ({ exclude, onAppend, onClearTag, onSubmit }) => {
<TagWrapper
title={input || placeholder}
hasInput={true}
feature={feature}
color={isAlbumTag ? 'primary' : undefined}
>
<input
type="text"