Fixing the logging to ouput debug window
- Route-scoped refresh - Mock TDelegationContext - notistack for log copy errors - main-thread Tauri emit for log viewer events.
This commit is contained in:
@@ -62,10 +62,14 @@ pub fn setup_logging(app_handle: tauri::AppHandle) -> Result<(), log::SetLoggerE
|
||||
message: record.args().to_string(),
|
||||
level: record.level().into(),
|
||||
};
|
||||
// Tauri 2: target the log webview explicitly so the dedicated window receives events.
|
||||
if let Some(log_win) = log_window_app.get_webview_window("log") {
|
||||
let _ = log_win.emit("log://log", msg);
|
||||
}
|
||||
let app = log_window_app.clone();
|
||||
let app_for_emit = app.clone();
|
||||
// Logging callbacks often run off the UI thread; WebView event delivery must run on main (macOS).
|
||||
let _ = app.run_on_main_thread(move || {
|
||||
if let Some(log_win) = app_for_emit.get_webview_window("log") {
|
||||
let _ = log_win.emit("log://log", msg);
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
base_config
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { helpLogToggleWindow } from 'src/requests/logging';
|
||||
import { Console } from 'src/utils/console';
|
||||
|
||||
@@ -96,6 +97,7 @@ interface RecordPayload {
|
||||
|
||||
export const LogViewer: FC = () => {
|
||||
const theme = useTheme();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const unlisten = useRef<UnlistenFn | null>(null);
|
||||
const [messages, setMessages] = useState<RecordPayload[]>([]);
|
||||
const [messageCount, setMessageCount] = useState(0);
|
||||
@@ -154,6 +156,7 @@ export const LogViewer: FC = () => {
|
||||
await writeText(chronological.map(formatLine).join('\n'));
|
||||
} catch (e) {
|
||||
Console.error(e);
|
||||
enqueueSnackbar('Could not copy logs to the clipboard', { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -164,6 +167,7 @@ export const LogViewer: FC = () => {
|
||||
await writeText(formatLine(latest));
|
||||
} catch (e) {
|
||||
Console.error(e);
|
||||
enqueueSnackbar('Could not copy to the clipboard', { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@ import { Console } from 'src/utils/console';
|
||||
import { AppContext } from 'src/context/main';
|
||||
import { delegationQueryKeys, fetchDelegationSummaryQuery } from './delegationQuery';
|
||||
|
||||
export type TDelegationRefreshOptions = {
|
||||
/** When true, do not flip the global loading state (keeps cached list visible during refetch). */
|
||||
background?: boolean;
|
||||
};
|
||||
|
||||
export type TDelegationContext = {
|
||||
delegationItemErrors?: { nodeId: string; errors: string };
|
||||
isLoading: boolean;
|
||||
@@ -33,7 +28,7 @@ export type TDelegationContext = {
|
||||
totalDelegations?: string;
|
||||
totalRewards?: string;
|
||||
totalDelegationsAndRewards?: string;
|
||||
refresh: (opts?: TDelegationRefreshOptions) => Promise<void>;
|
||||
refresh: () => Promise<void>;
|
||||
addDelegation: (
|
||||
data: { mix_id: number; amount: DecCoin },
|
||||
tokenPool: TPoolOption,
|
||||
@@ -62,7 +57,7 @@ export const DelegationContext = createContext<TDelegationContext>({
|
||||
isFetching: false,
|
||||
isError: false,
|
||||
lastUpdatedAtMs: 0,
|
||||
refresh: async (_opts?: TDelegationRefreshOptions) => undefined,
|
||||
refresh: async () => undefined,
|
||||
addDelegation: async () => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
@@ -108,17 +103,14 @@ export const DelegationContextProvider: FC<{
|
||||
|
||||
const bundle = clientAddress && onDelegationRoute ? query.data : undefined;
|
||||
|
||||
const refresh = useCallback(
|
||||
async (_opts?: TDelegationRefreshOptions) => {
|
||||
if (!clientAddress) {
|
||||
return;
|
||||
}
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: delegationQueryKeys.summary(clientAddress),
|
||||
});
|
||||
},
|
||||
[clientAddress, queryClient],
|
||||
);
|
||||
const refresh = useCallback(async () => {
|
||||
if (!clientAddress || !onDelegationRoute) {
|
||||
return;
|
||||
}
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: delegationQueryKeys.summary(clientAddress),
|
||||
});
|
||||
}, [clientAddress, onDelegationRoute, queryClient]);
|
||||
|
||||
const addDelegation = async (data: { mix_id: number; amount: DecCoin }, tokenPool: TPoolOption, fee?: FeeDetails) => {
|
||||
try {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
FeeDetails,
|
||||
TransactionExecuteResult,
|
||||
} from '@nymproject/types';
|
||||
import { DelegationContext, TDelegationRefreshOptions, TDelegationTransaction } from '../delegations';
|
||||
import { DelegationContext, TDelegationTransaction } from '../delegations';
|
||||
|
||||
import { mockSleep } from './utils';
|
||||
import { TPoolOption } from '../../components';
|
||||
@@ -71,6 +71,9 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
const [error, setError] = useState<string>();
|
||||
const [delegations, setDelegations] = useState<undefined | DelegationWithEverything[]>();
|
||||
const [totalDelegations, setTotalDelegations] = useState<undefined | string>();
|
||||
const [totalRewards, setTotalRewards] = useState<undefined | string>();
|
||||
const [totalDelegationsAndRewards, setTotalDelegationsAndRewards] = useState<undefined | string>();
|
||||
const [lastUpdatedAtMs, setLastUpdatedAtMs] = useState(0);
|
||||
const [delegationItemErrors, setDelegationItemErrors] = useState<{ nodeId: string; errors: string }>();
|
||||
|
||||
const triggerStateUpdate = () => setTrigger(new Date());
|
||||
@@ -81,8 +84,16 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
const recalculate = async () => {
|
||||
const newDelegations = await getDelegations();
|
||||
const newTotalDelegations = `${newDelegations.length * 100} NYM`;
|
||||
const rewardsSum = newDelegations.reduce((acc, d) => {
|
||||
const n = parseFloat(d.unclaimed_rewards?.amount ?? '0');
|
||||
return acc + (Number.isFinite(n) ? n : 0);
|
||||
}, 0);
|
||||
const newTotalRewards = `${rewardsSum} nym`;
|
||||
setDelegations(newDelegations);
|
||||
setTotalDelegations(newTotalDelegations);
|
||||
setTotalRewards(newTotalRewards);
|
||||
setTotalDelegationsAndRewards(`${newTotalDelegations} + ${newTotalRewards}`);
|
||||
setLastUpdatedAtMs(Date.now());
|
||||
};
|
||||
|
||||
const addDelegation = async (
|
||||
@@ -193,8 +204,7 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
};
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const undelegateVesting = async (mix_id: number, _fee?: FeeDetails) => ({
|
||||
const undelegateVesting = async (_mix_id: number) => ({
|
||||
msg_responses_json: '',
|
||||
data_json: '',
|
||||
logs_json: '',
|
||||
@@ -210,10 +220,13 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
setIsLoading(true);
|
||||
setError(undefined);
|
||||
setTotalDelegations(undefined);
|
||||
setTotalRewards(undefined);
|
||||
setTotalDelegationsAndRewards(undefined);
|
||||
setLastUpdatedAtMs(0);
|
||||
setDelegations([]);
|
||||
};
|
||||
|
||||
const refresh = useCallback(async (_opts?: TDelegationRefreshOptions) => {
|
||||
const refresh = useCallback(async () => {
|
||||
resetState();
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
@@ -239,18 +252,32 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
isLoading,
|
||||
isFetching: isLoading,
|
||||
isError: Boolean(error),
|
||||
lastUpdatedAtMs: 0,
|
||||
error,
|
||||
lastUpdatedAtMs,
|
||||
delegations,
|
||||
pendingDelegations: [],
|
||||
totalDelegations,
|
||||
totalRewards,
|
||||
totalDelegationsAndRewards,
|
||||
refresh,
|
||||
getDelegations,
|
||||
addDelegation,
|
||||
updateDelegation,
|
||||
undelegate,
|
||||
undelegateVesting,
|
||||
}),
|
||||
[isLoading, error, delegations, totalDelegations, trigger],
|
||||
[
|
||||
isLoading,
|
||||
error,
|
||||
delegations,
|
||||
totalDelegations,
|
||||
totalRewards,
|
||||
totalDelegationsAndRewards,
|
||||
lastUpdatedAtMs,
|
||||
refresh,
|
||||
addDelegation,
|
||||
undelegate,
|
||||
undelegateVesting,
|
||||
delegationItemErrors,
|
||||
trigger,
|
||||
],
|
||||
);
|
||||
|
||||
return <DelegationContext.Provider value={memoizedValue}>{children}</DelegationContext.Provider>;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { FeeDetails, TransactionExecuteResult } from '@nymproject/types';
|
||||
import { type TDelegationRefreshOptions, useDelegationContext } from './delegations';
|
||||
import { useDelegationContext } from './delegations';
|
||||
import { claimDelegatorRewards } from '../requests';
|
||||
|
||||
type TRewardsContext = {
|
||||
isLoading: boolean;
|
||||
error?: string;
|
||||
totalRewards?: string;
|
||||
refresh: (opts?: TDelegationRefreshOptions) => Promise<void>;
|
||||
refresh: () => Promise<void>;
|
||||
claimRewards: (mixId: number, fee?: FeeDetails) => Promise<TransactionExecuteResult[]>;
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ export type TRewardsTransaction = {
|
||||
|
||||
export const RewardsContext = createContext<TRewardsContext>({
|
||||
isLoading: false,
|
||||
refresh: async (_opts?: TDelegationRefreshOptions) => undefined,
|
||||
refresh: async () => undefined,
|
||||
claimRewards: async () => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { SnackbarProvider } from 'notistack';
|
||||
import { LogViewer } from './components/LogViewer';
|
||||
import { ErrorFallback } from './components';
|
||||
import { NymWalletTheme } from './theme';
|
||||
|
||||
const Log = () => (
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<NymWalletTheme>
|
||||
<LogViewer />
|
||||
</NymWalletTheme>
|
||||
<SnackbarProvider anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}>
|
||||
<NymWalletTheme>
|
||||
<LogViewer />
|
||||
</NymWalletTheme>
|
||||
</SnackbarProvider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ export const DelegationPage: FC = () => {
|
||||
const doMigrateNow = async () => {
|
||||
setShowVestingMigrationProgressModal(true);
|
||||
await migrateVestedDelegations();
|
||||
await refreshDelegations(undefined);
|
||||
await refreshDelegations();
|
||||
setShowVestingMigrationProgressModal(false);
|
||||
};
|
||||
|
||||
@@ -132,7 +132,7 @@ export const DelegationPage: FC = () => {
|
||||
});
|
||||
}
|
||||
prevConfirmationModalProps.current = confirmationModalProps;
|
||||
}, [confirmationModalProps]);
|
||||
}, [confirmationModalProps, refreshWithIntervalUpdate]);
|
||||
|
||||
const handleDelegationItemActionClick = (item: DelegationWithEverything, action: DelegationListItemActions) => {
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user