🐛 fixed unnecessary permission requests

This commit is contained in:
kawamataryo 2024-01-24 19:59:09 +09:00
parent c94ad748e2
commit fa98592205
7 changed files with 0 additions and 648 deletions

View File

@ -1,90 +0,0 @@
// TODO: Remove this file. This is for legacy code.
// import type { PlasmoCSConfig } from "plasmo";
// import { BskyServiceWorkerClient } from "~lib/bskyServiceWorkerClient";
// import { MESSAGE_NAMES, VIEWER_STATE } from "~lib/constants";
// import { searchAndInsertBskyUsers } from "~lib/searchAndInsertBskyUsers";
// import { type BskyLoginParams } from "../lib/bskyClient";
// import "../style.content.legacy.css";
// export const config: PlasmoCSConfig = {
// matches: ["https://twitter.com/*", "https://x.com/*"],
// all_frames: true,
// };
// const searchAndShowBskyUsers = async ({
// identifier,
// password,
// messageName,
// }: BskyLoginParams & { messageName: string }) => {
// const agent = await BskyServiceWorkerClient.createAgent({
// identifier,
// password,
// });
// switch (messageName) {
// case MESSAGE_NAMES.SEARCH_BSKY_USER_ON_FOLLOW_PAGE:
// await searchAndInsertBskyUsers({
// agent,
// btnLabel: {
// add: "Follow",
// remove: "Unfollow",
// progressive: "Following",
// },
// statusKey: VIEWER_STATE.FOLLOWING,
// userCellQueryParam:
// '[data-testid="primaryColumn"] [data-testid="UserCell"]',
// addQuery: async (arg: string) => await agent.follow(arg),
// removeQuery: async (arg: string) => await agent.unfollow(arg),
// });
// break;
// case MESSAGE_NAMES.SEARCH_BSKY_USER_ON_LIST_MEMBERS_PAGE:
// await searchAndInsertBskyUsers({
// agent,
// btnLabel: {
// add: "Follow",
// remove: "Unfollow",
// progressive: "Following",
// },
// statusKey: VIEWER_STATE.FOLLOWING,
// userCellQueryParam:
// '[data-testid="cellInnerDiv"] [data-testid="UserCell"]',
// addQuery: async (arg: string) => await agent.follow(arg),
// removeQuery: async (arg: string) => await agent.unfollow(arg),
// });
// break;
// case MESSAGE_NAMES.SEARCH_BSKY_USER_ON_BLOCK_PAGE:
// // TODO: If already blocked, don't show blocking state. because blocking user can't find.
// await searchAndInsertBskyUsers({
// agent,
// btnLabel: {
// add: "Block",
// remove: "Unblock",
// progressive: "Blocking",
// },
// statusKey: VIEWER_STATE.BLOCKING,
// userCellQueryParam: '[data-testid="UserCell"]',
// addQuery: async (arg: string) => await agent.block(arg),
// removeQuery: async (arg: string) => await agent.unblock(arg),
// });
// break;
// }
// };
// chrome.runtime.onMessage.addListener((message, _, sendResponse) => {
// if (Object.values(MESSAGE_NAMES).includes(message.name)) {
// searchAndShowBskyUsers({
// identifier: message.body.userId,
// password: message.body.password,
// messageName: message.name,
// })
// .then(() => {
// sendResponse({ hasError: false });
// })
// .catch((e) => {
// console.error(e);
// sendResponse({ hasError: true, message: e.toString() });
// });
// return true;
// }
// return false;
// });

View File

