mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 14:04:21 +01:00
update
This commit is contained in:
@@ -106,6 +106,53 @@ const DateFormatConfig = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ToggleButton = (props: {
|
||||||
|
value: boolean;
|
||||||
|
onClick: JSX.EventHandler<HTMLButtonElement, MouseEvent>;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
class="flex h-[24px] w-[48px] items-center rounded-full border border-primary px-1"
|
||||||
|
classList={{
|
||||||
|
'bg-white': !props.value,
|
||||||
|
'justify-start': !props.value,
|
||||||
|
'bg-rose-300': props.value,
|
||||||
|
'justify-end': props.value,
|
||||||
|
}}
|
||||||
|
area-label={props.value}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
<span class="m-[-2px] inline-block h-5 w-5 rounded-full border border-primary bg-white shadow" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const OtherConfig = () => {
|
||||||
|
const { config, setConfig } = useConfig();
|
||||||
|
|
||||||
|
const toggleKeepOpenPostForm = () => {
|
||||||
|
setConfig((current) => ({
|
||||||
|
...current,
|
||||||
|
keepOpenPostForm: !(current.keepOpenPostForm ?? false),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">その他</h3>
|
||||||
|
<div class="flex flex-col justify-evenly gap-2 sm:flex-row">
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1">投稿欄を開いたままにする</div>
|
||||||
|
<ToggleButton
|
||||||
|
value={config().keepOpenPostForm}
|
||||||
|
onClick={() => toggleKeepOpenPostForm()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ConfigUI = (props: ConfigProps) => {
|
const ConfigUI = (props: ConfigProps) => {
|
||||||
let containerRef: HTMLDivElement | undefined;
|
let containerRef: HTMLDivElement | undefined;
|
||||||
|
|
||||||
@@ -131,6 +178,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<RelayConfig />
|
<RelayConfig />
|
||||||
<DateFormatConfig />
|
<DateFormatConfig />
|
||||||
|
<OtherConfig />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,19 +22,21 @@ import eventWrapper from '@/core/event';
|
|||||||
import useConfig from '@/nostr/useConfig';
|
import useConfig from '@/nostr/useConfig';
|
||||||
import useCommands from '@/nostr/useCommands';
|
import useCommands from '@/nostr/useCommands';
|
||||||
import usePubkey from '@/nostr/usePubkey';
|
import usePubkey from '@/nostr/usePubkey';
|
||||||
|
import { useHandleCommand } from '@/hooks/useCommandBus';
|
||||||
|
|
||||||
type NotePostFormProps = {
|
type NotePostFormProps = {
|
||||||
replyTo?: NostrEvent;
|
replyTo?: NostrEvent;
|
||||||
mode?: 'normal' | 'reply';
|
mode?: 'normal' | 'reply';
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
onPost?: () => void;
|
||||||
|
textAreaRef?: (textAreaRef: HTMLTextAreaElement) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const placeholder = (mode: NotePostFormProps['mode']) => {
|
const placeholder = (mode: NotePostFormProps['mode']) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'normal':
|
|
||||||
return 'いまどうしてる?';
|
|
||||||
case 'reply':
|
case 'reply':
|
||||||
return '返信を投稿';
|
return '返信を投稿';
|
||||||
|
case 'normal':
|
||||||
default:
|
default:
|
||||||
return 'いまどうしてる?';
|
return 'いまどうしてる?';
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
console.log('succeeded to post');
|
console.log('succeeded to post');
|
||||||
clearText();
|
clearText();
|
||||||
props?.onClose();
|
props.onPost?.();
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
console.error('error', err);
|
console.error('error', err);
|
||||||
@@ -99,6 +101,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
if (ev.key === 'Enter' && (ev.ctrlKey || ev.metaKey)) {
|
if (ev.key === 'Enter' && (ev.ctrlKey || ev.metaKey)) {
|
||||||
submit();
|
submit();
|
||||||
} else if (ev.key === 'Escape') {
|
} else if (ev.key === 'Escape') {
|
||||||
|
textAreaRef?.blur();
|
||||||
props.onClose();
|
props.onClose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -129,7 +132,10 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
</Show>
|
</Show>
|
||||||
<form class="flex flex-col gap-1" onSubmit={handleSubmit}>
|
<form class="flex flex-col gap-1" onSubmit={handleSubmit}>
|
||||||
<textarea
|
<textarea
|
||||||
ref={textAreaRef}
|
ref={(el) => {
|
||||||
|
textAreaRef = el;
|
||||||
|
props.textAreaRef?.(el);
|
||||||
|
}}
|
||||||
name="text"
|
name="text"
|
||||||
class="rounded border-none"
|
class="rounded border-none"
|
||||||
rows={4}
|
rows={4}
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ import NotePostForm from '@/components/NotePostForm';
|
|||||||
import Config from '@/components/Config';
|
import Config from '@/components/Config';
|
||||||
|
|
||||||
import { useHandleCommand } from '@/hooks/useCommandBus';
|
import { useHandleCommand } from '@/hooks/useCommandBus';
|
||||||
|
import useConfig from '@/nostr/useConfig';
|
||||||
|
|
||||||
const SideBar: Component = () => {
|
const SideBar: Component = () => {
|
||||||
|
let textAreaRef: HTMLTextAreaElement | undefined;
|
||||||
|
|
||||||
|
const { config } = useConfig();
|
||||||
const [formOpened, setFormOpened] = createSignal(false);
|
const [formOpened, setFormOpened] = createSignal(false);
|
||||||
const [configOpened, setConfigOpened] = createSignal(false);
|
const [configOpened, setConfigOpened] = createSignal(false);
|
||||||
|
|
||||||
@@ -17,7 +21,10 @@ const SideBar: Component = () => {
|
|||||||
|
|
||||||
useHandleCommand(() => ({
|
useHandleCommand(() => ({
|
||||||
commandType: 'openPostForm',
|
commandType: 'openPostForm',
|
||||||
handler: (cmd) => openForm(),
|
handler: () => {
|
||||||
|
openForm();
|
||||||
|
setTimeout(() => textAreaRef?.focus?.(), 100);
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -48,8 +55,13 @@ const SideBar: Component = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Show when={formOpened()}>
|
<Show when={formOpened() || config().keepOpenPostForm}>
|
||||||
<NotePostForm onClose={closeForm} />
|
<NotePostForm
|
||||||
|
textAreaRef={(el) => {
|
||||||
|
textAreaRef = el;
|
||||||
|
}}
|
||||||
|
onClose={closeForm}
|
||||||
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={configOpened()}>
|
<Show when={configOpened()}>
|
||||||
<Config onClose={() => setConfigOpened(false)} />
|
<Config onClose={() => setConfigOpened(false)} />
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
const pubkey = usePubkey();
|
const pubkey = usePubkey();
|
||||||
|
|
||||||
const [showReplyForm, setShowReplyForm] = createSignal(false);
|
const [showReplyForm, setShowReplyForm] = createSignal(false);
|
||||||
|
const closeReplyForm = () => setShowReplyForm(false);
|
||||||
const [showMenu, setShowMenu] = createSignal(false);
|
const [showMenu, setShowMenu] = createSignal(false);
|
||||||
|
|
||||||
const event = createMemo(() => eventWrapper(props.event));
|
const event = createMemo(() => eventWrapper(props.event));
|
||||||
@@ -255,7 +256,12 @@ const TextNoteDisplay: Component<TextNoteDisplayProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Show when={showReplyForm()}>
|
<Show when={showReplyForm()}>
|
||||||
<NotePostForm mode="reply" replyTo={props.event} onClose={() => setShowReplyForm(false)} />
|
<NotePostForm
|
||||||
|
mode="reply"
|
||||||
|
replyTo={props.event}
|
||||||
|
onClose={closeReplyForm}
|
||||||
|
onPost={closeReplyForm}
|
||||||
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export const parseTextNote = (event: NostrEvent): ParsedTextNote => {
|
|||||||
}
|
}
|
||||||
} else if (match.groups?.nip19 && match.index >= pos) {
|
} else if (match.groups?.nip19 && match.index >= pos) {
|
||||||
try {
|
try {
|
||||||
const decoded = decode(match[0].toLowerCase());
|
const decoded = decode(match[0]);
|
||||||
const bech32Entity: Bech32Entity = {
|
const bech32Entity: Bech32Entity = {
|
||||||
type: 'Bech32Entity',
|
type: 'Bech32Entity',
|
||||||
content: match[0],
|
content: match[0],
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
export type Config = {
|
export type Config = {
|
||||||
relayUrls: string[];
|
relayUrls: string[];
|
||||||
dateFormat: 'relative' | 'absolute-long' | 'absolute-short';
|
dateFormat: 'relative' | 'absolute-long' | 'absolute-short';
|
||||||
|
keepOpenPostForm: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type UseConfig = {
|
type UseConfig = {
|
||||||
@@ -29,6 +30,7 @@ const InitialConfig: Config = {
|
|||||||
'wss://nostr.holybea.com',
|
'wss://nostr.holybea.com',
|
||||||
],
|
],
|
||||||
dateFormat: 'relative',
|
dateFormat: 'relative',
|
||||||
|
keepOpenPostForm: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const serializer = (config: Config): string => JSON.stringify(config);
|
const serializer = (config: Config): string => JSON.stringify(config);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createSignal, createEffect, onMount, type Component, onCleanup } from 'solid-js';
|
import { createSignal, createEffect, onMount, type Component, onCleanup } from 'solid-js';
|
||||||
import { useNavigate } from '@solidjs/router';
|
import { useNavigate } from '@solidjs/router';
|
||||||
|
import uniq from 'lodash/uniq';
|
||||||
|
|
||||||
import Column from '@/components/Column';
|
import Column from '@/components/Column';
|
||||||
import SideBar from '@/components/SideBar';
|
import SideBar from '@/components/SideBar';
|
||||||
@@ -48,7 +49,7 @@ const Home: Component = () => {
|
|||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
kinds: [1, 6],
|
kinds: [1, 6],
|
||||||
authors: followingPubkeys(),
|
authors: uniq([...followingPubkeys(), pubkeyNonNull]),
|
||||||
limit: 25,
|
limit: 25,
|
||||||
since: Math.floor(Date.now() / 1000) - 12 * 60 * 60,
|
since: Math.floor(Date.now() / 1000) - 12 * 60 * 60,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user