notifyDocuments method

void notifyDocuments(
  1. String documentPath,
  2. String documentId,
  3. DynamicMap value,
  4. ModelUpdateNotificationStatus status,
  5. ModelAdapterDocumentQuery query,
)

Sends notifications to monitored documents and collections based on documentPath and documentId.

The changed value is passed to value and the change status is passed to status.

Pass ModelAdapterDocumentQuery passed at the time of modification directly to query.

documentPathdocumentIdを元に監視対象にしたドキュメントやコレクションへ通知を送信します。

変更後の値をvalueに渡し、変更ステータスをstatusに渡します。

変更時に渡されたModelAdapterDocumentQueryqueryにそのまま渡してください。

Implementation

void notifyDocuments(
  String documentPath,
  String documentId,
  DynamicMap value,
  ModelUpdateNotificationStatus status,
  ModelAdapterDocumentQuery query,
) {
  final collectionPath = documentPath.parentPath();
  final collectionGroupPath = collectionPath.last();
  if (_documentListeners.containsKey(documentPath)) {
    for (final element in _documentListeners[documentPath]?.values ??
        <ModelAdapterDocumentQuery>[]) {
      element.callback?.call(
        ModelUpdateNotification(
          path: documentPath,
          id: documentId,
          status: status,
          value: Map.from(value),
          origin: query.origin,
          listen: query.listen,
          query: element.query,
        ),
      );
    }
  }
  if (_collectionListeners.containsKey(collectionPath)) {
    for (final element in _collectionListeners[collectionPath]?.values ??
        <ModelAdapterCollectionQuery>[]) {
      final entries = _collectionEntries[element.origin] ?? [];
      switch (status) {
        case ModelUpdateNotificationStatus.added:
          if (!element.query.hasMatchAsMap(value)) {
            continue;
          }
          final newIndex =
              element.query.seekIndex(entries, value) ?? entries.length;
          _collectionEntries[element.origin] = entries
            ..insert(newIndex, MapEntry(documentId, value));
          element.callback?.call(
            ModelUpdateNotification(
              path: documentPath,
              id: documentId,
              status: status,
              value: Map.from(value),
              origin: query.origin,
              oldIndex: null,
              newIndex: newIndex,
              listen: query.listen,
              query: element.query,
            ),
          );
          break;
        case ModelUpdateNotificationStatus.modified:
          if (element.query.hasMatchAsMap(value)) {
            final oldIndex = entries.indexWhere(
              (e) => e.key.trimQuery().trimString("/") == documentId,
            );

            if (oldIndex < 0) {
              final newIndex =
                  element.query.seekIndex(entries, value) ?? entries.length;
              _collectionEntries[element.origin] = entries
                ..insert(newIndex, MapEntry(documentId, value));
              element.callback?.call(
                ModelUpdateNotification(
                  path: documentPath,
                  id: documentId,
                  status: ModelUpdateNotificationStatus.added,
                  value: Map.from(value),
                  origin: query.origin,
                  oldIndex: null,
                  newIndex: newIndex,
                  listen: query.listen,
                  query: element.query,
                ),
              );
            } else {
              var newIndex =
                  element.query.seekIndex(entries, value) ?? oldIndex;
              if (oldIndex < newIndex) {
                newIndex = newIndex - 1;
              }
              _collectionEntries[element.origin] = entries
                ..removeAt(oldIndex)
                ..insert(newIndex, MapEntry(documentId, value));
              element.callback?.call(
                ModelUpdateNotification(
                  path: documentPath,
                  id: documentId,
                  status: status,
                  value: Map.from(value),
                  origin: query.origin,
                  oldIndex: oldIndex < 0 ? null : oldIndex,
                  newIndex: newIndex,
                  listen: query.listen,
                  query: element.query,
                ),
              );
            }
          } else {
            final oldIndex = entries.indexWhere(
              (e) => e.key.trimQuery().trimString("/") == documentId,
            );
            if (oldIndex >= 0) {
              _collectionEntries[element.origin] = entries
                ..removeAt(oldIndex);
              element.callback?.call(
                ModelUpdateNotification(
                  path: documentPath,
                  id: documentId,
                  status: ModelUpdateNotificationStatus.removed,
                  value: const {},
                  origin: query.origin,
                  oldIndex: oldIndex < 0 ? null : oldIndex,
                  newIndex: null,
                  listen: query.listen,
                  query: element.query,
                ),
              );
            }
          }
          break;
        case ModelUpdateNotificationStatus.removed:
          final oldIndex = entries.indexWhere(
            (e) => e.key.trimQuery().trimString("/") == documentId,
          );
          if (oldIndex >= 0) {
            _collectionEntries[element.origin] = entries..removeAt(oldIndex);
            element.callback?.call(
              ModelUpdateNotification(
                path: documentPath,
                id: documentId,
                status: status,
                value: const {},
                origin: query.origin,
                oldIndex: oldIndex < 0 ? null : oldIndex,
                newIndex: null,
                listen: query.listen,
                query: element.query,
              ),
            );
          }
          break;
      }
    }
  }
  if (_collectionGroupListeners.containsKey(collectionGroupPath)) {
    for (final element
        in _collectionGroupListeners[collectionGroupPath]?.values ??
            <ModelAdapterCollectionQuery>[]) {
      final entries = _collectionGroupEntries[element.origin] ?? [];
      switch (status) {
        case ModelUpdateNotificationStatus.added:
          if (!element.query.hasMatchAsMap(value)) {
            continue;
          }
          final newIndex =
              element.query.seekIndex(entries, value) ?? entries.length;
          _collectionGroupEntries[element.origin] = entries
            ..insert(newIndex, MapEntry(documentId, value));
          element.callback?.call(
            ModelUpdateNotification(
              path: documentPath,
              id: documentId,
              status: status,
              value: Map.from(value),
              origin: query.origin,
              oldIndex: null,
              newIndex: newIndex,
              listen: query.listen,
              query: element.query,
            ),
          );
          break;
        case ModelUpdateNotificationStatus.modified:
          if (element.query.hasMatchAsMap(value)) {
            final oldIndex = entries.indexWhere(
              (e) => e.key.trimQuery().trimString("/") == documentId,
            );

            if (oldIndex < 0) {
              final newIndex =
                  element.query.seekIndex(entries, value) ?? entries.length;
              _collectionGroupEntries[element.origin] = entries
                ..insert(newIndex, MapEntry(documentId, value));
              element.callback?.call(
                ModelUpdateNotification(
                  path: documentPath,
                  id: documentId,
                  status: ModelUpdateNotificationStatus.added,
                  value: Map.from(value),
                  origin: query.origin,
                  oldIndex: null,
                  newIndex: newIndex,
                  listen: query.listen,
                  query: element.query,
                ),
              );
            } else {
              var newIndex =
                  element.query.seekIndex(entries, value) ?? oldIndex;
              if (oldIndex < newIndex) {
                newIndex = newIndex - 1;
              }
              _collectionGroupEntries[element.origin] = entries
                ..removeAt(oldIndex)
                ..insert(newIndex, MapEntry(documentId, value));
              element.callback?.call(
                ModelUpdateNotification(
                  path: documentPath,
                  id: documentId,
                  status: status,
                  value: Map.from(value),
                  origin: query.origin,
                  oldIndex: oldIndex < 0 ? null : oldIndex,
                  newIndex: newIndex,
                  listen: query.listen,
                  query: element.query,
                ),
              );
            }
          } else {
            final oldIndex = entries.indexWhere(
              (e) => e.key.trimQuery().trimString("/") == documentId,
            );
            if (oldIndex >= 0) {
              _collectionGroupEntries[element.origin] = entries
                ..removeAt(oldIndex);
              element.callback?.call(
                ModelUpdateNotification(
                  path: documentPath,
                  id: documentId,
                  status: ModelUpdateNotificationStatus.removed,
                  value: const {},
                  origin: query.origin,
                  oldIndex: oldIndex < 0 ? null : oldIndex,
                  newIndex: null,
                  listen: query.listen,
                  query: element.query,
                ),
              );
            }
          }
          break;
        case ModelUpdateNotificationStatus.removed:
          final oldIndex = entries.indexWhere(
            (e) => e.key.trimQuery().trimString("/") == documentId,
          );
          if (oldIndex >= 0) {
            _collectionGroupEntries[element.origin] = entries
              ..removeAt(oldIndex);
            element.callback?.call(
              ModelUpdateNotification(
                path: documentPath,
                id: documentId,
                status: status,
                value: const {},
                origin: query.origin,
                oldIndex: oldIndex < 0 ? null : oldIndex,
                newIndex: null,
                listen: query.listen,
                query: element.query,
              ),
            );
          }
          break;
      }
    }
  }
}