From bd8da66940c1e8fd260b4d1f812833ec259589f7 Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:37:23 +0530 Subject: [PATCH 1/8] Add Logged out indicator after checking for missing user session --- backgroundScript.js | 37 +++++++++++++++++++++++++++++++++++ manifest.json | 3 ++- scripts/main.css | 27 +++++++++++++++++++++++++ scripts/orchestrator.js | 10 ++++++---- scripts/signedOutIndicator.js | 25 +++++++++++++++++++++++ 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 scripts/signedOutIndicator.js diff --git a/backgroundScript.js b/backgroundScript.js index 3ae4c5f..d844a24 100644 --- a/backgroundScript.js +++ b/backgroundScript.js @@ -31,3 +31,40 @@ chrome.runtime.onInstalled.addListener(() => { .then((data) => dataFromAPI = data); // Store the response data in the dataFromAPI variable. }) }) + +/** + * Checks Logged in status for showing indicator on supported pages like github and bitbucket. + * @param websiteUrl + * @returns {Promise} + */ +async function checkLoginStatus(websiteUrl) { + let result = false; + try { + const res = await fetch(`${websiteUrl}/api/auth/session`, {cache: 'no-store'}); + const json = await res.json(); + + if (json.user) { + result = true; + } + } catch (err) { + console.error(err); + } + return result; +} + +/** + * Listener to handle login status check request. + * The api session request only works via extension background script due to the need of auth cookies in request. + */ +chrome.runtime.onMessage.addListener( + function(request, sender, sendResponse) { + const message = request.message?.split(','); + if (message[0] === "check_login_status") { + const websiteUrl = message[1]; + checkLoginStatus(websiteUrl).then(loggedIn => { + sendResponse({status: loggedIn}); + }); + } + return true; // Will respond asynchronously. + } +); diff --git a/manifest.json b/manifest.json index 1f05f28..8902a92 100644 --- a/manifest.json +++ b/manifest.json @@ -39,7 +39,8 @@ "scripts/highlighting.js", "scripts/repoHandlers.js", "scripts/orchestrator.js", - "scripts/init.js" + "scripts/init.js", + "scripts/signedOutIndicator.js" ] } ] diff --git a/scripts/main.css b/scripts/main.css index 9ed3cac..0ac2bda 100644 --- a/scripts/main.css +++ b/scripts/main.css @@ -29,4 +29,31 @@ tr[data-hunk="9ab7f36934cf29a090a7f1f7f432ab43eda8cf806712acde424581fcf2a221ca"] background-color: rgb(164, 167, 0); } */ +#vibinex-indicator { + position: fixed; + top: 2px; + left: 45%; + display: block; + color: #f3f4f6; + text-decoration: none; + background-color: #2196f3; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + border-radius: 0.375rem; + font-size: 0.875rem; + z-index: 9999; + line-height: 1.25rem; + padding: 0.5rem; + margin-top: 0.5rem; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +#vibinex-indicator>img { + width: 1rem; + height: 1rem; + margin-right: 0.75rem; +} \ No newline at end of file diff --git a/scripts/orchestrator.js b/scripts/orchestrator.js index 117f758..4346935 100644 --- a/scripts/orchestrator.js +++ b/scripts/orchestrator.js @@ -1,21 +1,21 @@ /** * The `orchestrator` function is responsible for orchestrating various actions based on the current URL of the tab. - * + * * Functionality: * 1. Logs the updated tab URL for debugging purposes. * 2. Checks if the user is logged in when on GitHub or Bitbucket. If not, a warning is displayed. * 3. Retrieves the 'backendUrl' from Chrome local storage. - * + * * For GitHub: * - If on a specific repository page (e.g., https://github.com/mui/mui-toolpad), it displays a floating action button. * - If on a repository's pull requests page, it highlights relevant PRs. * - If viewing files of a specific pull request, it highlights important files and specific code hunks. * - If on a user or organization's main page or repositories page, it updates the display of tracked repositories. - * + * * For Bitbucket: * - If on a workspace's repositories page, it updates the display of tracked repositories. * - If on a repository's pull requests page, it highlights relevant PRs or specific files and code hunks in a PR. - * + * * Note: This function assumes it's running in the context of a browser extension, given its use of the 'chrome.storage' API and specific URL patterns for GitHub and Bitbucket. */ const orchestrator = async (tabUrl, websiteUrl, userId) => { @@ -32,6 +32,7 @@ const orchestrator = async (tabUrl, websiteUrl, userId) => { // TODO: create a UI element on the screen with CTA to login to Vibinex } if (urlObj[2] == 'github.com') { + addSignedOutIndicator(websiteUrl, 'github') if (urlObj[3] && (urlObj[3] !== 'orgs') && urlObj[4]) { // for showing fav button if org repo is not added, eg : https://github.com/mui/mui-toolpad const ownerName = urlObj[3]; @@ -88,6 +89,7 @@ const orchestrator = async (tabUrl, websiteUrl, userId) => { } if (urlObj[2] === 'bitbucket.org') { + addSignedOutIndicator(websiteUrl, 'bitbucket') // for showing tracked repo of a organization if (urlObj[4] === 'workspace' && urlObj[5] === 'repositories') { const workspaceSlug = urlObj[3]; diff --git a/scripts/signedOutIndicator.js b/scripts/signedOutIndicator.js new file mode 100644 index 0000000..c297029 --- /dev/null +++ b/scripts/signedOutIndicator.js @@ -0,0 +1,25 @@ +/** + * Checks if user is logged out and call addIndicator + * @param {string} provider + * @param {string} websiteUrl + */ +function addSignedOutIndicator(websiteUrl) { + chrome.runtime.sendMessage({ message: "check_login_status," + websiteUrl.toString() }, async function (response) { + if (response.status === false) { + // Fetch authentication providers from the server. + fetch(`${websiteUrl}/api/auth/providers`, { cache: 'no-store' }).then(async (res) => { + const providers = await res.json(); + // Create a new div element for signed out indicator + const loginProviderButton = document.createElement("div"); + loginProviderButton.setAttribute('id', "vibinex-indicator"); + loginProviderButton.setAttribute('class', "span"); + loginProviderButton.innerHTML = ` + Vibinex Logo + Logged out of Vibinex + `; + document.body.appendChild(loginProviderButton); + } + ) + } + }); +} From 5881e608c255a258561c6640e6c0ea660cb6803e Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 12:44:46 +0530 Subject: [PATCH 2/8] Switch to using Vibinex existing bottom left indicator for logged out case --- scripts/signedOutIndicator.js | 15 +-------------- scripts/utilities.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/scripts/signedOutIndicator.js b/scripts/signedOutIndicator.js index c297029..ef47ef2 100644 --- a/scripts/signedOutIndicator.js +++ b/scripts/signedOutIndicator.js @@ -6,20 +6,7 @@ function addSignedOutIndicator(websiteUrl) { chrome.runtime.sendMessage({ message: "check_login_status," + websiteUrl.toString() }, async function (response) { if (response.status === false) { - // Fetch authentication providers from the server. - fetch(`${websiteUrl}/api/auth/providers`, { cache: 'no-store' }).then(async (res) => { - const providers = await res.json(); - // Create a new div element for signed out indicator - const loginProviderButton = document.createElement("div"); - loginProviderButton.setAttribute('id', "vibinex-indicator"); - loginProviderButton.setAttribute('class', "span"); - loginProviderButton.innerHTML = ` - Vibinex Logo - Logged out of Vibinex - `; - document.body.appendChild(loginProviderButton); - } - ) + createElement("login") } }); } diff --git a/scripts/utilities.js b/scripts/utilities.js index 7046de9..19e2c5e 100644 --- a/scripts/utilities.js +++ b/scripts/utilities.js @@ -1,7 +1,7 @@ /** * Creates and appends a floating UI element to the page based on the specified type. * - * @param {string} type - The type of element to create ("loading", "add", or "error"). + * @param {string} type - The type of element to create ("loading", "add", "error" or "login"). * @param {string} websiteUrl - The base URL for Vibinex (default: "https://vibinex.com"). */ function createElement(type = "add", websiteUrl = "https://vibinex.com") { @@ -25,6 +25,10 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { imgUrl = "https://cdn-icons-png.flaticon.com/512/1243/1243911.png?w=740&t=st=1680153899~exp=1680154499~hmac=be129e6a5a3dd4b9a362138086907f3330050f0a300473c5ed0e7e9541ece2de" bannerMessage = "Something went wrong"; break; + case "login": + loadingIconID = "vibinexLoginIcon"; + imgUrl = "https://cdn-icons-png.flaticon.com/512/6980/6980070.png?filename=user_6980070.png&fd=1"; + bannerMessage = "Please Login to Vibinex" default: break; } @@ -59,6 +63,9 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { if (type === "add") { redirectLink.href = `${websiteUrl}/docs`; } + else if (type === "login") { + redirectLink.href = `${websiteUrl}/api/auth/signin` + } redirectLink.appendChild(loadingGif); redirectLink.appendChild(img); @@ -81,7 +88,7 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { } redirectLink.addEventListener('mouseover', () => changeCss(true)); redirectLink.addEventListener('mouseout', () => changeCss(false)); - // Append the created elements to the document body. + // Append the created elements to the document body. document.body.appendChild(redirectLink); document.body.appendChild(infoBanner); } From e0c8b2501846bb504ca81bc8a8a1360f5afa48ba Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:03:20 +0530 Subject: [PATCH 3/8] Check for auth provider in json.user response. Shows indicator if logged in with github but on bitbucket and vice versa now. --- backgroundScript.js | 17 ++++++++++------- scripts/signedOutIndicator.js | 6 ++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/backgroundScript.js b/backgroundScript.js index d844a24..b4721b7 100644 --- a/backgroundScript.js +++ b/backgroundScript.js @@ -34,16 +34,17 @@ chrome.runtime.onInstalled.addListener(() => { /** * Checks Logged in status for showing indicator on supported pages like github and bitbucket. - * @param websiteUrl + * @param {string} websiteUrl + * @param {string} provider * @returns {Promise} */ -async function checkLoginStatus(websiteUrl) { +async function checkLoginStatus(websiteUrl, provider) { let result = false; try { - const res = await fetch(`${websiteUrl}/api/auth/session`, {cache: 'no-store'}); + const res = await fetch(`${websiteUrl}/api/auth/session`, { cache: 'no-store' }); const json = await res.json(); - if (json.user) { + if (json.user && json.user.auth_info && json.user.auth_info[provider]) { result = true; } } catch (err) { @@ -52,17 +53,19 @@ async function checkLoginStatus(websiteUrl) { return result; } + /** * Listener to handle login status check request. * The api session request only works via extension background script due to the need of auth cookies in request. */ chrome.runtime.onMessage.addListener( - function(request, sender, sendResponse) { + function (request, _, sendResponse) { const message = request.message?.split(','); if (message[0] === "check_login_status") { const websiteUrl = message[1]; - checkLoginStatus(websiteUrl).then(loggedIn => { - sendResponse({status: loggedIn}); + const provider = message[2] + checkLoginStatus(websiteUrl, provider).then(loggedIn => { + sendResponse({ status: loggedIn }); }); } return true; // Will respond asynchronously. diff --git a/scripts/signedOutIndicator.js b/scripts/signedOutIndicator.js index ef47ef2..ffc7f39 100644 --- a/scripts/signedOutIndicator.js +++ b/scripts/signedOutIndicator.js @@ -3,8 +3,10 @@ * @param {string} provider * @param {string} websiteUrl */ -function addSignedOutIndicator(websiteUrl) { - chrome.runtime.sendMessage({ message: "check_login_status," + websiteUrl.toString() }, async function (response) { +function addSignedOutIndicator(websiteUrl, provider) { + chrome.runtime.sendMessage({ + message: "check_login_status," + websiteUrl.toString() + "," + provider.toString() + }, async function (response) { if (response.status === false) { createElement("login") } From 9eaf52e22720e47c9877e5cdcaf84b3076343b06 Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:15:04 +0530 Subject: [PATCH 4/8] add login element to destroyElement function --- scripts/utilities.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/utilities.js b/scripts/utilities.js index 19e2c5e..6241bfc 100644 --- a/scripts/utilities.js +++ b/scripts/utilities.js @@ -107,6 +107,9 @@ function destroyElement(type) { document.getElementById('vibinexPlusIcon').remove(); else if (type === "error") document.getElementById('vibinexErrorIcon').remove(); + else if (type === "login") { + document.getElementById('vibinexLoginIcon').remove(); + } } /** From 4544786690f77f129974733e4f941ce894152443 Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:17:17 +0530 Subject: [PATCH 5/8] Remove css of old login indicator --- scripts/main.css | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/scripts/main.css b/scripts/main.css index 0ac2bda..e5f15c1 100644 --- a/scripts/main.css +++ b/scripts/main.css @@ -28,32 +28,4 @@ tr[data-hunk="9ab7f36934cf29a090a7f1f7f432ab43eda8cf806712acde424581fcf2a221ca"] background-color: rgb(122, 126, 0); background-color: rgb(164, 167, 0); } - */ -#vibinex-indicator { - position: fixed; - top: 2px; - left: 45%; - display: block; - color: #f3f4f6; - text-decoration: none; - background-color: #2196f3; - display: flex; - justify-content: center; - align-items: center; - box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - border-radius: 0.375rem; - font-size: 0.875rem; - z-index: 9999; - line-height: 1.25rem; - padding: 0.5rem; - margin-top: 0.5rem; - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -#vibinex-indicator>img { - width: 1rem; - height: 1rem; - margin-right: 0.75rem; -} \ No newline at end of file + */ \ No newline at end of file From 9548c2fba4114c795f57c1af73396c549b89eac4 Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:29:25 +0530 Subject: [PATCH 6/8] Update log in indicator as per review --- scripts/signedOutIndicator.js | 2 +- scripts/utilities.js | 44 +++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/scripts/signedOutIndicator.js b/scripts/signedOutIndicator.js index ffc7f39..dfbd746 100644 --- a/scripts/signedOutIndicator.js +++ b/scripts/signedOutIndicator.js @@ -8,7 +8,7 @@ function addSignedOutIndicator(websiteUrl, provider) { message: "check_login_status," + websiteUrl.toString() + "," + provider.toString() }, async function (response) { if (response.status === false) { - createElement("login") + createElement(provider) } }); } diff --git a/scripts/utilities.js b/scripts/utilities.js index 6241bfc..d9a009f 100644 --- a/scripts/utilities.js +++ b/scripts/utilities.js @@ -1,7 +1,7 @@ /** * Creates and appends a floating UI element to the page based on the specified type. * - * @param {string} type - The type of element to create ("loading", "add", "error" or "login"). + * @param {string} type - The type of element to create ("loading", "add", "error", "github" or "bitbucket"). * @param {string} websiteUrl - The base URL for Vibinex (default: "https://vibinex.com"). */ function createElement(type = "add", websiteUrl = "https://vibinex.com") { @@ -25,10 +25,16 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { imgUrl = "https://cdn-icons-png.flaticon.com/512/1243/1243911.png?w=740&t=st=1680153899~exp=1680154499~hmac=be129e6a5a3dd4b9a362138086907f3330050f0a300473c5ed0e7e9541ece2de" bannerMessage = "Something went wrong"; break; - case "login": + case "github": loadingIconID = "vibinexLoginIcon"; - imgUrl = "https://cdn-icons-png.flaticon.com/512/6980/6980070.png?filename=user_6980070.png&fd=1"; - bannerMessage = "Please Login to Vibinex" + imgUrl = "https://img.icons8.com/external-tal-revivo-bold-tal-revivo/24/FFFFFF/external-github-with-cat-logo-an-online-community-for-software-development-logo-bold-tal-revivo.png"; + bannerMessage = "Log in with GitHub"; + break; + case "bitbucket": + loadingIconID = "vibinexLoginIcon"; + imgUrl = "https://img.icons8.com/external-tal-revivo-bold-tal-revivo/24/FFFFFF/external-bitbucket-is-a-web-based-version-control-repository-hosting-service-logo-bold-tal-revivo.png"; + bannerMessage = "Log in with Bitbucket"; + break; default: break; } @@ -63,8 +69,9 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { if (type === "add") { redirectLink.href = `${websiteUrl}/docs`; } - else if (type === "login") { + else if (type === "github" || type === "bitbucket") { redirectLink.href = `${websiteUrl}/api/auth/signin` + redirectLink.target = '_blank' } redirectLink.appendChild(loadingGif); redirectLink.appendChild(img); @@ -91,6 +98,33 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { // Append the created elements to the document body. document.body.appendChild(redirectLink); document.body.appendChild(infoBanner); + + if (loadingIconID === "vibinexLoginIcon") { + // Create and style the login indicator. + const loginButton = document.createElement('button'); + loginButton.style.borderRadius = '39px'; + loginButton.style.paddingLeft = '44px'; + loginButton.style.paddingRight = '15px'; + loginButton.style.border = 'none'; + loginButton.style.backgroundColor = 'black'; + loginButton.style.color = 'white'; + loginButton.style.cursor = 'pointer'; + loginButton.style.position = 'fixed'; + loginButton.style.left = '26px'; + loginButton.style.bottom = '48px'; + loginButton.style.height = '39px'; + loginButton.style.zIndex = '199' + loginButton.style.alignItems = 'center'; + + // Append the login text to the login button. + loginButton.appendChild(document.createTextNode(bannerMessage)); + + // Replace the loading icon with the login button. + redirectLink.replaceChild(loginButton, loadingGif); + redirectLink.href = `${websiteUrl}/api/auth/signin` + infoBanner.remove(); + } + } /** From e51bed6b99699386a05a790a0c594fd2ce86076f Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:37:28 +0530 Subject: [PATCH 7/8] code quality fixes as per review --- backgroundScript.js | 8 ++++---- manifest.json | 4 ++-- scripts/orchestrator.js | 1 - scripts/signedOutIndicator.js | 7 ++++++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/backgroundScript.js b/backgroundScript.js index b4721b7..8704692 100644 --- a/backgroundScript.js +++ b/backgroundScript.js @@ -60,10 +60,10 @@ async function checkLoginStatus(websiteUrl, provider) { */ chrome.runtime.onMessage.addListener( function (request, _, sendResponse) { - const message = request.message?.split(','); - if (message[0] === "check_login_status") { - const websiteUrl = message[1]; - const provider = message[2] + const message = JSON.parse(request.message); + if (message.action === "check_login_status") { + const websiteUrl = message.websiteUrl; + const provider = message.provider checkLoginStatus(websiteUrl, provider).then(loggedIn => { sendResponse({ status: loggedIn }); }); diff --git a/manifest.json b/manifest.json index 8902a92..509742c 100644 --- a/manifest.json +++ b/manifest.json @@ -38,9 +38,9 @@ "scripts/api.js", "scripts/highlighting.js", "scripts/repoHandlers.js", + "scripts/signedOutIndicator.js", "scripts/orchestrator.js", - "scripts/init.js", - "scripts/signedOutIndicator.js" + "scripts/init.js" ] } ] diff --git a/scripts/orchestrator.js b/scripts/orchestrator.js index 4346935..c08bf9e 100644 --- a/scripts/orchestrator.js +++ b/scripts/orchestrator.js @@ -29,7 +29,6 @@ const orchestrator = async (tabUrl, websiteUrl, userId) => { if (!userId && (urlObj[2] === 'github.com' || urlObj[2] === 'bitbucket.org')) { console.warn(`[Vibinex] You are not logged in. Head to ${websiteUrl} to log in`); - // TODO: create a UI element on the screen with CTA to login to Vibinex } if (urlObj[2] == 'github.com') { addSignedOutIndicator(websiteUrl, 'github') diff --git a/scripts/signedOutIndicator.js b/scripts/signedOutIndicator.js index dfbd746..1c27fed 100644 --- a/scripts/signedOutIndicator.js +++ b/scripts/signedOutIndicator.js @@ -4,8 +4,13 @@ * @param {string} websiteUrl */ function addSignedOutIndicator(websiteUrl, provider) { + const message = { + action: "check_login_status", + websiteUrl: websiteUrl, + provider: provider + } chrome.runtime.sendMessage({ - message: "check_login_status," + websiteUrl.toString() + "," + provider.toString() + message: JSON.stringify(message) }, async function (response) { if (response.status === false) { createElement(provider) From b7e74d1ceb6a6c7745e6cc1cbe2115f3f50a19be Mon Sep 17 00:00:00 2001 From: Ajay Krishna K V <55079486+AJAYK-01@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:44:49 +0530 Subject: [PATCH 8/8] remove duplicate href addition in login indicator --- scripts/utilities.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/utilities.js b/scripts/utilities.js index d9a009f..8900b4b 100644 --- a/scripts/utilities.js +++ b/scripts/utilities.js @@ -121,7 +121,6 @@ function createElement(type = "add", websiteUrl = "https://vibinex.com") { // Replace the loading icon with the login button. redirectLink.replaceChild(loginButton, loadingGif); - redirectLink.href = `${websiteUrl}/api/auth/signin` infoBanner.remove(); }