fix: eslint errors

This commit is contained in:
Shusui MOYATANI
2023-11-23 00:54:04 +09:00
parent 93cf0ce825
commit 52f7573475
49 changed files with 130 additions and 253 deletions

View File

@@ -81,6 +81,13 @@ module.exports = {
'created-at',
'actions',
'content',
'profile',
'profile-icon',
'profile-name',
'profile-username',
'notification-icon',
'notification-user',
'notification-event',
],
},
},

View File

@@ -4,7 +4,6 @@ about: Create a report to help us improve
title: ''
labels: bug
assignees: syusui-s
---
**Describe the bug**
@@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -4,7 +4,6 @@ about: 改善に取り組めるように報告を作成します
title: ''
labels: bug
assignees: syusui-s
---
**バグの説明**
@@ -12,6 +11,7 @@ assignees: syusui-s
**再現手順**
発生させる手順を説明してください:
1. '...'に移動
2. '....'をクリック
3. '....'までスクロールする
@@ -24,15 +24,17 @@ assignees: syusui-s
スクリーンショットがあればこちらに。
**デスクトップ (該当する場合は以下の情報を埋めてください):**
- OS: (例: Windows 11, macOS Ventura
- ブラウザ: (例: Chrome, Firefox, Safari, Edge
- バージョン: (例: 110
- OS: (例: Windows 11, macOS Ventura
- ブラウザ: (例: Chrome, Firefox, Safari, Edge
- バージョン: (例: 110
**スマートフォン (該当する場合は以下の情報を埋めてください):**
- デバイス: (例: iPhone 12)
- OS: 例: iOS 16.2, Android 13
- ブラウザ: (例: Safari, Chrome
- バージョン: (例: 110
- デバイス: (例: iPhone 12)
- OS: (例: iOS 16.2, Android 13
- ブラウザ: (例: Safari, Chrome
- バージョン: (例: 110
**追加の情報**
問題に関する他の情報があればこちらに。

View File

@@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: syusui-s
---
**Is your feature request related to a problem? Please describe.**

View File

@@ -4,7 +4,6 @@ about: このプロジェクトにアイデアを提案します
title: ''
labels: enhancement
assignees: syusui-s
---
**要望は何らかの問題に関連していますか?説明してください**

View File

@@ -3,7 +3,6 @@ name: Pull request
about: Suggest changes
title: ''
labels:
---
**Describe the changes**

View File

@@ -3,7 +3,6 @@ name: プルリクエスト
about: 変更を提案します
title: ''
labels:
---
**変更について説明してください**

View File

@@ -3,7 +3,7 @@ name: CI
on:
push:
branch:
- "*"
- '*'
jobs:
ci:
permissions:

View File

@@ -5,7 +5,7 @@ A nostr client like TweetDeck made with SolidJS.
## 使い方
1. NIP-07に対応したブラウザ拡張機能のインストールが事前に必要です
* [NIP-07](https://scrapbox.io/nostr/NIP-07#63e1c10c8b8fcb00000584fc) を参考に拡張機能をインストールしてください。
- [NIP-07](https://scrapbox.io/nostr/NIP-07#63e1c10c8b8fcb00000584fc) を参考に拡張機能をインストールしてください。
1. https://syusui-s.github.io/rabbit/ にアクセス
1. NIP-07拡張機能に許可を求められるので許可ボタンを押す
1. タイムラインが表示されます
@@ -29,11 +29,11 @@ the Free Software Foundation, either version 3 of the License, or
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
along with this program. If not, see <https://www.gnu.org/licenses/>.
### 日本語
@@ -41,8 +41,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
GNUアフェロー一般公衆利用許諾書バージョン3か、それ以降のいずれかのバージョン
が定める条件の下で再頒布または改変することができます。
このプログラムは有用であることを願って頒布されますが、 *全くの無保証* です。
*商業可能性**特定目的への適合性* に対する保証は言外に示されたものも含め、全く存在しません。
このプログラムは有用であることを願って頒布されますが、 _全くの無保証_ です。
_商業可能性__特定目的への適合性_ に対する保証は言外に示されたものも含め、全く存在しません。
詳しくはGNUアフェロー一般公衆利用許諾書をご覧ください。
あなたはこのプログラムと共にGNUアフェロー一般公衆利用許諾書のコピーを一部受け取っているはずです。

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="ja">
<head prefix="og: http://ogp.me/ns# website: http://ogp.me/ns/website#">
<meta charset="utf-8" />
@@ -6,12 +6,18 @@
<meta name="theme-color" content="#000000" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="@syusui-s" />
<meta name="twitter:image" content="https://syusui-s.github.io/rabbit/images/rabbit_app_1280.png" />
<meta
name="twitter:image"
content="https://syusui-s.github.io/rabbit/images/rabbit_app_1280.png"
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://syusui-s.github.io/rabbit/" />
<meta property="og:title" content="🐰rabbit" />
<meta property="og:description" content="Nostr Client" />
<meta property="og:image" content="https://syusui-s.github.io/rabbit/images/rabbit_app_1280.png" />
<meta property="og:description" content="Nostr Client" />
<meta
property="og:image"
content="https://syusui-s.github.io/rabbit/images/rabbit_app_1280.png"
/>
<meta property="og:locale" content="ja_JP" />
<link rel="manifest" href="manifest.json" />
<link rel="shortcut icon" type="image/png" href="./images/rabbit_256.png" />

View File

@@ -9,9 +9,11 @@
"dev": "npm run generatePackageInfo && vite",
"build": "npm run generatePackageInfo && vite build",
"serve": "npm run generatePackageInfo && vite preview",
"eslint": "eslint --cache .",
"lint": "npm run prettier && npm run eslint",
"fix": "npm run prettier-fix && npm run eslint-fix",
"eslint": "eslint .",
"prettier": "prettier -c .",
"eslint-fix": "eslint --cache --fix .",
"eslint-fix": "eslint --fix .",
"prettier-fix": "prettier --write .",
"tsc": "tsc --noEmit --skipLibCheck",
"test": "vitest run --no-watch",

View File

@@ -1,15 +1,14 @@
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rabbit</title>
</head>
<body>
<h1>お探しのページは見つかりませんでした</h1>
<p>
<a href="/rabbit/">トップに戻る</a>
</p>
</body>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Rabbit</title>
</head>
<body>
<h1>お探しのページは見つかりませんでした</h1>
<p>
<a href="/rabbit/">トップに戻る</a>
</p>
</body>
</html>

View File

@@ -6,13 +6,16 @@
"display": "browser",
"background_color": "#fff",
"description": "A deck style nostr client.",
"icons": [{
"src": "images/rabbit_app_256.png",
"sizes": "256x256",
"type": "image/png"
}, {
"src": "images/rabbit_app_1280.png",
"sizes": "1280x1280",
"type": "image/png"
}]
"icons": [
{
"src": "images/rabbit_app_256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "images/rabbit_app_1280.png",
"sizes": "1280x1280",
"type": "image/png"
}
]
}

View File

@@ -1,4 +1,4 @@
#!/bin/sh
prettier --write "$@"
eslint --cache --fix "$@"
eslint --fix "$@"

View File

@@ -76,6 +76,7 @@ const EmojiPicker: Component<EmojiPickerProps> = (props) => {
},
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
pickerElement = picker as any as HTMLElement;
popupRef?.elem?.appendChild(pickerElement);
};

View File

@@ -1,4 +1,4 @@
import { Component, Show, createEffect, onCleanup, onMount } from 'solid-js';
import { Component, Show } from 'solid-js';
import BookmarkIcon from 'heroicons/24/outline/bookmark.svg';
@@ -9,7 +9,6 @@ import Bookmark from '@/components/timeline/Bookmark';
import { BookmarkColumnType } from '@/core/column';
import useConfig from '@/core/useConfig';
import { useTranslation } from '@/i18n/useTranslation';
import useDecrypt from '@/nostr/useDecrypt';
import useParameterizedReplaceableEvent from '@/nostr/useParameterizedReplaceableEvent';
type BookmarkColumnDisplayProps = {
@@ -28,6 +27,8 @@ const BookmarkColumn: Component<BookmarkColumnDisplayProps> = (props) => {
identifier: props.column.identifier,
}));
// TODO 暗号化されたデータがある場合は復号する
return (
<Column
header={

View File

@@ -1,14 +1,13 @@
import { Component, createEffect, onCleanup, onMount } from 'solid-js';
import { Component } from 'solid-js';
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
import { uniq } from 'lodash';
import { Kind } from 'nostr-tools';
import BasicColumnHeader from '@/components/column/BasicColumnHeader';
import Column from '@/components/column/Column';
import ColumnSettings from '@/components/column/ColumnSettings';
import Timeline from '@/components/timeline/Timeline';
import { ChannelColumnType, FollowingColumnType } from '@/core/column';
import { ChannelColumnType } from '@/core/column';
import { applyContentFilter } from '@/core/contentFilter';
import useConfig from '@/core/useConfig';
import { useTranslation } from '@/i18n/useTranslation';

View File

@@ -19,14 +19,12 @@ type ColumnSettingsSectionProps = {
children: JSX.Element;
};
const ColumnSettingsSection: Component<ColumnSettingsSectionProps> = (props) => {
return (
<div class="flex flex-col gap-2 border-b p-2">
<div>{props.title}</div>
<div>{props.children}</div>
</div>
);
};
const ColumnSettingsSection: Component<ColumnSettingsSectionProps> = (props) => (
<div class="flex flex-col gap-2 border-b p-2">
<div>{props.title}</div>
<div>{props.children}</div>
</div>
);
const ColumnSettings: Component<ColumnSettingsProps> = (props) => {
const i18n = useTranslation();

View File

@@ -39,10 +39,10 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
<EventLink eventId={props.event.id} kind={props.event.kind} />
</span>
</Match>
<Match when={props.event.kind === Kind.Text}>
<Match when={props.event.kind === (Kind.Text as number)}>
<TextNote event={props.event} embedding={props.actions} actions={props.actions} />
</Match>
<Match when={(props.event.kind as number) === 6}>
<Match when={props.event.kind === (Kind.Repost as number)}>
<Repost event={props.event} />
</Match>
</Switch>

View File

@@ -1,24 +0,0 @@
import { Component } from 'solid-js';
import DocumentText from 'heroicons/24/outline/document-text.svg';
import { Kind, Event as NostrEvent } from 'nostr-tools';
import { genericEvent } from '@/nostr/event';
export type LongFormContentProps = {
event: NostrEvent;
};
const LongFormContent: Component<LongFormContentProps> = (props) => (
// const event = () => genericEvent(props.event);
<button class="flex flex-col gap-1 px-1">
<div class="flex items-center gap-1">
<span class="inline-block h-4 w-4 text-purple-400">
<DocumentText />
</span>
<span>TODO</span>
</div>
</button>
);
export default LongFormContent;

View File

@@ -1,6 +1,5 @@
import { Show, type Component } from 'solid-js';
import ColumnItem from '@/components/ColumnItem';
// eslint-disable-next-line import/no-cycle
import TextNoteDisplay, { TextNoteDisplayProps } from '@/components/event/textNote/TextNoteDisplay';
import useConfig from '@/core/useConfig';

View File

@@ -1,13 +1,13 @@
import { Component } 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 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 User from 'heroicons/24/outline/user.svg';
// import BookmarkIcon from 'heroicons/24/outline/bookmark.svg';
// import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
import BasicModal from '@/components/modal/BasicModal';
import {

View File

@@ -1,4 +1,4 @@
import { Component, For, createMemo } from 'solid-js';
import { Component, createMemo } from 'solid-js';
import { type Event as NostrEvent } from 'nostr-tools';

View File

@@ -25,7 +25,6 @@ import useVerification from '@/nostr/useVerification';
import ensureNonNull from '@/utils/ensureNonNull';
import epoch from '@/utils/epoch';
import npubEncodeFallback from '@/utils/npubEncodeFallback';
import stripMargin from '@/utils/stripMargin';
import timeout from '@/utils/timeout';
export type ProfileDisplayProps = {
@@ -83,7 +82,6 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
})),
);
const following = () => myFollowingPubkeys().includes(props.pubkey);
const refetchMyFollowing = () => myFollowingQuery.refetch();
const { followingPubkeys: userFollowingPubkeys, query: userFollowingQuery } = useFollowings(
() => ({ pubkey: props.pubkey }),

View File

@@ -6,7 +6,6 @@ import ColumnItem from '@/components/ColumnItem';
import Reaction from '@/components/event/Reaction';
import Repost from '@/components/event/Repost';
import TextNote from '@/components/event/TextNote';
import ZapReceipt from '@/components/event/ZapReceipt';
import useConfig from '@/core/useConfig';
export type NotificationProps = {
@@ -21,29 +20,22 @@ const Notification: Component<NotificationProps> = (props) => {
{(event) => (
<Show when={!shouldMuteEvent(event)}>
<Switch fallback={<div>unknown event</div>}>
<Match when={event.kind === Kind.Text}>
<Match when={event.kind === (Kind.Text as number)}>
<ColumnItem>
<TextNote event={event} />
</ColumnItem>
</Match>
<Match when={event.kind === Kind.Reaction}>
<Match when={event.kind === (Kind.Reaction as number)}>
<ColumnItem>
<Reaction event={event} />
</ColumnItem>
</Match>
{/* TODO ちゃんとnotification用のコンポーネント使う */}
<Match when={(event.kind as number) === 6}>
<Match when={event.kind === (Kind.Repost as number)}>
<ColumnItem>
<Repost event={event} />
</ColumnItem>
</Match>
{/*
<Match when={event.kind === Kind.Zap}>
<ColumnItem>
<ZapReceipt event={event} />
</ColumnItem>
</Match>
*/}
</Switch>
</Show>
)}

View File

@@ -1,4 +1,4 @@
import { createSignal, Show, type Component, type JSX } from 'solid-js';
import { createSignal, Show, type Component } from 'solid-js';
import ClipboardDocument from 'heroicons/24/outline/clipboard-document.svg';
@@ -13,7 +13,7 @@ const Copy: Component<CopyProps> = (props) => {
const handleClick = () => {
navigator.clipboard
.writeText(props.text)
.then((e) => {
.then(() => {
setShowPopup(true);
setTimeout(() => setShowPopup(false), 1000);
})

View File

@@ -181,7 +181,7 @@ const useConfig = (): UseConfig => {
const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey);
const hasMutedKeyword = (event: NostrEvent) => {
if (event.kind === Kind.Text) {
if (event.kind === (Kind.Text as number)) {
return config.mutedKeywords.some((keyword) => event.content.includes(keyword));
}
return false;
@@ -192,7 +192,7 @@ const useConfig = (): UseConfig => {
return (
isPubkeyMuted(event.pubkey) ||
ev.taggedPubkeys().some(isPubkeyMuted) ||
(event.kind === Kind.Text && hasMutedKeyword(event))
(event.kind === (Kind.Text as number) && hasMutedKeyword(event))
);
};

View File

@@ -1,11 +0,0 @@
import { createSignal, type JSX } from 'solid-js';
const useFileInput = () => {
const [file, setFile] = createSignal<File | undefined>();
const handleChange: JSX.EventHandler<HTMLInputElement, Event> = (ev) => {
setFile(ev.currentTarget.files?.[0]);
};
return { file, handleChange };
};

View File

@@ -16,6 +16,7 @@ export type MessageChannelRequest<T> = {
export type MessageChannelResponse<T> =
| { requestId: string; ok: true; response: T }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| { requestId: string; ok: false; error: any };
const [channels, setChannels]: Signal<Record<string, MessageChannel>> = createSignal({});

View File

@@ -5,14 +5,14 @@ export type UseResizedImageProps = {
imageUrl: Accessor<string | undefined>;
width: number;
height: number;
encoderOption?: number;
encoderOptions?: number;
};
const useResizedImage = ({
imageUrl,
width,
height,
encoderOption,
encoderOptions,
}: UseResizedImageProps): Accessor<string | undefined> => {
const [resizedImage, setResizedImage] = createSignal<string | undefined>(undefined);
@@ -39,7 +39,7 @@ const useResizedImage = ({
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, dw, dh);
const dataUrl = canvas.toDataURL('image/jpeg');
const dataUrl = canvas.toDataURL('image/jpeg', encoderOptions);
setResizedImage(dataUrl);
});

View File

@@ -1,7 +1,4 @@
// const commands = ['openPostForm'] as const;
// type Commands = (typeof commands)[number];
import { onMount, onCleanup, type JSX } from 'solid-js';
import { onMount, onCleanup } from 'solid-js';
import throttle from 'lodash/throttle';

View File

@@ -1,4 +1,4 @@
import { Kind, Event as NostrEvent } from 'nostr-tools';
import { Event as NostrEvent } from 'nostr-tools';
import GenericEvent from '@/nostr/event/GenericEvent';
import Reaction from '@/nostr/event/Reaction';

View File

@@ -1,44 +0,0 @@
import { Event as NostrEvent, Kind } from 'nostr-tools';
import GenericEvent from '@/nostr/event/GenericEvent';
class LongFormContent extends GenericEvent {
constructor(rawEvent: NostrEvent) {
if (rawEvent.kind !== Kind.Article) {
throw new TypeError('kind should be 30023');
}
super(rawEvent);
}
#getMeta(tagName: string): string | null {
const tags = this.findTagsByName(tagName);
if (tags.length === 0) return null;
const [, value] = tags[0];
return value;
}
title(): string | null {
return this.#getMeta('title');
}
image(): string | null {
return this.#getMeta('image');
}
summary(): string | null {
return this.#getMeta('image');
}
publishedAt(): string | null {
return this.#getMeta('publishedAt');
}
publishedAtAsDate(): Date | null {
const publishedAt = this.publishedAt();
if (publishedAt == null) return null;
return new Date(parseInt(publishedAt, 10) * 1000);
}
}
export default LongFormContent;

View File

@@ -19,6 +19,7 @@ export type NonStandardProfile = {
export type Profile = StandardProfile & NonStandardProfile;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ProfileWithOtherProperties = Profile & Record<string, any>;
export const parseProfile = (content: string | null): Profile => {

View File

@@ -30,7 +30,7 @@ const reactionToReactionTypes = (event: Reaction): ReactionTypes => {
export default class Reaction extends GenericEvent {
constructor(rawEvent: NostrEvent) {
if (rawEvent.kind !== Kind.Reaction) {
if (rawEvent.kind !== (Kind.Reaction as number)) {
throw new TypeError('kind should be 7');
}
super(rawEvent);

View File

@@ -1,5 +1,4 @@
import { Event as NostrEvent, Kind } from 'nostr-tools';
import { z } from 'zod';
import GenericEvent from '@/nostr/event/GenericEvent';
import isValidId from '@/nostr/event/isValidId';
@@ -9,7 +8,6 @@ import parseTextNote, {
ParsedTextNote,
TagReference,
} from '@/nostr/parseTextNote';
import ensureSchema from '@/utils/ensureSchema';
export type EventMarker = 'reply' | 'root' | 'mention';
@@ -69,7 +67,7 @@ export default class TextNote extends GenericEvent {
#memoizedParsed: ParsedTextNote | undefined;
constructor(rawEvent: NostrEvent) {
if (rawEvent.kind !== Kind.Text) {
if (rawEvent.kind !== (Kind.Text as number)) {
throw new TypeError('kind should be 1');
}
super(rawEvent);

View File

@@ -1,9 +1,8 @@
import assert from 'assert';
import { type Event as NostrEvent } from 'nostr-tools';
import { describe, it } from 'vitest';
import parseTextNote, { type ParsedTextNoteNode, TagReference } from '@/nostr/parseTextNote';
import parseTextNote, { type ParsedTextNoteNode } from '@/nostr/parseTextNote';
describe('parseTextNote', () => {
/*

View File

@@ -1,4 +1,4 @@
import { nip19, type Event as NostrEvent } from 'nostr-tools';
import { nip19 } from 'nostr-tools';
import { DecodeResult } from 'nostr-tools/lib/nip19';
const { decode } = nip19;

View File

@@ -162,33 +162,33 @@ const { addTask, removeTask } = useBatch<BatchedEventsTask>(() => ({
count += 1;
sub.on('event', (event: NostrEvent & { id: string }) => {
if (event.kind === Kind.Metadata) {
if (event.kind === (Kind.Metadata as number)) {
const registeredTasks = profileTasks.get(event.pubkey) ?? [];
resolveTasks(registeredTasks, event);
return;
}
if (event.kind === Kind.Reaction) {
if (event.kind === (Kind.Reaction as number)) {
// Use the last event id
const id = genericEvent(event).lastTaggedEventId();
if (id != null) {
const registeredTasks = reactionsTasks.get(id) ?? [];
resolveTasks(registeredTasks, event);
}
} else if ((event.kind as number) === 6) {
} else if (event.kind === (Kind.Repost as number)) {
// Use the last event id
const id = genericEvent(event).lastTaggedEventId();
if (id != null) {
const registeredTasks = repostsTasks.get(id) ?? [];
resolveTasks(registeredTasks, event);
}
} else if (event.kind === Kind.Zap) {
} else if (event.kind === (Kind.Zap as number)) {
const eTags = genericEvent(event).eTags();
eTags.forEach(([, id]) => {
const registeredTasks = repostsTasks.get(id) ?? [];
resolveTasks(registeredTasks, event);
});
} else if (event.kind === Kind.Contacts) {
} else if (event.kind === (Kind.Contacts as number)) {
const registeredTasks = followingsTasks.get(event.pubkey) ?? [];
resolveTasks(registeredTasks, event);
} else if (isParameterizedReplaceableEvent(event)) {

View File

@@ -6,7 +6,9 @@ type UseDecryptProps = {
encrypted: string;
};
// eslint-disable-next-line solid/reactivity
const [memo, setMemo] = createRoot(() => createSignal<Record<string, string>>({}));
// eslint-disable-next-line solid/reactivity
const [decrypting, setDecrypting] = createRoot(() => createSignal<Record<string, boolean>>({}));
const useDecrypt = (propsProvider: () => UseDecryptProps | null) => {

View File

@@ -1,6 +1,6 @@
import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools';
import { registerTask, BatchedEventsTask } from '@/nostr/useBatchedEvents';

View File

@@ -1,4 +1,4 @@
import { createMemo, observable } from 'solid-js';
import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools';

View File

@@ -16,7 +16,7 @@ const useVerification = (propsProvider: () => UseVerificationProps | null): UseV
const props = createMemo(propsProvider);
const query = createQuery(
() => ['useVerification', props()] as const,
({ queryKey, signal }) => {
({ queryKey }) => {
const [, currentProps] = queryKey;
if (currentProps == null) return Promise.resolve(null);
const { nip05: nip05string } = currentProps;

View File

@@ -6,7 +6,6 @@ import Columns from '@/components/column/Columns';
import GlobalModal from '@/components/modal/GlobalModal';
import SideBar from '@/components/SideBar';
import useConfig from '@/core/useConfig';
import useModalState from '@/hooks/useModalState';
import usePersistStatus from '@/hooks/usePersistStatus';
import { useMountShortcutKeys } from '@/hooks/useShortcutKeys';
import usePool from '@/nostr/usePool';

View File

@@ -1,18 +1,15 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
/* eslint-disable @typescript-eslint/no-explicit-any */
export type TupleNonNull<T extends readonly any[]> = {
[P in keyof T]: NonNullable<T[P]>;
};
const ensureNonNull =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
<T extends readonly any[]>(tuple: T) =>
<R>(f: (tupleNonNull: TupleNonNull<T>) => R): R | null => {
if (tuple.some((e) => e == null)) {
return null;
}
return f(tuple as TupleNonNull<T>);
};
<T extends readonly any[]>(tuple: T) =>
<R>(f: (tupleNonNull: TupleNonNull<T>) => R): R | null => {
if (tuple.some((e) => e == null)) {
return null;
}
return f(tuple as TupleNonNull<T>);
};
export default ensureNonNull;

View File

@@ -2,6 +2,7 @@ import { z } from 'zod';
const ensureSchema =
<T>(schema: z.Schema<T>) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(value: any): value is T =>
schema.safeParse(value).success;

View File

@@ -36,17 +36,6 @@ export type NostrBuildResult = {
}[];
};
const toHexString = (buff: ArrayBuffer): string => {
const arr = new Array(buff.byteLength);
const view = new Int8Array(buff);
for (let i = 0; i < view.byteLength; i += 1) {
arr[i] = view[i].toString(16).padStart(2, '0');
}
return arr.join();
};
export const uploadNostrBuild = async (blob: Blob): Promise<UploadResult> => {
const form = new FormData();
form.set('file', blob);
@@ -69,27 +58,6 @@ export const uploadNostrBuild = async (blob: Blob): Promise<UploadResult> => {
return { imageUrl: result.data[0].url };
};
export const uploadVoidCat = async (blob: Blob): Promise<any> => {
const data = await blob.arrayBuffer();
const digestBuffer = await window.crypto.subtle.digest('SHA-256', data);
const digest = toHexString(digestBuffer);
const res = await fetch('https://void.cat/upload', {
method: 'POST',
headers: {
Accept: 'application/json',
'V-Content-Type': blob.type,
'V-Full-Digest': digest,
},
mode: 'cors',
body: data,
});
if (!res.ok) throw new Error('failed to post image: status code was not 2xx');
return res.json();
};
export const uploaders = {
nostrBuild: {
name: 'nostr.build',

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const stripMargin = (strings: TemplateStringsArray, ...values: any[]) => {
const s = String.raw(strings, values);

View File

@@ -5,11 +5,7 @@
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"lib": ["dom", "dom.iterable", "esnext"],
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
@@ -20,19 +16,10 @@
"isolatedModules": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@/*": ["src/*"]
},
"incremental": true
},
"include": [
"vite.config.ts",
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx",
"./.eslintrc.js"
],
"exclude": [
"node_modules"
]
"include": ["vite.config.ts", "**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "./.eslintrc.js"],
"exclude": ["node_modules"]
}