Closes #17 Co-authored-by: Jon Staab <shtaab@gmail.com> Reviewed-on: #78 Co-authored-by: triesap <tyson@radroots.org> Co-committed-by: triesap <tyson@radroots.org>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {insertAt, removeAt} from "@welshman/lib"
|
||||
import SettingsMinimalistic from "@assets/icons/settings-minimalistic.svg?dataurl"
|
||||
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -9,9 +10,88 @@
|
||||
import MenuSpacesItem from "@app/components/MenuSpacesItem.svelte"
|
||||
import SpaceAdd from "@app/components/SpaceAdd.svelte"
|
||||
import {userSpaceUrls, loadUserGroupList, PLATFORM_RELAYS} from "@app/core/state"
|
||||
import {setSpaceMembershipOrder} from "@app/core/commands"
|
||||
import {pushModal} from "@app/util/modal"
|
||||
|
||||
const addSpace = () => pushModal(SpaceAdd)
|
||||
|
||||
const reconcileUrls = (currentUrls: string[], nextUrls: string[]) => {
|
||||
const mergedUrls = currentUrls.filter(url => nextUrls.includes(url))
|
||||
|
||||
for (const url of nextUrls) {
|
||||
if (!mergedUrls.includes(url)) {
|
||||
mergedUrls.push(url)
|
||||
}
|
||||
}
|
||||
|
||||
return mergedUrls
|
||||
}
|
||||
|
||||
const isSameOrder = (a: string[], b: string[]) =>
|
||||
a.length === b.length && a.every((url, index) => url === b[index])
|
||||
|
||||
const reorderSpaceUrls = (targetUrl: string) => {
|
||||
if (!draggedUrl) {
|
||||
return
|
||||
}
|
||||
|
||||
const sourceIndex = orderedSpaceUrls.indexOf(draggedUrl)
|
||||
const targetIndex = orderedSpaceUrls.indexOf(targetUrl)
|
||||
|
||||
if (sourceIndex === -1 || targetIndex === -1 || sourceIndex === targetIndex) {
|
||||
return
|
||||
}
|
||||
|
||||
orderedSpaceUrls = insertAt(
|
||||
targetIndex,
|
||||
orderedSpaceUrls[sourceIndex],
|
||||
removeAt(sourceIndex, orderedSpaceUrls),
|
||||
)
|
||||
}
|
||||
|
||||
const onDragStart = (e: DragEvent, url: string) => {
|
||||
draggedUrl = url
|
||||
dragStartOrder = [...orderedSpaceUrls]
|
||||
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.effectAllowed = "move"
|
||||
e.dataTransfer.setData("text/plain", url)
|
||||
}
|
||||
}
|
||||
|
||||
const onDragOver = (e: DragEvent, targetUrl: string) => {
|
||||
e.preventDefault()
|
||||
reorderSpaceUrls(targetUrl)
|
||||
}
|
||||
|
||||
const onDrop = (e: DragEvent, targetUrl: string) => {
|
||||
e.preventDefault()
|
||||
reorderSpaceUrls(targetUrl)
|
||||
draggedUrl = undefined
|
||||
|
||||
if (dragStartOrder && !isSameOrder(dragStartOrder, orderedSpaceUrls)) {
|
||||
void setSpaceMembershipOrder(orderedSpaceUrls).catch(console.error)
|
||||
}
|
||||
|
||||
dragStartOrder = undefined
|
||||
}
|
||||
|
||||
const onDragEnd = () => {
|
||||
draggedUrl = undefined
|
||||
dragStartOrder = undefined
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
const nextUrls = reconcileUrls(orderedSpaceUrls, $userSpaceUrls)
|
||||
|
||||
if (!isSameOrder(nextUrls, orderedSpaceUrls)) {
|
||||
orderedSpaceUrls = nextUrls
|
||||
}
|
||||
})
|
||||
|
||||
let orderedSpaceUrls = $state<string[]>([])
|
||||
let draggedUrl = $state<string | undefined>()
|
||||
let dragStartOrder = $state<string[] | undefined>()
|
||||
</script>
|
||||
|
||||
<Page class="cw-full">
|
||||
@@ -43,8 +123,17 @@
|
||||
Loading your spaces...
|
||||
</div>
|
||||
{:then}
|
||||
{#each $userSpaceUrls as url (url)}
|
||||
<MenuSpacesItem {url} />
|
||||
{#each orderedSpaceUrls as url (url)}
|
||||
<div
|
||||
class:opacity-60={draggedUrl === url}
|
||||
draggable="true"
|
||||
role="listitem"
|
||||
ondragstart={e => onDragStart(e, url)}
|
||||
ondragover={e => onDragOver(e, url)}
|
||||
ondrop={e => onDrop(e, url)}
|
||||
ondragend={onDragEnd}>
|
||||
<MenuSpacesItem {url} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col gap-8 items-center py-20">
|
||||
<p>You haven't added any spaces yet!</p>
|
||||
|
||||
Reference in New Issue
Block a user