Use user blossom server list for settings, add InputList

This commit is contained in:
Jon Staab
2025-04-29 11:04:39 -07:00
parent 8c71b7d9b9
commit 5a7750a91b
8 changed files with 133 additions and 38 deletions
+8 -13
View File
@@ -2,22 +2,15 @@ import {mount} from "svelte"
import type {Writable} from "svelte/store"
import {get} from "svelte/store"
import type {StampedEvent} from "@welshman/util"
import {getTagValue, getListTags} from "@welshman/util"
import {Router} from "@welshman/router"
import {signer, profileSearch} from "@welshman/app"
import {signer, profileSearch, userBlossomServers} from "@welshman/app"
import {Editor, MentionSuggestion, WelshmanExtension} from "@welshman/editor"
import {getSetting, userSettingValues} from "@app/state"
import {makeMentionNodeView} from "./MentionNodeView"
import ProfileSuggestion from "./ProfileSuggestion.svelte"
export const getUploadType = () => getSetting<"nip96" | "blossom">("upload_type")
export const getUploadUrl = () => {
const {upload_type, nip96_urls, blossom_urls} = userSettingValues.get()
return upload_type === "nip96"
? nip96_urls[0] || "https://nostr.build"
: blossom_urls[0] || "https://cdn.satellite.earth"
}
export const getUploadUrl = () =>
getTagValue("server", getListTags(userBlossomServers.get())) || "https://cdn.satellite.earth"
export const signWithAssert = async (template: StampedEvent) => {
const event = await signer.get().sign(template)
@@ -33,6 +26,7 @@ export const makeEditor = ({
placeholder = "",
url,
submit,
uploadUrl = getUploadUrl(),
uploading,
wordCount,
}: {
@@ -43,6 +37,7 @@ export const makeEditor = ({
placeholder?: string
url?: string
submit: () => void
uploadUrl?: string
uploading?: Writable<boolean>
wordCount?: Writable<number>
}) =>
@@ -54,8 +49,8 @@ export const makeEditor = ({
WelshmanExtension.configure({
submit,
sign: signWithAssert,
defaultUploadType: getUploadType(),
defaultUploadUrl: getUploadUrl(),
defaultUploadType: "blossom",
defaultUploadUrl: uploadUrl,
extensions: {
placeholder: {
config: {
+2
View File
@@ -41,6 +41,7 @@ import {
loadMutes,
loadFollows,
loadProfile,
loadBlossomServers,
loadRelaySelections,
loadInboxRelaySelections,
} from "@welshman/app"
@@ -392,6 +393,7 @@ export const loadUserData = async (pubkey: string, relays: string[] = []) => {
sleep(3000),
Promise.all([
loadInboxRelaySelections(pubkey, relays),
loadBlossomServers(pubkey, relays),
loadMembership(pubkey, relays),
loadSettings(pubkey, relays),
loadProfile(pubkey, relays),
-6
View File
@@ -297,9 +297,6 @@ export type Settings = {
report_usage: boolean
report_errors: boolean
send_delay: number
upload_type: "nip96" | "blossom"
nip96_urls: string[]
blossom_urls: string[]
}
}
@@ -309,9 +306,6 @@ export const defaultSettings = {
report_usage: true,
report_errors: false,
send_delay: 3000,
upload_type: "nip96",
nip96_urls: ["https://nostr.build"],
blossom_urls: ["https://cdn.satellite.earth"],
}
export const settings = deriveEventsMapped<Settings>(repository, {
+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 7L4 7" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
<path d="M20 12L4 12" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
<path d="M20 17L4 17" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 350 B

+2
View File
@@ -41,6 +41,7 @@
import GallerySend from "@assets/icons/Gallery Send.svg?dataurl"
import Ghost from "@assets/icons/Ghost.svg?dataurl"
import Hashtag from "@assets/icons/Hashtag.svg?dataurl"
import HamburgerMenu from "@assets/icons/Hamburger Menu.svg?dataurl"
import HandPills from "@assets/icons/Hand Pills.svg?dataurl"
import HomeSmile from "@assets/icons/Home Smile.svg?dataurl"
import Inbox from "@assets/icons/Inbox.svg?dataurl"
@@ -131,6 +132,7 @@
"gallery-send": GallerySend,
ghost: Ghost,
hashtag: Hashtag,
"hamburger-menu": HamburgerMenu,
"hand-pills": HandPills,
"home-smile": HomeSmile,
inbox: Inbox,
+80
View File
@@ -0,0 +1,80 @@
<script lang="ts">
import type {Snippet} from "svelte"
import {append, removeAt, replaceAt, insertAt} from "@welshman/lib"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
type Props = {
value: string[]
addLabel?: Snippet
placeholder?: string
}
let {value = $bindable(), addLabel, placeholder = "Enter text..."}: Props = $props()
let draggedIndex: number | null = $state(null)
const onChange = (newValue: string[]) => {
value = newValue
}
const addItem = () => onChange(append("", value))
const removeItem = (index: number) => onChange(removeAt(index, value))
const updateItem = (index: number, item: string) => onChange(replaceAt(index, item, value))
const handleDragStart = (e: DragEvent, index: number) => {
draggedIndex = index
if (e.dataTransfer) {
e.dataTransfer.effectAllowed = "move"
}
}
const handleDragOver = (e: DragEvent, index: number) => {
e.preventDefault()
if (draggedIndex !== null && draggedIndex !== index) {
onChange(insertAt(index, value[draggedIndex], removeAt(draggedIndex, value)))
draggedIndex = index
}
}
const handleDragEnd = () => {
draggedIndex = null
}
</script>
<div class="flex flex-col gap-2" role="list">
{#each value as item, index (item)}
<div
class="flex items-center gap-2"
draggable="true"
role="listitem"
aria-label="Draggable item"
ondragstart={e => handleDragStart(e, index)}
ondragover={e => handleDragOver(e, index)}
ondragend={handleDragEnd}>
<Button onclick={() => removeItem(index)}>
<Icon icon="trash-bin-2" />
</Button>
<input
type="text"
class="input input-bordered w-full"
value={item}
{placeholder}
oninput={e => updateItem(index, e.currentTarget.value)} />
<div class="cursor-move" role="button" aria-label="Drag handle">
<Icon icon="hamburger-menu" />
</div>
</div>
{/each}
<Button onclick={addItem} class="btn btn-link w-fit px-0">
<Icon icon="add-circle" size={5} />
{#if addLabel}
{@render addLabel?.()}
{:else}
Add Item
{/if}
</Button>
</div>
+3 -1
View File
@@ -19,6 +19,7 @@
FOLLOWS,
PROFILE,
RELAYS,
BLOSSOM_SERVERS,
getRelaysFromList,
} from "@welshman/util"
import {Nip46Broker, makeSecret} from "@welshman/signer"
@@ -137,7 +138,8 @@
limit: 10_000,
repository,
rankEvent: (e: TrustedEvent) => {
if ([PROFILE, FOLLOWS, MUTES, RELAYS, INBOX_RELAYS].includes(e.kind)) return 1
if ([PROFILE, FOLLOWS, MUTES, RELAYS, BLOSSOM_SERVERS, INBOX_RELAYS].includes(e.kind))
return 1
if ([EVENT_TIME, THREAD, MESSAGE, WRAP].includes(e.kind)) return 0.9
return 0
+33 -18
View File
@@ -1,19 +1,35 @@
<script lang="ts">
import {getListTags, createEvent, getPubkeyTagValues, MUTES} from "@welshman/util"
import {
getListTags,
tagger,
createEvent,
getPubkeyTagValues,
getTagValues,
MUTES,
BLOSSOM_SERVERS,
} from "@welshman/util"
import {Router} from "@welshman/router"
import {pubkey, signer, userMutes, tagPubkey, publishThunk} from "@welshman/app"
import {
pubkey,
signer,
userMutes,
tagPubkey,
publishThunk,
userBlossomServers,
} from "@welshman/app"
import {preventDefault} from "@lib/html"
import Field from "@lib/components/Field.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Icon from "@lib/components/Icon.svelte"
import InputList from "@lib/components/InputList.svelte"
import Button from "@lib/components/Button.svelte"
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
import {pushToast} from "@app/toast"
import {SETTINGS, PLATFORM_NAME, userSettingValues} from "@app/state"
const reset = () => {
mutedPubkeys = getPubkeyTagValues(getListTags($userMutes))
settings = {...$userSettingValues}
mutedPubkeys = getPubkeyTagValues(getListTags($userMutes))
blossomServers = getTagValues("server", getListTags($userBlossomServers))
}
const onsubmit = preventDefault(async () => {
@@ -31,11 +47,19 @@
relays,
})
publishThunk({
event: createEvent(BLOSSOM_SERVERS, {tags: blossomServers.map(tagger("server"))}),
relays,
})
pushToast({message: "Your settings have been saved!"})
})
let settings = $state({...$userSettingValues})
let mutedPubkeys = $state(getPubkeyTagValues(getListTags($userMutes)))
let blossomServers = $state(getTagValues("server", getListTags($userBlossomServers)))
$inspect(blossomServers)
</script>
<form class="content column gap-4" {onsubmit}>
@@ -134,20 +158,11 @@
<p>Media Server</p>
{/snippet}
{#snippet input()}
<div class="flex flex-col gap-2 lg:flex-row">
<select bind:value={settings.upload_type} class="select select-bordered">
<option value="nip96">NIP 96 (default)</option>
<option value="blossom">Blossom</option>
</select>
<label class="input input-bordered flex flex-grow items-center gap-2">
<Icon icon="link-round" />
{#if settings.upload_type === "nip96"}
<input class="grow" bind:value={settings.nip96_urls[0]} />
{:else}
<input class="grow" bind:value={settings.blossom_urls[0]} />
{/if}
</label>
</div>
<InputList bind:value={blossomServers}>
{#snippet addLabel()}
Add Server
{/snippet}
</InputList>
{/snippet}
{#snippet info()}
<p>Choose a media server type and url for files you upload to {PLATFORM_NAME}.</p>