mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 00:10:52 +00:00
Abort feed when updating opts
This commit is contained in:
parent
324045a1cb
commit
5a813e394e
@ -24,6 +24,7 @@
|
|||||||
- [x] Introduce new in-memory relay
|
- [x] Introduce new in-memory relay
|
||||||
- [x] Re-work feed controls
|
- [x] Re-work feed controls
|
||||||
- [x] Re-work utility library
|
- [x] Re-work utility library
|
||||||
|
- [x] Make buttons, chips, and inputs sleeker
|
||||||
|
|
||||||
# 0.4.4
|
# 0.4.4
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {equals} from 'ramda'
|
|
||||||
import {now} from "@welshman/lib"
|
import {now} from "@welshman/lib"
|
||||||
import {PublishStatus} from "@welshman/net"
|
import {PublishStatus} from "@welshman/net"
|
||||||
import {quantify, seconds} from "hurdak"
|
import {quantify, seconds} from "hurdak"
|
||||||
@ -98,7 +97,7 @@
|
|||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<Input
|
<Input
|
||||||
class="h-7 !rounded !border-tinted-700 !bg-neutral-800 !px-2 py-px text-tinted-200 outline-none"
|
class="border-tinted-700 bg-neutral-800 py-px text-tinted-200 outline-none"
|
||||||
on:blur={onSearchBlur}
|
on:blur={onSearchBlur}
|
||||||
on:keydown={onSearchKeydown}
|
on:keydown={onSearchKeydown}
|
||||||
bind:element={searchInput}
|
bind:element={searchInput}
|
||||||
|
@ -52,9 +52,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const update = async opts => {
|
const onChange = async opts => {
|
||||||
limit = 0
|
limit = 0
|
||||||
feed = opts.feed
|
feed = opts.feed
|
||||||
|
Storage.setJson("hideReplies", opts.shouldHideReplies)
|
||||||
start(opts)
|
start(opts)
|
||||||
|
|
||||||
if (feedLoader.compiler.canCompile(opts.feed)) {
|
if (feedLoader.compiler.canCompile(opts.feed)) {
|
||||||
@ -66,10 +67,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: {
|
onChange(opts)
|
||||||
update(opts)
|
|
||||||
Storage.setJson("hideReplies", opts.shouldHideReplies)
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const scroller = createScroller(loadMore, {element})
|
const scroller = createScroller(loadMore, {element})
|
||||||
@ -79,7 +77,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showControls}
|
{#if showControls}
|
||||||
<FeedControls {address} bind:opts />
|
<FeedControls {opts} {address} {onChange} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<FlexColumn xl bind:element>
|
<FlexColumn xl bind:element>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
} from "src/engine"
|
} from "src/engine"
|
||||||
|
|
||||||
export let opts
|
export let opts
|
||||||
|
export let onChange
|
||||||
export let address = null
|
export let address = null
|
||||||
|
|
||||||
const openListMenu = () => {
|
const openListMenu = () => {
|
||||||
@ -39,13 +40,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toggleReplies = () => {
|
const toggleReplies = () => {
|
||||||
opts = {...opts, shouldHideReplies: !opts.shouldHideReplies}
|
onChange({...opts, shouldHideReplies: !opts.shouldHideReplies})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSearch = definition => (getFeedArgs(definition)?.find(isSearchFeed)?.[1] as string) || ""
|
const getSearch = definition => (getFeedArgs(definition)?.find(isSearchFeed)?.[1] as string) || ""
|
||||||
|
|
||||||
const setFeedDefinition = definition => {
|
const setFeedDefinition = definition => {
|
||||||
opts = {...opts, feed: definition}
|
onChange({...opts, feed: definition})
|
||||||
search = getSearch(definition)
|
search = getSearch(definition)
|
||||||
closeListMenu()
|
closeListMenu()
|
||||||
closeForm()
|
closeForm()
|
||||||
@ -103,8 +104,9 @@
|
|||||||
|
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<Select
|
<Select
|
||||||
|
dark
|
||||||
value={subFeeds.find(isScopeFeed)?.[1] || null}
|
value={subFeeds.find(isScopeFeed)?.[1] || null}
|
||||||
class="hidden h-7 bg-tinted-700 text-neutral-200 sm:block">
|
class="hidden bg-tinted-700 sm:block">
|
||||||
<option value={Scope.Follows}>Follows</option>
|
<option value={Scope.Follows}>Follows</option>
|
||||||
<option value={Scope.Network}>Network</option>
|
<option value={Scope.Network}>Network</option>
|
||||||
<option value={null}>Global</option>
|
<option value={null}>Global</option>
|
||||||
@ -112,27 +114,28 @@
|
|||||||
<div class="flex flex-grow items-center justify-end gap-2">
|
<div class="flex flex-grow items-center justify-end gap-2">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<Input
|
<Input
|
||||||
class="hidden h-7 rounded-r-none bg-neutral-900 xs:block"
|
dark
|
||||||
|
class="hidden rounded-r-none xs:block"
|
||||||
on:input={onSearchBlur}
|
on:input={onSearchBlur}
|
||||||
bind:value={search}>
|
bind:value={search}>
|
||||||
<div slot="after" class="hidden text-white xs:block">
|
<div slot="after" class="hidden text-white xs:block">
|
||||||
<i class="fa fa-search" />
|
<i class="fa fa-search" />
|
||||||
</div>
|
</div>
|
||||||
</Input>
|
</Input>
|
||||||
<Anchor button low class="h-7 border-none xs:rounded-l-none" on:click={openForm}>
|
<Anchor button low class="border-none xs:rounded-l-none" on:click={openForm}>
|
||||||
Filters ({feed.definition.length - 1})
|
Filters ({feed.definition.length - 1})
|
||||||
</Anchor>
|
</Anchor>
|
||||||
</div>
|
</div>
|
||||||
<div class="float-right flex h-8 items-center justify-end gap-2">
|
<div class="float-right flex h-8 items-center justify-end gap-2">
|
||||||
{#if opts.shouldHideReplies}
|
{#if opts.shouldHideReplies}
|
||||||
<Anchor button low class="h-7 border-none opacity-50" on:click={toggleReplies}
|
<Anchor button low class="border-none opacity-50" on:click={toggleReplies}
|
||||||
>Replies</Anchor>
|
>Replies</Anchor>
|
||||||
{:else}
|
{:else}
|
||||||
<Anchor button accent class="h-7 border-none" on:click={toggleReplies}>Replies</Anchor>
|
<Anchor button accent class="border-none" on:click={toggleReplies}>Replies</Anchor>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="relative lg:hidden">
|
<div class="relative lg:hidden">
|
||||||
<div
|
<div
|
||||||
class="flex h-7 w-6 cursor-pointer items-center justify-center rounded bg-neutral-700 text-center text-neutral-50 transition-colors hover:bg-neutral-600"
|
class="flex h-8 w-6 cursor-pointer items-center justify-center rounded bg-neutral-700 text-center text-neutral-50 transition-colors hover:bg-neutral-600"
|
||||||
on:click={openListMenu}>
|
on:click={openListMenu}>
|
||||||
<i class="fa fa-sm fa-ellipsis-v" />
|
<i class="fa fa-sm fa-ellipsis-v" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<QRCode code={zap.invoice} onClick={collect}>
|
<QRCode code={zap.invoice} onClick={collect}>
|
||||||
<div slot="below" let:copy class="flex gap-1">
|
<div slot="below" let:copy class="flex gap-1">
|
||||||
<Input value={zap.invoice} wrapperClass="flex-grow">
|
<Input value={zap.invoice} class="flex-grow">
|
||||||
<button slot="after" class="fa fa-copy" on:click={copy} />
|
<button slot="after" class="fa fa-copy" on:click={copy} />
|
||||||
</Input>
|
</Input>
|
||||||
{#await getLightningImplementation()}
|
{#await getLightningImplementation()}
|
||||||
|
@ -48,6 +48,7 @@ export class FeedLoader {
|
|||||||
done = false
|
done = false
|
||||||
loader: Promise<Loader>
|
loader: Promise<Loader>
|
||||||
feedLoader: CoreFeedLoader<Rumor>
|
feedLoader: CoreFeedLoader<Rumor>
|
||||||
|
controller = new AbortController()
|
||||||
notes = writable<DisplayEvent[]>([])
|
notes = writable<DisplayEvent[]>([])
|
||||||
parents = new Map<string, DisplayEvent>()
|
parents = new Map<string, DisplayEvent>()
|
||||||
reposts = new Map<string, Event[]>()
|
reposts = new Map<string, Event[]>()
|
||||||
@ -60,6 +61,8 @@ export class FeedLoader {
|
|||||||
this.feedLoader = new CoreFeedLoader({
|
this.feedLoader = new CoreFeedLoader({
|
||||||
...baseFeedLoader.options,
|
...baseFeedLoader.options,
|
||||||
request: async ({relays, filters, onEvent}) => {
|
request: async ({relays, filters, onEvent}) => {
|
||||||
|
const signal = this.controller.signal
|
||||||
|
|
||||||
// Default to note kinds
|
// Default to note kinds
|
||||||
filters = filters?.map(filter => ({kinds: noteKinds, ...filter})) || []
|
filters = filters?.map(filter => ({kinds: noteKinds, ...filter})) || []
|
||||||
|
|
||||||
@ -73,10 +76,10 @@ export class FeedLoader {
|
|||||||
|
|
||||||
// Use relays specified in feeds
|
// Use relays specified in feeds
|
||||||
if (relays?.length > 0) {
|
if (relays?.length > 0) {
|
||||||
promises.push(load({filters, relays, tracker, onEvent}))
|
promises.push(load({filters, relays, tracker, onEvent, signal}))
|
||||||
} else {
|
} else {
|
||||||
if (!this.opts.skipCache) {
|
if (!this.opts.skipCache) {
|
||||||
promises.push(load({filters, relays: [LOCAL_RELAY_URL], tracker, onEvent}))
|
promises.push(load({filters, relays: [LOCAL_RELAY_URL], tracker, onEvent, signal}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.opts.skipNetwork) {
|
if (!this.opts.skipNetwork) {
|
||||||
@ -87,7 +90,7 @@ export class FeedLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const {relay, filters} of selections) {
|
for (const {relay, filters} of selections) {
|
||||||
promises.push(load({filters, relays: [relay], tracker, onEvent}))
|
promises.push(load({filters, relays: [relay], tracker, onEvent, signal}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,11 +103,17 @@ export class FeedLoader {
|
|||||||
// Public api
|
// Public api
|
||||||
|
|
||||||
start = (opts: Partial<FeedOpts>) => {
|
start = (opts: Partial<FeedOpts>) => {
|
||||||
|
const controller = new AbortController()
|
||||||
|
|
||||||
Object.assign(this.opts, opts)
|
Object.assign(this.opts, opts)
|
||||||
|
|
||||||
this.loader = this.feedLoader.getLoader(this.opts.feed, {
|
this.loader = this.feedLoader.getLoader(this.opts.feed, {
|
||||||
onEvent: batch(300, async events => {
|
onEvent: batch(300, async events => {
|
||||||
const keep = await this.discardEvents(events)
|
if (controller.signal.aborted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const keep = this.discardEvents(events)
|
||||||
|
|
||||||
if (this.opts.shouldLoadParents) {
|
if (this.opts.shouldLoadParents) {
|
||||||
this.loadParents(keep)
|
this.loadParents(keep)
|
||||||
@ -121,6 +130,8 @@ export class FeedLoader {
|
|||||||
|
|
||||||
// Clear everything out
|
// Clear everything out
|
||||||
this.notes.set([])
|
this.notes.set([])
|
||||||
|
this.controller.abort()
|
||||||
|
this.controller = controller
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe = f => this.notes.subscribe(f)
|
subscribe = f => this.notes.subscribe(f)
|
||||||
@ -129,7 +140,7 @@ export class FeedLoader {
|
|||||||
|
|
||||||
// Event selection, deferral, and parent loading
|
// Event selection, deferral, and parent loading
|
||||||
|
|
||||||
discardEvents = async events => {
|
discardEvents = events => {
|
||||||
let strict = true
|
let strict = true
|
||||||
|
|
||||||
// Be more tolerant when looking at communities
|
// Be more tolerant when looking at communities
|
||||||
@ -186,14 +197,20 @@ export class FeedLoader {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {signal} = this.controller
|
||||||
const selections = hints.merge(notesWithParent.map(hints.EventParents)).getSelections()
|
const selections = hints.merge(notesWithParent.map(hints.EventParents)).getSelections()
|
||||||
|
|
||||||
for (const {relay, values} of selections) {
|
for (const {relay, values} of selections) {
|
||||||
load({
|
load({
|
||||||
filters: getIdFilters(values),
|
filters: getIdFilters(values),
|
||||||
|
signal: this.controller.signal,
|
||||||
relays: this.opts.skipPlatform ? [relay] : forcePlatformRelays([relay]),
|
relays: this.opts.skipPlatform ? [relay] : forcePlatformRelays([relay]),
|
||||||
onEvent: batch(100, async events => {
|
onEvent: batch(100, async events => {
|
||||||
for (const e of await this.discardEvents(events)) {
|
if (signal.aborted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const e of this.discardEvents(events)) {
|
||||||
for (const k of getIdAndAddress(e)) {
|
for (const k of getIdAndAddress(e)) {
|
||||||
this.parents.set(k, e)
|
this.parents.set(k, e)
|
||||||
}
|
}
|
||||||
@ -215,7 +232,13 @@ export class FeedLoader {
|
|||||||
return parents.length === 0 || parents.some(k => this.parents.has(k))
|
return parents.length === 0 || parents.some(k => this.parents.has(k))
|
||||||
}, notes)
|
}, notes)
|
||||||
|
|
||||||
setTimeout(() => this.addToFeed(defer), 3000)
|
const {signal} = this.controller
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!signal.aborted) {
|
||||||
|
this.addToFeed(defer)
|
||||||
|
}
|
||||||
|
}, 3000)
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
<p class="text-center py-8">You haven't yet joined any groups.</p>
|
<p class="text-center py-8">You haven't yet joined any groups.</p>
|
||||||
{/each}
|
{/each}
|
||||||
<div class="mb-2 border-b border-solid border-neutral-600 pt-2" />
|
<div class="mb-2 border-b border-solid border-neutral-600 pt-2" />
|
||||||
<Input bind:value={q} type="text" wrapperClass="flex-grow" placeholder="Search groups">
|
<Input bind:value={q} type="text" class="flex-grow" placeholder="Search groups">
|
||||||
<i slot="before" class="fa-solid fa-search" />
|
<i slot="before" class="fa-solid fa-search" />
|
||||||
</Input>
|
</Input>
|
||||||
{#each otherGroups as group (group.address)}
|
{#each otherGroups as group (group.address)}
|
||||||
|
@ -136,8 +136,7 @@
|
|||||||
<div class="flex">
|
<div class="flex">
|
||||||
<Input
|
<Input
|
||||||
bind:value={username}
|
bind:value={username}
|
||||||
class="rounded-r-none"
|
class="flex-grow rounded-r-none"
|
||||||
wrapperClass="flex-grow"
|
|
||||||
placeholder="Username">
|
placeholder="Username">
|
||||||
<i slot="before" class="fa fa-user-astronaut" />
|
<i slot="before" class="fa fa-user-astronaut" />
|
||||||
</Input>
|
</Input>
|
||||||
@ -146,8 +145,7 @@
|
|||||||
defaultOptions={handlers}
|
defaultOptions={handlers}
|
||||||
getKey={prop("domain")}
|
getKey={prop("domain")}
|
||||||
termToItem={objOf("domain")}
|
termToItem={objOf("domain")}
|
||||||
inputClass="rounded-l-none border-l-0"
|
inputClass="rounded-l-none border-l-0 flex-grow"
|
||||||
inputWrapperClass="flex-grow"
|
|
||||||
search={() => handlers}>
|
search={() => handlers}>
|
||||||
<i slot="before" class="fa fa-at relative top-[2px]" />
|
<i slot="before" class="fa fa-at relative top-[2px]" />
|
||||||
<span slot="item" let:item>{item.domain}</span>
|
<span slot="item" let:item>{item.domain}</span>
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p>Help people recognize you by setting up your profile.</p>
|
<p>Help people recognize you by setting up your profile.</p>
|
||||||
<Field label="Your Name">
|
<Field label="Your Name">
|
||||||
<Input type="text" name="name" wrapperClass="flex-grow" bind:value={profile.name}>
|
<Input type="text" name="name" class="flex-grow" bind:value={profile.name}>
|
||||||
<i slot="before" class="fa-solid fa-user-astronaut" />
|
<i slot="before" class="fa-solid fa-user-astronaut" />
|
||||||
</Input>
|
</Input>
|
||||||
</Field>
|
</Field>
|
||||||
|
@ -202,7 +202,7 @@
|
|||||||
<Input
|
<Input
|
||||||
bind:value={q}
|
bind:value={q}
|
||||||
type="text"
|
type="text"
|
||||||
wrapperClass="flex-grow"
|
class="flex-grow"
|
||||||
placeholder="Search relays or add a custom url">
|
placeholder="Search relays or add a custom url">
|
||||||
<i slot="before" class="fa-solid fa-search" />
|
<i slot="before" class="fa-solid fa-search" />
|
||||||
</Input>
|
</Input>
|
||||||
|
@ -35,13 +35,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex w-full flex-col gap-8">
|
<div class="flex w-full flex-col gap-8">
|
||||||
<Field label="Username">
|
<Field label="Username">
|
||||||
<Input type="text" name="name" wrapperClass="flex-grow" bind:value={values.name}>
|
<Input type="text" name="name" class="flex-grow" bind:value={values.name}>
|
||||||
<i slot="before" class="fa-solid fa-user-astronaut" />
|
<i slot="before" class="fa-solid fa-user-astronaut" />
|
||||||
</Input>
|
</Input>
|
||||||
<div slot="info">In most clients, this image will be shown on your profile page.</div>
|
<div slot="info">In most clients, this image will be shown on your profile page.</div>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="NIP-05 Identifier">
|
<Field label="NIP-05 Identifier">
|
||||||
<Input type="text" name="name" wrapperClass="flex-grow" bind:value={values.nip05}>
|
<Input type="text" name="name" class="flex-grow" bind:value={values.nip05}>
|
||||||
<i slot="before" class="fa-solid fa-user-check" />
|
<i slot="before" class="fa-solid fa-user-check" />
|
||||||
</Input>
|
</Input>
|
||||||
<div slot="info">
|
<div slot="info">
|
||||||
@ -50,7 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="Lightning address">
|
<Field label="Lightning address">
|
||||||
<Input type="text" name="name" wrapperClass="flex-grow" bind:value={values.lud16}>
|
<Input type="text" name="name" class="flex-grow" bind:value={values.lud16}>
|
||||||
<i slot="before" class="fa-solid fa-bolt" />
|
<i slot="before" class="fa-solid fa-bolt" />
|
||||||
</Input>
|
</Input>
|
||||||
<div slot="info">
|
<div slot="info">
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="Website">
|
<Field label="Website">
|
||||||
<Input type="text" name="name" wrapperClass="flex-grow" bind:value={values.website}>
|
<Input type="text" name="name" class="flex-grow" bind:value={values.website}>
|
||||||
<i slot="before" class="fa-solid fa-link" />
|
<i slot="before" class="fa-solid fa-link" />
|
||||||
</Input>
|
</Input>
|
||||||
<div slot="info">Enter any url where people can find out more about you.</div>
|
<div slot="info">Enter any url where people can find out more about you.</div>
|
||||||
|
@ -38,7 +38,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex w-full flex-col gap-8">
|
<div class="flex w-full flex-col gap-8">
|
||||||
<Field label="Default zap amount">
|
<Field label="Default zap amount">
|
||||||
<Input bind:value={settings.default_zap} />
|
<Input bind:value={settings.default_zap}>
|
||||||
|
<i slot="before" class="fa fa-bolt" />
|
||||||
|
</Input>
|
||||||
<p slot="info">The default amount of sats to use when sending a lightning tip.</p>
|
<p slot="info">The default amount of sats to use when sending a lightning tip.</p>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="Platform zap split">
|
<Field label="Platform zap split">
|
||||||
@ -58,7 +60,7 @@
|
|||||||
<strong>Max relays per request</strong>
|
<strong>Max relays per request</strong>
|
||||||
<div>{settings.relay_limit} relays</div>
|
<div>{settings.relay_limit} relays</div>
|
||||||
</div>
|
</div>
|
||||||
<Input type="range" bind:value={settings.relay_limit} min={1} max={30} parse={parseInt} />
|
<Input type="range" class="bg-transparent" bind:value={settings.relay_limit} min={1} max={30} parse={parseInt} />
|
||||||
<p slot="info">
|
<p slot="info">
|
||||||
This controls how many relays to max out at when loading feeds and event context. More is
|
This controls how many relays to max out at when loading feeds and event context. More is
|
||||||
faster, but will require more bandwidth and processing power.
|
faster, but will require more bandwidth and processing power.
|
||||||
|
@ -33,11 +33,7 @@ export const projections = new Worker<Event>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
projections.addGlobalHandler(event => {
|
projections.addGlobalHandler(event => {
|
||||||
const kinds = [
|
const kinds = [Kind.Delete, Kind.Feed, Kind.ListBookmarks]
|
||||||
Kind.Delete,
|
|
||||||
Kind.Feed,
|
|
||||||
Kind.ListBookmarks,
|
|
||||||
]
|
|
||||||
|
|
||||||
if (kinds.includes(event.kind)) {
|
if (kinds.includes(event.kind)) {
|
||||||
repository.publish(event)
|
repository.publish(event)
|
||||||
@ -221,7 +217,7 @@ export const createAndPublish = async ({
|
|||||||
const template = createEvent(kind, {content, tags})
|
const template = createEvent(kind, {content, tags})
|
||||||
const event = await sign(template, {anonymous, sk})
|
const event = await sign(template, {anonymous, sk})
|
||||||
|
|
||||||
return publish({event, relays, timeout, verb})
|
return publish({event, relays, verb, signal: AbortSignal.timeout(timeout)})
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
export let danger = false
|
export let danger = false
|
||||||
export let circle = false
|
export let circle = false
|
||||||
export let underline = false
|
export let underline = false
|
||||||
export let short = false
|
|
||||||
export let tall = false
|
export let tall = false
|
||||||
export let grow = false
|
export let grow = false
|
||||||
export let style = null
|
export let style = null
|
||||||
@ -44,10 +43,10 @@
|
|||||||
button,
|
button,
|
||||||
"aspect-square flex justify-center items-center rounded-full !p-0": circle,
|
"aspect-square flex justify-center items-center rounded-full !p-0": circle,
|
||||||
"aspect-square flex justify-center items-center": square,
|
"aspect-square flex justify-center items-center": square,
|
||||||
"h-7": short,
|
"h-7": button && !tall,
|
||||||
"w-7": short && circle,
|
"w-7": button && !tall && circle,
|
||||||
"h-10": tall,
|
"h-10": button && tall,
|
||||||
"w-10": tall && circle,
|
"w-10": button && tall && circle,
|
||||||
"flex-grow": grow,
|
"flex-grow": grow,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<Input type="text" wrapperClass="flex-grow" bind:value placeholder="https://">
|
<Input type="text" class="flex-grow" bind:value placeholder="https://">
|
||||||
<i slot="before" class={`fa fa-${icon}`} />
|
<i slot="before" class={`fa fa-${icon}`} />
|
||||||
</Input>
|
</Input>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -3,19 +3,18 @@
|
|||||||
import {identity} from "ramda"
|
import {identity} from "ramda"
|
||||||
|
|
||||||
export let initialValue: string | number = ""
|
export let initialValue: string | number = ""
|
||||||
export let wrapperClass = ""
|
|
||||||
export let value = initialValue
|
export let value = initialValue
|
||||||
export let element = null
|
export let element = null
|
||||||
export let hideBefore = false
|
export let hideBefore = false
|
||||||
export let hideAfter = false
|
export let hideAfter = false
|
||||||
export let format: (x: any) => string = identity
|
export let format: (x: any) => string = identity
|
||||||
export let parse: (x: string) => any = identity
|
export let parse: (x: string) => any = identity
|
||||||
|
export let dark = false
|
||||||
|
|
||||||
const showBefore = $$slots.before && !hideBefore
|
const showBefore = $$slots.before && !hideBefore
|
||||||
const showAfter = $$slots.after && !hideAfter
|
const showAfter = $$slots.after && !hideAfter
|
||||||
const className = cx(
|
const className = cx(
|
||||||
$$props.class,
|
"outline-none px-3 w-full placeholder:text-neutral-400 h-7 bg-transparent",
|
||||||
"outline-none rounded shadow-inset py-2 px-4 w-full placeholder:text-neutral-400 text-black",
|
|
||||||
{"pl-10": showBefore, "pr-10": showAfter},
|
{"pl-10": showBefore, "pr-10": showAfter},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +25,11 @@
|
|||||||
$: inputValue = format(value)
|
$: inputValue = format(value)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={cx(wrapperClass, "relative")}>
|
<div
|
||||||
|
class={cx($$props.class, "shadow-inset relative rounded h-7 overflow-hidden", {
|
||||||
|
"bg-neutral-900 text-neutral-100": dark,
|
||||||
|
"bg-white dark:text-neutral-900": !dark,
|
||||||
|
})}>
|
||||||
<input
|
<input
|
||||||
{...$$props}
|
{...$$props}
|
||||||
class={className}
|
class={className}
|
||||||
@ -39,15 +42,14 @@
|
|||||||
on:input
|
on:input
|
||||||
on:keydown />
|
on:keydown />
|
||||||
{#if showBefore}
|
{#if showBefore}
|
||||||
<div class="absolute left-0 top-2 flex items-center gap-2 px-4 text-black opacity-75">
|
<div class="absolute left-0 top-0 flex items-center gap-2 px-3 opacity-75 h-7">
|
||||||
<div>
|
<div>
|
||||||
<slot name="before" />
|
<slot name="before" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if showAfter}
|
{#if showAfter}
|
||||||
<div
|
<div class="absolute right-0 top-0 m-px flex items-center gap-2 rounded-full px-3 opacity-75 h-7">
|
||||||
class="absolute right-0 top-2 m-px flex items-center gap-2 rounded-full px-4 text-black opacity-75">
|
|
||||||
<div>
|
<div>
|
||||||
<slot name="after" />
|
<slot name="after" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
export let value = null
|
export let value = null
|
||||||
export let onChange = null
|
export let onChange = null
|
||||||
export let inputClass = ""
|
export let inputClass = ""
|
||||||
export let inputWrapperClass = ""
|
|
||||||
export let placeholder = ""
|
export let placeholder = ""
|
||||||
export let delimiters = []
|
export let delimiters = []
|
||||||
export let search = null
|
export let search = null
|
||||||
@ -134,7 +133,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<Input
|
<Input
|
||||||
class={cx(inputClass, "cursor-text text-black outline-0")}
|
class={cx(inputClass, "cursor-text text-black outline-0")}
|
||||||
wrapperClass={inputWrapperClass}
|
|
||||||
{autofocus}
|
{autofocus}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
bind:value={term}
|
bind:value={term}
|
||||||
|
@ -3,15 +3,18 @@
|
|||||||
|
|
||||||
export let value
|
export let value
|
||||||
export let onChange = null
|
export let onChange = null
|
||||||
export let wrapperClass = ""
|
export let dark = false
|
||||||
|
|
||||||
const className = cx($$props.class, "rounded shadow-inset px-4 w-full cursor-pointer", {
|
const className = cx("px-3 w-full bg-transparent h-7", {
|
||||||
"pl-10": $$slots.before,
|
"pl-10": $$slots.before,
|
||||||
"pr-10": $$slots.after,
|
"pr-10": $$slots.after,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={cx(wrapperClass, "relative")}>
|
<div class={cx($$props.class, "rounded relative shadow-inset cursor-pointer h-7", {
|
||||||
|
"bg-neutral-900 text-neutral-100": dark,
|
||||||
|
"bg-neutral-100 text-neutral-900": !dark,
|
||||||
|
})}>
|
||||||
<select {...$$props} class={className} bind:value on:change={() => onChange(value)}>
|
<select {...$$props} class={className} bind:value on:change={() => onChange(value)}>
|
||||||
<slot />
|
<slot />
|
||||||
</select>
|
</select>
|
||||||
|
Loading…
Reference in New Issue
Block a user