reorder priority
This commit is contained in:
parent
ccdf346954
commit
57603a936f
|
@ -525,6 +525,15 @@ const resolvers = {
|
||||||
}
|
}
|
||||||
return { id }
|
return { id }
|
||||||
},
|
},
|
||||||
|
setWalletPriority: async (parent, { id, priority }, { me, models }) => {
|
||||||
|
if (!me) {
|
||||||
|
throw new GqlAuthenticationError()
|
||||||
|
}
|
||||||
|
|
||||||
|
await models.wallet.update({ where: { userId: me.id, id: Number(id) }, data: { priority } })
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
removeWallet: async (parent, { id }, { me, models }) => {
|
removeWallet: async (parent, { id }, { me, models }) => {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new GqlAuthenticationError()
|
throw new GqlAuthenticationError()
|
||||||
|
|
|
@ -81,6 +81,7 @@ const typeDefs = `
|
||||||
dropBolt11(id: ID): Withdrawl
|
dropBolt11(id: ID): Withdrawl
|
||||||
removeWallet(id: ID!): Boolean
|
removeWallet(id: ID!): Boolean
|
||||||
deleteWalletLogs(wallet: String): Boolean
|
deleteWalletLogs(wallet: String): Boolean
|
||||||
|
setWalletPriority(id: ID!, priority: Int!): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Wallet {
|
type Wallet {
|
||||||
|
|
|
@ -190,3 +190,9 @@ export const WALLET_LOGS = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const SET_WALLET_PRIORITY = gql`
|
||||||
|
mutation SetWalletPriority($id: ID!, $priority: Int!) {
|
||||||
|
setWalletPriority(id: $id, priority: $priority)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
|
@ -3,65 +3,69 @@ import Layout from '@/components/layout'
|
||||||
import styles from '@/styles/wallet.module.css'
|
import styles from '@/styles/wallet.module.css'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useWallets } from '@/wallets/index'
|
import { useWallets } from '@/wallets/index'
|
||||||
import { useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
import { useIsClient } from '@/components/use-client'
|
import { useIsClient } from '@/components/use-client'
|
||||||
import WalletCard from '@/components/wallet-card'
|
import WalletCard from '@/components/wallet-card'
|
||||||
|
import { useToast } from '@/components/toast'
|
||||||
|
|
||||||
export const getServerSideProps = getGetServerSideProps({ authRequired: true })
|
export const getServerSideProps = getGetServerSideProps({ authRequired: true })
|
||||||
|
|
||||||
async function reorder (wallets, sourceIndex, targetIndex) {
|
|
||||||
const newOrder = [...wallets]
|
|
||||||
|
|
||||||
const [source] = newOrder.splice(sourceIndex, 1)
|
|
||||||
const newTargetIndex = sourceIndex < targetIndex ? targetIndex - 1 : targetIndex
|
|
||||||
const append = sourceIndex < targetIndex
|
|
||||||
|
|
||||||
newOrder.splice(newTargetIndex + (append ? 1 : 0), 0, source)
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
newOrder.map((w, i) =>
|
|
||||||
w.setPriority(i).catch(console.error)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Wallet ({ ssrData }) {
|
export default function Wallet ({ ssrData }) {
|
||||||
const { wallets } = useWallets()
|
const { wallets, setPriorities, reloadLocalWallets } = useWallets()
|
||||||
|
const toast = useToast()
|
||||||
const isClient = useIsClient()
|
const isClient = useIsClient()
|
||||||
const [sourceIndex, setSourceIndex] = useState(null)
|
const [sourceIndex, setSourceIndex] = useState(null)
|
||||||
const [targetIndex, setTargetIndex] = useState(null)
|
const [targetIndex, setTargetIndex] = useState(null)
|
||||||
|
|
||||||
const onDragStart = (i) => (e) => {
|
const reorder = useCallback(async (sourceIndex, targetIndex) => {
|
||||||
|
const newOrder = [...wallets.filter(w => w.config?.enabled)]
|
||||||
|
const [source] = newOrder.splice(sourceIndex, 1)
|
||||||
|
const newTargetIndex = sourceIndex < targetIndex ? targetIndex - 1 : targetIndex
|
||||||
|
|
||||||
|
const priorities = newOrder.slice(0, newTargetIndex)
|
||||||
|
.concat(source)
|
||||||
|
.concat(newOrder.slice(newTargetIndex))
|
||||||
|
.map((w, i) => ({ wallet: w, priority: i }))
|
||||||
|
|
||||||
|
await setPriorities(priorities)
|
||||||
|
reloadLocalWallets()
|
||||||
|
}, [setPriorities, reloadLocalWallets, wallets])
|
||||||
|
|
||||||
|
const onDragStart = useCallback((i) => (e) => {
|
||||||
// e.dataTransfer.dropEffect = 'move'
|
// e.dataTransfer.dropEffect = 'move'
|
||||||
// We can only use the DataTransfer API inside the drop event
|
// We can only use the DataTransfer API inside the drop event
|
||||||
// see https://html.spec.whatwg.org/multipage/dnd.html#security-risks-in-the-drag-and-drop-model
|
// see https://html.spec.whatwg.org/multipage/dnd.html#security-risks-in-the-drag-and-drop-model
|
||||||
// e.dataTransfer.setData('text/plain', name)
|
// e.dataTransfer.setData('text/plain', name)
|
||||||
// That's why we use React state instead
|
// That's why we use React state instead
|
||||||
setSourceIndex(i)
|
setSourceIndex(i)
|
||||||
}
|
}, [setSourceIndex])
|
||||||
|
|
||||||
const onDragEnter = (i) => (e) => {
|
const onDragEnter = useCallback((i) => (e) => {
|
||||||
setTargetIndex(i)
|
setTargetIndex(i)
|
||||||
}
|
}, [setTargetIndex])
|
||||||
|
|
||||||
const onDragEnd = async (e) => {
|
const onReorderError = useCallback((err) => {
|
||||||
|
console.error(err)
|
||||||
|
toast.danger('failed to reorder wallets')
|
||||||
|
}, [toast])
|
||||||
|
|
||||||
|
const onDragEnd = useCallback((e) => {
|
||||||
setSourceIndex(null)
|
setSourceIndex(null)
|
||||||
setTargetIndex(null)
|
setTargetIndex(null)
|
||||||
|
|
||||||
if (sourceIndex === targetIndex) return
|
if (sourceIndex === targetIndex) return
|
||||||
|
|
||||||
await reorder(wallets, sourceIndex, targetIndex)
|
reorder(sourceIndex, targetIndex).catch(onReorderError)
|
||||||
}
|
}, [sourceIndex, targetIndex, reorder, onReorderError])
|
||||||
|
|
||||||
const onTouchStart = (i) => async (e) => {
|
const onTouchStart = useCallback((i) => (e) => {
|
||||||
if (sourceIndex !== null) {
|
if (sourceIndex !== null) {
|
||||||
await reorder(wallets, sourceIndex, i)
|
reorder(sourceIndex, i).catch(onReorderError)
|
||||||
setSourceIndex(null)
|
setSourceIndex(null)
|
||||||
} else {
|
} else {
|
||||||
setSourceIndex(i)
|
setSourceIndex(i)
|
||||||
}
|
}
|
||||||
}
|
}, [sourceIndex, reorder, onReorderError])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useMe } from '@/components/me'
|
import { useMe } from '@/components/me'
|
||||||
import { WALLETS } from '@/fragments/wallet'
|
import { SET_WALLET_PRIORITY, WALLETS } from '@/fragments/wallet'
|
||||||
import { SSR } from '@/lib/constants'
|
import { SSR } from '@/lib/constants'
|
||||||
import { useQuery } from '@apollo/client'
|
import { useMutation, useQuery } from '@apollo/client'
|
||||||
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||||
import { getStorageKey, getWalletByType, Status, walletPrioritySort, canSend } from './common'
|
import { getStorageKey, getWalletByType, Status, walletPrioritySort, canSend, isConfigured } from './common'
|
||||||
import useVault from '@/components/vault/use-vault'
|
import useVault from '@/components/vault/use-vault'
|
||||||
import { useWalletLogger } from '@/components/wallet-logger'
|
import { useWalletLogger } from '@/components/wallet-logger'
|
||||||
import { bolt11Tags } from '@/lib/bolt11'
|
import { bolt11Tags } from '@/lib/bolt11'
|
||||||
|
@ -21,7 +21,8 @@ function useLocalWallets () {
|
||||||
// form wallets into a list of { config, def }
|
// form wallets into a list of { config, def }
|
||||||
const wallets = walletDefs.map(w => {
|
const wallets = walletDefs.map(w => {
|
||||||
try {
|
try {
|
||||||
const config = window.localStorage.getItem(getStorageKey(w.name, me?.id))
|
const storageKey = getStorageKey(w.name, me?.id)
|
||||||
|
const config = window.localStorage.getItem(storageKey)
|
||||||
return { def: w, config: JSON.parse(config) }
|
return { def: w, config: JSON.parse(config) }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null
|
return null
|
||||||
|
@ -43,10 +44,12 @@ export function WalletsProvider ({ children }) {
|
||||||
const { decrypt } = useVault()
|
const { decrypt } = useVault()
|
||||||
const { me } = useMe()
|
const { me } = useMe()
|
||||||
const { wallets: localWallets, reloadLocalWallets } = useLocalWallets()
|
const { wallets: localWallets, reloadLocalWallets } = useLocalWallets()
|
||||||
|
const [setWalletPriority] = useMutation(SET_WALLET_PRIORITY)
|
||||||
|
|
||||||
const { data, refetch } = useQuery(WALLETS,
|
const { data, refetch } = useQuery(WALLETS,
|
||||||
SSR ? {} : { nextFetchPolicy: 'cache-and-network' })
|
SSR ? {} : { nextFetchPolicy: 'cache-and-network' })
|
||||||
|
|
||||||
|
// refetch wallets when the vault key hash changes or wallets are updated
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (me?.privates?.walletsUpdatedAt) {
|
if (me?.privates?.walletsUpdatedAt) {
|
||||||
refetch()
|
refetch()
|
||||||
|
@ -77,9 +80,26 @@ export function WalletsProvider ({ children }) {
|
||||||
.map(w => ({ ...w, status: w.config?.enabled ? Status.Enabled : Status.Disabled }))
|
.map(w => ({ ...w, status: w.config?.enabled ? Status.Enabled : Status.Disabled }))
|
||||||
}, [data?.wallets, localWallets])
|
}, [data?.wallets, localWallets])
|
||||||
|
|
||||||
|
const setPriorities = useCallback(async (priorities) => {
|
||||||
|
for (const { wallet, priority } of priorities) {
|
||||||
|
if (!isConfigured(wallet)) {
|
||||||
|
throw new Error(`cannot set priority for unconfigured wallet: ${wallet.def.name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wallet.config?.id) {
|
||||||
|
await setWalletPriority({ variables: { id: wallet.config.id, priority } })
|
||||||
|
} else {
|
||||||
|
const storageKey = getStorageKey(wallet.def.name, me?.id)
|
||||||
|
const config = window.localStorage.getItem(storageKey)
|
||||||
|
const newConfig = { ...JSON.parse(config), priority }
|
||||||
|
window.localStorage.setItem(storageKey, JSON.stringify(newConfig))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [setWalletPriority, me?.id])
|
||||||
|
|
||||||
// provides priority sorted wallets to children
|
// provides priority sorted wallets to children
|
||||||
return (
|
return (
|
||||||
<WalletsContext.Provider value={{ wallets, reloadLocalWallets }}>
|
<WalletsContext.Provider value={{ wallets, reloadLocalWallets, setPriorities }}>
|
||||||
{children}
|
{children}
|
||||||
</WalletsContext.Provider>
|
</WalletsContext.Provider>
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue