websocket.provider.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import 'dart:convert';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:hive/hive.dart';
  4. import 'package:hooks_riverpod/hooks_riverpod.dart';
  5. import 'package:immich_mobile/constants/hive_box.dart';
  6. import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
  7. import 'package:immich_mobile/shared/providers/asset.provider.dart';
  8. import 'package:openapi/api.dart';
  9. import 'package:socket_io_client/socket_io_client.dart';
  10. class WebscoketState {
  11. final Socket? socket;
  12. final bool isConnected;
  13. WebscoketState({
  14. this.socket,
  15. required this.isConnected,
  16. });
  17. WebscoketState copyWith({
  18. Socket? socket,
  19. bool? isConnected,
  20. }) {
  21. return WebscoketState(
  22. socket: socket ?? this.socket,
  23. isConnected: isConnected ?? this.isConnected,
  24. );
  25. }
  26. @override
  27. String toString() =>
  28. 'WebscoketState(socket: $socket, isConnected: $isConnected)';
  29. @override
  30. bool operator ==(Object other) {
  31. if (identical(this, other)) return true;
  32. return other is WebscoketState &&
  33. other.socket == socket &&
  34. other.isConnected == isConnected;
  35. }
  36. @override
  37. int get hashCode => socket.hashCode ^ isConnected.hashCode;
  38. }
  39. class WebsocketNotifier extends StateNotifier<WebscoketState> {
  40. WebsocketNotifier(this.ref)
  41. : super(WebscoketState(socket: null, isConnected: false)) {
  42. debugPrint("Init websocket instance");
  43. }
  44. final Ref ref;
  45. connect() {
  46. var authenticationState = ref.read(authenticationProvider);
  47. if (authenticationState.isAuthenticated) {
  48. var accessToken = Hive.box(userInfoBox).get(accessTokenKey);
  49. var endpoint = Hive.box(userInfoBox).get(serverEndpointKey);
  50. try {
  51. debugPrint("[WEBSOCKET] Attempting to connect to ws");
  52. // Configure socket transports must be sepecified
  53. Socket socket = io(
  54. endpoint.toString().replaceAll('/api', ''),
  55. OptionBuilder()
  56. .setPath('/api/socket.io')
  57. .setTransports(['websocket'])
  58. .enableReconnection()
  59. .enableForceNew()
  60. .enableForceNewConnection()
  61. .enableAutoConnect()
  62. .setExtraHeaders({"Authorization": "Bearer $accessToken"})
  63. .build(),
  64. );
  65. socket.onConnect((_) {
  66. debugPrint("[WEBSOCKET] Established Websocket Connection");
  67. state = WebscoketState(isConnected: true, socket: socket);
  68. });
  69. socket.onDisconnect((_) {
  70. debugPrint("[WEBSOCKET] Disconnect to Websocket Connection");
  71. state = WebscoketState(isConnected: false, socket: null);
  72. });
  73. socket.on('error', (errorMessage) {
  74. debugPrint("Webcoket Error - $errorMessage");
  75. state = WebscoketState(isConnected: false, socket: null);
  76. });
  77. socket.on('on_upload_success', (data) {
  78. var jsonString = jsonDecode(data.toString());
  79. AssetResponseDto? newAsset = AssetResponseDto.fromJson(jsonString);
  80. if (newAsset != null) {
  81. ref.watch(assetProvider.notifier).onNewAssetUploaded(newAsset);
  82. }
  83. });
  84. } catch (e) {
  85. debugPrint("[WEBSOCKET] Catch Websocket Error - ${e.toString()}");
  86. }
  87. }
  88. }
  89. disconnect() {
  90. debugPrint("[WEBSOCKET] Attempting to disconnect");
  91. var socket = state.socket?.disconnect();
  92. if (socket?.disconnected == true) {
  93. state = WebscoketState(isConnected: false, socket: null);
  94. }
  95. }
  96. stopListenToEvent(String eventName) {
  97. debugPrint("[Websocket] Stop listening to event $eventName");
  98. state.socket?.off(eventName);
  99. }
  100. listenUploadEvent() {
  101. debugPrint("[Websocket] Start listening to event on_upload_success");
  102. state.socket?.on('on_upload_success', (data) {
  103. var jsonString = jsonDecode(data.toString());
  104. AssetResponseDto? newAsset = AssetResponseDto.fromJson(jsonString);
  105. if (newAsset != null) {
  106. ref.watch(assetProvider.notifier).onNewAssetUploaded(newAsset);
  107. }
  108. });
  109. }
  110. }
  111. final websocketProvider =
  112. StateNotifierProvider<WebsocketNotifier, WebscoketState>((ref) {
  113. return WebsocketNotifier(ref);
  114. });