import React, { ReactElement } from 'react';
import { useAppDispatch, useAppSelector } from '../store/hooks';
import { isDev } from '../shared/utils';
import { cleanupAsync, isDesynced, updateWindowsAsync } from '../store/windowsSlice';
import { useLiveQuery } from 'dexie-react-hooks';
import { getBackupEveryNSeconds, getIsBackupOverdue, getLatestBackup, getTabvanaWindowId } from '../db/prefs';
import { requestBackupPermission, setBackupDir, maybeBackup } from '../db/backup';
import { faArrowsRotate, faBroom, faGear, faPlugCircleBolt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { openOptionsPageInWindow } from '../chrome/chromeActions';
import IconButton from '@mui/joy/IconButton';
import { Button, CircularProgress, Tooltip } from '@mui/joy';
import { useActiveProgress, clearAllProgress, useCompletedProgress } from '../db/progress';
import { clearQueue } from '../db/queue';
const GlobalButtons = React.memo((): ReactElement => {
const tabvanaWindowId = useLiveQuery(getTabvanaWindowId);
const isBackupOverdue = useLiveQuery(getIsBackupOverdue);
const { totalWork, completedWork, activeTasks, operations } = useActiveProgress();
const completedProgressTasks = useCompletedProgress();
const dispatch = useAppDispatch();
const desynced = useAppSelector(isDesynced);
const working = activeTasks > 0;
const handleCancelTasks = async () => {
await clearQueue();
await clearAllProgress();
};
const tooltipContent = (
{operations.length > 0 ? (
<>
Total: {completedWork} / {totalWork}
{Object.entries(
operations.reduce((acc, op) => {
if (!acc[op.type]) acc[op.type] = { current: 0, total: 0 };
acc[op.type].current += op.current;
acc[op.type].total += op.total;
return acc;
}, {} as Record
)
).map(([type, stats]) => {
const label = type === 'generateEmbedding'
? 'Generating embeddings'
: type === 'backup'
? 'Backup in progress'
: type === 'renormalize'
? 'Renormalizing database'
: type === 'similarity'
? 'Calculating similarities'
: type.charAt(0).toUpperCase() + type.slice(1);
return (
{label}: {stats.current} / {stats.total}
);
})}
>
) : (
No active background tasks
)}
{completedProgressTasks.length > 0 && (
<>
Completed Tasks ({completedProgressTasks.length})
{completedProgressTasks.map((op, i) => {
const label = op.type === 'generateEmbedding'
? 'Generated embeddings'
: op.type === 'backup'
? 'Backup completed'
: op.type === 'renormalize'
? 'Renormalized database'
: op.type === 'similarity'
? 'Calculated similarities'
: op.type.charAt(0).toUpperCase() + op.type.slice(1) + ' completed';
return (
{label} ({op.total})
);
})}
>
)}
);
return (
0}
value={activeTasks === 0 ? 0 : (totalWork > 0 ? (completedWork / totalWork) * 100 : undefined)}
color={activeTasks > 0 ? 'primary' : 'neutral'}
sx={{
verticalAlign: 'middle',
margin: '0.2rem',
...(activeTasks > 0 && {
animation: 'pulse 1.5s ease-in-out infinite',
'@keyframes pulse': {
'0%': { opacity: 0.6 },
'50%': { opacity: 1 },
'100%': { opacity: 0.6 },
},
}),
}}
>
{/* totalWork > 0 && {Math.round((completedWork / totalWork) * 100)}% */}
{isBackupOverdue && (
)}
{desynced && (
)}
{isDev && (
chrome.runtime.reload()} title="Reload Extension">
)}
{
dispatch(cleanupAsync(tabvanaWindowId));
}}
title="Clean Up"
/>
openOptionsPageInWindow()}
title="Settings"
/>
);
});
export default GlobalButtons;