Skip to content

Commit 29805e7

Browse files
committed
Introduce feature flagging with config cat
1 parent 1601586 commit 29805e7

File tree

11 files changed

+146
-37
lines changed

11 files changed

+146
-37
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"@plasmohq/storage": "^1.10.0",
2121
"@tailwindcss/forms": "^0.5.10",
2222
"classnames": "^2.5.1",
23+
"configcat-js": "^9.6.0",
24+
"configcat-react": "^4.9.0",
2325
"lucide-react": "^0.474.0",
2426
"plasmo": "^0.89.2",
2527
"react": "^18.3.1",

pnpm-lock.yaml

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/button/button.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1+
import { Storage } from "@plasmohq/storage";
2+
import { useStorage } from "@plasmohq/storage/hook";
13
import classNames from "classnames";
24
import { useEffect, useMemo, useRef, useState } from "react";
35
import { useHotkeys } from "react-hotkeys-hook";
46
import Logo from "react:./logo-mark.svg";
5-
6-
import { useStorage } from "@plasmohq/storage/hook";
7-
import { Storage } from "@plasmohq/storage";
8-
97
import { DEFAULT_GITPOD_ENDPOINT, EVENT_CURRENT_URL_CHANGED } from "~constants";
8+
import { FeatureFlags, useFlag } from "~hooks/use-configcat";
9+
import { OnaLettermark } from "~icons/OnaLettermark";
1010
import { STORAGE_KEY_ADDRESS, STORAGE_KEY_ALWAYS_OPTIONS, STORAGE_KEY_NEW_TAB } from "~storage";
11-
1211
import type { SupportedApplication } from "./button-contributions";
1312
import { CaretForProvider } from "./CaretForProvider";
1413

