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', 'created-at',
'actions', 'actions',
'content', '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: '' title: ''
labels: bug labels: bug
assignees: syusui-s assignees: syusui-s
--- ---
**Describe the bug** **Describe the bug**
@@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce** **To Reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 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. If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):** **Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari] - OS: [e.g. iOS]
- Version [e.g. 22] - Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):** **Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1] - Device: [e.g. iPhone6]
- Browser [e.g. stock browser, safari] - OS: [e.g. iOS8.1]
- Version [e.g. 22] - Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@ A nostr client like TweetDeck made with SolidJS.
## 使い方 ## 使い方
1. NIP-07に対応したブラウザ拡張機能のインストールが事前に必要です 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. https://syusui-s.github.io/rabbit/ にアクセス
1. NIP-07拡張機能に許可を求められるので許可ボタンを押す 1. NIP-07拡張機能に許可を求められるので許可ボタンを押す
1. タイムラインが表示されます 1. タイムラインが表示されます
@@ -41,8 +41,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
GNUアフェロー一般公衆利用許諾書バージョン3か、それ以降のいずれかのバージョン GNUアフェロー一般公衆利用許諾書バージョン3か、それ以降のいずれかのバージョン
が定める条件の下で再頒布または改変することができます。 が定める条件の下で再頒布または改変することができます。
このプログラムは有用であることを願って頒布されますが、 *全くの無保証* です。 このプログラムは有用であることを願って頒布されますが、 _全くの無保証_ です。
*商業可能性**特定目的への適合性* に対する保証は言外に示されたものも含め、全く存在しません。 _商業可能性__特定目的への適合性_ に対する保証は言外に示されたものも含め、全く存在しません。
詳しくはGNUアフェロー一般公衆利用許諾書をご覧ください。 詳しくはGNUアフェロー一般公衆利用許諾書をご覧ください。
あなたはこのプログラムと共にGNUアフェロー一般公衆利用許諾書のコピーを一部受け取っているはずです。 あなたはこのプログラムと共にGNUアフェロー一般公衆利用許諾書のコピーを一部受け取っているはずです。

View File

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

View File

