From ecf27daa15e5205bdc9d191bc3562eff174ffb50 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 25 Jul 2024 17:22:46 -0400 Subject: [PATCH] Upload button (dev only) can now be Enabled via User Attributes (#654) Co-authored-by: wil --- app/entry.client.tsx | 26 +--------- app/enums/authentication.ts | 7 +++ app/models/Users.ts | 4 +- .../comps/SidePanelTabs/hooks/index.ts | 1 + .../SidePanelTabs/hooks/useFeatureFlags.tsx | 19 +++++++ .../CharactersComboTabs/subtabAnimations.tsx | 8 +-- .../CharactersComboTabs/subtabCharacters.tsx | 8 +-- .../CharactersComboTabs/subtabExpressions.tsx | 8 +-- app/root.tsx | 49 ++++++++++++------- app/signals/authentication/authentication.ts | 12 ++++- app/signals/authentication/utilities.ts | 4 +- 11 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 app/pages/PageEnigma/comps/SidePanelTabs/hooks/useFeatureFlags.tsx diff --git a/app/entry.client.tsx b/app/entry.client.tsx index 4623515e1d..442da4f8a8 100644 --- a/app/entry.client.tsx +++ b/app/entry.client.tsx @@ -1,34 +1,12 @@ import { RemixBrowser } from "@remix-run/react"; -import { startTransition, StrictMode, useEffect } from "react"; +import { startTransition, StrictMode } from "react"; import { hydrateRoot } from "react-dom/client"; -import { posthog } from "posthog-js"; -import { PostHogProvider } from "posthog-js/react"; -import EnvironmentVariables from "~/Classes/EnvironmentVariables"; - -function PosthogInit() { - useEffect(() => { - const data = EnvironmentVariables.values; - - const apiKey = data.REACT_APP_PUBLIC_POSTHOG_KEY as string; - posthog.init(apiKey, { - //HACK: This is the default host from Netlify, but need to figure out why it isn't working on prod. - // api_host: data.DEPLOY_PRIME_URL + "/ingest" as string, - api_host: "https://studio.storyteller.ai/ingest" as string, - ui_host: data.REACT_APP_PUBLIC_POSTHOG_UI as string, - }); - }, []); - - return null; -} startTransition(() => { hydrateRoot( document, - - - - + , ); }); diff --git a/app/enums/authentication.ts b/app/enums/authentication.ts index ecd0425de0..73437ae571 100644 --- a/app/enums/authentication.ts +++ b/app/enums/authentication.ts @@ -17,3 +17,10 @@ export enum AUTH_ERROR_FALLBACKS { GetSessionError = "Unknown Error During Get Session", Unauthorized = "User Unauthorized", } + +export enum USER_FEATURE_FLAGS { + EXPLORE_MEDIA = "explore_media", + STUDIO = "studio", + UPLOAD_3D = "upload_3d", + VIDEO_STYLE_TRANSFER = "video_style_transfer", +} diff --git a/app/models/Users.ts b/app/models/Users.ts index 784839f31f..fc0caf6f17 100644 --- a/app/models/Users.ts +++ b/app/models/Users.ts @@ -1,3 +1,5 @@ +import { USER_FEATURE_FLAGS } from "~/enums"; + export interface CoreInfo { default_avatar: { color_index: number; @@ -19,7 +21,7 @@ export interface UserInfo { // Rollout feature flags can_access_studio: boolean; - maybe_feature_flags: string[]; + maybe_feature_flags: USER_FEATURE_FLAGS[]; // Usage can_use_tts: boolean; diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/hooks/index.ts b/app/pages/PageEnigma/comps/SidePanelTabs/hooks/index.ts index 91f2cb209a..f3d6a2ee51 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/hooks/index.ts +++ b/app/pages/PageEnigma/comps/SidePanelTabs/hooks/index.ts @@ -2,3 +2,4 @@ export * from "./useUserObjects"; export * from "./useFeaturedObjects"; export * from "./useSearchFeaturedObjects"; export * from "./useSearchUserObjects"; +export * from "./useFeatureFlags"; diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/hooks/useFeatureFlags.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/hooks/useFeatureFlags.tsx new file mode 100644 index 0000000000..7a11571725 --- /dev/null +++ b/app/pages/PageEnigma/comps/SidePanelTabs/hooks/useFeatureFlags.tsx @@ -0,0 +1,19 @@ +import { useSignals } from "@preact/signals-react/runtime"; +import { authentication } from "~/signals"; +import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; +import { FeatureFlags } from "~/enums"; + +export const useFeatureFlags = () => { + useSignals(); + + const showSearchObjectComponent = usePosthogFeatureFlag( + FeatureFlags.SHOW_SEARCH_OBJECTS, + ); + const showUploadButton = + usePosthogFeatureFlag(FeatureFlags.DEV_ONLY) || authentication.canUpload3D; + + return { + showSearchObjectComponent, + showUploadButton, + }; +}; diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabAnimations.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabAnimations.tsx index c223778627..be142f00b2 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabAnimations.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabAnimations.tsx @@ -4,7 +4,6 @@ import { ANIMATION_MIXAMO_FILE_TYPE, ANIMATION_MMD_FILE_TYPE, AssetFilterOption, - FeatureFlags, FilterEngineCategories, MediaFileAnimationType, } from "~/enums"; @@ -22,8 +21,8 @@ import { useFeaturedObjects, useSearchFeaturedObjects, useSearchUserdObjects, + useFeatureFlags, } from "../../hooks"; -import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; import { filterMixamoAnimations, filterMMDAnimations, @@ -39,10 +38,7 @@ export const AnimationsTab = ({ animationType: MediaFileAnimationType; demoAnimationItems?: MediaItem[]; }) => { - const showSearchObjectComponent = usePosthogFeatureFlag( - FeatureFlags.SHOW_SEARCH_OBJECTS, - ); - const showUploadButton = usePosthogFeatureFlag(FeatureFlags.DEV_ONLY); + const { showSearchObjectComponent, showUploadButton } = useFeatureFlags(); const [openUploadModal, setOpenUploadModal] = useState(false); diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabCharacters.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabCharacters.tsx index 746096dabf..29a6ca4f79 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabCharacters.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabCharacters.tsx @@ -4,7 +4,6 @@ import { AssetFilterOption, CHARACTER_MIXAMO_FILE_TYPE, CHARACTER_MMD_FILE_TYPE, - FeatureFlags, FilterEngineCategories, MediaFileAnimationType, } from "~/enums"; @@ -17,13 +16,13 @@ import { UploadModal, } from "~/components"; import { ItemElements } from "~/pages/PageEnigma/comps/SidePanelTabs/sharedComps"; -import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; import { isAnyStatusFetching } from "../../utilities"; import { useUserObjects, useFeaturedObjects, useSearchFeaturedObjects, useSearchUserdObjects, + useFeatureFlags, } from "../../hooks"; import { filterMixamoCharacters, @@ -39,10 +38,7 @@ export const CharactersTab = ({ animationType: MediaFileAnimationType; demoCharacterItems?: MediaItem[]; }) => { - const showSearchObjectComponent = usePosthogFeatureFlag( - FeatureFlags.SHOW_SEARCH_OBJECTS, - ); - const showUploadButton = usePosthogFeatureFlag(FeatureFlags.DEV_ONLY); + const { showSearchObjectComponent, showUploadButton } = useFeatureFlags(); const [openUploadModal, setOpenUploadModal] = useState(false); diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabExpressions.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabExpressions.tsx index 63fc933418..7c0bd099e7 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabExpressions.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersComboTabs/subtabExpressions.tsx @@ -4,7 +4,6 @@ import { AssetFilterOption, FilterEngineCategories, MediaFileAnimationType, - FeatureFlags, } from "~/enums"; import { Button, @@ -14,23 +13,20 @@ import { UploadModal, } from "~/components"; import { ItemElements } from "~/pages/PageEnigma/comps/SidePanelTabs/sharedComps"; -import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; import { isAnyStatusFetching } from "../../utilities"; import { useUserObjects, useFeaturedObjects, useSearchFeaturedObjects, useSearchUserdObjects, + useFeatureFlags, } from "../../hooks"; const filterEngineCategories = [FilterEngineCategories.EXPRESSION]; export const ExpressionTab = () => { - const showSearchObjectComponent = usePosthogFeatureFlag( - FeatureFlags.SHOW_SEARCH_OBJECTS, - ); + const { showSearchObjectComponent, showUploadButton } = useFeatureFlags(); - const showUploadButton = usePosthogFeatureFlag(FeatureFlags.DEV_ONLY); const [openUploadModal, setOpenUploadModal] = useState(false); diff --git a/app/root.tsx b/app/root.tsx index 32c5772f3d..d6268b0ca3 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,6 +1,8 @@ import { useEffect } from "react"; import { useSignals } from "@preact/signals-react/runtime"; import { LinksFunction } from "@remix-run/deno"; +import { posthog } from "posthog-js"; +import { PostHogProvider } from "posthog-js/react"; import { Links, Meta, @@ -99,7 +101,9 @@ export default function App() { {data && }
- + + + @@ -109,33 +113,44 @@ export default function App() { const GlobalSettingsManager = ({ env }: { env: Record }) => { useSignals(); - useEffect(() => { - function setPage() { - // TODO address this issue with zooming - pageHeight.value = window.innerHeight; - pageWidth.value = window.innerWidth; - } - - setPage(); - - window.addEventListener("resize", setPage); - - return () => { - window.removeEventListener("resize", setPage); - }; - }, []); + /// Initizations that depends on ENV vars /// + function PostHogInit() { + const data = EnvironmentVariables.values; + const apiKey = data.REACT_APP_PUBLIC_POSTHOG_KEY as string; + posthog.init(apiKey, { + //HACK: This is the default host from Netlify, but need to figure out why it isn't working on prod. + // api_host: data.DEPLOY_PRIME_URL + "/ingest" as string, + api_host: "https://studio.storyteller.ai/ingest" as string, + ui_host: data.REACT_APP_PUBLIC_POSTHOG_UI as string, + }); + } useEffect(() => { EnvironmentVariables.initialize(env); + PostHogInit(); }, [env]); - useEffect(() => { + /// Initizations that run only once on 1ST mount /// + function setPage() { + // TODO address this issue with zooming + pageHeight.value = window.innerHeight; + pageWidth.value = window.innerWidth; + } + function initWizard() { if (showWizard.value) { return; } const wizard = localStorage.getItem("storyteller-wizard"); showWizard.value = wizard ? "" : "initial"; localStorage.setItem("storyteller-wizard", "shown"); + } + useEffect(() => { + initWizard(); + setPage(); + window.addEventListener("resize", setPage); + return () => { + window.removeEventListener("resize", setPage); + }; }, []); return null; diff --git a/app/signals/authentication/authentication.ts b/app/signals/authentication/authentication.ts index fecbb833c8..b7a1128225 100644 --- a/app/signals/authentication/authentication.ts +++ b/app/signals/authentication/authentication.ts @@ -1,11 +1,20 @@ import { computed, signal } from "@preact/signals-core"; import { ActiveSubscriptions, UserInfo } from "~/models"; -import { AUTH_STATUS, LoyaltyProgram } from "~/enums"; +import { AUTH_STATUS, LoyaltyProgram, USER_FEATURE_FLAGS } from "~/enums"; const status = signal(AUTH_STATUS.INIT); const userInfo = signal(undefined); const activeSubs = signal(undefined); +const canUpload3D = computed(() => { + if (!userInfo.value || !userInfo.value.maybe_feature_flags) { + return undefined; + } + return userInfo.value.maybe_feature_flags.includes( + USER_FEATURE_FLAGS.UPLOAD_3D, + ); +}); + const hasAccess = computed(() => { if ( userInfo.value === undefined || @@ -33,6 +42,7 @@ export const authentication = { status, userInfo, activeSubs, + canUpload3D, hasAccess, hasPremium, }; diff --git a/app/signals/authentication/utilities.ts b/app/signals/authentication/utilities.ts index bfa2256aa3..df6602989d 100644 --- a/app/signals/authentication/utilities.ts +++ b/app/signals/authentication/utilities.ts @@ -1,8 +1,6 @@ -import { authentication } from "~/signals"; - import { AUTH_STATUS } from "~/enums"; import { UserInfo, ActiveSubscriptions } from "~/models"; -import { flushAllBackgroundLoadedMedia } from "~/signals"; +import { authentication, flushAllBackgroundLoadedMedia } from "~/signals"; export const updateAuthStatus = (newStatus: AUTH_STATUS) => { authentication.status.value = newStatus;