-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: display openrank information in developer information hover card (
#832) * Modified the developer name acquisition method and tried other monitoring methods * modify evenlistener method and add openrank info * feat: add the developer-avator-openrank * Modified the presentation of OpenRank * Improved the situation when openrank does not exist * Introduce openrank information to the bottom of the hovercard * Modify the names of some functions and fields * Add view.tsx and Adjust some details * Adjust openrank icon position * Solved the problem of mismatch between OpenRank information and people * Fixed the bug that OpenRank information was added multiple times * Adjust the display position of OpenRank * Introducing the renderTo function
- Loading branch information
1 parent
2e31b67
commit 32c6369
Showing
4 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
src/pages/ContentScripts/features/developer-hovercard-info/base64.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const rocketLight = | ||
'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgdD0iMTY2NDg5Mjg4OTU4NiIKICAgY2xhc3M9Imljb24iCiAgIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiCiAgIHZlcnNpb249IjEuMSIKICAgcC1pZD0iNzQzMTAiCiAgIHdpZHRoPSIzMiIKICAgaGVpZ2h0PSIzMiIKICAgaWQ9InN2ZzYiCiAgIHNvZGlwb2RpOmRvY25hbWU9IueBq+eurSAoNSkucG5nIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIxLjIgKGRjMmFlZGEsIDIwMjItMDUtMTUpIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMxMCIgLz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaWQ9Im5hbWVkdmlldzgiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjMDAwMDAwIgogICAgIGJvcmRlcm9wYWNpdHk9IjAuMjUiCiAgICAgaW5rc2NhcGU6c2hvd3BhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlY2hlY2tlcmJvYXJkPSIwIgogICAgIGlua3NjYXBlOmRlc2tjb2xvcj0iI2QxZDFkMSIKICAgICBzaG93Z3JpZD0iZmFsc2UiCiAgICAgaW5rc2NhcGU6em9vbT0iNy4zNzUiCiAgICAgaW5rc2NhcGU6Y3g9IjE1LjkzMjIwMyIKICAgICBpbmtzY2FwZTpjeT0iMTQuOTE1MjU0IgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTMxMyIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI0NTgiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjM0NiIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMTI5MSIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzYiIC8+CiAgPHBhdGgKICAgICBkPSJtIDUwNy4zODUxMywzNzYuNTk3ODIgYyAtNDYuODk5OTMsMCAtODUuMDU3NjIsMzguMTU3NjkgLTg1LjA1NzYyLDg1LjA1NzYxIDAsNDYuODk5OTMgMzguMTU3NjksODUuMDU2NDkgODUuMDU3NjIsODUuMDU2NDkgNDYuODk5OTIsMCA4NS4wNTc2MSwtMzguMTU3NjggODUuMDU3NjEsLTg1LjA1NzYxIDAsLTQ2Ljg5OTkzIC0zOC4xNTc2OSwtODUuMDU2NDkgLTg1LjA1NzYxLC04NS4wNTY0OSB6IG0gMCwxMDYuMzIwODkgYyAtMTEuNzI3NTEsMCAtMjEuMjY0NDEsLTkuNTQyNTEgLTIxLjI2NDQxLC0yMS4yNjQ0IDAsLTExLjcyMTg5IDkuNTM2OSwtMjEuMjY0NCAyMS4yNjQ0MSwtMjEuMjY0NCAxMS43Mjc1MSwwIDIxLjI2NDQsOS41NDI1MSAyMS4yNjQ0LDIxLjI2NDQgMCwxMS43MjMwMSAtOS41MzY4OSwyMS4yNjQ0IC0yMS4yNjQ0LDIxLjI2NDQgeiIKICAgICBwLWlkPSI3NDMxMSIKICAgICBmaWxsPSIjNTc2MDZhIgogICAgIGlkPSJwYXRoMiIKICAgICBzdHlsZT0ic3Ryb2tlLXdpZHRoOjA7c3Ryb2tlLWRhc2hhcnJheTpub25lIiAvPgogIDxwYXRoCiAgICAgZD0ibSA3MzguMjk3MDUsNjIzLjUwOTQ3IHYgLTk1Ljk3MDI0IGMgMCwtODcuNjk0NDUgLTI1LjE0NzcyLC0xNTEuNjY0MTIgLTcyLjcyMjAzLC0yMjUuMjA2NjUgLTMxLjY1Nzc2LC00OC45MzU0NCAtNzIuMjM0MjMsLTkwLjc5NDM2IC0xMTkuMjAxNiwtMTI0LjA5NzYxIC0xMi41NjgyNCwtOC45MDg1OSAtMjUuNTIwODgsLTE3LjI5MjI5IC0zOC45ODgyOSwtMjQuOTEzOTQgLTEzLjQ2MTgsNy42MjE2NSAtMjYuNDE0NDQsMTYuMDA1MzUgLTM4Ljk4MjY4LDI0LjkxMzk0IC00Ni45NjczNywzMy4zMDMyNSAtODcuNTQzODQsNzUuMTYyMTcgLTExOS4yMDE2LDEyNC4wOTc2MSAtNDcuNTc0MzEsNzMuNTQyNTMgLTcyLjcyMjAzLDEzNy41MTIyIC03Mi43MjIwMywyMjUuMjA2NjUgdiA5NS45NzAyNCBsIC00MS45ODM2OCw4NC41MTY5OCB2IDk3Ljg1OTY0IGggNTQ1Ljc4NTU5IHYgLTk3Ljg1OTY0IHogbSAtMjEuODA5NTMsMTE4LjU4MzQxIGggLTQxOC4yMDAzIHYgLTcuNjUxOTkgTCAzNDAuMjcwOSw2NDkuOTIzOTEgViA1MjcuNTM5MjMgYyAwLC03NS4zNzAxMSAyMS42MTE3MSwtMTI3LjM1NzEzIDYyLjQ4OTQxLC0xOTAuNTU4MDEgMjcuNzA3LC00Mi44MjQ0MSA2My4zMDk5LC03OS4zNjY5NCAxMDQuNjIzNjksLTEwOC4xOTU2NyA0MS4zMTM4LDI4LjgyODczIDc2LjkyMjMxLDY1LjM3MTI2IDEwNC42MjkzMiwxMDguMTk1NjcgNDAuODc3NjksNjMuMjAwODggNjIuNDg5NCwxMTUuMTg5MDIgNjIuNDg5NCwxOTAuNTU4MDEgdiAxMjIuMzgzNTYgbCA0MS45ODM2OCw4NC41MTY5OCB2IDcuNjUzMTEgeiBtIC0yMDkuMDk3OSwxMjcuMzg0MTEgYyAtMjUuMjA1MDQsLTEyLjg3NTA5IC00MS4zNjU0OSwtMjguNDU2NyAtNjAuNjAwMDEsLTQ2LjMyODk1IGggLTkwLjY5NTQ0IGMgMzkuOTc0MDIsNDYuNDkxOTIgODEuMDQzOTEsODQuMzgyMSAxMzcuODgwODYsMTEwLjczNDcyIGwgMTMuNDE0NTksNi4yMTg5MyAxMy40MTQ1OSwtNi4yMTg5MyBjIDU2LjgzMTM0LC0yNi4zNTE0OSA5Ny44OTU2MSwtNjQuMjM5NDMgMTM3Ljg3MDc1LC0xMTAuNzM0NzIgaCAtOTAuNjg1MzMgYyAtMTkuMjMzMzksMTcuODcxMTMgLTM1LjM5NDk2LDMzLjQ1Mzg2IC02MC42MDAwMSw0Ni4zMjg5NSB6IgogICAgIHAtaWQ9Ijc0MzEyIgogICAgIGZpbGw9IiM1NzYwNmEiCiAgICAgaWQ9InBhdGg0IgogICAgIHN0eWxlPSJzdHJva2Utd2lkdGg6MDtzdHJva2UtZGFzaGFycmF5Om5vbmUiIC8+Cjwvc3ZnPgo='; | ||
|
||
export const rocketDark = | ||
'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgdD0iMTY2NDg5Mjg4OTU4NiIKICAgY2xhc3M9Imljb24iCiAgIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiCiAgIHZlcnNpb249IjEuMSIKICAgcC1pZD0iNzQzMTAiCiAgIHdpZHRoPSIzMiIKICAgaGVpZ2h0PSIzMiIKICAgaWQ9InN2ZzYiCiAgIHNvZGlwb2RpOmRvY25hbWU9IueBq+eurSAoNSlkYXJrLnBuZyIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMS4yIChkYzJhZWRhLCAyMDIyLTA1LTE1KSIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTAiIC8+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJuYW1lZHZpZXc4IgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzAwMDAwMCIKICAgICBib3JkZXJvcGFjaXR5PSIwLjI1IgogICAgIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIKICAgICBpbmtzY2FwZTpkZXNrY29sb3I9IiNkMWQxZDEiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjcuMzc1IgogICAgIGlua3NjYXBlOmN4PSIxNS45MzIyMDMiCiAgICAgaW5rc2NhcGU6Y3k9IjE2IgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTMxMyIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI0NTgiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjM1NyIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMTM3NSIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzYiIC8+CiAgPHBhdGgKICAgICBkPSJNNTExLjk5OCAzNjAuNjQ5Yy00MS43MjcgMC03NS42NzYgMzMuOTQ5LTc1LjY3NiA3NS42NzZTNDcwLjI3MSA1MTIgNTExLjk5OCA1MTJzNzUuNjc2LTMzLjk0OSA3NS42NzYtNzUuNjc2LTMzLjk0OS03NS42NzUtNzUuNjc2LTc1LjY3NXogbTAgOTQuNTk0Yy0xMC40MzQgMC0xOC45MTktOC40OS0xOC45MTktMTguOTE5czguNDg1LTE4LjkxOSAxOC45MTktMTguOTE5YzEwLjQzNCAwIDE4LjkxOSA4LjQ5IDE4LjkxOSAxOC45MTkgMCAxMC40My04LjQ4NSAxOC45MTktMTguOTE5IDE4LjkxOXoiCiAgICAgcC1pZD0iNzQzMTEiCiAgICAgZmlsbD0iIzU3NjA2YSIKICAgICBpZD0icGF0aDIiCiAgICAgc3R5bGU9ImZpbGw6IzhiOTQ5ZTtmaWxsLW9wYWNpdHk6MSIgLz4KICA8cGF0aAogICAgIGQ9Ik03MTcuNDQxIDU4MC4zMjd2LTg1LjM4NWMwLTc4LjAyMi0yMi4zNzQtMTM0LjkzNi02NC43MDEtMjAwLjM2Ny0yOC4xNjYtNDMuNTM4LTY0LjI2Ny04MC43OC0xMDYuMDU0LTExMC40MS0xMS4xODItNy45MjYtMjIuNzA2LTE1LjM4NS0zNC42ODgtMjIuMTY2LTExLjk3NyA2Ljc4MS0yMy41MDEgMTQuMjQtMzQuNjgzIDIyLjE2Ni00MS43ODcgMjkuNjMtNzcuODg4IDY2Ljg3Mi0xMDYuMDU0IDExMC40MS00Mi4zMjcgNjUuNDMxLTY0LjcwMSAxMjIuMzQ1LTY0LjcwMSAyMDAuMzY3djg1LjM4NWwtMzcuMzUzIDc1LjE5NXY4Ny4wNjZoNDg1LjU4N3YtODcuMDY2bC0zNy4zNTMtNzUuMTk1eiBtLTE5LjQwNCAxMDUuNTA0SDMyNS45NjN2LTYuODA4bDM3LjM1My03NS4xOTVWNDk0Ljk0MmMwLTY3LjA1NyAxOS4yMjgtMTEzLjMxIDU1LjU5Ny0xNjkuNTQgMjQuNjUxLTM4LjEwMSA1Ni4zMjctNzAuNjEzIDkzLjA4NC05Ni4yNjIgMzYuNzU3IDI1LjY0OSA2OC40MzggNTguMTYxIDkzLjA4OSA5Ni4yNjIgMzYuMzY5IDU2LjIzIDU1LjU5NyAxMDIuNDg0IDU1LjU5NyAxNjkuNTR2MTA4Ljg4NWwzNy4zNTMgNzUuMTk1djYuODA5ek01MTIuMDAyIDc5OS4xNjVjLTIyLjQyNS0xMS40NTUtMzYuODAzLTI1LjMxOC01My45MTYtNDEuMjE5aC04MC42OTJjMzUuNTY1IDQxLjM2NCA3Mi4xMDUgNzUuMDc1IDEyMi42NzMgOTguNTIxTDUxMi4wMDIgODYybDExLjkzNS01LjUzM2M1MC41NjMtMjMuNDQ1IDg3LjA5OC01Ny4xNTQgMTIyLjY2NC05OC41MjFoLTgwLjY4M2MtMTcuMTEyIDE1LjktMzEuNDkxIDI5Ljc2NC01My45MTYgNDEuMjE5eiIKICAgICBwLWlkPSI3NDMxMiIKICAgICBmaWxsPSIjNTc2MDZhIgogICAgIGlkPSJwYXRoNCIKICAgICBzdHlsZT0iZmlsbDojOGI5NDllO2ZpbGwtb3BhY2l0eToxIiAvPgo8L3N2Zz4K'; |
82 changes: 82 additions & 0 deletions
82
src/pages/ContentScripts/features/developer-hovercard-info/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import features from '../../../../feature-manager'; | ||
import { getOpenrank } from '../../../../api/developer'; | ||
import elementReady from 'element-ready'; | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import View from './view'; | ||
|
||
const featureId = features.getFeatureID(import.meta.url); | ||
|
||
const getDeveloperLatestOpenrank = async (developerName: string): Promise<string | null> => { | ||
const data = await getOpenrank(developerName); | ||
if (data) { | ||
const values = Object.values(data) as string[]; | ||
const latestValue = values[values.length - 1]; | ||
return latestValue; | ||
} | ||
return null; | ||
}; | ||
|
||
const getDeveloperName = (target: HTMLElement): string | null => { | ||
const hovercardUrlAttribute = target.getAttribute('data-hovercard-url'); | ||
if (!hovercardUrlAttribute) return null; | ||
|
||
const matches = hovercardUrlAttribute.match(/\/users\/([^\/]+)\/hovercard/); | ||
return matches ? matches[1] : null; | ||
}; | ||
|
||
const renderTo = (container: HTMLElement, developerName: string, openrank: string) => { | ||
const openRankContainer = document.createElement('div'); | ||
container.appendChild(openRankContainer); | ||
ReactDOM.render(<View developerName={developerName} openrank={openrank} />, openRankContainer); | ||
}; | ||
|
||
const init = async (): Promise<void> => { | ||
let abortController = new AbortController(); | ||
const hovercardSelector = '[data-hovercard-type="user"]'; | ||
document.querySelectorAll(hovercardSelector).forEach((element) => { | ||
// isProcessing is used to Prevent OpenRank from adding duplicates | ||
element.addEventListener('mouseover', async () => { | ||
abortController.abort(); | ||
abortController = new AbortController(); | ||
const signal = abortController.signal; | ||
|
||
const developerName = getDeveloperName(element as HTMLElement) as string; | ||
|
||
// Create a unique identifier for the popover | ||
const popoverId = `popover-${developerName}`; | ||
|
||
// Get the floating card container | ||
const $popoverContainer = | ||
'body > div.logged-in.env-production.page-responsive > div.Popover.js-hovercard-content.position-absolute > div > div > div'; | ||
const popover = await elementReady($popoverContainer, { stopOnDomReady: false }); | ||
|
||
const openRankDiv = popover?.querySelector('.hypercrx-openrank-info'); | ||
const existingDeveloperName = openRankDiv?.getAttribute('data-developer-name'); | ||
if (existingDeveloperName === developerName) { | ||
return; | ||
} | ||
openRankDiv?.remove(); | ||
|
||
// Set the popover's unique identifier | ||
// make the current OpenRank information and person match | ||
popover?.setAttribute('data-popover-id', popoverId); | ||
|
||
const openrank = await getDeveloperLatestOpenrank(developerName); | ||
|
||
if (!openrank) { | ||
return; | ||
} | ||
|
||
if (!signal.aborted && popover && popover.getAttribute('data-popover-id') === popoverId) { | ||
// Check if the popover is still associated with the correct developer | ||
renderTo(popover, developerName, openrank); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
features.add(featureId, { | ||
awaitDomReady: false, | ||
init, | ||
}); |
35 changes: 35 additions & 0 deletions
35
src/pages/ContentScripts/features/developer-hovercard-info/view.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
import getGithubTheme from '../../../../helpers/get-github-theme'; | ||
import '../../../../helpers/i18n'; | ||
import { rocketLight, rocketDark } from './base64'; | ||
|
||
interface OpenRankProps { | ||
developerName: string; | ||
openrank: string; | ||
} | ||
|
||
const View: React.FC<OpenRankProps> = ({ developerName, openrank }) => { | ||
const theme = getGithubTheme() as 'light' | 'dark'; | ||
|
||
const textColor = theme === 'light' ? '#717981' : '#878f98'; | ||
const fontSize = '13px'; | ||
|
||
return ( | ||
<div className={`hypercrx-openrank-info ${theme}`} data-developer-name={developerName}> | ||
<div className="openrank-info"> | ||
<img | ||
width={20} | ||
height={20} | ||
style={{ display: 'inline-block', verticalAlign: 'middle', position: 'relative', left: '-2.5px' }} | ||
src={theme === 'light' ? rocketLight : rocketDark} | ||
alt="" | ||
/> | ||
<span style={{ display: 'inline-block', verticalAlign: 'middle', color: textColor, fontSize: fontSize }}> | ||
OpenRank {openrank} | ||
</span> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default View; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters