initiateChat function

  1. @riverpod
Future<InitiateChatFunction> initiateChat(
  1. InitiateChatRef ref
)

Implementation

@riverpod
Future<InitiateChatFunction> initiateChat(InitiateChatRef ref) async {
  var qiscus = await ref.watch(qiscusProvider.future);
  var userId = ref.watch(userIdProvider);
  var displayName = ref.watch(displayNameProvider);
  var avatarUrl = ref.watch(avatarUrlProvider);
  var userProperties = ref.watch(userPropertiesProvider);
  var channelId = ref.watch(channelIdConfigProvider);
  var sdkUserExtras = ref.watch(sdkUserExtrasProvider);
  var initiateUrl = ref.watch(initiateChatUrlProvider);
  var deviceId = ref.watch(deviceIdConfigProvider);
  var deviceIdDevelopment = ref.watch(deviceIdDevelopmentModeProvider);

  var storage = ref.watch(encSharedPreferenceProvider);

  return () async {
    var nonce = await qiscus.getJWTNonce();
    var data = <String, dynamic>{
      'app_id': qiscus.appId,
      'user_id': userId,
      'nonce': nonce,
    };

    if (displayName != null) data['name'] = displayName;
    if (avatarUrl != null) data['avatar'] = avatarUrl;
    if (sdkUserExtras != null) data['sdk_user_extras'] = sdkUserExtras;
    if (userProperties != null) {
      data['user_properties'] = jsonEncode(userProperties);
    }
    if (channelId != null) data['channel_id'] = channelId;

    var secureSession = await storage
        .read(key: StorageKey.secureSession)
        .then((v) => v == null ? null : jsonDecode(v) as Map<String, dynamic>)
        .then((v) => v == null ? null : SecureSession.fromJson(v));

    print('last session: $secureSession');

    if (secureSession != null &&
        secureSession.appId == qiscus.appId &&
        secureSession.channelId == channelId &&
        secureSession.userId == userId) {
      print('got last secure session data: $secureSession');
      data['session_id'] = secureSession.id;
    }

    var json = await http
        .post(initiateUrl, body: data)
        .then((r) => jsonDecode(r.body) as Map<String, dynamic>);

    var identityToken = json['data']['identity_token'] as String;
    var roomJson = json['data']['customer_room'] as Map<String, dynamic>;

    var roomId = int.parse(roomJson['room_id']);
    var isResolved = roomJson['is_resolved'] as bool?;
    var isSessional = roomJson['is_sessional'] as bool?;

    Map<String, dynamic>? properties;
    try {
      var prop = (roomJson['extras']['user_properties'] as List)
          .cast<Map<String, dynamic>>();

      if (prop.isNotEmpty) properties ??= {};
      for (var item in prop) {
        if (item['key'] != null) {
          properties?['${item['key']}'] = item['value'];
        }
      }
    } catch (_) {}

    final user = QAccount.merge(
      await qiscus.setUserWithIdentityToken(token: identityToken),
      properties,
    );

    if (deviceId != null) {
      qiscus
          .registerDeviceToken(
            token: deviceId,
            isDevelopment: deviceIdDevelopment,
          )
          .ignore();
    }

    QChatRoomWithMessages roomData;
    try {
      roomData = await getChatRoomWithMessages(qiscus: qiscus, roomId: roomId);
    } catch (e) {
      roomData = QChatRoomWithMessages(QChatRoom(id: 1, uniqueId: '1'), []);
      print('error: $e');
    }
    var room = roomData.room;
    var messages = roomData.messages;

    // Security Enchancements
    var isSecure = json['data']['is_secure'] as bool? ?? false;
    var sessionId = roomJson['session_id'] as String?;
    channelId = (roomJson['channel_id'] as int).toString();
    print('initiate chat: isSecure($isSecure) sessionId($sessionId)');
    if (isSecure == false) {
      storage.delete(key: StorageKey.secureSession).ignore();
    }
    if (isSecure && sessionId != null) {
      var userId = user.id.split('_')[1];
      // Save session data to local
      var data = SecureSession(
        appId: qiscus.appId!,
        channelId: channelId!,
        userId: userId,
        id: sessionId,
      );
      ref.read(secureSessionProvider.notifier).state = data;
      await storage.write(
        key: StorageKey.secureSession,
        value: jsonEncode(data.toJson()),
      );
    }

    // Update providers
    ref.read(isResolvedProvider.notifier).state = isResolved ?? false;
    ref.read(isSessionalProvider.notifier).state = isSessional ?? false;
    ref.read(appStateProvider.notifier).state = AppState.ready(
      roomId: roomId,
      account: user,
    );
    ref.read(roomStateProvider.notifier).state =
        QChatRoomWithMessages(room, messages);

    return room;
  };
}