Skip to content
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

Merged
merged 6 commits into from
Oct 9, 2024
Merged
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
10 changes: 8 additions & 2 deletions app/lib/backend/preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Comment on lines 400 to 403
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The setter for wals is missing null safety checks. If a null list is passed, it will cause a NullPointerException at the map function.

- set wals(List<Wal> wals) {
-   final List<String> value = wals.map((e) => jsonEncode(e.toJson())).toList();
-   saveStringList('wals', value);
- }
+ set wals(List<Wal> wals) {
+   if (wals != null) {
+     final List<String> value = wals.map((e) => jsonEncode(e.toJson())).toList();
+     saveStringList('wals', value);
+   } else {
+     saveStringList('wals', null);
+   }
+ }


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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

Similar to the setter, the getter for wals should also have null safety checks. If getStringList('wals') returns null, it will cause a NullPointerException at the map function.

- 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;
}
30 changes: 3 additions & 27 deletions app/lib/pages/memories/page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -67,7 +68,7 @@ class _MemoriesPageState extends State<MemoriesPage> with AutomaticKeepAliveClie

@override
Widget build(BuildContext context) {
print('building memories page');
debugPrint('building memories page');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The use of debugPrint instead of print is a good practice in Flutter, especially for logging during development. It allows you to turn off these logs in production by simply setting debugPrint = null;. However, it's important to note that this change doesn't affect the functionality of the code.

-    print('building memories page');
+    debugPrint('building memories page');

super.build(context);
return Consumer<MemoryProvider>(builder: (context, memoryProvider, child) {
return RefreshIndicator(
Expand All @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The introduction of LocalSyncWidget seems to replace a significant block of UI logic previously present in this file. This is a good move towards modularity and maintainability as it encapsulates the local sync related UI and logic into its own widget. However, without seeing the implementation of LocalSyncWidget, I can't comment on whether it correctly replicates the replaced functionality. Please ensure that LocalSyncWidget correctly handles all the cases previously handled here.

-            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)
Expand Down
118 changes: 118 additions & 0 deletions app/lib/pages/memories/widgets/local_sync.dart
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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The super.key in the constructor of LocalSyncWidget is not defined. It should be replaced with Key? key and passed to the super class.

-  const LocalSyncWidget({super.key});
+  const LocalSyncWidget({Key? key}) : super(key: key);

}

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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

Good practice to cancel timers in the dispose method to prevent memory leaks.


@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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The logic for setting _status and _missSeconds seems to be a bit convoluted. It might be more maintainable if you encapsulate this logic into separate methods, each responsible for determining a specific status. This would make the code easier to read and test.

-      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 _updateStatus method like:

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();
});
}
}
22 changes: 22 additions & 0 deletions app/lib/pages/settings/developer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,28 @@ class __DeveloperSettingsPageState extends State<_DeveloperSettingsPage> {
decoration: _getTextFieldDecoration('Endpoint URL'),
style: const TextStyle(color: Colors.white),
),
const SizedBox(height: 16),
Divider(color: Colors.grey.shade500),
const SizedBox(height: 32),
const Text(
'Experimental',
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600),
),
const SizedBox(height: 8),
Text(
'Try the latest experimental features from Omi Team.',
style: TextStyle(color: Colors.grey.shade200, fontSize: 14),
),
const SizedBox(height: 16.0),
CheckboxListTile(
contentPadding: const EdgeInsets.all(0),
title: const Text(
'Local Sync',
style: TextStyle(color: Colors.white, fontSize: 16),
),
value: provider.localSyncEnabled,
onChanged: provider.onLocalSyncEnabledChanged,
),
const SizedBox(height: 64),
],
),
Expand Down
42 changes: 35 additions & 7 deletions app/lib/providers/capture_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The import of pure_socket.dart has been added. Ensure that this new dependency is properly managed and does not introduce any breaking changes or conflicts with existing code.

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';
Expand All @@ -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';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The addition of internet_connection_checker_plus.dart indicates the introduction of internet connection status monitoring. Make sure to handle potential exceptions or errors that might occur during the checking process.

import 'package:permission_handler/permission_handler.dart';
import 'package:uuid/uuid.dart';

Expand All @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The initialization of _isWalSupported and _internetStatusListener has been added, along with a listener for internet status changes. It's important to ensure that these listeners are properly disposed of when they're no longer needed to prevent memory leaks. The disposal of _internetStatusListener is handled correctly in line 314.


