mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
Добавили заметки в сайдбар (#126)
* added notes sidebar * added note dropping and editing * added sidebar navigation * handling sidebarchanges over time * using router back for closing sidebar * fixed tripping inside single sidebar * added superpowers toggle to sidebar * user button opens sidebar now * added profile cover for profile sidebar * removed profile sidebar completely * ran prettier over project * added note not found error literal
This commit is contained in:
parent
fe3db608d6
commit
5d34090238
72 changed files with 1241 additions and 664 deletions
|
@ -9,22 +9,20 @@ import { stripHTMLTags } from '~/utils/stripHTMLTags';
|
|||
export const formatTextSanitizeYoutube = (text: string): string =>
|
||||
text.replace(
|
||||
/(https?:\/\/(www\.)?(youtube\.com|youtu\.be)\/(watch)?(\?v=)?[\w\-&=]+)/gim,
|
||||
'\n$1\n'
|
||||
'\n$1\n',
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes HTML tags
|
||||
*/
|
||||
export const formatTextSanitizeTags = (text: string): string => stripHTMLTags(text);
|
||||
export const formatTextSanitizeTags = (text: string): string =>
|
||||
stripHTMLTags(text);
|
||||
|
||||
/**
|
||||
* Returns clickable usernames
|
||||
*/
|
||||
export const formatTextClickableUsernames = (text: string): string =>
|
||||
text.replace(
|
||||
/~([\wа-яА-Я-]+)/giu,
|
||||
`<span class="username" onClick="window.postMessage({ type: '${EventMessageType.OpenProfile}', username: '$1'});">~$1</span>`
|
||||
);
|
||||
text.replace(/~([\wа-яА-Я-]+)/giu, `<span class="username">~$1</span>`);
|
||||
|
||||
/**
|
||||
* Makes gray comments
|
||||
|
@ -41,10 +39,13 @@ export const formatTextComments = (text: string): string =>
|
|||
*/
|
||||
export const formatTextTodos = (text: string): string =>
|
||||
text
|
||||
.replace(/\/\/\s*(todo|туду):?\s*([^\n]+)/gim, '// <span class="todo">$1</span> $2')
|
||||
.replace(
|
||||
/\/\/\s*(todo|туду):?\s*([^\n]+)/gim,
|
||||
'// <span class="todo">$1</span> $2',
|
||||
)
|
||||
.replace(
|
||||
/\/\/\s*(done|сделано|сделал|готово|fixed|пофикшено|фиксед):?\s*([^\n]+)/gim,
|
||||
'// <span class="done">$1</span> $2'
|
||||
'// <span class="done">$1</span> $2',
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -56,7 +57,8 @@ export const formatExclamations = (text: string): string =>
|
|||
/**
|
||||
* Replaces -- with dash
|
||||
*/
|
||||
export const formatTextDash = (text: string): string => text.replace(' -- ', ' — ');
|
||||
export const formatTextDash = (text: string): string =>
|
||||
text.replace(' -- ', ' — ');
|
||||
|
||||
/**
|
||||
* Formats with markdown
|
||||
|
|
21
src/utils/providers/NoteProvider.tsx
Normal file
21
src/utils/providers/NoteProvider.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { createContext, FC, useContext } from 'react';
|
||||
|
||||
import { useNotes } from '~/hooks/notes/useNotes';
|
||||
|
||||
const NoteContext = createContext<ReturnType<typeof useNotes>>({
|
||||
notes: [],
|
||||
hasMore: false,
|
||||
loadMore: async () => Promise.resolve(undefined),
|
||||
isLoading: false,
|
||||
create: () => Promise.resolve(),
|
||||
remove: () => Promise.resolve(),
|
||||
update: (id: number, text: string) => Promise.resolve(),
|
||||
});
|
||||
|
||||
export const NoteProvider: FC = ({ children }) => {
|
||||
const notes = useNotes('');
|
||||
|
||||
return <NoteContext.Provider value={notes}>{children}</NoteContext.Provider>;
|
||||
};
|
||||
|
||||
export const useNotesContext = () => useContext(NoteContext);
|
|
@ -1,78 +1,98 @@
|
|||
import { Context, createContext, createElement, FunctionComponent, PropsWithChildren, useCallback, useContext, useMemo } from 'react';
|
||||
import {
|
||||
Context,
|
||||
createContext,
|
||||
createElement,
|
||||
PropsWithChildren,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
|
||||
import { useRouter } from 'next/router';
|
||||
import { has } from 'ramda';
|
||||
import { has, omit } from 'ramda';
|
||||
|
||||
import { ModalWrapper } from '~/components/dialogs/ModalWrapper';
|
||||
import { sidebarComponents, SidebarName } from '~/constants/sidebar';
|
||||
import { DialogComponentProps } from '~/types/modal';
|
||||
import { SidebarName } from '~/constants/sidebar';
|
||||
import { sidebarComponents } from '~/constants/sidebar/components';
|
||||
import { SidebarComponent, SidebarProps } from '~/types/sidebar';
|
||||
|
||||
type ContextValue = typeof SidebarContext extends Context<infer U> ? U : never;
|
||||
type Name = keyof typeof sidebarComponents;
|
||||
|
||||
// TODO: use it to store props for sidebar
|
||||
type Props<T extends Name> = typeof sidebarComponents[T] extends FunctionComponent<infer U>
|
||||
? U extends DialogComponentProps ? Omit<U, 'onRequestClose'> : U
|
||||
: {};
|
||||
|
||||
const SidebarContext = createContext({
|
||||
current: undefined as SidebarName | undefined,
|
||||
open: <T extends Name>(name: T) => {},
|
||||
close: () => {},
|
||||
open: <T extends SidebarComponent>(name: T, props: SidebarProps<T>) => {},
|
||||
close: () => {},
|
||||
});
|
||||
|
||||
export const SidebarProvider = <T extends Name>({ children }: PropsWithChildren<{}>) => {
|
||||
export const SidebarProvider = <T extends SidebarComponent>({
|
||||
children,
|
||||
}: PropsWithChildren<{}>) => {
|
||||
const router = useRouter();
|
||||
const current = useMemo(() => {
|
||||
const val = router.query.sidebar as SidebarName | undefined
|
||||
const val = router.query.sidebar as SidebarName | undefined;
|
||||
|
||||
return val && has(val, sidebarComponents) ? val : undefined;
|
||||
}, [router]);
|
||||
|
||||
const open = useCallback(
|
||||
<T extends Name>(name: T) => {
|
||||
<T extends SidebarComponent>(name: T, props: SidebarProps<T>) => {
|
||||
const [path] = router.asPath.split('?');
|
||||
void router.push(path + '?sidebar=' + name, path + '?sidebar=' + name, {
|
||||
const query = Object.entries(props as {})
|
||||
.filter(([, val]) => val)
|
||||
.map(([name, val]) => `${name}=${val}`)
|
||||
.join('&');
|
||||
const url = path + '?sidebar=' + name + (query && `&${query}`);
|
||||
|
||||
// don't store history inside the same sidebar
|
||||
if (router.query?.sidebar === name) {
|
||||
void router.replace(url, url, {
|
||||
shallow: true,
|
||||
scroll: false,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void router.push(url, url, {
|
||||
shallow: true,
|
||||
scroll: false,
|
||||
});
|
||||
},
|
||||
[router]
|
||||
[router],
|
||||
);
|
||||
|
||||
const close = useCallback(
|
||||
() => {
|
||||
const [path] = router.asPath.split('?');
|
||||
const close = useCallback(() => {
|
||||
const [path] = router.asPath.split('?');
|
||||
|
||||
console.log('trying to close');
|
||||
void router.replace(path, path, {
|
||||
shallow: true,
|
||||
scroll: false,
|
||||
});
|
||||
}, [router]);
|
||||
|
||||
void router.replace(path, path, {
|
||||
shallow: true,
|
||||
scroll: false,
|
||||
});
|
||||
},
|
||||
[router]
|
||||
const value = useMemo<ContextValue>(
|
||||
() => ({
|
||||
current,
|
||||
open,
|
||||
close,
|
||||
}),
|
||||
[current, open, close],
|
||||
);
|
||||
|
||||
const value = useMemo<ContextValue>(() => ({
|
||||
current,
|
||||
open,
|
||||
close,
|
||||
}), [current, open, close]);
|
||||
|
||||
return (
|
||||
<SidebarContext.Provider value={value}>
|
||||
{children}
|
||||
{current &&
|
||||
{current && (
|
||||
<ModalWrapper onOverlayClick={close}>
|
||||
{createElement(
|
||||
sidebarComponents[current],
|
||||
{ onRequestClose: close } as any
|
||||
)}
|
||||
{createElement(sidebarComponents[current], {
|
||||
onRequestClose: close,
|
||||
openSidebar: open,
|
||||
...omit(['sidebar'], router.query),
|
||||
} as any)}
|
||||
</ModalWrapper>
|
||||
}
|
||||
)}
|
||||
</SidebarContext.Provider>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const useSidebar = () => useContext(SidebarContext);
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import { EventMessageType } from '~/constants/events';
|
||||
|
||||
export const openUserProfile = (username?: string) => {
|
||||
if (!username) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.postMessage({ type: EventMessageType.OpenProfile, username }, '*');
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue