neoagent 2.4.1-beta.11 → 2.4.1-beta.13

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.
@@ -65,6 +65,7 @@ part 'main_recordings.dart';
65
65
  part 'main_chat.dart';
66
66
  part 'main_account_settings.dart';
67
67
  part 'main_settings.dart';
68
+ part 'main_model_picker.dart';
68
69
  part 'main_operations.dart';
69
70
  part 'main_admin.dart';
70
71
  part 'main_unified.dart';
@@ -706,8 +706,8 @@ class _DevicesPanelState extends State<DevicesPanel> {
706
706
  onAction: _runQuickAction,
707
707
  ),
708
708
  if (kIsWeb) ...<Widget>[
709
- const SizedBox(height: 14),
710
- AndroidApkDropZone(
709
+ const SizedBox(height: 12),
710
+ _AndroidActionsBox(
711
711
  enabled: _androidOnline,
712
712
  busy: _isCurrentSurfaceBusy,
713
713
  onInstall: ({required filename, required bytes}) {
@@ -1264,6 +1264,77 @@ class _AndroidNavDock extends StatelessWidget {
1264
1264
  }
1265
1265
  }
1266
1266
 
1267
+ /// Tiny pill shown in the top-right corner of the preview to indicate no audio.
1268
+ class _MutedBadge extends StatelessWidget {
1269
+ const _MutedBadge();
1270
+
1271
+ @override
1272
+ Widget build(BuildContext context) {
1273
+ return Container(
1274
+ padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 4),
1275
+ decoration: BoxDecoration(
1276
+ color: Colors.black54,
1277
+ borderRadius: BorderRadius.circular(8),
1278
+ ),
1279
+ child: const Icon(Icons.volume_off_rounded, size: 11, color: Colors.white),
1280
+ );
1281
+ }
1282
+ }
1283
+
1284
+ /// Compact expandable actions box shown beneath the Android nav dock.
1285
+ /// Starts with APK install; more actions can be added as tiles.
1286
+ class _AndroidActionsBox extends StatelessWidget {
1287
+ const _AndroidActionsBox({
1288
+ required this.enabled,
1289
+ required this.busy,
1290
+ required this.onInstall,
1291
+ });
1292
+
1293
+ final bool enabled;
1294
+ final bool busy;
1295
+ final AndroidApkInstallCallback onInstall;
1296
+
1297
+ @override
1298
+ Widget build(BuildContext context) {
1299
+ return Container(
1300
+ width: double.infinity,
1301
+ padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
1302
+ decoration: BoxDecoration(
1303
+ color: _bgSecondary,
1304
+ borderRadius: BorderRadius.circular(18),
1305
+ border: Border.all(color: _borderLight),
1306
+ ),
1307
+ child: Column(
1308
+ crossAxisAlignment: CrossAxisAlignment.start,
1309
+ mainAxisSize: MainAxisSize.min,
1310
+ children: <Widget>[
1311
+ Text(
1312
+ 'ACTIONS',
1313
+ style: TextStyle(
1314
+ fontSize: 10,
1315
+ fontWeight: FontWeight.w700,
1316
+ letterSpacing: 0.8,
1317
+ color: _textSecondary,
1318
+ ),
1319
+ ),
1320
+ const SizedBox(height: 8),
1321
+ Wrap(
1322
+ spacing: 8,
1323
+ runSpacing: 8,
1324
+ children: <Widget>[
1325
+ AndroidApkTile(
1326
+ enabled: enabled,
1327
+ busy: busy,
1328
+ onInstall: onInstall,
1329
+ ),
1330
+ ],
1331
+ ),
1332
+ ],
1333
+ ),
1334
+ );
1335
+ }
1336
+ }
1337
+
1267
1338
  class _SurfaceSwitcher extends StatelessWidget {
1268
1339
  const _SurfaceSwitcher({required this.surface, required this.onSelect});
1269
1340
 
@@ -1636,6 +1707,14 @@ class _InteractiveSurfacePreviewState
1636
1707
  ? null
1637
1708
  : (x, y) => widget.onHover?.call(Offset(x, y)),
1638
1709
  ),
1710
+ const Positioned(
1711
+ top: 8,
1712
+ right: 8,
1713
+ child: Opacity(
1714
+ opacity: 0.45,
1715
+ child: _MutedBadge(),
1716
+ ),
1717
+ ),
1639
1718
  Positioned(
1640
1719
  left: 12,
1641
1720
  right: 12,
@@ -1743,6 +1822,14 @@ class _InteractiveSurfacePreviewState
1743
1822
  fit: BoxFit.contain,
1744
1823
  gaplessPlayback: true,
1745
1824
  ),
1825
+ const Positioned(
1826
+ top: 8,
1827
+ right: 8,
1828
+ child: Opacity(
1829
+ opacity: 0.45,
1830
+ child: _MutedBadge(),
1831
+ ),
1832
+ ),
1746
1833
  Positioned(
1747
1834
  left: 12,
1748
1835
  right: 12,