new ui using the options page

This commit is contained in:
kawamataryo
2024-11-02 11:32:34 +09:00
committed by kawamataryo
parent cb1c8e605a
commit 58ef98fa70
22 changed files with 1003 additions and 221 deletions

View File

@@ -1,8 +1,12 @@
import cssText from "data-text:~style.content.css";
import type { AtpSessionData } from "@atproto/api";
import { sendToBackground } from "@plasmohq/messaging";
import { getPort } from "@plasmohq/messaging/port";
import type { PlasmoCSConfig } from "plasmo";
import React from "react";
import AlertError from "~lib/components/AlertError";
import AlertSuccess from "~lib/components/AlertSuccess";
import LoadingCards from "~lib/components/LoadingCards";
import MatchTypeFilter from "~lib/components/MatchTypeFilter";
import Modal from "~lib/components/Modal";
import UserCard from "~lib/components/UserCard";
@@ -28,40 +32,21 @@ const App = () => {
modalRef,
users,
loading,
handleClickAction,
actionMode,
errorMessage,
restart,
isRateLimitError,
isSucceeded,
matchTypeFilter,
changeMatchTypeFilter,
filteredUsers,
stopRetrieveLoop,
restart,
isBottomReached,
} = useRetrieveBskyUsers();
React.useEffect(() => {
const messageHandler = (
message: {
name: (typeof MESSAGE_NAMES)[keyof typeof MESSAGE_NAMES];
body: {
identifier: string;
password: string;
authFactorToken?: string;
};
},
_sender: chrome.runtime.MessageSender,
sendResponse: (response?: Record<string, unknown>) => void,
) => {
if (Object.values(MESSAGE_NAMES).includes(message.name)) {
initialize({
identifier: message.body.identifier,
password: message.body.password,
messageName: message.name,
...(message.body.authFactorToken && {
authFactorToken: message.body.authFactorToken,
}),
})
initialize()
.then(() => {
sendResponse({ hasError: false });
})
@@ -80,51 +65,67 @@ const App = () => {
};
}, [initialize]);
const openOptionPage = () => {
sendToBackground({ name: "openOptionPage" });
};
const stopAndShowDetectedUsers = async () => {
stopRetrieveLoop();
await chrome.storage.local.set({ users: JSON.stringify(users) });
openOptionPage();
};
return (
<>
<Modal anchorRef={modalRef} onClose={stopRetrieveLoop}>
<div className="flex flex-col gap-6">
<div className="flex justify-between">
<h1 className="text-2xl font-bold">Find Bluesky Users</h1>
<div className="flex gap-3 items-center">
{loading && (
<p className="loading loading-spinner loading-md text-primary" />
)}
<p className="text-sm">Detected:</p>
<p className="font-bold text-xl">{users.length}</p>
<div className="flex flex-col gap-2 items-center">
{loading && (
<p className="text-lg font-bold">
Scanning 𝕏 users to find bsky users...
</p>
)}
<p className="text-2xl font-bold">
Detected <span className="text-4xl">{users.length}</span> users
</p>
{loading && (
<>
<button
type="button"
className="btn btn-primary mt-5 btn-ghost"
onClick={stopAndShowDetectedUsers}
>
Stop Scanning and View Results
</button>
<LoadingCards />
</>
)}
{!loading && !isBottomReached && (
<button
type="button"
className="btn btn-primary mt-5"
onClick={restart}
>
Resume Scanning
</button>
)}
{!loading && isBottomReached && (
<div className="flex flex-col gap-2 items-center">
<button
type="button"
className="btn btn-primary mt-5"
onClick={openOptionPage}
>
View Detected Users
</button>
<button
type="button"
className="btn btn-primary mt-5 btn-ghost"
onClick={restart}
>
Resume Scanning
</button>
</div>
</div>
<MatchTypeFilter
value={matchTypeFilter}
onChange={changeMatchTypeFilter}
/>
{isSucceeded && (
<AlertSuccess>
<span className="font-bold">{users.length}</span> Bluesky accounts
detected.
</AlertSuccess>
)}
{errorMessage && (
<AlertError retryAction={isRateLimitError ? restart : undefined}>
{errorMessage}
</AlertError>
)}
<div className="flex flex-col gap-4 overflow-scroll max-h-[60vh]">
{filteredUsers.length > 0 ? (
<div className="">
{filteredUsers.map((user) => (
<UserCard
key={user.handle}
user={user}
clickAction={handleClickAction}
actionMode={actionMode}
/>
))}
</div>
) : (
loading && <UserCardSkeleton />
)}
</div>
</div>
</Modal>
</>