mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 00:10:52 +00:00
Introduce state controllers, avoid double submit on group create. Fixes #326
This commit is contained in:
parent
c0e870907d
commit
b6027a608f
@ -29,6 +29,7 @@
|
|||||||
- [x] Only tag parent event in reactions
|
- [x] Only tag parent event in reactions
|
||||||
- [x] Fix url hashes, render code blocks
|
- [x] Fix url hashes, render code blocks
|
||||||
- [x] Use bitcoin connect instead of webln
|
- [x] Use bitcoin connect instead of webln
|
||||||
|
- [x] Fix double submit on group create dialog
|
||||||
|
|
||||||
# 0.4.4
|
# 0.4.4
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {debounce} from "throttle-debounce"
|
import {debounce} from "throttle-debounce"
|
||||||
import {isSearchFeed, makeSearchFeed, makeScopeFeed, Scope, getFeedArgs} from "@welshman/feeds"
|
import {isSearchFeed, makeSearchFeed, makeScopeFeed, Scope, getFeedArgs} from "@welshman/feeds"
|
||||||
|
import {boolCtrl} from 'src/partials/utils'
|
||||||
import Modal from "src/partials/Modal.svelte"
|
import Modal from "src/partials/Modal.svelte"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
import Popover2 from "src/partials/Popover2.svelte"
|
import Popover2 from "src/partials/Popover2.svelte"
|
||||||
@ -17,25 +18,19 @@
|
|||||||
|
|
||||||
feed.definition = normalizeFeedDefinition(feed.definition)
|
feed.definition = normalizeFeedDefinition(feed.definition)
|
||||||
|
|
||||||
|
const form = boolCtrl()
|
||||||
|
const listMenu = boolCtrl()
|
||||||
const followsFeed = makeFeed({definition: normalizeFeedDefinition(makeScopeFeed(Scope.Follows))})
|
const followsFeed = makeFeed({definition: normalizeFeedDefinition(makeScopeFeed(Scope.Follows))})
|
||||||
const networkFeed = makeFeed({definition: normalizeFeedDefinition(makeScopeFeed(Scope.Network))})
|
const networkFeed = makeFeed({definition: normalizeFeedDefinition(makeScopeFeed(Scope.Network))})
|
||||||
|
|
||||||
const openListMenu = () => {
|
|
||||||
listMenuIsOpen = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const closeListMenu = () => {
|
|
||||||
listMenuIsOpen = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const openForm = () => {
|
const openForm = () => {
|
||||||
savePoint = {...feed}
|
savePoint = {...feed}
|
||||||
formIsOpen = true
|
$form.enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeForm = () => {
|
const closeForm = () => {
|
||||||
feed = savePoint
|
feed = savePoint
|
||||||
formIsOpen = false
|
$form.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSearch = definition => (getFeedArgs(definition)?.find(isSearchFeed)?.[1] as string) || ""
|
const getSearch = definition => (getFeedArgs(definition)?.find(isSearchFeed)?.[1] as string) || ""
|
||||||
@ -43,8 +38,8 @@
|
|||||||
const setFeedDefinition = definition => {
|
const setFeedDefinition = definition => {
|
||||||
feed.definition = definition
|
feed.definition = definition
|
||||||
search = getSearch(definition)
|
search = getSearch(definition)
|
||||||
formIsOpen = false
|
$form.disable()
|
||||||
closeListMenu()
|
$listMenu.disable()
|
||||||
updateFeed(feed)
|
updateFeed(feed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +83,6 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
let savePoint
|
let savePoint
|
||||||
let formIsOpen = false
|
|
||||||
let listMenuIsOpen = false
|
|
||||||
let search = getSearch(feed.definition)
|
let search = getSearch(feed.definition)
|
||||||
|
|
||||||
$: subFeeds = getFeedArgs(feed.definition as any)
|
$: subFeeds = getFeedArgs(feed.definition as any)
|
||||||
@ -111,11 +104,11 @@
|
|||||||
<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-7 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={$listMenu.enable}>
|
||||||
<i class="fa fa-sm fa-ellipsis-v" />
|
<i class="fa fa-sm fa-ellipsis-v" />
|
||||||
</div>
|
</div>
|
||||||
{#if listMenuIsOpen}
|
{#if $listMenu.enabled}
|
||||||
<Popover2 absolute hideOnClick onClose={closeListMenu} class="right-0 top-8 w-60">
|
<Popover2 absolute hideOnClick onClose={$listMenu.disable} class="right-0 top-8 w-60">
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuItem inert class="staatliches bg-neutral-800 text-lg shadow">Your Feeds</MenuItem>
|
<MenuItem inert class="staatliches bg-neutral-800 text-lg shadow">Your Feeds</MenuItem>
|
||||||
<div class="max-h-96 overflow-auto">
|
<div class="max-h-96 overflow-auto">
|
||||||
@ -146,7 +139,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if formIsOpen}
|
{#if $form.enabled}
|
||||||
<Modal onEscape={closeForm}>
|
<Modal onEscape={closeForm}>
|
||||||
<FeedForm {feed} exit={exitForm} apply={() => setFeedDefinition(feed.definition)} />
|
<FeedForm {feed} exit={exitForm} apply={() => setFeedDefinition(feed.definition)} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
import {ucFirst} from "hurdak"
|
import {ucFirst} from "hurdak"
|
||||||
import {Address} from "@welshman/util"
|
import {Address} from "@welshman/util"
|
||||||
import {fly} from "src/util/transition"
|
import {fly} from "src/util/transition"
|
||||||
|
import {formCtrl} from "src/partials/utils"
|
||||||
import {showInfo, showWarning} from "src/partials/Toast.svelte"
|
import {showInfo, showWarning} from "src/partials/Toast.svelte"
|
||||||
import Field from "src/partials/Field.svelte"
|
import Field from "src/partials/Field.svelte"
|
||||||
import FieldInline from "src/partials/FieldInline.svelte"
|
import FieldInline from "src/partials/FieldInline.svelte"
|
||||||
@ -62,23 +63,23 @@
|
|||||||
values.feeds = values.feeds.toSpliced(i, 1)
|
values.feeds = values.feeds.toSpliced(i, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const submit = async () => {
|
const ctrl = formCtrl({
|
||||||
if (values.relays.length < 1) {
|
submit: async () => {
|
||||||
showWarning("At least one relay is required.")
|
if (values.relays.length < 1) {
|
||||||
|
showWarning("At least one relay is required.")
|
||||||
|
} else {
|
||||||
|
await onSubmit(values)
|
||||||
|
|
||||||
return
|
showInfo("Your group has been saved!")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
await onSubmit(values)
|
})
|
||||||
|
|
||||||
showInfo("Your group has been saved!")
|
|
||||||
}
|
|
||||||
|
|
||||||
let feedsInput
|
let feedsInput
|
||||||
let showAdvanced = false
|
let showAdvanced = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form on:submit|preventDefault={submit} in:fly={{y: 20}}>
|
<form on:submit|preventDefault={$ctrl.submit} in:fly={{y: 20}}>
|
||||||
<FlexColumn>
|
<FlexColumn>
|
||||||
<div class="mb-4 flex flex-col items-center justify-center">
|
<div class="mb-4 flex flex-col items-center justify-center">
|
||||||
<Heading>{ucFirst(mode)} Group</Heading>
|
<Heading>{ucFirst(mode)} Group</Heading>
|
||||||
@ -180,7 +181,7 @@
|
|||||||
<span>Show Advanced Settings</span>
|
<span>Show Advanced Settings</span>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
{/if}
|
{/if}
|
||||||
<Anchor button tag="button" type="submit">{buttonText}</Anchor>
|
<Anchor button loading={$ctrl.loading} tag="button" type="submit">{buttonText}</Anchor>
|
||||||
</div>
|
</div>
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
</form>
|
</form>
|
||||||
|
44
src/partials/utils.ts
Normal file
44
src/partials/utils.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import {writable, assoc} from '@welshman/lib'
|
||||||
|
|
||||||
|
export const formCtrl = ({submit}) => {
|
||||||
|
const store = writable({
|
||||||
|
loading: false,
|
||||||
|
submit: async () => {
|
||||||
|
if (store.get().loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
store.update(assoc("loading", true))
|
||||||
|
|
||||||
|
try {
|
||||||
|
await submit()
|
||||||
|
} catch (e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
|
||||||
|
store.update(assoc("loading", false))
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
export const boolCtrl = ({defaultValue = false} = {}) => {
|
||||||
|
const store = writable({
|
||||||
|
enabled: defaultValue,
|
||||||
|
disable: () => store.update(assoc('enabled', false)),
|
||||||
|
enable: () => store.update(assoc('enabled', true)),
|
||||||
|
})
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
export const valueCtrl = ({defaultValue = null} = {}) => {
|
||||||
|
const store = writable({
|
||||||
|
enabled: defaultValue,
|
||||||
|
clear: () => store.update(assoc('enabled', null)),
|
||||||
|
set: value => store.update(assoc('enabled', value)),
|
||||||
|
})
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user