Skip to content

Commit f11ded8

Browse files
committed
Migrate home navigation state to Riverpod
1 parent 8034323 commit f11ded8

3 files changed

Lines changed: 64 additions & 154 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/// Primary destinations for [HomeScreen] bottom navigation.
2+
enum HomeTab {
3+
dashboard,
4+
calendar,
5+
workspace,
6+
chat,
7+
profile;
8+
9+
static HomeTab fromIndex(int index) {
10+
if (index < 0 || index >= HomeTab.values.length) {
11+
return HomeTab.dashboard;
12+
}
13+
return HomeTab.values[index];
14+
}
15+
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'package:flutter_riverpod/flutter_riverpod.dart';
22

3-
/// Bottom navigation index for the home shell ([HomeScreen]).
4-
///
5-
/// 0: Dashboard, 1: Calendar, 2: Workspace, 3: Chat, 4: Profile.
6-
///
7-
/// Not wired to [HomeScreen] yet — foundation for future migration.
8-
final homeTabIndexProvider = StateProvider<int>((ref) => 0);
3+
import 'navigation/models/home_tab.dart';
4+
5+
/// Selected tab for [HomeScreen] bottom navigation.
6+
final homeTabProvider = StateProvider<HomeTab>(
7+
(ref) => HomeTab.dashboard,
8+
);

lib/screens/home/home_screen.dart

Lines changed: 43 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,32 @@
11
import 'package:flutter/material.dart';
2-
import 'package:flutter/services.dart';
3-
import '../../widgets/custom_widgets.dart';
4-
import '../../services/navigation_service.dart';
2+
import 'package:flutter_riverpod/flutter_riverpod.dart';
3+
import '../../providers/navigation/models/home_tab.dart';
4+
import '../../providers/navigation_provider.dart';
55
import '../workspace/workspace_screen.dart';
66
import '../calendar/calendar_screen.dart';
77
import '../profile/profile_screen.dart';
88
import '../chat/chat_screen.dart';
99
import 'dashboard_screen.dart';
1010

11-
class HomeScreen extends StatefulWidget {
11+
class HomeScreen extends ConsumerStatefulWidget {
1212
final Map<String, dynamic>? arguments;
1313

1414
const HomeScreen({super.key, this.arguments});
1515

1616
@override
17-
State<HomeScreen> createState() => _HomeScreenState();
17+
ConsumerState<HomeScreen> createState() => _HomeScreenState();
1818
}
1919

20-
class _HomeScreenState extends State<HomeScreen>
21-
with SingleTickerProviderStateMixin {
22-
final TextEditingController _messageController = TextEditingController();
23-
final ScrollController _scrollController = ScrollController();
24-
final List<ChatMessage> _messages = [];
25-
bool _isListening = false;
26-
int _selectedIndex = 0;
27-
bool _isFabExpanded = false;
28-
late AnimationController _fabController;
29-
late Animation<double> _fabAnimation;
30-
20+
class _HomeScreenState extends ConsumerState<HomeScreen> {
3121
List<Widget> _screens = [];
3222

3323
@override
3424
void initState() {
3525
super.initState();
36-
_fabController = AnimationController(
37-
duration: const Duration(milliseconds: 300),
38-
vsync: this,
39-
);
40-
_fabAnimation = CurvedAnimation(
41-
parent: _fabController,
42-
curve: Curves.easeOut,
43-
reverseCurve: Curves.easeIn,
44-
);
45-
46-
// Initialize screens
4726
_initializeScreens();
4827

49-
// Handle initial arguments if provided
5028
WidgetsBinding.instance.addPostFrameCallback((_) {
51-
if (widget.arguments != null) {
52-
if (widget.arguments!.containsKey('screen') &&
53-
widget.arguments!['screen'] is int) {
54-
setState(() {
55-
_selectedIndex = widget.arguments!['screen'];
56-
});
57-
}
58-
59-
// Handle initial message for chat screen
60-
if (widget.arguments!.containsKey('initial_message') &&
61-
widget.arguments!['initial_message'] is String &&
62-
_selectedIndex == 3) {
63-
// Update the chat screen with the initial message
64-
setState(() {
65-
_screens[3] = ChatScreen(arguments: {
66-
'initial_message': widget.arguments!['initial_message']
67-
});
68-
});
69-
}
70-
}
29+
_applyRouteArguments();
7130
});
7231
}
7332

@@ -81,70 +40,43 @@ class _HomeScreenState extends State<HomeScreen>
8140
];
8241
}
8342

84-
@override
85-
void dispose() {
86-
_messageController.dispose();
87-
_scrollController.dispose();
88-
_fabController.dispose();
89-
super.dispose();
43+
void _applyRouteArguments() {
44+
final args = widget.arguments;
45+
if (args == null) return;
46+
47+
if (args.containsKey('screen') && args['screen'] is int) {
48+
ref.read(homeTabProvider.notifier).state =
49+
HomeTab.fromIndex(args['screen'] as int);
50+
}
51+
52+
if (args.containsKey('initial_message') &&
53+
args['initial_message'] is String &&
54+
ref.read(homeTabProvider) == HomeTab.chat) {
55+
setState(() {
56+
_screens[HomeTab.chat.index] = ChatScreen(arguments: {
57+
'initial_message': args['initial_message'],
58+
});
59+
});
60+
}
9061
}
9162

92-
void _sendMessage() {
93-
if (_messageController.text.trim().isEmpty) return;
94-
95-
setState(() {
96-
_messages.add(
97-
ChatMessage(
98-
text: _messageController.text,
99-
isUser: true,
100-
timestamp: DateTime.now(),
101-
),
102-
);
103-
_messageController.clear();
104-
});
105-
106-
_scrollToBottom();
107-
// TODO: Implement AI response
108-
}
109-
110-
void _scrollToBottom() {
111-
WidgetsBinding.instance.addPostFrameCallback((_) {
112-
if (_scrollController.hasClients) {
113-
_scrollController.animateTo(
114-
_scrollController.position.maxScrollExtent,
115-
duration: const Duration(milliseconds: 300),
116-
curve: Curves.easeOut,
117-
);
118-
}
119-
});
120-
}
121-
122-
void _toggleListening() {
123-
setState(() {
124-
_isListening = !_isListening;
125-
});
126-
// TODO: Implement voice recognition
127-
}
128-
129-
void _toggleFab() {
130-
setState(() {
131-
_isFabExpanded = !_isFabExpanded;
132-
if (_isFabExpanded) {
133-
_fabController.forward();
134-
} else {
135-
_fabController.reverse();
136-
}
137-
});
63+
void _selectTab(int index) {
64+
ref.read(homeTabProvider.notifier).state = HomeTab.fromIndex(index);
13865
}
13966

14067
@override
14168
Widget build(BuildContext context) {
14269
final theme = Theme.of(context);
70+
final selectedTab = ref.watch(homeTabProvider);
71+
14372
return Scaffold(
144-
body: IndexedStack(index: _selectedIndex, children: _screens),
73+
body: IndexedStack(
74+
index: selectedTab.index,
75+
children: _screens,
76+
),
14577
bottomNavigationBar: BottomNavigationBar(
146-
currentIndex: _selectedIndex,
147-
onTap: (index) => setState(() => _selectedIndex = index),
78+
currentIndex: selectedTab.index,
79+
onTap: _selectTab,
14880
type: BottomNavigationBarType.fixed,
14981
selectedItemColor: theme.colorScheme.primary,
15082
unselectedItemColor: theme.colorScheme.onSurfaceVariant,
@@ -157,57 +89,20 @@ class _HomeScreenState extends State<HomeScreen>
15789
icon: Icon(Icons.calendar_today),
15890
label: 'Calendar',
15991
),
160-
BottomNavigationBarItem(icon: Icon(Icons.work), label: 'Workspace'),
92+
BottomNavigationBarItem(
93+
icon: Icon(Icons.work),
94+
label: 'Workspace',
95+
),
16196
BottomNavigationBarItem(
16297
icon: Icon(Icons.chat_bubble_outline),
16398
label: 'Chat',
16499
),
165-
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
166-
],
167-
),
168-
);
169-
}
170-
}
171-
172-
class _ChatBubble extends StatelessWidget {
173-
final ChatMessage message;
174-
175-
const _ChatBubble({required this.message});
176-
177-
@override
178-
Widget build(BuildContext context) {
179-
return Align(
180-
alignment: message.isUser ? Alignment.centerRight : Alignment.centerLeft,
181-
child: Container(
182-
margin: const EdgeInsets.symmetric(vertical: 4),
183-
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
184-
decoration: BoxDecoration(
185-
color: message.isUser
186-
? Colors.green.shade400
187-
: Theme.of(context).colorScheme.surfaceContainerHighest,
188-
borderRadius: BorderRadius.circular(20),
189-
),
190-
child: Text(
191-
message.text,
192-
style: TextStyle(
193-
color: message.isUser
194-
? Colors.white
195-
: Theme.of(context).colorScheme.onSurface,
100+
BottomNavigationBarItem(
101+
icon: Icon(Icons.person),
102+
label: 'Profile',
196103
),
197-
),
104+
],
198105
),
199106
);
200107
}
201108
}
202-
203-
class ChatMessage {
204-
final String text;
205-
final bool isUser;
206-
final DateTime timestamp;
207-
208-
ChatMessage({
209-
required this.text,
210-
required this.isUser,
211-
required this.timestamp,
212-
});
213-
}

0 commit comments

Comments
 (0)