sendToDeviceEncryptedChunked method

Future<void> sendToDeviceEncryptedChunked(
  1. List<DeviceKeys> deviceKeys,
  2. String eventType,
  3. Map<String, dynamic> message
)

Sends an encrypted message of this eventType to these deviceKeys. This request happens partly in the background and partly in the foreground. It automatically chunks sending to device keys based on activity.

Implementation

Future<void> sendToDeviceEncryptedChunked(
  List<DeviceKeys> deviceKeys,
  String eventType,
  Map<String, dynamic> message,
) async {
  if (!encryptionEnabled) return;
  // be sure to copy our device keys list
  deviceKeys = List<DeviceKeys>.from(deviceKeys);
  deviceKeys.removeWhere((DeviceKeys k) =>
      k.blocked || (k.userId == userID && k.deviceId == deviceID));
  if (deviceKeys.isEmpty) return;
  message = message.copy(); // make sure we deep-copy the message
  // make sure all the olm sessions are loaded from database
  Logs().v('Sending to device chunked... (${deviceKeys.length} devices)');
  // sort so that devices we last received messages from get our message first
  deviceKeys.sort((keyA, keyB) => keyB.lastActive.compareTo(keyA.lastActive));
  // and now send out in chunks of 20
  const chunkSize = 20;

  // first we send out all the chunks that we await
  var i = 0;
  // we leave this in a for-loop for now, so that we can easily adjust the break condition
  // based on other things, if we want to hard-`await` more devices in the future
  for (; i < deviceKeys.length && i <= 0; i += chunkSize) {
    Logs().v('Sending chunk $i...');
    final chunk = deviceKeys.sublist(
        i,
        i + chunkSize > deviceKeys.length
            ? deviceKeys.length
            : i + chunkSize);
    // and send
    await sendToDeviceEncrypted(chunk, eventType, message);
  }
  // now send out the background chunks
  if (i < deviceKeys.length) {
    // ignore: unawaited_futures
    () async {
      for (; i < deviceKeys.length; i += chunkSize) {
        // wait 50ms to not freeze the UI
        await Future.delayed(Duration(milliseconds: 50));
        Logs().v('Sending chunk $i...');
        final chunk = deviceKeys.sublist(
            i,
            i + chunkSize > deviceKeys.length
                ? deviceKeys.length
                : i + chunkSize);
        // and send
        await sendToDeviceEncrypted(chunk, eventType, message);
      }
    }();
  }
}