Added handle editing with warning.

This commit is contained in:
Atridad Lahiji 2025-01-27 00:05:19 -06:00
parent 8d08cc435a
commit 72e7a8fd6e
Signed by: atridad
SSH key fingerprint: SHA256:LGomp8Opq0jz+7kbwNcdfTcuaLRb5Nh0k5AchDDb438
2 changed files with 134 additions and 3 deletions

View file

@ -4,6 +4,7 @@ import { useRefresh } from "../../../lib/RefreshContext";
interface User {
did: string;
handle?: string;
displayName?: string;
description?: string;
avatar?: {
@ -14,6 +15,7 @@ interface User {
createdAt: string;
}
interface RepoResponse {
cursor: string;
repos: {
@ -79,6 +81,16 @@ export default function UserList() {
show: false,
user: null,
});
const [editModal, setEditModal] = useState<{
show: boolean;
user: User | null;
newHandle: string;
}>({
show: false,
user: null,
newHandle: "",
});
const resetState = () => {
setUsers([]);
@ -108,6 +120,7 @@ export default function UserList() {
const data = await response.json();
return {
did,
handle: data.value.handle,
displayName: data.value.displayName,
description: data.value.description,
avatar: data.value.avatar,
@ -210,6 +223,48 @@ export default function UserList() {
}
};
const updateUserHandle = async (did: string, newHandle: string) => {
try {
setLoading(true);
setError(null);
const baseUrl = await Settings.getServiceUrl();
if (!baseUrl) throw new Error("Service URL not configured");
const headers = {
Authorization: await getAuthHeader(),
"Content-Type": "application/json",
};
const response = await fetch(
`${baseUrl}/xrpc/com.atproto.admin.updateAccountHandle`,
{
method: "POST",
headers,
body: JSON.stringify({
did,
handle: newHandle,
}),
}
);
if (!response.ok) {
const errorText = await response.text();
console.error("Error response:", errorText);
throw new Error(
`Failed to update handle: ${response.status} ${response.statusText}`
);
}
await fetchUsers(); // Refresh the user list after successful update
} catch (err) {
console.error("Update handle error:", err);
setError(err instanceof Error ? err.message : "Failed to update handle");
} finally {
setLoading(false);
}
};
useEffect(() => {
async function checkSettings() {
try {
@ -304,6 +359,69 @@ export default function UserList() {
</button>
</div>
{/* Edit Handle Modal */}
{editModal.show && editModal.user && (
<dialog className="modal modal-open">
<div className="modal-box">
<h3 className="font-bold text-lg">Edit Handle</h3>
<p className="py-4">
Update handle for{" "}
<span className="font-semibold">
{editModal.user.displayName || "Anonymous"}
</span>.
<br />
<br />
<span className="font-bold">**Note that you will need a "_atproto" TXT record with the corresponding "did=SOME_DID_NUMBER" before changing your handle to a subdomain of your PDS domain.</span>
</p>
<div className="form-control">
<label className="label">
<span className="label-text">New Handle</span>
</label>
<input
type="text"
placeholder="new.handle.pds.domain"
className="input input-bordered"
value={editModal.newHandle}
onChange={(e) =>
setEditModal({ ...editModal, newHandle: e.target.value })
}
/>
</div>
<div className="modal-action">
<button
className="btn"
onClick={() =>
setEditModal({ show: false, user: null, newHandle: "" })
}
>
Cancel
</button>
<button
className="btn btn-primary"
onClick={async () => {
if (editModal.user && editModal.newHandle) {
await updateUserHandle(editModal.user.did, editModal.newHandle);
setEditModal({ show: false, user: null, newHandle: "" });
}
}}
disabled={!editModal.newHandle}
>
Update Handle
</button>
</div>
</div>
<form method="dialog" className="modal-backdrop">
<button
onClick={() =>
setEditModal({ show: false, user: null, newHandle: "" })
}
>
close
</button>
</form>
</dialog>
)}
{/* Confirmation Modal */}
{deleteConfirmation.show && deleteConfirmation.user && (
<dialog className="modal modal-open">
@ -396,6 +514,9 @@ export default function UserList() {
<h2 className="text-lg font-semibold">
{user.displayName || "Anonymous"}
</h2>
<div className="font-mono text-sm opacity-70 mt-1">
{user.handle}
</div>
<div className="font-mono text-sm opacity-70 mt-1">
{user.did}
</div>
@ -405,11 +526,21 @@ export default function UserList() {
</p>
)}
</div>
<div className="flex flex-col gap-2">
<button
onClick={() =>
setDeleteConfirmation({ show: true, user })
}
onClick={() => setEditModal({
show: true,
user,
newHandle: user.handle || ""
})}
className="btn btn-sm btn-primary"
disabled={loading}
>
Edit
</button>
<button
onClick={() => setDeleteConfirmation({ show: true, user })}
className="btn btn-sm btn-error"
disabled={loading}
>

View file