mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
Bring code up to date with the latest gomuks
This commit is contained in:
parent
13a45b7722
commit
0d8a6bce23
3 changed files with 105 additions and 65 deletions
|
@ -17,7 +17,7 @@ import { use, useCallback, useEffect, useState } from "react"
|
||||||
import { PuffLoader } from "react-spinners"
|
import { PuffLoader } from "react-spinners"
|
||||||
import { getAvatarURL } from "@/api/media.ts"
|
import { getAvatarURL } from "@/api/media.ts"
|
||||||
import { useRoomMember } from "@/api/statestore"
|
import { useRoomMember } from "@/api/statestore"
|
||||||
import { MemberEventContent, UserID, UserProfile, Presence } from "@/api/types"
|
import { MemberEventContent, UserID, UserProfile } from "@/api/types"
|
||||||
import { getLocalpart } from "@/util/validation.ts"
|
import { getLocalpart } from "@/util/validation.ts"
|
||||||
import ClientContext from "../ClientContext.ts"
|
import ClientContext from "../ClientContext.ts"
|
||||||
import { LightboxContext } from "../modal"
|
import { LightboxContext } from "../modal"
|
||||||
|
@ -26,7 +26,6 @@ import UserExtendedProfile from "./UserExtendedProfile.tsx"
|
||||||
import DeviceList from "./UserInfoDeviceList.tsx"
|
import DeviceList from "./UserInfoDeviceList.tsx"
|
||||||
import UserInfoError from "./UserInfoError.tsx"
|
import UserInfoError from "./UserInfoError.tsx"
|
||||||
import MutualRooms from "./UserInfoMutualRooms.tsx"
|
import MutualRooms from "./UserInfoMutualRooms.tsx"
|
||||||
import { ErrorResponse } from "@/api/rpc.ts"
|
|
||||||
import { UserPresence } from "./UserPresence.tsx"
|
import { UserPresence } from "./UserPresence.tsx"
|
||||||
|
|
||||||
interface UserInfoProps {
|
interface UserInfoProps {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// gomuks - A Matrix client written in Go.
|
// gomuks - A Matrix client written in Go.
|
||||||
// Copyright (C) 2024 Tulir Asokan
|
// Copyright (C) 2025 Nexus Nicholson
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -13,10 +13,10 @@
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import { MouseEvent, useEffect, useState } from "react"
|
import { FormEvent, MouseEvent, useEffect, useState } from "react"
|
||||||
import { UserID, Presence, RPCEvent } from "@/api/types"
|
|
||||||
import { ErrorResponse } from "@/api/rpc.ts"
|
|
||||||
import Client from "@/api/client"
|
import Client from "@/api/client"
|
||||||
|
import { ErrorResponse } from "@/api/rpc.ts"
|
||||||
|
import { Presence, RPCEvent, UserID } from "@/api/types"
|
||||||
|
|
||||||
interface UserPresenceProps {
|
interface UserPresenceProps {
|
||||||
client: Client,
|
client: Client,
|
||||||
|
@ -28,9 +28,18 @@ interface EditUserPresenceProps {
|
||||||
setter: (presence: Presence) => void
|
setter: (presence: Presence) => void
|
||||||
}
|
}
|
||||||
const PresenceEmojis = {
|
const PresenceEmojis = {
|
||||||
"online": <svg className="presence-indicator presence-online" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="50" /></svg>,
|
"online": <svg
|
||||||
"offline": <svg className="presence-indicator presence-offline" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="50" /></svg>,
|
className="presence-indicator presence-online"
|
||||||
"unavailable": <svg className="presence-indicator presence-unavailable" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="50" /></svg>,
|
viewBox="0 0 16 16"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="50" /></svg>,
|
||||||
|
"offline": <svg
|
||||||
|
className="presence-indicator presence-offline"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="50" /></svg>,
|
||||||
|
"unavailable": <svg
|
||||||
|
className="presence-indicator presence-unavailable"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><circle cx="16" cy="16" r="50" /></svg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserPresence = ({ client, userID }: UserPresenceProps) => {
|
export const UserPresence = ({ client, userID }: UserPresenceProps) => {
|
||||||
|
@ -41,7 +50,7 @@ export const UserPresence = ({ client, userID }: UserPresenceProps) => {
|
||||||
if (event.command === "update_presence" && event.data.user_id === userID) {
|
if (event.command === "update_presence" && event.data.user_id === userID) {
|
||||||
setPresence({
|
setPresence({
|
||||||
"presence": event.data.presence,
|
"presence": event.data.presence,
|
||||||
"status_msg": event.data.status_msg || null
|
"status_msg": event.data.status_msg || null,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -54,13 +63,13 @@ export const UserPresence = ({ client, userID }: UserPresenceProps) => {
|
||||||
if (err instanceof ErrorResponse && err.message.startsWith("M_NOT_FOUND")) {
|
if (err instanceof ErrorResponse && err.message.startsWith("M_NOT_FOUND")) {
|
||||||
setPresence(null)
|
setPresence(null)
|
||||||
} else {
|
} else {
|
||||||
errors?.length ? setErrors([...errors, `${err}`]) : setErrors([`${err}`])
|
setErrors([...errors||[], `${err}`])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}, [client, userID])
|
}, [client, userID])
|
||||||
|
|
||||||
if(!presence) return null;
|
if(!presence) {return null}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -73,13 +82,16 @@ export const UserPresence = ({ client, userID }: UserPresenceProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DisplayUserPresence = ({ presence }: { presence: Presence | null }) => {
|
export const DisplayUserPresence = ({ presence }: { presence: Presence | null }) => {
|
||||||
if(!presence) return null
|
if(!presence) {return null}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="presence" title={presence.presence}>{PresenceEmojis[presence.presence]} {presence.presence}</div>
|
<div className="presence" title={presence.presence}>{PresenceEmojis[presence.presence]} {presence.presence}
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
presence.status_msg && (
|
presence.status_msg && (
|
||||||
<div className="statusmessage" title={"Status message"}><blockquote>{presence.status_msg}</blockquote></div>
|
<div className="statusmessage" title={"Status message"}>
|
||||||
|
<blockquote>{presence.status_msg}</blockquote>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
@ -93,30 +105,59 @@ export const EditUserPresence = ({ client, presence, setter }: EditUserPresenceP
|
||||||
err => console.error(err),
|
err => console.error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const createPresence = (status: "online" | "unavailable" | "offline") => {
|
||||||
|
return { ...(presence || {}), "presence": status }
|
||||||
|
}
|
||||||
const clearStatusMessage = (e: MouseEvent<HTMLButtonElement>) => {
|
const clearStatusMessage = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
let p = presence || {"presence": "offline"}
|
const p = presence || { "presence": "offline" }
|
||||||
if(p.status_msg) {
|
if(p.status_msg) {
|
||||||
delete p.status_msg
|
delete p.status_msg
|
||||||
}
|
}
|
||||||
const textInputElement = e.currentTarget.parentElement?.querySelector("input[type=text]") as HTMLInputElement
|
const textInputElement = e.currentTarget.parentElement?.querySelector("input[type=text]") as HTMLInputElement
|
||||||
client.rpc.setPresence(p).then(
|
client.rpc.setPresence(p).then(
|
||||||
() => {setter(p); if(textInputElement) textInputElement.value = ""},
|
() => {setter(p); if(textInputElement) {textInputElement.value = ""}},
|
||||||
err => console.error(err),
|
err => console.error(err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const onFormSubmit = (e: FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault()
|
||||||
|
const textInputElement = e.currentTarget[0] as HTMLInputElement
|
||||||
|
const newPresence = { ...(presence || {}), "status_msg": textInputElement.value }
|
||||||
|
client.rpc.setPresence(newPresence).then(
|
||||||
|
() => {setter(newPresence); textInputElement.value = ""},
|
||||||
|
err => console.error(err),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h4>Set presence</h4>
|
<h4>Set presence</h4>
|
||||||
<div className="presencesetter">
|
<div className="presencesetter">
|
||||||
<button title="Set presence to online" onClick={() => sendNewPresence({...(presence || {}), "presence": "online"})} type="button">{PresenceEmojis["online"]} Online</button>
|
<button
|
||||||
<button title="Set presence to unavailable" onClick={() => sendNewPresence({...(presence || {}), "presence": "unavailable"})} type="button">{PresenceEmojis["unavailable"]} Unavailable</button>
|
title="Set presence to online"
|
||||||
<button title="Set presence to offline" onClick={() => sendNewPresence({...(presence || {}), "presence": "offline"})} type="button">{PresenceEmojis["offline"]} Offline</button>
|
onClick={() => sendNewPresence(createPresence("online"))}
|
||||||
|
type="button">
|
||||||
|
{PresenceEmojis["online"]} Online
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
title="Set presence to unavailable"
|
||||||
|
onClick={() => sendNewPresence(createPresence("unavailable"))}
|
||||||
|
type="button">
|
||||||
|
{PresenceEmojis["unavailable"]} Unavailable
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
title="Set presence to offline"
|
||||||
|
onClick={() => sendNewPresence(createPresence("offline"))}
|
||||||
|
type="button">
|
||||||
|
{PresenceEmojis["offline"]} Offline
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p></p>
|
<p></p>
|
||||||
<div className="statussetter">
|
<div className="statussetter">
|
||||||
<form className={presence?.status_msg ? "canclear" : "cannotclear"} onSubmit={(e) => {e.preventDefault(); sendNewPresence({...(presence || {}), "status_msg": (e.currentTarget[0] as HTMLInputElement).value})}}>
|
<form className={presence?.status_msg ? "canclear" : "cannotclear"} onSubmit={onFormSubmit}>
|
||||||
<input type="text" placeholder="Status message" defaultValue={presence?.status_msg || ""}/>
|
<input type="text" placeholder="Status message" defaultValue={presence?.status_msg || ""}/>
|
||||||
{presence?.status_msg && <button title="Clear status" type="button" onClick={(e) => clearStatusMessage(e)}>Clear</button>}
|
{presence?.status_msg &&
|
||||||
|
<button title="Clear status" type="button" onClick={clearStatusMessage}>Clear</button>}
|
||||||
<button title="Set status message" type="submit">Set</button>
|
<button title="Set status message" type="submit">Set</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue