Persist space icon order
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {insertAt, removeAt} from "@welshman/lib"
|
||||
import MenuSpacesItem from "@app/components/MenuSpacesItem.svelte"
|
||||
import {setSpaceMembershipOrder} from "@app/core/commands"
|
||||
|
||||
type Props = {
|
||||
urls: string[]
|
||||
@@ -7,35 +9,31 @@
|
||||
|
||||
const {urls}: Props = $props()
|
||||
|
||||
const reorderUrls = (sourceUrl: string, targetUrl: string, currentUrls: string[]) => {
|
||||
if (sourceUrl === targetUrl) {
|
||||
return currentUrls
|
||||
}
|
||||
const isSameOrder = (a: string[], b: string[]) =>
|
||||
a.length === b.length && a.every((url, index) => url === b[index])
|
||||
|
||||
const sourceIndex = currentUrls.indexOf(sourceUrl)
|
||||
const targetIndex = currentUrls.indexOf(targetUrl)
|
||||
|
||||
if (sourceIndex === -1 || targetIndex === -1) {
|
||||
return currentUrls
|
||||
}
|
||||
|
||||
const nextUrls = currentUrls.filter(url => url !== sourceUrl)
|
||||
|
||||
nextUrls.splice(targetIndex, 0, sourceUrl)
|
||||
|
||||
return nextUrls
|
||||
}
|
||||
|
||||
const moveDraggedUrl = (targetUrl: string) => {
|
||||
const reorderSpaceUrls = (targetUrl: string) => {
|
||||
if (!draggedUrl) {
|
||||
return
|
||||
}
|
||||
|
||||
orderedUrls = reorderUrls(draggedUrl, targetUrl, orderedUrls)
|
||||
const sourceIndex = orderedUrls.indexOf(draggedUrl)
|
||||
const targetIndex = orderedUrls.indexOf(targetUrl)
|
||||
|
||||
if (sourceIndex === -1 || targetIndex === -1 || sourceIndex === targetIndex) {
|
||||
return
|
||||
}
|
||||
|
||||
orderedUrls = insertAt(
|
||||
targetIndex,
|
||||
orderedUrls[sourceIndex],
|
||||
removeAt(sourceIndex, orderedUrls),
|
||||
)
|
||||
}
|
||||
|
||||
const onDragStart = (e: DragEvent, url: string) => {
|
||||
draggedUrl = url
|
||||
dragStartOrder = [...orderedUrls]
|
||||
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.effectAllowed = "move"
|
||||
@@ -45,21 +43,29 @@
|
||||
|
||||
const onDragOver = (e: DragEvent, targetUrl: string) => {
|
||||
e.preventDefault()
|
||||
moveDraggedUrl(targetUrl)
|
||||
reorderSpaceUrls(targetUrl)
|
||||
}
|
||||
|
||||
const onDrop = (e: DragEvent, targetUrl: string) => {
|
||||
e.preventDefault()
|
||||
moveDraggedUrl(targetUrl)
|
||||
reorderSpaceUrls(targetUrl)
|
||||
draggedUrl = undefined
|
||||
|
||||
if (dragStartOrder && !isSameOrder(dragStartOrder, orderedUrls)) {
|
||||
void setSpaceMembershipOrder(orderedUrls).catch(console.error)
|
||||
}
|
||||
|
||||
dragStartOrder = undefined
|
||||
}
|
||||
|
||||
const onDragEnd = () => {
|
||||
draggedUrl = undefined
|
||||
dragStartOrder = undefined
|
||||
}
|
||||
|
||||
let orderedUrls = $state([...urls])
|
||||
let draggedUrl = $state<string | undefined>()
|
||||
let dragStartOrder = $state<string[] | undefined>()
|
||||
</script>
|
||||
|
||||
<div class="column menu gap-2 p-3" role="list">
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
makeList,
|
||||
addToListPublicly,
|
||||
removeFromListByPredicate,
|
||||
updateList,
|
||||
getTag,
|
||||
getListTags,
|
||||
getRelayTagValues,
|
||||
@@ -148,6 +149,20 @@ export const removeSpaceMembership = async (url: string) => {
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
|
||||
export const setSpaceMembershipOrder = async (urls: string[]) => {
|
||||
const list = get(userGroupList) || makeList({kind: ROOMS})
|
||||
const orderedUrls = uniq(urls.map(normalizeRelayUrl))
|
||||
const relayTags = list.publicTags.filter(t => t[0] === "r")
|
||||
const otherPublicTags = list.publicTags.filter(t => t[0] !== "r")
|
||||
const relayTagByUrl = new Map(relayTags.map(t => [normalizeRelayUrl(t[1]), t]))
|
||||
const orderedRelayTags = orderedUrls.map(url => relayTagByUrl.get(url) || ["r", url])
|
||||
const publicTags = [...orderedRelayTags, ...otherPublicTags]
|
||||
const event = await updateList(list, {publicTags}).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
|
||||
export const addRoomMembership = async (url: string, h: string) => {
|
||||
const list = get(userGroupList) || makeList({kind: ROOMS})
|
||||
const newTags = [
|
||||
|
||||
@@ -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,6 +10,7 @@
|
||||
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)
|
||||
@@ -28,35 +30,28 @@
|
||||
const isSameOrder = (a: string[], b: string[]) =>
|
||||
a.length === b.length && a.every((url, index) => url === b[index])
|
||||
|
||||
const reorderUrls = (sourceUrl: string, targetUrl: string, currentUrls: string[]) => {
|
||||
if (sourceUrl === targetUrl) {
|
||||
return currentUrls
|
||||
}
|
||||
|
||||
const sourceIndex = currentUrls.indexOf(sourceUrl)
|
||||
const targetIndex = currentUrls.indexOf(targetUrl)
|
||||
|
||||
if (sourceIndex === -1 || targetIndex === -1) {
|
||||
return currentUrls
|
||||
}
|
||||
|
||||
const nextUrls = currentUrls.filter(url => url !== sourceUrl)
|
||||
|
||||
nextUrls.splice(targetIndex, 0, sourceUrl)
|
||||
|
||||
return nextUrls
|
||||
}
|
||||
|
||||
const moveDraggedUrl = (targetUrl: string) => {
|
||||
const reorderSpaceUrls = (targetUrl: string) => {
|
||||
if (!draggedUrl) {
|
||||
return
|
||||
}
|
||||
|
||||
orderedSpaceUrls = reorderUrls(draggedUrl, targetUrl, orderedSpaceUrls)
|
||||
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"
|
||||
@@ -66,17 +61,24 @@
|
||||
|
||||
const onDragOver = (e: DragEvent, targetUrl: string) => {
|
||||
e.preventDefault()
|
||||
moveDraggedUrl(targetUrl)
|
||||
reorderSpaceUrls(targetUrl)
|
||||
}
|
||||
|
||||
const onDrop = (e: DragEvent, targetUrl: string) => {
|
||||
e.preventDefault()
|
||||
moveDraggedUrl(targetUrl)
|
||||
reorderSpaceUrls(targetUrl)
|
||||
draggedUrl = undefined
|
||||
|
||||
if (dragStartOrder && !isSameOrder(dragStartOrder, orderedSpaceUrls)) {
|
||||
void setSpaceMembershipOrder(orderedSpaceUrls).catch(console.error)
|
||||
}
|
||||
|
||||
dragStartOrder = undefined
|
||||
}
|
||||
|
||||
const onDragEnd = () => {
|
||||
draggedUrl = undefined
|
||||
dragStartOrder = undefined
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
@@ -89,6 +91,7 @@
|
||||
|
||||
let orderedSpaceUrls = $state<string[]>([])
|
||||
let draggedUrl = $state<string | undefined>()
|
||||
let dragStartOrder = $state<string[] | undefined>()
|
||||
</script>
|
||||
|
||||
<Page class="cw-full">
|
||||
|
||||
Reference in New Issue
Block a user