mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
feat: enhance error handling in WalletInfoSection and improve user feedback
- Added error reporting functionality in `WalletInfoSection` to capture and enqueue errors when wallet info fails to load. - Updated `Mnemonic` component to handle user state more robustly, ensuring encryption key is only set if the user is loaded. - Refactored `TauriCommandsPanel` to improve string comparisons for loading states by converting to lowercase. - Adjusted deep link handling in `desktopDeepLinkListener` to use trimmed hex values for encryption key conversion.
This commit is contained in:
@@ -3,6 +3,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useUser } from '../hooks/useUser';
|
||||
import { useSkillConnectionStatus } from '../lib/skills/hooks';
|
||||
import { skillManager } from '../lib/skills/manager';
|
||||
import { buildManualSentryEvent, enqueueError } from '../services/errorReportQueue';
|
||||
import { useAppSelector } from '../store/hooks';
|
||||
|
||||
function truncateAddress(address: string): string {
|
||||
@@ -131,6 +132,18 @@ export default function WalletInfoSection() {
|
||||
return;
|
||||
}
|
||||
console.error('[WalletInfoSection] Failed to load wallet info:', e);
|
||||
enqueueError({
|
||||
id: crypto.randomUUID(),
|
||||
timestamp: Date.now(),
|
||||
source: 'manual',
|
||||
title: 'Failed to load wallet info',
|
||||
message: e instanceof Error ? e.message : String(e),
|
||||
sentryEvent: buildManualSentryEvent(
|
||||
{ type: 'WalletInfoLoadError', value: e instanceof Error ? e.message : String(e) },
|
||||
{ component: 'WalletInfoSection' }
|
||||
),
|
||||
originalError: e instanceof Error ? e : new Error(String(e)),
|
||||
});
|
||||
setError('Failed to load wallet info');
|
||||
setBalance(null);
|
||||
setNetworkName(null);
|
||||
|
||||
@@ -37,8 +37,8 @@ import {
|
||||
runtimeEnableSkill,
|
||||
runtimeIsSkillEnabled,
|
||||
runtimeListSkills,
|
||||
SkillSnapshot,
|
||||
TunnelConfig,
|
||||
type SkillSnapshot,
|
||||
type TunnelConfig,
|
||||
} from '../../../utils/tauriCommands';
|
||||
import SettingsHeader from '../components/SettingsHeader';
|
||||
import { useSettingsNavigation } from '../hooks/useSettingsNavigation';
|
||||
@@ -554,9 +554,9 @@ const TauriCommandsPanel = () => {
|
||||
defaultExpanded={!isCollapsed('security-data')}
|
||||
hasChanges={false}
|
||||
loading={
|
||||
operationLoading?.includes('Secret') ||
|
||||
operationLoading?.includes('Models') ||
|
||||
operationLoading?.includes('Integration')
|
||||
operationLoading?.toLowerCase()?.includes('secret') ||
|
||||
operationLoading?.toLowerCase()?.includes('models') ||
|
||||
operationLoading?.toLowerCase()?.includes('integration')
|
||||
}>
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<InputGroup
|
||||
@@ -680,9 +680,9 @@ const TauriCommandsPanel = () => {
|
||||
defaultExpanded={!isCollapsed('network-infrastructure')}
|
||||
hasChanges={false}
|
||||
loading={
|
||||
operationLoading?.includes('Gateway') ||
|
||||
operationLoading?.includes('Tunnel') ||
|
||||
operationLoading?.includes('Memory')
|
||||
operationLoading?.toLowerCase()?.includes('gateway') ||
|
||||
operationLoading?.toLowerCase()?.includes('tunnel') ||
|
||||
operationLoading?.toLowerCase()?.includes('memory')
|
||||
}>
|
||||
<div className="grid gap-8 lg:grid-cols-2">
|
||||
<InputGroup
|
||||
@@ -861,9 +861,9 @@ const TauriCommandsPanel = () => {
|
||||
defaultExpanded={!isCollapsed('development-operations')}
|
||||
hasChanges={false}
|
||||
loading={
|
||||
operationLoading?.includes('Doctor') ||
|
||||
operationLoading?.includes('Hardware') ||
|
||||
operationLoading?.includes('Migration')
|
||||
operationLoading?.toLowerCase()?.includes('doctor') ||
|
||||
operationLoading?.toLowerCase()?.includes('hardware') ||
|
||||
operationLoading?.toLowerCase()?.includes('migration')
|
||||
}>
|
||||
<div className="grid gap-8 lg:grid-cols-2">
|
||||
<InputGroup title="Diagnostics" description="System health checks and model probing">
|
||||
|
||||
@@ -150,11 +150,14 @@ const Mnemonic = () => {
|
||||
const aesKey = deriveAesKeyFromMnemonic(phraseToUse);
|
||||
const walletAddress = deriveEvmAddressFromMnemonic(phraseToUse);
|
||||
|
||||
if (user?._id) {
|
||||
dispatch(setEncryptionKeyForUser({ userId: user._id, key: aesKey }));
|
||||
await skillManager.setWalletAddress(walletAddress);
|
||||
if (!user?._id) {
|
||||
const msg = 'User not loaded. Please sign in again or refresh the page.';
|
||||
setError(msg);
|
||||
console.error('[Mnemonic] Cannot save encryption key: user not loaded');
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setEncryptionKeyForUser({ userId: user._id, key: aesKey }));
|
||||
await skillManager.setWalletAddress(walletAddress);
|
||||
navigate('/home');
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : 'Something went wrong. Please try again.');
|
||||
|
||||
@@ -146,7 +146,7 @@ const handleOAuthDeepLink = async (parsed: URL) => {
|
||||
|
||||
let keyForBackend: string;
|
||||
try {
|
||||
keyForBackend = hexToBase64(encryptionKeyHex);
|
||||
keyForBackend = hexToBase64(trimmedHex);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
'[DeepLink] Cannot fetch integration tokens: encryption key conversion failed',
|
||||
@@ -191,7 +191,7 @@ const handleOAuthDeepLink = async (parsed: URL) => {
|
||||
try {
|
||||
const decryptedJson = await decryptIntegrationTokens(
|
||||
response.data.encrypted,
|
||||
encryptionKeyHex
|
||||
trimmedHex
|
||||
);
|
||||
const payload = JSON.parse(decryptedJson) as IntegrationTokensPayload;
|
||||
if (payload.accessToken) {
|
||||
|
||||
Reference in New Issue
Block a user