void updateProviderInstances(MemoryProvider? mp, MessageProvider? p) {
memoryProvider = mp;
Expand Down Expand Up @@ -72,7 +85,7 @@ class CaptureProvider extends ChangeNotifier

bool _transcriptServiceReady = false;

bool get transcriptServiceReady => _transcriptServiceReady;
bool get transcriptServiceReady => _transcriptServiceReady && _internetStatus == InternetStatus.connected;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The condition for transcriptServiceReady now includes a check for internet connectivity. This could potentially lead to unexpected behavior if other parts of the code rely on transcriptServiceReady without considering internet connectivity. Ensure that this change is reflected throughout the codebase where necessary.


bool get recordingDeviceServiceReady => _recordingDevice != null || recordingState == RecordingState.record;

Expand Down Expand Up @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

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 SharedPreferencesUtil().localSyncEnabled. Make sure that these changes align with the intended functionality and that the new time threshold doesn't negatively impact user experience.

if (_isWalSupported) {
_walService.onByteStream(value);
}

Expand All @@ -174,7 +190,7 @@ class CaptureProvider extends ChangeNotifier
_socket?.send(trimmedValue);

// synced
if (isWalEnabled) {
if (_isWalSupported) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The condition for syncing bytes has been updated to use _isWalSupported instead of isWalEnabled. Ensure that this change is consistent with the intended logic.

_walService.onBytesSync(value);
}
}
Expand Down Expand Up @@ -295,6 +311,7 @@ class CaptureProvider extends ChangeNotifier
_bleBytesStream?.cancel();
_socket?.unsubscribe(this);
_keepAliveTimer?.cancel();
_internetStatusListener?.cancel();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The cancellation of _internetStatusListener has been added to the dispose() method. This is a good practice as it prevents potential memory leaks.

super.dispose();
}

Expand Down Expand Up @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

New methods onInternetSatusChanged and setIsWalSupported have been added. These methods update the respective variables and notify listeners of the changes. This is a good practice as it ensures that any changes to these variables are propagated throughout the application. However, there's a typo in onInternetSatusChanged - it should be onInternetStatusChanged. Here's the corrected code:

- void onInternetSatusChanged(InternetStatus status) {
+ void onInternetStatusChanged(InternetStatus status) {
    debugPrint("[SocketService] Internet connection changed $status");
    _internetStatus = status;
    notifyListeners();
  }


/*
*
*
Expand Down
14 changes: 14 additions & 0 deletions app/lib/providers/developer_mode_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The initialize() method is not asynchronous, but it's calling SharedPreferencesUtil() which might involve disk I/O operations. This could potentially block the main thread and degrade the app performance. Consider making this method asynchronous and use await with SharedPreferencesUtil() calls.

-   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());
Expand All @@ -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,
Expand All @@ -62,4 +71,9 @@ class DeveloperModeProvider extends BaseProvider {
'Settings saved!',
);
}

void onLocalSyncEnabledChanged(var value) {
localSyncEnabled = value;
notifyListeners();
}
Comment on lines +75 to +78
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The onLocalSyncEnabledChanged method does not validate the input value before assigning it to localSyncEnabled. It's a good practice to validate inputs in setter methods to prevent potential issues. If value is expected to be a boolean, consider adding a type check.

-  void onLocalSyncEnabledChanged(var value) {
+  void onLocalSyncEnabledChanged(bool value) {
     if (value is bool) {
       localSyncEnabled = value;
       notifyListeners();
     } else {
       throw ArgumentError('Expected a boolean value');
     }
   }

}
4 changes: 1 addition & 3 deletions app/lib/services/sockets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ class SocketServicePool extends ISocketService {
TranscriptSegmentSocketService? _socket;

@override
void start() {
// TODO: implement start
}
void start() {}

@override
void stop() async {
Expand Down
13 changes: 12 additions & 1 deletion app/lib/utils/other/string_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,15 @@ String extractJson(String input) {
return input.substring(startIndex, endIndex + 1);
}
return '';
}
}

String convertToHHMMSS(int seconds) {
int hours = seconds ~/ 3600;
int minutes = (seconds % 3600) ~/ 60;
int remainingSeconds = seconds % 60;

String twoDigits(int n) => n.toString().padLeft(2, '0');

return '${twoDigits(hours)}:${twoDigits(minutes)}:${twoDigits(remainingSeconds)}';
}

Loading