Skip to content

Commit

Permalink
Processing memory with status, capturing to, get list and more. (#930)
Browse files Browse the repository at this point in the history
  • Loading branch information
beastoin authored Sep 28, 2024
2 parents d4cc128 + d0a8e69 commit 067d2ef
Show file tree
Hide file tree
Showing 20 changed files with 897 additions and 285 deletions.
18 changes: 18 additions & 0 deletions app/lib/backend/http/api/memories.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,24 @@ Future<List<ServerMemory>> getMemories({int limit = 50, int offset = 0}) async {
return [];
}

Future<List<ServerProcessingMemory>> getProcessingMemories(
{List<String> filterIds = const [], int limit = 5, int offset = 0}) async {
var url = '${Env.apiBaseUrl}v1/processing-memories?filter_ids=${filterIds.join(",")}&limit=$limit&offset=$offset';
var response = await makeApiCall(url: url, headers: {}, method: 'GET', body: '');
if (response == null) return [];
if (response.statusCode == 200) {
// decode body bytes to utf8 string and then parse json so as to avoid utf8 char issues
var body = utf8.decode(response.bodyBytes);
var memories =
(jsonDecode(body)["result"] as List<dynamic>).map((memory) => ServerProcessingMemory.fromJson(memory)).toList();
debugPrint('getProcessingMemories length: ${memories.length}');
return memories;
} else {
debugPrint("[API-Error] $url - ${response.statusCode}");
}
return [];
}

Future<ServerMemory?> reProcessMemoryServer(String memoryId) async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/memories/$memoryId/reprocess',
Expand Down
29 changes: 26 additions & 3 deletions app/lib/backend/http/api/processing_memories.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,13 @@ Future<UpdateProcessingMemoryResponse?> updateProcessingMemoryServer({
bodyData.addAll({"geolocation": geolocation.toJson()});
}

debugPrint(jsonEncode(bodyData));

var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/processing-memories/$id',
headers: {},
method: 'PATCH',
body: jsonEncode(bodyData),
);
if (response == null) return null;
debugPrint('updateProcessingMemoryServer: ${response.body}');
if (response.statusCode == 200) {
return UpdateProcessingMemoryResponse.fromJson(jsonDecode(response.body));
} else {
Expand All @@ -46,3 +43,29 @@ Future<UpdateProcessingMemoryResponse?> updateProcessingMemoryServer({
}
return null;
}

Future<ProcessingMemoryResponse?> fetchProcessingMemoryServer({
required String id,
}) async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/processing-memories/$id',
headers: {},
method: 'GET',
body: "",
);
if (response == null) return null;
if (response.statusCode == 200) {
return ProcessingMemoryResponse.fromJson(jsonDecode(response.body));
} else {
// TODO: Server returns 304 doesn't recover
CrashReporting.reportHandledCrash(
Exception('Failed to create memory'),
StackTrace.current,
level: NonFatalExceptionLevel.info,
userAttributes: {
'response': response.body,
},
);
}
return null;
}
50 changes: 50 additions & 0 deletions app/lib/backend/schema/memory.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:math';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:friend_private/backend/schema/geolocation.dart';
import 'package:friend_private/backend/schema/message.dart';
Expand Down Expand Up @@ -57,22 +58,52 @@ class MemoryPostProcessing {
toJson() => {'status': status.toString().split('.').last, 'model': model.toString().split('.').last};
}

enum ServerProcessingMemoryStatus {
capturing('capturing'),
processing('processing'),
done('done'),
unknown('unknown'),
;

final String value;
const ServerProcessingMemoryStatus(this.value);

static ServerProcessingMemoryStatus valuesFromString(String value) {
return ServerProcessingMemoryStatus.values.firstWhereOrNull((e) => e.value == value) ??
ServerProcessingMemoryStatus.unknown;
}
}

class ServerProcessingMemory {
final String id;
final DateTime createdAt;
final DateTime? startedAt;
final DateTime? capturingTo;
final ServerProcessingMemoryStatus? status;
final List<TranscriptSegment> transcriptSegments;
final String? memoryId;

ServerProcessingMemory({
required this.id,
required this.createdAt,
this.startedAt,
this.capturingTo,
this.status,
this.transcriptSegments = const [],
this.memoryId,
});

factory ServerProcessingMemory.fromJson(Map<String, dynamic> json) {
return ServerProcessingMemory(
id: json['id'],
createdAt: DateTime.parse(json['created_at']).toLocal(),
startedAt: json['started_at'] != null ? DateTime.parse(json['started_at']).toLocal() : null,
capturingTo: json['capturing_to'] != null ? DateTime.parse(json['capturing_to']).toLocal() : null,
status: json['status'] != null ? ServerProcessingMemoryStatus.valuesFromString(json['status']) : null,
transcriptSegments: ((json['transcript_segments'] ?? []) as List<dynamic>)
.map((segment) => TranscriptSegment.fromJson(segment))
.toList(),
memoryId: json['memory_id'],
);
}

Expand All @@ -81,6 +112,10 @@ class ServerProcessingMemory {
'id': id,
'created_at': createdAt.toUtc().toIso8601String(),
'started_at': startedAt?.toUtc().toIso8601String(),
'capturing_to': capturingTo?.toUtc().toIso8601String(),
'status': status.toString(),
'transcript_segments': transcriptSegments.map((segment) => segment.toJson()).toList(),
'memory_id': memoryId,
};
}

Expand All @@ -97,6 +132,18 @@ class ServerProcessingMemory {
}
}

class ProcessingMemoryResponse {
final ServerProcessingMemory? result;

ProcessingMemoryResponse({required this.result});

factory ProcessingMemoryResponse.fromJson(Map<String, dynamic> json) {
return ProcessingMemoryResponse(
result: json['result'] != null ? ServerProcessingMemory.fromJson(json['result']) : null,
);
}
}

