├── assets
├── images
│ ├── logo.png
│ └── logo_latte.png
└── fonts
│ ├── OpenSans-Bold.ttf
│ ├── OpenSans-Regular.ttf
│ └── OpenSans-SemiBold.ttf
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── values-night
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── ollama_app
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── build.gradle
└── settings.gradle
├── analysis_options.yaml
├── lib
├── types
│ └── message.dart
├── widgets
│ ├── icons
│ │ ├── bars3.dart
│ │ ├── check.dart
│ │ ├── xmark.dart
│ │ ├── arrowup.dart
│ │ ├── arrowleft.dart
│ │ ├── cog6tooth.dart
│ │ ├── usercircle.dart
│ │ └── ollama_logo.dart
│ ├── ez
│ │ ├── button.dart
│ │ ├── text.dart
│ │ ├── dropdown.dart
│ │ ├── scaffold.dart
│ │ ├── appbar.dart
│ │ ├── message.dart
│ │ └── textfield.dart
│ └── rerender_widget.dart
├── main.dart
├── utils
│ └── api.dart
├── globals.dart
└── routes
│ ├── home.dart
│ └── settings.dart
├── pubspec.yaml
├── .gitignore
├── LICENSE
├── .metadata
└── pubspec.lock
/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/assets/images/logo.png
--------------------------------------------------------------------------------
/assets/images/logo_latte.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/assets/images/logo_latte.png
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/assets/fonts/OpenSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/assets/fonts/OpenSans-Bold.ttf
--------------------------------------------------------------------------------
/assets/fonts/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/assets/fonts/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/assets/fonts/OpenSans-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/assets/fonts/OpenSans-SemiBold.ttf
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 |
3 | linter:
4 | rules:
5 | avoid_print: true
6 | prefer_single_quotes: true
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duccdev/ollama_app/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/ollama_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.ollama
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
6 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
6 |
--------------------------------------------------------------------------------
/lib/types/message.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Message {
4 | Message({
5 | required this.username,
6 | this.content,
7 | required this.pfp,
8 | this.error,
9 | });
10 |
11 | String username;
12 | String? content;
13 | Widget pfp;
14 | bool? error;
15 | }
16 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = '../build'
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(':app')
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/widgets/icons/bars3.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class Bars3 extends StatelessWidget {
5 | const Bars3({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.bars3,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/widgets/icons/check.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class Check extends StatelessWidget {
5 | const Check({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.check,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/widgets/icons/xmark.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class XMark extends StatelessWidget {
5 | const XMark({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.xMark,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/widgets/icons/arrowup.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class ArrowUp extends StatelessWidget {
5 | const ArrowUp({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.arrowUp,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/widgets/icons/arrowleft.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class ArrowLeft extends StatelessWidget {
5 | const ArrowLeft({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.arrowLeft,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/widgets/icons/cog6tooth.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class Cog6Tooth extends StatelessWidget {
5 | const Cog6Tooth({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.cog6Tooth,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/widgets/icons/usercircle.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:heroicons/heroicons.dart';
3 |
4 | class UserCircle extends StatelessWidget {
5 | const UserCircle({super.key, this.color, this.size});
6 |
7 | final Color? color;
8 | final double? size;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return HeroIcon(
13 | HeroIcons.userCircle,
14 | color: color ?? Colors.white,
15 | style: HeroIconStyle.mini,
16 | size: size ?? 32,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/widgets/ez/button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 |
4 | typedef OnPressedCallback = void Function();
5 |
6 | class EzButton extends StatelessWidget {
7 | const EzButton({super.key, required this.child, required this.onPressed});
8 |
9 | final Widget child;
10 | final OnPressedCallback onPressed;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return ElevatedButton(
15 | onPressed: onPressed,
16 | style: ElevatedButton.styleFrom(backgroundColor: Globals.ctp.surface0),
17 | child: child,
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/widgets/icons/ollama_logo.dart:
--------------------------------------------------------------------------------
1 | import 'package:catppuccin_flutter/catppuccin_flutter.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:ollama_app/globals.dart';
4 |
5 | class OllamaLogo extends StatelessWidget {
6 | const OllamaLogo({super.key, this.width, this.height});
7 |
8 | final double? width;
9 | final double? height;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Globals.ctp == catppuccin.latte
14 | ? Image.asset('assets/images/logo_latte.png',
15 | width: width ?? 48, height: height ?? 48)
16 | : Image.asset('assets/images/logo.png',
17 | width: width ?? 48, height: height ?? 48);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/widgets/rerender_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class RerenderWidget extends StatefulWidget {
4 | const RerenderWidget({super.key, required this.child});
5 |
6 | final Widget child;
7 |
8 | static void rerenderApp(BuildContext context) {
9 | context.findAncestorStateOfType()?.rerenderApp();
10 | }
11 |
12 | @override
13 | RerenderWidgetState createState() => RerenderWidgetState();
14 | }
15 |
16 | class RerenderWidgetState extends State {
17 | Key key = UniqueKey();
18 |
19 | void rerenderApp() {
20 | setState(() {
21 | key = UniqueKey();
22 | });
23 | }
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return KeyedSubtree(
28 | key: key,
29 | child: widget.child,
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: ollama_app
2 | description: "Android app for Ollama"
3 | publish_to: "none"
4 | version: 1.0.0+1
5 |
6 | environment:
7 | sdk: ">=3.3.4 <4.0.0"
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | catppuccin_flutter: ^1.0.0
14 | fluttertoast: ^8.2.5
15 | heroicons: ^0.10.0
16 | http: ^1.2.1
17 | shared_preferences: ^2.2.3
18 | shimmer: ^3.0.0
19 |
20 | dev_dependencies:
21 | flutter_lints: ^4.0.0
22 |
23 | flutter:
24 | uses-material-design: true
25 |
26 | assets:
27 | - assets/images/
28 |
29 | fonts:
30 | - family: OpenSans
31 | fonts:
32 | - asset: assets/fonts/OpenSans-Regular.ttf
33 | weight: 400
34 | - asset: assets/fonts/OpenSans-SemiBold.ttf
35 | weight: 600
36 | - asset: assets/fonts/OpenSans-Bold.ttf
37 | weight: 700
38 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 | import 'package:ollama_app/routes/home.dart';
4 | import 'package:ollama_app/routes/settings.dart';
5 | import 'package:ollama_app/widgets/ez/scaffold.dart';
6 | import 'package:ollama_app/widgets/rerender_widget.dart';
7 |
8 | void main() async {
9 | WidgetsFlutterBinding.ensureInitialized();
10 | await Globals.init();
11 | runApp(const RerenderWidget(child: Entry()));
12 | }
13 |
14 | class Entry extends StatelessWidget {
15 | const Entry({super.key});
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return MaterialApp(
20 | title: 'Ollama',
21 | theme: ThemeData(fontFamily: 'OpenSans'),
22 | routes: {'/settings': (context) => const Settings()},
23 | home: const EzScaffold(body: Home()),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Symbolication related
35 | app.*.symbols
36 |
37 | # Obfuscation related
38 | app.*.map.json
39 |
40 | # Android Studio will place build artifacts here
41 | /android/app/debug
42 | /android/app/profile
43 | /android/app/release
44 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }
9 | settings.ext.flutterSdkPath = flutterSdkPath()
10 |
11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
12 |
13 | repositories {
14 | google()
15 | mavenCentral()
16 | gradlePluginPortal()
17 | }
18 | }
19 |
20 | plugins {
21 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
22 | id "com.android.application" version "7.3.0" apply false
23 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false
24 | }
25 |
26 | include ":app"
27 |
--------------------------------------------------------------------------------
/lib/widgets/ez/text.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 |
4 | class EzText extends StatelessWidget {
5 | const EzText(this.content,
6 | {super.key,
7 | this.fontSize,
8 | this.color,
9 | this.textAlign,
10 | this.bold,
11 | this.semibold});
12 |
13 | final String content;
14 | final Color? color;
15 | final TextAlign? textAlign;
16 | final double? fontSize;
17 | final bool? bold;
18 | final bool? semibold;
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Text(
23 | content,
24 | softWrap: true,
25 | textAlign: textAlign,
26 | style: TextStyle(
27 | fontSize: fontSize ?? 24,
28 | color: color ?? Globals.ctp.text,
29 | fontWeight: (bold ?? false)
30 | ? FontWeight.w700
31 | : ((semibold ?? false) ? FontWeight.w600 : FontWeight.normal),
32 | ),
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib/utils/api.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:http/http.dart' as http;
4 | import 'package:ollama_app/globals.dart';
5 |
6 | Future isConnected() async {
7 | if (Globals.baseUrl == null) return false;
8 |
9 | try {
10 | var response = await http.get(Uri.parse(Globals.baseUrl!));
11 | if (response.statusCode != 200) return false;
12 | return true;
13 | } catch (e) {
14 | return false;
15 | }
16 | }
17 |
18 | Future infer(String prompt, String model) async {
19 | if (Globals.baseUrl == null) return null;
20 |
21 | try {
22 | var response = await http.post(
23 | Uri.parse('${Globals.baseUrl!}/api/generate'),
24 | body: jsonEncode({'model': model, 'prompt': prompt, 'stream': false}),
25 | headers: {'Content-Type': 'application/json'},
26 | );
27 | if (response.statusCode != 200) return null;
28 |
29 | return (jsonDecode(response.body) as Map)['response'];
30 | } catch (e) {
31 | return null;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/globals.dart:
--------------------------------------------------------------------------------
1 | import 'package:catppuccin_flutter/catppuccin_flutter.dart';
2 | import 'package:shared_preferences/shared_preferences.dart';
3 |
4 | class Globals {
5 | static Flavor ctp = catppuccin.mocha;
6 | static String? model;
7 | static String? baseUrl;
8 | static String? apiKey;
9 | static late SharedPreferences prefs;
10 |
11 | static Future init() async {
12 | prefs = await SharedPreferences.getInstance();
13 | reloadGlobals();
14 | }
15 |
16 | static void reloadGlobals() {
17 | if (prefs.containsKey('theme')) {
18 | switch (prefs.getString('theme')) {
19 | case 'Latte':
20 | ctp = catppuccin.latte;
21 | break;
22 | case 'Frappé':
23 | ctp = catppuccin.frappe;
24 | break;
25 | case 'Macchiato':
26 | ctp = catppuccin.macchiato;
27 | break;
28 | case 'Mocha':
29 | ctp = catppuccin.mocha;
30 | break;
31 | }
32 | }
33 |
34 | model = prefs.getString('model');
35 | baseUrl = prefs.getString('baseUrl');
36 | apiKey = prefs.getString('apiKey');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-present duccdev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lib/widgets/ez/dropdown.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 | import 'package:ollama_app/widgets/ez/text.dart';
4 |
5 | typedef OnChangedCallback = void Function(String value);
6 |
7 | class Dropdown extends StatefulWidget {
8 | const Dropdown(
9 | {super.key,
10 | required this.items,
11 | required this.defaultItem,
12 | this.onChanged});
13 |
14 | final List items;
15 | final String defaultItem;
16 | final OnChangedCallback? onChanged;
17 |
18 | @override
19 | State createState() => _DropdownState();
20 | }
21 |
22 | class _DropdownState extends State {
23 | String? _value;
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return DropdownButton(
28 | value: _value ?? widget.defaultItem,
29 | items: widget.items
30 | .map((value) => DropdownMenuItem(
31 | value: value,
32 | child: EzText(value, fontSize: 18),
33 | ))
34 | .toList(),
35 | dropdownColor: Globals.ctp.base,
36 | onChanged: (value) {
37 | setState(() => _value = value!);
38 | if (widget.onChanged != null) widget.onChanged!(value!);
39 | },
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/widgets/ez/scaffold.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 | import 'package:ollama_app/widgets/ez/appbar.dart';
4 |
5 | class EzScaffold extends StatelessWidget {
6 | const EzScaffold(
7 | {super.key, this.body, this.noAppBar, this.appBar, this.centerAppBar});
8 |
9 | final Widget? body;
10 | final bool? noAppBar;
11 | final Widget? appBar;
12 | final bool? centerAppBar;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | if (noAppBar ?? false) {
17 | return Scaffold(
18 | backgroundColor: Globals.ctp.base,
19 | body: Padding(padding: const EdgeInsets.all(12), child: body),
20 | appBar: AppBar(
21 | backgroundColor: Colors.transparent,
22 | iconTheme: IconThemeData(color: Globals.ctp.text),
23 | ),
24 | );
25 | }
26 |
27 | if (appBar != null) {
28 | return Scaffold(
29 | backgroundColor: Globals.ctp.base,
30 | body: Padding(padding: const EdgeInsets.all(12), child: body),
31 | appBar: AppBar(
32 | backgroundColor: Colors.transparent,
33 | iconTheme: IconThemeData(color: Globals.ctp.text),
34 | title: appBar,
35 | centerTitle: centerAppBar,
36 | ),
37 | );
38 | }
39 |
40 | return Scaffold(
41 | backgroundColor: Globals.ctp.base,
42 | body: Padding(padding: const EdgeInsets.all(12), child: body),
43 | appBar: const EzAppBar(),
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/widgets/ez/appbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:catppuccin_flutter/catppuccin_flutter.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:ollama_app/globals.dart';
4 | import 'package:ollama_app/widgets/ez/text.dart';
5 | import 'package:ollama_app/widgets/icons/bars3.dart';
6 | import 'package:ollama_app/widgets/icons/cog6tooth.dart';
7 | import 'package:ollama_app/widgets/icons/ollama_logo.dart';
8 |
9 | class EzAppBar extends StatefulWidget implements PreferredSizeWidget {
10 | const EzAppBar({super.key});
11 |
12 | @override
13 | EzAppBarState createState() => EzAppBarState();
14 |
15 | @override
16 | Size get preferredSize => const Size.fromHeight(kToolbarHeight);
17 | }
18 |
19 | class EzAppBarState extends State {
20 | @override
21 | Widget build(BuildContext context) {
22 | return AppBar(
23 | backgroundColor: Colors.transparent,
24 | iconTheme: IconThemeData(color: Globals.ctp.text),
25 | title: Row(
26 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
27 | children: [
28 | IconButton(
29 | onPressed: () {},
30 | icon: Bars3(color: Globals.ctp.text),
31 | ),
32 | Row(children: [
33 | const Padding(
34 | padding: EdgeInsets.only(right: 8),
35 | child: OllamaLogo(),
36 | ),
37 | EzText('Ollama',
38 | color: Globals.ctp == catppuccin.latte
39 | ? Colors.black
40 | : Colors.white,
41 | bold: true,
42 | fontSize: 28),
43 | ]),
44 | IconButton(
45 | onPressed: () => Navigator.of(context).pushNamed('/settings'),
46 | icon: Cog6Tooth(color: Globals.ctp.text),
47 | ),
48 | ],
49 | ),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: "54e66469a933b60ddf175f858f82eaeb97e48c8d"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
17 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
18 | - platform: android
19 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
20 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
21 | - platform: ios
22 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
23 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
24 | - platform: linux
25 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
26 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
27 | - platform: macos
28 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
29 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
30 | - platform: web
31 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
32 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
33 | - platform: windows
34 | create_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
35 | base_revision: 54e66469a933b60ddf175f858f82eaeb97e48c8d
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | def localProperties = new Properties()
8 | def localPropertiesFile = rootProject.file('local.properties')
9 | if (localPropertiesFile.exists()) {
10 | localPropertiesFile.withReader('UTF-8') { reader ->
11 | localProperties.load(reader)
12 | }
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 | }
24 |
25 | android {
26 | namespace "com.ollama"
27 | compileSdk flutter.compileSdkVersion
28 | ndkVersion flutter.ndkVersion
29 |
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 |
35 | kotlinOptions {
36 | jvmTarget = '1.8'
37 | }
38 |
39 | sourceSets {
40 | main.java.srcDirs += 'src/main/kotlin'
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "com.ollama"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdkVersion flutter.minSdkVersion
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | buildTypes {
55 | release {
56 | // TODO: Add your own signing config for the release build.
57 | // Signing with the debug keys for now, so `flutter run --release` works.
58 | signingConfig signingConfigs.debug
59 | }
60 | }
61 | }
62 |
63 | flutter {
64 | source '../..'
65 | }
66 |
67 | dependencies {}
68 |
--------------------------------------------------------------------------------
/lib/routes/home.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/types/message.dart';
3 | import 'package:ollama_app/widgets/ez/message.dart';
4 | import 'package:ollama_app/widgets/ez/textfield.dart';
5 | import 'package:ollama_app/utils/api.dart' as api;
6 | import 'package:ollama_app/widgets/icons/ollama_logo.dart';
7 | import 'package:ollama_app/widgets/icons/usercircle.dart';
8 |
9 | class Home extends StatefulWidget {
10 | const Home({super.key});
11 |
12 | @override
13 | State createState() => _HomeState();
14 | }
15 |
16 | class _HomeState extends State {
17 | late List _messages;
18 |
19 | @override
20 | void initState() {
21 | super.initState();
22 | _messages = [];
23 | }
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return Column(
28 | children: [
29 | Column(
30 | children: _messages
31 | .map((message) => EzMessage(message: message))
32 | .toList()),
33 | Align(
34 | alignment: FractionalOffset.bottomCenter,
35 | child: EzTextField(
36 | hintText: 'Message Ollama',
37 | onSubmitted: (text) async {
38 | setState(() {
39 | _messages.add(Message(
40 | username: 'You',
41 | content: text,
42 | pfp: const UserCircle(size: 55),
43 | ));
44 |
45 | _messages.add(Message(
46 | username: 'LLaMA 3',
47 | content: null,
48 | pfp: const OllamaLogo(width: 55, height: 55),
49 | ));
50 | });
51 |
52 | String? res = await api.infer(text, 'llama3');
53 | if (res == null) {
54 | setState(() {
55 | _messages.last.error = true;
56 | _messages.last.content = 'Failed to infer Ollama!';
57 | });
58 |
59 | return;
60 | }
61 |
62 | setState(() => _messages.last.content = res);
63 | },
64 | ),
65 | ),
66 | ],
67 | );
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib/widgets/ez/message.dart:
--------------------------------------------------------------------------------
1 | import 'package:shimmer/shimmer.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:ollama_app/globals.dart';
4 | import 'package:ollama_app/types/message.dart';
5 | import 'package:ollama_app/widgets/ez/text.dart';
6 |
7 | class EzMessage extends StatelessWidget {
8 | const EzMessage({super.key, required this.message});
9 |
10 | final Message message;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Padding(
15 | padding: const EdgeInsets.symmetric(vertical: 4),
16 | child: Row(
17 | children: [
18 | message.pfp,
19 | Padding(
20 | padding: const EdgeInsets.only(left: 8),
21 | child: Column(
22 | crossAxisAlignment: CrossAxisAlignment.start,
23 | mainAxisAlignment: MainAxisAlignment.start,
24 | children: [
25 | EzText(message.username, fontSize: 20, bold: true),
26 | message.content == null
27 | ? SizedBox(
28 | width: MediaQuery.of(context).size.width - 100,
29 | height: 30,
30 | child: Shimmer.fromColors(
31 | baseColor: Globals.ctp.surface0,
32 | highlightColor: Globals.ctp.text,
33 | period: const Duration(milliseconds: 1500),
34 | child: Container(
35 | decoration: const BoxDecoration(
36 | borderRadius: BorderRadius.all(
37 | Radius.circular(3.3),
38 | ),
39 | color: Colors.white,
40 | ),
41 | ),
42 | ),
43 | )
44 | : EzText(
45 | message.content!,
46 | fontSize: 20,
47 | color: (message.error ?? false)
48 | ? Globals.ctp.red
49 | : Globals.ctp.text,
50 | ),
51 | ],
52 | ),
53 | ),
54 | ],
55 | ),
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
32 |
33 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/lib/widgets/ez/textfield.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 | import 'package:ollama_app/widgets/icons/arrowup.dart';
4 |
5 | typedef OnSubmittedCallback = void Function(String text);
6 | typedef OnChangedCallback = void Function(String text);
7 |
8 | class EzTextField extends StatefulWidget {
9 | const EzTextField({
10 | super.key,
11 | this.onSubmitted,
12 | this.onChanged,
13 | this.disableSubmitButton,
14 | this.hintText,
15 | this.obscureText,
16 | this.defaultValue,
17 | });
18 |
19 | final OnSubmittedCallback? onSubmitted;
20 | final OnChangedCallback? onChanged;
21 | final bool? disableSubmitButton;
22 | final String? hintText;
23 | final bool? obscureText;
24 | final String? defaultValue;
25 |
26 | @override
27 | State createState() => _EzTextFieldState();
28 | }
29 |
30 | class _EzTextFieldState extends State {
31 | bool _sendButtonDisabled = true;
32 | late TextEditingController _controller;
33 |
34 | @override
35 | void initState() {
36 | super.initState();
37 | _controller = TextEditingController();
38 | _controller.addListener(_onTextChanged);
39 | _controller.text = widget.defaultValue ?? '';
40 | }
41 |
42 | @override
43 | void dispose() {
44 | _controller.removeListener(_onTextChanged);
45 | _controller.dispose();
46 | super.dispose();
47 | }
48 |
49 | void _onTextChanged() {
50 | setState(() {
51 | if (widget.onChanged != null) {
52 | widget.onChanged!(_controller.text);
53 | }
54 |
55 | if (_controller.text.trim().isNotEmpty) {
56 | _sendButtonDisabled = false;
57 | return;
58 | }
59 |
60 | _sendButtonDisabled = true;
61 | });
62 | }
63 |
64 | @override
65 | Widget build(BuildContext context) {
66 | const border = OutlineInputBorder(
67 | borderSide: BorderSide.none,
68 | borderRadius: BorderRadius.horizontal(
69 | left: Radius.circular(9999),
70 | right: Radius.circular(9999),
71 | ),
72 | );
73 |
74 | return SizedBox(
75 | height: 48,
76 | child: TextField(
77 | controller: _controller,
78 | style: TextStyle(color: Globals.ctp.text, fontWeight: FontWeight.w600),
79 | decoration: InputDecoration(
80 | filled: true,
81 | fillColor: Globals.ctp.surface2,
82 | border: border,
83 | focusedBorder: border,
84 | contentPadding: const EdgeInsets.symmetric(horizontal: 18),
85 | hintText: widget.hintText,
86 | hintStyle: TextStyle(
87 | color: Globals.ctp.overlay2,
88 | fontWeight: FontWeight.w600,
89 | ),
90 | suffixIcon: (widget.disableSubmitButton ?? false)
91 | ? null
92 | : Padding(
93 | padding: const EdgeInsets.all(4),
94 | child: IconButton.filled(
95 | icon: ArrowUp(
96 | color: _sendButtonDisabled
97 | ? Globals.ctp.text
98 | : Globals.ctp.base),
99 | style: ButtonStyle(
100 | backgroundColor: WidgetStateProperty.all(
101 | _sendButtonDisabled
102 | ? Globals.ctp.surface0
103 | : Globals.ctp.green,
104 | ),
105 | ),
106 | onPressed: _sendButtonDisabled
107 | ? null
108 | : () => (widget.onSubmitted ??
109 | (String text) {})(_controller.text),
110 | ),
111 | ),
112 | ),
113 | obscureText: widget.obscureText ?? false,
114 | cursorColor: Globals.ctp.lavender,
115 | ),
116 | );
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/lib/routes/settings.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ollama_app/globals.dart';
3 | import 'package:ollama_app/widgets/ez/button.dart';
4 | import 'package:ollama_app/widgets/ez/dropdown.dart';
5 | import 'package:ollama_app/widgets/ez/scaffold.dart';
6 | import 'package:ollama_app/widgets/ez/text.dart';
7 | import 'package:ollama_app/widgets/ez/textfield.dart';
8 | import 'package:ollama_app/widgets/icons/check.dart';
9 | import 'package:ollama_app/widgets/icons/cog6tooth.dart';
10 | import 'package:ollama_app/widgets/icons/xmark.dart';
11 | import 'package:ollama_app/widgets/rerender_widget.dart';
12 | import 'package:ollama_app/utils/api.dart' as api;
13 |
14 | class Settings extends StatefulWidget {
15 | const Settings({super.key});
16 |
17 | @override
18 | State createState() => _SettingsState();
19 | }
20 |
21 | class _SettingsState extends State {
22 | late Map _connectionTestStates;
23 | late String _currentConnectionTestState;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | _connectionTestStates = {
29 | 'notTesting': EzButton(
30 | onPressed: () async {
31 | setState(() => _currentConnectionTestState = 'testing');
32 |
33 | if (await api.isConnected()) {
34 | setState(() => _currentConnectionTestState = 'success');
35 | } else {
36 | setState(() => _currentConnectionTestState = 'failed');
37 | }
38 |
39 | Future.delayed(
40 | const Duration(seconds: 3),
41 | () => setState(() => _currentConnectionTestState = 'notTesting'),
42 | );
43 | },
44 | child: const EzText(
45 | 'Test connection',
46 | fontSize: 20,
47 | ),
48 | ),
49 | 'testing': Center(
50 | child: CircularProgressIndicator(
51 | backgroundColor: Colors.transparent,
52 | color: Globals.ctp.blue,
53 | ),
54 | ),
55 | 'failed': const Row(
56 | mainAxisAlignment: MainAxisAlignment.center,
57 | crossAxisAlignment: CrossAxisAlignment.center,
58 | children: [
59 | Padding(
60 | padding: EdgeInsets.only(right: 8),
61 | child: XMark(),
62 | ),
63 | EzText('Failed!'),
64 | ],
65 | ),
66 | 'success': const Row(
67 | mainAxisAlignment: MainAxisAlignment.center,
68 | crossAxisAlignment: CrossAxisAlignment.center,
69 | children: [
70 | Padding(
71 | padding: EdgeInsets.only(right: 8),
72 | child: Check(),
73 | ),
74 | EzText('Connected!'),
75 | ],
76 | ),
77 | };
78 | _currentConnectionTestState = 'notTesting';
79 | }
80 |
81 | @override
82 | Widget build(BuildContext context) {
83 | return EzScaffold(
84 | appBar: Row(
85 | mainAxisAlignment: MainAxisAlignment.center,
86 | mainAxisSize: MainAxisSize.min,
87 | children: [
88 | Padding(
89 | padding: const EdgeInsets.only(right: 8),
90 | child: Cog6Tooth(color: Globals.ctp.text),
91 | ),
92 | const EzText('Settings'),
93 | ],
94 | ),
95 | centerAppBar: true,
96 | body: Column(
97 | children: [
98 | const Align(
99 | alignment: Alignment.topLeft,
100 | child: Padding(
101 | padding: EdgeInsets.only(right: 6, left: 6, bottom: 12),
102 | child: EzText('Ollama API', fontSize: 32, bold: true),
103 | ),
104 | ),
105 | Padding(
106 | padding: const EdgeInsets.only(bottom: 8),
107 | child: EzTextField(
108 | disableSubmitButton: true,
109 | hintText: 'Ollama Base URL (Required)',
110 | onChanged: (text) {
111 | Globals.prefs.setString('baseUrl', text);
112 | Globals.baseUrl = text;
113 | },
114 | defaultValue: Globals.baseUrl,
115 | ),
116 | ),
117 | Padding(
118 | padding: const EdgeInsets.only(bottom: 6),
119 | child: EzTextField(
120 | disableSubmitButton: true,
121 | hintText: 'Ollama API Key (Optional)',
122 | onChanged: (text) {
123 | Globals.prefs.setString('apiKey', text);
124 | Globals.apiKey = text;
125 | },
126 | obscureText: true,
127 | defaultValue: Globals.apiKey,
128 | ),
129 | ),
130 | Padding(
131 | padding: const EdgeInsets.only(top: 8),
132 | child: SizedBox(
133 | width: 200,
134 | height: 50,
135 | child: _connectionTestStates[_currentConnectionTestState]!,
136 | ),
137 | ),
138 | const Align(
139 | alignment: Alignment.topLeft,
140 | child: Padding(
141 | padding: EdgeInsets.only(right: 6, left: 6, top: 32),
142 | child: EzText('Personalization', fontSize: 32, bold: true),
143 | ),
144 | ),
145 | Padding(
146 | padding: const EdgeInsets.symmetric(horizontal: 6),
147 | child: Row(children: [
148 | const EzText('Catppuccin Theme: ', fontSize: 20),
149 | Padding(
150 | padding: const EdgeInsets.symmetric(horizontal: 8),
151 | child: SizedBox(
152 | child: Dropdown(
153 | items: const ['Latte', 'Frappé', 'Macchiato', 'Mocha'],
154 | defaultItem: Globals.prefs.getString('theme') ?? 'Mocha',
155 | onChanged: (item) {
156 | Globals.prefs.setString('theme', item);
157 | Globals.reloadGlobals();
158 | RerenderWidget.rerenderApp(context);
159 | },
160 | ),
161 | ),
162 | ),
163 | ]),
164 | ),
165 | ],
166 | ),
167 | );
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | args:
5 | dependency: transitive
6 | description:
7 | name: args
8 | sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.5.0"
12 | async:
13 | dependency: transitive
14 | description:
15 | name: async
16 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.11.0"
20 | catppuccin_flutter:
21 | dependency: "direct main"
22 | description:
23 | name: catppuccin_flutter
24 | sha256: af76e96f39ebf228d943b46f64e50c683d2580b4ef4088f28214e35ff26a2543
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.0.0"
28 | characters:
29 | dependency: transitive
30 | description:
31 | name: characters
32 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.3.0"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.18.0"
44 | ffi:
45 | dependency: transitive
46 | description:
47 | name: ffi
48 | sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "2.1.2"
52 | file:
53 | dependency: transitive
54 | description:
55 | name: file
56 | sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "7.0.0"
60 | flutter:
61 | dependency: "direct main"
62 | description: flutter
63 | source: sdk
64 | version: "0.0.0"
65 | flutter_lints:
66 | dependency: "direct dev"
67 | description:
68 | name: flutter_lints
69 | sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
70 | url: "https://pub.dev"
71 | source: hosted
72 | version: "4.0.0"
73 | flutter_svg:
74 | dependency: transitive
75 | description:
76 | name: flutter_svg
77 | sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2"
78 | url: "https://pub.dev"
79 | source: hosted
80 | version: "2.0.10+1"
81 | flutter_web_plugins:
82 | dependency: transitive
83 | description: flutter
84 | source: sdk
85 | version: "0.0.0"
86 | fluttertoast:
87 | dependency: "direct main"
88 | description:
89 | name: fluttertoast
90 | sha256: "81b68579e23fcbcada2db3d50302813d2371664afe6165bc78148050ab94bf66"
91 | url: "https://pub.dev"
92 | source: hosted
93 | version: "8.2.5"
94 | heroicons:
95 | dependency: "direct main"
96 | description:
97 | name: heroicons
98 | sha256: "762f907af146105a3956e61e16e0a2cafadd39317e88cc4e4d0ed32846a0452e"
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "0.10.0"
102 | http:
103 | dependency: "direct main"
104 | description:
105 | name: http
106 | sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
107 | url: "https://pub.dev"
108 | source: hosted
109 | version: "1.2.1"
110 | http_parser:
111 | dependency: transitive
112 | description:
113 | name: http_parser
114 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
115 | url: "https://pub.dev"
116 | source: hosted
117 | version: "4.0.2"
118 | lints:
119 | dependency: transitive
120 | description:
121 | name: lints
122 | sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
123 | url: "https://pub.dev"
124 | source: hosted
125 | version: "4.0.0"
126 | material_color_utilities:
127 | dependency: transitive
128 | description:
129 | name: material_color_utilities
130 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
131 | url: "https://pub.dev"
132 | source: hosted
133 | version: "0.8.0"
134 | meta:
135 | dependency: transitive
136 | description:
137 | name: meta
138 | sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
139 | url: "https://pub.dev"
140 | source: hosted
141 | version: "1.12.0"
142 | path:
143 | dependency: transitive
144 | description:
145 | name: path
146 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
147 | url: "https://pub.dev"
148 | source: hosted
149 | version: "1.9.0"
150 | path_parsing:
151 | dependency: transitive
152 | description:
153 | name: path_parsing
154 | sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
155 | url: "https://pub.dev"
156 | source: hosted
157 | version: "1.0.1"
158 | path_provider_linux:
159 | dependency: transitive
160 | description:
161 | name: path_provider_linux
162 | sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
163 | url: "https://pub.dev"
164 | source: hosted
165 | version: "2.2.1"
166 | path_provider_platform_interface:
167 | dependency: transitive
168 | description:
169 | name: path_provider_platform_interface
170 | sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
171 | url: "https://pub.dev"
172 | source: hosted
173 | version: "2.1.2"
174 | path_provider_windows:
175 | dependency: transitive
176 | description:
177 | name: path_provider_windows
178 | sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
179 | url: "https://pub.dev"
180 | source: hosted
181 | version: "2.2.1"
182 | petitparser:
183 | dependency: transitive
184 | description:
185 | name: petitparser
186 | sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
187 | url: "https://pub.dev"
188 | source: hosted
189 | version: "6.0.2"
190 | platform:
191 | dependency: transitive
192 | description:
193 | name: platform
194 | sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
195 | url: "https://pub.dev"
196 | source: hosted
197 | version: "3.1.4"
198 | plugin_platform_interface:
199 | dependency: transitive
200 | description:
201 | name: plugin_platform_interface
202 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
203 | url: "https://pub.dev"
204 | source: hosted
205 | version: "2.1.8"
206 | shared_preferences:
207 | dependency: "direct main"
208 | description:
209 | name: shared_preferences
210 | sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
211 | url: "https://pub.dev"
212 | source: hosted
213 | version: "2.2.3"
214 | shared_preferences_android:
215 | dependency: transitive
216 | description:
217 | name: shared_preferences_android
218 | sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
219 | url: "https://pub.dev"
220 | source: hosted
221 | version: "2.2.2"
222 | shared_preferences_foundation:
223 | dependency: transitive
224 | description:
225 | name: shared_preferences_foundation
226 | sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
227 | url: "https://pub.dev"
228 | source: hosted
229 | version: "2.4.0"
230 | shared_preferences_linux:
231 | dependency: transitive
232 | description:
233 | name: shared_preferences_linux
234 | sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
235 | url: "https://pub.dev"
236 | source: hosted
237 | version: "2.3.2"
238 | shared_preferences_platform_interface:
239 | dependency: transitive
240 | description:
241 | name: shared_preferences_platform_interface
242 | sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
243 | url: "https://pub.dev"
244 | source: hosted
245 | version: "2.3.2"
246 | shared_preferences_web:
247 | dependency: transitive
248 | description:
249 | name: shared_preferences_web
250 | sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
251 | url: "https://pub.dev"
252 | source: hosted
253 | version: "2.3.0"
254 | shared_preferences_windows:
255 | dependency: transitive
256 | description:
257 | name: shared_preferences_windows
258 | sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
259 | url: "https://pub.dev"
260 | source: hosted
261 | version: "2.3.2"
262 | shimmer:
263 | dependency: "direct main"
264 | description:
265 | name: shimmer
266 | sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9"
267 | url: "https://pub.dev"
268 | source: hosted
269 | version: "3.0.0"
270 | sky_engine:
271 | dependency: transitive
272 | description: flutter
273 | source: sdk
274 | version: "0.0.99"
275 | source_span:
276 | dependency: transitive
277 | description:
278 | name: source_span
279 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
280 | url: "https://pub.dev"
281 | source: hosted
282 | version: "1.10.0"
283 | string_scanner:
284 | dependency: transitive
285 | description:
286 | name: string_scanner
287 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
288 | url: "https://pub.dev"
289 | source: hosted
290 | version: "1.2.0"
291 | term_glyph:
292 | dependency: transitive
293 | description:
294 | name: term_glyph
295 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
296 | url: "https://pub.dev"
297 | source: hosted
298 | version: "1.2.1"
299 | typed_data:
300 | dependency: transitive
301 | description:
302 | name: typed_data
303 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
304 | url: "https://pub.dev"
305 | source: hosted
306 | version: "1.3.2"
307 | vector_graphics:
308 | dependency: transitive
309 | description:
310 | name: vector_graphics
311 | sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3"
312 | url: "https://pub.dev"
313 | source: hosted
314 | version: "1.1.11+1"
315 | vector_graphics_codec:
316 | dependency: transitive
317 | description:
318 | name: vector_graphics_codec
319 | sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da
320 | url: "https://pub.dev"
321 | source: hosted
322 | version: "1.1.11+1"
323 | vector_graphics_compiler:
324 | dependency: transitive
325 | description:
326 | name: vector_graphics_compiler
327 | sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81"
328 | url: "https://pub.dev"
329 | source: hosted
330 | version: "1.1.11+1"
331 | vector_math:
332 | dependency: transitive
333 | description:
334 | name: vector_math
335 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
336 | url: "https://pub.dev"
337 | source: hosted
338 | version: "2.1.4"
339 | web:
340 | dependency: transitive
341 | description:
342 | name: web
343 | sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
344 | url: "https://pub.dev"
345 | source: hosted
346 | version: "0.5.1"
347 | win32:
348 | dependency: transitive
349 | description:
350 | name: win32
351 | sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
352 | url: "https://pub.dev"
353 | source: hosted
354 | version: "5.5.0"
355 | xdg_directories:
356 | dependency: transitive
357 | description:
358 | name: xdg_directories
359 | sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
360 | url: "https://pub.dev"
361 | source: hosted
362 | version: "1.0.4"
363 | xml:
364 | dependency: transitive
365 | description:
366 | name: xml
367 | sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
368 | url: "https://pub.dev"
369 | source: hosted
370 | version: "6.5.0"
371 | sdks:
372 | dart: ">=3.3.4 <4.0.0"
373 | flutter: ">=3.19.0"
374 |
--------------------------------------------------------------------------------