|
|
|
|
@ -1,3 +1,4 @@
|
|
|
|
|
import 'dart:async';
|
|
|
|
|
import 'dart:convert';
|
|
|
|
|
|
|
|
|
|
import 'package:collection/collection.dart';
|
|
|
|
|
@ -10,6 +11,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|
|
|
|
import 'package:immich_mobile/models/server_info/server_version.model.dart';
|
|
|
|
|
import 'package:immich_mobile/providers/asset.provider.dart';
|
|
|
|
|
import 'package:immich_mobile/providers/auth.provider.dart';
|
|
|
|
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
|
|
|
|
import 'package:immich_mobile/providers/db.provider.dart';
|
|
|
|
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
|
|
|
|
import 'package:immich_mobile/services/api.service.dart';
|
|
|
|
|
@ -106,6 +108,18 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|
|
|
|
final Debouncer _debounce =
|
|
|
|
|
Debouncer(interval: const Duration(milliseconds: 500));
|
|
|
|
|
|
|
|
|
|
final Debouncer _batchDebouncer = Debouncer(
|
|
|
|
|
interval: const Duration(seconds: 5),
|
|
|
|
|
maxWaitTime: const Duration(seconds: 10),
|
|
|
|
|
);
|
|
|
|
|
final List<dynamic> _batchedAssetUploadReady = [];
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void dispose() {
|
|
|
|
|
_batchDebouncer.dispose();
|
|
|
|
|
super.dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Connects websocket to server unless already connected
|
|
|
|
|
void connect() {
|
|
|
|
|
if (state.isConnected) return;
|
|
|
|
|
@ -171,6 +185,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|
|
|
|
socket.on('on_asset_stack_update', _handleServerUpdates);
|
|
|
|
|
socket.on('on_asset_hidden', _handleOnAssetHidden);
|
|
|
|
|
socket.on('on_new_release', _handleReleaseUpdates);
|
|
|
|
|
socket.on('AssetUploadReadyV1', _handleSyncAssetUploadReady);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
debugPrint("[WEBSOCKET] Catch Websocket Error - ${e.toString()}");
|
|
|
|
|
}
|
|
|
|
|
@ -180,6 +195,8 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|
|
|
|
void disconnect() {
|
|
|
|
|
debugPrint("Attempting to disconnect from websocket");
|
|
|
|
|
|
|
|
|
|
_batchedAssetUploadReady.clear();
|
|
|
|
|
|
|
|
|
|
var socket = state.socket?.disconnect();
|
|
|
|
|
|
|
|
|
|
if (socket?.disconnected == true) {
|
|
|
|
|
@ -288,7 +305,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handlePendingChanges() async {
|
|
|
|
|
Future<void> handlePendingChanges() async {
|
|
|
|
|
await _handlePendingUploaded();
|
|
|
|
|
await _handlePendingDeletes();
|
|
|
|
|
await _handlingPendingHidden();
|
|
|
|
|
@ -347,6 +364,29 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|
|
|
|
.read(serverInfoProvider.notifier)
|
|
|
|
|
.handleNewRelease(serverVersion, releaseVersion);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _handleSyncAssetUploadReady(dynamic data) {
|
|
|
|
|
_batchedAssetUploadReady.add(data);
|
|
|
|
|
_batchDebouncer.run(_processBatchedAssetUploadReady);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _processBatchedAssetUploadReady() {
|
|
|
|
|
if (_batchedAssetUploadReady.isEmpty) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
unawaited(
|
|
|
|
|
_ref
|
|
|
|
|
.read(backgroundSyncProvider)
|
|
|
|
|
.syncWebsocketBatch(_batchedAssetUploadReady.toList()),
|
|
|
|
|
);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
_log.severe("Error processing batched AssetUploadReadyV1 events: $error");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_batchedAssetUploadReady.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final websocketProvider =
|
|
|
|
|
|