class UpdateProcessingMemoryResponse {
final ServerProcessingMemory? result;

Expand Down Expand Up @@ -135,6 +182,9 @@ class ServerMemory {
final bool failed;
int retries;

// local label
bool isNew = false;

ServerMemory({
required this.id,
required this.createdAt,
Expand Down
6 changes: 6 additions & 0 deletions app/lib/backend/schema/message_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enum MessageEventType {
memoryPostProcessingSuccess('memory_post_processing_success'),
memoryPostProcessingFailed('memory_post_processing_failed'),
newProcessingMemoryCreated('new_processing_memory_created'),
processingMemoryStatusChanged('processing_memory_status_changed'),
ping('ping'),
unknown('unknown'),
;
Expand All @@ -26,13 +27,15 @@ class ServerMessageEvent {
String? processingMemoryId;
ServerMemory? memory;
List<ServerMessage>? messages;
ServerProcessingMemoryStatus? processingMemoryStatus;

ServerMessageEvent(
this.type,
this.memoryId,
this.processingMemoryId,
this.memory,
this.messages,
this.processingMemoryStatus,
);

static ServerMessageEvent fromJson(Map<String, dynamic> json) {
Expand All @@ -42,6 +45,9 @@ class ServerMessageEvent {
json['processing_memory_id'],
json['memory'] != null ? ServerMemory.fromJson(json['memory']) : null,
((json['messages'] ?? []) as List<dynamic>).map((message) => ServerMessage.fromJson(message)).toList(),
json['processing_memory_status'] != null
? ServerProcessingMemoryStatus.valuesFromString(json['processing_memory_status'])
: null,
);
}
}
1 change: 0 additions & 1 deletion app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
debugPrint("App > lifecycle changed $state");
if (state == AppLifecycleState.detached) {
_deinit();
}
Expand Down
1 change: 1 addition & 0 deletions app/lib/pages/memories/page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class _MemoriesPageState extends State<MemoriesPage> with AutomaticKeepAliveClie
const SliverToBoxAdapter(child: SizedBox(height: 32)),
const SliverToBoxAdapter(child: SpeechProfileCardWidget()),
SliverToBoxAdapter(child: getMemoryCaptureWidget()),
getProcessingMemoriesWidget(memoryProvider.processingMemories),
if (memoryProvider.groupedMemories.isEmpty && !memoryProvider.isLoadingMemories)
const SliverToBoxAdapter(
child: Center(
Expand Down
37 changes: 0 additions & 37 deletions app/lib/pages/memories/widgets/capture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,50 +77,13 @@ class LiteCaptureWidgetState extends State<LiteCaptureWidget>
super.dispose();
}

// TODO: use connection directly
Future<BleAudioCodec> _getAudioCodec(String deviceId) async {
var connection = await ServiceManager.instance().device.ensureConnection(deviceId);
if (connection == null) {
return BleAudioCodec.pcm8;
}
return connection.getAudioCodec();
}
// Future requestLocationPermission() async {
// LocationService locationService = LocationService();
// bool serviceEnabled = await locationService.enableService();
// if (!serviceEnabled) {
// debugPrint('Location service not enabled');
// if (mounted) {
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text(
// 'Location services are disabled. Enable them for a better experience.',
// style: TextStyle(color: Colors.white, fontSize: 14),
// ),
// ),
// );
// }
// } else {
// PermissionStatus permissionGranted = await locationService.requestPermission();
// SharedPreferencesUtil().locationEnabled = permissionGranted == PermissionStatus.granted;
// MixpanelManager().setUserProperty('Location Enabled', SharedPreferencesUtil().locationEnabled);
// if (permissionGranted == PermissionStatus.denied) {
// debugPrint('Location permission not granted');
// } else if (permissionGranted == PermissionStatus.deniedForever) {
// debugPrint('Location permission denied forever');
// if (mounted) {
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text(
// 'If you change your mind, you can enable location services in your device settings.',
// style: TextStyle(color: Colors.white, fontSize: 14),
// ),
// ),
// );
// }
// }
// }
// }

@override
Widget build(BuildContext context) {
Expand Down
17 changes: 13 additions & 4 deletions app/lib/pages/memories/widgets/memory_list_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class _MemoryListItemState extends State<MemoryListItem> {
onTap: () async {
MixpanelManager().memoryListItemClicked(widget.memory, widget.memoryIdx);
context.read<MemoryDetailProvider>().updateMemory(widget.memoryIdx, widget.date);
Provider.of<MemoryProvider>(context, listen: false).onMemoryTap(widget.memoryIdx);
routeToPage(
context,
MemoryDetailPage(memory: widget.memory, isFromOnboarding: widget.isFromOnboarding),
Expand All @@ -46,10 +47,18 @@ class _MemoryListItemState extends State<MemoryListItem> {
EdgeInsets.only(top: 12, left: widget.isFromOnboarding ? 0 : 16, right: widget.isFromOnboarding ? 0 : 16),
child: Container(
width: double.maxFinite,
decoration: BoxDecoration(
color: Colors.grey.shade900,
borderRadius: BorderRadius.circular(16.0),
),
decoration: widget.memory.isNew
? BoxDecoration(
color: Colors.grey.shade900,
borderRadius: BorderRadius.circular(16.0),
border: Border.all(
color: Colors.lightBlue,
width: 1,
))
: BoxDecoration(
color: Colors.grey.shade900,
borderRadius: BorderRadius.circular(16.0),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Dismissible(
Expand Down
Loading

0 comments on commit 067d2ef

Please sign in to comment.