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

Make clicking an external link in Firefox close the popup #38

Merged
merged 2 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions src/deepLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,3 @@ export const getGitKrakenDeepLinkUrl = (provider: FocusViewSupportedProvider, ur

return getGKDotDevLinkUrl(redirectUrl);
};

export const openGitKrakenDeepLink = (provider: FocusViewSupportedProvider, url: string | null) => {
const deepLink = getGitKrakenDeepLinkUrl(provider, url);
if (!deepLink) {
return;
}

window.open(deepLink, '_blank');
};
21 changes: 9 additions & 12 deletions src/popup/components/ConnectAProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
import React from 'react';
import { GKDotDevUrl } from '../../shared';
import { ExternalLink } from './ExternalLink';

export const ConnectAProvider = () => {
return (
<div className="connect-provider-container">
<div className="connect-provider-prompt text-center">
<div className="text-2xl bold">Connect an integration to see all of your pull requests</div>
<div className="provider-buttons">
<a
<ExternalLink
className="provider-button text-sm text-secondary"
href={`${GKDotDevUrl}/settings/integrations?connect=github`}
target="_blank"
>
<img src="img/github-color.svg" height={24} />
<div>GitHub</div>
</a>
<a
</ExternalLink>
<ExternalLink
className="provider-button text-sm text-secondary"
href={`${GKDotDevUrl}/settings/integrations?connect=gitlab`}
target="_blank"
>
<img src="img/gitlab-color.svg" height={24} />
<div>GitLab</div>
</a>
<a
</ExternalLink>
<ExternalLink
className="provider-button text-sm text-secondary"
href={`${GKDotDevUrl}/settings/integrations?connect=bitbucket`}
target="_blank"
>
<img src="img/bitbucket-color.svg" height={24} />
<div>Bitbucket</div>
</a>
<a
</ExternalLink>
<ExternalLink
className="provider-button text-sm text-secondary"
href={`${GKDotDevUrl}/settings/integrations?connect=azure`}
target="_blank"
>
<img src="img/azuredevops-color.svg" height={24} />
<div>Azure DevOps</div>
</a>
</ExternalLink>
</div>
<div className="text-sm text-secondary italic">
*Only cloud-hosted providers are currently supported.
Expand Down
42 changes: 42 additions & 0 deletions src/popup/components/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { tabs } from 'webextension-polyfill';

type ExternalLinkProps = {
children: React.ReactNode;
className?: string;
href?: string;
onClick?: () => any;
title?: string;
};

export const ExternalLink = ({ children, className, href, onClick, title }: ExternalLinkProps) => {
return (
<a
className={className}
href={href}
rel="noreferrer noopener"
target="_blank"
title={title}
onClick={async e => {
// Opening external links in Firefox will not cause the popup to automatically close,
// so we must manually close it.

// Closing the popup window before the link has finished opening will cause Firefox to open
// the link in a new window instead of in a new tab. In order to prevent this, we manually
// open the link in a new tab and await that, then close the popup window afterwards.
e.preventDefault();

if (onClick) {
await onClick();
}
if (href) {
await tabs.create({ url: href });
}

window.close();
}}
>
{children}
</a>
);
};
26 changes: 10 additions & 16 deletions src/popup/components/FocusView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { GitProviderUtils } from '@gitkraken/provider-apis';
import { useQueryClient } from '@tanstack/react-query';
import React, { useEffect, useMemo, useState } from 'react';
import { storage } from 'webextension-polyfill';
import { openGitKrakenDeepLink } from '../../deepLink';
import { getGitKrakenDeepLinkUrl } from '../../deepLink';
import { ProviderMeta } from '../../providers';
import { GKDotDevUrl } from '../../shared';
import type {
Expand All @@ -12,6 +12,7 @@ import type {
} from '../../types';
import { useFocusViewConnectedProviders, useFocusViewDataQuery, usePullRequestDraftCountsQuery } from '../hooks';
import { ConnectAProvider } from './ConnectAProvider';
import { ExternalLink } from './ExternalLink';

type PullRequestRowProps = {
userId: string;
Expand All @@ -22,17 +23,17 @@ type PullRequestRowProps = {

const PullRequestRow = ({ userId, pullRequest, provider, draftCount = 0 }: PullRequestRowProps) => {
const queryClient = useQueryClient();
const deepLinkUrl = getGitKrakenDeepLinkUrl(provider, pullRequest.url);

return (
<>
<div className="pull-request">
<div className="pull-request-title truncate">{pullRequest.title}</div>
<div className="repository-name text-secondary truncate">{pullRequest.repository.name}</div>
<div className="pull-request-number">
<a
<ExternalLink
className="text-link"
href={pullRequest.url || undefined}
target="_blank"
onClick={() => {
// Since there is a decent chance that the PR will be acted upon after the user clicks on it,
// mark the focus view data as stale so that it will be refetched when the user returns.
Expand All @@ -41,32 +42,25 @@ const PullRequestRow = ({ userId, pullRequest, provider, draftCount = 0 }: PullR
title={`View pull request on ${ProviderMeta[provider].name}`}
>
#{pullRequest.number}
</a>
</ExternalLink>
</div>
{pullRequest.url && (
<a
href="#"
onClick={() => {
openGitKrakenDeepLink(provider, pullRequest.url);
}}
title="Open with GitKraken"
>
{deepLinkUrl && (
<ExternalLink href={deepLinkUrl} title="Open with GitKraken">
<i className="fa-brands fa-gitkraken icon text-link text-lg" />
</a>
</ExternalLink>
)}
</div>
{draftCount > 0 && (
<a
<ExternalLink
className="pr-drafts-badge text-disabled"
href={`${GKDotDevUrl}/drafts/suggested-change/${encodeURIComponent(
btoa(pullRequest.uniqueId),
)}?source=browserExtension`}
target="_blank"
title={`View code suggestion${draftCount === 1 ? '' : 's'} on gitkraken.dev`}
>
<i className="fa-regular fa-message-code icon" />
Code Suggestion{draftCount === 1 ? '' : 's'}
</a>
</ExternalLink>
)}
</>
);
Expand Down
5 changes: 3 additions & 2 deletions src/popup/components/SignedIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { logoutUser } from '../../gkApi';
import type { PermissionsRequest } from '../../permissions-helper';
import { GKDotDevUrl } from '../../shared';
import type { User } from '../../types';
import { ExternalLink } from './ExternalLink';
import { FocusView } from './FocusView';
import { RequestPermissionsBanner } from './RequestPermissionsBanner';

Expand Down Expand Up @@ -45,9 +46,9 @@ export const SignedIn = ({ permissionsRequest, user }: { permissionsRequest?: Pe
<div>{user.name || user.username}</div>
<div className="text-sm text-secondary">{user.email}</div>
</div>
<a href={GKDotDevUrl} target="_blank" title="Open gitkraken.dev">
<ExternalLink href={GKDotDevUrl} title="Open gitkraken.dev">
<i className="fa-regular fa-arrow-up-right-from-square icon text-lg" />
</a>
</ExternalLink>
</div>
<button className="icon-btn" onClick={onSignOutClick} title="Sign out">
<i className="fa-regular fa-right-from-bracket icon text-lg" />
Expand Down
9 changes: 5 additions & 4 deletions src/popup/components/SignedOut.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import type { PermissionsRequest } from '../../permissions-helper';
import { GKDotDevUrl } from '../../shared';
import { ExternalLink } from './ExternalLink';
import { RequestPermissionsBanner } from './RequestPermissionsBanner';

export const SignedOut = ({ permissionsRequest }: { permissionsRequest?: PermissionsRequest }) => {
Expand All @@ -9,13 +10,13 @@ export const SignedOut = ({ permissionsRequest }: { permissionsRequest?: Permiss
{permissionsRequest && <RequestPermissionsBanner permissionsRequest={permissionsRequest} />}
<div className="sign-in-prompt">
<div className="text-2xl bold">Sign in to view your Pull Requests</div>
<a className="sign-in-link text-sm text-secondary bg-02" href={`${GKDotDevUrl}/login`} target="_blank">
<ExternalLink className="sign-in-link text-sm text-secondary bg-02" href={`${GKDotDevUrl}/login`}>
<img src="img/gk-logo-36.svg" height={36} width={36} />
Sign in with GitKraken
</a>
<a className="text-link" href={`${GKDotDevUrl}/register`} target="_blank">
</ExternalLink>
<ExternalLink className="text-link" href={`${GKDotDevUrl}/register`}>
Create an account
</a>
</ExternalLink>
</div>
</div>
);
Expand Down
Loading