From 54edc01e3574cac2fee26d8baa9fdc541bc70e3c Mon Sep 17 00:00:00 2001 From: Florent Date: Thu, 3 Jun 2021 15:08:05 +0200 Subject: [PATCH] Fix duplication and cropped hovercard in `user-local-time` (#4384) --- source/features/user-local-time.css | 5 ++ source/features/user-local-time.tsx | 108 ++++++++++++++-------------- 2 files changed, 61 insertions(+), 52 deletions(-) create mode 100644 source/features/user-local-time.css diff --git a/source/features/user-local-time.css b/source/features/user-local-time.css new file mode 100644 index 00000000000..e7fa3992904 --- /dev/null +++ b/source/features/user-local-time.css @@ -0,0 +1,5 @@ +/* Reserve some space in the hovercard to fix #4345 */ +.js-hovercard-content .Popover-message div.d-flex.mt-3 > div.overflow-hidden.ml-3:not(.rgh-user-local-time-container-added) { + /* 26px is the height of the div that is being inserted plus its margin https://user-images.githubusercontent.com/46634000/120511483-bf95ae80-c3ca-11eb-8a97-310b32ae96c0.png */ + padding-bottom: 26px !important; +} diff --git a/source/features/user-local-time.tsx b/source/features/user-local-time.tsx index 911651028fb..dc1a8cd58b7 100644 --- a/source/features/user-local-time.tsx +++ b/source/features/user-local-time.tsx @@ -1,16 +1,17 @@ /* eslint-disable no-await-in-loop */ +import './user-local-time.css'; import React from 'dom-chef'; import cache from 'webext-storage-cache'; import delay from 'delay'; import select from 'select-dom'; import onetime from 'onetime'; +import {observe} from 'selector-observer'; import {ClockIcon} from '@primer/octicons-react'; import features from '.'; import * as api from '../github-helpers/api'; import {getUsername} from '../github-helpers'; -import observeElement from '../helpers/simplified-element-observer'; interface Commit { url: string; @@ -77,68 +78,71 @@ function parseOffset(date: string): number { return (hours * 60) + (hours < 0 ? -minutes : minutes); } -function init(): void { - const hovercard = select('.js-hovercard-content > .Popover-message')!; - - observeElement(hovercard, async () => { - if ( - select.exists('.rgh-local-user-time', hovercard) || // Time already added - !select.exists('[data-hydro-view*="user-hovercard-hover"]', hovercard) // It's not the hovercard type we expect - ) { - return; - } +async function insertUserLocalTime(hovercardContainer: Element): Promise { + const hovercard = hovercardContainer.closest('div.Popover-message')!; + if (!select.exists('[data-hydro-view*="user-hovercard-hover"]', hovercard)) { + // It's not the hovercard type we expect + return; + } - const login = select('a[data-octo-dimensions="link_type:profile"]', hovercard)?.pathname.slice(1); - if (!login || login === getUsername()) { - return; - } + const login = select('a[data-octo-dimensions="link_type:profile"]', hovercard)?.pathname.slice(1); + if (!login || login === getUsername()) { + return; + } - const datePromise = getLastCommitDate(login); - const race = await Promise.race([delay(300), datePromise]); - if (race === false) { - // The timezone was undeterminable and this resolved "immediately" (or was cached), so don't add the icon at all - return; - } + hovercardContainer.classList.add('rgh-user-local-time-container-added'); - const placeholder = Guessing local time…; - const container = ( -
- {placeholder} -
- ); + const datePromise = getLastCommitDate(login); + const race = await Promise.race([delay(300), datePromise]); + if (race === false) { + // The timezone was undeterminable and this resolved "immediately" (or was cached), so don't add the icon at all + return; + } - // Adding the time element might change the height of the hovercard and thus break its positioning - const hovercardHeight = hovercard.offsetHeight; + const placeholder = Guessing local time…; + const container = ( +
+ {placeholder} +
+ ); - select('div.d-flex.mt-3 > div.overflow-hidden.ml-3', hovercard)!.append(container); + // Adding the time element might change the height of the hovercard and thus break its positioning + const hovercardHeight = hovercard.offsetHeight; - if (hovercard.matches('.Popover-message--bottom-right, .Popover-message--bottom-left')) { - const diff = hovercard.offsetHeight - hovercardHeight; - if (diff > 0) { - const parent = hovercard.parentElement!; - const top = Number.parseInt(parent.style.top, 10); - parent.style.top = `${top - diff}px`; - } - } + hovercardContainer.append(container); - const date = await datePromise; - if (!date) { - placeholder.textContent = 'Timezone unknown'; - container.title = 'Timezone couldn’t be determined from their last commits'; - return; + if (hovercard.matches('.Popover-message--bottom-right, .Popover-message--bottom-left')) { + const diff = hovercard.offsetHeight - hovercardHeight; + if (diff > 0) { + const parent = hovercard.parentElement!; + const top = Number.parseInt(parent.style.top, 10); + parent.style.top = `${top - diff}px`; } + } + + const date = await datePromise; + if (!date) { + placeholder.textContent = 'Timezone unknown'; + container.title = 'Timezone couldn’t be determined from their last commits'; + return; + } - const userTime = new Date(); - userTime.setMinutes(parseOffset(date) + userTime.getTimezoneOffset() + userTime.getMinutes()); + const userTime = new Date(); + userTime.setMinutes(parseOffset(date) + userTime.getTimezoneOffset() + userTime.getMinutes()); - const timeFormatter = new Intl.DateTimeFormat(undefined, { - hour: 'numeric', - minute: 'numeric', - weekday: userTime.getDay() === new Date().getDay() ? undefined : 'long' - }); + const timeFormatter = new Intl.DateTimeFormat(undefined, { + hour: 'numeric', + minute: 'numeric', + weekday: userTime.getDay() === new Date().getDay() ? undefined : 'long' + }); + + placeholder.textContent = timeFormatter.format(userTime); + container.title = `Timezone guessed from their last commit: ${date}`; +} - placeholder.textContent = timeFormatter.format(userTime); - container.title = `Timezone guessed from their last commit: ${date}`; +function init(): void { + observe('.js-hovercard-content .Popover-message div.d-flex.mt-3 > div.overflow-hidden.ml-3:not(.rgh-user-local-time-container-added)', { + add: insertUserLocalTime }); }