diff --git a/src/components/main/WebAppModal.module.scss b/src/components/main/WebAppModal.module.scss new file mode 100644 index 000000000..5b69a36ad --- /dev/null +++ b/src/components/main/WebAppModal.module.scss @@ -0,0 +1,138 @@ +.root { + :global { + .modal-header { + border-bottom: 1px solid var(--color-dividers); + padding: 0.5rem; + } + + .modal-dialog { + height: 75%; + justify-content: center; + border: none; + box-shadow: none; + margin: 0; + overflow: hidden; + } + + .modal-content { + display: flex; + flex-direction: column; + overflow: hidden; + padding: 0; + border-bottom-right-radius: var(--border-radius-default); + border-bottom-left-radius: var(--border-radius-default); + } + + @media (max-width: 600px) { + .modal-dialog { + background-color: var(--color-background); + border-radius: 0; + height: 100%; + max-width: 100% !important; + } + + .modal-content { + max-height: none; + border-radius: 0; + } + } + } +} + +.close-icon { + position: absolute; + transform: rotate(-45deg); + + &, + &::before, + &::after { + width: 1.125rem; + height: 0.125rem; + border-radius: 0.125rem; + background-color: var(--color-text-secondary); + transition: transform var(--slide-transition); + } + + &::before, + &::after { + position: absolute; + left: 0; + top: 0; + content: ""; + } + + &::before { + transform: rotate(90deg); + } + + &.state-back { + transform: rotate(180deg); + + &::before { + transform: rotate(45deg) scaleX(0.75) translate(0, -0.375rem); + } + + &::after { + transform: rotate(-45deg) scaleX(0.75) translate(0, 0.375rem); + } + } +} + +.loading-spinner { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + transition: opacity 0.2s ease-in-out; +} + +.hide { + opacity: 0; +} + +.frame { + width: 100%; + height: 100%; + border: 0; + z-index: 1; + + &.with-button { + height: calc(100% - 3.5rem); + } +} + +.main-button { + position: absolute; + bottom: 0; + border-radius: 0; + transform: translateY(100%); + transition: 0.25s ease-in-out transform; + + &.visible { + transform: translateY(0); + } + + &.hidden { + visibility: hidden; + } +} + +.main-button-spinner { + position: absolute; + right: 1rem; +} + +.web-app-popup { + :global(.modal-dialog) { + max-width: min(30rem, 100%); + } + + &.without-title :global(.modal-content) { + padding-top: 0; + } + + :global(.modal-content) { + padding-left: 2rem; + } +} diff --git a/src/components/main/WebAppModal.scss b/src/components/main/WebAppModal.scss deleted file mode 100644 index 201d4b849..000000000 --- a/src/components/main/WebAppModal.scss +++ /dev/null @@ -1,122 +0,0 @@ -.WebAppModal { - .modal-header { - border-bottom: 1px solid var(--color-dividers); - padding: 0.5rem; - } - - .modal-dialog { - height: 75%; - justify-content: center; - border: none; - box-shadow: none; - margin: 0; - overflow: hidden; - } - - .modal-content { - display: flex; - flex-direction: column; - overflow: hidden; - padding: 0; - border-bottom-right-radius: var(--border-radius-default); - border-bottom-left-radius: var(--border-radius-default); - } - - .web-app-frame { - width: 100%; - height: 100%; - border: 0; - - &.with-button { - height: calc(100% - 56px); - } - } - - .web-app-button { - position: absolute; - bottom: 0; - border-radius: 0; - transform: translateY(100%); - transition: 0.25s ease-in-out transform; - - &.visible { - transform: translateY(0); - } - - &.hidden { - visibility: hidden; - } - } - - .Spinner { - position: absolute; - right: 1rem; - } - - @media (max-width: 600px) { - .modal-dialog { - background-color: var(--color-background); - border-radius: 0; - height: 100%; - max-width: 100% !important; - } - - .modal-content { - max-height: none; - border-radius: 0; - } - } - - .animated-close-icon { - position: absolute; - transform: rotate(-45deg); - - &, - &::before, - &::after { - width: 1.125rem; - height: 0.125rem; - border-radius: 0.125rem; - background-color: var(--color-text-secondary); - transition: transform var(--slide-transition); - } - - &::before, - &::after { - position: absolute; - left: 0; - top: 0; - content: ""; - } - - &::before { - transform: rotate(90deg); - } - - &.state-back { - transform: rotate(180deg); - - &::before { - transform: rotate(45deg) scaleX(0.75) translate(0, -0.375rem); - } - - &::after { - transform: rotate(-45deg) scaleX(0.75) translate(0, 0.375rem); - } - } - } -} - -.web-app-popup { - .modal-dialog { - max-width: min(30rem, 100%); - } - - &.without-title .modal-content { - padding-top: 0; - } - - .modal-content { - padding-left: 2rem; - } -} diff --git a/src/components/main/WebAppModal.tsx b/src/components/main/WebAppModal.tsx index de152c173..ba11bd5c3 100644 --- a/src/components/main/WebAppModal.tsx +++ b/src/components/main/WebAppModal.tsx @@ -31,7 +31,7 @@ import MenuItem from '../ui/MenuItem'; import Spinner from '../ui/Spinner'; import ConfirmDialog from '../ui/ConfirmDialog'; -import './WebAppModal.scss'; +import styles from './WebAppModal.module.scss'; type WebAppButton = { isVisible: boolean; @@ -101,6 +101,7 @@ const WebAppModal: FC = ({ const [headerColor, setHeaderColor] = useState(extractCurrentThemeParams().bg_color); const [confirmClose, setConfirmClose] = useState(false); const [isCloseModalOpen, openCloseModal, closeCloseModal] = useFlag(false); + const [isLoaded, markLoaded, markUnloaded] = useFlag(false); const [popupParams, setPopupParams] = useState(); const { isMobile } = useAppLayout(); const prevPopupParams = usePrevious(popupParams); @@ -204,7 +205,7 @@ const WebAppModal: FC = ({ const { reloadFrame, sendEvent, sendViewport, sendTheme, - } = useWebAppFrame(frameRef, isOpen, isSimple, handleEvent); + } = useWebAppFrame(frameRef, isOpen, isSimple, handleEvent, markLoaded); const shouldShowMainButton = mainButton?.isVisible && mainButton.text.trim().length > 0; @@ -315,8 +316,9 @@ const WebAppModal: FC = ({ setConfirmClose(false); closeCloseModal(); setPopupParams(undefined); + markUnloaded(); } - }, [closeCloseModal, isOpen]); + }, [closeCloseModal, isOpen, markUnloaded]); const MoreMenuButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => { return ({ onTrigger, isOpen: isMenuOpen }) => ( @@ -335,8 +337,8 @@ const WebAppModal: FC = ({ }, [isMobile]); const backButtonClassName = buildClassName( - 'animated-close-icon', - isBackButtonVisible && 'state-back', + styles.closeIcon, + isBackButtonVisible && styles.stateBack, ); const header = useMemo(() => { @@ -361,6 +363,11 @@ const WebAppModal: FC = ({ {lang('BotWebViewOpenBot')} )} {lang('WebApp.ReloadPage')} + {attachBot?.hasSettings && ( + + {lang('Settings')} + + )} {bot?.isAttachBot && ( = ({ {lang(attachBot ? 'WebApp.RemoveBot' : 'WebApp.AddToAttachmentAdd')} )} - {attachBot?.hasSettings && ( - - {lang('Settings')} - - )} ); @@ -425,17 +427,18 @@ const WebAppModal: FC = ({ return ( + {isOpen && ( <>