forked from gitpod-io/gitpod
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browser Extension Advertisement (gitpod-io#19650)
* Browser Extension in-app banner * add icons * Prevent undefined browsers * Local storage control * use sessionstorage * Tweak colors and hide on small viewports * Dismiss button * Universal icon * fix icon * reset button * Remove unused class * Fix close button? * Modify layout * add missing browsers * Fix extra whitespace * do not show when autostarting * remove duplicate type dep * Prevent flashing * Apply new copy Co-authored-by: Lou Bichard <[email protected]> * Address review comments Co-authored-by: Brad Harris <[email protected]> * Fix svg path * fix colors * Layout * minor changis * 🤷♂️ * Fix spacing and max width * Layout fixes * Bigger top margin * Dynamic auth provider message * Update dashboard typescript * ui updates * Fix center alignment I literally have no idea why this works * sort provider names and show only when a ff is on * Track events * Open in new tab * margin to the right of the img * Rename event * Remove duplicate sort * Organize imports * some design tweaks from pr review * extend right padding * fix text size * revert text size change and update screenshot padding --------- Co-authored-by: Lou Bichard <[email protected]> Co-authored-by: Brad Harris <[email protected]>
- Loading branch information
1 parent
f48dc13
commit 8f3888d
Showing
11 changed files
with
219 additions
and
1 deletion.
There are no files selected for viewing
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
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
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
Binary file not shown.
Binary file not shown.
Binary file not shown.
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
185 changes: 185 additions & 0 deletions
185
components/dashboard/src/workspaces/BrowserExtensionBanner.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,185 @@ | ||
/** | ||
* Copyright (c) 2023 Gitpod GmbH. All rights reserved. | ||
* Licensed under the GNU Affero General Public License (AGPL). | ||
* See License.AGPL.txt in the project root for license information. | ||
*/ | ||
|
||
import { useCallback, useEffect, useMemo, useState } from "react"; | ||
import UAParser from "ua-parser-js"; | ||
import { useUserLoader } from "../hooks/use-user-loader"; | ||
import { User } from "@gitpod/public-api/lib/gitpod/v1/user_pb"; | ||
import { AuthProviderDescription, AuthProviderType } from "@gitpod/public-api/lib/gitpod/v1/authprovider_pb"; | ||
import { useAuthProviderDescriptions } from "../data/auth-providers/auth-provider-descriptions-query"; | ||
import { useFeatureFlag } from "../data/featureflag-query"; | ||
import { trackEvent } from "../Analytics"; | ||
|
||
import bitbucketButton from "../images/browser-extension/bitbucket.webp"; | ||
import githubButton from "../images/browser-extension/github.webp"; | ||
import gitlabButton from "../images/browser-extension/gitlab.webp"; | ||
|
||
const browserExtensionImages = { | ||
Bitbucket: bitbucketButton, | ||
GitHub: githubButton, | ||
GitLab: gitlabButton, | ||
} as const; | ||
|
||
type BrowserOption = { | ||
type: "firefox" | "chromium"; | ||
aliases?: string[]; | ||
url: string; | ||
}; | ||
type UnifiedAuthProvider = "Bitbucket" | "GitLab" | "GitHub"; | ||
|
||
const installationOptions: BrowserOption[] = [ | ||
{ | ||
type: "firefox", | ||
aliases: ["firefox"], | ||
url: "https://addons.mozilla.org/en-US/firefox/addon/gitpod/", | ||
}, | ||
{ | ||
type: "chromium", | ||
aliases: ["chrome", "edge", "brave", "chromium", "vivaldi", "opera"], | ||
url: "https://chrome.google.com/webstore/detail/gitpod-always-ready-to-co/dodmmooeoklaejobgleioelladacbeki", | ||
}, | ||
]; | ||
|
||
const isIdentity = (identity?: AuthProviderDescription): identity is AuthProviderDescription => !!identity; | ||
const unifyProviderType = (type: AuthProviderType): UnifiedAuthProvider | undefined => { | ||
switch (type) { | ||
case AuthProviderType.BITBUCKET: | ||
case AuthProviderType.BITBUCKET_SERVER: | ||
return "Bitbucket"; | ||
case AuthProviderType.GITHUB: | ||
return "GitHub"; | ||
case AuthProviderType.GITLAB: | ||
return "GitLab"; | ||
default: | ||
return undefined; | ||
} | ||
}; | ||
|
||
const isAuthProviderType = (type?: UnifiedAuthProvider): type is UnifiedAuthProvider => !!type; | ||
const getDeduplicatedScmProviders = (user: User, descriptions: AuthProviderDescription[]): UnifiedAuthProvider[] => { | ||
const userIdentities = user.identities.map((identity) => identity.authProviderId); | ||
const userProviders = userIdentities | ||
.map((id) => descriptions?.find((provider) => provider.id === id)) | ||
.filter(isIdentity) | ||
.map((provider) => provider.type); | ||
|
||
return userProviders | ||
.map((type) => unifyProviderType(type)) | ||
.filter(isAuthProviderType) | ||
.sort(); | ||
}; | ||
|
||
const displayScmProviders = (providers: UnifiedAuthProvider[]): string => { | ||
const formatter = new Intl.ListFormat("en", { style: "long", type: "disjunction" }); | ||
|
||
return formatter.format(providers); | ||
}; | ||
|
||
export function BrowserExtensionBanner() { | ||
const { user } = useUserLoader(); | ||
const { data: authProviderDescriptions } = useAuthProviderDescriptions(); | ||
|
||
const usedProviders = useMemo(() => { | ||
if (!user || !authProviderDescriptions) return; | ||
|
||
return getDeduplicatedScmProviders(user, authProviderDescriptions); | ||
}, [user, authProviderDescriptions]); | ||
|
||
const scmProviderString = useMemo(() => usedProviders && displayScmProviders(usedProviders), [usedProviders]); | ||
|
||
const parser = useMemo(() => new UAParser(), []); | ||
const browserName = useMemo(() => parser.getBrowser().name?.toLowerCase(), [parser]); | ||
|
||
const [isVisible, setIsVisible] = useState(false); | ||
const isFeatureFlagEnabled = useFeatureFlag("showBrowserExtensionPromotion"); | ||
|
||
useEffect(() => { | ||
const installedOrDismissed = | ||
sessionStorage.getItem("browser-extension-installed") || | ||
localStorage.getItem("browser-extension-banner-dismissed"); | ||
|
||
setIsVisible(!installedOrDismissed); | ||
}, []); | ||
|
||
// const handleClose = () => { | ||
// let persistSuccess = true; | ||
// try { | ||
// localStorage.setItem("browser-extension-banner-dismissed", "true"); | ||
// } catch (e) { | ||
// persistSuccess = false; | ||
// } finally { | ||
// setIsVisible(false); | ||
// trackEvent("coachmark_dismissed", { | ||
// name: "browser_extension_promotion", | ||
// success: persistSuccess, | ||
// }); | ||
// } | ||
// }; | ||
|
||
const browserOption = | ||
browserName && | ||
Object.values(installationOptions).find((opt) => opt.aliases && opt.aliases.includes(browserName)); | ||
|
||
const handleClick = useCallback( | ||
(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => { | ||
if (!browserOption) return; | ||
|
||
event.preventDefault(); | ||
|
||
trackEvent("browser_extension_promotion_interaction", { | ||
action: browserOption.type === "chromium" ? "chrome_navigation" : "firefox_navigation", | ||
}); | ||
|
||
window.open(browserOption.url, "_blank"); | ||
}, | ||
[browserOption], | ||
); | ||
|
||
if (!isVisible || !browserName || !isFeatureFlagEnabled) { | ||
return null; | ||
} | ||
|
||
if (!scmProviderString || !usedProviders?.length) { | ||
return null; | ||
} | ||
|
||
if (!browserOption) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<section className="flex justify-center mt-24 mx-4"> | ||
<div className="sm:flex justify-between border-pk-border-light border-2 rounded-xl hidden max-w-xl mt-4"> | ||
<div className="flex flex-col gap-1 py-5 pl-6 pr-8 justify-center"> | ||
<span className="text-lg font-semibold text-pk-content-secondary"> | ||
Open from {scmProviderString} | ||
</span> | ||
<span className="text-sm"> | ||
<a | ||
href={browserOption.url} | ||
target="_blank" | ||
onClick={handleClick} | ||
className="gp-link" | ||
rel="noreferrer" | ||
> | ||
Install the Gitpod extension | ||
</a>{" "} | ||
to launch workspaces from {scmProviderString}. | ||
</span> | ||
</div> | ||
<img | ||
alt="A button that says Gitpod" | ||
src={browserExtensionImages[usedProviders.at(0)!]} | ||
className="w-32 h-fit self-end mb-4 mr-8" | ||
/> | ||
{/* <Button variant={"ghost"} onClick={handleClose} className="ml-3 self-start hover:bg-transparent"> | ||
<span className="sr-only">Close</span> | ||
<XSvg className={cn("w-3 h-4 dark:text-white text-gray-700")} /> | ||
</Button> */} | ||
</div> | ||
</section> | ||
); | ||
} |
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
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
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 |
---|---|---|
|
@@ -4076,6 +4076,11 @@ | |
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311" | ||
integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g== | ||
|
||
"@types/ua-parser-js@^0.7.37": | ||
version "0.7.37" | ||
resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.37.tgz#2e45bf948a6a94391859a1b0682104ae3c13ba72" | ||
integrity sha512-4sOxS3ZWXC0uHJLYcWAaLMxTvjRX3hT96eF4YWUh1ovTaenvibaZOE5uXtIp4mksKMLRwo7YDiCBCw6vBiUPVg== | ||
|
||
"@types/[email protected]", "@types/uuid@^8.3.1": | ||
version "8.3.1" | ||
resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz" | ||
|
@@ -15068,6 +15073,16 @@ typescript@^4.2.4, typescript@~4.4.2, typescript@~4.4.4: | |
resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz" | ||
integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== | ||
|
||
typescript@^5.4.5: | ||
version "5.4.5" | ||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" | ||
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== | ||
|
||
ua-parser-js@^1.0.36: | ||
version "1.0.36" | ||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz#a9ab6b9bd3a8efb90bb0816674b412717b7c428c" | ||
integrity sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw== | ||
|
||
uc.micro@^1.0.1, uc.micro@^1.0.5: | ||
version "1.0.6" | ||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" | ||
|