mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 05:54:19 +01:00
feat: add buttons in the sidebar to jump to each column (#86)
* feat: add buttons in the sidebar to jump to each column * fix: dump error when the promise is rejected Co-authored-by: Shusui MOYATANI <syusui.s@gmail.com> * fix: improve style Co-authored-by: Shusui MOYATANI <syusui.s@gmail.com> * fix: improve style Co-authored-by: Shusui MOYATANI <syusui.s@gmail.com> * fix: syntax error * fix: remove CustomFilterColumn temporarily * perf: move const var * fix: move container element to component --------- Co-authored-by: Shusui MOYATANI <syusui.s@gmail.com>
This commit is contained in:
@@ -1,17 +1,36 @@
|
|||||||
import { createSignal, Show, onMount, onCleanup, lazy, type JSX, Component } from 'solid-js';
|
import {
|
||||||
|
createSignal,
|
||||||
|
Show,
|
||||||
|
onMount,
|
||||||
|
onCleanup,
|
||||||
|
lazy,
|
||||||
|
type JSX,
|
||||||
|
Component,
|
||||||
|
For,
|
||||||
|
createMemo,
|
||||||
|
} from 'solid-js';
|
||||||
|
|
||||||
|
import Bell from 'heroicons/24/outline/bell.svg';
|
||||||
|
import BookmarkIcon from 'heroicons/24/outline/bookmark.svg';
|
||||||
|
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
|
||||||
import Cog6Tooth from 'heroicons/24/outline/cog-6-tooth.svg';
|
import Cog6Tooth from 'heroicons/24/outline/cog-6-tooth.svg';
|
||||||
|
import GlobeAlt from 'heroicons/24/outline/globe-alt.svg';
|
||||||
|
import Heart from 'heroicons/24/outline/heart.svg';
|
||||||
|
import Home from 'heroicons/24/outline/home.svg';
|
||||||
|
import MagnifyingGlass from 'heroicons/24/outline/magnifying-glass.svg';
|
||||||
import Plus from 'heroicons/24/outline/plus.svg';
|
import Plus from 'heroicons/24/outline/plus.svg';
|
||||||
import MagnifyingGlass from 'heroicons/24/solid/magnifying-glass.svg';
|
import User from 'heroicons/24/outline/user.svg';
|
||||||
import PencilSquare from 'heroicons/24/solid/pencil-square.svg';
|
import PencilSquare from 'heroicons/24/solid/pencil-square.svg';
|
||||||
|
import { ParseKeys } from 'i18next';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
|
|
||||||
import NotePostForm from '@/components/NotePostForm';
|
import NotePostForm from '@/components/NotePostForm';
|
||||||
import usePopup, { type UsePopup } from '@/components/utils/usePopup';
|
import usePopup, { type UsePopup } from '@/components/utils/usePopup';
|
||||||
import { createSearchColumn } from '@/core/column';
|
import { ColumnType, createSearchColumn } from '@/core/column';
|
||||||
import useConfig from '@/core/useConfig';
|
import useConfig from '@/core/useConfig';
|
||||||
import { useHandleCommand, useRequestCommand } from '@/hooks/useCommandBus';
|
import { useHandleCommand, useRequestCommand } from '@/hooks/useCommandBus';
|
||||||
import useModalState from '@/hooks/useModalState';
|
import useModalState from '@/hooks/useModalState';
|
||||||
|
import { useTranslation } from '@/i18n/useTranslation';
|
||||||
import isMobile from '@/utils/isMobile';
|
import isMobile from '@/utils/isMobile';
|
||||||
import resolveAsset from '@/utils/resolveAsset';
|
import resolveAsset from '@/utils/resolveAsset';
|
||||||
|
|
||||||
@@ -94,6 +113,81 @@ const SearchButton = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ColumnKind = ColumnType['columnType'];
|
||||||
|
const columns: Readonly<Record<ColumnKind, { icon: string /* svg */; nameKey: ParseKeys }>> = {
|
||||||
|
Bookmark: {
|
||||||
|
icon: BookmarkIcon,
|
||||||
|
nameKey: 'column.bookmark',
|
||||||
|
},
|
||||||
|
Channel: {
|
||||||
|
icon: ChatBubbleLeftRight,
|
||||||
|
nameKey: 'column.channel',
|
||||||
|
},
|
||||||
|
Following: {
|
||||||
|
icon: Home,
|
||||||
|
nameKey: 'column.home',
|
||||||
|
},
|
||||||
|
Notification: {
|
||||||
|
icon: Bell,
|
||||||
|
nameKey: 'column.notification',
|
||||||
|
},
|
||||||
|
Posts: {
|
||||||
|
icon: User,
|
||||||
|
nameKey: 'column.posts',
|
||||||
|
},
|
||||||
|
Reactions: {
|
||||||
|
icon: Heart,
|
||||||
|
nameKey: 'column.reactions',
|
||||||
|
},
|
||||||
|
Relays: {
|
||||||
|
icon: GlobeAlt,
|
||||||
|
nameKey: 'column.relay',
|
||||||
|
},
|
||||||
|
Search: { icon: MagnifyingGlass, nameKey: 'column.search' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const ColumnButton: Component<{ column: ColumnType; index: number }> = (props) => {
|
||||||
|
const i18n = useTranslation();
|
||||||
|
|
||||||
|
const request = useRequestCommand();
|
||||||
|
const jumpToColumn = () => {
|
||||||
|
request({
|
||||||
|
command: 'moveToColumn',
|
||||||
|
columnIndex: props.index,
|
||||||
|
}).catch((err) => console.error(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
const Icon = createMemo(() => columns[props.column.columnType].icon);
|
||||||
|
const columnNameKey = createMemo(() => columns[props.column.columnType].nameKey);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class="relative flex w-full flex-col items-center py-3 text-primary hover:text-primary-hover"
|
||||||
|
onClick={() => jumpToColumn()}
|
||||||
|
title={props.column.name ?? i18n.t(columnNameKey())}
|
||||||
|
>
|
||||||
|
<span class="inline-block size-6">
|
||||||
|
<Icon />
|
||||||
|
</span>
|
||||||
|
<span class="absolute bottom-2 right-0 text-xs text-primary">{props.index}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ColumnButtons: Component = () => {
|
||||||
|
const { config } = useConfig();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="scrollbar flex w-full grow overflow-y-auto overflow-x-hidden border-y border-primary/30 px-2 ">
|
||||||
|
<div class="size-full flex-col items-center justify-center py-2">
|
||||||
|
<For each={config().columns}>
|
||||||
|
{(column, index) => <ColumnButton column={column} index={index() + 1} />}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const SideBar: Component = () => {
|
const SideBar: Component = () => {
|
||||||
let textAreaRef: HTMLTextAreaElement | undefined;
|
let textAreaRef: HTMLTextAreaElement | undefined;
|
||||||
|
|
||||||
@@ -156,7 +250,7 @@ const SideBar: Component = () => {
|
|||||||
</Show>
|
</Show>
|
||||||
<SearchButton />
|
<SearchButton />
|
||||||
</div>
|
</div>
|
||||||
<div class="grow" />
|
<ColumnButtons />
|
||||||
<div class="flex w-full flex-col items-center gap-2 pb-2">
|
<div class="flex w-full flex-col items-center gap-2 pb-2">
|
||||||
<button
|
<button
|
||||||
class="flex w-full flex-col items-center py-1 text-primary hover:text-primary-hover"
|
class="flex w-full flex-col items-center py-1 text-primary hover:text-primary-hover"
|
||||||
|
|||||||
@@ -112,8 +112,9 @@ export type ColumnType =
|
|||||||
| ChannelColumnType
|
| ChannelColumnType
|
||||||
| RelaysColumnType
|
| RelaysColumnType
|
||||||
| SearchColumnType
|
| SearchColumnType
|
||||||
| BookmarkColumnType
|
| BookmarkColumnType;
|
||||||
| CustomFilterColumnType;
|
/* WIP: */
|
||||||
|
/* | CustomFilterColumnType */
|
||||||
|
|
||||||
type CreateParams<T extends BaseColumn> = Omit<T, keyof BaseColumn | 'columnType'> &
|
type CreateParams<T extends BaseColumn> = Omit<T, keyof BaseColumn | 'columnType'> &
|
||||||
Partial<BaseColumn>;
|
Partial<BaseColumn>;
|
||||||
|
|||||||
Reference in New Issue
Block a user