From d98ac9d7c67ec1393d89eb85ee0018b11deea7d0 Mon Sep 17 00:00:00 2001 From: unclebill Date: Tue, 22 Feb 2022 13:09:01 +0800 Subject: [PATCH 1/2] fix(twitter): fails to detect text color in tweet detail page the compose anchor doesn't show up in tweet detail page --- .../twitter.com/customization/custom.ts | 35 +++++++++++++++---- .../twitter.com/utils/isMobile.ts | 6 +--- .../twitter.com/utils/selector.ts | 2 ++ packages/mask/src/utils/theme-tools.ts | 6 ++-- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts b/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts index 3c0a9bb1b85b..f334fd374caf 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts @@ -7,13 +7,14 @@ import { useMemo } from 'react' import type { SocialNetworkUI } from '../../../social-network' import { fromRGB, getBackgroundColor, getForegroundColor, isDark, shade, toRGB } from '../../../utils/theme-tools' import { isMobileTwitter } from '../utils/isMobile' -import { composeAnchorSelector, composeAnchorTextSelector } from '../utils/selector' +import { composeAnchorSelector, composeAnchorTextSelector, headingTextSelector } from '../utils/selector' import twitterColorSchema from './twitter-color-schema.json' import { parseColor } from '@masknet/theme' +import { noop } from 'lodash-unified' -const primaryColorRef = new ValueRef(toRGB([29, 161, 242])) -const primaryColorContrastColorRef = new ValueRef(toRGB([255, 255, 255])) -const backgroundColorRef = new ValueRef(toRGB([255, 255, 255])) +const primaryColorRef = new ValueRef('rgb(29, 161, 242)') +const primaryColorContrastColorRef = new ValueRef('rgb(255, 255, 255)') +const backgroundColorRef = new ValueRef('rgb(255, 255, 255)') const currentTheme = new ValueRef('light') export const PaletteModeProviderTwitter: SocialNetworkUI.Customization.PaletteModeProvider = { @@ -23,13 +24,17 @@ export const PaletteModeProviderTwitter: SocialNetworkUI.Customization.PaletteMo export function startWatchThemeColor(signal: AbortSignal) { function updateThemeColor() { - const color = getBackgroundColor(composeAnchorSelector().evaluate()!) - const contrastColor = getForegroundColor(composeAnchorTextSelector().evaluate()!) + const composeAnchor = composeAnchorSelector().evaluate() + const anchorText = composeAnchorTextSelector().evaluate() + const headingText = headingTextSelector().evaluate() + const color = getBackgroundColor(composeAnchor) + const contrastColor = getForegroundColor(anchorText || headingText) const backgroundColor = getBackgroundColor(document.body) currentTheme.value = isDark(fromRGB(backgroundColor)!) ? 'dark' : 'light' if (color) primaryColorRef.value = color if (contrastColor) primaryColorContrastColorRef.value = contrastColor + console.log({ color, contrastColor }) if (backgroundColor) backgroundColorRef.value = backgroundColor } const watcher = new MutationObserverWatcher(composeAnchorSelector()) @@ -39,7 +44,23 @@ export function startWatchThemeColor(signal: AbortSignal) { childList: true, subtree: true, }) - signal.addEventListener('abort', () => watcher.stopWatch()) + const unwatchAnchor = () => watcher.stopWatch() + let unwatchHeadingText = noop + + if (isMobileTwitter) { + const headingWatcher = new MutationObserverWatcher(headingTextSelector()) + .addListener('onAdd', updateThemeColor) + .addListener('onChange', updateThemeColor) + .startWatch({ + childList: true, + subtree: true, + }) + unwatchHeadingText = () => headingWatcher.stopWatch() + } + signal.addEventListener('abort', () => { + unwatchAnchor() + unwatchHeadingText() + }) } export function useThemeTwitterVariant(baseTheme: Theme) { const primaryColor = useValueRef(primaryColorRef) diff --git a/packages/mask/src/social-network-adaptor/twitter.com/utils/isMobile.ts b/packages/mask/src/social-network-adaptor/twitter.com/utils/isMobile.ts index fd05b9fe86c4..f0daab5eada6 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/utils/isMobile.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/utils/isMobile.ts @@ -1,7 +1,3 @@ -import { Environment, isEnvironment } from '@dimensiondev/holoflows-kit' -import { twitterUrl } from './url' +export const isMobileTwitter = !!navigator.userAgent.match(/Mobile|mobile/) -export const isMobileTwitter = isEnvironment(Environment.ContentScript) - ? location.hostname === twitterUrl.hostLeadingUrlMobile.substr(8) - : !!navigator.userAgent.match(/Mobile|mobile/) export const twitterDomain = isMobileTwitter ? 'https://mobile.twitter.com/' : 'https://twitter.com/' diff --git a/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts b/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts index ffa57cdf7c03..647f6c73188d 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/utils/selector.ts @@ -80,6 +80,8 @@ export const composeAnchorTextSelector: () => LiveSelector( 'header[role=banner] a[href="/compose/tweet"] div[dir],aside a[href="/compose/tweet"] div[dir]', ) +export const headingTextSelector: () => LiveSelector = () => + querySelector('[role="banner"] [role="heading"]') export const postEditorContentInPopupSelector: () => LiveSelector = () => querySelector( diff --git a/packages/mask/src/utils/theme-tools.ts b/packages/mask/src/utils/theme-tools.ts index 3192a97f5482..197f11140ba4 100644 --- a/packages/mask/src/utils/theme-tools.ts +++ b/packages/mask/src/utils/theme-tools.ts @@ -50,7 +50,8 @@ function isRGBA(color: string) { return color.match(/^rgba\((\d{1,3}%?),\s*(\d{1,3}%?),\s*(\d{1,3}%?),\s*(\d*(?:\.\d+)?)\)$/) } -export function getBackgroundColor(element: HTMLElement | HTMLBodyElement) { +export function getBackgroundColor(element: HTMLElement | HTMLBodyElement | undefined) { + if (!element) return '' const color = getComputedStyle(element).backgroundColor if (isRGBA(color)) { return fromRGBAtoRGB(color) @@ -58,7 +59,8 @@ export function getBackgroundColor(element: HTMLElement | HTMLBodyElement) { return color ? toRGB(fromRGB(color)) : '' } -export function getForegroundColor(element: HTMLElement | HTMLBodyElement) { +export function getForegroundColor(element: HTMLElement | HTMLBodyElement | undefined) { + if (!element) return '' const color = getComputedStyle(element).color if (isRGBA(color)) { return fromRGBAtoRGB(color) From 4231286c139927dff2757c42b54e6bb061ac7184 Mon Sep 17 00:00:00 2001 From: unclebill Date: Tue, 22 Feb 2022 13:16:54 +0800 Subject: [PATCH 2/2] fixup! fix(twitter): fails to detect text color in tweet detail page --- .../twitter.com/customization/custom.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts b/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts index f334fd374caf..8eb6f0b7bdb5 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts @@ -12,8 +12,8 @@ import twitterColorSchema from './twitter-color-schema.json' import { parseColor } from '@masknet/theme' import { noop } from 'lodash-unified' -const primaryColorRef = new ValueRef('rgb(29, 161, 242)') -const primaryColorContrastColorRef = new ValueRef('rgb(255, 255, 255)') +const themeColorRef = new ValueRef('rgb(29, 161, 242)') +const textColorRef = new ValueRef('rgb(255, 255, 255)') const backgroundColorRef = new ValueRef('rgb(255, 255, 255)') const currentTheme = new ValueRef('light') @@ -27,14 +27,13 @@ export function startWatchThemeColor(signal: AbortSignal) { const composeAnchor = composeAnchorSelector().evaluate() const anchorText = composeAnchorTextSelector().evaluate() const headingText = headingTextSelector().evaluate() - const color = getBackgroundColor(composeAnchor) - const contrastColor = getForegroundColor(anchorText || headingText) + const themeColor = getBackgroundColor(composeAnchor) + const textColor = getForegroundColor(anchorText || headingText) const backgroundColor = getBackgroundColor(document.body) currentTheme.value = isDark(fromRGB(backgroundColor)!) ? 'dark' : 'light' - if (color) primaryColorRef.value = color - if (contrastColor) primaryColorContrastColorRef.value = contrastColor - console.log({ color, contrastColor }) + if (themeColor) themeColorRef.value = themeColor + if (textColor) textColorRef.value = textColor if (backgroundColor) backgroundColorRef.value = backgroundColor } const watcher = new MutationObserverWatcher(composeAnchorSelector()) @@ -63,8 +62,8 @@ export function startWatchThemeColor(signal: AbortSignal) { }) } export function useThemeTwitterVariant(baseTheme: Theme) { - const primaryColor = useValueRef(primaryColorRef) - const primaryContrastColor = useValueRef(primaryColorContrastColorRef) + const primaryColor = useValueRef(themeColorRef) + const primaryContrastColor = useValueRef(textColorRef) const backgroundColor = useValueRef(backgroundColorRef) return useMemo(() => { const primaryColorRGB = fromRGB(primaryColor)!