From 60e63ffde3fda9999fe04e12332db041d0ec1777 Mon Sep 17 00:00:00 2001 From: Yacine Badiss Date: Sun, 14 Jan 2024 20:58:38 +0100 Subject: [PATCH] [extension] fix css for different color schemes --- .../config/webpack.config.js | 2 +- .../src/contentModifiers.js | 113 ++----- .../src/defaultContentScript.js | 12 +- .../src/statusContentScript.js | 4 +- fc-community-extension/src/utils/selectors.js | 10 - fc-community-extension/src/xHtml.js | 287 ++++++++++++++++++ 6 files changed, 315 insertions(+), 113 deletions(-) delete mode 100644 fc-community-extension/src/utils/selectors.js create mode 100644 fc-community-extension/src/xHtml.js diff --git a/fc-community-extension/config/webpack.config.js b/fc-community-extension/config/webpack.config.js index 44ba2457..1fca5e43 100644 --- a/fc-community-extension/config/webpack.config.js +++ b/fc-community-extension/config/webpack.config.js @@ -18,10 +18,10 @@ const config = (env, argv) => statusContentScript: PATHS.src + '/statusContentScript.js', subscribeContentScript: PATHS.src + '/subscribeContentScript.js', contentModifiers: PATHS.src + '/contentModifiers.js', + xHtml: PATHS.src + '/xHtml.js', web3: PATHS.src + '/utils/web3.js', logging: PATHS.src + '/utils/logging.js', constants: PATHS.src + '/utils/constants.js', - selectors: PATHS.src + '/utils/selectors.js', backend: PATHS.src + '/utils/backend.js', serviceWorker: PATHS.src + '/serviceWorker.js', }, diff --git a/fc-community-extension/src/contentModifiers.js b/fc-community-extension/src/contentModifiers.js index 73919eb5..e0115daa 100644 --- a/fc-community-extension/src/contentModifiers.js +++ b/fc-community-extension/src/contentModifiers.js @@ -1,31 +1,18 @@ import { logger } from './utils/logging'; import { parseUrl, NOTE_URL_REGEX, POST_URL_REGEX } from './utils/constants'; -import { xSelectors } from './utils/selectors'; +import { + makeFactchainNoteHtml, + makeMintXNoteOnDetailsPageHtml, + makeMintXNoteOnMainPageHtml, + makeDropdownNoteCreationButton, + noteContentSelector, + dropdownUrlSelector, +} from './xHtml'; /// --------------------------- /// Birdwatch content modifiers /// --------------------------- -const logoSvg = - ''; - -const separatorMintNoteHtml = `
-
-
- Like this note? -
-
-
-
- - Collect it - -
-
-
-
-
`; - export const alterRatingPageTwitterNote = (twitterNote) => { if (twitterNote.classList.contains('factchain-1.0')) { // Add a special class to avoid re-processing the same twitter note multiple times @@ -35,14 +22,17 @@ export const alterRatingPageTwitterNote = (twitterNote) => { } else { // First time we see this twitter note let's do something with it twitterNote.classList.add('factchain-1.0'); - twitterNote.insertAdjacentHTML('afterend', separatorMintNoteHtml); + twitterNote.insertAdjacentHTML( + 'afterend', + makeMintXNoteOnDetailsPageHtml() + ); const noteUrl = parseUrl(document.URL, NOTE_URL_REGEX); twitterNote.parentNode .querySelector('#mintNoteButton') .addEventListener('click', async () => { const content = twitterNote.querySelector( - xSelectors.noteContent + noteContentSelector() ).textContent; logger.log( `Minting twitter from rating page note ${noteUrl} and content '${content}'` @@ -56,21 +46,6 @@ export const alterRatingPageTwitterNote = (twitterNote) => { } }; -const makeMintNoteHtml = () => { - return `
-
- Like this note? -
-
-
- - Collect it - -
-
-
`; -}; - export const alterMainPageTwitterNote = (twitterNote) => { if (twitterNote.classList.contains('factchain-1.0')) { // Add a special class to avoid re-processing the same twitter note multiple times @@ -80,7 +55,7 @@ export const alterMainPageTwitterNote = (twitterNote) => { } else { // First time we see this twitter note let's do something with it twitterNote.classList.add('factchain-1.0'); - twitterNote.insertAdjacentHTML('beforeend', makeMintNoteHtml()); + twitterNote.insertAdjacentHTML('beforeend', makeMintXNoteOnMainPageHtml()); } }; @@ -89,19 +64,7 @@ export const alterMainPageTwitterNote = (twitterNote) => { /// --------------------------- const addNoteCreationButton = (dropdown, postUrl) => { - dropdown.insertAdjacentHTML( - 'beforeend', - ` \ -
\ - ${logoSvg} -
\ -
\ -
\ - Create Factchain Note \ -
\ -
\ - ` - ); + dropdown.insertAdjacentHTML('beforeend', makeDropdownNoteCreationButton()); dropdown.querySelector('#createNoteButton').addEventListener('click', () => { logger.log(`Creating note on ${postUrl}`); @@ -122,7 +85,7 @@ export const alterDropdown = async (dropdown) => { // First time we see this dropdown let's do something with it dropdown.classList.add('factchain-1.0'); const postUrl = parseUrl( - dropdown.querySelector(xSelectors.dropdownUrl).href, + dropdown.querySelector(dropdownUrlSelector()).href, POST_URL_REGEX ); addNoteCreationButton(dropdown, postUrl); @@ -133,48 +96,6 @@ export const alterDropdown = async (dropdown) => { /// Status content modifiers /// --------------------------- -const rateItHtml = ( - rateNoteButtonID -) => ` -
-
- Do you find this helpful? -
-
-
- - Rate it - -
-
-
`; - -const makeFactchainHtmlNote = (isAuthor, content, rateNoteButtonID) => { - const author = isAuthor ? 'You' : 'Factchain users'; - let noteHTML = `
-
-
- ${logoSvg} -
- ${author} added context -
-
-
- -
- - ${content} - -
- `; - - if (rateNoteButtonID) { - noteHTML += `
${rateItHtml(rateNoteButtonID)}
`; - } - noteHTML += '
'; - return noteHTML; -}; - const addNote = async (mainArticle, note, userAddress) => { const isAuthor = userAddress && @@ -183,7 +104,7 @@ const addNote = async (mainArticle, note, userAddress) => { !note.finalRating && !isAuthor ? `rateNoteButton-${note.creatorAddress}` : null; - const htmlNote = makeFactchainHtmlNote( + const htmlNote = makeFactchainNoteHtml( isAuthor, note.content, rateNoteButtonID diff --git a/fc-community-extension/src/defaultContentScript.js b/fc-community-extension/src/defaultContentScript.js index 17b38fd6..fb1ea021 100644 --- a/fc-community-extension/src/defaultContentScript.js +++ b/fc-community-extension/src/defaultContentScript.js @@ -4,13 +4,17 @@ import { alterRatingPageTwitterNote, alterMainPageTwitterNote, } from './contentModifiers'; -import { xSelectors } from './utils/selectors'; +import { + approvedNotesSelector, + dropdownSelector, + ratingStatusSelector, +} from './xHtml'; let observer = new MutationObserver(async (mutations) => { for (let mutation of mutations) { for (let addedNode of mutation.addedNodes) { if (addedNode && typeof addedNode.querySelector === 'function') { - const dropdown = addedNode.querySelector(xSelectors.dropdown); + const dropdown = addedNode.querySelector(dropdownSelector()); if (dropdown) { // Triggered whenever the user opens a dropdown on an article. logger.log('New dropdown', dropdown); @@ -18,7 +22,7 @@ let observer = new MutationObserver(async (mutations) => { } const ratingStatuses = Array.from( - addedNode.querySelectorAll(xSelectors.ratingStatus) + addedNode.querySelectorAll(ratingStatusSelector) ); // Only keep the rating statuses that are for helpful notes. const helpfulRatings = ratingStatuses.filter( @@ -34,7 +38,7 @@ let observer = new MutationObserver(async (mutations) => { alterRatingPageTwitterNote(helpfulNote); } - const twitterNote = addedNode.querySelector(xSelectors.approvedNotes); + const twitterNote = addedNode.querySelector(approvedNotesSelector()); if (twitterNote) { // Triggered whenever an approved note is displayed, on any page // but mostly on the main feed. diff --git a/fc-community-extension/src/statusContentScript.js b/fc-community-extension/src/statusContentScript.js index 300ed320..1f8ad1b5 100644 --- a/fc-community-extension/src/statusContentScript.js +++ b/fc-community-extension/src/statusContentScript.js @@ -1,12 +1,12 @@ import { logger } from './utils/logging'; import { alterMainArticle } from './contentModifiers'; -import { xSelectors } from './utils/selectors'; +import { mainArticleSelector } from './xHtml'; let observer = new MutationObserver(async (mutations) => { for (let mutation of mutations) { for (let addedNode of mutation.addedNodes) { if (addedNode && typeof addedNode.querySelector === 'function') { - const mainArticle = addedNode.querySelector(xSelectors.mainArticle); + const mainArticle = addedNode.querySelector(mainArticleSelector()); if (mainArticle) { // Triggered whenever an article details page is displayed. logger.log('Found main article', mainArticle); diff --git a/fc-community-extension/src/utils/selectors.js b/fc-community-extension/src/utils/selectors.js deleted file mode 100644 index 8d1ce0da..00000000 --- a/fc-community-extension/src/utils/selectors.js +++ /dev/null @@ -1,10 +0,0 @@ -export const xSelectors = { - mainArticle: "article[tabindex='-1']", - dropdown: "div[data-testid='Dropdown']", - dropdownUrl: "a[data-testid='tweetEngagements']", - ratingStatus: "div[data-testid='ratingStatus']", - noteContent: 'div.css-175oi2r.r-1471scf.r-18u37iz.r-iphfwy.r-1h8ys4a', - // All birdwatch elements with the classes of an already approved note - approvedNotes: - "div[data-testid='birdwatch-pivot'].css-175oi2r.r-1kqtdi0.r-1udh08x.r-g2wdr4.r-1mhqjh3.r-5kkj8d.r-1va55bh.r-1mnahxq.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21", -}; diff --git a/fc-community-extension/src/xHtml.js b/fc-community-extension/src/xHtml.js new file mode 100644 index 00000000..038f4d7b --- /dev/null +++ b/fc-community-extension/src/xHtml.js @@ -0,0 +1,287 @@ +const getColorScheme = () => { + const backgroundColor = + document.getElementsByTagName('body')[0].style['background-color']; + if (backgroundColor === 'rgb(0, 0, 0)') { + return 'dark'; + } else if (backgroundColor === 'rgb(255, 255, 255)') { + return 'light'; + } else { + return 'dim'; + } +}; + +const removeWhitespaces = (htmlContent) => htmlContent.replaceAll(/>\s+/g, '>'); + +export const mainArticleSelector = () => "article[tabindex='-1']"; +export const dropdownSelector = () => "div[data-testid='Dropdown']"; +export const dropdownUrlSelector = () => "a[data-testid='tweetEngagements']"; +export const ratingStatusSelector = () => "div[data-testid='ratingStatus']"; +export const noteContentSelector = () => + 'div.css-175oi2r.r-1471scf.r-18u37iz.r-iphfwy.r-1h8ys4a'; + +export const approvedNotesSelector = () => { + const colorScheme = getColorScheme(); + const htmlBuilder = htmlBuilders[colorScheme]; + return removeWhitespaces(htmlBuilder.approvedNotes); +}; + +export const makeFactchainNoteHtml = (isAuthor, content, rateNoteButtonID) => { + const colorScheme = getColorScheme(); + const htmlBuilder = htmlBuilders[colorScheme]; + const actionHtml = rateNoteButtonID + ? htmlBuilder.action( + 'Do you find this helpful?', + rateNoteButtonID, + 'Rate it' + ) + : ''; + const title = `${isAuthor ? 'You' : 'Factchain users'} added context`; + return removeWhitespaces( + htmlBuilder.note(title, content, htmlBuilder.logo, actionHtml) + ); +}; + +export const makeDropdownNoteCreationButton = () => { + const colorScheme = getColorScheme(); + const htmlBuilder = htmlBuilders[colorScheme]; + return removeWhitespaces( + htmlBuilder.dropdownNoteCreationButton(htmlBuilder.logo) + ); +}; + +export const makeMintXNoteOnDetailsPageHtml = () => { + const colorScheme = getColorScheme(); + const htmlBuilder = htmlBuilders[colorScheme]; + return removeWhitespaces(htmlBuilder.mintXNoteOnDetailsPage); +}; + +export const makeMintXNoteOnMainPageHtml = () => { + const colorScheme = getColorScheme(); + const htmlBuilder = htmlBuilders[colorScheme]; + return removeWhitespaces(htmlBuilder.mintXNoteOnMainPage); +}; + +const htmlBuilders = { + dim: { + logo: '', + action: (title, buttonId, content) => + ` +
+
+ ${title} +
+
+
+ + ${content} + +
+
+
`, + note: (title, content, logoHtml, actionHtml) => + `
+
+
+ ${logoHtml} +
+ ${title} +
+
+
+ +
+ ${content} +
+ ${actionHtml} +
`, + dropdownNoteCreationButton: (logoHtml) => + `
+
+ ${logoHtml} +
+
+
+ Create Factchain Note +
+
+ `, + mintXNoteOnDetailsPage: `
+
+
+ Like this note? +
+
+
+
+ + Collect it on Factchain + +
+
+
+
+
`, + mintXNoteOnMainPage: `
+
+ Like this note? +
+
+
+ + Collect it on Factchain + +
+
+
`, + approvedNotes: + "div[data-testid='birdwatch-pivot'].css-175oi2r.r-18bvks7.r-1udh08x.r-g6ijar.r-1mhqjh3.r-5kkj8d.r-1va55bh.r-1mnahxq.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21", + }, + dark: { + logo: '', + action: (title, buttonId, content) => + ` +
+
+ ${title} +
+
+
+ + ${content} + +
+
+
`, + note: (title, content, logoHtml, actionHtml) => + `
+
+
+ ${logoHtml} +
+ ${title} +
+
+
+ +
+ ${content} +
+ ${actionHtml} +
`, + dropdownNoteCreationButton: (logoHtml) => + `
+
+ ${logoHtml} +
+
+
+ Create Factchain Note +
+
+ `, + mintXNoteOnDetailsPage: `
+
+
+ Like this note? +
+
+
+
+ + Collect it on Factchain + +
+
+
+
+
`, + mintXNoteOnMainPage: `
+
+ Like this note? +
+
+
+ + Collect it on Factchain + +
+
+
`, + approvedNotes: + "div[data-testid='birdwatch-pivot'].css-175oi2r.r-1kqtdi0.r-1udh08x.r-g2wdr4.r-1mhqjh3.r-5kkj8d.r-1va55bh.r-1mnahxq.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21", + }, + light: { + logo: '', + action: (title, buttonId, content) => + ` +
+
+ ${title} +
+
+
+ + ${content} + +
+
+
`, + note: (title, content, logoHtml, actionHtml) => + `
+
+
+ ${logoHtml} +
+ ${title} +
+
+
+ +
+ ${content} +
+ ${actionHtml} +
`, + dropdownNoteCreationButton: (logoHtml) => + `
+
+ ${logoHtml} +
+
+
+ Create Factchain Note +
+
+ `, + mintXNoteOnDetailsPage: `
+
+
+ Like this note? +
+
+
+
+ + Collect it on Factchain + +
+
+
+
+
`, + mintXNoteOnMainPage: `
+
+ Like this note? +
+
+
+ + Collect it on Factchain + +
+
+
`, + approvedNotes: + "div[data-testid='birdwatch-pivot'].css-175oi2r.r-1ets6dv.r-1udh08x.r-x572qd.r-1mhqjh3.r-5kkj8d.r-1va55bh.r-1mnahxq.r-o7ynqc.r-6416eg.r-1ny4l3l.r-1loqt21", + }, +};