loadView method

Future<NiceViewLoadResult> loadView(
  1. String module,
  2. String viewId
)

Load a view definition from server or cache.

Uses If-None-Match (ETag) for delta updates:

  • If the server returns 304, the cached version is used.
  • If the server returns 200, the new version is cached.

Implementation

Future<NiceViewLoadResult> loadView(String module, String viewId) async {
  final fullId = '$module/$viewId';

  // Check cache first
  final cached = await cache.get(fullId);
  final cachedETag = await cache.getETag(fullId);

  final headers = <String, String>{};
  if (config.headersFactory != null) {
    headers.addAll(await config.headersFactory!());
  }
  if (cachedETag != null) {
    headers['If-None-Match'] = cachedETag;
  }

  try {
    final response = await transport.get(
      '${config.baseUrl}/api/views/$module/$viewId',
      headers: headers,
    );

    // 304 Not Modified — use cache
    if (response.statusCode == 304 && cached != null) {
      return NiceViewLoadResult(
          definition: cached, fromCache: true, etag: cachedETag);
    }

    if (response.statusCode == 200) {
      final json = jsonDecode(response.body) as Map<String, dynamic>;
      final definition = NiceViewDefinition.fromJson(json);
      final newETag = response.headers['etag'];

      await cache.put(definition, etag: newETag);

      // Notify hot-swap listeners if version changed
      if (cached != null && cached.version != definition.version) {
        _updateController.add(fullId);
      }

      return NiceViewLoadResult(
          definition: definition, fromCache: false, etag: newETag);
    }

    // Fallback to cache if server error
    if (cached != null) {
      return NiceViewLoadResult(
          definition: cached, fromCache: true, etag: cachedETag);
    }

    throw NiceViewServiceException(
        'Failed to load view $fullId: HTTP ${response.statusCode}');
  } catch (e) {
    // Network error — fallback to cache
    if (cached != null) {
      return NiceViewLoadResult(
          definition: cached, fromCache: true, etag: cachedETag);
    }
    rethrow;
  }
}