@@ -23,6 +22,7 @@ export const GitpodButton = ({ application, additionalClassNames, urlTransformer
2322
const [disableAutostart] = useStorage<boolean>(STORAGE_KEY_ALWAYS_OPTIONS, false);
2423
const [showDropdown, setShowDropdown] = useState(false);
2524
const [currentHref, setCurrentHref] = useState(window.location.href);
25+
const { value: isOnaEnabled } = useFlag(FeatureFlags.ONA_ENABLED, false);
2626

2727
const linkRef = useRef<HTMLAnchorElement | null>(null);
2828

@@ -96,7 +96,7 @@ export const GitpodButton = ({ application, additionalClassNames, urlTransformer
9696
return (
9797
<div
9898
id="gitpod-btn-nav"
99-
title="Gitpod"
99+
title={`Open with ${isOnaEnabled ? "Ona" : "Gitpod"}`}
100100
className={classNames("gitpod-button", application, ...(additionalClassNames ?? []))}
101101
>
102102
<div className={classNames("button")}>
@@ -108,7 +108,10 @@ export const GitpodButton = ({ application, additionalClassNames, urlTransformer
108108
ref={linkRef}
109109
>
110110
<span className={classNames("action-label")}>
111-
<Logo className={classNames("action-logo")} width={14} height={14} />
111+
{isOnaEnabled ?
112+
<OnaLettermark className={classNames("action-logo")} width={14} height={14} /> :
113+
<Logo className={classNames("action-logo")} width={14} height={14} />
114+
}
112115
{actions[0].label}
113116
</span>
114117
</a>

src/components/forms/Button.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import classNames from "classnames";
22
import React, { forwardRef, type FC, type ForwardedRef, type ReactNode } from "react";
3+
import { FeatureFlags, useFlag } from "~hooks/use-configcat";
34

45
export type ButtonProps = {
56
type?: "primary" | "secondary" | "danger" | "danger.secondary" | "transparent";
@@ -32,15 +33,18 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
3233
},
3334
ref: ForwardedRef<HTMLButtonElement>,
3435
) => {
36+
const { value: isOnaEnabled } = useFlag(FeatureFlags.ONA_ENABLED, false);
37+
3538
return (
3639
<button
3740
type={htmlType}
3841
className={classNames(
3942
"inline-flex items-center whitespace-nowrap rounded-lg text-sm justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 h-9 px-4 py-2",
4043
type === "primary" ?
4144
[
42-
"bg-gray-900 hover:bg-gray-800 dark:bg-kumquat-base dark:hover:bg-kumquat-ripe text-gray-50 dark:text-gray-900",
45+
"bg-gray-900 hover:bg-gray-800",
4346
"text-gray-50 dark:text-gray-900",
47+
{ "bg-[#1F1F1F] hover:bg-[#737373] dark:bg-[#FAFAFA] dark:hover:bg-[#A3A3A3]": isOnaEnabled },
4448
]
4549
: null,
4650
type === "secondary" ?

src/components/forms/CheckboxInputField.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ export const CheckboxInputField: FC<CheckboxInputFieldProps> = ({
6767
<input
6868
type="checkbox"
6969
className={classNames(
70-
"h-4 w-4 mt-0.5 rounded cursor-pointer border-2 dark:invert",
71-
"focus:ring-2 ring-blue-400",
70+
"size-4 mt-0.5 rounded cursor-pointer border-2 dark:invert",
71+
"focus:ring-2 ring-[#262626]",
7272
"border-gray-600 dark:border-gray-900 bg-transparent",
7373
"checked:bg-gray-600 dark:checked:bg-gray-900",
7474
)}

src/components/forms/TextInputField.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import classNames from "classnames";
88
import React, { memo, useCallback, useId, type PropsWithChildren, type ReactNode } from "react";
9-
9+
import { FeatureFlags, useFlag } from "~hooks/use-configcat";
1010
import { InputField } from "./InputField";
1111

1212
type TextInputFieldTypes = "text" | "password" | "email" | "url";
@@ -97,8 +97,10 @@ export const TextInput = memo(
9797
onChange,
9898
onBlur,
9999
}: PropsWithChildren<TextInputProps>) => {
100+
const { value: isOnaEnabled } = useFlag(FeatureFlags.ONA_ENABLED, false);
101+
100102
const handleChange = useCallback(
101-
(e) => {
103+
(e: React.ChangeEvent<HTMLInputElement>) => {
102104
onChange && onChange(e.target.value);
103105
},
104106
[onChange],
@@ -115,6 +117,7 @@ export const TextInput = memo(
115117
"py-2 px-3",
116118
"placeholder:text-gray-400 dark:placeholder:text-gray-500",
117119
"disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:border disabled:border-gray-200 dark:disabled:border-gray-600 disabled:text-gray-400 dark:disabled:text-gray-500",
120+
{ "bg-white focus-visible:ring-2 focus-visible:ring-gray-400 dark:bg-[#262626]": isOnaEnabled },
118121
className,
119122
)}
120123
value={value}

src/contents/button.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import cssText from "data-text:../button/button.css";
22
import type { PlasmoCSConfig, PlasmoGetInlineAnchor } from "plasmo";
33
import React, { type ReactElement } from "react";
4-
54
import { EVENT_CURRENT_URL_CHANGED } from "~constants";
5+
import { ConfigCatProvider, configCatProviderConfig } from "~hooks/use-configcat";
66

77
import { GitpodButton } from "../button/button";
88
import { buttonContributions, isSiteSuitable, type ButtonContributionParams } from "../button/button-contributions";
@@ -42,12 +42,14 @@ class ButtonContributionManager {
4242
if (!this.buttons.has(containerId)) {
4343
this.buttons.set(
4444
containerId,
45-
<GitpodButton
46-
key={containerId}
47-
application={contribution.application}
48-
additionalClassNames={contribution.additionalClassNames}
49-
urlTransformer={contribution.urlTransformer}
50-
/>,
45+
<ConfigCatProvider {...configCatProviderConfig}>
46+
<GitpodButton
47+
key={containerId}
48+
application={contribution.application}
49+
additionalClassNames={contribution.additionalClassNames}
50+
urlTransformer={contribution.urlTransformer}
51+
/>
52+
</ConfigCatProvider>,
5153
);
5254
}
5355
}

src/hooks/use-configcat.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { useConfigCatClient, useFeatureFlag, ConfigCatProvider } from 'configcat-react';
2+
import { PollingMode, createConsoleLogger, LogLevel, User } from 'configcat-js';
3+
4+
const CONFIGCAT_SDK_KEY_PRODUCTION = 'configcat-sdk-1/ykHcCKiz4EKB7k23mNcvBw/ut0FmOIkA0a-Ife7zHC-qg';
5+
const CONFIGCAT_SDK_KEY_DEV = 'configcat-sdk-1/ykHcCKiz4EKB7k23mNcvBw/4zALdAjwI0iIB4y4eWr-bQ';
6+
7+
const logger = createConsoleLogger(LogLevel.Warn);
8+
9+
export const configCatProviderConfig = {
10+
sdkKey: process.env.NODE_ENV === 'production' ? CONFIGCAT_SDK_KEY_PRODUCTION : CONFIGCAT_SDK_KEY_DEV,
11+
pollingMode: PollingMode.AutoPoll,
12+
options: {
13+
pollIntervalSeconds: 60,
14+
logger: logger,
15+
requestTimeoutMs: 30000,
16+
},
17+
};
18+
19+
export const FeatureFlags = {
20+
ONA_ENABLED: 'is_ona_browser_extension_enabled',
21+
} as const;
22+
23+
export type FeatureFlagKey = (typeof FeatureFlags)[keyof typeof FeatureFlags];
24+
25+
export function useFlag(
26+
key: FeatureFlagKey,
27+
defaultValue: boolean = false,
28+
user?: User
29+
): { value: boolean; loading: boolean } {
30+
return useFeatureFlag(key, defaultValue, user);
31+
}
32+
33+
// Re-export commonly used hooks and components from configcat-react
34+
export { useConfigCatClient, useFeatureFlag, ConfigCatProvider };

src/icons/OnaLettermark.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { forwardRef, type SVGProps } from "react";
2+
3+
export const OnaLettermark = forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(({ ...props }, ref) => (
4+
<svg width="32" height="33" viewBox="0 0 32 33" fill="currentColor" xmlns="http://www.w3.org/2000/svg" {...props} ref={ref}>
5+
<path
6+
d="M30.9471 9.86238C31.588 10.5033 32 11.3731 32 12.3803V20.6664C32 21.6735 31.588 22.5434 30.9471 23.1843L22.6609 31.4704C22.02 32.1571 21.1044 32.5233 20.1431 32.5233H11.8569C10.8498 32.5233 9.97997 32.1571 9.29328 31.4704L1.00715 23.1843C0.366237 22.5434 0 21.6735 0 20.6664V12.3803C0 11.3731 0.366237 10.5033 1.00715 9.8166L9.29328 1.53047C9.97997 0.889556 10.8498 0.477539 11.8569 0.477539H20.1431C21.1044 0.477539 22.02 0.889557 22.6609 1.57625L30.9471 9.86238ZM24.4101 21.3626V11.6841C24.4101 9.71554 22.8078 8.06747 20.8393 8.06747H11.1607C9.14644 8.06747 7.54415 9.71554 7.54415 11.6841V21.3626C7.54415 23.3311 9.14644 24.9334 11.1607 24.9334H20.8393C22.8078 24.9334 24.4101 23.3311 24.4101 21.3626Z"
7+
/>
8+
</svg>
9+
));
10+
11+
OnaLettermark.displayName = "OnaWordmark";

src/popup.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@
1010
body {
1111
@apply bg-white dark:bg-gitpod-black text-black dark:text-white;
1212
}
13+
div.ona {
14+
@apply dark:bg-[#262626] dark:text-white text-[#1F1F1F];
15+
}
1316
h1 {
1417
@apply text-gray-900 dark:text-gray-100 font-bold;
1518
line-height: 64px;
1619
font-size: 48px;
1720
}
21+
h1.ona {
22+
@apply text-[#1F1F1F];
23+
}
1824
h2 {
1925
@apply text-base text-gray-500 dark:text-gray-400;
2026
}

0 commit comments

Comments
 (0)