Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix duplication and cropped hovercard in user-local-time #4384

Merged
merged 8 commits into from
Jun 3, 2021
5 changes: 5 additions & 0 deletions source/features/user-local-time.css
Original file line number Diff line number Diff line change
@@ -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;
}
108 changes: 56 additions & 52 deletions source/features/user-local-time.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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
cheap-glitch marked this conversation as resolved.
Show resolved Hide resolved
!select.exists('[data-hydro-view*="user-hovercard-hover"]', hovercard) // It's not the hovercard type we expect
) {
return;
}
async function insertUserLocalTime(hovercardContainer: Element): Promise<void> {
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 = <span>Guessing local time…</span>;
const container = (
<div className="rgh-local-user-time mt-2 text-gray color-text-secondary text-small">
<ClockIcon/> {placeholder}
</div>
);
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 = <span>Guessing local time…</span>;
const container = (
<div className="mt-2 text-gray color-text-secondary text-small">
<ClockIcon/> {placeholder}
</div>
);

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
});
}

Expand Down