mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2026-03-13 10:00:26 +08:00
Merge pull request #92 from AppFlowy-IO/loading_animatino
Use dot animation instead of workspace animation
This commit is contained in:
@@ -6,6 +6,7 @@ import { ReactComponent as LoginIcon } from '@/assets/icons/logout.svg';
|
||||
import { ReactComponent as MoonIcon } from '@/assets/icons/moon.svg';
|
||||
import { ReactComponent as SunIcon } from '@/assets/icons/sun.svg';
|
||||
import CacheClearingDialog from '@/components/_shared/modal/CacheClearingDialog';
|
||||
import LogoutConfirm from '@/components/app/workspaces/LogoutConfirm';
|
||||
import { AFConfigContext } from '@/components/main/app.hooks';
|
||||
import { ThemeModeContext } from '@/components/main/useAppThemeMode';
|
||||
import { openUrl } from '@/utils/url';
|
||||
@@ -23,12 +24,21 @@ function MoreActionsContent({
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleLogin = useCallback(() => {
|
||||
const handleLogout = useCallback(() => {
|
||||
clearRedirectTo(); // Clear stored redirect URL from previous user
|
||||
invalidToken();
|
||||
navigate('/login?redirectTo=' + encodeURIComponent(window.location.href));
|
||||
}, [navigate]);
|
||||
|
||||
const handleLogin = useCallback(() => {
|
||||
if (isAuthenticated) {
|
||||
setOpenLogoutConfirm(true);
|
||||
} else {
|
||||
handleLogout();
|
||||
}
|
||||
}, [isAuthenticated, handleLogout]);
|
||||
const [openConfirm, setOpenConfirm] = React.useState(false);
|
||||
const [openLogoutConfirm, setOpenLogoutConfirm] = React.useState(false);
|
||||
|
||||
const actions = useMemo(() => {
|
||||
const items = [
|
||||
@@ -98,6 +108,11 @@ function MoreActionsContent({
|
||||
<>
|
||||
{actionsContent}
|
||||
<CacheClearingDialog open={openConfirm} onClose={() => setOpenConfirm(false)} />
|
||||
<LogoutConfirm
|
||||
open={openLogoutConfirm}
|
||||
onClose={() => setOpenLogoutConfirm(false)}
|
||||
onConfirm={handleLogout}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import { AuthInternalContext } from './contexts/AuthInternalContext';
|
||||
import { AppAuthLayer } from './layers/AppAuthLayer';
|
||||
import { AppBusinessLayer } from './layers/AppBusinessLayer';
|
||||
import { AppSyncLayer } from './layers/AppSyncLayer';
|
||||
import { WorkspaceLoadingAnimation } from './WorkspaceLoadingAnimation';
|
||||
import LoadingDots from '@/components/_shared/LoadingDots';
|
||||
|
||||
// Main AppContext interface - kept identical to maintain backward compatibility
|
||||
export interface AppContextType {
|
||||
@@ -101,7 +101,11 @@ const ConditionalWorkspaceLayers = ({ children }: { children: React.ReactNode })
|
||||
|
||||
// Show loading animation while workspace ID is being loaded
|
||||
if (!userWorkspaceInfo) {
|
||||
return <WorkspaceLoadingAnimation />;
|
||||
return (
|
||||
<div className='fixed inset-0 flex items-center justify-center bg-background-primary'>
|
||||
<LoadingDots className='flex items-center justify-center' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -18,7 +18,7 @@ export const AppAuthLayer: React.FC<AppAuthLayerProps> = ({ children }) => {
|
||||
const service = useService();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
|
||||
|
||||
const [userWorkspaceInfo, setUserWorkspaceInfo] = useState<UserWorkspaceInfo | undefined>(undefined);
|
||||
|
||||
// Calculate current workspace ID from URL params or user info
|
||||
|
||||
69
src/components/app/workspaces/LogoutConfirm.tsx
Normal file
69
src/components/app/workspaces/LogoutConfirm.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { createHotkey, HOT_KEY_NAME } from '@/utils/hotkeys';
|
||||
|
||||
export function LogoutConfirm({
|
||||
open,
|
||||
onClose,
|
||||
onConfirm,
|
||||
}: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onConfirm: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleLogout = () => {
|
||||
onConfirm();
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(status) => {
|
||||
if (!status) {
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogContent
|
||||
onCloseAutoFocus={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
e.stopPropagation();
|
||||
if (createHotkey(HOT_KEY_NAME.ENTER)(e.nativeEvent)) {
|
||||
handleLogout();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('button.logout')}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
{t('settings.menu.logoutPrompt')}
|
||||
</DialogDescription>
|
||||
<DialogFooter>
|
||||
<Button variant={'outline'} onClick={onClose}>
|
||||
{t('button.cancel')}
|
||||
</Button>
|
||||
<Button variant={'destructive'} onClick={handleLogout} data-testid="logout-confirm-button">
|
||||
{t('button.logout')}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default LogoutConfirm;
|
||||
@@ -40,6 +40,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip
|
||||
import { openUrl } from '@/utils/url';
|
||||
|
||||
import { AccountSettings } from './AccountSettings';
|
||||
import LogoutConfirm from '@/components/app/workspaces/LogoutConfirm';
|
||||
|
||||
export function Workspaces() {
|
||||
const { t } = useTranslation();
|
||||
@@ -66,6 +67,7 @@ export function Workspaces() {
|
||||
const [openRenameWorkspace, setOpenRenameWorkspace] = useState<Workspace | null>(null);
|
||||
const [openDeleteWorkspace, setOpenDeleteWorkspace] = useState<Workspace | null>(null);
|
||||
const [openLeaveWorkspace, setOpenLeaveWorkspace] = useState<Workspace | null>(null);
|
||||
const [openLogoutConfirm, setOpenLogoutConfirm] = useState(false);
|
||||
|
||||
const isOwner = currentWorkspace?.owner?.uid.toString() === currentUser?.uid.toString();
|
||||
|
||||
@@ -229,7 +231,7 @@ export function Workspaces() {
|
||||
<div className={'flex-1 text-left'}>{t('web.accountSettings')}</div>
|
||||
</DropdownMenuItem>
|
||||
</AccountSettings>
|
||||
<DropdownMenuItem onSelect={handleSignOut}>
|
||||
<DropdownMenuItem onSelect={() => setOpenLogoutConfirm(true)}>
|
||||
<LogoutIcon />
|
||||
{t('button.logout')}
|
||||
</DropdownMenuItem>
|
||||
@@ -323,6 +325,12 @@ export function Workspaces() {
|
||||
openOnChange={() => setOpenLeaveWorkspace(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<LogoutConfirm
|
||||
open={openLogoutConfirm}
|
||||
onClose={() => setOpenLogoutConfirm(false)}
|
||||
onConfirm={handleSignOut}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import LinearProgress from '@mui/material/LinearProgress';
|
||||
import * as React from 'react';
|
||||
|
||||
export default function LinearBuffer () {
|
||||
export default function LinearBuffer() {
|
||||
const [progress, setProgress] = React.useState(0);
|
||||
const [buffer, setBuffer] = React.useState(10);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useContext, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ReactComponent as ErrorIcon } from '@/assets/icons/error.svg';
|
||||
import { WorkspaceLoadingAnimation } from '@/components/app/WorkspaceLoadingAnimation';
|
||||
import LoadingDots from '@/components/_shared/LoadingDots';
|
||||
|
||||
function LoginAuth () {
|
||||
const service = useContext(AFConfigContext)?.service;
|
||||
@@ -36,7 +36,7 @@ function LoginAuth () {
|
||||
<>
|
||||
{loading ? (
|
||||
<div className={'flex h-screen w-screen items-center justify-center p-20'}>
|
||||
<WorkspaceLoadingAnimation />
|
||||
<LoadingDots className='flex items-center justify-center' />
|
||||
</div>
|
||||
) : null}
|
||||
<NormalModal
|
||||
|
||||
Reference in New Issue
Block a user