@@ -9,9 +9,11 @@
"dev": "npm run generatePackageInfo && vite", "dev": "npm run generatePackageInfo && vite",
"build": "npm run generatePackageInfo && vite build", "build": "npm run generatePackageInfo && vite build",
"serve": "npm run generatePackageInfo && vite preview", "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 .", "prettier": "prettier -c .",
"eslint-fix": "eslint --cache --fix .", "eslint-fix": "eslint --fix .",
"prettier-fix": "prettier --write .", "prettier-fix": "prettier --write .",
"tsc": "tsc --noEmit --skipLibCheck", "tsc": "tsc --noEmit --skipLibCheck",
"test": "vitest run --no-watch", "test": "vitest run --no-watch",

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
prettier --write "$@" 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; pickerElement = picker as any as HTMLElement;
popupRef?.elem?.appendChild(pickerElement); 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'; import BookmarkIcon from 'heroicons/24/outline/bookmark.svg';
@@ -9,7 +9,6 @@ import Bookmark from '@/components/timeline/Bookmark';
import { BookmarkColumnType } from '@/core/column'; import { BookmarkColumnType } from '@/core/column';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import { useTranslation } from '@/i18n/useTranslation'; import { useTranslation } from '@/i18n/useTranslation';
import useDecrypt from '@/nostr/useDecrypt';
import useParameterizedReplaceableEvent from '@/nostr/useParameterizedReplaceableEvent'; import useParameterizedReplaceableEvent from '@/nostr/useParameterizedReplaceableEvent';
type BookmarkColumnDisplayProps = { type BookmarkColumnDisplayProps = {
@@ -28,6 +27,8 @@ const BookmarkColumn: Component<BookmarkColumnDisplayProps> = (props) => {
identifier: props.column.identifier, identifier: props.column.identifier,
})); }));
// TODO 暗号化されたデータがある場合は復号する
return ( return (
<Column <Column
header={ 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 ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
import { uniq } from 'lodash';
import { Kind } from 'nostr-tools'; import { Kind } from 'nostr-tools';
import BasicColumnHeader from '@/components/column/BasicColumnHeader'; import BasicColumnHeader from '@/components/column/BasicColumnHeader';
import Column from '@/components/column/Column'; import Column from '@/components/column/Column';
import ColumnSettings from '@/components/column/ColumnSettings'; import ColumnSettings from '@/components/column/ColumnSettings';
import Timeline from '@/components/timeline/Timeline'; import Timeline from '@/components/timeline/Timeline';
import { ChannelColumnType, FollowingColumnType } from '@/core/column'; import { ChannelColumnType } from '@/core/column';
import { applyContentFilter } from '@/core/contentFilter'; import { applyContentFilter } from '@/core/contentFilter';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import { useTranslation } from '@/i18n/useTranslation'; import { useTranslation } from '@/i18n/useTranslation';

View File

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

View File

@@ -39,10 +39,10 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
<EventLink eventId={props.event.id} kind={props.event.kind} /> <EventLink eventId={props.event.id} kind={props.event.kind} />
</span> </span>
</Match> </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} /> <TextNote event={props.event} embedding={props.actions} actions={props.actions} />
</Match> </Match>
<Match when={(props.event.kind as number) === 6}> <Match when={props.event.kind === (Kind.Repost as number)}>
<Repost event={props.event} /> <Repost event={props.event} />
</Match> </Match>
</Switch> </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 { Show, type Component } from 'solid-js';
import ColumnItem from '@/components/ColumnItem';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import TextNoteDisplay, { TextNoteDisplayProps } from '@/components/event/textNote/TextNoteDisplay'; import TextNoteDisplay, { TextNoteDisplayProps } from '@/components/event/textNote/TextNoteDisplay';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';

View File

@@ -1,13 +1,13 @@
import { Component } from 'solid-js'; import { Component } from 'solid-js';
import Bell from 'heroicons/24/outline/bell.svg'; 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 GlobeAlt from 'heroicons/24/outline/globe-alt.svg';
import Heart from 'heroicons/24/outline/heart.svg'; import Heart from 'heroicons/24/outline/heart.svg';
import Home from 'heroicons/24/outline/home.svg'; import Home from 'heroicons/24/outline/home.svg';
import MagnifyingGlass from 'heroicons/24/outline/magnifying-glass.svg'; import MagnifyingGlass from 'heroicons/24/outline/magnifying-glass.svg';
import User from 'heroicons/24/outline/user.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 BasicModal from '@/components/modal/BasicModal';
import { 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'; 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 ensureNonNull from '@/utils/ensureNonNull';
import epoch from '@/utils/epoch'; import epoch from '@/utils/epoch';
import npubEncodeFallback from '@/utils/npubEncodeFallback'; import npubEncodeFallback from '@/utils/npubEncodeFallback';
import stripMargin from '@/utils/stripMargin';
import timeout from '@/utils/timeout'; import timeout from '@/utils/timeout';
export type ProfileDisplayProps = { export type ProfileDisplayProps = {
@@ -83,7 +82,6 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
})), })),
); );
const following = () => myFollowingPubkeys().includes(props.pubkey); const following = () => myFollowingPubkeys().includes(props.pubkey);
const refetchMyFollowing = () => myFollowingQuery.refetch();
const { followingPubkeys: userFollowingPubkeys, query: userFollowingQuery } = useFollowings( const { followingPubkeys: userFollowingPubkeys, query: userFollowingQuery } = useFollowings(
() => ({ pubkey: props.pubkey }), () => ({ pubkey: props.pubkey }),

View File

@@ -6,7 +6,6 @@ import ColumnItem from '@/components/ColumnItem';
import Reaction from '@/components/event/Reaction'; import Reaction from '@/components/event/Reaction';
import Repost from '@/components/event/Repost'; import Repost from '@/components/event/Repost';
import TextNote from '@/components/event/TextNote'; import TextNote from '@/components/event/TextNote';
import ZapReceipt from '@/components/event/ZapReceipt';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
export type NotificationProps = { export type NotificationProps = {
@@ -21,29 +20,22 @@ const Notification: Component<NotificationProps> = (props) => {
{(event) => ( {(event) => (
<Show when={!shouldMuteEvent(event)}> <Show when={!shouldMuteEvent(event)}>
<Switch fallback={<div>unknown event</div>}> <Switch fallback={<div>unknown event</div>}>
<Match when={event.kind === Kind.Text}> <Match when={event.kind === (Kind.Text as number)}>
<ColumnItem> <ColumnItem>
<TextNote event={event} /> <TextNote event={event} />
</ColumnItem> </ColumnItem>
</Match> </Match>
<Match when={event.kind === Kind.Reaction}> <Match when={event.kind === (Kind.Reaction as number)}>
<ColumnItem> <ColumnItem>
<Reaction event={event} /> <Reaction event={event} />
</ColumnItem> </ColumnItem>
</Match> </Match>
{/* TODO ちゃんとnotification用のコンポーネント使う */} {/* TODO ちゃんとnotification用のコンポーネント使う */}
<Match when={(event.kind as number) === 6}> <Match when={event.kind === (Kind.Repost as number)}>
<ColumnItem> <ColumnItem>
<Repost event={event} /> <Repost event={event} />
</ColumnItem> </ColumnItem>
</Match> </Match>
{/*
<Match when={event.kind === Kind.Zap}>
<ColumnItem>
<ZapReceipt event={event} />
</ColumnItem>
</Match>
*/}
</Switch> </Switch>
</Show> </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'; import ClipboardDocument from 'heroicons/24/outline/clipboard-document.svg';
@@ -13,7 +13,7 @@ const Copy: Component<CopyProps> = (props) => {
const handleClick = () => { const handleClick = () => {
navigator.clipboard navigator.clipboard
.writeText(props.text) .writeText(props.text)
.then((e) => { .then(() => {
setShowPopup(true); setShowPopup(true);
setTimeout(() => setShowPopup(false), 1000); setTimeout(() => setShowPopup(false), 1000);
}) })

View File

@@ -181,7 +181,7 @@ const useConfig = (): UseConfig => {
const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey); const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey);
const hasMutedKeyword = (event: NostrEvent) => { 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 config.mutedKeywords.some((keyword) => event.content.includes(keyword));
} }
return false; return false;
@@ -192,7 +192,7 @@ const useConfig = (): UseConfig => {
return ( return (
isPubkeyMuted(event.pubkey) || isPubkeyMuted(event.pubkey) ||
ev.taggedPubkeys().some(isPubkeyMuted) || 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> = export type MessageChannelResponse<T> =
| { requestId: string; ok: true; response: T } | { requestId: string; ok: true; response: T }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| { requestId: string; ok: false; error: any }; | { requestId: string; ok: false; error: any };
const [channels, setChannels]: Signal<Record<string, MessageChannel>> = createSignal({}); const [channels, setChannels]: Signal<Record<string, MessageChannel>> = createSignal({});

View File

@@ -5,14 +5,14 @@ export type UseResizedImageProps = {
imageUrl: Accessor<string | undefined>; imageUrl: Accessor<string | undefined>;
width: number; width: number;
height: number; height: number;
encoderOption?: number; encoderOptions?: number;
}; };
const useResizedImage = ({ const useResizedImage = ({
imageUrl, imageUrl,
width, width,
height, height,
encoderOption, encoderOptions,
}: UseResizedImageProps): Accessor<string | undefined> => { }: UseResizedImageProps): Accessor<string | undefined> => {
const [resizedImage, setResizedImage] = createSignal<string | undefined>(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); 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); setResizedImage(dataUrl);
}); });

View File

@@ -1,7 +1,4 @@
// const commands = ['openPostForm'] as const; import { onMount, onCleanup } from 'solid-js';
// type Commands = (typeof commands)[number];
import { onMount, onCleanup, type JSX } from 'solid-js';
import throttle from 'lodash/throttle'; 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 GenericEvent from '@/nostr/event/GenericEvent';
import Reaction from '@/nostr/event/Reaction'; 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; export type Profile = StandardProfile & NonStandardProfile;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ProfileWithOtherProperties = Profile & Record<string, any>; export type ProfileWithOtherProperties = Profile & Record<string, any>;
export const parseProfile = (content: string | null): Profile => { export const parseProfile = (content: string | null): Profile => {

View File

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

View File

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

View File

@@ -1,9 +1,8 @@
import assert from 'assert'; import assert from 'assert';
import { type Event as NostrEvent } from 'nostr-tools';
import { describe, it } from 'vitest'; import { describe, it } from 'vitest';
import parseTextNote, { type ParsedTextNoteNode, TagReference } from '@/nostr/parseTextNote'; import parseTextNote, { type ParsedTextNoteNode } from '@/nostr/parseTextNote';
describe('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'; import { DecodeResult } from 'nostr-tools/lib/nip19';
const { decode } = nip19; const { decode } = nip19;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ import { z } from 'zod';
const ensureSchema = const ensureSchema =
<T>(schema: z.Schema<T>) => <T>(schema: z.Schema<T>) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(value: any): value is T => (value: any): value is T =>
schema.safeParse(value).success; 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> => { export const uploadNostrBuild = async (blob: Blob): Promise<UploadResult> => {
const form = new FormData(); const form = new FormData();
form.set('file', blob); form.set('file', blob);
@@ -69,27 +58,6 @@ export const uploadNostrBuild = async (blob: Blob): Promise<UploadResult> => {
return { imageUrl: result.data[0].url }; 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 = { export const uploaders = {
nostrBuild: { nostrBuild: {
name: 'nostr.build', 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 stripMargin = (strings: TemplateStringsArray, ...values: any[]) => {
const s = String.raw(strings, values); const s = String.raw(strings, values);

View File

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