added option for scrolling within modals, applied to login/signup modal, also added onModalOpen/onModalClose events

This commit is contained in:
Victor committed 2024-08-27 15:30:45 -07:00
1 parent 214f15aeb9
commit 400b9856d0
12 files changed
+114 -57

No files matched your search

@@ -19,6 +19,7 @@ export interface ActionButtonProps {
toggle: (entityToken: string, entityType: string) => any;
toolTipOff?: string;
toolTipOn?: string;
visible?: boolean;
}
export default function ActionButton({
@@ -34,6 +35,7 @@ export default function ActionButton({
toggle,
toolTipOff,
toolTipOn,
visible
}: ActionButtonProps) {
const { events, status } = useAnimationStatus();
const onClick = () => {
@@ -52,13 +54,13 @@ export default function ActionButton({
placement: "bottom",
theme: "fakeyou",
trigger: "mouseenter",
visible,
}}
>
<button
{...{
className: `fy-action-button ${actionType}-action-button ${
isToggled ? "action-button-toggled" : ""
}`,
className: `fy-action-button ${actionType}-action-button ${isToggled ? "action-button-toggled" : ""
}`,
disabled: busy,
onClick,
}}
@@ -39,11 +39,6 @@
height: fit-content;
}
.fy-modal-body-square {
// width: 75vh;
// height: 75vh;
}
.fy-modal-body-wide,
.fy-modal-body-narrow,
.fy-modal-body-small,
@@ -83,4 +78,8 @@
.fy-modal-no-padding {
padding: 0;
}
}
.fy-modal-scrollable {
overflow-y: scroll;
}
}
@@ -3,7 +3,7 @@ import { a, easings, useTransition } from "@react-spring/web";
import { ModalWidth } from "hooks";
import "./ModalLayer.scss";
interface Props {
interface ModalLayerProps {
content?: React.ElementType | null;
contentProps?: any;
close: () => void;
@@ -13,6 +13,7 @@ interface Props {
modalOpen: boolean;
onModalCloseEnd: (x: any) => void;
padding?: boolean;
scroll?: boolean;
width?: ModalWidth;
}
@@ -25,8 +26,9 @@ export default function ModalLayer({
modalOpen,
onModalCloseEnd,
padding = true,
scroll,
width = "wide",
}: Props) {
}: ModalLayerProps) {
const mainClassName = "fy-modal-layer";
const tintTransition = useTransition(modalOpen, {
config: {
@@ -39,7 +41,7 @@ export default function ModalLayer({
onRest: onModalCloseEnd,
});
if (debug) console.log(`🐛 ModalLayer debug at ${debug}`, modalOpen);
if (debug) { console.log(`🐛 ModalLayer debug at ${debug}`, modalOpen); }
return tintTransition(
(tintStyle, modalIsOpen) =>
@@ -61,9 +63,9 @@ export default function ModalLayer({
>
<div
{...{
className: `fy-modal-body-${width}${
padding ? "" : " fy-modal-no-padding"
}`,
className: `fy-modal-body-${width}${padding ? "" : " fy-modal-no-padding"
}${scroll ? " fy-modal-scrollable" : ""
}`,
}}
>
{Content && (
@@ -15,12 +15,13 @@ export interface ModalContextShared {
}
export const ModalContext = createContext<ModalContextShared>({
close: () => {},
open: () => {},
close: () => { },
open: () => { },
modalOpen: false,
modalState: null,
});
// how this works
//
// When modalState is set via open(), modalOpen is set to true to via useEffect
@@ -51,6 +52,7 @@ export default function ModalProvider({ children }: ModalProviderProps) {
modalOpen,
onModalCloseEnd,
padding: modalState?.padding,
scroll: modalState?.scroll,
width: modalState?.width,
}}
/>
@@ -13,12 +13,17 @@ export interface AccountModalMessages {
signupMessage?: string;
}
export interface AccountModalEvents {
onModalClose?: () => void;
onModalOpen?: () => void;
}
interface SessionContextType {
canAccessStudio: () => boolean;
canEditTtsModel: (creatorUserToken: string) => boolean;
canEditMediaFile: (creatorUserToken?: string) => boolean;
canBanUsers: () => boolean;
loggedInOrModal: (acctMsgs: AccountModalMessages) => boolean;
loggedInOrModal: (acctMsgs: AccountModalMessages, cfg?: AccountModalEvents) => boolean;
loggedIn: boolean;
modal: {
close: () => void;
@@ -61,8 +66,8 @@ export const SessionContext = createContext<SessionContextType>({
studioAccessCheck: () => null,
styleVideoAccessCheck: () => null,
modal: {
close: () => {},
open: () => {},
close: () => { },
open: () => { },
},
userTokenMatch: () => false,
sessionWrapper: SessionWrapper.emptySession(),
@@ -85,14 +90,16 @@ export default function SessionProvider({
const { close, killModal, modalOpen, modalState, onModalCloseEnd, open } =
useModalState({});
const loggedInOrModal = (accountModalMessages: AccountModalMessages) => {
const loggedInOrModal = (accountModalMessages: AccountModalMessages, events?: AccountModalEvents) => {
if (user) {
return true;
} else {
open({
component: AccountModal,
scroll: true,
width: "small",
props: { ...accountModalMessages },
...events
});
return false;
}
@@ -157,6 +164,7 @@ export default function SessionProvider({
lockTint: modalState?.lockTint,
modalOpen,
onModalCloseEnd,
scroll: modalState?.scroll,
width: modalState?.width,
}}
/>
@@ -2,7 +2,7 @@ import useAnimationStatus, {
AnimationEvents,
AnimationStatus,
} from "./useAnimationStatus";
import useBatchContent from "./useBatchContent";
import useBatchContent, { BatchInputProps, MakeBatchPropsParams } from "./useBatchContent";
import useBookmarks, { MakeBookmarksProps } from "./useBookmarks";
import useChanger from "./useChanger";
import useCoverImgUpload from "./useCoverImgUpload";
@@ -76,7 +76,9 @@ export {
export type {
AnimationEvents,
BatchInputProps,
MakeBookmarksProps,
MakeBatchPropsParams,
MakeRatingsProps,
ModalConfig,
ModalWidth,
@@ -2,7 +2,7 @@ import { useState } from "react";
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
import { useSession } from "hooks";
interface Props {
interface UseBatchContentProps {
checker: any;
debug?: string;
fetcher: any;
@@ -26,20 +26,18 @@ interface Gather {
type BatchToggle = (entity_token: string, entity_type: string) => boolean;
export interface MakePropsParams {
export interface MakeBatchPropsParams {
entityToken: string;
entityType: string;
}
export interface BatchInputProps {
busy: boolean;
entityToken: string;
entityType: string;
export interface BatchInputProps extends MakeBatchPropsParams {
busy?: boolean;
isToggled: boolean;
toggle: BatchToggle;
}
export type MakeBatchProps = (x: MakePropsParams) => BatchInputProps;
export type MakeBatchProps = (x: MakeBatchPropsParams) => BatchInputProps;
export default function useBatchContent({
checker,
@@ -47,15 +45,16 @@ export default function useBatchContent({
fetcher,
modLibrary = (current: any, res: any, entity_token: string) => current,
onPass,
onFail = { fetch: () => new Promise(() => {}) },
onFail = { fetch: () => new Promise(() => { }) },
resultsKey,
toggleCheck,
}: Props) {
}: UseBatchContentProps) {
const session = useSession();
const [library, librarySet] = useState<Library>({});
const [busyList, busyListSet] = useState<Library>({});
const [status, statusSet] = useState(FetchStatus.ready);
const [tokenType, tokenTypeSet] = useState("");
const [modalOpen, modalOpenSet] = useState(false);
const dlog = (...dbg: any) => (debug ? console.log(...dbg) : {});
@@ -109,7 +108,10 @@ export default function useBatchContent({
});
const toggle: BatchToggle = (entity_token, entity_type) => {
if (session.loggedInOrModal({})) {
if (session.loggedInOrModal({}, {
onModalClose: () => { modalOpenSet(false); },
onModalOpen: () => { modalOpenSet(true); },
})) {
let inLibrary = library[entity_token];
statusSet(FetchStatus.in_progress);
busyAdd(entity_token);
@@ -150,12 +152,13 @@ export default function useBatchContent({
const toggled = (entity_token = "") => toggleCheck(library[entity_token]);
const makeProps = ({ entityToken, entityType }: MakePropsParams) => ({
const makeProps = ({ entityToken, entityType }: MakeBatchPropsParams) => ({
busy: busyList[entityToken],
entityToken,
entityType,
isToggled: toggled(entityToken),
toggle,
...modalOpen ? { visible: false } : {}
});
return {
@@ -1,2 +0,0 @@
export { default } from "./useBatchContent";
export type { BatchInputProps, MakeBatchProps, MakePropsParams } from "./useBatchContent";
@@ -4,11 +4,11 @@ import { DeleteBookmark } from "@storyteller/components/src/api/bookmarks/Delete
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faBookmark } from "@fortawesome/pro-solid-svg-icons";
import { faBookmark as faBookmarkOutline } from "@fortawesome/pro-regular-svg-icons";
import useBatchContent, {
import {
useBatchContent,
BatchInputProps,
MakePropsParams,
} from "hooks/useBatchContent";
MakeBatchPropsParams,
} from "hooks";
export interface BookmarksProps extends BatchInputProps {
actionType: "bookmark";
@@ -18,21 +18,21 @@ export interface BookmarksProps extends BatchInputProps {
labelOn: string | number;
}
export type MakeBookmarksProps = (x: MakePropsParams) => BookmarksProps;
export type MakeBookmarksProps = (x: MakeBatchPropsParams) => BookmarksProps;
export default function useBookmarks() {
const toggleList =
(toBookmark: boolean) =>
(res: any, entity_token: string, entity_type: string, lib: any) => {
return {
...lib,
[entity_token]: {
entity_type,
is_bookmarked: toBookmark,
maybe_bookmark_token: toBookmark ? res.user_bookmark_token : null,
},
(res: any, entity_token: string, entity_type: string, lib: any) => {
return {
...lib,
[entity_token]: {
entity_type,
is_bookmarked: toBookmark,
maybe_bookmark_token: toBookmark ? res.user_bookmark_token : null,
},
};
};
};
const bookmarks = useBatchContent({
debug: "bookmarks",
@@ -60,7 +60,7 @@ export default function useBookmarks() {
const makeProps: MakeBookmarksProps = ({
entityToken,
entityType,
}: MakePropsParams) => {
}: MakeBatchPropsParams) => {
return {
...bookmarks.makeProps({ entityToken, entityType }),
actionType: "bookmark",
@@ -7,7 +7,10 @@ export interface ModalConfig {
component: React.ElementType;
lockTint?: boolean;
padding?: boolean;
onModalClose?: () => void;
onModalOpen?: () => void;
props?: any;
scroll?: boolean;
width?: ModalWidth;
}
@@ -28,6 +31,9 @@ export default function useModalState({ debug = "" }) {
if (debug) {
console.log(`🚪 useModalState open() at ${debug}`, { cfg });
}
if (cfg.onModalOpen) {
cfg.onModalOpen();
}
modalStateSet(cfg);
};
@@ -35,6 +41,9 @@ export default function useModalState({ debug = "" }) {
if (debug) {
console.log(`🔥 useModalState close() at ${debug}`);
}
if (modalState?.onModalClose) {
modalState.onModalClose();
}
killModalSet(true);
modalOpenSet(false);
};
@@ -3,10 +3,11 @@ import { SetRating } from "@storyteller/components/src/api/user_ratings/SetRatin
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faHeart } from "@fortawesome/pro-solid-svg-icons";
import { faHeart as faHeartOutline } from "@fortawesome/pro-regular-svg-icons";
import useBatchContent, {
import {
useBatchContent,
BatchInputProps,
MakePropsParams,
} from "hooks/useBatchContent";
MakeBatchPropsParams,
} from "hooks";
export interface RatingsProps extends BatchInputProps {
actionType: "like";
@@ -17,7 +18,7 @@ export interface RatingsProps extends BatchInputProps {
labelOn: string | number;
}
export type MakeRatingsProps = (x: MakePropsParams) => RatingsProps;
export type MakeRatingsProps = (x: MakeBatchPropsParams) => RatingsProps;
export default function useRatings() {
const fetch = (entity_token: string, entity_type: string, lib: any) => {
@@ -59,8 +60,8 @@ export default function useRatings() {
) => {
let result = res.results
? res.results.find((item: any, i: number) => {
return (item.details || item)[tokenType] === entity_token;
})
return (item.details || item)[tokenType] === entity_token;
})
: res;
let { positive_rating_count } = (result.details || result).stats;
@@ -76,7 +77,7 @@ export default function useRatings() {
const makeProps: MakeRatingsProps = ({
entityToken,
entityType,
}: MakePropsParams) => {
}: MakeBatchPropsParams) => {
const likeCount = ratings.library[entityToken]?.positive_rating_count || 0;
return {
...ratings.makeProps({ entityToken, entityType }),
@@ -0,0 +1,31 @@
import React, { useEffect, useState } from "react";
import Container from "components/common/Container";
import PageHeader from "components/layout/PageHeader";
import { AITools } from "components/marketing";
export default function NotFound() {
const [loaded, loadedSet] = useState(false);
useEffect(() => {
if (!loaded) {
loadedSet(true);
// @ts-ignore
window.dataLayer.push({
"event": "fe_page_not_found",
"page": "*",
"user_id": "$user_id"
});
}
}, [loaded]);
return (
<Container type="panel" className="mb-5">
<PageHeader
title="This page couldn't be found, maybe try one of our AI media creation tools?"
titleH2={true}
panel={false}
/>
<AITools />
</Container>
);
}