diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..77dde72a --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Ran ESLint formatter(--fix) +7fa3b3bb0ed3e493ab4a6dd0a5ff13e185417f02 \ No newline at end of file diff --git a/src/content-scripts/profileScreen.ts b/src/content-scripts/profileScreen.ts index 21db7d20..e0112d13 100644 --- a/src/content-scripts/profileScreen.ts +++ b/src/content-scripts/profileScreen.ts @@ -7,7 +7,7 @@ import { prefersDarkMode } from "../utils/colorPreference"; const processProfilePage = async () => { const username = getGithubUsername(window.location.href); - if (username != null) { + if (username) { const darkMode = prefersDarkMode(document.cookie); if (darkMode) { @@ -25,8 +25,8 @@ const processProfilePage = async () => { chrome.runtime.onMessage.addListener(request => { if (request.message === "GITHUB_URL_CHANGED") { - processProfilePage(); + void processProfilePage(); } }); -processProfilePage(); +void processProfilePage(); diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts index de17f6cf..5873f6bb 100644 --- a/src/hooks/useAuth.ts +++ b/src/hooks/useAuth.ts @@ -2,11 +2,11 @@ import { useEffect, useState } from "react"; import { OPEN_SAUCED_AUTH_TOKEN_KEY, OPEN_SAUCED_SESSION_ENDPOINT } from "../constants"; import { cachedFetch } from "../utils/cache"; -const removeTokenFromStorage = async () => new Promise((resolve, reject) => { - chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY, () => { - resolve(true); - }); +const removeTokenFromStorage = async () => new Promise(resolve => { + chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY, () => { + resolve(true); }); +}); export const useAuth = () => { const [authToken, setAuthToken] = useState(null); @@ -14,32 +14,32 @@ export const useAuth = () => { const [isTokenValid, setIsTokenValid] = useState(null); useEffect(() => { - chrome.storage.sync.get([OPEN_SAUCED_AUTH_TOKEN_KEY], result => { + chrome.storage.sync.get([OPEN_SAUCED_AUTH_TOKEN_KEY], async result => { if (result[OPEN_SAUCED_AUTH_TOKEN_KEY]) { setAuthToken(result[OPEN_SAUCED_AUTH_TOKEN_KEY]); - // get account data - cachedFetch(OPEN_SAUCED_SESSION_ENDPOINT, { - expireInSeconds: 2 * 60 * 60, // 2 hours + const resp = await cachedFetch(OPEN_SAUCED_SESSION_ENDPOINT, { + expireInSeconds: 2 * 60 * 60, headers: { Authorization: `Bearer ${result[OPEN_SAUCED_AUTH_TOKEN_KEY]}`, Accept: "application/json", }, - }).then(async resp => { - if (!resp.ok) { - console.log("error getting user info"); - removeTokenFromStorage().then(() => { - setAuthToken(null); - setUser(null); - setIsTokenValid(false); - }); - } - return resp.json(); - }) - .then(json => { - setUser(json); - setIsTokenValid(true); - }); + }); + + if (!resp?.ok) { + removeTokenFromStorage().then(() => { + setAuthToken(null); + setUser(null); + setIsTokenValid(false); + return null; + }) + .catch(console.error); + } else { + const json = await resp.json(); + + setUser(json); + setIsTokenValid(true); + } } else { setIsTokenValid(false); } diff --git a/src/hooks/useOpensaucedUserCheck.ts b/src/hooks/useOpensaucedUserCheck.ts index 8ea650d9..1f92f195 100644 --- a/src/hooks/useOpensaucedUserCheck.ts +++ b/src/hooks/useOpensaucedUserCheck.ts @@ -7,13 +7,12 @@ export const useOpensaucedUserCheck = () => { const [checkedUser, setCheckedUser] = useState(null); useEffect(() => { - // get active tab chrome.tabs.query({ active: true, currentWindow: true }, async tabs => { if (tabs.length > 0) { const tab = tabs[0]; const username = getGithubUsername(tab.url!); - if (username != null) { + if (username) { setCheckedUser(username); setCurrentTabIsOpensaucedUser(await isOpenSaucedUser(username)); } else { diff --git a/src/pages/home.tsx b/src/pages/home.tsx index a9791e9d..c52940b2 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from "react"; +import { useContext } from "react"; import { HiArrowTopRightOnSquare, HiUserCircle } from "react-icons/hi2"; import { RouteContext } from "../App"; import OpenSaucedLogo from "../assets/opensauced-logo.svg"; @@ -22,14 +22,14 @@ const Home = () => { {user && + {checkedUser} + 's profile + } diff --git a/src/pages/loading.tsx b/src/pages/loading.tsx index 11edb002..b63faca8 100644 --- a/src/pages/loading.tsx +++ b/src/pages/loading.tsx @@ -1,5 +1,3 @@ -import React from "react"; - const Loading = () => (

Loading...

diff --git a/src/pages/profile.tsx b/src/pages/profile.tsx index 1869bbe9..36d50697 100644 --- a/src/pages/profile.tsx +++ b/src/pages/profile.tsx @@ -32,16 +32,16 @@ export const Profile = () => { const [user, setUser] = useState(null); const [userPR, setUserPR] = useState(null); -useEffect(() => { + useEffect(() => { const fetchUserData = async () => { - const [userData, userPRData] = await Promise.all([getUserData(page.props.userName), getUserPRData(page.props.userName)]); + const [userData, userPRData] = await Promise.all([getUserData(page.props.userName), getUserPRData(page.props.userName)]); - setUser(userData); - setUserPR(userPRData); + setUser(userData); + setUserPR(userPRData); }; - fetchUserData(); -}, []); + void fetchUserData(); + }, []); return ( @@ -51,8 +51,8 @@ useEffect(() => { @@ -81,14 +81,14 @@ useEffect(() => {
profile image

-@ -{page.props.userName} + @ + {page.props.userName}

{(user?.linkedin_url || user?.twitter_username) && @@ -117,7 +117,7 @@ useEffect(() => {
} {user?.bio && -{user.bio} + {user.bio} } {user?.blog && @@ -138,7 +138,7 @@ useEffect(() => {

Open Issues

-{user?.open_issues} + {user?.open_issues}

@@ -146,7 +146,7 @@ useEffect(() => {

PRs Made

-{userPR?.meta.itemCount} + {userPR?.meta.itemCount}

@@ -164,27 +164,27 @@ useEffect(() => {
-

Current Interest

+

Current Interest

-
- {user?.interests.split(",").map(interest => ( - - {interestIcon[interest as InterestIconKeys] ?? null} - - {interest} - - ))} -
+
+ {user?.interests.split(",").map(interest => ( + + {interestIcon[interest as InterestIconKeys]} + + {interest} + + ))} +
diff --git a/src/utils/cache.ts b/src/utils/cache.ts index 290a1d98..36677269 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -2,10 +2,10 @@ export const cachedFetch = async ( url: string, options: | number - | (RequestInit & { expireInSeconds: number; forceRefresh?: boolean }) + | (RequestInit & { expireInSeconds?: number; forceRefresh?: boolean }) | undefined, ) => { - let expiry = 5 * 60; // 5 min default + let expiry = 5 * 60; if (typeof options === "number") { expiry = options; @@ -26,24 +26,22 @@ export const cachedFetch = async ( return Promise.resolve(response); } - chrome.storage.local.remove(cacheKey); - chrome.storage.local.remove(`${cacheKey}:ts`); + void chrome.storage.local.remove(cacheKey); + void chrome.storage.local.remove(`${cacheKey}:ts`); } - return fetch(url, options).then(response => { + return fetch(url, options).then(async response => { if (response.status === 200) { const ct = response.headers.get("Content-Type"); - if (ct && ct.match(/(application\/json|text\/.*)/i)) { - response - .clone() - .text() - .then(content => { - chrome.storage.local.set({ [cacheKey]: content }); - chrome.storage.local.set({ [`${cacheKey}:ts`]: Date.now() }); - }); + if (ct?.match(/(application\/json|text\/.*)/i)) { + const content = await response.clone().text(); + + void chrome.storage.local.set({ [cacheKey]: content }); + void chrome.storage.local.set({ [`${cacheKey}:ts`]: Date.now() }); } } return response; - }); + }) +.catch(console.error); }; diff --git a/src/utils/createHtmlElement.ts b/src/utils/createHtmlElement.ts index 523f2805..e1bfaab5 100644 --- a/src/utils/createHtmlElement.ts +++ b/src/utils/createHtmlElement.ts @@ -12,9 +12,9 @@ export function createHtmlElement ( props: ElementProps, ) { const { style, ...nonStyleProps } = props; - const element = Object.assign(document.createElement(nodeName), props); + const element = Object.assign(document.createElement(nodeName), nonStyleProps); - if (style != undefined) { + if (style !== undefined) { Object.entries(style).forEach(([key, value]) => { element.style[key as CssDeclaration] = value; }); diff --git a/src/utils/dom-utils/inviteToOpenSauced.ts b/src/utils/dom-utils/inviteToOpenSauced.ts index 288da434..f63bc36a 100644 --- a/src/utils/dom-utils/inviteToOpenSauced.ts +++ b/src/utils/dom-utils/inviteToOpenSauced.ts @@ -4,15 +4,30 @@ import { InviteToOpenSaucedModal } from "../../content-scripts/components/Invite import { getTwitterUsername, getLinkedInUsername } from "../urlMatchers"; const injectOpenSaucedInviteButton = (username: string) => { - const emailAddress: string | undefined = ( - document.querySelector(`a[href^="mailto:"]`)! - ).href.substr(7); - const twitterUrl: string | undefined = ( - document.querySelector(`a[href*="twitter.com"]`)! - ).href; - const linkedInUrl: string | undefined = ( - document.querySelector(`a[href*="linkedin.com"]`)! - ).href; + const emailAddress: string | undefined = (() => { + const element = document.querySelector(`a[href^="mailto:"]`); + + if (element instanceof HTMLAnchorElement) { + return element.href; + } + return undefined; + })(); + const twitterUrl: string | undefined = (() => { + const element = document.querySelector(`a[href*="twitter.com"]`); + + if (element instanceof HTMLAnchorElement) { + return element.href; + } + return undefined; + })(); + const linkedInUrl: string | undefined = (() => { + const element = document.querySelector(`a[href*="linkedin.com"]`); + + if (element instanceof HTMLAnchorElement) { + return element.href; + } + return undefined; + })(); if (!(emailAddress || twitterUrl || linkedInUrl)) { return; @@ -33,7 +48,7 @@ const injectOpenSaucedInviteButton = (username: string) => { const userBio = document.querySelector(GITHUB_PROFILE_MENU_SELECTOR); - if (!userBio || !userBio.parentNode) { + if (!userBio?.parentNode) { return; } if (userBio.lastChild?.isEqualNode(inviteToOpenSaucedButton)) { diff --git a/src/utils/dom-utils/viewOnOpenSauced.ts b/src/utils/dom-utils/viewOnOpenSauced.ts index c108fa54..c545ebb5 100644 --- a/src/utils/dom-utils/viewOnOpenSauced.ts +++ b/src/utils/dom-utils/viewOnOpenSauced.ts @@ -11,7 +11,7 @@ const injectViewOnOpenSaucedButton = (username: string) => { `${GITHUB_PROFILE_MENU_SELECTOR}, ${GITHUB_PROFILE_EDIT_MENU_SELECTOR}`, ); - if (!userBio || !userBio.parentNode) { + if (!userBio?.parentNode) { return; } if (userBio.lastChild?.isEqualNode(viewOnOpenSaucedButton)) { diff --git a/src/utils/fetchOpenSaucedApiData.ts b/src/utils/fetchOpenSaucedApiData.ts index e3ec0e58..6509d388 100644 --- a/src/utils/fetchOpenSaucedApiData.ts +++ b/src/utils/fetchOpenSaucedApiData.ts @@ -28,25 +28,25 @@ export const checkTokenValidity = async (token: string) => { }; export const getUserData = async (userName: string, forceRefresh: boolean = false) => cachedFetch(`${OPEN_SAUCED_USERS_ENDPOINT}/${userName}`, { - expireInSeconds: 2 * 60 * 60, // 2 hours - forceRefresh, - headers: { Accept: "application/json" }, - }).then(async resp => { - if (!resp.ok) { - console.log("error getting user info"); - } - return resp.json(); - }) - .then(json => json); + expireInSeconds: 2 * 60 * 60, + forceRefresh, + headers: { Accept: "application/json" }, +}).then(async resp => { + if (!resp?.ok) { + console.log("error getting user info"); + } + return resp?.json(); +}) + .then(json => json); export const getUserPRData = async (userName: string, forceRefresh: boolean = false) => cachedFetch(`${OPEN_SAUCED_USERS_ENDPOINT}/${userName}/prs`, { - expireInSeconds: 2 * 60 * 60, // 2 hours - forceRefresh, - headers: { Accept: "application/json" }, - }).then(async resp => { - if (!resp.ok) { - console.log("error getting user PR info"); - } - return resp.json(); - }) - .then(json => json); + expireInSeconds: 2 * 60 * 60, + forceRefresh, + headers: { Accept: "application/json" }, +}).then(async resp => { + if (!resp?.ok) { + console.log("error getting user PR info"); + } + return resp?.json(); +}) + .then(json => json); diff --git a/src/utils/urlMatchers.ts b/src/utils/urlMatchers.ts index c88f5005..c46930c1 100644 --- a/src/utils/urlMatchers.ts +++ b/src/utils/urlMatchers.ts @@ -1,12 +1,12 @@ export const getGithubUsername = (url: string) => { const match = url.match(/github\.com\/([\w.-]+)/); - return match && match[1]; + return match ? match[1] : undefined; }; export const getLinkedInUsername = (url: string) => { const match = url.match( - /(?:https?:\/\/)?(?:www\.)?linkedin\.com\/in\/(?:#!\/)?@?([^\/\?\s]*)/, + /(?:https?:\/\/)?(?:www\.)?linkedin\.com\/in\/(?:#!\/)?@?([^/?\s]*)/, ); return match ? match[1] : undefined; @@ -14,7 +14,7 @@ export const getLinkedInUsername = (url: string) => { export const getTwitterUsername = (url: string) => { const match = url.match( - /(?:https?:\/\/)?(?:www\.)?twitter\.com\/(?:#!\/)?@?([^\/\?\s]*)/, + /(?:https?:\/\/)?(?:www\.)?twitter\.com\/(?:#!\/)?@?([^/?\s]*)/, ); return match ? match[1] : undefined; diff --git a/src/worker/background.ts b/src/worker/background.ts index 13d881b9..2977019d 100644 --- a/src/worker/background.ts +++ b/src/worker/background.ts @@ -3,32 +3,32 @@ import { checkTokenValidity } from "../utils/fetchOpenSaucedApiData"; import setAccessTokenInChromeStorage from "../utils/setAccessToken"; chrome.webRequest.onCompleted.addListener( - details => { - chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); + () => { + void chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); }, { urls: [SUPABASE_LOGOUT_URL] }, ); chrome.tabs.onUpdated.addListener((tabId, changeInfo) => { if (changeInfo.url?.includes("github.com")) { - chrome.tabs.sendMessage(tabId, { message: "GITHUB_URL_CHANGED" }); + void chrome.tabs.sendMessage(tabId, { message: "GITHUB_URL_CHANGED" }); } }); chrome.cookies.onChanged.addListener(async changeInfo => { try { - if (changeInfo.cookie.name != SUPABASE_COOKIE_NAME || changeInfo.cookie.domain != SUPABASE_AUTH_DOMAIN) { - return; -} - if (changeInfo.removed) { - return chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); -} - const isValidToken = await checkTokenValidity(changeInfo.cookie.value); + if (changeInfo.cookie.name !== SUPABASE_COOKIE_NAME || changeInfo.cookie.domain !== SUPABASE_AUTH_DOMAIN) { + return; + } + if (changeInfo.removed) { + return chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); + } + const isValidToken = await checkTokenValidity(changeInfo.cookie.value); - if (!isValidToken) { - return chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); -} - setAccessTokenInChromeStorage(changeInfo.cookie.value); + if (!isValidToken) { + return chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); + } + void setAccessTokenInChromeStorage(changeInfo.cookie.value); } catch (error) { console.error("Error processing cookie update:", error); }