From 7bce9d2bbe919b26e03d5d2f5d7cec857a32161e Mon Sep 17 00:00:00 2001 From: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Date: Sun, 5 Apr 2026 17:21:05 -0700 Subject: [PATCH] UI polish: skill encryption key, disconnect fix, settings layout cleanup (#330) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add overlay process launcher for OpenHuman (#328) - Introduced a new `overlay` module to manage the lifecycle of the `openhuman-overlay` Tauri application. - Implemented the `spawn_overlay` function to discover and launch the overlay as a child process, enhancing the user experience with a transparent debug/voice panel. - Updated the `jsonrpc.rs` file to invoke the overlay process when the core server starts, ensuring seamless integration. - Enhanced module organization by adding the `overlay` module to the `openhuman` namespace. * feat: add animated mesh gradient background to App component - Introduced a new `MeshGradient` component that renders an animated WebGL mesh gradient background, enhancing the visual appeal of the application. - Updated the `App` component to include the `MeshGradient`, ensuring it renders behind the dotted canvas overlay for improved aesthetics. - Modified the CSS for the `app-dotted-canvas` to use a transparent background and adjusted the gradient styling for better integration with the new component. - Added TypeScript definitions and implementation for the `Gradient` class to manage the mesh gradient functionality. * style: update MeshGradient component colors and opacity - Changed the opacity of the mesh gradient from 20% to 10% for a more subtle effect. - Updated gradient colors to enhance visual appeal, replacing previous colors with a new palette for better integration with the overall design. * feat: enhance SkillSetupWizard with encryption key support - Added a new input field for client-side encryption key in the OAuthLoginView component, improving security during manual integration. - Implemented validation to ensure the encryption key is provided before submission, enhancing error handling. - Updated the layout to accommodate both integration ID and encryption key inputs, improving user experience in development mode. - Refactored related logic to streamline the handling of integration ID and encryption key during OAuth completion. * feat: integrate skill installation check in SkillSetupWizard - Updated the OAuthLoginView component to ensure skills are installed before starting the runtime, enhancing reliability during the setup process. - Added error handling to manage cases where the skill may already be installed, improving user experience and reducing potential runtime errors. * fix: improve base directory resolution in skill runtime - Updated the base directory resolution logic in both `jsonrpc.rs` and `skills_cli.rs` to filter out empty workspace paths, enhancing robustness. - Added debug logging in `qjs_engine.rs` to provide better visibility into skill startup processes, including checks for manifest existence and workspace directory status. * feat: enhance SkillManager with skill stopping and client key cleanup - Implemented the `stopSkill` method to halt the frontend-side runtime and added a call to `rpcStopSkill` for stopping the core sidecar skill process. - Introduced `removePersistedClientKey` function to clear the client-side encryption key, ensuring better security and resource management during skill revocation. - Added error handling and debug logging for both stopping the skill and cleaning up the client key, improving observability and reliability. * style: update OnboardingOverlay background opacity and refine settings warning message - Changed the background opacity of the OnboardingOverlay from 95% to 50% for a more subtle appearance. - Revised the warning message in SettingsHome to clarify the local data deletion process, improving user understanding of the consequences of signing out. * refactor: simplify layout structure in settings components - Removed unnecessary overflow properties from the main container divs in SettingsHome, SettingsSectionPage, and SettingsPanelLayout components, improving layout clarity. - Adjusted child divs to ensure proper content display without overflow, enhancing user experience in the settings interface. * style: adjust padding and spacing in SettingsSectionPage component - Updated padding in the main container from `p-4` to `py-4` for improved vertical spacing. - Increased horizontal padding of the description text from `px-1` to `px-5`, enhancing readability and visual appeal. * style: refine layout and spacing in settings components - Adjusted padding and spacing in SettingsSectionPage, SettingsBackButton, and SettingsHeader components for improved visual consistency. - Updated font sizes and margins to enhance readability and user experience across the settings interface. * style: simplify layout and improve spacing in settings panels - Removed unnecessary flex properties and adjusted padding in various settings panels for a cleaner layout. - Standardized spacing across panels to enhance visual consistency and user experience. - Updated component structures to eliminate redundant overflow properties, improving content display. * style: simplify section layouts and improve spacing in settings panels - Removed unnecessary border and background properties from multiple sections in the Accessibility, Screen Intelligence, and other settings panels for a cleaner appearance. - Standardized section spacing and padding across various panels to enhance visual consistency and user experience. - Updated font sizes for better readability and adjusted button styles for improved interaction. * style: standardize panel headings from text-lg to text-sm Co-Authored-By: Claude Opus 4.6 (1M context) * style: update heading for connected skills section to improve clarity - Changed the section title from "Connected Skills" to "3rd Party Skills" for better representation of the content. * style: improve code formatting and spacing in various components - Enhanced readability by adjusting spacing and formatting in SettingsBackButton, MemoryDebugPanel, WebhooksDebugPanel, and other components. - Standardized the layout of JSX elements for better visual consistency across the application. - Cleaned up log messages in Rust files for improved clarity and debugging. * fix: enhance MeshGradient cleanup and improve settings warning message - Added a call to `gradient.disconnect()` in the MeshGradient component to ensure proper cleanup on unmount. - Updated the warning message in SettingsHome to use a list format for better clarity regarding local data deletion consequences. - Removed unused 'tauri-commands' route from settings navigation for cleaner code. - Added validation for the encryption key in SkillSetupWizard to prevent invalid characters. - Updated the Gradient class to include additional checks for canvas element and WebGL context during initialization. - Improved error handling in SkillManager's `stopSkill` method for better debugging and reliability. * style: correct comment formatting in meshGradient.js - Updated comment syntax in the Gradient class to ensure proper code documentation and readability. * fix: add encryption key validation and remove double transition in dev setup - Validate devEncryptionKey for invalid characters (quotes, backslashes, control chars) before using as X-Encryption-Key header - Remove explicit onManualComplete() call — let the snapshot effect handle the connected→setup transition to avoid double-firing startSkill/startSetup Co-Authored-By: Claude Opus 4.6 (1M context) * fix: improve encryption key validation in SkillSetupWizard - Enhanced validation for the devEncryptionKey to check for quotes, backslashes, and control characters, ensuring only valid characters are accepted. - This change prevents potential issues when using the encryption key in the application. * fix: resolve lint errors in MeshGradient, meshGradient.js, and SkillSetupWizard - Fix canvasRef.current stale ref warning by capturing to local variable - Add eslint-disable for browser globals in vendored meshGradient.js - Replace control character regex with printable-range check - Remove unused onManualComplete from dependency array Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) --- app/src/App.tsx | 12 +- app/src/components/MeshGradient.tsx | 45 ++ app/src/components/OnboardingOverlay.tsx | 2 +- app/src/components/settings/SettingsHome.tsx | 22 +- .../settings/SettingsSectionPage.tsx | 32 +- .../components/SettingsBackButton.tsx | 12 +- .../settings/components/SettingsHeader.tsx | 8 +- .../components/SettingsPanelLayout.tsx | 4 +- .../settings/hooks/useSettingsNavigation.ts | 2 - .../components/settings/panels/AIPanel.tsx | 12 +- .../settings/panels/AccessibilityPanel.tsx | 12 +- .../settings/panels/AdvancedPanel.tsx | 56 +- .../settings/panels/AgentChatPanel.tsx | 8 +- .../settings/panels/AutocompletePanel.tsx | 4 +- .../settings/panels/BillingPanel.tsx | 2 +- .../settings/panels/ConnectionsPanel.tsx | 6 +- .../settings/panels/CronJobsPanel.tsx | 8 +- .../settings/panels/DeveloperOptionsPanel.tsx | 46 +- .../settings/panels/LocalModelPanel.tsx | 26 +- .../settings/panels/MemoryDebugPanel.tsx | 440 +++++------ .../settings/panels/MessagingPanel.tsx | 4 +- .../settings/panels/PrivacyPanel.tsx | 6 +- .../settings/panels/ProfilePanel.tsx | 44 +- .../settings/panels/RecoveryPhrasePanel.tsx | 4 +- .../panels/ScreenIntelligencePanel.tsx | 14 +- .../settings/panels/SkillsPanel.tsx | 8 +- .../settings/panels/TauriCommandsPanel.tsx | 4 +- .../settings/panels/TeamInvitesPanel.tsx | 6 +- .../settings/panels/TeamManagementPanel.tsx | 14 +- .../settings/panels/TeamMembersPanel.tsx | 8 +- .../components/settings/panels/TeamPanel.tsx | 6 +- .../settings/panels/WebhooksDebugPanel.tsx | 284 +++----- .../components/skills/SkillSetupWizard.tsx | 67 +- app/src/index.css | 4 +- app/src/lib/meshGradient.d.ts | 14 + app/src/lib/meshGradient.js | 686 ++++++++++++++++++ app/src/lib/skills/manager.ts | 22 + app/src/lib/skills/skillsApi.ts | 8 + app/src/pages/Settings.tsx | 8 +- app/src/pages/Skills.tsx | 2 +- src/core/jsonrpc.rs | 22 +- src/core/repl.rs | 21 +- src/core/skills_cli.rs | 4 +- src/openhuman/config/schema/load.rs | 83 +-- src/openhuman/config/schema/mod.rs | 1 + src/openhuman/config/schema/types.rs | 6 + src/openhuman/mod.rs | 1 + src/openhuman/overlay/mod.rs | 7 + src/openhuman/overlay/process.rs | 134 ++++ src/openhuman/skills/qjs_engine.rs | 17 + yarn.lock | 31 +- 51 files changed, 1523 insertions(+), 776 deletions(-) create mode 100644 app/src/components/MeshGradient.tsx create mode 100644 app/src/lib/meshGradient.d.ts create mode 100644 app/src/lib/meshGradient.js create mode 100644 src/openhuman/overlay/mod.rs create mode 100644 src/openhuman/overlay/process.rs diff --git a/app/src/App.tsx b/app/src/App.tsx index b4b993fdf..31bb56172 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -8,6 +8,7 @@ import BottomTabBar from './components/BottomTabBar'; import ServiceBlockingGate from './components/daemon/ServiceBlockingGate'; import ErrorFallbackScreen from './components/ErrorFallbackScreen'; import LocalAIDownloadSnackbar from './components/LocalAIDownloadSnackbar'; +import MeshGradient from './components/MeshGradient'; import OnboardingOverlay from './components/OnboardingOverlay'; import CoreStateProvider from './providers/CoreStateProvider'; import SocketProvider from './providers/SocketProvider'; @@ -29,11 +30,14 @@ function App() { -
-
- +
+ +
+
+ +
+
-
diff --git a/app/src/components/MeshGradient.tsx b/app/src/components/MeshGradient.tsx new file mode 100644 index 000000000..db380c278 --- /dev/null +++ b/app/src/components/MeshGradient.tsx @@ -0,0 +1,45 @@ +import { useEffect, useRef } from 'react'; + +import { Gradient } from '../lib/meshGradient'; + +/** + * Animated WebGL mesh gradient background (Stripe-style). + * Renders behind the dotted-canvas overlay so dots remain visible on top. + */ +export default function MeshGradient() { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + const gradient = new Gradient(); + gradient.initGradient('#mesh-gradient'); + + return () => { + gradient.disconnect(); + gradient.pause(); + if (canvas) { + const gl = canvas.getContext('webgl') || canvas.getContext('webgl2'); + if (gl) { + gl.getExtension('WEBGL_lose_context')?.loseContext(); + } + } + }; + }, []); + + return ( + + ); +} diff --git a/app/src/components/OnboardingOverlay.tsx b/app/src/components/OnboardingOverlay.tsx index e2ab9f937..3c0ce9343 100644 --- a/app/src/components/OnboardingOverlay.tsx +++ b/app/src/components/OnboardingOverlay.tsx @@ -53,7 +53,7 @@ const OnboardingOverlay = () => { if (!shouldShow) return null; return createPortal( -
+
, document.body diff --git a/app/src/components/settings/SettingsHome.tsx b/app/src/components/settings/SettingsHome.tsx index f1f5c38a2..f4f0dcc15 100644 --- a/app/src/components/settings/SettingsHome.tsx +++ b/app/src/components/settings/SettingsHome.tsx @@ -180,10 +180,10 @@ const SettingsHome = () => { ]; return ( -
+
-
+
{/* Grouped Settings */} {groupedMenuItems.map((item, index) => ( {
-

- This will sign you out and permanently delete local app data including: • App - settings and conversations • Email data from Gmail • Chat history from Telegram • - Cached files from Notion • All other skills data -
-
- This action cannot be undone and may take a few moments to complete. -

+
+

This will sign you out and permanently delete local app data including:

+
    +
  • App settings and conversations
  • +
  • All skills data
  • +
  • Workspace data
  • +
  • All other local data
  • +
+

This action cannot be undone.

+
{error && (
diff --git a/app/src/components/settings/SettingsSectionPage.tsx b/app/src/components/settings/SettingsSectionPage.tsx index af90c1709..5830f2a65 100644 --- a/app/src/components/settings/SettingsSectionPage.tsx +++ b/app/src/components/settings/SettingsSectionPage.tsx @@ -22,26 +22,24 @@ const SettingsSectionPage = ({ title, description, items }: SettingsSectionPageP const { navigateBack, navigateToSettings } = useSettingsNavigation(); return ( -
+
-
-
- {description &&

{description}

} +
+ {description &&

{description}

} -
- {items.map((item, index) => ( - navigateToSettings(item.route)} - isFirst={index === 0} - isLast={index === items.length - 1} - /> - ))} -
+
+ {items.map((item, index) => ( + navigateToSettings(item.route)} + isFirst={index === 0} + isLast={index === items.length - 1} + /> + ))}
diff --git a/app/src/components/settings/components/SettingsBackButton.tsx b/app/src/components/settings/components/SettingsBackButton.tsx index 80f6289e3..5a424b09e 100644 --- a/app/src/components/settings/components/SettingsBackButton.tsx +++ b/app/src/components/settings/components/SettingsBackButton.tsx @@ -10,15 +10,19 @@ const SettingsBackButton = ({ className = '', }: SettingsBackButtonProps) => { return ( -
+
); diff --git a/app/src/components/settings/components/SettingsHeader.tsx b/app/src/components/settings/components/SettingsHeader.tsx index a272ed2e8..513eb2013 100644 --- a/app/src/components/settings/components/SettingsHeader.tsx +++ b/app/src/components/settings/components/SettingsHeader.tsx @@ -12,16 +12,16 @@ const SettingsHeader = ({ onBack, }: SettingsHeaderProps) => { return ( -
+
{/* Back button */} {showBackButton && onBack && (
); diff --git a/app/src/components/settings/components/SettingsPanelLayout.tsx b/app/src/components/settings/components/SettingsPanelLayout.tsx index 5e52a4833..c406d1ae2 100644 --- a/app/src/components/settings/components/SettingsPanelLayout.tsx +++ b/app/src/components/settings/components/SettingsPanelLayout.tsx @@ -16,9 +16,9 @@ const SettingsPanelLayout = ({ className = '', }: SettingsPanelLayoutProps) => { return ( -
+
-
{children}
+
{children}
); }; diff --git a/app/src/components/settings/hooks/useSettingsNavigation.ts b/app/src/components/settings/hooks/useSettingsNavigation.ts index 96831c700..ac742399d 100644 --- a/app/src/components/settings/hooks/useSettingsNavigation.ts +++ b/app/src/components/settings/hooks/useSettingsNavigation.ts @@ -23,7 +23,6 @@ export type SettingsRoute = | 'skills' | 'ai' | 'local-model' - | 'tauri-commands' | 'memory-debug' | 'recovery-phrase' | 'webhooks-debug' @@ -81,7 +80,6 @@ export const useSettingsNavigation = (): SettingsNavigationHook => { if (path.includes('/settings/skills')) return 'skills'; if (path.includes('/settings/ai')) return 'ai'; if (path.includes('/settings/local-model')) return 'local-model'; - if (path.includes('/settings/tauri-commands')) return 'tauri-commands'; if (path.includes('/settings/memory-debug')) return 'memory-debug'; if (path.includes('/settings/webhooks-debug')) return 'webhooks-debug'; if (path.includes('/settings/recovery-phrase')) return 'recovery-phrase'; diff --git a/app/src/components/settings/panels/AIPanel.tsx b/app/src/components/settings/panels/AIPanel.tsx index 3501d0ac1..7712dd998 100644 --- a/app/src/components/settings/panels/AIPanel.tsx +++ b/app/src/components/settings/panels/AIPanel.tsx @@ -74,12 +74,12 @@ const AIPanel = () => { }; return ( -
+
-
+
-

AI System Overview

+

AI System Overview

Prompt and markdown orchestration is handled in Rust runtime.

@@ -110,7 +110,7 @@ const AIPanel = () => {
-

Local Model Runtime

+

Local Model Runtime

-

Capability Assets

+

Capability Assets

Quantization preference: {assets?.quantization ?? 'q4'} @@ -883,7 +883,7 @@ const LocalModelPanel = () => {
-

Test Summarization

+

Test Summarization