-
Notifications
You must be signed in to change notification settings - Fork 607
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
Jzecm wal local sync 958 #1010
Jzecm wal local sync 958 #1010
Changes from all commits
d919d53
eb4b0f9
9fd9fa7
b685289
f19b141
2ae9037
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -395,13 +395,19 @@ class SharedPreferencesUtil { | |
|
||
bool get locationPermissionRequested => getBool('locationPermissionRequested') ?? false; | ||
|
||
// WAL | ||
|
||
set wals(List<Wal> wals) { | ||
final List<String> value = wals.map((e) => jsonEncode(e.toJson())).toList(); | ||
saveStringList('v3/wals', value); | ||
saveStringList('wals', value); | ||
} | ||
|
||
List<Wal> get wals { | ||
final List<String> value = getStringList('v3/wals') ?? []; | ||
final List<String> value = getStringList('wals') ?? []; | ||
return Wal.fromJsonList(value.map((e) => jsonDecode(e)).toList()); | ||
} | ||
Comment on lines
+406
to
408
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the setter, the getter for - List<Wal> get wals {
- final List<String> value = getStringList('wals') ?? [];
- return Wal.fromJsonList(value.map((e) => jsonDecode(e)).toList());
- }
+ List<Wal> get wals {
+ final List<String> value = getStringList('wals');
+ if (value != null) {
+ return Wal.fromJsonList(value.map((e) => jsonDecode(e)).toList());
+ } else {
+ return null;
+ }
+ } |
||
|
||
set localSyncEnabled(bool value) => saveBool('localSyncEnabled', value); | ||
|
||
bool get localSyncEnabled => getBool('localSyncEnabled') ?? false; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ import 'package:friend_private/backend/schema/memory.dart'; | |
import 'package:friend_private/pages/capture/widgets/widgets.dart'; | ||
import 'package:friend_private/pages/memories/sync_page.dart'; | ||
import 'package:friend_private/pages/memories/widgets/date_list_item.dart'; | ||
import 'package:friend_private/pages/memories/widgets/local_sync.dart'; | ||
import 'package:friend_private/pages/memories/widgets/processing_capture.dart'; | ||
import 'package:friend_private/providers/memory_provider.dart'; | ||
import 'package:friend_private/utils/other/temp.dart'; | ||
|
@@ -67,7 +68,7 @@ class _MemoriesPageState extends State<MemoriesPage> with AutomaticKeepAliveClie | |
|
||
@override | ||
Widget build(BuildContext context) { | ||
print('building memories page'); | ||
debugPrint('building memories page'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of - print('building memories page');
+ debugPrint('building memories page'); |
||
super.build(context); | ||
return Consumer<MemoryProvider>(builder: (context, memoryProvider, child) { | ||
return RefreshIndicator( | ||
|
@@ -78,34 +79,9 @@ class _MemoriesPageState extends State<MemoriesPage> with AutomaticKeepAliveClie | |
}, | ||
child: CustomScrollView( | ||
slivers: [ | ||
SliverToBoxAdapter( | ||
child: memoryProvider.missingWalsInSeconds > 120 | ||
? GestureDetector( | ||
onTap: () { | ||
routeToPage(context, const SyncPage()); | ||
}, | ||
child: Container( | ||
width: double.maxFinite, | ||
decoration: BoxDecoration( | ||
color: Colors.grey.shade900, | ||
borderRadius: const BorderRadius.all(Radius.circular(12)), | ||
), | ||
margin: const EdgeInsets.fromLTRB(16, 18, 16, 0), | ||
padding: const EdgeInsets.all(16), | ||
child: ListTile( | ||
leading: const Icon(Icons.record_voice_over_rounded), | ||
title: Text( | ||
'You have ${secondsToHumanReadable(memoryProvider.missingWalsInSeconds)} of conversation locally, sync now?', | ||
style: const TextStyle(color: Colors.white, fontSize: 16), | ||
), | ||
), | ||
), | ||
) | ||
: const SizedBox.shrink(), | ||
), | ||
const SliverToBoxAdapter(child: SizedBox(height: 26)), | ||
const SliverToBoxAdapter(child: SpeechProfileCardWidget()), | ||
const SliverToBoxAdapter(child: UpdateFirmwareCardWidget()), | ||
const SliverToBoxAdapter(child: LocalSyncWidget()), | ||
Comment on lines
82
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The introduction of - SliverToBoxAdapter(
- child: memoryProvider.missingWalsInSeconds > 120
- ? GestureDetector(
- onTap: () {
- routeToPage(context, const SyncPage());
- },
- child: Container(
- width: double.maxFinite,
- decoration: BoxDecoration(
- color: Colors.grey.shade900,
- borderRadius: const BorderRadius.all(Radius.circular(12)),
- ),
- margin: const EdgeInsets.fromLTRB(16, 18, 16, 0),
- padding: const EdgeInsets.all(16),
- child: ListTile(
- leading: const Icon(Icons.record_voice_over_rounded),
- title: Text(
- 'You have ${secondsToHumanReadable(memoryProvider.missingWalsInSeconds)} of conversation locally, sync now?',
- style: const TextStyle(color: Colors.white, fontSize: 16),
- ),
- ),
- ),
- )
- : const SizedBox.shrink(),
- ),
- const SliverToBoxAdapter(child: SizedBox(height: 26)),
+ const SliverToBoxAdapter(child: LocalSyncWidget()), |
||
const SliverToBoxAdapter(child: MemoryCaptureWidget()), | ||
getProcessingMemoriesWidget(memoryProvider.processingMemories), | ||
if (memoryProvider.groupedMemories.isEmpty && !memoryProvider.isLoadingMemories) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import 'dart:async'; | ||
import 'dart:math'; | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:friend_private/pages/memories/page.dart'; | ||
import 'package:friend_private/pages/memories/sync_page.dart'; | ||
import 'package:friend_private/providers/capture_provider.dart'; | ||
import 'package:friend_private/providers/developer_mode_provider.dart'; | ||
import 'package:friend_private/providers/memory_provider.dart'; | ||
import 'package:friend_private/utils/other/string_utils.dart'; | ||
import 'package:friend_private/utils/other/temp.dart'; | ||
import 'package:provider/provider.dart'; | ||
|
||
class LocalSyncWidget extends StatefulWidget { | ||
const LocalSyncWidget({super.key}); | ||
|
||
@override | ||
State<LocalSyncWidget> createState() => _LocalSyncWidgetState(); | ||
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
enum LocalSyncStatus { | ||
disabled, | ||
inProgress, | ||
flush, // flushed to disk | ||
} | ||
|
||
class _LocalSyncWidgetState extends State<LocalSyncWidget> { | ||
LocalSyncStatus? _status; | ||
Timer? _missSecondsInEstTimer; | ||
int _missSeconds = 0; | ||
|
||
@override | ||
void dispose() { | ||
_missSecondsInEstTimer?.cancel(); | ||
super.dispose(); | ||
} | ||
Comment on lines
+32
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Consumer2<MemoryProvider, CaptureProvider>(builder: (context, provider, captureProvider, child) { | ||
if (provider.missingWalsInSeconds > 120) { | ||
_status = LocalSyncStatus.flush; | ||
_missSeconds = max(_missSeconds, provider.missingWalsInSeconds); // est. good for ux | ||
} else if (!captureProvider.isWalSupported) { | ||
_status = LocalSyncStatus.disabled; | ||
_missSecondsInEstTimer?.cancel(); | ||
} else if ((!captureProvider.transcriptServiceReady && captureProvider.recordingDeviceServiceReady) || | ||
provider.missingWalsInSeconds > 0) { | ||
var previousStatus = _status; | ||
_status = LocalSyncStatus.inProgress; | ||
|
||
// Change state to in progress | ||
if (previousStatus != LocalSyncStatus.inProgress) { | ||
_missSecondsInEstTimer?.cancel(); | ||
_missSeconds = provider.missingWalsInSeconds; | ||
_missSecondsInEstTimer = Timer.periodic(const Duration(seconds: 1), (t) { | ||
setState(() { | ||
_missSeconds++; | ||
}); | ||
}); | ||
} | ||
} | ||
Comment on lines
+40
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logic for setting - if (provider.missingWalsInSeconds > 120) {
- _status = LocalSyncStatus.flush;
- _missSeconds = max(_missSeconds, provider.missingWalsInSeconds); // est. good for ux
- } else if (!captureProvider.isWalSupported) {
- _status = LocalSyncStatus.disabled;
- _missSecondsInEstTimer?.cancel();
- } else if ((!captureProvider.transcriptServiceReady && captureProvider.recordingDeviceServiceReady) ||
- provider.missingWalsInSeconds > 0) {
- var previousStatus = _status;
- _status = LocalSyncStatus.inProgress;
-
- // Change state to in progress
- if (previousStatus != LocalSyncStatus.inProgress) {
- _missSecondsInEstTimer?.cancel();
- _missSeconds = provider.missingWalsInSeconds;
- _missSecondsInEstTimer = Timer.periodic(const Duration(seconds: 1), (t) {
- setState(() {
- _missSeconds++;
- });
- });
- }
- }
+ _updateStatus(provider, captureProvider); And then define void _updateStatus(MemoryProvider provider, CaptureProvider captureProvider) {
if (provider.missingWalsInSeconds > 120) {
_status = LocalSyncStatus.flush;
_missSeconds = max(_missSeconds, provider.missingWalsInSeconds); // est. good for ux
} else if (!captureProvider.isWalSupported) {
_status = LocalSyncStatus.disabled;
_missSecondsInEstTimer?.cancel();
} else if ((!captureProvider.transcriptServiceReady && captureProvider.recordingDeviceServiceReady) ||
provider.missingWalsInSeconds > 0) {
var previousStatus = _status;
_status = LocalSyncStatus.inProgress;
// Change state to in progress
if (previousStatus != LocalSyncStatus.inProgress) {
_missSecondsInEstTimer?.cancel();
_missSeconds = provider.missingWalsInSeconds;
_startMissSecondsTimer();
}
}
}
void _startMissSecondsTimer() {
_missSecondsInEstTimer = Timer.periodic(const Duration(seconds: 1), (t) {
setState(() {
_missSeconds++;
});
});
} |
||
|
||
// in progress | ||
if (_status == LocalSyncStatus.inProgress) { | ||
return Container( | ||
decoration: BoxDecoration( | ||
color: Colors.grey.shade900, | ||
borderRadius: const BorderRadius.all(Radius.circular(12)), | ||
), | ||
margin: const EdgeInsets.fromLTRB(16, 16, 16, 16), | ||
padding: const EdgeInsets.all(16), | ||
child: Text( | ||
'${convertToHHMMSS(_missSeconds)} of conversation locally', | ||
style: const TextStyle(color: Colors.white, fontSize: 16), | ||
textAlign: TextAlign.center, | ||
), | ||
); | ||
} | ||
|
||
// ready to sync | ||
if (_status == LocalSyncStatus.flush) { | ||
return GestureDetector( | ||
onTap: () { | ||
routeToPage(context, const SyncPage()); | ||
}, | ||
child: Container( | ||
decoration: BoxDecoration( | ||
color: Colors.grey.shade900, | ||
borderRadius: const BorderRadius.all(Radius.circular(12)), | ||
), | ||
margin: const EdgeInsets.fromLTRB(16, 16, 16, 16), | ||
padding: const EdgeInsets.all(16), | ||
child: Row( | ||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
children: [ | ||
Expanded( | ||
child: Row( | ||
children: [ | ||
const Icon(Icons.download_rounded), | ||
const SizedBox(width: 16), | ||
Text( | ||
'${secondsToHumanReadable(_missSeconds)} available. Sync now?', | ||
style: const TextStyle(color: Colors.white, fontSize: 16), | ||
), | ||
], | ||
), | ||
), | ||
], | ||
), | ||
), | ||
); | ||
} | ||
|
||
return const SizedBox.shrink(); | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ import 'package:friend_private/providers/message_provider.dart'; | |
import 'package:friend_private/services/devices.dart'; | ||
import 'package:friend_private/services/notifications.dart'; | ||
import 'package:friend_private/services/services.dart'; | ||
import 'package:friend_private/services/sockets/pure_socket.dart'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
import 'package:friend_private/services/sockets/sdcard_socket.dart'; | ||
import 'package:friend_private/services/sockets/transcription_connection.dart'; | ||
import 'package:friend_private/services/wals.dart'; | ||
|
@@ -25,6 +26,7 @@ import 'package:friend_private/utils/enums.dart'; | |
import 'package:friend_private/utils/logger.dart'; | ||
import 'package:friend_private/utils/memories/integrations.dart'; | ||
import 'package:friend_private/utils/memories/process.dart'; | ||
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
import 'package:permission_handler/permission_handler.dart'; | ||
import 'package:uuid/uuid.dart'; | ||
|
||
|
@@ -42,9 +44,20 @@ class CaptureProvider extends ChangeNotifier | |
|
||
ServerMemory? get inProgressMemory => _inProgressMemory; | ||
|
||
bool _walFeatureEnabled = false; | ||
IWalService get _walService => ServiceManager.instance().wal; | ||
IDeviceService get _deviceService => ServiceManager.instance().device; | ||
bool _isWalSupported = false; | ||
bool get isWalSupported => _isWalSupported; | ||
|
||
StreamSubscription<InternetStatus>? _internetStatusListener; | ||
InternetStatus? _internetStatus; | ||
get internetStatus => _internetStatus; | ||
|
||
CaptureProvider() { | ||
_internetStatusListener = PureCore().internetConnection.onStatusChange.listen((InternetStatus status) { | ||
onInternetSatusChanged(status); | ||
}); | ||
} | ||
Comment on lines
47
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The initialization of |
||
|
||
void updateProviderInstances(MemoryProvider? mp, MessageProvider? p) { | ||
memoryProvider = mp; | ||
|
@@ -72,7 +85,7 @@ class CaptureProvider extends ChangeNotifier | |
|
||
bool _transcriptServiceReady = false; | ||
|
||
bool get transcriptServiceReady => _transcriptServiceReady; | ||
bool get transcriptServiceReady => _transcriptServiceReady && _internetStatus == InternetStatus.connected; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The condition for |
||
|
||
bool get recordingDeviceServiceReady => _recordingDevice != null || recordingState == RecordingState.record; | ||
|
||
|
@@ -160,11 +173,14 @@ class CaptureProvider extends ChangeNotifier | |
|
||
// support: opus codec, 1m from the first device connectes | ||
var deviceFirstConnectedAt = _deviceService.getFirstConnectedAt(); | ||
var isWalEnabled = codec == BleAudioCodec.opus && | ||
var checkWalSupported = codec == BleAudioCodec.opus && | ||
(deviceFirstConnectedAt != null && | ||
deviceFirstConnectedAt.isBefore(DateTime.now().subtract(const Duration(seconds: 60)))) && | ||
_walFeatureEnabled; | ||
if (isWalEnabled) { | ||
deviceFirstConnectedAt.isBefore(DateTime.now().subtract(const Duration(seconds: 15)))) && | ||
SharedPreferencesUtil().localSyncEnabled; | ||
if (checkWalSupported != _isWalSupported) { | ||
setIsWalSupported(checkWalSupported); | ||
} | ||
Comment on lines
+176
to
+182
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The conditions for setting WAL support have been updated. The time threshold for device connection has been reduced from 60 seconds to 15 seconds, and there's an additional check for |
||
if (_isWalSupported) { | ||
_walService.onByteStream(value); | ||
} | ||
|
||
|
@@ -174,7 +190,7 @@ class CaptureProvider extends ChangeNotifier | |
_socket?.send(trimmedValue); | ||
|
||
// synced | ||
if (isWalEnabled) { | ||
if (_isWalSupported) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
_walService.onBytesSync(value); | ||
} | ||
} | ||
|
@@ -295,6 +311,7 @@ class CaptureProvider extends ChangeNotifier | |
_bleBytesStream?.cancel(); | ||
_socket?.unsubscribe(this); | ||
_keepAliveTimer?.cancel(); | ||
_internetStatusListener?.cancel(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
super.dispose(); | ||
} | ||
|
||
|
@@ -468,6 +485,17 @@ class CaptureProvider extends ChangeNotifier | |
notifyListeners(); | ||
} | ||
|
||
void onInternetSatusChanged(InternetStatus status) { | ||
debugPrint("[SocketService] Internet connection changed $status"); | ||
_internetStatus = status; | ||
notifyListeners(); | ||
} | ||
|
||
void setIsWalSupported(bool value) { | ||
_isWalSupported = value; | ||
notifyListeners(); | ||
} | ||
Comment on lines
+488
to
+497
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New methods - void onInternetSatusChanged(InternetStatus status) {
+ void onInternetStatusChanged(InternetStatus status) {
debugPrint("[SocketService] Internet connection changed $status");
_internetStatus = status;
notifyListeners();
} |
||
|
||
/* | ||
* | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,18 +16,24 @@ class DeveloperModeProvider extends BaseProvider { | |
bool loadingExportMemories = false; | ||
bool loadingImportMemories = false; | ||
|
||
bool localSyncEnabled = false; | ||
|
||
void initialize() { | ||
gcpCredentialsController.text = SharedPreferencesUtil().gcpCredentials; | ||
gcpBucketNameController.text = SharedPreferencesUtil().gcpBucketName; | ||
webhookOnMemoryCreated.text = SharedPreferencesUtil().webhookOnMemoryCreated; | ||
webhookOnTranscriptReceived.text = SharedPreferencesUtil().webhookOnTranscriptReceived; | ||
localSyncEnabled = SharedPreferencesUtil().localSyncEnabled; | ||
Comment on lines
+19
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The - void initialize() {
+ Future<void> initialize() async {
gcpCredentialsController.text = SharedPreferencesUtil().gcpCredentials;
gcpBucketNameController.text = SharedPreferencesUtil().gcpBucketName;
webhookOnMemoryCreated.text = SharedPreferencesUtil().webhookOnMemoryCreated;
webhookOnTranscriptReceived.text = SharedPreferencesUtil().webhookOnTranscriptReceived;
localSyncEnabled = await SharedPreferencesUtil().localSyncEnabled;
notifyListeners();
} |
||
|
||
notifyListeners(); | ||
} | ||
|
||
void saveSettings() async { | ||
if (savingSettingsLoading) return; | ||
savingSettingsLoading = true; | ||
notifyListeners(); | ||
final prefs = SharedPreferencesUtil(); | ||
|
||
if (gcpCredentialsController.text.isNotEmpty && gcpBucketNameController.text.isNotEmpty) { | ||
try { | ||
await authenticateGCP(base64: gcpCredentialsController.text.trim()); | ||
|
@@ -50,6 +56,9 @@ class DeveloperModeProvider extends BaseProvider { | |
prefs.webhookOnMemoryCreated = webhookOnMemoryCreated.text.trim(); | ||
prefs.webhookOnTranscriptReceived = webhookOnTranscriptReceived.text.trim(); | ||
|
||
// Experimental | ||
prefs.localSyncEnabled = localSyncEnabled; | ||
|
||
MixpanelManager().settingsSaved( | ||
hasGCPCredentials: prefs.gcpCredentials.isNotEmpty, | ||
hasGCPBucketName: prefs.gcpBucketName.isNotEmpty, | ||
|
@@ -62,4 +71,9 @@ class DeveloperModeProvider extends BaseProvider { | |
'Settings saved!', | ||
); | ||
} | ||
|
||
void onLocalSyncEnabledChanged(var value) { | ||
localSyncEnabled = value; | ||
notifyListeners(); | ||
} | ||
Comment on lines
+75
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The - void onLocalSyncEnabledChanged(var value) {
+ void onLocalSyncEnabledChanged(bool value) {
if (value is bool) {
localSyncEnabled = value;
notifyListeners();
} else {
throw ArgumentError('Expected a boolean value');
}
} |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setter for
wals
is missing null safety checks. If a null list is passed, it will cause aNullPointerException
at the map function.