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;