neoagent 2.3.1-beta.57 → 2.3.1-beta.59
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/flutter_app/lib/features/onboarding/onboarding_chrome.dart +569 -0
- package/flutter_app/lib/features/onboarding/onboarding_messaging_step.dart +125 -230
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +183 -248
- package/flutter_app/lib/features/onboarding/onboarding_shell.dart +3 -5
- package/flutter_app/lib/features/onboarding/onboarding_video_step.dart +140 -107
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +32 -150
- package/flutter_app/lib/main_app_shell.dart +439 -19
- package/flutter_app/lib/main_controller.dart +12 -6
- package/flutter_app/lib/main_devices.dart +204 -109
- package/flutter_app/lib/main_settings.dart +16 -77
- package/flutter_app/lib/main_shared.dart +1 -0
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +75022 -74341
|
@@ -1477,39 +1477,459 @@ class _Sidebar extends StatelessWidget {
|
|
|
1477
1477
|
}
|
|
1478
1478
|
}
|
|
1479
1479
|
|
|
1480
|
-
class _AgentSwitcher extends
|
|
1480
|
+
class _AgentSwitcher extends StatefulWidget {
|
|
1481
1481
|
const _AgentSwitcher({required this.controller, this.onChanged});
|
|
1482
1482
|
|
|
1483
1483
|
final NeoAgentController controller;
|
|
1484
1484
|
final VoidCallback? onChanged;
|
|
1485
1485
|
|
|
1486
|
+
@override
|
|
1487
|
+
State<_AgentSwitcher> createState() => _AgentSwitcherState();
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
class _AgentSwitcherState extends State<_AgentSwitcher> {
|
|
1491
|
+
final MenuController _menuController = MenuController();
|
|
1492
|
+
|
|
1493
|
+
void _toggleMenu() {
|
|
1494
|
+
if (_menuController.isOpen) {
|
|
1495
|
+
_menuController.close();
|
|
1496
|
+
} else {
|
|
1497
|
+
_menuController.open();
|
|
1498
|
+
}
|
|
1499
|
+
setState(() {});
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
Future<void> _selectAgent(String agentId) async {
|
|
1503
|
+
if (widget.controller.selectedAgentId == agentId) {
|
|
1504
|
+
_menuController.close();
|
|
1505
|
+
setState(() {});
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
widget.onChanged?.call();
|
|
1509
|
+
_menuController.close();
|
|
1510
|
+
setState(() {});
|
|
1511
|
+
await widget.controller.switchAgent(agentId);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1486
1514
|
@override
|
|
1487
1515
|
Widget build(BuildContext context) {
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1516
|
+
final controller = widget.controller;
|
|
1517
|
+
final selectedAgent =
|
|
1518
|
+
controller.activeAgent ?? controller.agentProfiles.first;
|
|
1519
|
+
final isMenuOpen = _menuController.isOpen;
|
|
1520
|
+
|
|
1521
|
+
return MenuAnchor(
|
|
1522
|
+
controller: _menuController,
|
|
1523
|
+
style: MenuStyle(
|
|
1524
|
+
backgroundColor: WidgetStateProperty.all(Colors.transparent),
|
|
1525
|
+
surfaceTintColor: WidgetStateProperty.all(Colors.transparent),
|
|
1526
|
+
shadowColor: WidgetStateProperty.all(Colors.transparent),
|
|
1527
|
+
elevation: WidgetStateProperty.all(0),
|
|
1528
|
+
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
|
1529
|
+
shape: WidgetStateProperty.all(
|
|
1530
|
+
RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
|
1531
|
+
),
|
|
1495
1532
|
),
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1533
|
+
crossAxisUnconstrained: false,
|
|
1534
|
+
onOpen: () => setState(() {}),
|
|
1535
|
+
onClose: () => setState(() {}),
|
|
1536
|
+
menuChildren: <Widget>[
|
|
1537
|
+
SizedBox(
|
|
1538
|
+
width: 320,
|
|
1539
|
+
child: _GlassSurface(
|
|
1540
|
+
borderRadius: BorderRadius.circular(24),
|
|
1541
|
+
blurSigma: 28,
|
|
1542
|
+
fillColor: _bgCard.withValues(alpha: 0.9),
|
|
1543
|
+
overlayGradient: LinearGradient(
|
|
1544
|
+
colors: <Color>[
|
|
1545
|
+
Colors.white.withValues(alpha: 0.1),
|
|
1546
|
+
_bgSecondary.withValues(alpha: 0.92),
|
|
1547
|
+
_bgPrimary.withValues(alpha: 0.94),
|
|
1548
|
+
],
|
|
1549
|
+
begin: Alignment.topLeft,
|
|
1550
|
+
end: Alignment.bottomRight,
|
|
1501
1551
|
),
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1552
|
+
boxShadow: <BoxShadow>[
|
|
1553
|
+
..._softPanelShadow,
|
|
1554
|
+
BoxShadow(
|
|
1555
|
+
color: Colors.black.withValues(alpha: 0.22),
|
|
1556
|
+
blurRadius: 28,
|
|
1557
|
+
offset: const Offset(0, 16),
|
|
1558
|
+
),
|
|
1559
|
+
],
|
|
1560
|
+
child: Padding(
|
|
1561
|
+
padding: const EdgeInsets.all(10),
|
|
1562
|
+
child: Column(
|
|
1563
|
+
mainAxisSize: MainAxisSize.min,
|
|
1564
|
+
children: controller.agentProfiles
|
|
1565
|
+
.map(
|
|
1566
|
+
(agent) => Padding(
|
|
1567
|
+
padding: const EdgeInsets.symmetric(vertical: 3),
|
|
1568
|
+
child: _AgentSwitcherMenuItem(
|
|
1569
|
+
agent: agent,
|
|
1570
|
+
selected: agent.id == controller.selectedAgentId,
|
|
1571
|
+
onTap: () => _selectAgent(agent.id),
|
|
1572
|
+
),
|
|
1573
|
+
),
|
|
1574
|
+
)
|
|
1575
|
+
.toList(),
|
|
1576
|
+
),
|
|
1577
|
+
),
|
|
1578
|
+
),
|
|
1579
|
+
),
|
|
1580
|
+
],
|
|
1581
|
+
builder: (context, menuController, child) {
|
|
1582
|
+
return Material(
|
|
1583
|
+
color: Colors.transparent,
|
|
1584
|
+
child: InkWell(
|
|
1585
|
+
borderRadius: BorderRadius.circular(24),
|
|
1586
|
+
onTap: _toggleMenu,
|
|
1587
|
+
child: AnimatedContainer(
|
|
1588
|
+
duration: const Duration(milliseconds: 180),
|
|
1589
|
+
curve: Curves.easeOutCubic,
|
|
1590
|
+
padding: const EdgeInsets.fromLTRB(14, 12, 14, 12),
|
|
1591
|
+
decoration: BoxDecoration(
|
|
1592
|
+
borderRadius: BorderRadius.circular(24),
|
|
1593
|
+
gradient: LinearGradient(
|
|
1594
|
+
colors: <Color>[
|
|
1595
|
+
Colors.white.withValues(alpha: isMenuOpen ? 0.13 : 0.08),
|
|
1596
|
+
_accentMuted.withValues(alpha: isMenuOpen ? 0.24 : 0.14),
|
|
1597
|
+
_bgSecondary.withValues(alpha: isMenuOpen ? 0.92 : 0.84),
|
|
1598
|
+
],
|
|
1599
|
+
begin: Alignment.topLeft,
|
|
1600
|
+
end: Alignment.bottomRight,
|
|
1601
|
+
),
|
|
1602
|
+
border: Border.all(
|
|
1603
|
+
color: isMenuOpen
|
|
1604
|
+
? _accent.withValues(alpha: 0.65)
|
|
1605
|
+
: _borderLight,
|
|
1606
|
+
),
|
|
1607
|
+
boxShadow: isMenuOpen
|
|
1608
|
+
? <BoxShadow>[
|
|
1609
|
+
BoxShadow(
|
|
1610
|
+
color: _accent.withValues(alpha: 0.16),
|
|
1611
|
+
blurRadius: 24,
|
|
1612
|
+
offset: const Offset(0, 10),
|
|
1613
|
+
),
|
|
1614
|
+
]
|
|
1615
|
+
: null,
|
|
1616
|
+
),
|
|
1617
|
+
child: Row(
|
|
1618
|
+
children: <Widget>[
|
|
1619
|
+
_AgentGlyph(
|
|
1620
|
+
agent: selectedAgent,
|
|
1621
|
+
selected: true,
|
|
1622
|
+
compact: false,
|
|
1623
|
+
),
|
|
1624
|
+
const SizedBox(width: 12),
|
|
1625
|
+
Expanded(
|
|
1626
|
+
child: Column(
|
|
1627
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1628
|
+
children: <Widget>[
|
|
1629
|
+
Row(
|
|
1630
|
+
children: <Widget>[
|
|
1631
|
+
Flexible(
|
|
1632
|
+
child: Text(
|
|
1633
|
+
selectedAgent.displayName,
|
|
1634
|
+
maxLines: 1,
|
|
1635
|
+
overflow: TextOverflow.ellipsis,
|
|
1636
|
+
style: const TextStyle(
|
|
1637
|
+
fontSize: 14,
|
|
1638
|
+
fontWeight: FontWeight.w700,
|
|
1639
|
+
letterSpacing: -0.15,
|
|
1640
|
+
),
|
|
1641
|
+
),
|
|
1642
|
+
),
|
|
1643
|
+
if (selectedAgent.isDefault) ...<Widget>[
|
|
1644
|
+
const SizedBox(width: 8),
|
|
1645
|
+
_AgentTag(
|
|
1646
|
+
label: 'DEFAULT',
|
|
1647
|
+
color: _accent,
|
|
1648
|
+
foreground: _accentHover,
|
|
1649
|
+
),
|
|
1650
|
+
],
|
|
1651
|
+
],
|
|
1652
|
+
),
|
|
1653
|
+
const SizedBox(height: 3),
|
|
1654
|
+
Text(
|
|
1655
|
+
_agentSwitcherSubtitle(selectedAgent),
|
|
1656
|
+
maxLines: 1,
|
|
1657
|
+
overflow: TextOverflow.ellipsis,
|
|
1658
|
+
style: TextStyle(
|
|
1659
|
+
color: _textSecondary,
|
|
1660
|
+
fontSize: 11.5,
|
|
1661
|
+
fontWeight: FontWeight.w500,
|
|
1662
|
+
height: 1.2,
|
|
1663
|
+
),
|
|
1664
|
+
),
|
|
1665
|
+
],
|
|
1666
|
+
),
|
|
1667
|
+
),
|
|
1668
|
+
const SizedBox(width: 10),
|
|
1669
|
+
AnimatedRotation(
|
|
1670
|
+
turns: isMenuOpen ? 0.5 : 0,
|
|
1671
|
+
duration: const Duration(milliseconds: 180),
|
|
1672
|
+
curve: Curves.easeOutCubic,
|
|
1673
|
+
child: Icon(
|
|
1674
|
+
Icons.keyboard_arrow_down_rounded,
|
|
1675
|
+
color: isMenuOpen ? _accentHover : _textSecondary,
|
|
1676
|
+
),
|
|
1677
|
+
),
|
|
1678
|
+
],
|
|
1679
|
+
),
|
|
1680
|
+
),
|
|
1681
|
+
),
|
|
1682
|
+
);
|
|
1508
1683
|
},
|
|
1509
1684
|
);
|
|
1510
1685
|
}
|
|
1511
1686
|
}
|
|
1512
1687
|
|
|
1688
|
+
String _agentSwitcherSubtitle(AgentProfile agent) {
|
|
1689
|
+
if (agent.description.trim().isNotEmpty) {
|
|
1690
|
+
return agent.description.trim();
|
|
1691
|
+
}
|
|
1692
|
+
if (agent.responsibilities.trim().isNotEmpty) {
|
|
1693
|
+
return agent.responsibilities.trim();
|
|
1694
|
+
}
|
|
1695
|
+
return agent.canDelegate
|
|
1696
|
+
? 'Can coordinate delegated work'
|
|
1697
|
+
: 'Focused execution profile';
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
class _AgentSwitcherMenuItem extends StatelessWidget {
|
|
1701
|
+
const _AgentSwitcherMenuItem({
|
|
1702
|
+
required this.agent,
|
|
1703
|
+
required this.selected,
|
|
1704
|
+
required this.onTap,
|
|
1705
|
+
});
|
|
1706
|
+
|
|
1707
|
+
final AgentProfile agent;
|
|
1708
|
+
final bool selected;
|
|
1709
|
+
final VoidCallback onTap;
|
|
1710
|
+
|
|
1711
|
+
@override
|
|
1712
|
+
Widget build(BuildContext context) {
|
|
1713
|
+
return Material(
|
|
1714
|
+
color: Colors.transparent,
|
|
1715
|
+
child: InkWell(
|
|
1716
|
+
borderRadius: BorderRadius.circular(18),
|
|
1717
|
+
onTap: onTap,
|
|
1718
|
+
child: Ink(
|
|
1719
|
+
decoration: BoxDecoration(
|
|
1720
|
+
borderRadius: BorderRadius.circular(18),
|
|
1721
|
+
gradient: selected
|
|
1722
|
+
? LinearGradient(
|
|
1723
|
+
colors: <Color>[
|
|
1724
|
+
_accent.withValues(alpha: 0.18),
|
|
1725
|
+
_accentMuted.withValues(alpha: 0.3),
|
|
1726
|
+
],
|
|
1727
|
+
begin: Alignment.topLeft,
|
|
1728
|
+
end: Alignment.bottomRight,
|
|
1729
|
+
)
|
|
1730
|
+
: null,
|
|
1731
|
+
color: selected ? null : Colors.white.withValues(alpha: 0.025),
|
|
1732
|
+
border: Border.all(
|
|
1733
|
+
color: selected ? _accent.withValues(alpha: 0.5) : _borderLight,
|
|
1734
|
+
),
|
|
1735
|
+
),
|
|
1736
|
+
child: Padding(
|
|
1737
|
+
padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
|
|
1738
|
+
child: Row(
|
|
1739
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1740
|
+
children: <Widget>[
|
|
1741
|
+
_AgentGlyph(agent: agent, selected: selected, compact: true),
|
|
1742
|
+
const SizedBox(width: 12),
|
|
1743
|
+
Expanded(
|
|
1744
|
+
child: Column(
|
|
1745
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
1746
|
+
children: <Widget>[
|
|
1747
|
+
Row(
|
|
1748
|
+
children: <Widget>[
|
|
1749
|
+
Expanded(
|
|
1750
|
+
child: Text(
|
|
1751
|
+
agent.displayName,
|
|
1752
|
+
maxLines: 1,
|
|
1753
|
+
overflow: TextOverflow.ellipsis,
|
|
1754
|
+
style: TextStyle(
|
|
1755
|
+
color: _textPrimary,
|
|
1756
|
+
fontSize: 13.5,
|
|
1757
|
+
fontWeight: selected
|
|
1758
|
+
? FontWeight.w700
|
|
1759
|
+
: FontWeight.w600,
|
|
1760
|
+
letterSpacing: -0.1,
|
|
1761
|
+
),
|
|
1762
|
+
),
|
|
1763
|
+
),
|
|
1764
|
+
if (agent.isDefault) ...<Widget>[
|
|
1765
|
+
const SizedBox(width: 8),
|
|
1766
|
+
_AgentTag(
|
|
1767
|
+
label: 'DEFAULT',
|
|
1768
|
+
color: _accent,
|
|
1769
|
+
foreground: _accentHover,
|
|
1770
|
+
),
|
|
1771
|
+
],
|
|
1772
|
+
],
|
|
1773
|
+
),
|
|
1774
|
+
const SizedBox(height: 4),
|
|
1775
|
+
Text(
|
|
1776
|
+
_agentSwitcherSubtitle(agent),
|
|
1777
|
+
maxLines: 2,
|
|
1778
|
+
overflow: TextOverflow.ellipsis,
|
|
1779
|
+
style: TextStyle(
|
|
1780
|
+
color: _textSecondary,
|
|
1781
|
+
fontSize: 11.5,
|
|
1782
|
+
height: 1.3,
|
|
1783
|
+
fontWeight: FontWeight.w500,
|
|
1784
|
+
),
|
|
1785
|
+
),
|
|
1786
|
+
],
|
|
1787
|
+
),
|
|
1788
|
+
),
|
|
1789
|
+
const SizedBox(width: 10),
|
|
1790
|
+
AnimatedOpacity(
|
|
1791
|
+
duration: const Duration(milliseconds: 140),
|
|
1792
|
+
opacity: selected ? 1 : 0,
|
|
1793
|
+
child: Container(
|
|
1794
|
+
width: 24,
|
|
1795
|
+
height: 24,
|
|
1796
|
+
decoration: BoxDecoration(
|
|
1797
|
+
shape: BoxShape.circle,
|
|
1798
|
+
color: _accent.withValues(alpha: 0.2),
|
|
1799
|
+
border: Border.all(
|
|
1800
|
+
color: _accent.withValues(alpha: 0.45),
|
|
1801
|
+
),
|
|
1802
|
+
),
|
|
1803
|
+
child: Icon(
|
|
1804
|
+
Icons.check_rounded,
|
|
1805
|
+
size: 15,
|
|
1806
|
+
color: _accentHover,
|
|
1807
|
+
),
|
|
1808
|
+
),
|
|
1809
|
+
),
|
|
1810
|
+
],
|
|
1811
|
+
),
|
|
1812
|
+
),
|
|
1813
|
+
),
|
|
1814
|
+
),
|
|
1815
|
+
);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
class _AgentGlyph extends StatelessWidget {
|
|
1820
|
+
const _AgentGlyph({
|
|
1821
|
+
required this.agent,
|
|
1822
|
+
required this.selected,
|
|
1823
|
+
required this.compact,
|
|
1824
|
+
});
|
|
1825
|
+
|
|
1826
|
+
final AgentProfile agent;
|
|
1827
|
+
final bool selected;
|
|
1828
|
+
final bool compact;
|
|
1829
|
+
|
|
1830
|
+
@override
|
|
1831
|
+
Widget build(BuildContext context) {
|
|
1832
|
+
final baseColor = agent.isDefault ? _accent : _accentAlt;
|
|
1833
|
+
final initials = _agentInitials(agent.displayName);
|
|
1834
|
+
final size = compact ? 42.0 : 44.0;
|
|
1835
|
+
return Container(
|
|
1836
|
+
width: size,
|
|
1837
|
+
height: size,
|
|
1838
|
+
decoration: BoxDecoration(
|
|
1839
|
+
shape: BoxShape.circle,
|
|
1840
|
+
gradient: LinearGradient(
|
|
1841
|
+
colors: <Color>[
|
|
1842
|
+
baseColor.withValues(alpha: selected ? 0.85 : 0.65),
|
|
1843
|
+
Color.lerp(
|
|
1844
|
+
baseColor,
|
|
1845
|
+
_bgSecondary,
|
|
1846
|
+
0.35,
|
|
1847
|
+
)!.withValues(alpha: selected ? 0.9 : 0.78),
|
|
1848
|
+
],
|
|
1849
|
+
begin: Alignment.topLeft,
|
|
1850
|
+
end: Alignment.bottomRight,
|
|
1851
|
+
),
|
|
1852
|
+
border: Border.all(
|
|
1853
|
+
color: Colors.white.withValues(alpha: selected ? 0.34 : 0.2),
|
|
1854
|
+
),
|
|
1855
|
+
boxShadow: <BoxShadow>[
|
|
1856
|
+
BoxShadow(
|
|
1857
|
+
color: baseColor.withValues(alpha: selected ? 0.22 : 0.12),
|
|
1858
|
+
blurRadius: compact ? 12 : 16,
|
|
1859
|
+
offset: const Offset(0, 6),
|
|
1860
|
+
),
|
|
1861
|
+
],
|
|
1862
|
+
),
|
|
1863
|
+
child: Stack(
|
|
1864
|
+
alignment: Alignment.center,
|
|
1865
|
+
children: <Widget>[
|
|
1866
|
+
Icon(
|
|
1867
|
+
agent.canDelegate ? Icons.hub_rounded : Icons.smart_toy_outlined,
|
|
1868
|
+
size: compact ? 17 : 18,
|
|
1869
|
+
color: Colors.white.withValues(alpha: 0.2),
|
|
1870
|
+
),
|
|
1871
|
+
Text(
|
|
1872
|
+
initials,
|
|
1873
|
+
style: TextStyle(
|
|
1874
|
+
color: Colors.white,
|
|
1875
|
+
fontSize: compact ? 12 : 12.5,
|
|
1876
|
+
fontWeight: FontWeight.w800,
|
|
1877
|
+
letterSpacing: 0.35,
|
|
1878
|
+
),
|
|
1879
|
+
),
|
|
1880
|
+
],
|
|
1881
|
+
),
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
class _AgentTag extends StatelessWidget {
|
|
1887
|
+
const _AgentTag({
|
|
1888
|
+
required this.label,
|
|
1889
|
+
required this.color,
|
|
1890
|
+
required this.foreground,
|
|
1891
|
+
});
|
|
1892
|
+
|
|
1893
|
+
final String label;
|
|
1894
|
+
final Color color;
|
|
1895
|
+
final Color foreground;
|
|
1896
|
+
|
|
1897
|
+
@override
|
|
1898
|
+
Widget build(BuildContext context) {
|
|
1899
|
+
return Container(
|
|
1900
|
+
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 4),
|
|
1901
|
+
decoration: BoxDecoration(
|
|
1902
|
+
borderRadius: BorderRadius.circular(999),
|
|
1903
|
+
color: color.withValues(alpha: 0.14),
|
|
1904
|
+
border: Border.all(color: color.withValues(alpha: 0.3)),
|
|
1905
|
+
),
|
|
1906
|
+
child: Text(
|
|
1907
|
+
label,
|
|
1908
|
+
style: TextStyle(
|
|
1909
|
+
color: foreground,
|
|
1910
|
+
fontSize: 9.5,
|
|
1911
|
+
fontWeight: FontWeight.w800,
|
|
1912
|
+
letterSpacing: 0.6,
|
|
1913
|
+
),
|
|
1914
|
+
),
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
String _agentInitials(String label) {
|
|
1920
|
+
final parts = label
|
|
1921
|
+
.trim()
|
|
1922
|
+
.split(RegExp(r'\s+'))
|
|
1923
|
+
.where((part) => part.isNotEmpty)
|
|
1924
|
+
.toList(growable: false);
|
|
1925
|
+
if (parts.isEmpty) return 'A';
|
|
1926
|
+
if (parts.length == 1) {
|
|
1927
|
+
return parts.first.characters.take(2).toString().toUpperCase();
|
|
1928
|
+
}
|
|
1929
|
+
return (parts.first.characters.first + parts.last.characters.first)
|
|
1930
|
+
.toUpperCase();
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1513
1933
|
class _ProfileSettingsButton extends StatelessWidget {
|
|
1514
1934
|
const _ProfileSettingsButton({required this.controller, required this.onTap});
|
|
1515
1935
|
|
|
@@ -16,7 +16,7 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
16
16
|
_recordingBridge.onRecordingStopped = _handleRecordingStopped;
|
|
17
17
|
_recordingBridge.addListener(_handleRecordingBridgeChanged);
|
|
18
18
|
_desktopCompanion.addListener(notifyListeners);
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
AndroidAutoBridge.instance.onStartVoiceMode = startLiveVoiceCapture;
|
|
21
21
|
AndroidAutoBridge.instance.onStopVoiceMode = interruptLiveVoiceAssistant;
|
|
22
22
|
|
|
@@ -1210,10 +1210,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1210
1210
|
isAwaitingTwoFactor = false;
|
|
1211
1211
|
pendingTwoFactorUsername = '';
|
|
1212
1212
|
password = '';
|
|
1213
|
-
|
|
1214
|
-
final bool backendCompletedOnboarding =
|
|
1213
|
+
|
|
1214
|
+
final bool backendCompletedOnboarding =
|
|
1215
|
+
user?['hasCompletedOnboarding'] == true;
|
|
1215
1216
|
showOnboarding = isRegistration || !backendCompletedOnboarding;
|
|
1216
|
-
|
|
1217
|
+
|
|
1217
1218
|
_clearQrLoginChallenge();
|
|
1218
1219
|
await _persistCredentials();
|
|
1219
1220
|
await refresh();
|
|
@@ -1458,6 +1459,10 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
1458
1459
|
}
|
|
1459
1460
|
}
|
|
1460
1461
|
|
|
1462
|
+
void reopenOnboarding() {
|
|
1463
|
+
showOnboarding = true;
|
|
1464
|
+
notifyListeners();
|
|
1465
|
+
}
|
|
1461
1466
|
|
|
1462
1467
|
void _clearAuthenticatedState() {
|
|
1463
1468
|
_disconnectSocket();
|
|
@@ -3923,10 +3928,11 @@ class NeoAgentController extends ChangeNotifier {
|
|
|
3923
3928
|
if (_isStartingLiveVoice || _isStoppingLiveVoice) {
|
|
3924
3929
|
return;
|
|
3925
3930
|
}
|
|
3926
|
-
|
|
3931
|
+
|
|
3927
3932
|
bool routingStarted = false;
|
|
3928
3933
|
try {
|
|
3929
|
-
routingStarted = await AndroidAutoBridge.instance
|
|
3934
|
+
routingStarted = await AndroidAutoBridge.instance
|
|
3935
|
+
.startTelecomCallRouting();
|
|
3930
3936
|
} catch (_) {
|
|
3931
3937
|
// Swallowed safely
|
|
3932
3938
|
}
|