Skip to content

Feature/chatgpt integration #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion .github/workflows/push-playstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
track: zest
status: completed
# status: completed
changesNotSentForReview: true
changesNotSentForReview: false
# inAppUpdatePriority: 2
# whatsNewDirectory: distribution/whatsnew
# mappingFile: app/build/outputs/mapping/release/mapping.txt
Expand Down
64 changes: 63 additions & 1 deletion frontend/lib/recipes/screens/recipe_edit.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:country_flags/country_flags.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
Expand All @@ -10,6 +12,7 @@ import 'package:form_builder_extra_fields/form_builder_extra_fields.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:zest/chatgpt/api.dart';
import 'package:zest/config/constants.dart';

import 'package:zest/recipes/controller/edit_controller.dart';
Expand Down Expand Up @@ -285,7 +288,66 @@ class RecipeEditWideWidget extends HookConsumerWidget {
}
},
),
)
),
if (recipeId == null)
IconButton(
onPressed: () async {
FilePickerResult? result =
await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['pdf'],
);

if (result == null ||
result.files.single.path == null) {
return;
}

// File file = File(
// "/home/dbadrian/Downloads/Pasta alla Norma_sizilianisch-1.pdf"); //result.files.single.path!);
// // debugPrint(result.files.single.path!);

final pdfText = await ref
.read(chatGPTApiServiceProvider)
.getPDFtext(File(result.files.single.path!));
debugPrint(pdfText);

final assistantId = await ref
.read(chatGPTApiServiceProvider)
.createAssistant();
debugPrint(assistantId);

if (assistantId == null) {
return;
}

// final uploadedFileId = await ref
// .read(chatGPTApiServiceProvider)
// .uploadPDF(file);
// if (uploadedFileId == null) {
// return;
// }

// Upload the PDF to OpenAI
final ret = await ref
.read(chatGPTApiServiceProvider)
.analyzeRecipePDF(pdfText, assistantId);
debugPrint(ret);

if (ret == null) {
return;
}

final json = jsonDecode(
ret); // Attempt to decode the JSON string
// debugPrint(json);
ref
.read(recipeEditControllerProvider(recipeId,
draftId: draftId)
.notifier)
.fillRecipeFromJSON(json);
},
icon: Icon(Icons.file_upload))
// TextButton(
// child: Text("ADD FROM JSON"),
// onPressed: () {},
Expand Down
17 changes: 14 additions & 3 deletions frontend/lib/settings/settings_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ part 'settings_provider.g.dart';
// Keys for basic settings
const _languageKey = 'settings_language';
const _searchAllLanguagesKey = 'settings_search_all_languages_key';
const apiUrlKey = 'settings_api_url';
const _apiUrlKey = 'settings_api_url';
const _chatGPTAPIKey = 'settings_chat_gpt_key';

const _themeUseDarkThemeKey = 'settings_useDarkTheme';
const _themeBaseColorKey = 'settings_themeBaseColor';
Expand All @@ -42,6 +43,7 @@ class SettingsStateData with _$SettingsStateData {
// API Related
@Default(DEFAULT_API_URL) apiUrl,
@Default(false) bool apiUrlDirty,
@Default("") chatGPTKey,

// Advanced Settings
@Default(false) bool showAdvancedSettings,
Expand Down Expand Up @@ -87,6 +89,10 @@ class Settings extends _$Settings {
state = state.copyWith.dirty(apiUrl: apiUrl, apiUrlDirty: true);
}

void setChatGPTAPIKey(String chatGPTKey) {
state = state.copyWith.dirty(chatGPTKey: chatGPTKey);
}

void setShowAdvancedSettings(bool showAdvancedSettings) {
state = state.copyWith.dirty(showAdvancedSettings: showAdvancedSettings);
}
Expand All @@ -103,9 +109,11 @@ class Settings extends _$Settings {
// Advanced
final showAdvancedSettings =
prefs.getBool(_showAdvancedSettingsKey) ?? false;
final apiUrl = prefs.getString(apiUrlKey) ?? DEFAULT_API_URL;
final apiUrl = prefs.getString(_apiUrlKey) ?? DEFAULT_API_URL;
final apiUrlDirty = false;

final chatGPTKey = prefs.getString(_chatGPTAPIKey) ?? "";

final gt = SettingsStateData(
useDarkTheme: useDarkTheme,
pickerColor: Color(pickerColor),
Expand All @@ -115,6 +123,7 @@ class Settings extends _$Settings {
showAdvancedSettings: showAdvancedSettings,
apiUrl: apiUrl,
apiUrlDirty: apiUrlDirty,
chatGPTKey: chatGPTKey,
);

return SettingsState(current: gt, dirty: gt);
Expand Down Expand Up @@ -145,7 +154,9 @@ class Settings extends _$Settings {
prefs.setBool(_searchAllLanguagesKey, state.dirty.searchAllLanguages);
// Advanced
prefs.setBool(_showAdvancedSettingsKey, state.dirty.showAdvancedSettings);
prefs.setString(apiUrlKey, state.dirty.apiUrl);
prefs.setString(_apiUrlKey, state.dirty.apiUrl);

prefs.setString(_chatGPTAPIKey, state.dirty.chatGPTKey);

state = state.copyWith(current: state.dirty);
}
Expand Down
48 changes: 48 additions & 0 deletions frontend/lib/settings/settings_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,58 @@ class APIFieldWidget extends HookConsumerWidget {
}
}

class ChatGPTFieldWidget extends HookConsumerWidget {
const ChatGPTFieldWidget({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final settings = ref.watch(settingsProvider.notifier);
final chatGPTKey =
ref.watch(settingsProvider.select((s) => s.dirty.chatGPTKey));
final TextEditingController chatGPTKeyCtrl = useTextEditingController();

final double screenWidth = MediaQuery.of(context).size.width;

// The following updates the text-editing controller with the current value
// but it will also reset the cursor position to the end of the text
// hence we need to cache the position -> seleciton
final cacheSelection = chatGPTKeyCtrl.selection;
chatGPTKeyCtrl.text = chatGPTKey; // to refresh the text on changes
chatGPTKeyCtrl.selection = TextSelection.fromPosition(TextPosition(
offset: min(chatGPTKeyCtrl.text.length, cacheSelection.baseOffset)));

return ListTile(
leading: const Icon(Icons.connect_without_contact),
title: const Text("API"),
trailing: ConstrainedBox(
constraints:
BoxConstraints(minWidth: 40, maxWidth: max(250, screenWidth * 0.5)),
child: Row(
children: [
Expanded(
child: TextFormField(
controller: chatGPTKeyCtrl,
onChanged: ((value) => settings.setChatGPTAPIKey(value)),
// controller: ref.apiAddressCtrl,
decoration: InputDecoration(
// border: OutlineInputBorder(),
hintText: 'Chat GPT API Key',
),
textAlign: TextAlign.center,
),
),
],
),
),
);
}
}

Widget _buildAdvancedSettingsImpl(ref) {
return const Column(
children: [
APIFieldWidget(),
ChatGPTFieldWidget(),
],
);
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import FlutterMacOS
import Foundation

import downloadsfolder
import file_picker
import flutter_secure_storage_macos
import package_info_plus
import path_provider_foundation
Expand All @@ -18,6 +19,7 @@ import window_manager

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DownloadsfolderPlugin.register(with: registry.registrar(forPlugin: "DownloadsfolderPlugin"))
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
Expand Down
Loading
Loading