2023-11-14 15:10:00 +00:00
|
|
|
|
import { getPagePath } from '@nanostores/router'
|
2022-11-13 19:35:57 +00:00
|
|
|
|
import { clsx } from 'clsx'
|
2024-02-04 11:25:21 +00:00
|
|
|
|
import { Show, createMemo, createSignal, onCleanup, onMount } from 'solid-js'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
|
|
|
|
|
import { useEditorContext } from '../../context/editor'
|
2023-02-17 09:21:02 +00:00
|
|
|
|
import { useLocalize } from '../../context/localize'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
import { useNotifications } from '../../context/notifications'
|
|
|
|
|
import { useSession } from '../../context/session'
|
|
|
|
|
import { router, useRouter } from '../../stores/router'
|
|
|
|
|
import { showModal } from '../../stores/ui'
|
2024-02-04 11:25:21 +00:00
|
|
|
|
import { Userpic } from '../Author/Userpic'
|
2023-04-05 21:51:01 +00:00
|
|
|
|
import { Button } from '../_shared/Button'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
import { Icon } from '../_shared/Icon'
|
2023-05-13 17:00:58 +00:00
|
|
|
|
import { Popover } from '../_shared/Popover'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
|
|
|
|
|
|
|
|
|
|
import { ProfilePopup } from './ProfilePopup'
|
|
|
|
|
|
2024-02-05 19:05:49 +00:00
|
|
|
|
import { useSnackbar } from '../../context/snackbar'
|
2024-04-08 11:26:20 +00:00
|
|
|
|
import { Popup } from '../_shared/Popup'
|
|
|
|
|
import { VotersList } from '../_shared/VotersList'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
import styles from './Header/Header.module.scss'
|
2022-11-13 19:35:57 +00:00
|
|
|
|
|
2023-08-04 15:59:36 +00:00
|
|
|
|
type Props = {
|
2022-11-13 19:35:57 +00:00
|
|
|
|
setIsProfilePopupVisible: (value: boolean) => void
|
|
|
|
|
}
|
2023-08-04 15:59:36 +00:00
|
|
|
|
|
|
|
|
|
type IconedButtonProps = {
|
2023-05-13 17:00:58 +00:00
|
|
|
|
value: string
|
|
|
|
|
icon: string
|
|
|
|
|
action: () => void
|
|
|
|
|
}
|
2022-11-13 19:35:57 +00:00
|
|
|
|
|
2023-05-13 17:00:58 +00:00
|
|
|
|
const MD_WIDTH_BREAKPOINT = 992
|
2023-08-04 15:59:36 +00:00
|
|
|
|
export const HeaderAuth = (props: Props) => {
|
2023-02-17 09:21:02 +00:00
|
|
|
|
const { t } = useLocalize()
|
2022-11-13 19:35:57 +00:00
|
|
|
|
const { page } = useRouter()
|
2024-01-18 17:34:17 +00:00
|
|
|
|
const { session, author, isAuthenticated, isSessionLoaded } = useSession()
|
2024-02-04 17:40:15 +00:00
|
|
|
|
const { unreadNotificationsCount, showNotificationsPanel } = useNotifications()
|
|
|
|
|
const { form, toggleEditorPanel, saveShout, publishShout } = useEditorContext()
|
2023-04-26 02:37:29 +00:00
|
|
|
|
|
2022-11-13 19:35:57 +00:00
|
|
|
|
const handleBellIconClick = (event: Event) => {
|
|
|
|
|
event.preventDefault()
|
|
|
|
|
|
|
|
|
|
if (!isAuthenticated()) {
|
|
|
|
|
showModal('auth')
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-10-14 11:39:24 +00:00
|
|
|
|
|
|
|
|
|
showNotificationsPanel()
|
2022-11-13 19:35:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-31 12:23:18 +00:00
|
|
|
|
const isEditorPage = createMemo(() => page().route === 'edit' || page().route === 'editSettings')
|
2023-10-14 11:39:24 +00:00
|
|
|
|
const isNotificationsVisible = createMemo(() => isAuthenticated() && !isEditorPage())
|
|
|
|
|
const isSaveButtonVisible = createMemo(() => isAuthenticated() && isEditorPage())
|
2024-04-08 11:26:20 +00:00
|
|
|
|
const isCreatePostButtonVisible = createMemo(() => !isEditorPage())
|
2024-01-18 17:34:17 +00:00
|
|
|
|
const isAuthenticatedControlsVisible = createMemo(
|
|
|
|
|
() => isAuthenticated() && session()?.user?.email_verified,
|
|
|
|
|
)
|
2023-04-20 13:58:56 +00:00
|
|
|
|
|
2023-05-01 18:32:32 +00:00
|
|
|
|
const handleBurgerButtonClick = () => {
|
2023-05-03 16:13:48 +00:00
|
|
|
|
toggleEditorPanel()
|
2023-05-01 18:32:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-08 17:21:06 +00:00
|
|
|
|
const handleSaveButtonClick = () => {
|
2023-08-04 15:59:36 +00:00
|
|
|
|
saveShout(form)
|
2023-05-08 17:21:06 +00:00
|
|
|
|
}
|
2023-05-05 20:05:50 +00:00
|
|
|
|
|
2023-05-13 17:00:58 +00:00
|
|
|
|
const [width, setWidth] = createSignal(0)
|
2024-04-08 11:26:20 +00:00
|
|
|
|
const [editorMode, setEditorMode] = createSignal(t('Editing'))
|
2023-10-14 11:39:24 +00:00
|
|
|
|
|
2023-05-13 17:00:58 +00:00
|
|
|
|
onMount(() => {
|
2023-10-14 11:39:24 +00:00
|
|
|
|
const handleResize = () => setWidth(window.innerWidth)
|
2023-05-13 17:00:58 +00:00
|
|
|
|
handleResize()
|
|
|
|
|
window.addEventListener('resize', handleResize)
|
|
|
|
|
onCleanup(() => window.removeEventListener('resize', handleResize))
|
|
|
|
|
})
|
|
|
|
|
|
2023-08-04 15:59:36 +00:00
|
|
|
|
const renderIconedButton = (buttonProps: IconedButtonProps) => {
|
2023-05-13 17:00:58 +00:00
|
|
|
|
return (
|
|
|
|
|
<Show
|
|
|
|
|
when={width() < MD_WIDTH_BREAKPOINT}
|
|
|
|
|
fallback={
|
|
|
|
|
<Button
|
2023-08-04 15:59:36 +00:00
|
|
|
|
value={<span class={styles.textLabel}>{buttonProps.value}</span>}
|
2023-10-31 21:21:30 +00:00
|
|
|
|
variant={'light'}
|
2023-08-04 15:59:36 +00:00
|
|
|
|
onClick={buttonProps.action}
|
2023-10-31 21:21:30 +00:00
|
|
|
|
class={styles.editorControl}
|
2023-05-13 17:00:58 +00:00
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
>
|
2023-08-04 15:59:36 +00:00
|
|
|
|
<Popover content={buttonProps.value}>
|
2023-05-13 17:00:58 +00:00
|
|
|
|
{(ref) => (
|
|
|
|
|
<Button
|
|
|
|
|
ref={ref}
|
2023-10-31 21:21:30 +00:00
|
|
|
|
variant={'light'}
|
2023-08-04 15:59:36 +00:00
|
|
|
|
onClick={buttonProps.action}
|
|
|
|
|
value={<Icon name={buttonProps.icon} class={styles.icon} />}
|
2023-10-31 21:21:30 +00:00
|
|
|
|
class={styles.editorControl}
|
2023-05-13 17:00:58 +00:00
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</Popover>
|
|
|
|
|
</Show>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-13 19:35:57 +00:00
|
|
|
|
return (
|
2022-11-15 16:16:31 +00:00
|
|
|
|
<ShowOnlyOnClient>
|
2024-01-18 17:34:17 +00:00
|
|
|
|
<Show when={isSessionLoaded()} keyed={true}>
|
2023-10-16 20:11:08 +00:00
|
|
|
|
<div class={clsx('col-auto col-lg-7', styles.usernav)}>
|
2023-09-04 20:45:02 +00:00
|
|
|
|
<div class={styles.userControl}>
|
2024-04-08 11:26:20 +00:00
|
|
|
|
<Show when={isCreatePostButtonVisible() && isAuthenticated()}>
|
2023-03-23 17:15:50 +00:00
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
|
|
|
|
<a href={getPagePath(router, 'create')}>
|
|
|
|
|
<span class={styles.textLabel}>{t('Create post')}</span>
|
|
|
|
|
<Icon name="pencil" class={styles.icon} />
|
2023-07-23 15:59:28 +00:00
|
|
|
|
<Icon name="pencil" class={clsx(styles.icon, styles.iconHover)} />
|
2023-03-23 17:15:50 +00:00
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</Show>
|
2022-11-13 19:35:57 +00:00
|
|
|
|
|
2023-10-31 21:21:30 +00:00
|
|
|
|
<Show when={!isSaveButtonVisible()}>
|
2024-04-08 11:26:20 +00:00
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemSearch)}>
|
2024-01-28 07:06:31 +00:00
|
|
|
|
<a href="?m=search">
|
2023-10-31 21:21:30 +00:00
|
|
|
|
<Icon name="search" class={styles.icon} />
|
|
|
|
|
<Icon name="search" class={clsx(styles.icon, styles.iconHover)} />
|
2024-01-25 15:06:26 +00:00
|
|
|
|
</a>
|
2023-10-31 21:21:30 +00:00
|
|
|
|
</div>
|
|
|
|
|
</Show>
|
2023-05-24 21:51:47 +00:00
|
|
|
|
|
2023-12-15 13:45:34 +00:00
|
|
|
|
<Show when={isNotificationsVisible() || !author()}>
|
2023-10-14 11:39:24 +00:00
|
|
|
|
<div class={styles.userControlItem} onClick={handleBellIconClick}>
|
2023-10-16 22:13:13 +00:00
|
|
|
|
<div class={styles.button}>
|
2023-12-15 13:45:34 +00:00
|
|
|
|
<Icon
|
|
|
|
|
name="bell-white"
|
2023-12-24 08:16:41 +00:00
|
|
|
|
counter={session() ? unreadNotificationsCount() || 0 : 1}
|
2023-12-15 13:45:34 +00:00
|
|
|
|
class={styles.icon}
|
|
|
|
|
/>
|
2023-10-16 22:13:13 +00:00
|
|
|
|
<Icon
|
|
|
|
|
name="bell-white-hover"
|
2023-12-24 08:16:41 +00:00
|
|
|
|
counter={session() ? unreadNotificationsCount() || 0 : 1}
|
2023-10-16 22:13:13 +00:00
|
|
|
|
class={clsx(styles.icon, styles.iconHover)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2022-11-13 19:35:57 +00:00
|
|
|
|
</div>
|
|
|
|
|
</Show>
|
2023-10-23 22:35:02 +00:00
|
|
|
|
|
2023-10-14 11:39:24 +00:00
|
|
|
|
<Show when={isSaveButtonVisible()}>
|
2024-04-08 11:26:20 +00:00
|
|
|
|
<Popup
|
|
|
|
|
trigger={
|
|
|
|
|
<span class={styles.editorModePopupOpener}>
|
|
|
|
|
<Icon name="swiper-r-arr" class={styles.editorModePopupOpenerIcon} />
|
|
|
|
|
{editorMode()}
|
|
|
|
|
</span>
|
|
|
|
|
}
|
|
|
|
|
variant="bordered"
|
|
|
|
|
popupCssClass={styles.editorPopup}
|
|
|
|
|
>
|
|
|
|
|
<ul class={clsx('nodash', styles.editorModesList)}>
|
|
|
|
|
<li
|
|
|
|
|
class={clsx({ [styles.editorModesSelected]: editorMode() === t('Preview') })}
|
|
|
|
|
onClick={() => setEditorMode(t('Preview'))}
|
|
|
|
|
>
|
|
|
|
|
<Icon name="eye" class={styles.editorModeIcon} />
|
|
|
|
|
<div class={styles.editorModeTitle}>{t('Preview')}</div>
|
|
|
|
|
<div class={styles.editorModeDescription}>
|
|
|
|
|
Посмотрите, как материал будет выглядеть при публикации
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
<li
|
|
|
|
|
class={clsx({ [styles.editorModesSelected]: editorMode() === t('Editing') })}
|
|
|
|
|
onClick={() => setEditorMode(t('Editing'))}
|
|
|
|
|
>
|
|
|
|
|
<Icon name="pencil-outline" class={styles.editorModeIcon} />
|
|
|
|
|
<div class={styles.editorModeTitle}>{t('Editing')}</div>
|
|
|
|
|
<div class={styles.editorModeDescription}>Изменяйте текст напрямую в редакторе</div>
|
|
|
|
|
</li>
|
|
|
|
|
<li
|
|
|
|
|
class={clsx({ [styles.editorModesSelected]: editorMode() === t('Commenting') })}
|
|
|
|
|
onClick={() => setEditorMode(t('Commenting'))}
|
|
|
|
|
>
|
|
|
|
|
<Icon name="comment" class={styles.editorModeIcon} />
|
|
|
|
|
<div class={styles.editorModeTitle}>{t('Commenting')}</div>
|
|
|
|
|
<div class={styles.editorModeDescription}>
|
|
|
|
|
Предлагайте правки и комментарии, чтобы сделать материал лучше
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</Popup>
|
2023-04-05 21:51:01 +00:00
|
|
|
|
|
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
2023-05-13 17:00:58 +00:00
|
|
|
|
{renderIconedButton({
|
|
|
|
|
value: t('Publish'),
|
|
|
|
|
icon: 'publish',
|
2024-02-12 08:12:23 +00:00
|
|
|
|
action: () => publishShout(form),
|
2023-05-13 17:00:58 +00:00
|
|
|
|
})}
|
2023-04-05 21:51:01 +00:00
|
|
|
|
</div>
|
2023-04-06 21:40:34 +00:00
|
|
|
|
|
2024-04-08 11:26:20 +00:00
|
|
|
|
<div
|
|
|
|
|
class={clsx(
|
|
|
|
|
styles.userControlItem,
|
|
|
|
|
styles.settingsControlContainer,
|
|
|
|
|
styles.userControlItemVerbose,
|
|
|
|
|
)}
|
|
|
|
|
>
|
2023-05-13 17:00:58 +00:00
|
|
|
|
<Popover content={t('Settings')}>
|
|
|
|
|
{(ref) => (
|
|
|
|
|
<Button
|
|
|
|
|
ref={ref}
|
2024-04-08 11:26:20 +00:00
|
|
|
|
value={<Icon name="ellipsis" />}
|
2023-10-31 21:21:30 +00:00
|
|
|
|
variant={'light'}
|
2023-05-13 17:00:58 +00:00
|
|
|
|
onClick={handleBurgerButtonClick}
|
2023-10-31 21:21:30 +00:00
|
|
|
|
class={styles.settingsControl}
|
2023-05-13 17:00:58 +00:00
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</Popover>
|
2023-04-06 21:40:34 +00:00
|
|
|
|
</div>
|
2023-04-05 21:51:01 +00:00
|
|
|
|
</Show>
|
2024-04-08 11:26:20 +00:00
|
|
|
|
|
|
|
|
|
<Show when={isCreatePostButtonVisible() && !isAuthenticated()}>
|
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
|
|
|
|
<a href={getPagePath(router, 'create')}>
|
|
|
|
|
<span class={styles.textLabel}>{t('Create post')}</span>
|
|
|
|
|
<Icon name="pencil" class={styles.icon} />
|
|
|
|
|
<Icon name="pencil" class={clsx(styles.icon, styles.iconHover)} />
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</Show>
|
|
|
|
|
|
2022-11-13 19:35:57 +00:00
|
|
|
|
<Show
|
2023-10-14 11:39:24 +00:00
|
|
|
|
when={isAuthenticatedControlsVisible()}
|
2022-11-13 19:35:57 +00:00
|
|
|
|
fallback={
|
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose, 'loginbtn')}>
|
2024-01-27 06:21:48 +00:00
|
|
|
|
<a href="?m=auth&mode=login">
|
2022-11-13 19:35:57 +00:00
|
|
|
|
<span class={styles.textLabel}>{t('Enter')}</span>
|
2023-10-16 20:11:08 +00:00
|
|
|
|
<Icon name="key" class={styles.icon} />
|
2023-07-18 21:50:27 +00:00
|
|
|
|
{/*<Icon name="user-default" class={clsx(styles.icon, styles.iconHover)} />*/}
|
2022-11-13 19:35:57 +00:00
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
>
|
2023-10-31 21:21:30 +00:00
|
|
|
|
<Show when={!isSaveButtonVisible()}>
|
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemInbox)}>
|
2023-12-25 05:31:26 +00:00
|
|
|
|
<a href={getPagePath(router, 'inbox')}>
|
2023-10-31 21:21:30 +00:00
|
|
|
|
<div classList={{ entered: page().path === '/inbox' }}>
|
|
|
|
|
<Icon name="inbox-white" class={styles.icon} />
|
|
|
|
|
<Icon name="inbox-white-hover" class={clsx(styles.icon, styles.iconHover)} />
|
|
|
|
|
</div>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</Show>
|
2022-11-13 19:35:57 +00:00
|
|
|
|
</Show>
|
|
|
|
|
</div>
|
2024-04-08 11:26:20 +00:00
|
|
|
|
|
|
|
|
|
<Show when={isAuthenticated()}>
|
|
|
|
|
<ProfilePopup
|
|
|
|
|
onVisibilityChange={(isVisible) => {
|
|
|
|
|
props.setIsProfilePopupVisible(isVisible)
|
|
|
|
|
}}
|
|
|
|
|
containerCssClass={styles.control}
|
|
|
|
|
trigger={
|
|
|
|
|
<div class={clsx(styles.userControlItem, styles.userControlItemUserpic)}>
|
|
|
|
|
<button class={styles.button}>
|
|
|
|
|
<div classList={{ entered: page().path === `/${author()?.slug}` }}>
|
|
|
|
|
<Userpic
|
|
|
|
|
size={'L'}
|
|
|
|
|
name={author()?.name}
|
|
|
|
|
userpic={author()?.pic}
|
|
|
|
|
class={styles.userpic}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</Show>
|
2022-11-13 19:35:57 +00:00
|
|
|
|
</div>
|
|
|
|
|
</Show>
|
2022-11-15 16:16:31 +00:00
|
|
|
|
</ShowOnlyOnClient>
|
2022-11-13 19:35:57 +00:00
|
|
|
|
)
|
|
|
|
|
}
|