feat: use crossbell kit to update character
This commit is contained in:
parent
b50fadc2a0
commit
550c27159a
|
|
@ -23,20 +23,18 @@ export default function SettingsCSSPage() {
|
|||
const handleSubmit = (e: any) => {
|
||||
e.preventDefault()
|
||||
updateSite.mutate({
|
||||
site: subdomain,
|
||||
characterId: site.data?.characterId,
|
||||
css: css,
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (updateSite.isSuccess) {
|
||||
if (updateSite.data?.code === 0) {
|
||||
toast.success("Saved!")
|
||||
} else {
|
||||
toast.error("Failed to update site" + ": " + updateSite.data.message)
|
||||
}
|
||||
toast.success("Saved!")
|
||||
updateSite.reset()
|
||||
} else if (updateSite.isError) {
|
||||
toast.error("Failed to update site")
|
||||
updateSite.reset()
|
||||
}
|
||||
}, [updateSite.isSuccess, updateSite.isError])
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,14 @@ import { OUR_DOMAIN } from "~/lib/env"
|
|||
import { getSiteLink } from "~/lib/helpers"
|
||||
import { useTranslation } from "~/lib/i18n/client"
|
||||
import { checkDomain } from "~/models/site.model"
|
||||
import { useGetSite, useUpdateSite } from "~/queries/site"
|
||||
import { useGetSite, useUpdateHandle, useUpdateSite } from "~/queries/site"
|
||||
|
||||
export default function SettingsDomainsPage() {
|
||||
const params = useParams()
|
||||
const subdomain = params?.subdomain as string
|
||||
|
||||
const updateSite = useUpdateSite()
|
||||
const updateHandle = useUpdateHandle()
|
||||
const site = useGetSite(subdomain)
|
||||
const userRole = useUserRole(subdomain)
|
||||
const { t } = useTranslation("dashboard")
|
||||
|
|
@ -45,14 +46,18 @@ export default function SettingsDomainsPage() {
|
|||
})
|
||||
|
||||
const handleSubmit = form.handleSubmit((values) => {
|
||||
updateSite.mutate({
|
||||
site: subdomain,
|
||||
...(subdomain !== values.subdomain && { subdomain: values.subdomain }),
|
||||
...(site.data?.metadata?.content?.custom_domain !==
|
||||
values.custom_domain && {
|
||||
if (site.data?.metadata?.content?.custom_domain !== values.custom_domain) {
|
||||
updateSite.mutate({
|
||||
characterId: site.data?.characterId,
|
||||
custom_domain: values.custom_domain,
|
||||
}),
|
||||
})
|
||||
})
|
||||
}
|
||||
if (subdomain !== values.subdomain) {
|
||||
updateHandle.mutate({
|
||||
characterId: site.data?.characterId,
|
||||
handle: values.subdomain,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const [customDomain, setCustomDomain] = useState("")
|
||||
|
|
@ -66,26 +71,29 @@ export default function SettingsDomainsPage() {
|
|||
const customSubdomain = customDomain?.split(".").slice(0, -2).join(".") || ""
|
||||
|
||||
useEffect(() => {
|
||||
if (updateSite.isSuccess) {
|
||||
if (updateSite.data?.code === 0) {
|
||||
if (!updateSite.isLoading && !updateHandle.isLoading) {
|
||||
if (updateSite.isError || updateHandle.isError) {
|
||||
toast.error("Failed to update site")
|
||||
} else if (updateSite.isSuccess || updateHandle.isSuccess) {
|
||||
toast.success("Saved!")
|
||||
useAccountState
|
||||
.getState()
|
||||
.refresh()
|
||||
.then(() => {
|
||||
router.replace(
|
||||
`/dashboard/${
|
||||
updateSite.variables?.subdomain || updateSite.variables?.site
|
||||
}/settings/domains`,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
toast.error("Failed to update site" + ": " + updateSite.data.message)
|
||||
if (updateHandle.isSuccess) {
|
||||
useAccountState
|
||||
.getState()
|
||||
.refresh()
|
||||
.then(() => {
|
||||
router.replace(
|
||||
`/dashboard/${updateHandle.variables?.handle}/settings/domains`,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (updateSite.isError) {
|
||||
toast.error("Failed to update site")
|
||||
}
|
||||
}, [updateSite.isSuccess])
|
||||
}, [
|
||||
updateSite.isSuccess,
|
||||
updateSite.isLoading,
|
||||
updateHandle.isSuccess,
|
||||
updateHandle.isLoading,
|
||||
])
|
||||
|
||||
const [domainCheckResult, setDomainCheckResult] = useState<{
|
||||
isLoading: boolean
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ export default function SiteSettingsGeneralPage() {
|
|||
|
||||
const handleSubmit = form.handleSubmit((values) => {
|
||||
updateSite.mutate({
|
||||
characterId: site.data?.characterId,
|
||||
icon: values.icon,
|
||||
banner: values.banner,
|
||||
site: subdomain,
|
||||
name: values.name,
|
||||
site_name: values.site_name,
|
||||
description: values.description,
|
||||
|
|
@ -63,11 +63,7 @@ export default function SiteSettingsGeneralPage() {
|
|||
|
||||
useEffect(() => {
|
||||
if (updateSite.isSuccess) {
|
||||
if (updateSite.data?.code === 0) {
|
||||
toast.success("Site updated")
|
||||
} else {
|
||||
toast.error("Failed to update site" + ": " + updateSite.data.message)
|
||||
}
|
||||
toast.success("Site updated")
|
||||
} else if (updateSite.isError) {
|
||||
toast.error("Failed to update site")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export default function SiteSettingsNavigationPage() {
|
|||
e.preventDefault()
|
||||
if (site.data?.handle) {
|
||||
updateSite.mutate({
|
||||
site: site.data?.handle,
|
||||
characterId: site.data?.characterId,
|
||||
navigation: items,
|
||||
})
|
||||
}
|
||||
|
|
@ -110,11 +110,7 @@ export default function SiteSettingsNavigationPage() {
|
|||
|
||||
useEffect(() => {
|
||||
if (updateSite.isSuccess) {
|
||||
if (updateSite.data?.code === 0) {
|
||||
toast.success("Saved")
|
||||
} else {
|
||||
toast.error("Failed to save" + ": " + updateSite.data.message)
|
||||
}
|
||||
toast.success("Saved")
|
||||
} else if (updateSite.isError) {
|
||||
toast.error("Failed to save")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ export default function SiteSettingsNavigationPage() {
|
|||
e.preventDefault()
|
||||
if (site.data?.handle) {
|
||||
updateSite.mutate({
|
||||
site: site.data?.handle,
|
||||
characterId: site.data?.characterId,
|
||||
connected_accounts: items.map(({ id, ...item }) => item),
|
||||
})
|
||||
}
|
||||
|
|
@ -124,11 +124,7 @@ export default function SiteSettingsNavigationPage() {
|
|||
|
||||
useEffect(() => {
|
||||
if (updateSite.isSuccess) {
|
||||
if (updateSite.data?.code === 0) {
|
||||
toast.success("Saved")
|
||||
} else {
|
||||
toast.error("Failed to save" + ": " + updateSite.data.message)
|
||||
}
|
||||
toast.success("Saved")
|
||||
} else if (updateSite.isError) {
|
||||
toast.error("Failed to save")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import { CharacterOperatorPermission } from "crossbell"
|
||||
import type Unidata from "unidata.js"
|
||||
import type { Address } from "viem"
|
||||
|
||||
import type { useContract } from "@crossbell/contract"
|
||||
import { indexer } from "@crossbell/indexer"
|
||||
|
||||
import { expandCrossbellCharacter } from "~/lib/expand-unit"
|
||||
import { SiteNavigationItem } from "~/lib/types"
|
||||
import { client } from "~/queries/graphql"
|
||||
|
||||
type Contract = ReturnType<typeof useContract>
|
||||
|
|
@ -91,124 +89,6 @@ export const getSiteToSubscriptions = async (data: {
|
|||
})
|
||||
}
|
||||
|
||||
export async function updateSite(
|
||||
payload: {
|
||||
site: string
|
||||
name?: string
|
||||
site_name?: string
|
||||
description?: string
|
||||
icon?: string | null
|
||||
subdomain?: string
|
||||
navigation?: SiteNavigationItem[]
|
||||
css?: string
|
||||
ga?: string
|
||||
ua?: string
|
||||
uh?: string
|
||||
custom_domain?: string
|
||||
banner?: {
|
||||
address: string
|
||||
mime_type: string
|
||||
}
|
||||
connected_accounts?: {
|
||||
identity: string
|
||||
platform: string
|
||||
url?: string | undefined
|
||||
}[]
|
||||
},
|
||||
customUnidata?: Unidata,
|
||||
newbieToken?: string,
|
||||
) {
|
||||
const { default: unidata } = await import("~/queries/unidata.server")
|
||||
|
||||
return await (customUnidata || unidata).profiles.set(
|
||||
{
|
||||
source: "Crossbell Profile",
|
||||
identity: payload.site,
|
||||
platform: "Crossbell",
|
||||
action: "update",
|
||||
},
|
||||
{
|
||||
...(payload.name && { name: payload.name }),
|
||||
...(payload.description && { bio: payload.description }),
|
||||
...(payload.icon && { avatars: [payload.icon] }),
|
||||
...(payload.banner && { banners: [payload.banner] }),
|
||||
...(payload.subdomain && { username: payload.subdomain }),
|
||||
...(payload.connected_accounts && {
|
||||
connected_accounts: payload.connected_accounts,
|
||||
}),
|
||||
...((payload.navigation !== undefined ||
|
||||
payload.css !== undefined ||
|
||||
payload.ga !== undefined ||
|
||||
payload.ua !== undefined ||
|
||||
payload.uh !== undefined ||
|
||||
payload.custom_domain !== undefined) && {
|
||||
attributes: [
|
||||
...(payload.navigation !== undefined
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_navigation",
|
||||
value: JSON.stringify(payload.navigation),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(payload.css !== undefined
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_css",
|
||||
value: payload.css,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(payload.ga !== undefined
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_ga",
|
||||
value: payload.ga,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(payload.ua !== undefined
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_ua",
|
||||
value: payload.ua,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(payload.uh !== undefined
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_uh",
|
||||
value: payload.uh,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(payload.custom_domain !== undefined
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_custom_domain",
|
||||
value: payload.custom_domain,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(payload.site_name !== undefined &&
|
||||
payload.site_name !== payload.name
|
||||
? [
|
||||
{
|
||||
trait_type: "xlog_site_name",
|
||||
value: payload.site_name,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
newbieToken,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function getCommentsBySite(input: {
|
||||
characterId?: number
|
||||
cursor?: string
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ import {
|
|||
useFollowCharacters,
|
||||
useTip,
|
||||
useUnfollowCharacter,
|
||||
useUpdateCharacterHandle,
|
||||
useUpdateCharacterMetadata,
|
||||
} from "@crossbell/connect-kit"
|
||||
import { useContract } from "@crossbell/contract"
|
||||
import { useRefCallback } from "@crossbell/util-hooks"
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useMutation,
|
||||
|
|
@ -15,10 +18,9 @@ import {
|
|||
useQueryClient,
|
||||
} from "@tanstack/react-query"
|
||||
|
||||
import { SiteNavigationItem } from "~/lib/types"
|
||||
import * as siteModel from "~/models/site.model"
|
||||
|
||||
import { useUnidata } from "./unidata"
|
||||
|
||||
export const useGetSite = (input?: string) => {
|
||||
return useQuery(["getSite", input], async () => {
|
||||
if (!input) {
|
||||
|
|
@ -86,21 +88,208 @@ export const useGetSiteToSubscriptions = (data: { characterId?: number }) => {
|
|||
})
|
||||
}
|
||||
|
||||
export function useUpdateSite() {
|
||||
const newbieToken = useAccountState((s) => s.email?.token)
|
||||
const unidata = useUnidata()
|
||||
export function useUpdateHandle() {
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useMutation(
|
||||
async (payload: Parameters<typeof siteModel.updateSite>[0]) => {
|
||||
return siteModel.updateSite(payload, unidata, newbieToken)
|
||||
},
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getSite"])
|
||||
},
|
||||
const { mutateAsync: _, ...updateCharacterHandle } =
|
||||
useUpdateCharacterHandle()
|
||||
|
||||
const mutate = useRefCallback(
|
||||
(input: { characterId?: number; handle?: string }) => {
|
||||
if (!input.characterId || !input.handle) {
|
||||
throw new Error("characterId and handle are required")
|
||||
}
|
||||
|
||||
return updateCharacterHandle.mutate(
|
||||
{
|
||||
characterId: input.characterId,
|
||||
handle: input.handle,
|
||||
},
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getSite"])
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
return mutation
|
||||
|
||||
return {
|
||||
...updateCharacterHandle,
|
||||
mutate,
|
||||
}
|
||||
}
|
||||
|
||||
export function useUpdateSite() {
|
||||
const queryClient = useQueryClient()
|
||||
const { mutateAsync: _, ...updateCharacterMetadata } =
|
||||
useUpdateCharacterMetadata()
|
||||
|
||||
const mutate = useRefCallback(
|
||||
(input: {
|
||||
characterId?: number
|
||||
name?: string
|
||||
site_name?: string
|
||||
description?: string
|
||||
icon?: string
|
||||
navigation?: SiteNavigationItem[]
|
||||
css?: string
|
||||
ga?: string
|
||||
ua?: string
|
||||
uh?: string
|
||||
custom_domain?: string
|
||||
banner?: {
|
||||
address: string
|
||||
mime_type: string
|
||||
}
|
||||
connected_accounts?: {
|
||||
identity: string
|
||||
platform: string
|
||||
url?: string | undefined
|
||||
}[]
|
||||
}) => {
|
||||
if (!input.characterId) {
|
||||
throw new Error("characterId are required")
|
||||
}
|
||||
|
||||
return updateCharacterMetadata.mutate(
|
||||
{
|
||||
characterId: input.characterId,
|
||||
edit(metadataDraft) {
|
||||
if (input.name !== undefined) {
|
||||
metadataDraft.name = input.name
|
||||
}
|
||||
if (input.description !== undefined) {
|
||||
metadataDraft.bio = input.description
|
||||
}
|
||||
if (input.icon !== undefined) {
|
||||
metadataDraft.avatars = [input.icon]
|
||||
}
|
||||
if (input.banner !== undefined) {
|
||||
metadataDraft.banners = [input.banner]
|
||||
}
|
||||
if (input.connected_accounts !== undefined) {
|
||||
metadataDraft.connected_accounts = input.connected_accounts.map(
|
||||
(account) => {
|
||||
if (account.identity && account.platform) {
|
||||
return `csb://account:${
|
||||
account.identity
|
||||
}@${account.platform.toLowerCase()}`
|
||||
} else if (typeof account === "string") {
|
||||
return account
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// attributes
|
||||
if (input.navigation !== undefined) {
|
||||
const navigation = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_navigation",
|
||||
)
|
||||
if (navigation) {
|
||||
navigation.value = JSON.stringify(input.navigation)
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_navigation",
|
||||
value: JSON.stringify(input.navigation),
|
||||
})
|
||||
}
|
||||
}
|
||||
if (input.css !== undefined) {
|
||||
const css = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_css",
|
||||
)
|
||||
if (css) {
|
||||
css.value = input.css
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_css",
|
||||
value: input.css,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (input.ga !== undefined) {
|
||||
const ga = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_ga",
|
||||
)
|
||||
if (ga) {
|
||||
ga.value = input.ga
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_ga",
|
||||
value: input.ga,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (input.ua !== undefined) {
|
||||
const ua = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_ua",
|
||||
)
|
||||
if (ua) {
|
||||
ua.value = input.ua
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_ua",
|
||||
value: input.ua,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (input.uh !== undefined) {
|
||||
const uh = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_uh",
|
||||
)
|
||||
if (uh) {
|
||||
uh.value = input.uh
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_uh",
|
||||
value: input.uh,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (input.custom_domain !== undefined) {
|
||||
const custom_domain = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_custom_domain",
|
||||
)
|
||||
if (custom_domain) {
|
||||
custom_domain.value = input.custom_domain
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_custom_domain",
|
||||
value: input.custom_domain,
|
||||
})
|
||||
}
|
||||
}
|
||||
if (input.site_name !== undefined) {
|
||||
const site_name = metadataDraft.attributes?.find(
|
||||
(attr) => attr.trait_type === "xlog_site_name",
|
||||
)
|
||||
if (site_name) {
|
||||
site_name.value = input.site_name
|
||||
} else {
|
||||
metadataDraft.attributes?.push({
|
||||
trait_type: "xlog_site_name",
|
||||
value: input.site_name,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getSite"])
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
return {
|
||||
...updateCharacterMetadata,
|
||||
mutate,
|
||||
}
|
||||
}
|
||||
|
||||
export function useSubscribeToSite() {
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import type Unidata from "unidata.js"
|
||||
import { useAccount } from "wagmi"
|
||||
|
||||
import { IPFS_GATEWAY } from "../lib/env"
|
||||
|
||||
export const useUnidata = () => {
|
||||
const { connector, isConnected } = useAccount()
|
||||
|
||||
const [unidata, setUnidata] = useState<Unidata>()
|
||||
|
||||
useEffect(() => {
|
||||
import("unidata.js").then(({ default: Unidata }) => {
|
||||
if (isConnected && connector) {
|
||||
connector?.getProvider().then((provider) => {
|
||||
setUnidata(
|
||||
new Unidata({
|
||||
ethereumProvider: provider,
|
||||
ipfsGateway: IPFS_GATEWAY,
|
||||
ipfsRelay: "https://ipfs-relay.crossbell.io/json?gnfd=t",
|
||||
}),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
setUnidata(
|
||||
new Unidata({
|
||||
ipfsGateway: IPFS_GATEWAY,
|
||||
ipfsRelay: "https://ipfs-relay.crossbell.io/json?gnfd=t",
|
||||
}),
|
||||
)
|
||||
}
|
||||
})
|
||||
}, [isConnected, connector])
|
||||
|
||||
return unidata
|
||||
}
|
||||
Loading…
Reference in New Issue