diff --git a/src/background/messages/addUserToList.ts b/src/background/messages/addUserToList.ts new file mode 100644 index 0000000..9a40767 --- /dev/null +++ b/src/background/messages/addUserToList.ts @@ -0,0 +1,21 @@ +import type { PlasmoMessaging } from "@plasmohq/messaging"; +import { BskyClient } from "~lib/bskyClient"; + +const handler: PlasmoMessaging.MessageHandler = async (req, res) => { + const { session, userDid, listUri } = req.body; + const client = await BskyClient.createAgentFromSession(session); + + try { + res.send({ + result: await client.addUserToList({ userDid, listUri }), + }); + } catch (e) { + res.send({ + error: { + message: e.message, + }, + }); + } +}; + +export default handler; \ No newline at end of file diff --git a/src/background/messages/createList.ts b/src/background/messages/createList.ts new file mode 100644 index 0000000..3a9bc83 --- /dev/null +++ b/src/background/messages/createList.ts @@ -0,0 +1,21 @@ +import type { PlasmoMessaging } from "@plasmohq/messaging"; +import { BskyClient } from "~lib/bskyClient"; + +const handler: PlasmoMessaging.MessageHandler = async (req, res) => { + const { session, name, description } = req.body; + const client = await BskyClient.createAgentFromSession(session); + + try { + res.send({ + uri: await client.createList({ name, description }), + }); + } catch (e) { + res.send({ + error: { + message: e.message, + }, + }); + } +}; + +export default handler; \ No newline at end of file diff --git a/src/background/messages/createListAndAddUsers.ts b/src/background/messages/createListAndAddUsers.ts new file mode 100644 index 0000000..239cf2a --- /dev/null +++ b/src/background/messages/createListAndAddUsers.ts @@ -0,0 +1,33 @@ +import type { PlasmoMessaging } from "@plasmohq/messaging"; +import { BskyClient } from "~lib/bskyClient"; +import { STORAGE_KEYS } from "~lib/constants"; + +const handler: PlasmoMessaging.MessageHandler = async (req, res) => { + const { name, description, userDids } = req.body; + + const storage = await chrome.storage.local.get(STORAGE_KEYS.BSKY_CLIENT_SESSION); + const session = storage[STORAGE_KEYS.BSKY_CLIENT_SESSION]; + + if (!session || !session.did) { + res.send({ + error: { + message: "Invalid session data", + }, + }); + return; + } + + try { + const client = await BskyClient.createAgentFromSession(session); + await client.createListAndAddUsers({ name, description, userDids }); + res.send({ success: true }); + } catch (e) { + res.send({ + error: { + message: e.message, + }, + }); + } +}; + +export default handler; \ No newline at end of file diff --git a/src/contents/App.tsx b/src/contents/App.tsx index 7e3fda4..9baf64a 100644 --- a/src/contents/App.tsx +++ b/src/contents/App.tsx @@ -30,6 +30,7 @@ const App = () => { restart, isBottomReached, errorMessage, + listName, } = useRetrieveBskyUsers(); React.useEffect(() => { @@ -66,7 +67,7 @@ const App = () => { const stopAndShowDetectedUsers = async () => { stopRetrieveLoop(); - await chrome.storage.local.set({ users: JSON.stringify(users) }); + await chrome.storage.local.set({ users: JSON.stringify(users), listName: listName }); openOptionPage(); }; diff --git a/src/lib/bskyClient.ts b/src/lib/bskyClient.ts index e3a9195..8e3c627 100644 --- a/src/lib/bskyClient.ts +++ b/src/lib/bskyClient.ts @@ -114,4 +114,59 @@ export class BskyClient { rkey, }); }; -} + + public createList = async ({ + name, + description, + }: { + name: string; + description: string; + }) => { + const result = await this.agent.com.atproto.repo.createRecord({ + repo: this.me.did, + collection: 'app.bsky.graph.list', + record: { + $type: 'app.bsky.graph.list', + purpose: 'app.bsky.graph.defs#curatelist', + name, + description, + createdAt: new Date().toISOString() + } + }); + return result.data.uri; + }; + + public addUserToList = async ({ + userDid, + listUri, + }: { + userDid: string; + listUri: string; + }) => { + return await this.agent.com.atproto.repo.createRecord({ + repo: this.me.did, + collection: 'app.bsky.graph.listitem', + record: { + $type: 'app.bsky.graph.listitem', + subject: userDid, + list: listUri, + createdAt: new Date().toISOString() + } + }); + }; + + public createListAndAddUsers = async ({ + name, + description, + userDids, + }: { + name: string; + description: string; + userDids: string[]; + }) => { + const listUri = await this.createList({ name, description }); + for (const userDid of userDids) { + await this.addUserToList({ userDid, listUri }); + } + }; +} \ No newline at end of file diff --git a/src/lib/bskyServiceWorkerClient.ts b/src/lib/bskyServiceWorkerClient.ts index 6a72c15..1cb7ede 100644 --- a/src/lib/bskyServiceWorkerClient.ts +++ b/src/lib/bskyServiceWorkerClient.ts @@ -110,4 +110,59 @@ export class BskyServiceWorkerClient { return result; }; + + public createList = async ({ + name, + description, + }: { + name: string; + description: string; + }) => { + const { uri, error } = await sendToBackground({ + name: "createList", + body: { + session: this.session, + name, + description, + }, + }); + if (error) throw new Error(error.message); + + return uri; + }; + + public addUserToList = async ({ + userDid, + listUri, + }: { + userDid: string; + listUri: string; + }) => { + const { result, error } = await sendToBackground({ + name: "addUserToList", + body: { + session: this.session, + userDid, + listUri, + }, + }); + if (error) throw new Error(error.message); + + return result; + }; + + public createListAndAddUsers = async ({ + name, + description, + userDids, + }: { + name: string; + description: string; + userDids: string[]; + }) => { + const listUri = await this.createList({ name, description }); + for (const userDid of userDids) { + await this.addUserToList({ userDid, listUri }); + } + }; } diff --git a/src/lib/components/Sidebar.tsx b/src/lib/components/Sidebar.tsx index 3b36edf..76f862d 100644 --- a/src/lib/components/Sidebar.tsx +++ b/src/lib/components/Sidebar.tsx @@ -25,6 +25,19 @@ const Sidebar = ({ actionMode, matchTypeStats, }: Props) => { + const getActionLabel = () => { + switch (actionMode) { + case ACTION_MODE.FOLLOW: + return "Follow All"; + case ACTION_MODE.BLOCK: + return "Block All"; + case ACTION_MODE.IMPORT_LIST: + return "Import List"; + default: + return ""; + } + }; + return (