Skip to content
Closed
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: 7 additions & 1 deletion app/lib/backend/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ Future<UserCredential?> signInWithGoogle() async {
try {
debugPrint('Signing in with Google');
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await GoogleSignIn(scopes: ['profile', 'email']).signIn();
final GoogleSignInAccount? googleUser = await GoogleSignIn(scopes: ['profile', 'email']
).signIn();
debugPrint('Google User: $googleUser');

// Obtain the auth details from the request
Expand Down Expand Up @@ -143,6 +144,11 @@ Future<UserCredential?> signInWithGoogle() async {
SharedPreferencesUtil().givenName = givenName;
SharedPreferencesUtil().familyName = familyName;
}
// To reduce unnecessary invoking of getIdToken() on web
IdTokenResult? tokenResult = await FirebaseAuth.instance.currentUser?.getIdTokenResult();
SharedPreferencesUtil().authToken = await FirebaseAuth.instance.currentUser?.getIdToken()?? '';
SharedPreferencesUtil().tokenExpirationTime = tokenResult?.expirationTime?.millisecondsSinceEpoch ?? 0 ;

Comment thread
rutikthakre marked this conversation as resolved.
// TODO: test subsequent signIn
debugPrint('signInWithGoogle Email: ${SharedPreferencesUtil().email}');
debugPrint('signInWithGoogle Name: ${SharedPreferencesUtil().givenName}');
Expand Down
58 changes: 46 additions & 12 deletions app/lib/backend/http/api/apps.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';

import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:omi/backend/http/shared.dart';
import 'package:omi/backend/preferences.dart';
import 'package:omi/backend/schema/app.dart';
Expand Down Expand Up @@ -75,12 +76,20 @@ Future<bool> reviewApp(String appId, AppReview review) async {
}
}

Future<Map<String, String>> uploadAppThumbnail(File file) async {
Future<Map<String, String>> uploadAppThumbnail(XFile file) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v1/app/thumbnails'),
);
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(
http.MultipartFile.fromBytes(
'file',
await file.readAsBytes(),
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
filename: filename,
),
);
request.headers.addAll({'Authorization': await getAuthHeader()});

try {
Expand Down Expand Up @@ -185,12 +194,20 @@ Future<bool> isAppSetupCompleted(String? url) async {
}
}

Future<(bool, String, String?)> submitAppServer(File file, Map<String, dynamic> appData) async {
Future<(bool, String, String?)> submitAppServer(XFile file, Map<String, dynamic> appData) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v1/apps'),
);
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(
http.MultipartFile.fromBytes(
'file',
await file.readAsBytes(),
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
filename: filename,
),
);
request.headers.addAll({'Authorization': await getAuthHeader()});
request.fields.addAll({'app_data': jsonEncode(appData)});
debugPrint(jsonEncode(appData));
Expand Down Expand Up @@ -221,13 +238,14 @@ Future<(bool, String, String?)> submitAppServer(File file, Map<String, dynamic>
}
}

Future<bool> updateAppServer(File? file, Map<String, dynamic> appData) async {
Future<bool> updateAppServer(XFile? file, Map<String, dynamic> appData) async {
var request = http.MultipartRequest(
'PATCH',
Uri.parse('${Env.apiBaseUrl}v1/apps/${appData['id']}'),
);
if (file != null) {
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
var bytes = await file.readAsBytes();
request.files.add(http.MultipartFile.fromBytes('file', bytes, filename: basename(file.path)));
}
request.headers.addAll({'Authorization': await getAuthHeader()});
request.fields.addAll({'app_data': jsonEncode(appData)});
Expand Down Expand Up @@ -474,12 +492,20 @@ Future<bool> deleteApiKeyServer(String appId, String keyId) async {
}
}

Future<Map> createPersonaApp(File file, Map<String, dynamic> personaData) async {
Future<Map> createPersonaApp(XFile file, Map<String, dynamic> personaData) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v1/personas'),
);
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(
http.MultipartFile.fromBytes(
'file',
await file.readAsBytes(),
filename: filename,
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
),
);
request.headers.addAll({'Authorization': await getAuthHeader()});
request.fields.addAll({'persona_data': jsonEncode(personaData)});
print(jsonEncode(personaData));
Expand All @@ -500,13 +526,21 @@ Future<Map> createPersonaApp(File file, Map<String, dynamic> personaData) async
}
}

