From b7c84d5218a5d9a59d3f0b4b6458bbb930ebf8d7 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Mon, 31 Jul 2023 18:59:21 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E5=85=81=E8=AE=B8=E7=94=A8npm?= =?UTF-8?q?=E6=89=93=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Ackee.js | 29 ++++++++++++++--------------- components/CusdisComponent.js | 3 +-- components/FacebookMessenger.js | 3 +-- components/ShareButtons.js | 10 +--------- package.json | 6 +----- 5 files changed, 18 insertions(+), 33 deletions(-) diff --git a/components/Ackee.js b/components/Ackee.js index ab22c969640..f17d536d57a 100644 --- a/components/Ackee.js +++ b/components/Ackee.js @@ -1,20 +1,19 @@ -import { useRouter } from 'next/router' -import useAckee from 'use-ackee' -import BLOG from '@/blog.config' +// import { useRouter } from 'next/router' +// import BLOG from '@/blog.config' const Ackee = () => { - const router = useRouter() - useAckee( - router.asPath, - { - server: BLOG.ANALYTICS_ACKEE_DATA_SERVER, - domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID - }, - { - detailed: false, - ignoreLocalhost: true - } - ) +// const router = useRouter() +// useAckee( +// router.asPath, +// { +// server: BLOG.ANALYTICS_ACKEE_DATA_SERVER, +// domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID +// }, +// { +// detailed: false, +// ignoreLocalhost: true +// } +// ) return null } diff --git a/components/CusdisComponent.js b/components/CusdisComponent.js index 83b962b55a5..0e2a4f00b53 100644 --- a/components/CusdisComponent.js +++ b/components/CusdisComponent.js @@ -1,5 +1,4 @@ import { useGlobal } from '@/lib/global' -import { ReactCusdis } from 'react-cusdis' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { useEffect } from 'react' @@ -28,7 +27,7 @@ const CusdisComponent = ({ frontMatter }) => { } }) - return ( - { - return import('qrcode.react') - }, - { ssr: false } -) - /** * @author https://github.com/txs * @param {*} param0 @@ -354,7 +346,7 @@ const ShareButtons = ({ shareUrl, title, body, image }) => {
- + {/* */}
{locale.COMMON.SCAN_QR_CODE} diff --git a/package.json b/package.json index c1baace52f6..4b623870b4e 100644 --- a/package.json +++ b/package.json @@ -43,18 +43,14 @@ "nprogress": "^0.2.0", "preact": "^10.5.15", "prism-themes": "1.9.0", - "qrcode.react": "^1.0.1", "react": "^18.2.0", "react-cookies": "^0.1.1", - "react-cusdis": "^2.1.3", "react-dom": "^18.2.0", "react-facebook": "^8.1.4", - "react-messenger-customer-chat": "^0.8.0", "react-notion-x": "6.16.0", "react-share": "^4.4.1", "react-tweet-embed": "~2.0.0", - "typed.js": "^2.0.12", - "use-ackee": "^3.0.0" + "typed.js": "^2.0.12" }, "devDependencies": { "@waline/client": "^2.5.1", From 187b173ead4e21dc065900d000a640c6ba7fd3de Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Mon, 31 Jul 2023 21:30:38 +0800 Subject: [PATCH 02/13] =?UTF-8?q?qrcode=20=E6=94=B9=E4=B8=BAcdn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog.config.js | 2 ++ components/GoogleAdsense.js | 2 +- components/PrismMac.js | 1 - components/QrCode.js | 34 ++++++++++++++++++++++++++++++++++ components/ShareButtons.js | 7 +++++-- lib/utils.js | 10 ++++++++-- themes/gitbook/index.js | 1 - 7 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 components/QrCode.js diff --git a/blog.config.js b/blog.config.js index fab696b818e..9f8511b8b6e 100644 --- a/blog.config.js +++ b/blog.config.js @@ -119,6 +119,8 @@ const BLOG = { // Mermaid 图表CDN MERMAID_CDN: process.env.NEXT_PUBLIC_MERMAID_CDN || 'https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.2.4/mermaid.min.js', // CDN + // QRCodeCDN + QR_CODE_CDN: process.env.NEXT_PUBLIC_QR_CODE_CDN || 'https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js', BACKGROUND_LIGHT: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc BACKGROUND_DARK: '#000000', // use hex value, don't forget '#' diff --git a/components/GoogleAdsense.js b/components/GoogleAdsense.js index 22fca8793dc..420dc993662 100644 --- a/components/GoogleAdsense.js +++ b/components/GoogleAdsense.js @@ -21,7 +21,7 @@ export default function GoogleAdsense() { for (let i = 0; i <= ads.length; i++) { try { adsbygoogle.push(ads[i]) - console.log('adsbygoogle', i, ads[i], adsbygoogle) + // console.log('adsbygoogle', i, ads[i], adsbygoogle) } catch (e) { } diff --git a/components/PrismMac.js b/components/PrismMac.js index 172c6ceb147..38742281d11 100644 --- a/components/PrismMac.js +++ b/components/PrismMac.js @@ -141,7 +141,6 @@ const renderMermaid = async() => { if (needLoad) { loadExternalResource(BLOG.MERMAID_CDN, 'js').then(url => { const mermaid = window.mermaid - console.log('mermaid加载成功', url, mermaid) mermaid.contentLoaded() }) } diff --git a/components/QrCode.js b/components/QrCode.js new file mode 100644 index 00000000000..ca78c8816fb --- /dev/null +++ b/components/QrCode.js @@ -0,0 +1,34 @@ +import BLOG from '@/blog.config' +import { loadExternalResource } from '@/lib/utils' +import { useEffect } from 'react' + +/** + * 二维码生成 + */ +export default function QrCode({ value }) { + useEffect(() => { + let qrcode + if (!value) { + return + } + loadExternalResource(BLOG.QR_CODE_CDN, 'js').then(url => { + const QRCode = window.QRCode + qrcode = new QRCode(document.getElementById('qrcode'), { + text: value, + width: 256, + height: 256, + colorDark: '#000000', + colorLight: '#ffffff', + correctLevel: QRCode.CorrectLevel.H + }) + console.log('二维码', qrcode, value) + }) + return () => { + if (qrcode) { + qrcode.clear() // clear the code. + } + } + }, []) + + return
+} diff --git a/components/ShareButtons.js b/components/ShareButtons.js index 02ca7230ea0..efd3ab87214 100644 --- a/components/ShareButtons.js +++ b/components/ShareButtons.js @@ -1,6 +1,7 @@ import BLOG from '@/blog.config' import { useGlobal } from '@/lib/global' import copy from 'copy-to-clipboard' +import dynamic from 'next/dynamic' import { useState } from 'react' import { @@ -48,6 +49,8 @@ import { HatenaIcon } from 'react-share' +const QrCode = dynamic(() => import('@/components/QrCode'), { ssr: false }) + /** * @author https://github.com/txs * @param {*} param0 @@ -345,8 +348,8 @@ const ShareButtons = ({ shareUrl, title, body, image }) => {
-
- {/* */} +
+
{locale.COMMON.SCAN_QR_CODE} diff --git a/lib/utils.js b/lib/utils.js index e13b192f0cb..ef419793a62 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -39,8 +39,14 @@ export function loadExternalResource(url, type) { tag.src = url } if (tag) { - tag.onload = () => resolve(url) - tag.onerror = () => reject(url) + tag.onload = () => { + console.log(url, '加载成功') + resolve(url) + } + tag.onerror = () => { + console.log(url, '加载失败') + reject(url) + } document.head.appendChild(tag) } }) diff --git a/themes/gitbook/index.js b/themes/gitbook/index.js index e5fcaeac953..cde4c530736 100644 --- a/themes/gitbook/index.js +++ b/themes/gitbook/index.js @@ -53,7 +53,6 @@ const LayoutBase = (props) => { const showTocButton = post?.toc?.length > 1 useEffect(() => { - console.log('更新导航', allNavPages) setFilteredNavPages(allNavPages) }, [post]) From c7f700e2d49082537b7daf12efa6916cddc6ab1e Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Mon, 31 Jul 2023 21:54:43 +0800 Subject: [PATCH 03/13] =?UTF-8?q?CusDis=E7=BB=84=E4=BB=B6=20CDN=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/CusdisComponent.js | 41 +++++++++++++---------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/components/CusdisComponent.js b/components/CusdisComponent.js index 0e2a4f00b53..b3fa0bdac1e 100644 --- a/components/CusdisComponent.js +++ b/components/CusdisComponent.js @@ -2,6 +2,7 @@ import { useGlobal } from '@/lib/global' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { useEffect } from 'react' +import { loadExternalResource } from '@/lib/utils' const CusdisComponent = ({ frontMatter }) => { const { locale } = useGlobal() @@ -10,33 +11,21 @@ const CusdisComponent = ({ frontMatter }) => { // 处理cusdis主题 useEffect(() => { - const cusdisThread = document?.getElementById('cusdis_thread') - const cusdisIframe = cusdisThread?.getElementsByTagName('iframe') - if (cusdisIframe) { - const cusdisWrapper = cusdisIframe[0]?.contentDocument?.getElementById('root') - if (isDarkMode) { - cusdisWrapper?.classList?.remove('light') - cusdisWrapper?.classList?.add('dark') - } else { - cusdisWrapper?.classList?.remove('dark') - cusdisWrapper?.classList?.add('light') - } - if (!cusdisWrapper?.firstElementChild?.classList?.contains('dark:text-gray-100')) { - cusdisWrapper?.firstElementChild?.classList?.add('dark:text-gray-100') - } - } - }) + loadExternalResource(BLOG.COMMENT_CUSDIS_SCRIPT_SRC, 'js').then(url => { + const CUSDIS = window.CUSDIS + CUSDIS.initial() + }) + }, [isDarkMode]) - return
+ return
} export default CusdisComponent From 0ae88e975ad423a8beea33a78dee4cded1db70c7 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Mon, 31 Jul 2023 22:17:10 +0800 Subject: [PATCH 04/13] Ackee --- blog.config.js | 10 ++++------ components/Ackee.js | 35 ++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/blog.config.js b/blog.config.js index 9f8511b8b6e..cea4584515a 100644 --- a/blog.config.js +++ b/blog.config.js @@ -309,12 +309,10 @@ const BLOG = { ANALYTICS_CNZZ_ID: process.env.NEXT_PUBLIC_ANALYTICS_CNZZ_ID || '', // 只需要填写站长统计的id, [cnzz_id] -> https://s9.cnzz.com/z_stat.php?id=[cnzz_id]&web_id=[cnzz_id] ANALYTICS_GOOGLE_ID: process.env.NEXT_PUBLIC_ANALYTICS_GOOGLE_ID || '', // 谷歌Analytics的id e.g: G-XXXXXXXXXX - ANALYTICS_ACKEE_TRACKER: - process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || '', // e.g 'https://ackee.tangly1024.net/tracker.js' - ANALYTICS_ACKEE_DATA_SERVER: - process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.net , don't end with a slash - ANALYTICS_ACKEE_DOMAIN_ID: - process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b' + // ACKEE网站访客统计工具 + ANALYTICS_ACKEE_TRACKER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || 'https://cdn.jsdelivr.net/npm/ackee-tracker@5.1.0/dist/ackee-tracker.min.js', // e.g 'https://ackee.tangly1024.net/tracker.js' + ANALYTICS_ACKEE_DATA_SERVER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.net , don't end with a slash + ANALYTICS_ACKEE_DOMAIN_ID: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b' SEO_GOOGLE_SITE_VERIFICATION: process.env.NEXT_PUBLIC_SEO_GOOGLE_SITE_VERIFICATION || '', // Remove the value or replace it with your own google site verification code diff --git a/components/Ackee.js b/components/Ackee.js index f17d536d57a..0be74ecdac6 100644 --- a/components/Ackee.js +++ b/components/Ackee.js @@ -1,19 +1,28 @@ // import { useRouter } from 'next/router' -// import BLOG from '@/blog.config' +import BLOG from '@/blog.config' +import { loadExternalResource } from '@/lib/utils' +import { useEffect } from 'react' const Ackee = () => { -// const router = useRouter() -// useAckee( -// router.asPath, -// { -// server: BLOG.ANALYTICS_ACKEE_DATA_SERVER, -// domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID -// }, -// { -// detailed: false, -// ignoreLocalhost: true -// } -// ) + useEffect(() => { + loadExternalResource(BLOG.ANALYTICS_ACKEE_TRACKER, 'js').then(url => { + const ackeeTracker = window.ackeeTracker + console.log('ackeeTracker', ackeeTracker) + }) + }) + + // const router = useRouter() + // useAckee( + // router.asPath, + // { + // server: BLOG.ANALYTICS_ACKEE_DATA_SERVER, + // domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID + // }, + // { + // detailed: false, + // ignoreLocalhost: true + // } + // ) return null } From 115b43b4298f558952b73d472a22dc5bb1c931d1 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Tue, 1 Aug 2023 11:48:04 +0800 Subject: [PATCH 05/13] ACKEE --- blog.config.js | 6 ++-- components/Ackee.js | 75 +++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/blog.config.js b/blog.config.js index cea4584515a..216d925cc70 100644 --- a/blog.config.js +++ b/blog.config.js @@ -310,9 +310,9 @@ const BLOG = { ANALYTICS_GOOGLE_ID: process.env.NEXT_PUBLIC_ANALYTICS_GOOGLE_ID || '', // 谷歌Analytics的id e.g: G-XXXXXXXXXX // ACKEE网站访客统计工具 - ANALYTICS_ACKEE_TRACKER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || 'https://cdn.jsdelivr.net/npm/ackee-tracker@5.1.0/dist/ackee-tracker.min.js', // e.g 'https://ackee.tangly1024.net/tracker.js' - ANALYTICS_ACKEE_DATA_SERVER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.net , don't end with a slash - ANALYTICS_ACKEE_DOMAIN_ID: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b' + ANALYTICS_ACKEE_TRACKER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || '', // e.g 'https://ackee.tangly1024.com/tracker.js' + ANALYTICS_ACKEE_DATA_SERVER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.com , don't end with a slash + ANALYTICS_ACKEE_DOMAIN_ID: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '82e51db6-dec2-423a-b7c9-b4ff7ebb3302' SEO_GOOGLE_SITE_VERIFICATION: process.env.NEXT_PUBLIC_SEO_GOOGLE_SITE_VERIFICATION || '', // Remove the value or replace it with your own google site verification code diff --git a/components/Ackee.js b/components/Ackee.js index 0be74ecdac6..63b47037d2f 100644 --- a/components/Ackee.js +++ b/components/Ackee.js @@ -1,29 +1,64 @@ -// import { useRouter } from 'next/router' +'use strict' + +import { useEffect } from 'react' import BLOG from '@/blog.config' import { loadExternalResource } from '@/lib/utils' -import { useEffect } from 'react' +import { useRouter } from 'next/router' const Ackee = () => { + const router = useRouter() useEffect(() => { - loadExternalResource(BLOG.ANALYTICS_ACKEE_TRACKER, 'js').then(url => { - const ackeeTracker = window.ackeeTracker - console.log('ackeeTracker', ackeeTracker) - }) - }) - - // const router = useRouter() - // useAckee( - // router.asPath, - // { - // server: BLOG.ANALYTICS_ACKEE_DATA_SERVER, - // domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID - // }, - // { - // detailed: false, - // ignoreLocalhost: true - // } - // ) + handleAckee( + router.asPath, + { + server: BLOG.ANALYTICS_ACKEE_DATA_SERVER, + domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID + }, + { + detailed: false, + ignoreLocalhost: false + } + ) + }, [router]) + return null } export default Ackee + +/** + * Function to use Ackee. + * Creates an instance once and a new record every time the pathname changes. + * Safely no-ops during server-side rendering. + * @param {?String} pathname - Current path. + * @param {Object} environment - Object containing the URL of the Ackee server and the domain id. + * @param {?Object} options - Ackee options. + */ +const handleAckee = async function(pathname, environment, options = {}) { + await loadExternalResource(BLOG.ANALYTICS_ACKEE_TRACKER, 'js') + const ackeeTracker = window.ackeeTracker + + const instance = ackeeTracker.create(environment.server, options) + + if (instance == null) { + console.warn('Skipped record creation because useAckee has been called in a non-browser environment') + return + } + + const hasPathname = ( + pathname != null && pathname !== '' + ) + + if (hasPathname === false) { + console.warn('Skipped record creation because useAckee has been called without pathname') + return + } + + const attributes = ackeeTracker.attributes(options.detailed) + const url = new URL(pathname, location) + + return instance.record(environment.domainId, { + ...attributes, + siteLocation: url.href + }).stop +} From 6eb50b11385c6167fd9317cec02d36d861457083 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Tue, 1 Aug 2023 12:47:33 +0800 Subject: [PATCH 06/13] =?UTF-8?q?isBrowser=E6=96=B9=E6=B3=95=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Comment.js | 2 +- components/ExternalScript.js | 2 +- components/FullScreenButton.js | 2 +- components/NotionPage.js | 2 +- components/Twikoo.js | 3 +-- lib/global.js | 2 +- lib/lang.js | 2 +- lib/utils.js | 16 ++++++++-------- pages/[prefix]/index.js | 2 +- pages/archive/index.js | 2 +- themes/example/index.js | 2 +- themes/fukasawa/components/BlogListPage.js | 2 +- themes/fukasawa/index.js | 4 ++-- themes/gitbook/components/Catalog.js | 2 +- themes/gitbook/components/Progress.js | 2 +- themes/gitbook/index.js | 2 +- themes/heo/components/NavBar.js | 4 ++-- themes/heo/components/Swipe.js | 2 +- themes/hexo/components/Progress.js | 2 +- themes/hexo/index.js | 4 ++-- themes/matery/components/Progress.js | 2 +- themes/medium/components/Progress.js | 2 +- themes/medium/index.js | 2 +- themes/next/components/Progress.js | 2 +- themes/next/index.js | 6 +++--- themes/nobelium/index.js | 2 +- themes/plog/index.js | 2 +- themes/simple/index.js | 4 ++-- 28 files changed, 41 insertions(+), 42 deletions(-) diff --git a/components/Comment.js b/components/Comment.js index 2baebfbb52a..1b335fe793c 100644 --- a/components/Comment.js +++ b/components/Comment.js @@ -62,7 +62,7 @@ const ValineComponent = dynamic(() => import('@/components/ValineComponent'), { const Comment = ({ frontMatter, className }) => { const router = useRouter() - if (isBrowser() && ('giscus' in router.query || router.query.target === 'comment')) { + if (isBrowser && ('giscus' in router.query || router.query.target === 'comment')) { setTimeout(() => { const url = router.asPath.replace('?target=comment', '') history.replaceState({}, '', url) diff --git a/components/ExternalScript.js b/components/ExternalScript.js index 62b6e95c3f8..7f5d015d57b 100644 --- a/components/ExternalScript.js +++ b/components/ExternalScript.js @@ -8,7 +8,7 @@ import { isBrowser, loadExternalResource } from '@/lib/utils' * @returns */ const ExternalScript = () => { - if (isBrowser()) { + if (isBrowser) { // 静态导入本地自定义样式 loadExternalResource('/css/custom.css', 'css') loadExternalResource('/js/custom.js', 'js') diff --git a/components/FullScreenButton.js b/components/FullScreenButton.js index 053de666968..6c7ec2e41dd 100644 --- a/components/FullScreenButton.js +++ b/components/FullScreenButton.js @@ -9,7 +9,7 @@ const FullScreenButton = () => { const [isFullScreen, setIsFullScreen] = useState(false) const handleFullScreenClick = () => { - if (!isBrowser()) { + if (!isBrowser) { return } const element = document.documentElement diff --git a/components/NotionPage.js b/components/NotionPage.js index 0ff61e11406..1cbfad3686d 100644 --- a/components/NotionPage.js +++ b/components/NotionPage.js @@ -65,7 +65,7 @@ const NotionPage = ({ post, className }) => { // 将相册gallery下的图片加入放大功能 if (JSON.parse(BLOG.POST_DISABLE_GALLERY_CLICK)) { setTimeout(() => { - if (isBrowser()) { + if (isBrowser) { const imgList = document?.querySelectorAll('.notion-collection-card-cover img') if (imgList && zoomRef.current) { for (let i = 0; i < imgList.length; i++) { diff --git a/components/Twikoo.js b/components/Twikoo.js index 7b6080b6e71..233e77adf1e 100644 --- a/components/Twikoo.js +++ b/components/Twikoo.js @@ -13,8 +13,7 @@ import { useEffect } from 'react' const Twikoo = ({ isDarkMode }) => { const loadTwikoo = async () => { try { - const url = await loadExternalResource(BLOG.COMMENT_TWIKOO_CDN_URL, 'js') - console.log('twikoo 加载成功', url) + await loadExternalResource(BLOG.COMMENT_TWIKOO_CDN_URL, 'js') const twikoo = window.twikoo twikoo.init({ envId: BLOG.COMMENT_TWIKOO_ENV_ID, // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app) diff --git a/lib/global.js b/lib/global.js index 04d0176e5e7..c290a9e0dfd 100644 --- a/lib/global.js +++ b/lib/global.js @@ -91,7 +91,7 @@ export function GlobalContextProvider(props) { * @param {*} setTheme */ const initTheme = () => { - if (isBrowser()) { + if (isBrowser) { setTimeout(() => { const elements = document.querySelectorAll('[id^="theme-"]') if (elements?.length > 1) { diff --git a/lib/lang.js b/lib/lang.js index 83f867b31bd..abc51354858 100644 --- a/lib/lang.js +++ b/lib/lang.js @@ -64,7 +64,7 @@ export function generateLocaleDict(langString) { * 根据用户当前浏览器语言进行切换 */ export function initLocale(lang, locale, changeLang, changeLocale) { - if (isBrowser()) { + if (isBrowser) { const queryLang = getQueryVariable('lang') || loadLangFromCookies() || window.navigator.language let currentLang = lang if (queryLang !== lang) { diff --git a/lib/utils.js b/lib/utils.js index ef419793a62..5f5d864dfbf 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,6 +1,12 @@ // 封装异步加载资源的方法 import { memo } from 'react' +/** + * 判断是否客户端 + * @returns {boolean} + */ +export const isBrowser = typeof window !== 'undefined' + /** * 组件持久化 */ @@ -58,7 +64,7 @@ export function loadExternalResource(url, type) { * @returns */ export function getQueryVariable(key) { - const query = isBrowser() ? window.location.search.substring(1) : '' + const query = isBrowser ? window.location.search.substring(1) : '' const vars = query.split('&') for (let i = 0; i < vars.length; i++) { const pair = vars[i].split('=') @@ -143,12 +149,6 @@ export function deepClone(obj) { */ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms)) -/** - * 判断是否客户端 - * @returns {boolean} - */ -export const isBrowser = () => typeof window !== 'undefined' - /** * 获取从第1页到指定页码的文章 * @param pageIndex 第几页 @@ -168,7 +168,7 @@ export const getListByPage = function (list, pageIndex, pageSize) { */ export const isMobile = () => { let isMobile = false - if (!isBrowser()) { + if (!isBrowser) { return isMobile } diff --git a/pages/[prefix]/index.js b/pages/[prefix]/index.js index 5f6ac5c8b6e..079f1a83be0 100644 --- a/pages/[prefix]/index.js +++ b/pages/[prefix]/index.js @@ -41,7 +41,7 @@ const Slug = props => { // 404 if (!post) { setTimeout(() => { - if (isBrowser()) { + if (isBrowser) { const article = document.getElementById('notion-article') if (!article) { router.push('/404').then(() => { diff --git a/pages/archive/index.js b/pages/archive/index.js index 1ef1f216865..106ad7d2df5 100644 --- a/pages/archive/index.js +++ b/pages/archive/index.js @@ -15,7 +15,7 @@ const ArchiveIndex = props => { const Layout = getLayoutByTheme(useRouter()) useEffect(() => { - if (isBrowser()) { + if (isBrowser) { const anchor = window.location.hash if (anchor) { setTimeout(() => { diff --git a/themes/example/index.js b/themes/example/index.js index 0772f7fdea0..36ec9108e2f 100644 --- a/themes/example/index.js +++ b/themes/example/index.js @@ -177,7 +177,7 @@ const LayoutSearch = props => { const slotTop =
const router = useRouter() useEffect(() => { - if (isBrowser()) { + if (isBrowser) { // 高亮搜索到的结果 const container = document.getElementById('posts-wrapper') if (keyword && container) { diff --git a/themes/fukasawa/components/BlogListPage.js b/themes/fukasawa/components/BlogListPage.js index b48655f202f..30f0c38b5df 100644 --- a/themes/fukasawa/components/BlogListPage.js +++ b/themes/fukasawa/components/BlogListPage.js @@ -77,7 +77,7 @@ const BlogListPage = ({ page = 1, posts = [], postCount, siteInfo }) => { * @returns */ const calculateColumns = () => { - if (!isBrowser()) { + if (!isBrowser) { return 3 } else { if (window.innerWidth >= 1024) { diff --git a/themes/fukasawa/index.js b/themes/fukasawa/index.js index 6b5eb94b699..2e867cde337 100644 --- a/themes/fukasawa/index.js +++ b/themes/fukasawa/index.js @@ -57,7 +57,7 @@ const LayoutBase = (props) => { // 在组件卸载时保存 open 状态到本地存储中 useEffect(() => { - if (isBrowser()) { + if (isBrowser) { localStorage.setItem('fukasawa-sidebar-collapse', isCollapsed) } }, [isCollapsed]) @@ -149,7 +149,7 @@ const LayoutSearch = props => { const { keyword } = props const router = useRouter() useEffect(() => { - if (isBrowser()) { + if (isBrowser) { replaceSearchResult({ doms: document.getElementById('posts-wrapper'), search: keyword, diff --git a/themes/gitbook/components/Catalog.js b/themes/gitbook/components/Catalog.js index 5a51bee68dd..f6722511dba 100644 --- a/themes/gitbook/components/Catalog.js +++ b/themes/gitbook/components/Catalog.js @@ -49,7 +49,7 @@ const Catalog = ({ post }) => { } setActiveSection(currentSectionId) const index = tocIds.indexOf(currentSectionId) || 0 - if (isBrowser() && tocIds?.length > 0) { + if (isBrowser && tocIds?.length > 0) { for (const tocWrapper of document?.getElementsByClassName('toc-wrapper')) { tocWrapper?.scrollTo({ top: 28 * index, behavior: 'smooth' }) } diff --git a/themes/gitbook/components/Progress.js b/themes/gitbook/components/Progress.js index bca7a17d96d..669d09a84c7 100644 --- a/themes/gitbook/components/Progress.js +++ b/themes/gitbook/components/Progress.js @@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (isBrowser() && document.getElementById('posts-wrapper')) + const target = currentRef || (isBrowser && document.getElementById('posts-wrapper')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/gitbook/index.js b/themes/gitbook/index.js index cde4c530736..d67dbb63f95 100644 --- a/themes/gitbook/index.js +++ b/themes/gitbook/index.js @@ -170,7 +170,7 @@ const LayoutIndex = (props) => { router.push(CONFIG.INDEX_PAGE).then(() => { // console.log('跳转到指定首页', CONFIG.INDEX_PAGE) setTimeout(() => { - if (isBrowser()) { + if (isBrowser) { const article = document.getElementById('notion-article') if (!article) { console.log('请检查您的Notion数据库中是否包含此slug页面: ', CONFIG.INDEX_PAGE) diff --git a/themes/heo/components/NavBar.js b/themes/heo/components/NavBar.js index cd1c205bf99..eff61f68f18 100644 --- a/themes/heo/components/NavBar.js +++ b/themes/heo/components/NavBar.js @@ -84,12 +84,12 @@ const NavBar = props => { } } - if (isBrowser()) { + if (isBrowser) { window.addEventListener('scroll', handleScroll) } return () => { - if (isBrowser()) { + if (isBrowser) { window.removeEventListener('scroll', handleScroll) } } diff --git a/themes/heo/components/Swipe.js b/themes/heo/components/Swipe.js index f8d4be3e2d2..6afc5f274d4 100644 --- a/themes/heo/components/Swipe.js +++ b/themes/heo/components/Swipe.js @@ -11,7 +11,7 @@ export function Swipe({ items }) { const [activeIndex, setActiveIndex] = useState(0) const handleClick = (item) => { - if (isBrowser()) { + if (isBrowser) { window.open(item?.url) } } diff --git a/themes/hexo/components/Progress.js b/themes/hexo/components/Progress.js index 5b4f9b20fea..59ee1697934 100644 --- a/themes/hexo/components/Progress.js +++ b/themes/hexo/components/Progress.js @@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (isBrowser() && document.getElementById('article-wrapper')) + const target = currentRef || (isBrowser && document.getElementById('article-wrapper')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/hexo/index.js b/themes/hexo/index.js index c07e70a0b97..e550c7b2f69 100644 --- a/themes/hexo/index.js +++ b/themes/hexo/index.js @@ -191,7 +191,7 @@ const LayoutSlug = props => { const { post, lock, validPassword } = props const drawerRight = useRef(null) - const targetRef = isBrowser() ? document.getElementById('article-wrapper') : null + const targetRef = isBrowser ? document.getElementById('article-wrapper') : null const floatSlot = <> {post?.toc?.length > 1 &&
@@ -254,7 +254,7 @@ const Layout404 = props => { useEffect(() => { // 延时3秒如果加载失败就返回首页 setTimeout(() => { - if (isBrowser()) { + if (isBrowser) { const article = document.getElementById('notion-article') if (!article) { router.push('/').then(() => { diff --git a/themes/matery/components/Progress.js b/themes/matery/components/Progress.js index d6a68fe8034..dcdea5bae6c 100644 --- a/themes/matery/components/Progress.js +++ b/themes/matery/components/Progress.js @@ -11,7 +11,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const [percent, changePercent] = useState(0) const scrollListener = () => { requestAnimationFrame(() => { - const target = currentRef || (isBrowser() && document.getElementById('article-wrapper')) + const target = currentRef || (isBrowser && document.getElementById('article-wrapper')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/medium/components/Progress.js b/themes/medium/components/Progress.js index b57a3bb5037..62e1cc87715 100644 --- a/themes/medium/components/Progress.js +++ b/themes/medium/components/Progress.js @@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (isBrowser() && document.getElementById('article-wrapper')) + const target = currentRef || (isBrowser && document.getElementById('article-wrapper')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/medium/index.js b/themes/medium/index.js index 01d3f904d96..82811e46f27 100644 --- a/themes/medium/index.js +++ b/themes/medium/index.js @@ -206,7 +206,7 @@ const LayoutSearch = (props) => { const currentSearch = keyword || router?.query?.s useEffect(() => { - if (isBrowser()) { + if (isBrowser) { replaceSearchResult({ doms: document.getElementById('posts-wrapper'), search: keyword, diff --git a/themes/next/components/Progress.js b/themes/next/components/Progress.js index 2f29064d201..8eab47e9e77 100644 --- a/themes/next/components/Progress.js +++ b/themes/next/components/Progress.js @@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (isBrowser() && document.getElementById('article-wrapper')) + const target = currentRef || (isBrowser && document.getElementById('article-wrapper')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/next/index.js b/themes/next/index.js index e3b079a0414..935905251c8 100644 --- a/themes/next/index.js +++ b/themes/next/index.js @@ -161,7 +161,7 @@ const LayoutSearch = (props) => { const { posts, keyword } = props useEffect(() => { - if (isBrowser()) { + if (isBrowser) { replaceSearchResult({ doms: document.getElementById('posts-wrapper'), search: keyword, @@ -201,7 +201,7 @@ const Layout404 = props => { useEffect(() => { // 延时3秒如果加载失败就返回首页 setTimeout(() => { - const article = isBrowser() && document.getElementById('article-wrapper') + const article = isBrowser && document.getElementById('article-wrapper') if (!article) { router.push('/').then(() => { // console.log('找不到页面', router.asPath) @@ -253,7 +253,7 @@ const LayoutArchive = (props) => { const LayoutSlug = (props) => { const { post, lock, validPassword } = props const drawerRight = useRef(null) - const targetRef = isBrowser() ? document.getElementById('article-wrapper') : null + const targetRef = isBrowser ? document.getElementById('article-wrapper') : null const floatSlot =
{ drawerRight?.current?.handleSwitchVisible() diff --git a/themes/nobelium/index.js b/themes/nobelium/index.js index d9a930e0c19..d175e2c920d 100644 --- a/themes/nobelium/index.js +++ b/themes/nobelium/index.js @@ -134,7 +134,7 @@ const LayoutPostList = props => { const LayoutSearch = props => { const { keyword } = props useEffect(() => { - if (isBrowser()) { + if (isBrowser) { replaceSearchResult({ doms: document.getElementById('posts-wrapper'), search: keyword, diff --git a/themes/plog/index.js b/themes/plog/index.js index 55895df4e05..0f44c2a4120 100644 --- a/themes/plog/index.js +++ b/themes/plog/index.js @@ -132,7 +132,7 @@ const LayoutSearch = props => { const { keyword } = props useEffect(() => { - if (isBrowser()) { + if (isBrowser) { replaceSearchResult({ doms: document.getElementById('posts-wrapper'), search: keyword, diff --git a/themes/simple/index.js b/themes/simple/index.js index b0c9f95c07b..13d38a87550 100644 --- a/themes/simple/index.js +++ b/themes/simple/index.js @@ -36,7 +36,7 @@ const LayoutBase = props => { const { children, slotTop, meta } = props const { onLoading } = useGlobal() - if (isBrowser()) { + if (isBrowser) { loadExternalResource('/css/theme-simple.css', 'css') } return ( @@ -122,7 +122,7 @@ const LayoutSearch = props => { const { keyword } = props useEffect(() => { - if (isBrowser()) { + if (isBrowser) { replaceSearchResult({ doms: document.getElementById('posts-wrapper'), search: keyword, From 3bdb6e439f31f5adf2e6424840804ad7f686ea69 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Tue, 1 Aug 2023 12:47:37 +0800 Subject: [PATCH 07/13] facebook --- components/FacebookMessenger.js | 247 +++++++++++++++++++++++++++++++- components/FacebookPage.js | 6 +- 2 files changed, 248 insertions(+), 5 deletions(-) diff --git a/components/FacebookMessenger.js b/components/FacebookMessenger.js index c1b84db4017..1787a7e6633 100644 --- a/components/FacebookMessenger.js +++ b/components/FacebookMessenger.js @@ -1,10 +1,249 @@ import BLOG from '@/blog.config' +import { Component } from 'react' +import PropTypes from 'prop-types' -const Messenger = () => ( -
-) -export default Messenger +} + +/** + * @see https://github.com/Yoctol/react-messenger-customer-chat + */ +class MessengerCustomerChat extends Component { + constructor(props) { + super(props) + this.state = { + fbLoaded: false, + shouldShowDialog: undefined + } + } + + componentDidMount() { + this.setFbAsyncInit() + this.reloadSDKAsynchronously() + } + + componentDidUpdate(prevProps) { + if ( + prevProps.pageId !== this.props.pageId || + prevProps.appId !== this.props.appId || + prevProps.shouldShowDialog !== this.props.shouldShowDialog || + prevProps.htmlRef !== this.props.htmlRef || + prevProps.minimized !== this.props.minimized || + prevProps.themeColor !== this.props.themeColor || + prevProps.loggedInGreeting !== this.props.loggedInGreeting || + prevProps.loggedOutGreeting !== this.props.loggedOutGreeting || + prevProps.greetingDialogDisplay !== this.props.greetingDialogDisplay || + prevProps.greetingDialogDelay !== this.props.greetingDialogDelay || + prevProps.autoLogAppEvents !== this.props.autoLogAppEvents || + prevProps.xfbml !== this.props.xfbml || + prevProps.version !== this.props.version || + prevProps.language !== this.props.language + ) { + this.setFbAsyncInit() + this.reloadSDKAsynchronously() + } + } + + componentWillUnmount() { + if (window.FB !== undefined) { + window.FB.CustomerChat.hide() + } + } + + setFbAsyncInit() { + const { appId, autoLogAppEvents, xfbml, version } = this.props + + window.fbAsyncInit = () => { + window.FB.init({ + appId, + autoLogAppEvents, + xfbml, + version: `v${version}` + }) + + this.setState({ fbLoaded: true }) + } + } + + loadSDKAsynchronously() { + const { language } = this.props; + /* eslint-disable */ + (function (d, s, id) { + var js, + fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) { + return; + } + js = d.createElement(s); + js.id = id; + js.src = `https://connect.facebook.net/${language}/sdk/xfbml.customerchat.js`; + fjs.parentNode.insertBefore(js, fjs); + })(document, 'script', 'facebook-jssdk'); + /* eslint-enable */ + } + + removeFacebookSDK() { + removeElementByIds(['facebook-jssdk', 'fb-root']) + + delete window.FB + } + + reloadSDKAsynchronously() { + this.removeFacebookSDK() + this.loadSDKAsynchronously() + } + + controlPlugin() { + const { shouldShowDialog } = this.props + + if (shouldShowDialog) { + window.FB.CustomerChat.showDialog() + } else { + window.FB.CustomerChat.hideDialog() + } + } + + subscribeEvents() { + const { onCustomerChatDialogShow, onCustomerChatDialogHide } = this.props + + if (onCustomerChatDialogShow) { + window.FB.Event.subscribe( + 'customerchat.dialogShow', + onCustomerChatDialogShow + ) + } + + if (onCustomerChatDialogHide) { + window.FB.Event.subscribe( + 'customerchat.dialogHide', + onCustomerChatDialogHide + ) + } + } + + createMarkup() { + const { + pageId, + htmlRef, + minimized, + themeColor, + loggedInGreeting, + loggedOutGreeting, + greetingDialogDisplay, + greetingDialogDelay + } = this.props + + const refAttribute = htmlRef !== undefined ? `ref="${htmlRef}"` : '' + const minimizedAttribute = + minimized !== undefined ? `minimized="${minimized}"` : '' + const themeColorAttribute = + themeColor !== undefined ? `theme_color="${themeColor}"` : '' + const loggedInGreetingAttribute = + loggedInGreeting !== undefined + ? `logged_in_greeting="${loggedInGreeting}"` + : '' + const loggedOutGreetingAttribute = + loggedOutGreeting !== undefined + ? `logged_out_greeting="${loggedOutGreeting}"` + : '' + const greetingDialogDisplayAttribute = + greetingDialogDisplay !== undefined + ? `greeting_dialog_display="${greetingDialogDisplay}"` + : '' + const greetingDialogDelayAttribute = + greetingDialogDelay !== undefined + ? `greeting_dialog_delay="${greetingDialogDelay}"` + : '' + + return { + __html: `
` + } + } + + render() { + const { fbLoaded, shouldShowDialog } = this.state + + if (fbLoaded && shouldShowDialog !== this.props.shouldShowDialog) { + document.addEventListener( + 'DOMNodeInserted', + (event) => { + const element = event.target + if ( + element.className && + typeof element.className === 'string' && + element.className.includes('fb_dialog') + ) { + this.controlPlugin() + } + }, + false + ) + this.subscribeEvents() + } + // Add a random key to rerender. Reference: + // https://stackoverflow.com/questions/30242530/dangerouslysetinnerhtml-doesnt-update-during-render + return
+ } +} + +const removeElementByIds = (ids) => { + ids.forEach((id) => { + const element = document.getElementById(id) + if (element && element.parentNode) { + element.parentNode.removeChild(element) + } + }) +} + +MessengerCustomerChat.propTypes = { + pageId: PropTypes.string.isRequired, + appId: PropTypes.string, + shouldShowDialog: PropTypes.bool, + htmlRef: PropTypes.string, + minimized: PropTypes.bool, + themeColor: PropTypes.string, + loggedInGreeting: PropTypes.string, + loggedOutGreeting: PropTypes.string, + greetingDialogDisplay: PropTypes.oneOf(['show', 'hide', 'fade']), + greetingDialogDelay: PropTypes.number, + autoLogAppEvents: PropTypes.bool, + xfbml: PropTypes.bool, + version: PropTypes.string, + language: PropTypes.string, + onCustomerChatDialogShow: PropTypes.func, + onCustomerChatDialogHide: PropTypes.func +} + +MessengerCustomerChat.defaultProps = { + appId: null, + shouldShowDialog: false, + htmlRef: undefined, + minimized: undefined, + themeColor: undefined, + loggedInGreeting: undefined, + loggedOutGreeting: undefined, + greetingDialogDisplay: undefined, + greetingDialogDelay: undefined, + autoLogAppEvents: true, + xfbml: true, + version: '11.0', + language: 'en_US', + onCustomerChatDialogShow: undefined, + onCustomerChatDialogHide: undefined +} diff --git a/components/FacebookPage.js b/components/FacebookPage.js index e4e52c93011..9acadf79676 100644 --- a/components/FacebookPage.js +++ b/components/FacebookPage.js @@ -2,13 +2,17 @@ import BLOG from '@/blog.config' import { FacebookProvider, Page } from 'react-facebook' import { FacebookIcon } from 'react-share' +/** + * facebook个人主页 + * @returns + */ const FacebookPage = () => { if (!BLOG.FACEBOOK_APP_ID && !BLOG.FACEBOOK_PAGE) { return <> } return
{BLOG.FACEBOOK_PAGE && ( -
+
Date: Tue, 1 Aug 2023 15:58:31 +0800 Subject: [PATCH 08/13] =?UTF-8?q?Ackee=20=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Ackee.js | 27 +++++++++++++++++++++++---- components/CommonScript.js | 4 ++-- lib/utils.js | 4 ++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/components/Ackee.js b/components/Ackee.js index 63b47037d2f..dd9467f0b8b 100644 --- a/components/Ackee.js +++ b/components/Ackee.js @@ -4,10 +4,11 @@ import { useEffect } from 'react' import BLOG from '@/blog.config' import { loadExternalResource } from '@/lib/utils' import { useRouter } from 'next/router' - const Ackee = () => { const router = useRouter() - useEffect(() => { + + // handleAckee 函数 + const handleAckeeCallback = () => { handleAckee( router.asPath, { @@ -15,10 +16,28 @@ const Ackee = () => { domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID }, { - detailed: false, - ignoreLocalhost: false + /* + * Enable or disable tracking of personal data. + * We recommend to ask the user for permission before turning this option on. + */ + detailed: true, + /* + * Enable or disable tracking when on localhost. + */ + ignoreLocalhost: false, + /* + * Enable or disable the tracking of your own visits. + * This is enabled by default, but should be turned off when using a wildcard Access-Control-Allow-Origin header. + * Some browsers strictly block third-party cookies. The option won't have an impact when this is the case. + */ + ignoreOwnVisits: false } ) + } + + // 或者使用其他依赖数组,根据需要执行 handleAckee + useEffect(() => { + handleAckeeCallback() }, [router]) return null diff --git a/components/CommonScript.js b/components/CommonScript.js index 6912c3cc964..4bef4da0392 100644 --- a/components/CommonScript.js +++ b/components/CommonScript.js @@ -56,12 +56,12 @@ const CommonScript = () => { {/* 代码统计 */} {/* ackee统计脚本 */} - {BLOG.ANALYTICS_ACKEE_TRACKER && ( + {/* {BLOG.ANALYTICS_ACKEE_TRACKER && (