Skip to content

Commit 95647f9

Browse files
committed
feat: finishing up
1 parent 436a29b commit 95647f9

36 files changed

+988
-1050
lines changed

.env.example

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEMINI_AI_TOKEN=

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@ app.*.map.json
4343
/android/app/release
4444

4545
# FVM Version Cache
46-
.fvm/
46+
.fvm/
47+
48+
# .env file
49+
.env

README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
# Flutter + Riverpod Boilerplate
1+
# Gemini Chat
22

3-
A flutter app that showing how to use Riverpod state management within Flutter App.
3+
A flutter app that showing the usage of `flutter_gemini`, built with Riverpod.
44

55
## Notes
66

77
While you developing, make sure you run :
88

9-
`dart run build_runner watch`
10-
11-
to automatically build the freezed class from model.
9+
1. Head to the [Google AI](https://ai.google.dev/) and get the API key.
10+
2. Copy the .env.example to .env and paste the key to `GEMINI_AI_TOKEN`
11+
3. Run `dart run build_runner watch` in terminal to automatically build the freezed class from model.
12+
4. Run the app

android/app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ if (flutterVersionName == null) {
2323
}
2424

2525
android {
26-
namespace "xyz.radenadri.flutter_boilerplate"
26+
namespace "xyz.radenadri.gemini_chat"
2727
compileSdk flutter.compileSdkVersion
2828
ndkVersion flutter.ndkVersion
2929

@@ -42,7 +42,7 @@ android {
4242

4343
defaultConfig {
4444
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45-
applicationId "xyz.radenadri.flutter_boilerplate"
45+
applicationId "xyz.radenadri.gemini_chat"
4646
// You can update the following values to match your application needs.
4747
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
4848
minSdkVersion flutter.minSdkVersion

android/app/src/main/AndroidManifest.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
<application
44
android:label="Boilerplate"
55
android:name="${applicationName}"
6-
android:icon="@mipmap/ic_launcher">
6+
android:icon="@mipmap/ic_launcher"
7+
android:requestLegacyExternalStorage="true">
78
<activity
89
android:name=".MainActivity"
910
android:exported="true"

android/app/src/main/kotlin/xyz/radenadri/flutter_boilerplate/MainActivity.kt android/app/src/main/kotlin/xyz/radenadri/gemini_chat/MainActivity.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package xyz.radenadri.flutter_boilerplate
1+
package xyz.radenadri.gemini_chat
22

33
import io.flutter.embedding.android.FlutterActivity
44

ios/Podfile.lock

+6
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
PODS:
22
- Flutter (1.0.0)
3+
- image_picker_ios (0.0.1):
4+
- Flutter
35
- shared_preferences_foundation (0.0.1):
46
- Flutter
57
- FlutterMacOS
68

79
DEPENDENCIES:
810
- Flutter (from `Flutter`)
11+
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
912
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
1013

1114
EXTERNAL SOURCES:
1215
Flutter:
1316
:path: Flutter
17+
image_picker_ios:
18+
:path: ".symlinks/plugins/image_picker_ios/ios"
1419
shared_preferences_foundation:
1520
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
1621

1722
SPEC CHECKSUMS:
1823
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
24+
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
1925
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
2026

2127
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796

ios/Runner.xcodeproj/project.pbxproj

+6-6
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@
478478
"$(inherited)",
479479
"@executable_path/Frameworks",
480480
);
481-
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.flutter_boilerplate;
481+
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.gemini_chat;
482482
PRODUCT_NAME = "$(TARGET_NAME)";
483483
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
484484
SWIFT_VERSION = 5.0;
@@ -495,7 +495,7 @@
495495
CURRENT_PROJECT_VERSION = 1;
496496
GENERATE_INFOPLIST_FILE = YES;
497497
MARKETING_VERSION = 1.0;
498-
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.flutter_boilerplate.RunnerTests;
498+
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.gemini_chat.RunnerTests;
499499
PRODUCT_NAME = "$(TARGET_NAME)";
500500
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
501501
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -513,7 +513,7 @@
513513
CURRENT_PROJECT_VERSION = 1;
514514
GENERATE_INFOPLIST_FILE = YES;
515515
MARKETING_VERSION = 1.0;
516-
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.flutter_boilerplate.RunnerTests;
516+
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.gemini_chat.RunnerTests;
517517
PRODUCT_NAME = "$(TARGET_NAME)";
518518
SWIFT_VERSION = 5.0;
519519
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -529,7 +529,7 @@
529529
CURRENT_PROJECT_VERSION = 1;
530530
GENERATE_INFOPLIST_FILE = YES;
531531
MARKETING_VERSION = 1.0;
532-
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.flutter_boilerplate.RunnerTests;
532+
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.gemini_chat.RunnerTests;
533533
PRODUCT_NAME = "$(TARGET_NAME)";
534534
SWIFT_VERSION = 5.0;
535535
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -661,7 +661,7 @@
661661
"$(inherited)",
662662
"@executable_path/Frameworks",
663663
);
664-
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.flutter_boilerplate;
664+
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.gemini_chat;
665665
PRODUCT_NAME = "$(TARGET_NAME)";
666666
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
667667
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -684,7 +684,7 @@
684684
"$(inherited)",
685685
"@executable_path/Frameworks",
686686
);
687-
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.flutter_boilerplate;
687+
PRODUCT_BUNDLE_IDENTIFIER = xyz.radenadri.gemini_chat;
688688
PRODUCT_NAME = "$(TARGET_NAME)";
689689
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
690690
SWIFT_VERSION = 5.0;

ios/Runner/Info.plist

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
<key>CFBundleDevelopmentRegion</key>
66
<string>$(DEVELOPMENT_LANGUAGE)</string>
77
<key>CFBundleDisplayName</key>
8-
<string>Boilerplate</string>
8+
<string>Gemini Chat</string>
99
<key>CFBundleExecutable</key>
1010
<string>$(EXECUTABLE_NAME)</string>
1111
<key>CFBundleIdentifier</key>
1212
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
1313
<key>CFBundleInfoDictionaryVersion</key>
1414
<string>6.0</string>
1515
<key>CFBundleName</key>
16-
<string>flutter_boilerplate</string>
16+
<string>gemini_chat</string>
1717
<key>CFBundlePackageType</key>
1818
<string>APPL</string>
1919
<key>CFBundleShortVersionString</key>
@@ -45,5 +45,9 @@
4545
<true/>
4646
<key>UIApplicationSupportsIndirectInputEvents</key>
4747
<true/>
48+
<key>NSPhotoLibraryUsageDescription</key>
49+
<string>Needed for get a picture to send for Gemini</string>
50+
<key>NSCameraUsageDescription</key>
51+
<string>Needed for take a shot to send for Gemini</string>
4852
</dict>
4953
</plist>

lib/config/constants.dart

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
// ignore_for_file: constant_identifier_names
1+
// ignore_for_file: constant_identifier_names, non_constant_identifier_names
2+
import 'package:flutter_dotenv/flutter_dotenv.dart';
23

3-
const API_URL = 'http://numbersapi.com';
4+
String GEMINI_AI_TOKEN = dotenv.env['GEMINI_AI_TOKEN'] ?? '';

lib/config/routes.dart

+3-40
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,12 @@
11
import 'package:go_router/go_router.dart';
2-
import 'package:riverpod_counter_app/views/ios/counter_view.dart' as ios;
3-
import 'package:riverpod_counter_app/views/ios/home_view.dart' as ios;
4-
import 'package:riverpod_counter_app/views/ios/number_trivia_view.dart' as ios;
5-
import 'package:riverpod_counter_app/views/android/counter_view.dart'
6-
as android;
7-
import 'package:riverpod_counter_app/views/android/home_view.dart' as android;
8-
import 'package:riverpod_counter_app/views/android/number_trivia_view.dart'
9-
as android;
2+
import 'package:gemini_chat/views/home_view.dart';
103

11-
final iosRouter = GoRouter(
4+
final router = GoRouter(
125
routes: [
136
GoRoute(
147
name: 'home',
158
path: '/',
16-
builder: (context, state) => const ios.HomeView(),
17-
),
18-
GoRoute(
19-
name: 'counter',
20-
path: '/counter',
21-
builder: (context, state) => const ios.CounterView(),
22-
),
23-
GoRoute(
24-
name: 'number_trivia',
25-
path: '/number_trivia',
26-
builder: (context, state) => const ios.NumberTriviaView(),
27-
),
28-
],
29-
);
30-
31-
final androidRouter = GoRouter(
32-
routes: [
33-
GoRoute(
34-
name: 'home',
35-
path: '/',
36-
builder: (context, state) => const android.HomeView(),
37-
),
38-
GoRoute(
39-
name: 'counter',
40-
path: '/counter',
41-
builder: (context, state) => const android.CounterView(),
42-
),
43-
GoRoute(
44-
name: 'number_trivia',
45-
path: '/number_trivia',
46-
builder: (context, state) => const android.NumberTriviaView(),
9+
builder: (context, state) => const HomeView(),
4710
),
4811
],
4912
);

lib/main.dart

+21-26
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
1-
import 'package:flutter/cupertino.dart';
2-
import 'package:flutter/foundation.dart';
31
import 'package:flutter/material.dart';
2+
import 'package:flutter_dotenv/flutter_dotenv.dart';
3+
import 'package:flutter_gemini/flutter_gemini.dart';
44
import 'package:flutter_riverpod/flutter_riverpod.dart';
5-
import 'package:riverpod_counter_app/config/routes.dart';
5+
import 'package:gemini_chat/config/constants.dart';
6+
import 'package:gemini_chat/config/routes.dart';
67

7-
void main() {
8-
if (defaultTargetPlatform == TargetPlatform.iOS) {
9-
runApp(
10-
ProviderScope(
11-
child: CupertinoApp.router(
12-
routerConfig: iosRouter,
13-
title: 'Flutter + Riverpod Boilerplate',
14-
theme: const CupertinoThemeData(brightness: Brightness.light),
15-
),
16-
),
17-
);
18-
} else if (defaultTargetPlatform == TargetPlatform.android) {
19-
runApp(
20-
ProviderScope(
21-
child: MaterialApp.router(
22-
routerConfig: androidRouter,
23-
title: 'Flutter + Riverpod Boilerplate',
24-
theme: ThemeData(
25-
colorSchemeSeed: Colors.green,
26-
useMaterial3: true,
27-
),
8+
void main() async {
9+
await dotenv.load(fileName: '.env');
10+
11+
Gemini.init(
12+
apiKey: GEMINI_AI_TOKEN,
13+
);
14+
15+
runApp(
16+
ProviderScope(
17+
child: MaterialApp.router(
18+
routerConfig: router,
19+
title: 'Gemini Chat',
20+
theme: ThemeData(
21+
colorSchemeSeed: Colors.blue,
22+
useMaterial3: true,
2823
),
2924
),
30-
);
31-
}
25+
),
26+
);
3227
}

lib/models/message_model.dart

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:freezed_annotation/freezed_annotation.dart';
2+
3+
part 'message_model.freezed.dart';
4+
part 'message_model.g.dart';
5+
6+
@freezed
7+
class Message with _$Message {
8+
const Message._();
9+
10+
const factory Message({
11+
required String owner,
12+
required String text,
13+
String? imageUrl,
14+
}) = _Message;
15+
16+
factory Message.fromJson(Map<String, dynamic> json) =>
17+
_$MessageFromJson(json);
18+
19+
bool isMine() => owner == 'Me';
20+
}

0 commit comments

Comments
 (0)