Merge pull request #92 from AppFlowy-IO/loading_animatino

Use dot animation instead of workspace animation
This commit is contained in:
Nathan.fooo
2025-10-01 21:27:32 +08:00
committed by GitHub
7 changed files with 105 additions and 9 deletions

View File

@@ -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}
/>
</>
);
}

View File

@@ -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 (

View File

@@ -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

View 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;

View File

@@ -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}
/>
</>
);
}

View File

@@ -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);

View File

@@ -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