From 22c91fff4bf79fe285063600ef2cd8bb848c8cd2 Mon Sep 17 00:00:00 2001 From: Lam Tang Date: Wed, 24 Apr 2024 20:45:19 +0800 Subject: [PATCH] refactor: a basic demo showing how to use native popover to present our content --- .../features/repo-star-tooltip/index.tsx | 92 ++++++++++--------- .../features/repo-star-tooltip/view.tsx | 5 +- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/pages/ContentScripts/features/repo-star-tooltip/index.tsx b/src/pages/ContentScripts/features/repo-star-tooltip/index.tsx index 97ef1062..27d156f9 100644 --- a/src/pages/ContentScripts/features/repo-star-tooltip/index.tsx +++ b/src/pages/ContentScripts/features/repo-star-tooltip/index.tsx @@ -1,21 +1,19 @@ -import React from 'react'; -import { render, Container } from 'react-dom'; -import elementReady from 'element-ready'; -import $ from 'jquery'; - import features from '../../../../feature-manager'; -import getGithubTheme from '../../../../helpers/get-github-theme'; +import View from './view'; +import { checkLogined } from '../../../../helpers/get-developer-info'; +import elementReady from 'element-ready'; import { getRepoName, hasRepoContainerHeader, isPublicRepoWithMeta, } from '../../../../helpers/get-repo-info'; import { getStars } from '../../../../api/repo'; -import View from './view'; import { RepoMeta, metaStore } from '../../../../api/common'; -import { checkLogined } from '../../../../helpers/get-developer-info'; -const githubTheme = getGithubTheme(); +import React from 'react'; +import { render, Container, unmountComponentAtNode } from 'react-dom'; +import $ from 'jquery'; + const featureId = features.getFeatureID(import.meta.url); let repoName: string; let stars: any; @@ -33,44 +31,56 @@ const renderTo = (container: Container) => { const init = async (): Promise => { repoName = getRepoName(); await getData(); - const isLogined = checkLogined(); - const selector = isLogined + const starButtonSelector = isLogined ? 'button[data-ga-click*="star button"]' : 'a[data-hydro-click*="star button"]'; - await elementReady(selector); - const attributes = { - 'data-tip': '', - 'data-for': 'star-tooltip', - 'data-class': `floating-window ${githubTheme}`, - 'data-place': 'left', - 'data-effect': 'solid', - 'data-delay-hide': 500, - 'data-delay-show': 1000, - style: { color: githubTheme === 'light' ? '#24292f' : '#c9d1d9' }, - 'data-text-color': githubTheme === 'light' ? '#24292F' : '#C9D1D9', - 'data-background-color': githubTheme === 'light' ? 'white' : '#161B22', - }; - $(selector).attr(attributes); + await elementReady(starButtonSelector); + const $starButton = $(starButtonSelector); + // get the position of the star button + const offset = $starButton.offset(); + if (!offset) { + return; + } + const { top, left } = offset; + const width = $starButton.outerWidth(); + const height = $starButton.outerHeight(); + if (!height || !width) { + return; + } - const container = document.createElement('div'); - container.id = featureId; - renderTo(container); - (await elementReady('#repository-container-header'))?.append(container); + $starButton[0].addEventListener('mouseenter', () => { + const popoverContainerSelector = 'div.Popover'; + const popoverContentSelector = 'div.Popover-message'; + const $popoverContent = $(popoverContentSelector); + const contentWidth = $popoverContent.outerWidth(); + if (!contentWidth) { + return; + } + const $popoverContainer = $(popoverContainerSelector); + $popoverContainer.css('display', 'block'); + $popoverContainer.css('top', `${top + height + 10}px`); + $popoverContent.removeClass('Popover-message--bottom-left'); + $popoverContent.removeClass('Popover-message--large'); + $popoverContent.css('width', '270px'); + $popoverContainer.css('left', `${left - (contentWidth - width) / 2}px`); + $popoverContent.addClass('Popover-message--top-middle'); + renderTo($popoverContent[0]); + }); + $starButton[0].addEventListener('mouseleave', () => { + const popoverContainerSelector = 'div.Popover'; + const popoverContentSelector = 'div.Popover-message'; + const $popoverContent = $(popoverContentSelector); + const $popoverContainer = $(popoverContainerSelector); + $popoverContent.addClass('Popover-message--large'); + $popoverContainer.css('display', 'none'); + if ($popoverContent.children().length > 0) { + unmountComponentAtNode($popoverContent[0]); + } + }); }; -const restore = async () => { - // Clicking another repo link in one repo will trigger a turbo:visit, - // so in a restoration visit we should be careful of the current repo. - if (repoName !== getRepoName()) { - repoName = getRepoName(); - await getData(); - } - // Ideally, we should do nothing if the container already exists. But after a tubor - // restoration visit, tooltip cannot be triggered though it exists in DOM tree. One - // way to solve this is to rerender the view to the container. At least this way works. - renderTo($(`#${featureId}`)[0]); -}; +const restore = async () => {}; features.add(featureId, { asLongAs: [isPublicRepoWithMeta, hasRepoContainerHeader], diff --git a/src/pages/ContentScripts/features/repo-star-tooltip/view.tsx b/src/pages/ContentScripts/features/repo-star-tooltip/view.tsx index dfc4cb82..b2a50d0b 100644 --- a/src/pages/ContentScripts/features/repo-star-tooltip/view.tsx +++ b/src/pages/ContentScripts/features/repo-star-tooltip/view.tsx @@ -7,7 +7,6 @@ import optionsStorage, { defaults, } from '../../../../options-storage'; import generateDataByMonth from '../../../../helpers/generate-data-by-month'; -import ReactTooltip from 'react-tooltip'; import StarChart from './StarChart'; import { RepoMeta } from '../../../../api/common'; @@ -30,7 +29,7 @@ const View = ({ stars, meta }: Props): JSX.Element | null => { if (!stars) return null; return ( - + <>
{getMessageByLocale('star_popup_title', options.locale)}
@@ -40,7 +39,7 @@ const View = ({ stars, meta }: Props): JSX.Element | null => { height={130} data={generateDataByMonth(stars, meta.updatedAt)} /> -
+ ); };