forked from coracle/flotilla
Use user blossom server list for settings, add InputList
This commit is contained in:
+8
-13
@@ -2,22 +2,15 @@ import {mount} from "svelte"
|
|||||||
import type {Writable} from "svelte/store"
|
import type {Writable} from "svelte/store"
|
||||||
import {get} from "svelte/store"
|
import {get} from "svelte/store"
|
||||||
import type {StampedEvent} from "@welshman/util"
|
import type {StampedEvent} from "@welshman/util"
|
||||||
|
import {getTagValue, getListTags} from "@welshman/util"
|
||||||
import {Router} from "@welshman/router"
|
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 {Editor, MentionSuggestion, WelshmanExtension} from "@welshman/editor"
|
||||||
import {getSetting, userSettingValues} from "@app/state"
|
|
||||||
import {makeMentionNodeView} from "./MentionNodeView"
|
import {makeMentionNodeView} from "./MentionNodeView"
|
||||||
import ProfileSuggestion from "./ProfileSuggestion.svelte"
|
import ProfileSuggestion from "./ProfileSuggestion.svelte"
|
||||||
|
|
||||||
export const getUploadType = () => getSetting<"nip96" | "blossom">("upload_type")
|
export const getUploadUrl = () =>
|
||||||
|
getTagValue("server", getListTags(userBlossomServers.get())) || "https://cdn.satellite.earth"
|
||||||
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 signWithAssert = async (template: StampedEvent) => {
|
export const signWithAssert = async (template: StampedEvent) => {
|
||||||
const event = await signer.get().sign(template)
|
const event = await signer.get().sign(template)
|
||||||
@@ -33,6 +26,7 @@ export const makeEditor = ({
|
|||||||
placeholder = "",
|
placeholder = "",
|
||||||
url,
|
url,
|
||||||
submit,
|
submit,
|
||||||
|
uploadUrl = getUploadUrl(),
|
||||||
uploading,
|
uploading,
|
||||||
wordCount,
|
wordCount,
|
||||||
}: {
|
}: {
|
||||||
@@ -43,6 +37,7 @@ export const makeEditor = ({
|
|||||||
placeholder?: string
|
placeholder?: string
|
||||||
url?: string
|
url?: string
|
||||||
submit: () => void
|
submit: () => void
|
||||||
|
uploadUrl?: string
|
||||||
uploading?: Writable<boolean>
|
uploading?: Writable<boolean>
|
||||||
wordCount?: Writable<number>
|
wordCount?: Writable<number>
|
||||||
}) =>
|
}) =>
|
||||||
@@ -54,8 +49,8 @@ export const makeEditor = ({
|
|||||||
WelshmanExtension.configure({
|
WelshmanExtension.configure({
|
||||||
submit,
|
submit,
|
||||||
sign: signWithAssert,
|
sign: signWithAssert,
|
||||||
defaultUploadType: getUploadType(),
|
defaultUploadType: "blossom",
|
||||||
defaultUploadUrl: getUploadUrl(),
|
defaultUploadUrl: uploadUrl,
|
||||||
extensions: {
|
extensions: {
|
||||||
placeholder: {
|
placeholder: {
|
||||||
config: {
|
config: {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import {
|
|||||||
loadMutes,
|
loadMutes,
|
||||||
loadFollows,
|
loadFollows,
|
||||||
loadProfile,
|
loadProfile,
|
||||||
|
loadBlossomServers,
|
||||||
loadRelaySelections,
|
loadRelaySelections,
|
||||||
loadInboxRelaySelections,
|
loadInboxRelaySelections,
|
||||||
} from "@welshman/app"
|
} from "@welshman/app"
|
||||||
@@ -392,6 +393,7 @@ export const loadUserData = async (pubkey: string, relays: string[] = []) => {
|
|||||||
sleep(3000),
|
sleep(3000),
|
||||||
Promise.all([
|
Promise.all([
|
||||||
loadInboxRelaySelections(pubkey, relays),
|
loadInboxRelaySelections(pubkey, relays),
|
||||||
|
loadBlossomServers(pubkey, relays),
|
||||||
loadMembership(pubkey, relays),
|
loadMembership(pubkey, relays),
|
||||||
loadSettings(pubkey, relays),
|
loadSettings(pubkey, relays),
|
||||||
loadProfile(pubkey, relays),
|
loadProfile(pubkey, relays),
|
||||||
|
|||||||
@@ -297,9 +297,6 @@ export type Settings = {
|
|||||||
report_usage: boolean
|
report_usage: boolean
|
||||||
report_errors: boolean
|
report_errors: boolean
|
||||||
send_delay: number
|
send_delay: number
|
||||||
upload_type: "nip96" | "blossom"
|
|
||||||
nip96_urls: string[]
|
|
||||||
blossom_urls: string[]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,9 +306,6 @@ export const defaultSettings = {
|
|||||||
report_usage: true,
|
report_usage: true,
|
||||||
report_errors: false,
|
report_errors: false,
|
||||||
send_delay: 3000,
|
send_delay: 3000,
|
||||||
upload_type: "nip96",
|
|
||||||
nip96_urls: ["https://nostr.build"],
|
|
||||||
blossom_urls: ["https://cdn.satellite.earth"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const settings = deriveEventsMapped<Settings>(repository, {
|
export const settings = deriveEventsMapped<Settings>(repository, {
|
||||||
|
|||||||
@@ -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 |
@@ -41,6 +41,7 @@
|
|||||||
import GallerySend from "@assets/icons/Gallery Send.svg?dataurl"
|
import GallerySend from "@assets/icons/Gallery Send.svg?dataurl"
|
||||||
import Ghost from "@assets/icons/Ghost.svg?dataurl"
|
import Ghost from "@assets/icons/Ghost.svg?dataurl"
|
||||||
import Hashtag from "@assets/icons/Hashtag.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 HandPills from "@assets/icons/Hand Pills.svg?dataurl"
|
||||||
import HomeSmile from "@assets/icons/Home Smile.svg?dataurl"
|
import HomeSmile from "@assets/icons/Home Smile.svg?dataurl"
|
||||||
import Inbox from "@assets/icons/Inbox.svg?dataurl"
|
import Inbox from "@assets/icons/Inbox.svg?dataurl"
|
||||||
@@ -131,6 +132,7 @@
|
|||||||
"gallery-send": GallerySend,
|
"gallery-send": GallerySend,
|
||||||
ghost: Ghost,
|
ghost: Ghost,
|
||||||
hashtag: Hashtag,
|
hashtag: Hashtag,
|
||||||
|
"hamburger-menu": HamburgerMenu,
|
||||||
"hand-pills": HandPills,
|
"hand-pills": HandPills,
|
||||||
"home-smile": HomeSmile,
|
"home-smile": HomeSmile,
|
||||||
inbox: Inbox,
|
inbox: Inbox,
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
FOLLOWS,
|
FOLLOWS,
|
||||||
PROFILE,
|
PROFILE,
|
||||||
RELAYS,
|
RELAYS,
|
||||||
|
BLOSSOM_SERVERS,
|
||||||
getRelaysFromList,
|
getRelaysFromList,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import {Nip46Broker, makeSecret} from "@welshman/signer"
|
import {Nip46Broker, makeSecret} from "@welshman/signer"
|
||||||
@@ -137,7 +138,8 @@
|
|||||||
limit: 10_000,
|
limit: 10_000,
|
||||||
repository,
|
repository,
|
||||||
rankEvent: (e: TrustedEvent) => {
|
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
|
if ([EVENT_TIME, THREAD, MESSAGE, WRAP].includes(e.kind)) return 0.9
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -1,19 +1,35 @@
|
|||||||
<script lang="ts">
|
<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 {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 {preventDefault} from "@lib/html"
|
||||||
import Field from "@lib/components/Field.svelte"
|
import Field from "@lib/components/Field.svelte"
|
||||||
import FieldInline from "@lib/components/FieldInline.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 Button from "@lib/components/Button.svelte"
|
||||||
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
|
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
|
||||||
import {pushToast} from "@app/toast"
|
import {pushToast} from "@app/toast"
|
||||||
import {SETTINGS, PLATFORM_NAME, userSettingValues} from "@app/state"
|
import {SETTINGS, PLATFORM_NAME, userSettingValues} from "@app/state"
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
mutedPubkeys = getPubkeyTagValues(getListTags($userMutes))
|
|
||||||
settings = {...$userSettingValues}
|
settings = {...$userSettingValues}
|
||||||
|
mutedPubkeys = getPubkeyTagValues(getListTags($userMutes))
|
||||||
|
blossomServers = getTagValues("server", getListTags($userBlossomServers))
|
||||||
}
|
}
|
||||||
|
|
||||||
const onsubmit = preventDefault(async () => {
|
const onsubmit = preventDefault(async () => {
|
||||||
@@ -31,11 +47,19 @@
|
|||||||
relays,
|
relays,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
publishThunk({
|
||||||
|
event: createEvent(BLOSSOM_SERVERS, {tags: blossomServers.map(tagger("server"))}),
|
||||||
|
relays,
|
||||||
|
})
|
||||||
|
|
||||||
pushToast({message: "Your settings have been saved!"})
|
pushToast({message: "Your settings have been saved!"})
|
||||||
})
|
})
|
||||||
|
|
||||||
let settings = $state({...$userSettingValues})
|
let settings = $state({...$userSettingValues})
|
||||||
let mutedPubkeys = $state(getPubkeyTagValues(getListTags($userMutes)))
|
let mutedPubkeys = $state(getPubkeyTagValues(getListTags($userMutes)))
|
||||||
|
let blossomServers = $state(getTagValues("server", getListTags($userBlossomServers)))
|
||||||
|
|
||||||
|
$inspect(blossomServers)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form class="content column gap-4" {onsubmit}>
|
<form class="content column gap-4" {onsubmit}>
|
||||||
@@ -134,20 +158,11 @@
|
|||||||
<p>Media Server</p>
|
<p>Media Server</p>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet input()}
|
{#snippet input()}
|
||||||
<div class="flex flex-col gap-2 lg:flex-row">
|
<InputList bind:value={blossomServers}>
|
||||||
<select bind:value={settings.upload_type} class="select select-bordered">
|
{#snippet addLabel()}
|
||||||
<option value="nip96">NIP 96 (default)</option>
|
Add Server
|
||||||
<option value="blossom">Blossom</option>
|
{/snippet}
|
||||||
</select>
|
</InputList>
|
||||||
<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>
|
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet info()}
|
{#snippet info()}
|
||||||
<p>Choose a media server type and url for files you upload to {PLATFORM_NAME}.</p>
|
<p>Choose a media server type and url for files you upload to {PLATFORM_NAME}.</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user