neoagent 2.4.1-beta.8 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +33 -3
- package/LICENSE +111 -56
- package/README.md +8 -3
- package/docs/configuration.md +8 -0
- package/docs/getting-started.md +9 -3
- package/docs/index.md +4 -0
- package/extensions/chrome-browser/background.mjs +45 -7
- package/extensions/chrome-browser/icons/icon128.png +0 -0
- package/extensions/chrome-browser/icons/icon16.png +0 -0
- package/extensions/chrome-browser/icons/icon48.png +0 -0
- package/extensions/chrome-browser/icons/logo.svg +39 -8
- package/extensions/chrome-browser/manifest.json +3 -2
- package/extensions/chrome-browser/popup.html +5 -1
- package/extensions/chrome-browser/popup.js +15 -2
- package/flutter_app/android/app/src/main/AndroidManifest.xml +2 -1
- package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/flutter_app/assets/branding/app_icon_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_64.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
- package/flutter_app/assets/branding/onboarding_intro.mp4 +0 -0
- package/flutter_app/assets/branding/tray_icon_light_template.png +0 -0
- package/flutter_app/assets/branding/tray_icon_template.png +0 -0
- package/flutter_app/lib/features/location/location_service.dart +3 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +391 -382
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +743 -0
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +18 -16
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +19 -18
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +8 -1
- package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +16 -13
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +17 -13
- package/flutter_app/lib/main.dart +3 -0
- package/flutter_app/lib/main_account_settings.dart +10 -34
- package/flutter_app/lib/main_admin.dart +14 -1
- package/flutter_app/lib/main_app_shell.dart +377 -340
- package/flutter_app/lib/main_chat.dart +707 -227
- package/flutter_app/lib/main_controller.dart +338 -46
- package/flutter_app/lib/main_devices.dart +851 -122
- package/flutter_app/lib/main_integrations.dart +255 -6
- package/flutter_app/lib/main_launcher.dart +1 -1
- package/flutter_app/lib/main_model_picker.dart +685 -0
- package/flutter_app/lib/main_models.dart +212 -0
- package/flutter_app/lib/main_navigation.dart +1 -9
- package/flutter_app/lib/main_operations.dart +1417 -614
- package/flutter_app/lib/main_settings.dart +764 -887
- package/flutter_app/lib/main_shared.dart +971 -443
- package/flutter_app/lib/main_spacing.dart +4 -4
- package/flutter_app/lib/main_theme.dart +22 -14
- package/flutter_app/lib/main_unified.dart +5 -72
- package/flutter_app/lib/src/android_apk_drop_zone.dart +24 -0
- package/flutter_app/lib/src/android_apk_drop_zone_stub.dart +13 -0
- package/flutter_app/lib/src/android_apk_drop_zone_web.dart +219 -0
- package/flutter_app/lib/src/backend_client.dart +79 -0
- package/flutter_app/lib/src/desktop_companion_actions.dart +56 -7
- package/flutter_app/lib/src/desktop_companion_io.dart +77 -1
- package/flutter_app/lib/src/desktop_native_bridge.dart +13 -0
- package/flutter_app/lib/src/security/password_strength.dart +84 -0
- package/flutter_app/lib/src/stream_renderer.dart +205 -35
- package/flutter_app/lib/src/theme/palette.dart +76 -34
- package/flutter_app/linux/runner/resources/app_icon.png +0 -0
- package/flutter_app/macos/Runner/AppDelegate.swift +44 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/flutter_app/pubspec.lock +2 -2
- package/flutter_app/pubspec.yaml +7 -1
- package/flutter_app/tool/branding_source/neoagent-icon-1024.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-128.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-16.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-180.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-192.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-256.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-32.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-48.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-512.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-64.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon.svg +43 -0
- package/flutter_app/tool/generate_desktop_branding.py +154 -152
- package/flutter_app/web/favicon.png +0 -0
- package/flutter_app/web/favicon.svg +40 -9
- package/flutter_app/web/favicon_light.svg +43 -0
- package/flutter_app/web/icons/Icon-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-192.png +0 -0
- package/flutter_app/web/icons/Icon-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-512.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
- package/flutter_app/windows/runner/main.cpp +7 -1
- package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
- package/lib/manager.js +445 -83
- package/package.json +17 -3
- package/runtime/paths.js +3 -1
- package/server/admin/access.js +198 -0
- package/server/admin/admin.css +268 -0
- package/server/admin/admin.js +348 -0
- package/server/admin/analytics.js +128 -0
- package/server/admin/index.html +1015 -0
- package/server/admin/login.html +290 -0
- package/server/admin/logo.svg +43 -0
- package/server/admin/sql.js +134 -0
- package/server/admin/users.js +147 -0
- package/server/config/origins.js +3 -1
- package/server/db/database.js +92 -0
- package/server/db/ftsQuery.js +27 -0
- package/server/http/routes.js +1 -0
- package/server/http/static.js +23 -6
- package/server/index.js +1 -1
- package/server/middleware/adminAuth.js +48 -0
- package/server/middleware/auth.js +1 -40
- package/server/public/.last_build_id +1 -1
- package/server/public/app_icon.png +0 -0
- package/server/public/assets/AssetManifest.bin +1 -1
- package/server/public/assets/AssetManifest.bin.json +1 -1
- package/server/public/assets/assets/branding/app_icon_1024.png +0 -0
- package/server/public/assets/assets/branding/app_icon_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_512.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_1024.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
- package/server/public/assets/assets/branding/onboarding_intro.mp4 +0 -0
- package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
- package/server/public/assets/assets/branding/tray_icon_template.png +0 -0
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/assets/web/icons/Icon-192.png +0 -0
- package/server/public/favicon.png +0 -0
- package/server/public/favicon.svg +40 -9
- package/server/public/favicon_light.svg +43 -0
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/icons/Icon-192-light.png +0 -0
- package/server/public/icons/Icon-192.png +0 -0
- package/server/public/icons/Icon-512-light.png +0 -0
- package/server/public/icons/Icon-512.png +0 -0
- package/server/public/icons/Icon-maskable-192-light.png +0 -0
- package/server/public/icons/Icon-maskable-192.png +0 -0
- package/server/public/icons/Icon-maskable-512-light.png +0 -0
- package/server/public/icons/Icon-maskable-512.png +0 -0
- package/server/public/main.dart.js +88944 -85720
- package/server/routes/admin.js +632 -0
- package/server/routes/agent_profiles.js +3 -0
- package/server/routes/agents.js +1 -1
- package/server/routes/auth.js +3 -1
- package/server/routes/browser.js +14 -0
- package/server/routes/browser_extension.js +21 -4
- package/server/routes/desktop.js +10 -0
- package/server/routes/mcp.js +29 -13
- package/server/routes/memory.js +23 -1
- package/server/routes/messaging.js +2 -0
- package/server/routes/screenHistory.js +14 -8
- package/server/routes/settings.js +14 -2
- package/server/routes/stream.js +12 -3
- package/server/routes/triggers.js +4 -4
- package/server/routes/voice_assistant.js +36 -1
- package/server/routes/workspace.js +86 -0
- package/server/services/account/admin_two_factor.js +132 -0
- package/server/services/account/password_policy.js +6 -1
- package/server/services/ai/completion.js +44 -0
- package/server/services/ai/engine.js +321 -500
- package/server/services/ai/imageAnalysis.js +9 -5
- package/server/services/ai/logFormat.js +46 -0
- package/server/services/ai/loopPolicy.js +11 -0
- package/server/services/ai/messagingFallback.js +228 -0
- package/server/services/ai/models.js +194 -55
- package/server/services/ai/providerRetry.js +169 -0
- package/server/services/ai/providers/anthropic.js +15 -4
- package/server/services/ai/providers/google.js +38 -11
- package/server/services/ai/providers/grok.js +19 -68
- package/server/services/ai/providers/grokOauth.js +141 -0
- package/server/services/ai/providers/nvidia.js +154 -0
- package/server/services/ai/providers/ollama.js +76 -39
- package/server/services/ai/providers/openai.js +20 -31
- package/server/services/ai/providers/openaiCodex.js +6 -2
- package/server/services/ai/providers/openaiCompatible.js +70 -0
- package/server/services/ai/providers/openrouter.js +162 -0
- package/server/services/ai/settings.js +30 -0
- package/server/services/ai/systemPrompt.js +51 -29
- package/server/services/ai/taskAnalysis.js +60 -1
- package/server/services/ai/toolEvidence.js +207 -0
- package/server/services/ai/toolSelector.js +8 -1
- package/server/services/ai/tools.js +80 -15
- package/server/services/android/controller.js +36 -1
- package/server/services/browser/controller.js +18 -0
- package/server/services/browser/extension/manifest.js +33 -0
- package/server/services/browser/extension/provider.js +12 -6
- package/server/services/browser/extension/registry.js +229 -18
- package/server/services/desktop/protocol.js +1 -0
- package/server/services/desktop/provider.js +4 -0
- package/server/services/desktop/registry.js +104 -1
- package/server/services/desktop/screenRecorder.js +208 -98
- package/server/services/desktop/screen_recorder_support.js +46 -0
- package/server/services/integrations/google/provider.js +13 -0
- package/server/services/integrations/home_assistant/constants.js +88 -0
- package/server/services/integrations/home_assistant/network.js +207 -0
- package/server/services/integrations/home_assistant/provider.js +249 -0
- package/server/services/integrations/home_assistant/snapshot.js +98 -0
- package/server/services/integrations/home_assistant/tools.js +101 -0
- package/server/services/integrations/manager.js +5 -0
- package/server/services/integrations/registry.js +2 -0
- package/server/services/integrations/trello/provider.js +8 -2
- package/server/services/manager.js +51 -47
- package/server/services/mcp/client.js +208 -268
- package/server/services/mcp/client_support.js +172 -0
- package/server/services/mcp/recovery.js +116 -0
- package/server/services/mcp/tool_operations.js +123 -0
- package/server/services/memory/ingestion.js +185 -370
- package/server/services/memory/ingestion_coverage.js +129 -0
- package/server/services/memory/ingestion_documents.js +123 -0
- package/server/services/memory/ingestion_support.js +171 -0
- package/server/services/memory/intelligence.js +181 -0
- package/server/services/memory/manager.js +476 -32
- package/server/services/messaging/automation.js +71 -134
- package/server/services/messaging/formatting_guides.js +26 -1
- package/server/services/messaging/inbound_queue.js +111 -0
- package/server/services/messaging/manager.js +25 -8
- package/server/services/messaging/typing_keepalive.js +110 -0
- package/server/services/runtime/manager.js +7 -3
- package/server/services/runtime/settings.js +17 -0
- package/server/services/streaming/android-stream.js +296 -32
- package/server/services/streaming/stream-hub.js +1 -1
- package/server/services/tasks/integration_runtime.js +4 -1
- package/server/services/tasks/runtime.js +415 -56
- package/server/services/tasks/task_repository.js +48 -6
- package/server/services/websocket.js +8 -2
- package/server/services/widgets/service.js +17 -1
- package/server/services/workspace/manager.js +116 -0
- package/server/utils/logger.js +44 -6
- package/server/utils/security.js +3 -0
- package/server/utils/version.js +29 -19
- package/server/services/memory/openhuman_uplift.test.js +0 -98
|
@@ -4,9 +4,9 @@ part of 'main.dart';
|
|
|
4
4
|
// surface palette to create visual contrast during the auth flow. Named here
|
|
5
5
|
// so they can be updated in one place rather than hunted across the widget tree.
|
|
6
6
|
const Color _qrPanelGradientStart = Color(0xFF0A1D2E);
|
|
7
|
-
const Color _qrPanelGradientEnd
|
|
8
|
-
const Color _qrPanelGlowBlue
|
|
9
|
-
const Color _qrPanelGlowGreen
|
|
7
|
+
const Color _qrPanelGradientEnd = Color(0xFF112B43);
|
|
8
|
+
const Color _qrPanelGlowBlue = Color(0xFF6EDBFF);
|
|
9
|
+
const Color _qrPanelGlowGreen = Color(0xFF58E0A2);
|
|
10
10
|
|
|
11
11
|
class SplashView extends StatelessWidget {
|
|
12
12
|
const SplashView({super.key});
|
|
@@ -37,7 +37,7 @@ class SplashView extends StatelessWidget {
|
|
|
37
37
|
),
|
|
38
38
|
),
|
|
39
39
|
const SizedBox(height: 14),
|
|
40
|
-
const Text('Loading
|
|
40
|
+
const Text('Loading NeoAgent'),
|
|
41
41
|
],
|
|
42
42
|
),
|
|
43
43
|
),
|
|
@@ -274,7 +274,7 @@ class _AuthViewState extends State<AuthView> {
|
|
|
274
274
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
275
275
|
children: <Widget>[
|
|
276
276
|
Text(
|
|
277
|
-
'Enter your username or account email.
|
|
277
|
+
'Enter your username or account email. NeoAgent will send a reset link if it can match the account.',
|
|
278
278
|
style: TextStyle(color: _textSecondary, height: 1.45),
|
|
279
279
|
),
|
|
280
280
|
const SizedBox(height: 16),
|
|
@@ -480,7 +480,7 @@ class _AuthViewState extends State<AuthView> {
|
|
|
480
480
|
const SizedBox(height: 8),
|
|
481
481
|
Text(
|
|
482
482
|
awaitingTwoFactor
|
|
483
|
-
? 'Open your authenticator app and enter the current
|
|
483
|
+
? 'Open your authenticator app and enter the current NeoAgent code.'
|
|
484
484
|
: subtitle,
|
|
485
485
|
style: TextStyle(color: _textSecondary, height: 1.5),
|
|
486
486
|
),
|
|
@@ -767,9 +767,9 @@ class _AuthViewState extends State<AuthView> {
|
|
|
767
767
|
crossAxisAlignment: contentAlignment,
|
|
768
768
|
children: <Widget>[
|
|
769
769
|
Text(
|
|
770
|
-
'Scan with
|
|
770
|
+
'Scan with NeoAgent on your phone',
|
|
771
771
|
textAlign: titleAlignment,
|
|
772
|
-
style: GoogleFonts.
|
|
772
|
+
style: GoogleFonts.geist(
|
|
773
773
|
fontSize: titleSize,
|
|
774
774
|
fontWeight: FontWeight.w700,
|
|
775
775
|
letterSpacing: compact ? -0.3 : -0.6,
|
|
@@ -948,9 +948,9 @@ class _AuthViewState extends State<AuthView> {
|
|
|
948
948
|
: 'Sign in';
|
|
949
949
|
final subtitle = _registerMode
|
|
950
950
|
? (controller.hasUser
|
|
951
|
-
? 'Create another
|
|
952
|
-
: 'This account will unlock
|
|
953
|
-
: 'Enter your
|
|
951
|
+
? 'Create another NeoAgent account.'
|
|
952
|
+
: 'This account will unlock NeoAgent on this machine.')
|
|
953
|
+
: 'Enter your NeoAgent account details.';
|
|
954
954
|
final awaitingTwoFactor = controller.isAwaitingTwoFactor;
|
|
955
955
|
final showRegisterToggle =
|
|
956
956
|
controller.registrationOpen && controller.hasUser;
|
|
@@ -982,7 +982,9 @@ class _AuthViewState extends State<AuthView> {
|
|
|
982
982
|
),
|
|
983
983
|
child: Padding(
|
|
984
984
|
padding: EdgeInsets.all(
|
|
985
|
-
viewportConstraints.maxWidth < AppBreakpoints.mobile
|
|
985
|
+
viewportConstraints.maxWidth < AppBreakpoints.mobile
|
|
986
|
+
? 14
|
|
987
|
+
: 24,
|
|
986
988
|
),
|
|
987
989
|
child: Center(
|
|
988
990
|
child: ConstrainedBox(
|
|
@@ -998,10 +1000,22 @@ class _AuthViewState extends State<AuthView> {
|
|
|
998
1000
|
fillColor: _glassFill,
|
|
999
1001
|
child: Padding(
|
|
1000
1002
|
padding: EdgeInsets.fromLTRB(
|
|
1001
|
-
viewportConstraints.maxWidth <
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1003
|
+
viewportConstraints.maxWidth <
|
|
1004
|
+
AppBreakpoints.mobile
|
|
1005
|
+
? 18
|
|
1006
|
+
: 34,
|
|
1007
|
+
viewportConstraints.maxWidth <
|
|
1008
|
+
AppBreakpoints.mobile
|
|
1009
|
+
? 20
|
|
1010
|
+
: 30,
|
|
1011
|
+
viewportConstraints.maxWidth <
|
|
1012
|
+
AppBreakpoints.mobile
|
|
1013
|
+
? 18
|
|
1014
|
+
: 34,
|
|
1015
|
+
viewportConstraints.maxWidth <
|
|
1016
|
+
AppBreakpoints.mobile
|
|
1017
|
+
? 20
|
|
1018
|
+
: 30,
|
|
1005
1019
|
),
|
|
1006
1020
|
child: LayoutBuilder(
|
|
1007
1021
|
builder: (context, panelConstraints) {
|
|
@@ -1188,59 +1202,54 @@ class _HomeViewState extends State<HomeView> {
|
|
|
1188
1202
|
final wide = MediaQuery.sizeOf(context).width >= 1080;
|
|
1189
1203
|
|
|
1190
1204
|
if (wide) {
|
|
1191
|
-
return
|
|
1205
|
+
return _ControlSurfaceBackdrop(
|
|
1192
1206
|
child: Scaffold(
|
|
1193
1207
|
backgroundColor: Colors.transparent,
|
|
1194
|
-
body:
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
opacity: animation,
|
|
1225
|
-
child: SlideTransition(
|
|
1226
|
-
position: offset,
|
|
1227
|
-
child: child,
|
|
1228
|
-
),
|
|
1229
|
-
);
|
|
1230
|
-
},
|
|
1231
|
-
child: KeyedSubtree(
|
|
1232
|
-
key: ValueKey<AppSection>(
|
|
1233
|
-
controller.selectedSection,
|
|
1234
|
-
),
|
|
1235
|
-
child: _SectionBody(controller: controller, devicesPanelKey: _devicesPanelKey),
|
|
1208
|
+
body: Row(
|
|
1209
|
+
children: <Widget>[
|
|
1210
|
+
_Sidebar(
|
|
1211
|
+
controller: controller,
|
|
1212
|
+
expandedGroup: _expandedSidebarGroup,
|
|
1213
|
+
onToggleGroup: _toggleSidebarGroup,
|
|
1214
|
+
),
|
|
1215
|
+
Expanded(
|
|
1216
|
+
child: ClipRect(
|
|
1217
|
+
child: AnimatedSwitcher(
|
|
1218
|
+
duration: const Duration(milliseconds: 320),
|
|
1219
|
+
switchInCurve: Curves.easeOutBack,
|
|
1220
|
+
switchOutCurve: Curves.easeInCubic,
|
|
1221
|
+
transitionBuilder: (child, animation) {
|
|
1222
|
+
final offset = Tween<Offset>(
|
|
1223
|
+
begin: const Offset(0.018, 0.026),
|
|
1224
|
+
end: Offset.zero,
|
|
1225
|
+
).animate(animation);
|
|
1226
|
+
final scale = Tween<double>(
|
|
1227
|
+
begin: 0.992,
|
|
1228
|
+
end: 1,
|
|
1229
|
+
).animate(animation);
|
|
1230
|
+
return ScaleTransition(
|
|
1231
|
+
scale: scale,
|
|
1232
|
+
alignment: Alignment.topCenter,
|
|
1233
|
+
child: FadeTransition(
|
|
1234
|
+
opacity: animation,
|
|
1235
|
+
child: SlideTransition(
|
|
1236
|
+
position: offset,
|
|
1237
|
+
child: child,
|
|
1236
1238
|
),
|
|
1237
1239
|
),
|
|
1240
|
+
);
|
|
1241
|
+
},
|
|
1242
|
+
child: KeyedSubtree(
|
|
1243
|
+
key: ValueKey<AppSection>(controller.selectedSection),
|
|
1244
|
+
child: _SectionBody(
|
|
1245
|
+
controller: controller,
|
|
1246
|
+
devicesPanelKey: _devicesPanelKey,
|
|
1238
1247
|
),
|
|
1239
1248
|
),
|
|
1240
1249
|
),
|
|
1241
|
-
|
|
1250
|
+
),
|
|
1242
1251
|
),
|
|
1243
|
-
|
|
1252
|
+
],
|
|
1244
1253
|
),
|
|
1245
1254
|
),
|
|
1246
1255
|
);
|
|
@@ -1268,21 +1277,38 @@ class _HomeViewState extends State<HomeView> {
|
|
|
1268
1277
|
body: SafeArea(
|
|
1269
1278
|
child: Padding(
|
|
1270
1279
|
padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
|
|
1271
|
-
child:
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1280
|
+
child: Container(
|
|
1281
|
+
decoration: BoxDecoration(
|
|
1282
|
+
color: _bgPrimary,
|
|
1283
|
+
borderRadius: BorderRadius.circular(22),
|
|
1284
|
+
border: Border.all(color: _border),
|
|
1285
|
+
boxShadow: _softPanelShadow,
|
|
1286
|
+
),
|
|
1287
|
+
clipBehavior: Clip.antiAlias,
|
|
1277
1288
|
child: ClipRRect(
|
|
1278
|
-
borderRadius: BorderRadius.circular(
|
|
1289
|
+
borderRadius: BorderRadius.circular(22),
|
|
1279
1290
|
child: AnimatedSwitcher(
|
|
1280
|
-
duration: const Duration(milliseconds:
|
|
1281
|
-
switchInCurve: Curves.
|
|
1291
|
+
duration: const Duration(milliseconds: 280),
|
|
1292
|
+
switchInCurve: Curves.easeOutBack,
|
|
1282
1293
|
switchOutCurve: Curves.easeInCubic,
|
|
1294
|
+
transitionBuilder: (child, animation) {
|
|
1295
|
+
return FadeTransition(
|
|
1296
|
+
opacity: animation,
|
|
1297
|
+
child: SlideTransition(
|
|
1298
|
+
position: Tween<Offset>(
|
|
1299
|
+
begin: const Offset(0, 0.018),
|
|
1300
|
+
end: Offset.zero,
|
|
1301
|
+
).animate(animation),
|
|
1302
|
+
child: child,
|
|
1303
|
+
),
|
|
1304
|
+
);
|
|
1305
|
+
},
|
|
1283
1306
|
child: KeyedSubtree(
|
|
1284
1307
|
key: ValueKey<AppSection>(controller.selectedSection),
|
|
1285
|
-
child: _SectionBody(
|
|
1308
|
+
child: _SectionBody(
|
|
1309
|
+
controller: controller,
|
|
1310
|
+
devicesPanelKey: _devicesPanelKey,
|
|
1311
|
+
),
|
|
1286
1312
|
),
|
|
1287
1313
|
),
|
|
1288
1314
|
),
|
|
@@ -1396,55 +1422,58 @@ class _Sidebar extends StatelessWidget {
|
|
|
1396
1422
|
|
|
1397
1423
|
@override
|
|
1398
1424
|
Widget build(BuildContext context) {
|
|
1399
|
-
return
|
|
1400
|
-
width:
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
fillColor: _bgSecondary.withValues(alpha: 0.34),
|
|
1405
|
-
overlayGradient: LinearGradient(
|
|
1406
|
-
colors: <Color>[
|
|
1407
|
-
_bgSecondary.withValues(alpha: 0.96),
|
|
1408
|
-
_bgTertiary.withValues(alpha: 0.88),
|
|
1409
|
-
],
|
|
1410
|
-
begin: Alignment.topCenter,
|
|
1411
|
-
end: Alignment.bottomCenter,
|
|
1425
|
+
return Container(
|
|
1426
|
+
width: 268,
|
|
1427
|
+
decoration: BoxDecoration(
|
|
1428
|
+
color: _bgSecondary,
|
|
1429
|
+
border: Border(right: BorderSide(color: _border)),
|
|
1412
1430
|
),
|
|
1413
1431
|
child: Column(
|
|
1414
1432
|
children: <Widget>[
|
|
1415
|
-
|
|
1416
|
-
padding: const EdgeInsets.fromLTRB(
|
|
1417
|
-
|
|
1418
|
-
border: Border(bottom: BorderSide(color: _border)),
|
|
1419
|
-
),
|
|
1420
|
-
child: Column(
|
|
1421
|
-
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1433
|
+
Padding(
|
|
1434
|
+
padding: const EdgeInsets.fromLTRB(20, 18, 18, 12),
|
|
1435
|
+
child: Row(
|
|
1422
1436
|
children: <Widget>[
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1437
|
+
const _LogoBadge(size: 38),
|
|
1438
|
+
const SizedBox(width: 11),
|
|
1439
|
+
Expanded(
|
|
1440
|
+
child: Column(
|
|
1441
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1442
|
+
mainAxisSize: MainAxisSize.min,
|
|
1443
|
+
children: <Widget>[
|
|
1444
|
+
Text(
|
|
1445
|
+
'NeoAgent',
|
|
1446
|
+
style: GoogleFonts.geist(
|
|
1447
|
+
fontSize: 17,
|
|
1448
|
+
fontWeight: FontWeight.w600,
|
|
1449
|
+
color: _textPrimary,
|
|
1450
|
+
letterSpacing: -0.3,
|
|
1451
|
+
),
|
|
1432
1452
|
),
|
|
1433
|
-
|
|
1434
|
-
|
|
1453
|
+
const SizedBox(height: 2),
|
|
1454
|
+
Text(
|
|
1455
|
+
'CONTROL SURFACE',
|
|
1456
|
+
style: GoogleFonts.geistMono(
|
|
1457
|
+
fontSize: 9.5,
|
|
1458
|
+
fontWeight: FontWeight.w600,
|
|
1459
|
+
color: _textMuted,
|
|
1460
|
+
letterSpacing: 1.8,
|
|
1461
|
+
),
|
|
1462
|
+
),
|
|
1463
|
+
],
|
|
1464
|
+
),
|
|
1435
1465
|
),
|
|
1436
1466
|
],
|
|
1437
1467
|
),
|
|
1438
1468
|
),
|
|
1439
|
-
if (controller.agentProfiles.isNotEmpty)
|
|
1469
|
+
if (controller.agentProfiles.isNotEmpty)
|
|
1440
1470
|
Padding(
|
|
1441
|
-
padding: const EdgeInsets.fromLTRB(14,
|
|
1471
|
+
padding: const EdgeInsets.fromLTRB(14, 2, 14, 14),
|
|
1442
1472
|
child: _AgentSwitcher(controller: controller),
|
|
1443
1473
|
),
|
|
1444
|
-
],
|
|
1445
1474
|
Expanded(
|
|
1446
1475
|
child: ListView(
|
|
1447
|
-
padding: const EdgeInsets.
|
|
1476
|
+
padding: const EdgeInsets.fromLTRB(12, 0, 12, 8),
|
|
1448
1477
|
children: _buildSidebarItems(
|
|
1449
1478
|
controller,
|
|
1450
1479
|
onSelect: controller.setSelectedSection,
|
|
@@ -1454,40 +1483,42 @@ class _Sidebar extends StatelessWidget {
|
|
|
1454
1483
|
),
|
|
1455
1484
|
),
|
|
1456
1485
|
Container(
|
|
1457
|
-
padding: const EdgeInsets.
|
|
1486
|
+
padding: const EdgeInsets.fromLTRB(16, 12, 12, 14),
|
|
1458
1487
|
decoration: BoxDecoration(
|
|
1459
1488
|
border: Border(top: BorderSide(color: _border)),
|
|
1460
1489
|
),
|
|
1461
|
-
child:
|
|
1490
|
+
child: Row(
|
|
1462
1491
|
children: <Widget>[
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
_ProfileSettingsButton(
|
|
1479
|
-
controller: controller,
|
|
1480
|
-
onTap: () => controller.setSelectedSection(
|
|
1481
|
-
AppSection.accountSettings,
|
|
1482
|
-
),
|
|
1483
|
-
),
|
|
1484
|
-
const SizedBox(width: 8),
|
|
1485
|
-
_SidebarIconButton(
|
|
1486
|
-
tooltip: 'Logout',
|
|
1487
|
-
icon: Icons.logout,
|
|
1488
|
-
onTap: controller.logout,
|
|
1492
|
+
_SidebarAccountAvatar(
|
|
1493
|
+
controller: controller,
|
|
1494
|
+
onTap: () =>
|
|
1495
|
+
controller.setSelectedSection(AppSection.accountSettings),
|
|
1496
|
+
),
|
|
1497
|
+
const SizedBox(width: 10),
|
|
1498
|
+
Expanded(
|
|
1499
|
+
child: Text(
|
|
1500
|
+
controller.accountLabel,
|
|
1501
|
+
maxLines: 1,
|
|
1502
|
+
overflow: TextOverflow.ellipsis,
|
|
1503
|
+
style: GoogleFonts.geist(
|
|
1504
|
+
color: _textSecondary,
|
|
1505
|
+
fontSize: 12.5,
|
|
1506
|
+
fontWeight: FontWeight.w500,
|
|
1489
1507
|
),
|
|
1490
|
-
|
|
1508
|
+
),
|
|
1509
|
+
),
|
|
1510
|
+
const SizedBox(width: 8),
|
|
1511
|
+
_SidebarIconButton(
|
|
1512
|
+
tooltip: 'Settings',
|
|
1513
|
+
icon: Icons.settings_outlined,
|
|
1514
|
+
onTap: () =>
|
|
1515
|
+
controller.setSelectedSection(AppSection.accountSettings),
|
|
1516
|
+
),
|
|
1517
|
+
const SizedBox(width: 2),
|
|
1518
|
+
_SidebarIconButton(
|
|
1519
|
+
tooltip: 'Logout',
|
|
1520
|
+
icon: Icons.logout,
|
|
1521
|
+
onTap: controller.logout,
|
|
1491
1522
|
),
|
|
1492
1523
|
],
|
|
1493
1524
|
),
|
|
@@ -1557,27 +1588,14 @@ class _AgentSwitcherState extends State<_AgentSwitcher> {
|
|
|
1557
1588
|
menuChildren: <Widget>[
|
|
1558
1589
|
SizedBox(
|
|
1559
1590
|
width: 320,
|
|
1560
|
-
child:
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
Colors.white.withValues(alpha: 0.1),
|
|
1567
|
-
_bgSecondary.withValues(alpha: 0.92),
|
|
1568
|
-
_bgPrimary.withValues(alpha: 0.94),
|
|
1569
|
-
],
|
|
1570
|
-
begin: Alignment.topLeft,
|
|
1571
|
-
end: Alignment.bottomRight,
|
|
1591
|
+
child: Container(
|
|
1592
|
+
decoration: BoxDecoration(
|
|
1593
|
+
color: _bgCard,
|
|
1594
|
+
borderRadius: BorderRadius.circular(18),
|
|
1595
|
+
border: Border.all(color: _border),
|
|
1596
|
+
boxShadow: _softPanelShadow,
|
|
1572
1597
|
),
|
|
1573
|
-
|
|
1574
|
-
..._softPanelShadow,
|
|
1575
|
-
BoxShadow(
|
|
1576
|
-
color: Colors.black.withValues(alpha: 0.22),
|
|
1577
|
-
blurRadius: 28,
|
|
1578
|
-
offset: const Offset(0, 16),
|
|
1579
|
-
),
|
|
1580
|
-
],
|
|
1598
|
+
clipBehavior: Clip.antiAlias,
|
|
1581
1599
|
child: Padding(
|
|
1582
1600
|
padding: const EdgeInsets.all(10),
|
|
1583
1601
|
child: Column(
|
|
@@ -1605,106 +1623,96 @@ class _AgentSwitcherState extends State<_AgentSwitcher> {
|
|
|
1605
1623
|
child: Tooltip(
|
|
1606
1624
|
message: 'Switch agent',
|
|
1607
1625
|
child: InkWell(
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1626
|
+
borderRadius: BorderRadius.circular(14),
|
|
1627
|
+
onTap: _toggleMenu,
|
|
1628
|
+
child: AnimatedContainer(
|
|
1629
|
+
duration: const Duration(milliseconds: 180),
|
|
1630
|
+
curve: Curves.easeOutCubic,
|
|
1631
|
+
padding: const EdgeInsets.all(12),
|
|
1632
|
+
decoration: BoxDecoration(
|
|
1633
|
+
borderRadius: BorderRadius.circular(14),
|
|
1634
|
+
color: _bgCard,
|
|
1635
|
+
border: Border.all(
|
|
1636
|
+
color: isMenuOpen
|
|
1637
|
+
? _accent.withValues(alpha: 0.45)
|
|
1638
|
+
: _borderLight,
|
|
1639
|
+
),
|
|
1640
|
+
boxShadow: <BoxShadow>[
|
|
1641
|
+
BoxShadow(
|
|
1642
|
+
color: Colors.black.withValues(alpha: 0.05),
|
|
1643
|
+
blurRadius: 8,
|
|
1644
|
+
offset: const Offset(0, 1),
|
|
1645
|
+
),
|
|
1621
1646
|
],
|
|
1622
|
-
begin: Alignment.topLeft,
|
|
1623
|
-
end: Alignment.bottomRight,
|
|
1624
1647
|
),
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
:
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1651
|
-
mainAxisSize: MainAxisSize.min,
|
|
1652
|
-
children: <Widget>[
|
|
1653
|
-
Row(
|
|
1654
|
-
children: <Widget>[
|
|
1655
|
-
Flexible(
|
|
1656
|
-
child: Text(
|
|
1657
|
-
selectedAgent.displayName,
|
|
1658
|
-
maxLines: 1,
|
|
1659
|
-
overflow: TextOverflow.ellipsis,
|
|
1660
|
-
style: const TextStyle(
|
|
1661
|
-
fontSize: 13.5,
|
|
1662
|
-
fontWeight: FontWeight.w700,
|
|
1663
|
-
letterSpacing: -0.15,
|
|
1648
|
+
child: Row(
|
|
1649
|
+
children: <Widget>[
|
|
1650
|
+
_AgentGlyph(
|
|
1651
|
+
agent: selectedAgent,
|
|
1652
|
+
selected: true,
|
|
1653
|
+
compact: true,
|
|
1654
|
+
),
|
|
1655
|
+
const SizedBox(width: 10),
|
|
1656
|
+
Expanded(
|
|
1657
|
+
child: Column(
|
|
1658
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1659
|
+
mainAxisSize: MainAxisSize.min,
|
|
1660
|
+
children: <Widget>[
|
|
1661
|
+
Row(
|
|
1662
|
+
children: <Widget>[
|
|
1663
|
+
Flexible(
|
|
1664
|
+
child: Text(
|
|
1665
|
+
selectedAgent.displayName,
|
|
1666
|
+
maxLines: 1,
|
|
1667
|
+
overflow: TextOverflow.ellipsis,
|
|
1668
|
+
style: const TextStyle(
|
|
1669
|
+
fontSize: 13.5,
|
|
1670
|
+
fontWeight: FontWeight.w700,
|
|
1671
|
+
letterSpacing: -0.15,
|
|
1672
|
+
),
|
|
1664
1673
|
),
|
|
1665
1674
|
),
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1675
|
+
if (selectedAgent.isDefault) ...<Widget>[
|
|
1676
|
+
const SizedBox(width: 8),
|
|
1677
|
+
_AgentTag(
|
|
1678
|
+
label: 'DEFAULT',
|
|
1679
|
+
color: _accent,
|
|
1680
|
+
foreground: _accentHover,
|
|
1681
|
+
),
|
|
1682
|
+
],
|
|
1674
1683
|
],
|
|
1675
|
-
],
|
|
1676
|
-
),
|
|
1677
|
-
const SizedBox(height: 2),
|
|
1678
|
-
Text(
|
|
1679
|
-
_agentSwitcherSubtitle(selectedAgent),
|
|
1680
|
-
maxLines: 1,
|
|
1681
|
-
overflow: TextOverflow.ellipsis,
|
|
1682
|
-
style: TextStyle(
|
|
1683
|
-
color: _textSecondary,
|
|
1684
|
-
fontSize: 12,
|
|
1685
|
-
fontWeight: FontWeight.w600,
|
|
1686
|
-
height: 1.2,
|
|
1687
1684
|
),
|
|
1688
|
-
|
|
1689
|
-
|
|
1685
|
+
const SizedBox(height: 2),
|
|
1686
|
+
Text(
|
|
1687
|
+
_agentSwitcherSubtitle(selectedAgent),
|
|
1688
|
+
maxLines: 1,
|
|
1689
|
+
overflow: TextOverflow.ellipsis,
|
|
1690
|
+
style: TextStyle(
|
|
1691
|
+
color: _textSecondary,
|
|
1692
|
+
fontSize: 12,
|
|
1693
|
+
fontWeight: FontWeight.w600,
|
|
1694
|
+
height: 1.2,
|
|
1695
|
+
),
|
|
1696
|
+
),
|
|
1697
|
+
],
|
|
1698
|
+
),
|
|
1690
1699
|
),
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1700
|
+
const SizedBox(width: 8),
|
|
1701
|
+
AnimatedRotation(
|
|
1702
|
+
turns: isMenuOpen ? 0.5 : 0,
|
|
1703
|
+
duration: const Duration(milliseconds: 180),
|
|
1704
|
+
curve: Curves.easeOutCubic,
|
|
1705
|
+
child: Icon(
|
|
1706
|
+
Icons.keyboard_arrow_down_rounded,
|
|
1707
|
+
size: 20,
|
|
1708
|
+
color: isMenuOpen ? _accentHover : _textSecondary,
|
|
1709
|
+
),
|
|
1701
1710
|
),
|
|
1702
|
-
|
|
1703
|
-
|
|
1711
|
+
],
|
|
1712
|
+
),
|
|
1704
1713
|
),
|
|
1705
1714
|
),
|
|
1706
1715
|
),
|
|
1707
|
-
),
|
|
1708
1716
|
);
|
|
1709
1717
|
},
|
|
1710
1718
|
);
|
|
@@ -1741,105 +1749,97 @@ class _AgentSwitcherMenuItem extends StatelessWidget {
|
|
|
1741
1749
|
child: Tooltip(
|
|
1742
1750
|
message: agent.displayName,
|
|
1743
1751
|
child: InkWell(
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
begin: Alignment.topLeft,
|
|
1756
|
-
end: Alignment.bottomRight,
|
|
1757
|
-
)
|
|
1758
|
-
: null,
|
|
1759
|
-
color: selected ? null : Colors.white.withValues(alpha: 0.025),
|
|
1760
|
-
border: Border.all(
|
|
1761
|
-
color: selected ? _accent.withValues(alpha: 0.5) : _borderLight,
|
|
1752
|
+
borderRadius: BorderRadius.circular(14),
|
|
1753
|
+
onTap: onTap,
|
|
1754
|
+
child: Ink(
|
|
1755
|
+
decoration: BoxDecoration(
|
|
1756
|
+
borderRadius: BorderRadius.circular(14),
|
|
1757
|
+
color: selected ? _accent.withValues(alpha: 0.10) : _bgSecondary,
|
|
1758
|
+
border: Border.all(
|
|
1759
|
+
color: selected
|
|
1760
|
+
? _accent.withValues(alpha: 0.55)
|
|
1761
|
+
: _borderLight,
|
|
1762
|
+
),
|
|
1762
1763
|
),
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1764
|
+
child: Padding(
|
|
1765
|
+
padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
|
|
1766
|
+
child: Row(
|
|
1767
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1768
|
+
children: <Widget>[
|
|
1769
|
+
_AgentGlyph(agent: agent, selected: selected, compact: true),
|
|
1770
|
+
const SizedBox(width: 12),
|
|
1771
|
+
Expanded(
|
|
1772
|
+
child: Column(
|
|
1773
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1774
|
+
children: <Widget>[
|
|
1775
|
+
Row(
|
|
1776
|
+
children: <Widget>[
|
|
1777
|
+
Expanded(
|
|
1778
|
+
child: Text(
|
|
1779
|
+
agent.displayName,
|
|
1780
|
+
maxLines: 1,
|
|
1781
|
+
overflow: TextOverflow.ellipsis,
|
|
1782
|
+
style: TextStyle(
|
|
1783
|
+
color: _textPrimary,
|
|
1784
|
+
fontSize: 13.5,
|
|
1785
|
+
fontWeight: selected
|
|
1786
|
+
? FontWeight.w700
|
|
1787
|
+
: FontWeight.w600,
|
|
1788
|
+
letterSpacing: -0.1,
|
|
1789
|
+
),
|
|
1789
1790
|
),
|
|
1790
1791
|
),
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1792
|
+
if (agent.isDefault) ...<Widget>[
|
|
1793
|
+
const SizedBox(width: 8),
|
|
1794
|
+
_AgentTag(
|
|
1795
|
+
label: 'DEFAULT',
|
|
1796
|
+
color: _accent,
|
|
1797
|
+
foreground: _accentHover,
|
|
1798
|
+
),
|
|
1799
|
+
],
|
|
1799
1800
|
],
|
|
1800
|
-
],
|
|
1801
|
-
),
|
|
1802
|
-
const SizedBox(height: 4),
|
|
1803
|
-
Text(
|
|
1804
|
-
_agentSwitcherSubtitle(agent),
|
|
1805
|
-
maxLines: 2,
|
|
1806
|
-
overflow: TextOverflow.ellipsis,
|
|
1807
|
-
style: TextStyle(
|
|
1808
|
-
color: _textSecondary,
|
|
1809
|
-
fontSize: 12,
|
|
1810
|
-
height: 1.3,
|
|
1811
|
-
fontWeight: FontWeight.w600,
|
|
1812
1801
|
),
|
|
1813
|
-
|
|
1814
|
-
|
|
1802
|
+
const SizedBox(height: 4),
|
|
1803
|
+
Text(
|
|
1804
|
+
_agentSwitcherSubtitle(agent),
|
|
1805
|
+
maxLines: 2,
|
|
1806
|
+
overflow: TextOverflow.ellipsis,
|
|
1807
|
+
style: TextStyle(
|
|
1808
|
+
color: _textSecondary,
|
|
1809
|
+
fontSize: 12,
|
|
1810
|
+
height: 1.3,
|
|
1811
|
+
fontWeight: FontWeight.w600,
|
|
1812
|
+
),
|
|
1813
|
+
),
|
|
1814
|
+
],
|
|
1815
|
+
),
|
|
1815
1816
|
),
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1817
|
+
const SizedBox(width: 10),
|
|
1818
|
+
AnimatedOpacity(
|
|
1819
|
+
duration: const Duration(milliseconds: 140),
|
|
1820
|
+
opacity: selected ? 1 : 0,
|
|
1821
|
+
child: Container(
|
|
1822
|
+
width: 24,
|
|
1823
|
+
height: 24,
|
|
1824
|
+
decoration: BoxDecoration(
|
|
1825
|
+
shape: BoxShape.circle,
|
|
1826
|
+
color: _accent.withValues(alpha: 0.2),
|
|
1827
|
+
border: Border.all(
|
|
1828
|
+
color: _accent.withValues(alpha: 0.45),
|
|
1829
|
+
),
|
|
1830
|
+
),
|
|
1831
|
+
child: Icon(
|
|
1832
|
+
Icons.check_rounded,
|
|
1833
|
+
size: 15,
|
|
1834
|
+
color: _accentHover,
|
|
1829
1835
|
),
|
|
1830
|
-
),
|
|
1831
|
-
child: Icon(
|
|
1832
|
-
Icons.check_rounded,
|
|
1833
|
-
size: 15,
|
|
1834
|
-
color: _accentHover,
|
|
1835
1836
|
),
|
|
1836
1837
|
),
|
|
1837
|
-
|
|
1838
|
-
|
|
1838
|
+
],
|
|
1839
|
+
),
|
|
1839
1840
|
),
|
|
1840
1841
|
),
|
|
1841
1842
|
),
|
|
1842
|
-
),
|
|
1843
1843
|
),
|
|
1844
1844
|
);
|
|
1845
1845
|
}
|
|
@@ -1860,12 +1860,12 @@ class _AgentGlyph extends StatelessWidget {
|
|
|
1860
1860
|
Widget build(BuildContext context) {
|
|
1861
1861
|
final baseColor = agent.isDefault ? _accent : _accentAlt;
|
|
1862
1862
|
final initials = _agentInitials(agent.displayName);
|
|
1863
|
-
final size = compact ?
|
|
1863
|
+
final size = compact ? 38.0 : 42.0;
|
|
1864
1864
|
return Container(
|
|
1865
1865
|
width: size,
|
|
1866
1866
|
height: size,
|
|
1867
1867
|
decoration: BoxDecoration(
|
|
1868
|
-
|
|
1868
|
+
borderRadius: BorderRadius.circular(compact ? 11 : 12),
|
|
1869
1869
|
gradient: LinearGradient(
|
|
1870
1870
|
colors: <Color>[
|
|
1871
1871
|
baseColor.withValues(alpha: selected ? 0.85 : 0.65),
|
|
@@ -1926,9 +1926,9 @@ class _AgentTag extends StatelessWidget {
|
|
|
1926
1926
|
@override
|
|
1927
1927
|
Widget build(BuildContext context) {
|
|
1928
1928
|
return Container(
|
|
1929
|
-
padding: const EdgeInsets.symmetric(horizontal:
|
|
1929
|
+
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
|
1930
1930
|
decoration: BoxDecoration(
|
|
1931
|
-
borderRadius: BorderRadius.circular(
|
|
1931
|
+
borderRadius: BorderRadius.circular(5),
|
|
1932
1932
|
color: color.withValues(alpha: 0.14),
|
|
1933
1933
|
border: Border.all(color: color.withValues(alpha: 0.3)),
|
|
1934
1934
|
),
|
|
@@ -1936,9 +1936,9 @@ class _AgentTag extends StatelessWidget {
|
|
|
1936
1936
|
label,
|
|
1937
1937
|
style: TextStyle(
|
|
1938
1938
|
color: foreground,
|
|
1939
|
-
fontSize: 9
|
|
1940
|
-
fontWeight: FontWeight.
|
|
1941
|
-
letterSpacing:
|
|
1939
|
+
fontSize: 9,
|
|
1940
|
+
fontWeight: FontWeight.w600,
|
|
1941
|
+
letterSpacing: 1,
|
|
1942
1942
|
),
|
|
1943
1943
|
),
|
|
1944
1944
|
);
|
|
@@ -2021,6 +2021,45 @@ class _ProfileSettingsButton extends StatelessWidget {
|
|
|
2021
2021
|
}
|
|
2022
2022
|
}
|
|
2023
2023
|
|
|
2024
|
+
class _SidebarAccountAvatar extends StatelessWidget {
|
|
2025
|
+
const _SidebarAccountAvatar({required this.controller, required this.onTap});
|
|
2026
|
+
|
|
2027
|
+
final NeoAgentController controller;
|
|
2028
|
+
final VoidCallback onTap;
|
|
2029
|
+
|
|
2030
|
+
@override
|
|
2031
|
+
Widget build(BuildContext context) {
|
|
2032
|
+
final label = controller.accountLabel.trim();
|
|
2033
|
+
final initial = label.isEmpty ? 'N' : label.characters.first.toUpperCase();
|
|
2034
|
+
final active = controller.selectedSection == AppSection.accountSettings;
|
|
2035
|
+
return Tooltip(
|
|
2036
|
+
message: 'Account settings',
|
|
2037
|
+
child: InkWell(
|
|
2038
|
+
borderRadius: BorderRadius.circular(999),
|
|
2039
|
+
onTap: onTap,
|
|
2040
|
+
child: Container(
|
|
2041
|
+
width: 30,
|
|
2042
|
+
height: 30,
|
|
2043
|
+
decoration: BoxDecoration(
|
|
2044
|
+
shape: BoxShape.circle,
|
|
2045
|
+
color: active ? _accentMuted : _bgCard,
|
|
2046
|
+
border: Border.all(color: active ? _accent : _borderLight),
|
|
2047
|
+
),
|
|
2048
|
+
alignment: Alignment.center,
|
|
2049
|
+
child: Text(
|
|
2050
|
+
initial,
|
|
2051
|
+
style: TextStyle(
|
|
2052
|
+
color: active ? _accentHover : _textPrimary,
|
|
2053
|
+
fontWeight: FontWeight.w700,
|
|
2054
|
+
fontSize: 11,
|
|
2055
|
+
),
|
|
2056
|
+
),
|
|
2057
|
+
),
|
|
2058
|
+
),
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2024
2063
|
class _MobileDrawer extends StatelessWidget {
|
|
2025
2064
|
const _MobileDrawer({
|
|
2026
2065
|
required this.controller,
|
|
@@ -2137,8 +2176,6 @@ class _SectionBody extends StatelessWidget {
|
|
|
2137
2176
|
return SettingsWorkspacePanel(controller: controller);
|
|
2138
2177
|
case AppSection.accountSettings:
|
|
2139
2178
|
return SettingsWorkspacePanel(controller: controller);
|
|
2140
|
-
case AppSection.logs:
|
|
2141
|
-
return RunsAndLogsPanel(controller: controller);
|
|
2142
2179
|
case AppSection.skills:
|
|
2143
2180
|
return ToolsPanel(controller: controller);
|
|
2144
2181
|
case AppSection.agents:
|