1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-17 12:22:31 +02:00
immich/mobile/lib/shared/providers/websocket.provider.dart
Zack Pollard 1a3d05ffc3
chore: improve default setup (#234)
* chore: remove UPLOAD_LOCATION as it isn't used in the server

* docker: remove network in docker compose as docker creates one by default

* nginx: update reverse proxy to put web at root and api at /api

* docker: remove unneeded exposed ports and docker network

Align dev setup with prod, but with ports exposed for direct connection
Most communication between services happens on the internal network, so we don't need to expose all these services.
With the nginx changes, the api and web panel are both server through the reverse proxy on / for web and /api for the API.
The only service that should expose ports is nginx as that is the entrypoint to the application.

* chore: remove CORS now we serve the api on /api in the default setup

* docs: update README.md to include /api

* Fixed docket-compose file for dev environment and websocket on web and mobile

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2022-06-23 22:18:50 -05:00

128 lines
4.0 KiB
Dart

import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/shared/models/immich_asset.model.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:socket_io_client/socket_io_client.dart';
class WebscoketState {
final Socket? socket;
final bool isConnected;
WebscoketState({
this.socket,
required this.isConnected,
});
WebscoketState copyWith({
Socket? socket,
bool? isConnected,
}) {
return WebscoketState(
socket: socket ?? this.socket,
isConnected: isConnected ?? this.isConnected,
);
}
@override
String toString() => 'WebscoketState(socket: $socket, isConnected: $isConnected)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is WebscoketState && other.socket == socket && other.isConnected == isConnected;
}
@override
int get hashCode => socket.hashCode ^ isConnected.hashCode;
}
class WebsocketNotifier extends StateNotifier<WebscoketState> {
WebsocketNotifier(this.ref) : super(WebscoketState(socket: null, isConnected: false)) {
debugPrint("Init websocket instance");
}
final Ref ref;
connect() {
var authenticationState = ref.read(authenticationProvider);
if (authenticationState.isAuthenticated) {
var accessToken = Hive.box(userInfoBox).get(accessTokenKey);
var endpoint = Hive.box(userInfoBox).get(serverEndpointKey);
try {
debugPrint("[WEBSOCKET] Attempting to connect to ws");
// Configure socket transports must be sepecified
Socket socket = io(
endpoint.toString().replaceAll('/api', ''),
OptionBuilder()
.setPath('/api/socket.io')
.setTransports(['websocket'])
.enableReconnection()
.enableForceNew()
.enableForceNewConnection()
.enableAutoConnect()
.setExtraHeaders({"Authorization": "Bearer $accessToken"})
.build(),
);
socket.onConnect((_) {
debugPrint("[WEBSOCKET] Established Websocket Connection");
state = WebscoketState(isConnected: true, socket: socket);
});
socket.onDisconnect((_) {
debugPrint("[WEBSOCKET] Disconnect to Websocket Connection");
state = WebscoketState(isConnected: false, socket: null);
});
socket.on('error', (errorMessage) {
debugPrint("Webcoket Error - $errorMessage");
state = WebscoketState(isConnected: false, socket: null);
});
socket.on('on_upload_success', (data) {
var jsonString = jsonDecode(data.toString());
ImmichAsset newAsset = ImmichAsset.fromMap(jsonString);
ref.watch(assetProvider.notifier).onNewAssetUploaded(newAsset);
});
} catch (e) {
debugPrint("[WEBSOCKET] Catch Websocket Error - ${e.toString()}");
}
}
}
disconnect() {
debugPrint("[WEBSOCKET] Attempting to disconnect");
var socket = state.socket?.disconnect();
if (socket != null) {
if (socket.disconnected) {
state = WebscoketState(isConnected: false, socket: null);
}
}
}
stopListenToEvent(String eventName) {
debugPrint("[Websocket] Stop listening to event $eventName");
state.socket?.off(eventName);
}
listenUploadEvent() {
debugPrint("[Websocket] Start listening to event on_upload_success");
state.socket?.on('on_upload_success', (data) {
var jsonString = jsonDecode(data.toString());
ImmichAsset newAsset = ImmichAsset.fromMap(jsonString);
ref.watch(assetProvider.notifier).onNewAssetUploaded(newAsset);
});
}
}
final websocketProvider = StateNotifierProvider<WebsocketNotifier, WebscoketState>((ref) {
return WebsocketNotifier(ref);
});