Skip to content

Commit 186efe1

Browse files
Update colorist for Riverpod 3 (#2347)
## Pre-launch Checklist - [x] I read the [Effective Dart: Style] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-devrel channel on [Discord]. <!-- Links --> [Effective Dart: Style]: https://dart.dev/guides/language/effective-dart/style [CLA]: https://cla.developers.google.com/ [Discord]: https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md
1 parent 7a9de29 commit 186efe1

File tree

70 files changed

+2041
-1269
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2041
-1269
lines changed

colorist/codelab_rebuild.yaml

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ steps:
1717
replace-contents: |
1818
include: ../../analysis_options.yaml
1919
20-
# analyzer:
21-
# plugins:
22-
# - custom_lint
20+
analyzer:
21+
plugins:
22+
- custom_lint
2323
2424
linter:
2525
rules:
@@ -96,8 +96,8 @@ steps:
9696
9797
// A fake LLM that just echoes back what it receives.
9898
void sendMessage(String message, WidgetRef ref) {
99-
final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
100-
final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
99+
final chatStateNotifier = ref.read(chatStateProvider.notifier);
100+
final logStateNotifier = ref.read(logStateProvider.notifier);
101101
102102
chatStateNotifier.addUserMessage(message);
103103
logStateNotifier.logUserText(message);
@@ -167,18 +167,17 @@ steps:
167167
168168
import 'package:firebase_ai/firebase_ai.dart';
169169
import 'package:firebase_core/firebase_core.dart';
170-
import 'package:flutter_riverpod/flutter_riverpod.dart';
171170
import 'package:riverpod_annotation/riverpod_annotation.dart';
172171
173172
import '../firebase_options.dart';
174173
175174
part 'gemini.g.dart';
176175
177-
@riverpod
176+
@Riverpod(keepAlive: true)
178177
Future<FirebaseApp> firebaseApp(Ref ref) =>
179178
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
180179
181-
@riverpod
180+
@Riverpod(keepAlive: true)
182181
Future<GenerativeModel> geminiModel(Ref ref) async {
183182
await ref.watch(firebaseAppProvider.future);
184183
@@ -207,7 +206,6 @@ steps:
207206
208207
import 'package:colorist_ui/colorist_ui.dart';
209208
import 'package:firebase_ai/firebase_ai.dart';
210-
import 'package:flutter_riverpod/flutter_riverpod.dart';
211209
import 'package:riverpod_annotation/riverpod_annotation.dart';
212210
213211
import '../providers/gemini.dart';
@@ -220,8 +218,8 @@ steps:
220218
221219
Future<void> sendMessage(String message) async {
222220
final chatSession = await ref.read(chatSessionProvider.future);
223-
final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
224-
final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
221+
final chatStateNotifier = ref.read(chatStateProvider.notifier);
222+
final logStateNotifier = ref.read(logStateProvider.notifier);
225223
226224
chatStateNotifier.addUserMessage(message);
227225
logStateNotifier.logUserText(message);
@@ -247,7 +245,7 @@ steps:
247245
}
248246
}
249247
250-
@riverpod
248+
@Riverpod(keepAlive: true)
251249
GeminiChatService geminiChatService(Ref ref) => GeminiChatService(ref);
252250
- name: Run build_runner
253251
path: colorist
@@ -298,8 +296,8 @@ steps:
298296
-
299297
- // A fake LLM that just echoes back what it receives.
300298
- void sendMessage(String message, WidgetRef ref) {
301-
- final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
302-
- final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
299+
- final chatStateNotifier = ref.read(chatStateProvider.notifier);
300+
- final logStateNotifier = ref.read(logStateProvider.notifier);
303301
-
304302
- chatStateNotifier.addUserMessage(message);
305303
- logStateNotifier.logUserText(message);
@@ -446,29 +444,28 @@ steps:
446444
// found in the LICENSE file.
447445
448446
import 'package:flutter/services.dart';
449-
import 'package:flutter_riverpod/flutter_riverpod.dart';
450447
import 'package:riverpod_annotation/riverpod_annotation.dart';
451448
452449
part 'system_prompt.g.dart';
453450
454-
@riverpod
451+
@Riverpod(keepAlive: true)
455452
Future<String> systemPrompt(Ref ref) =>
456453
rootBundle.loadString('assets/system_prompt.md');
457454
- name: Patch lib/providers/gemini.dart
458455
path: colorist/lib/providers/gemini.dart
459456
patch-u: |
460-
--- a/colorist/step_03/lib/providers/gemini.dart
461-
+++ b/colorist/step_03/lib/providers/gemini.dart
462-
@@ -10,6 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
457+
--- b/colorist/step_03/lib/providers/gemini.dart
458+
+++ a/colorist/step_03/lib/providers/gemini.dart
459+
@@ -9,6 +9,7 @@ import 'package:firebase_core/firebase_core.dart';
463460
import 'package:riverpod_annotation/riverpod_annotation.dart';
464461
465462
import '../firebase_options.dart';
466463
+import 'system_prompt.dart';
467464
468465
part 'gemini.g.dart';
469466
470-
@@ -20,9 +21,11 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
471-
@riverpod
467+
@@ -19,9 +20,11 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
468+
@Riverpod(keepAlive: true)
472469
Future<GenerativeModel> geminiModel(Ref ref) async {
473470
await ref.watch(firebaseAppProvider.future);
474471
+ final systemPrompt = await ref.watch(systemPromptProvider.future);
@@ -505,7 +502,6 @@ steps:
505502
// found in the LICENSE file.
506503
507504
import 'package:firebase_ai/firebase_ai.dart';
508-
import 'package:flutter_riverpod/flutter_riverpod.dart';
509505
import 'package:riverpod_annotation/riverpod_annotation.dart';
510506
511507
part 'gemini_tools.g.dart';
@@ -530,22 +526,22 @@ steps:
530526
];
531527
}
532528
533-
@riverpod
529+
@Riverpod(keepAlive: true)
534530
GeminiTools geminiTools(Ref ref) => GeminiTools(ref);
535531
- name: Patch lib/providers/gemini.dart
536532
path: colorist/lib/providers/gemini.dart
537533
patch-u: |
538-
--- a/colorist/step_04/lib/providers/gemini.dart
539-
+++ b/colorist/step_04/lib/providers/gemini.dart
540-
@@ -10,6 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
534+
--- b/colorist/step_04/lib/providers/gemini.dart
535+
+++ a/colorist/step_04/lib/providers/gemini.dart
536+
@@ -9,6 +9,7 @@ import 'package:firebase_core/firebase_core.dart';
541537
import 'package:riverpod_annotation/riverpod_annotation.dart';
542538
543539
import '../firebase_options.dart';
544540
+import '../services/gemini_tools.dart';
545541
import 'system_prompt.dart';
546542
547543
part 'gemini.g.dart';
548-
@@ -22,10 +23,12 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
544+
@@ -21,10 +22,12 @@ Future<FirebaseApp> firebaseApp(Ref ref) =>
549545
Future<GenerativeModel> geminiModel(Ref ref) async {
550546
await ref.watch(firebaseAppProvider.future);
551547
final systemPrompt = await ref.watch(systemPromptProvider.future);
@@ -634,15 +630,15 @@ steps:
634630
patch-u: |
635631
--- b/colorist/step_05/lib/services/gemini_chat_service.dart
636632
+++ a/colorist/step_05/lib/services/gemini_chat_service.dart
637-
@@ -10,6 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
633+
@@ -9,6 +9,7 @@ import 'package:firebase_ai/firebase_ai.dart';
638634
import 'package:riverpod_annotation/riverpod_annotation.dart';
639635
640636
import '../providers/gemini.dart';
641637
+import 'gemini_tools.dart';
642638
643639
part 'gemini_chat_service.g.dart';
644640
645-
@@ -33,6 +34,27 @@ class GeminiChatService {
641+
@@ -32,6 +33,27 @@ class GeminiChatService {
646642
logStateNotifier.logLlmText(responseText);
647643
chatStateNotifier.appendToMessage(llmMessage.id, responseText);
648644
}
@@ -681,9 +677,9 @@ steps:
681677
682678
+import 'package:colorist_ui/colorist_ui.dart';
683679
import 'package:firebase_ai/firebase_ai.dart';
684-
import 'package:flutter_riverpod/flutter_riverpod.dart';
685680
import 'package:riverpod_annotation/riverpod_annotation.dart';
686-
@@ -26,6 +27,44 @@ class GeminiTools {
681+
682+
@@ -25,6 +26,44 @@ class GeminiTools {
687683
List<Tool> get tools => [
688684
Tool.functionDeclarations([setColorFuncDecl]),
689685
];
@@ -692,7 +688,7 @@ steps:
692688
+ String functionName,
693689
+ Map<String, Object?> arguments,
694690
+ ) {
695-
+ final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
691+
+ final logStateNotifier = ref.read(logStateProvider.notifier);
696692
+ logStateNotifier.logFunctionCall(functionName, arguments);
697693
+ return switch (functionName) {
698694
+ 'set_color' => handleSetColor(arguments),
@@ -701,7 +697,7 @@ steps:
701697
+ }
702698
+
703699
+ Map<String, Object?> handleSetColor(Map<String, Object?> arguments) {
704-
+ final colorStateNotifier = ref.read(colorStateNotifierProvider.notifier);
700+
+ final colorStateNotifier = ref.read(colorStateProvider.notifier);
705701
+ final red = (arguments['red'] as num).toDouble();
706702
+ final green = (arguments['green'] as num).toDouble();
707703
+ final blue = (arguments['blue'] as num).toDouble();
@@ -712,13 +708,13 @@ steps:
712708
+ .toLLMContextMap(),
713709
+ };
714710
+
715-
+ final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
711+
+ final logStateNotifier = ref.read(logStateProvider.notifier);
716712
+ logStateNotifier.logFunctionResults(functionResults);
717713
+ return functionResults;
718714
+ }
719715
+
720716
+ Map<String, Object?> handleUnknownFunction(String functionName) {
721-
+ final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
717+
+ final logStateNotifier = ref.read(logStateProvider.notifier);
722718
+ logStateNotifier.logWarning('Unsupported function call $functionName');
723719
+ return {
724720
+ 'success': false,
@@ -727,7 +723,7 @@ steps:
727723
+ }
728724
}
729725
730-
@riverpod
726+
@Riverpod(keepAlive: true)
731727
- name: Run build_runner
732728
path: colorist
733729
dart: run build_runner build --delete-conflicting-outputs
@@ -751,13 +747,35 @@ steps:
751747
patch-u: |
752748
--- b/colorist/step_06/lib/services/gemini_chat_service.dart
753749
+++ a/colorist/step_06/lib/services/gemini_chat_service.dart
754-
@@ -14,46 +14,41 @@ import 'gemini_tools.dart';
750+
@@ -6,6 +6,7 @@ import 'dart:async';
751+
752+
import 'package:colorist_ui/colorist_ui.dart';
753+
import 'package:firebase_ai/firebase_ai.dart';
754+
+import 'package:flutter_riverpod/flutter_riverpod.dart';
755+
import 'package:riverpod_annotation/riverpod_annotation.dart';
756+
757+
import '../providers/gemini.dart';
758+
@@ -13,46 +14,55 @@ import 'gemini_tools.dart';
755759
756760
part 'gemini_chat_service.g.dart';
757-
758-
+final conversationStateProvider = StateProvider(
759-
+ (ref) => ConversationState.idle,
760-
+);
761+
762+
+class ConversationStateNotifier extends Notifier<ConversationState> {
763+
+ @override
764+
+ ConversationState build() => ConversationState.idle;
765+
+
766+
+ void busy() {
767+
+ state = ConversationState.busy;
768+
+ }
769+
+
770+
+ void idle() {
771+
+ state = ConversationState.idle;
772+
+ }
773+
+}
774+
+
775+
+final conversationStateProvider =
776+
+ NotifierProvider<ConversationStateNotifier, ConversationState>(
777+
+ ConversationStateNotifier.new,
778+
+ );
761779
+
762780
class GeminiChatService {
763781
GeminiChatService(this.ref);
@@ -766,8 +784,8 @@ steps:
766784
Future<void> sendMessage(String message) async {
767785
final chatSession = await ref.read(chatSessionProvider.future);
768786
+ final conversationState = ref.read(conversationStateProvider);
769-
final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
770-
final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
787+
final chatStateNotifier = ref.read(chatStateProvider.notifier);
788+
final logStateNotifier = ref.read(logStateProvider.notifier);
771789
772790
+ if (conversationState == ConversationState.busy) {
773791
+ logStateNotifier.logWarning(
@@ -780,7 +798,7 @@ steps:
780798
+ final conversationStateNotifier = ref.read(
781799
+ conversationStateProvider.notifier,
782800
+ );
783-
+ conversationStateNotifier.state = ConversationState.busy;
801+
+ conversationStateNotifier.busy();
784802
chatStateNotifier.addUserMessage(message);
785803
logStateNotifier.logUserText(message);
786804
final llmMessage = chatStateNotifier.createLlmMessage();
@@ -820,11 +838,11 @@ steps:
820838
}
821839
} catch (e, st) {
822840
logStateNotifier.logError(e, st: st);
823-
@@ -64,6 +59,45 @@ class GeminiChatService {
841+
@@ -63,6 +73,44 @@ class GeminiChatService {
824842
);
825843
} finally {
826844
chatStateNotifier.finalizeMessage(llmMessage.id);
827-
+ conversationStateNotifier.state = ConversationState.idle;
845+
+ conversationStateNotifier.idle();
828846
+ }
829847
+ }
830848
+
@@ -833,10 +851,9 @@ steps:
833851
+ String llmMessageId,
834852
+ ) async {
835853
+ final chatSession = await ref.read(chatSessionProvider.future);
836-
+ final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
837-
+ final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
854+
+ final chatStateNotifier = ref.read(chatStateProvider.notifier);
855+
+ final logStateNotifier = ref.read(logStateProvider.notifier);
838856
+ final blockText = block.text;
839-
+
840857
+ if (blockText != null) {
841858
+ logStateNotifier.logLlmText(blockText);
842859
+ chatStateNotifier.appendToMessage(llmMessageId, blockText);
@@ -900,6 +917,7 @@ steps:
900917
- name: Flutter clean
901918
path: step_06
902919
flutter: clean
920+
903921
- name: step_07
904922
steps:
905923
- name: Remove generated code
@@ -917,7 +935,7 @@ steps:
917935
918936
import 'package:colorist_ui/colorist_ui.dart';
919937
import 'package:firebase_ai/firebase_ai.dart';
920-
@@ -22,6 +23,10 @@ class GeminiChatService {
938+
@@ -36,6 +37,10 @@ class GeminiChatService {
921939
GeminiChatService(this.ref);
922940
final Ref ref;
923941
@@ -994,5 +1012,6 @@ steps:
9941012
- name: Flutter clean
9951013
path: step_07
9961014
flutter: clean
1015+
9971016
- name: Cleanup
9981017
rmdir: colorist

colorist/step_01/analysis_options.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
include: ../../analysis_options.yaml
22

3-
# analyzer:
4-
# plugins:
5-
# - custom_lint
3+
analyzer:
4+
plugins:
5+
- custom_lint
66

77
linter:
88
rules:

colorist/step_01/lib/main.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class MainApp extends ConsumerWidget {
2929

3030
// A fake LLM that just echoes back what it receives.
3131
void sendMessage(String message, WidgetRef ref) {
32-
final chatStateNotifier = ref.read(chatStateNotifierProvider.notifier);
33-
final logStateNotifier = ref.read(logStateNotifierProvider.notifier);
32+
final chatStateNotifier = ref.read(chatStateProvider.notifier);
33+
final logStateNotifier = ref.read(logStateProvider.notifier);
3434

3535
chatStateNotifier.addUserMessage(message);
3636
logStateNotifier.logUserText(message);

colorist/step_01/pubspec.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,24 @@ publish_to: 'none'
44
version: 0.1.0
55

66
environment:
7-
sdk: ^3.9.0
7+
sdk: ^3.9.2
88

99
dependencies:
1010
flutter:
1111
sdk: flutter
12-
colorist_ui: ^0.2.5
13-
flutter_riverpod: ^2.6.1
14-
riverpod_annotation: ^2.6.1
12+
colorist_ui: ^0.3.0
13+
flutter_riverpod: ^3.0.0
14+
riverpod_annotation: ^3.0.0
1515

1616
dev_dependencies:
1717
flutter_test:
1818
sdk: flutter
1919
flutter_lints: ^6.0.0
20-
build_runner: ^2.5.4
21-
riverpod_generator: ^2.6.5
22-
riverpod_lint: ^2.6.5
23-
json_serializable: ^6.9.5
24-
custom_lint: ^0.7.6
20+
build_runner: ^2.7.1
21+
riverpod_generator: ^3.0.0
22+
riverpod_lint: ^3.0.0
23+
json_serializable: ^6.11.1
24+
custom_lint: ^0.8.0
2525

2626
flutter:
2727
uses-material-design: true

0 commit comments

Comments
 (0)