diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..21113f6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +npm run lint +npm run check diff --git a/package-lock.json b/package-lock.json index 02b6973..54df626 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@tiptap/extension-placeholder": "^2.9.1", "@tiptap/extension-text": "^2.6.6", "@tiptap/suggestion": "^2.6.4", + "@types/qrcode": "^1.5.5", "@types/throttle-debounce": "^5.0.2", "@vite-pwa/assets-generator": "^0.2.6", "@vite-pwa/sveltekit": "^0.6.6", @@ -43,6 +44,7 @@ "dotenv": "^16.4.5", "emoji-picker-element": "^1.22.8", "fuse.js": "^7.0.0", + "husky": "^9.1.6", "idb": "^8.0.0", "nostr-editor": "^0.0.3", "nostr-tools": "^2.7.2", @@ -3764,6 +3766,15 @@ "integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==", "dev": true }, + "node_modules/@types/qrcode": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz", + "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -6555,6 +6566,21 @@ "node": ">= 0.4" } }, + "node_modules/husky": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ico-endec": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz", diff --git a/package.json b/package.json index 2c8d306..f5c4e28 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --check . && eslint .", - "format": "prettier --write ." + "format": "prettier --write .", + "prepare": "husky" }, "devDependencies": { "@sveltejs/kit": "^2.0.0", @@ -51,6 +52,7 @@ "@tiptap/extension-placeholder": "^2.9.1", "@tiptap/extension-text": "^2.6.6", "@tiptap/suggestion": "^2.6.4", + "@types/qrcode": "^1.5.5", "@types/throttle-debounce": "^5.0.2", "@vite-pwa/assets-generator": "^0.2.6", "@vite-pwa/sveltekit": "^0.6.6", @@ -68,6 +70,7 @@ "dotenv": "^16.4.5", "emoji-picker-element": "^1.22.8", "fuse.js": "^7.0.0", + "husky": "^9.1.6", "idb": "^8.0.0", "nostr-editor": "^0.0.3", "nostr-tools": "^2.7.2", diff --git a/src/app/commands.ts b/src/app/commands.ts index d870f43..01108b3 100644 --- a/src/app/commands.ts +++ b/src/app/commands.ts @@ -30,7 +30,7 @@ import { signer, repository, publishThunk, - mergeThunks, + publishThunks, loadProfile, loadInboxRelaySelections, profilesByPubkey, @@ -335,15 +335,13 @@ export const sendWrapped = async ({ }) => { const nip59 = Nip59.fromSigner(signer.get()!) - return mergeThunks( + return publishThunks( await Promise.all( - uniq(pubkeys).map(async recipient => - publishThunk({ - event: await nip59.wrap(recipient, stamp(template)), - relays: ctx.app.router.PubkeyInbox(recipient).getUrls(), - delay, - }), - ), + uniq(pubkeys).map(async recipient => ({ + event: await nip59.wrap(recipient, stamp(template)), + relays: ctx.app.router.PubkeyInbox(recipient).getUrls(), + delay, + })), ), ) } diff --git a/src/app/components/ChannelConversation.svelte b/src/app/components/ChannelConversation.svelte index d271443..2b0eb7d 100644 --- a/src/app/components/ChannelConversation.svelte +++ b/src/app/components/ChannelConversation.svelte @@ -1,11 +1,11 @@
diff --git a/src/app/components/ChannelMessage.svelte b/src/app/components/ChannelMessage.svelte index 9395c43..48241d5 100644 --- a/src/app/components/ChannelMessage.svelte +++ b/src/app/components/ChannelMessage.svelte @@ -2,8 +2,13 @@ import {readable} from "svelte/store" import {hash} from "@welshman/lib" import type {TrustedEvent} from "@welshman/util" - import {deriveProfile, deriveProfileDisplay, formatTimestampAsTime, pubkey} from "@welshman/app" - import type {Thunk} from "@welshman/app" + import { + thunks, + deriveProfile, + deriveProfileDisplay, + formatTimestampAsTime, + pubkey, + } from "@welshman/app" import {isMobile} from "@lib/html" import LongPress from "@lib/components/LongPress.svelte" import Avatar from "@lib/components/Avatar.svelte" @@ -16,13 +21,12 @@ import ChannelMessageEmojiButton from "@app/components/ChannelMessageEmojiButton.svelte" import ChannelMessageMenuButton from "@app/components/ChannelMessageMenuButton.svelte" import ChannelMessageMenuMobile from "@app/components/ChannelMessageMenuMobile.svelte" - import {colors, thunks, tagRoom, deriveEvent, pubkeyLink} from "@app/state" + import {colors, tagRoom, deriveEvent, pubkeyLink} from "@app/state" import {publishDelete, publishReaction} from "@app/commands" import {pushDrawer, pushModal} from "@app/modal" export let url, room export let event: TrustedEvent - export let thunk: Thunk export let showPubkey = false export let isHead = false export let inert = false @@ -90,7 +94,7 @@
{#if thunk} - + {/if}
diff --git a/src/app/components/Chat.svelte b/src/app/components/Chat.svelte index fa929ab..9a7127b 100644 --- a/src/app/components/Chat.svelte +++ b/src/app/components/Chat.svelte @@ -10,7 +10,7 @@ -
- {#if canCancel || isPending} - +
+ {#if isFailure && failure} + {@const [url, {message, status}] = failure} + + + + Failed to send! + + + {:else if canCancel || isPending} + Sending... {#if canCancel} {/if} - {:else if isFailure && failure} - {@const [url, {message, status}] = failure} - - - - Failed to send! - - {/if}
diff --git a/src/app/state.ts b/src/app/state.ts index 42c405e..1938ab6 100644 --- a/src/app/state.ts +++ b/src/app/state.ts @@ -1,5 +1,5 @@ import twColors from "tailwindcss/colors" -import {get, derived, writable} from "svelte/store" +import {get, derived} from "svelte/store" import {nip19} from "nostr-tools" import type {Maybe} from "@welshman/lib" import { @@ -55,7 +55,7 @@ import { userFollows, ensurePlaintext, } from "@welshman/app" -import type {AppSyncOpts, Thunk} from "@welshman/app" +import type {AppSyncOpts} from "@welshman/app" import type {SubscribeRequestWithHandlers} from "@welshman/net" import {deriveEvents, deriveEventsMapped, withGetter} from "@welshman/store" @@ -144,8 +144,6 @@ export const pubkeyLink = ( relays = ctx.app.router.FromPubkeys([pubkey]).getUrls(), ) => entityLink(nip19.nprofileEncode({pubkey, relays})) -export const thunks = writable({} as Record) - export const tagRoom = (room: string, url: string) => [ROOM, room, url] export const getDefaultPubkeys = () => { diff --git a/src/lib/components/LongPress.svelte b/src/lib/components/LongPress.svelte index 83f60b8..f626b0b 100644 --- a/src/lib/components/LongPress.svelte +++ b/src/lib/components/LongPress.svelte @@ -21,7 +21,7 @@ const onTouchEnd = () => clearTimeout(timeout) let touch: Touch - let timeout: number + let timeout: any
{ return result } -type ScrollerOpts = { +export type ScrollerOpts = { onScroll: () => any element: Element threshold?: number @@ -24,6 +24,11 @@ type ScrollerOpts = { delay?: number } +export type Scroller = { + check: () => Promise + stop: () => void +} + export const createScroller = ({ onScroll, element, diff --git a/src/routes/spaces/[relay]/[room]/+page.svelte b/src/routes/spaces/[relay]/[room]/+page.svelte index be6f6a7..028eee5 100644 --- a/src/routes/spaces/[relay]/[room]/+page.svelte +++ b/src/routes/spaces/[relay]/[room]/+page.svelte @@ -10,7 +10,7 @@