Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
102 changes: 102 additions & 0 deletions example/lib/custom_strings/custom_strings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright 2025 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:firebase_ai/firebase_ai.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';

import '../firebase_options.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const App());
}

class App extends StatelessWidget {
static const title = 'Example: Google Gemini AI';

const App({super.key});

@override
Widget build(BuildContext context) =>
const MaterialApp(title: title, home: CustomStringsExample());
}

class CustomStringsExample extends StatelessWidget {
static const title = 'Custom Chat Strings';

const CustomStringsExample({super.key});

@override
Widget build(BuildContext context) {
final customStrings = const LlmChatViewStrings(
addAttachment: 'Add',
attachFile: 'Attach File',
takePhoto: 'Take Photo',
stop: '⏹️ Stop',
close: '❌ Close',
cancel: '❌ Cancel',
copyToClipboard: '📋 Copy',
editMessage: '✏️ Edit',
attachImage: '🖼️ Add Image',
recordAudio: '🎤 Record',
submitMessage: '📤 Send',
closeMenu: '❌ Close Menu',

// Message related
typeAMessage: 'Type your message here...',
recording: '🔴 Recording...',
tapToStop: 'Tap to stop',
tapToRecord: 'Tap to record',
releaseToCancel: 'Release to cancel',
slideToCancel: 'Slide to cancel',

submit: 'Submit',
send: 'Send',
delete: '🗑️ Delete',
edit: '✏️ Edit',
copy: '📋 Copy',
share: '↗️ Share',
retry: '🔄 Retry',
yes: '✅ Yes',
no: '❌ No',
clear: '🗑️ Clear',
search: '🔍 Search',

// Messages and errors
messageCopiedToClipboard: '📋 Copied to clipboard!',
editing: '✏️ Editing',
error: '❌ Error',
cancelMessage: 'Cancel',
confirmDelete: 'Confirm Delete',
areYouSureYouWantToDeleteThisMessage:
'Are you sure you want to delete this message?',
errorSendingMessage: '❌ Failed to send message',
errorLoadingMessages: '❌ Failed to load messages',
noMessagesYet: 'No messages yet. Start the conversation!',
tapToRetry: 'Tap to retry',
noResultsFound: 'No results found',
unableToRecordAudio: 'Unable to record audio',
unsupportedImageSource: 'Unsupported image source',
unableToPickImage: 'Unable to pick image',
unableToPickFile: 'Unable to pick file',
unableToPickUrl: 'Unable to process URL',
);

return Scaffold(
appBar: AppBar(title: const Text(App.title)),
body: LlmChatView(
provider: FirebaseProvider(
model: FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.0-flash',
),
),
strings: customStrings,
style: LlmChatViewStyle(strings: customStrings),
),
);
}
}
1 change: 1 addition & 0 deletions lib/flutter_ai_toolkit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export 'src/providers/interface/chat_message.dart';
export 'src/providers/providers.dart';
export 'src/styles/styles.dart';
export 'src/views/llm_chat_view/llm_chat_view.dart';
export 'src/strings/strings.dart';
14 changes: 13 additions & 1 deletion lib/src/chat_view_model/chat_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart';

import '../providers/interface/llm_provider.dart';
import '../strings/llm_chat_view_strings.dart';
import '../styles/llm_chat_view_style.dart';
import '../views/response_builder.dart';

Expand Down Expand Up @@ -35,6 +36,7 @@ class ChatViewModel {
required this.speechToText,
required this.enableAttachments,
required this.enableVoiceNotes,
this.strings = const LlmChatViewStrings(),
});

/// The LLM provider for the chat interface.
Expand Down Expand Up @@ -92,6 +94,12 @@ class ChatViewModel {
/// will be disabled.
final bool enableVoiceNotes;

/// The strings used throughout the chat interface.
///
/// This provides access to all the text strings used in the chat interface,
/// allowing for easy customization and internationalization.
final LlmChatViewStrings strings;

// The following is needed to support the
// ChatViewModelProvider.updateShouldNotify implementation
@override
Expand All @@ -104,8 +112,10 @@ class ChatViewModel {
other.welcomeMessage == welcomeMessage &&
other.responseBuilder == responseBuilder &&
other.messageSender == messageSender &&
other.speechToText == speechToText &&
other.enableAttachments == enableAttachments &&
other.enableVoiceNotes == enableVoiceNotes);
other.enableVoiceNotes == enableVoiceNotes &&
other.strings == strings);

// the following is best practices when overriding operator ==
@override
Expand All @@ -116,7 +126,9 @@ class ChatViewModel {
welcomeMessage,
responseBuilder,
messageSender,
speechToText,
enableAttachments,
enableVoiceNotes,
strings,
);
}
Loading