This commit is contained in:
parent
622bf8eb0d
commit
45267c7e4e
6 changed files with 37 additions and 51 deletions
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "pdsmanager",
|
||||
"type": "module",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
|
|
|
@ -57,8 +57,8 @@ export default function AuthWrapper() {
|
|||
<RefreshContext.Provider value={{ refresh, lastUpdate }}>
|
||||
<div className="w-full flex flex-col">
|
||||
<Header />
|
||||
<div className="min-h-[calc(100vh-64px)] p-4">
|
||||
<div className="container mx-auto">
|
||||
<div className="min-h-[calc(100vh-64px)] p-2 sm:p-4">
|
||||
<div className="container mx-auto max-w-full">
|
||||
<TabView />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -185,12 +185,12 @@ export default function InviteCodes() {
|
|||
|
||||
return (
|
||||
<div className="card bg-base-100 shadow-xl">
|
||||
<div className="card-body">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<h1 className="card-title text-2xl">Invite Codes</h1>
|
||||
<div className="card-body p-2 sm:p-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-2 sm:gap-4 mb-4">
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-2 sm:gap-4">
|
||||
<h1 className="card-title text-xl sm:text-2xl">Invite Codes</h1>
|
||||
<label className="cursor-pointer label gap-2">
|
||||
<span className="label-text">Show Disabled Codes</span>
|
||||
<span className="label-text">Show Disabled</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="toggle toggle-sm toggle-primary"
|
||||
|
@ -202,7 +202,7 @@ export default function InviteCodes() {
|
|||
<button
|
||||
onClick={createCode}
|
||||
disabled={loading}
|
||||
className="btn btn-primary"
|
||||
className="btn btn-primary w-full sm:w-auto"
|
||||
>
|
||||
{loading ? (
|
||||
<span className="loading loading-spinner loading-sm"></span>
|
||||
|
@ -249,21 +249,18 @@ export default function InviteCodes() {
|
|||
className={`card ${code.disabled ? "bg-base-300 opacity-75" : "bg-base-200"
|
||||
} hover:shadow-md transition-shadow`}
|
||||
>
|
||||
<div className="card-body">
|
||||
<div className="flex justify-between items-start">
|
||||
<div
|
||||
className={`font-mono text-lg bg-base-100 p-3 rounded-box select-all flex-1 mr-4 ${code.disabled ? "opacity-50" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="card-body p-3 sm:p-6">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start gap-4">
|
||||
<div className="font-mono text-base sm:text-lg bg-base-100 p-2 sm:p-3 rounded-box select-all w-full sm:flex-1 break-all">
|
||||
{code.code}
|
||||
</div>
|
||||
<div className="flex flex-col items-end gap-2">
|
||||
<div className="flex flex-row sm:flex-col items-center sm:items-end gap-2 w-full sm:w-auto">
|
||||
{code.disabled ? (
|
||||
<span className="badge badge-error">Disabled</span>
|
||||
<span className="badge badge-error w-full sm:w-auto justify-center">Disabled</span>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => disableCode(code.code)}
|
||||
className="btn btn-sm btn-warning"
|
||||
className="btn btn-sm btn-warning w-full sm:w-auto"
|
||||
title="Disable code"
|
||||
>
|
||||
Disable
|
||||
|
@ -271,7 +268,7 @@ export default function InviteCodes() {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-4 mt-2 text-sm">
|
||||
<div className="flex flex-wrap gap-2 mt-2 text-sm">
|
||||
{!code.disabled && (
|
||||
<div className="badge badge-neutral">
|
||||
Uses: {code.uses.length} / {code.available}
|
||||
|
@ -282,16 +279,12 @@ export default function InviteCodes() {
|
|||
</div>
|
||||
{code.uses.length > 0 && (
|
||||
<div className="badge badge-info">
|
||||
{code.uses.length}{" "}
|
||||
{code.uses.length === 1 ? "use" : "uses"}
|
||||
{code.uses.length} {code.uses.length === 1 ? "use" : "uses"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{code.uses.length > 0 && (
|
||||
<div
|
||||
className={`text-sm mt-2 ${code.disabled ? "opacity-75" : "opacity-70"
|
||||
}`}
|
||||
>
|
||||
<div className="text-sm mt-2 break-all">
|
||||
<span className="font-semibold">Used by:</span>{" "}
|
||||
{code.uses.map((use) => use.usedBy).join(", ")}
|
||||
</div>
|
||||
|
@ -299,11 +292,9 @@ export default function InviteCodes() {
|
|||
</div>
|
||||
</div>
|
||||
))}
|
||||
{!loading && codes.length === 0 && (
|
||||
{!loading && filterAndSortCodes(codes).length === 0 && (
|
||||
<div className="text-center p-8 bg-base-200 rounded-box">
|
||||
<div className="text-base-content/70">
|
||||
No invite codes found
|
||||
</div>
|
||||
<div className="text-base-content/70">No invite codes found</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -120,7 +120,6 @@ export default function UserList() {
|
|||
"Content-Type": "application/json",
|
||||
};
|
||||
|
||||
// First get the account info which includes email
|
||||
const accountResponse = await fetch(
|
||||
`${baseUrl}/xrpc/com.atproto.admin.getAccountInfo?did=${did}`,
|
||||
{ headers }
|
||||
|
@ -132,7 +131,6 @@ export default function UserList() {
|
|||
|
||||
const accountData = await accountResponse.json();
|
||||
|
||||
// Then get the profile data as before
|
||||
const profileResponse = await fetch(
|
||||
`${baseUrl}/xrpc/com.atproto.repo.getRecord?collection=app.bsky.actor.profile&repo=${did}&rkey=self`,
|
||||
{ headers }
|
||||
|
@ -146,7 +144,7 @@ export default function UserList() {
|
|||
|
||||
return {
|
||||
did,
|
||||
email: accountData.email, // Add email from account info
|
||||
email: accountData.email,
|
||||
handle: profileData.value.handle,
|
||||
displayName: profileData.value.displayName,
|
||||
description: profileData.value.description,
|
||||
|
@ -284,7 +282,7 @@ export default function UserList() {
|
|||
);
|
||||
}
|
||||
|
||||
await fetchUsers(); // Refresh the user list after successful update
|
||||
await fetchUsers();
|
||||
} catch (err) {
|
||||
console.error("Update handle error:", err);
|
||||
setError(err instanceof Error ? err.message : "Failed to update handle");
|
||||
|
@ -418,7 +416,7 @@ export default function UserList() {
|
|||
if (!settingsLoaded) {
|
||||
return (
|
||||
<div className="card bg-base-100 shadow-xl">
|
||||
<div className="card-body">
|
||||
<div className="card-body p-2 sm:p-8">
|
||||
<div className="flex justify-center p-8">
|
||||
<span className="loading loading-spinner loading-lg"></span>
|
||||
</div>
|
||||
|
@ -430,7 +428,7 @@ export default function UserList() {
|
|||
if (!hasValidSettings) {
|
||||
return (
|
||||
<div className="card bg-base-100 shadow-xl">
|
||||
<div className="card-body">
|
||||
<div className="card-body p-2 sm:p-8">
|
||||
<div className="alert alert-warning">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -459,13 +457,13 @@ export default function UserList() {
|
|||
|
||||
return (
|
||||
<div className="card bg-base-100 shadow-xl">
|
||||
<div className="card-body">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h1 className="card-title text-2xl">Users</h1>
|
||||
<div className="card-body p-2 sm:p-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-2 sm:gap-4 mb-4">
|
||||
<h1 className="card-title text-xl sm:text-2xl">Users</h1>
|
||||
<button
|
||||
onClick={() => fetchUsers()}
|
||||
disabled={loading}
|
||||
className="btn btn-primary"
|
||||
className="btn btn-primary w-full sm:w-auto"
|
||||
>
|
||||
{loading ? (
|
||||
<span className="loading loading-spinner loading-sm"></span>
|
||||
|
@ -708,17 +706,17 @@ export default function UserList() {
|
|||
key={user.did}
|
||||
className="card bg-base-200 hover:shadow-md transition-shadow"
|
||||
>
|
||||
<div className="card-body">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="card-body p-3 sm:p-6">
|
||||
<div className="flex flex-col sm:flex-row items-start gap-4">
|
||||
<UserAvatar user={user} />
|
||||
<div className="flex-1">
|
||||
<h2 className="text-lg font-semibold">
|
||||
<div className="flex-1 w-full">
|
||||
<h2 className="text-lg font-semibold break-all">
|
||||
{user.displayName || "Anonymous"}
|
||||
</h2>
|
||||
<div className="font-mono text-sm opacity-70 mt-1">
|
||||
<div className="font-mono text-sm opacity-70 mt-1 break-all">
|
||||
{user.handle}
|
||||
</div>
|
||||
<div className="font-mono text-sm opacity-70 mt-1">
|
||||
<div className="font-mono text-sm opacity-70 mt-1 break-all">
|
||||
{user.did}
|
||||
</div>
|
||||
{user.description && (
|
||||
|
@ -727,8 +725,7 @@ export default function UserList() {
|
|||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="grid grid-cols-2 sm:grid-cols-1 gap-2 mt-4 sm:mt-0">
|
||||
<button
|
||||
onClick={() => setEditModal({
|
||||
show: true,
|
||||
|
@ -793,4 +790,5 @@ export default function UserList() {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import Footer from "../components/navigation/Footer.astro";
|
|||
<html data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link
|
||||
rel="icon"
|
||||
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🦋</text></svg>"
|
||||
|
|
|
@ -26,7 +26,6 @@ export class Settings {
|
|||
);
|
||||
resolve(key);
|
||||
} else {
|
||||
// Generate new key if none exists
|
||||
const key = await window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
|
@ -36,13 +35,11 @@ export class Settings {
|
|||
["encrypt", "decrypt"],
|
||||
);
|
||||
|
||||
// Export and store the key
|
||||
const exportedKey = await window.crypto.subtle.exportKey(
|
||||
"raw",
|
||||
key,
|
||||
);
|
||||
|
||||
// Create a new transaction for storing the key
|
||||
const newTransaction = db.transaction(this.STORE_NAME, "readwrite");
|
||||
const newStore = newTransaction.objectStore(this.STORE_NAME);
|
||||
newStore.put(exportedKey, this.ENCRYPTION_KEY_NAME);
|
||||
|
|
Loading…
Add table
Reference in a new issue