Future<bool> updatePersonaApp(File? file, Map<String, dynamic> personaData) async {
Future<bool> updatePersonaApp(XFile? file, Map<String, dynamic> personaData) async {
var request = http.MultipartRequest(
'PATCH',
Uri.parse('${Env.apiBaseUrl}v1/personas/${personaData['id']}'),
);
if (file != null) {
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(
http.MultipartFile.fromBytes(
'file',
await file.readAsBytes(),
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
filename: filename,
),
);
}
request.headers.addAll({'Authorization': await getAuthHeader()});
request.fields.addAll({'persona_data': jsonEncode(personaData)});
Expand Down
27 changes: 22 additions & 5 deletions app/lib/backend/http/api/conversations.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'package:omi/backend/http/shared.dart';
import 'package:omi/backend/schema/conversation.dart';
import 'package:omi/backend/schema/structured.dart';
import 'package:omi/backend/schema/transcript_segment.dart';
import 'package:omi/env/env.dart';
import 'package:http/http.dart' as http;
import 'package:instabug_flutter/instabug_flutter.dart';
import 'package:omi/utils/omi_file/omi_file.dart';
import 'package:path/path.dart';

Future<CreateConversationResponse?> processInProgressConversation() async {
Expand Down Expand Up @@ -300,13 +303,19 @@ Future<bool> deleteConversationActionItem(String conversationId, ActionItem item
}

//this is expected to return complete memories
Future<List<ServerConversation>> sendStorageToBackend(File file, String sdCardDateTimeString) async {
Future<List<ServerConversation>> sendStorageToBackend(XFile file, String sdCardDateTimeString) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}sdcard_memory?date_time=$sdCardDateTimeString'),
);
request.headers.addAll({'Authorization': await getAuthHeader()});
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(http.MultipartFile.fromBytes(
'file',
await file.readAsBytes(),
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
filename: filename,
));
try {
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
Expand All @@ -330,13 +339,21 @@ Future<List<ServerConversation>> sendStorageToBackend(File file, String sdCardDa
}
}

Future<SyncLocalFilesResponse> syncLocalFiles(List<File> files) async {
Future<SyncLocalFilesResponse> syncLocalFiles(List<OmiFile> files) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v1/sync-local-files'),
);
for (var file in files) {
request.files.add(await http.MultipartFile.fromPath('files', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(
http.MultipartFile.fromBytes(
'files',
await file.readAsBytes(),
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
filename: filename,
),
);
}
request.headers.addAll({'Authorization': await getAuthHeader()});

Expand Down
77 changes: 56 additions & 21 deletions app/lib/backend/http/api/messages.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'package:omi/backend/http/shared.dart';
import 'package:omi/backend/schema/message.dart';
import 'package:omi/env/env.dart';
import 'package:omi/utils/logger.dart';
import 'package:omi/utils/omi_file/omi_file.dart';
import 'package:omi/utils/other/string_utils.dart';
import 'package:http/http.dart' as http;
import 'package:instabug_flutter/instabug_flutter.dart';
Expand Down Expand Up @@ -110,25 +113,36 @@ Stream<ServerMessageChunk> sendMessageStreamServer(String text, {String? appId,
}

try {
final request = await HttpClient().postUrl(Uri.parse(url));
request.headers.set('Authorization', await getAuthHeader());
request.headers.contentType = ContentType.json;
request.write(jsonEncode({'text': text, 'file_ids': filesId}));
final uri = Uri.parse(url);
final headers = {
'Authorization': await getAuthHeader(),
'Content-Type': 'application/json',
};
final body = jsonEncode({'text': text, 'file_ids': filesId});

final response = await request.close();
// Create a client to handle the streamed response
var client = http.Client();
var request = http.Request('POST', uri);
request.headers.addAll(headers);
request.body = body;

var response = await client.send(request);

if (response.statusCode != 200) {
Logger.error('Failed to send message: ${response.statusCode}');
yield ServerMessageChunk.failedMessage();
client.close();
return;
}

var buffers = <String>[];
var messageId = "1000"; // Default new message
await for (var data in response.transform(utf8.decoder)) {
var lines = data.split('\n\n');
var buffers = <String>[];

// Process the streamed response
await for (var data in response.stream.transform(utf8.decoder)) {
var lines = data.split('\n\n'); // Make sure this is the correct delimiter for your server responses
for (var line in lines.where((line) => line.isNotEmpty)) {
// Dealing w/ the package spliting by 1024 bytes in dart
// Dealing w/ the package splitting by certain byte size in http package
// Waiting for the next package
if (line.length >= 1024) {
buffers.add(line);
Expand Down Expand Up @@ -156,6 +170,8 @@ Stream<ServerMessageChunk> sendMessageStreamServer(String text, {String? appId,
yield messageChunk;
}
}

client.close();
} catch (e) {
Logger.error('Error sending message: $e');
yield ServerMessageChunk.failedMessage();
Expand All @@ -178,13 +194,19 @@ Future<ServerMessage> getInitialAppMessage(String? appId) {
});
}

Stream<ServerMessageChunk> sendVoiceMessageStreamServer(List<File> files) async* {
Stream<ServerMessageChunk> sendVoiceMessageStreamServer(List<XFile> files) async* {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v2/voice-messages'),
);
for (var file in files) {
request.files.add(await http.MultipartFile.fromPath('files', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(http.MultipartFile.fromBytes(
'files',
await file.readAsBytes(),
filename: filename,
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
));
}
request.headers.addAll({'Authorization': await getAuthHeader()});

Expand Down Expand Up @@ -235,13 +257,21 @@ Stream<ServerMessageChunk> sendVoiceMessageStreamServer(List<File> files) async*
}
}

Future<List<ServerMessage>> sendVoiceMessageServer(List<File> files) async {
Future<List<ServerMessage>> sendVoiceMessageServer(List<XFile> files) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v1/voice-messages'),
);
for (var file in files) {
request.files.add(await http.MultipartFile.fromPath('files', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(
http.MultipartFile.fromBytes(
'files',
await file.readAsBytes(),
filename: filename,
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
),
);
}
request.headers.addAll({'Authorization': await getAuthHeader()});

Expand All @@ -261,7 +291,7 @@ Future<List<ServerMessage>> sendVoiceMessageServer(List<File> files) async {
}
}

Future<List<MessageFile>?> uploadFilesServer(List<File> files, {String? appId}) async {
Future<List<MessageFile>?> uploadFilesServer(List<XFile> files, {String? appId}) async {
var url = '${Env.apiBaseUrl}v1/files?plugin_id=$appId';
if (appId == null || appId.isEmpty || appId == 'null' || appId == 'no_selected') {
url = '${Env.apiBaseUrl}v1/files';
Expand Down Expand Up @@ -312,20 +342,25 @@ Future reportMessageServer(String messageId) async {
}
}


Future<String> transcribeVoiceMessage(File audioFile) async {
Future<String> transcribeVoiceMessage(OmiFile audioFile) async {
try {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v1/voice-message/transcribe'),
);

request.headers.addAll({'Authorization': await getAuthHeader()});
request.files.add(await http.MultipartFile.fromPath('files', audioFile.path));

String filename = basename(audioFile.path);
request.files.add(http.MultipartFile.fromBytes(
'files',
await audioFile.readAsBytes(),
filename: filename,
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
));

var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);

if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['transcript'] ?? '';
Expand Down
14 changes: 11 additions & 3 deletions app/lib/backend/http/api/speech_profile.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'package:omi/backend/http/shared.dart';
import 'package:omi/env/env.dart';
import 'package:http/http.dart' as http;
Expand Down Expand Up @@ -35,12 +37,18 @@ Future<String?> getUserSpeechProfile() async {
return null;
}

Future<bool> uploadProfile(File file) async {
Future<bool> uploadProfile(XFile file) async {
var request = http.MultipartRequest(
'POST',
Uri.parse('${Env.apiBaseUrl}v3/upload-audio'),
);
request.files.add(await http.MultipartFile.fromPath('file', file.path, filename: basename(file.path)));
String filename = basename(file.path);
request.files.add(http.MultipartFile.fromBytes(
'file',
await file.readAsBytes(),
contentType: MediaType.parse(lookupMimeType(filename) ?? 'application/octet-stream'),
filename: filename,
));
request.headers.addAll({'Authorization': await getAuthHeader()});

try {
Expand Down
Loading