@ -1,209 +0,0 @@
import type {
ProfileView,
ViewerState,
} from "@atproto/api/dist/client/types/app/bsky/actor/defs";
import { P, match } from "ts-pattern";
import van from "vanjs-core";
import { BSKY_USER_MATCH_TYPE } from "~lib/constants";
const { a, div, p, img, button, span } = van.tags;
const { svg, path } = van.tagsNS("http://www.w3.org/2000/svg");
export type UserCellBtnLabel = {
add: string;
remove: string;
progressive: string;
};
const ActionButton = ({
statusKey,
profile,
btnLabel,
addAction,
removeAction,
}: {
profile: ProfileView;
statusKey: keyof ViewerState;
btnLabel: UserCellBtnLabel;
addAction: () => Promise<void>;
removeAction: () => Promise<void>;
}) => {
const label = van.state(
`${
profile.viewer[statusKey] ? btnLabel.progressive : btnLabel.add
} on Bluesky`,
);
const isStateOfBeing = van.state(profile.viewer[statusKey]);
const isProcessing = van.state(false);
const isJustApplied = van.state(false);
const beingClass = van.derive(() =>
isStateOfBeing.val ? "action-button__being" : "",
);
const processingClass = van.derive(() =>
isProcessing.val ? "action-button__processing" : "",
);
const justAppliedClass = van.derive(() =>
isJustApplied.val ? "action-button__just-applied" : "",
);
const onClick = async () => {
if (isProcessing.val) return;
isProcessing.val = true;
label.val = "Processing...";
if (isStateOfBeing.val) {
await removeAction();
label.val = `${btnLabel.add} on Bluesky`;
isStateOfBeing.val = false;
} else {
await addAction();
label.val = `${btnLabel.progressive} on Bluesky`;
isStateOfBeing.val = true;
isJustApplied.val = true;
}
isProcessing.val = false;
};
const onMouseover = () => {
if (isProcessing.val || isJustApplied.val || !isStateOfBeing.val) return;
label.val = `${btnLabel.remove} on Bluesky`;
};
const onMouseout = () => {
if (isJustApplied.val) {
isJustApplied.val = false;
}
if (!isStateOfBeing.val) return;
label.val = `${btnLabel.progressive} on Bluesky`;
};
return button(
{
class: () =>
`action-button ${beingClass.val} ${processingClass.val} ${justAppliedClass.val}`,
onclick: onClick,
onmouseover: onMouseover,
onmouseout: onMouseout,
},
() => label.val,
);
};
const Avatar = ({ avatar }: { avatar?: string }) => {
return avatar
? img({ src: avatar, width: "40" })
: div({ class: "no-avatar" });
};
const MatchTypeLabel = ({
matchType,
}: {
matchType: (typeof BSKY_USER_MATCH_TYPE)[keyof typeof BSKY_USER_MATCH_TYPE];
}) => {
const [text, labelClass] = match(matchType)
.with(BSKY_USER_MATCH_TYPE.HANDLE, () => [
"Same handle name",
"match-type__handle",
])
.with(BSKY_USER_MATCH_TYPE.DISPLAY_NAME, () => [
"Same display name",
"match-type__display-name",
])
.with(BSKY_USER_MATCH_TYPE.DESCRIPTION, () => [
"Included handle name in description",
"match-type__description",
])
.run();
return div(
{ class: `match-type ${labelClass}` },
svg(
{
fill: "none",
width: "12",
viewBox: "0 0 24 24",
"stroke-width": "3",
stroke: "currentColor",
class: "w-6 h-6",
},
path({
"stroke-linecap": "round",
"stroke-linejoin": "round",
d: "M4.5 12.75l6 6 9-13.5",
}),
),
text,
);
};
export const BskyUserCell = ({
profile,
statusKey,
btnLabel,
matchType,
addAction,
removeAction,
}: {
profile: ProfileView;
statusKey: keyof ViewerState;
btnLabel: UserCellBtnLabel;
matchType: (typeof BSKY_USER_MATCH_TYPE)[keyof typeof BSKY_USER_MATCH_TYPE];
addAction: () => Promise<void>;
removeAction: () => Promise<void>;
}) => {
return div(
{ class: "bsky-user-content-wrapper" },
MatchTypeLabel({ matchType }),
div(
{ class: "bsky-user-content bsky-fade-in" },
div(
{ class: "icon-section" },
a(
{
href: `https://bsky.app/profile/${profile.handle}`,
target: "_blank",
rel: "noopener",
},
Avatar({ avatar: profile.avatar }),
),
),
div(
{ class: "content" },
div(
{ class: "name-and-controller" },
div(
p(
{ class: "display-name" },
a(
{
href: `https://bsky.app/profile/${profile.handle}`,
target: "_blank",
rel: "noopener",
},
profile.displayName ?? profile.handle,
),
),
p({ class: "handle" }, `@${profile.handle}`),
),
div(
ActionButton({
profile,
statusKey,
btnLabel,
addAction,
removeAction,
}),
),
),
profile.description
? p({ class: "description" }, profile.description)
: "",
),
),
);
};

View File

@ -1,35 +0,0 @@
import van from "vanjs-core";
const { div, p } = van.tags;
const { svg, path } = van.tagsNS("http://www.w3.org/2000/svg");
const WarningIcon = () =>
svg(
{
fill: "none",
"stroke-width": "1.5",
stroke: "currentColor",
class: "w-6 h-6",
viewBox: "0 0 24 24",
},
path({
"stroke-linecap": "round",
"stroke-linejoin": "round",
d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z",
}),
);
export const NotFoundCell = () =>
div(
{ class: "bsky-user-content-wrapper" },
div(
{ class: "bsky-user-content bsky-user-content__not-found bsky-fade-in" },
WarningIcon(),
p(
{
class: "not-found",
},
"No similar users found.",
),
),
);

View File

@ -1,24 +0,0 @@
import van from "vanjs-core";
const { button, div } = van.tags;
export const ReloadButton = ({ clickAction }: { clickAction: () => void }) => {
const deleted = van.state(false);
return () =>
deleted.val
? null
: div(
{ class: "bsky-reload-btn-wrapper" },
button(
{
class: "bsky-reload-btn bsky-fade-in",
onclick: () => {
clickAction();
deleted.val = true;
},
},
"Find More",
),
);
};

View File

@ -1,13 +1,3 @@
import type {
ProfileView,
ViewerState,
} from "@atproto/api/dist/client/types/app/bsky/actor/defs";
import van from "vanjs-core";
import { BskyUserCell, type UserCellBtnLabel } from "./components/BskyUserCell";
import { NotFoundCell } from "./components/NotFoundCell";
import { ReloadButton } from "./components/ReloadBtn";
import type { BSKY_USER_MATCH_TYPE } from "./constants";
export const getUserCells = ({
queryParam,
filterInsertedElement,
@ -29,20 +19,6 @@ export const getUserCells = ({
return Array.from(userCells);
};
export const insertReloadEl = (clickAction: () => void) => {
const lastInsertedEl = Array.from(
document.querySelectorAll(".bsky-user-content"),
).at(-1);
van.add(lastInsertedEl.parentElement, ReloadButton({ clickAction }));
};
export const removeReloadEl = () => {
const reloadEl = document.querySelectorAll(".bsky-reload-btn-wrapper");
for (const el of reloadEl) {
el.remove();
}
};
export const getAccountNameAndDisplayName = (userCell: Element) => {
const [avatarEl, displayNameEl] = userCell.querySelectorAll("a");
const twAccountName = avatarEl?.getAttribute("href")?.replace("/", "");
@ -50,42 +26,3 @@ export const getAccountNameAndDisplayName = (userCell: Element) => {
const twDisplayName = displayNameEl?.textContent;
return { twAccountName, twDisplayName, twAccountNameRemoveUnderscore };
};
export const insertBskyProfileEl = ({
dom,
profile,
statusKey,
btnLabel,
matchType,
addAction,
removeAction,
}: {
dom: Element;
profile: ProfileView;
statusKey: keyof ViewerState;
btnLabel: UserCellBtnLabel;
matchType: (typeof BSKY_USER_MATCH_TYPE)[keyof typeof BSKY_USER_MATCH_TYPE];
addAction: () => Promise<void>;
removeAction: () => Promise<void>;
}) => {
van.add(
dom.parentElement,
BskyUserCell({
profile,
statusKey,
btnLabel,
matchType,
addAction,
removeAction,
}),
);
};
export const insertNotFoundEl = (dom: Element) => {
van.add(dom.parentElement, NotFoundCell());
};
export const isOutOfTopViewport = (el: Element) => {
const rect = el.getBoundingClientRect();
return rect.top < 0;
};

View File

@ -1,142 +0,0 @@
import type { ViewerState } from "@atproto/api/dist/client/types/app/bsky/actor/defs";
import { isSimilarUser } from "~lib/bskyHelpers";
import {
getAccountNameAndDisplayName,
getUserCells,
insertBskyProfileEl,
insertNotFoundEl,
insertReloadEl,
} from "~lib/domHelpers";
import { debugLog, isOneSymbol } from "~lib/utils";
import type { BskyClient } from "./bskyClient";
import type { BskyServiceWorkerClient } from "./bskyServiceWorkerClient";
import type { UserCellBtnLabel } from "./components/BskyUserCell";
import { isOutOfTopViewport, removeReloadEl } from "./domHelpers";
const notFoundUserCache = new Set<string>();
const bskyUserUrlMap = new Map<string, string>();
export const searchAndInsertBskyUsers = async ({
agent,
btnLabel,
userCellQueryParam,
statusKey,
addQuery,
removeQuery,
}: {
agent: BskyServiceWorkerClient | BskyClient;
userCellQueryParam: string;
btnLabel: UserCellBtnLabel;
statusKey: keyof ViewerState;
// biome-ignore lint:
addQuery: (arg: string) => Promise<any>;
// biome-ignore lint:
removeQuery: (arg: string) => Promise<any>;
}) => {
removeReloadEl();
const userCells = getUserCells({
queryParam: userCellQueryParam,
filterInsertedElement: true,
});
debugLog(`userCells length: ${userCells.length}`);
let index = 0;
// loop over twitter user profile cells and search and insert bsky user
for (const userCell of userCells) {
if (isOutOfTopViewport(userCell)) {
continue;
}
const { twAccountName, twDisplayName, twAccountNameRemoveUnderscore } =
getAccountNameAndDisplayName(userCell);
if (notFoundUserCache.has(twAccountName)) {
insertNotFoundEl(userCell);
continue;
}
const searchTerms = [twAccountNameRemoveUnderscore, twDisplayName];
let targetAccount = null;
let matchType = null;
// Loop over search parameters and break if a user is found
searchLoop: for (const term of searchTerms) {
// one symbol is not a valid search term for bsky
if (!term || isOneSymbol(term)) {
continue;
}
try {
const searchResults = await agent.searchUser({
term: term,
limit: 3,
});
for (const searchResult of searchResults) {
const { isSimilar: isUserFound, type } = isSimilarUser(
{
accountName: twAccountName,
accountNameRemoveUnderscore: twAccountNameRemoveUnderscore,
displayName: twDisplayName,
},
searchResult,
);
if (isUserFound) {
targetAccount = searchResult;
matchType = type;
break searchLoop; // Stop searching when a user is found
}
}
} catch (e) {
console.error(e);
}
}
// insert bsky profile or not found element
if (targetAccount) {
insertBskyProfileEl({
dom: userCell,
profile: targetAccount,
statusKey,
btnLabel,
matchType,
addAction: async () => {
const result = await addQuery(targetAccount.did);
bskyUserUrlMap.set(targetAccount.did, result.uri);
},
removeAction: async () => {
if (targetAccount?.viewer?.following) {
await removeQuery(targetAccount?.viewer?.following);
} else {
await removeQuery(bskyUserUrlMap.get(targetAccount.did));
}
},
});
} else {
insertNotFoundEl(userCell);
notFoundUserCache.add(twAccountName);
}
index++;
if (process.env.NODE_ENV === "development" && index > 5) {
break;
}
}
// TODO: if there are more users, insert reload button
insertReloadEl(async () => {
await searchAndInsertBskyUsers({
agent,
btnLabel,
userCellQueryParam,
statusKey,
addQuery,
removeQuery,
});
});
};

View File

@ -3,9 +3,6 @@ import { isSimilarUser } from "~lib/bskyHelpers";
import {
getAccountNameAndDisplayName,
getUserCells,
insertBskyProfileEl,
insertNotFoundEl,
insertReloadEl,
} from "~lib/domHelpers";
import { debugLog, isOneSymbol } from "~lib/utils";
import type { BskyClient } from "./bskyClient";
@ -63,85 +60,3 @@ export const searchBskyUser = async ({
return null;
};
export const searchBskyUsers = async ({
agent,
userCellQueryParam,
}: {
agent: BskyServiceWorkerClient | BskyClient;
userCellQueryParam: string;
}) => {
const userCells = getUserCells({
queryParam: userCellQueryParam,
filterInsertedElement: true,
});
debugLog(`userCells length: ${userCells.length}`);
let index = 0;
const targetAccounts = [] as ProfileView[];
// loop over twitter user profile cells and search and insert bsky user
for (const userCell of userCells) {
const { twAccountName, twDisplayName, twAccountNameRemoveUnderscore } =
getAccountNameAndDisplayName(userCell);
if (notFoundUserCache.has(twAccountName)) {
insertNotFoundEl(userCell);
continue;
}
const searchTerms = [twAccountNameRemoveUnderscore, twDisplayName];
let targetAccount = null;
let matchType = null;
// Loop over search parameters and break if a user is found
searchLoop: for (const term of searchTerms) {
// one symbol is not a valid search term for bsky
if (!term || isOneSymbol(term)) {
continue;
}
try {
const searchResults = await agent.searchUser({
term: term,
limit: 3,
});
for (const searchResult of searchResults) {
const { isSimilar: isUserFound, type } = isSimilarUser(
{
accountName: twAccountName,
accountNameRemoveUnderscore: twAccountNameRemoveUnderscore,
displayName: twDisplayName,
},
searchResult,
);
if (isUserFound) {
targetAccount = searchResult;
matchType = type;
break searchLoop; // Stop searching when a user is found
}
}
} catch (e) {
console.error(e);
}
}
// insert bsky profile or not found element
if (targetAccount) {
targetAccounts.push(targetAccount);
} else {
notFoundUserCache.add(twAccountName);
}
index++;
// if (process.env.NODE_ENV === "development" && index > 5) {
// break
// }
}
return targetAccounts;
};