@@ -2,6 +2,7 @@ import 'dart:io';
22
33import 'package:equatable/equatable.dart' ;
44import 'package:flutter/foundation.dart' ;
5+ import 'package:flutter/material.dart' ;
56
67import 'package:logging/logging.dart' ;
78
@@ -58,6 +59,7 @@ class FeatureAccess extends Equatable {
5859 this .termsConfig,
5960 this .systemNotificationsConfig,
6061 this .sipPresenceConfig,
62+ this .supportedConfig,
6163 );
6264
6365 final EmbeddedConfig embeddedConfig;
@@ -70,6 +72,7 @@ class FeatureAccess extends Equatable {
7072 final TermsConfig termsConfig;
7173 final SystemNotificationsConfig systemNotificationsConfig;
7274 final SipPresenceConfig sipPresenceConfig;
75+ final SupportedConfig supportedConfig;
7376
7477 static FeatureAccess create (
7578 AppConfig appConfig,
@@ -93,6 +96,7 @@ class FeatureAccess extends Equatable {
9396 final contactsConfig = ContactsMapper .map (appConfig);
9497 final systemNotificationsConfig = SystemNotificationsMapper .map (coreSupportSnapshot, appConfig);
9598 final sipPresenceConfig = SipPresenceMapper .map (coreSupportSnapshot, appConfig);
99+ final supportedConfig = SupportedMapper .map (appConfig.supported);
96100
97101 return FeatureAccess ._(
98102 embeddedConfig,
@@ -105,6 +109,7 @@ class FeatureAccess extends Equatable {
105109 termsConfig,
106110 systemNotificationsConfig,
107111 sipPresenceConfig,
112+ supportedConfig,
108113 );
109114 } catch (e, stackTrace) {
110115 _logger.severe ('Failed to initialize FeatureAccess' , e, stackTrace);
@@ -502,6 +507,41 @@ abstract final class ContactsMapper {
502507 }
503508}
504509
510+ /// Mapper responsible for constructing [SupportedConfig] from the raw list of [SupportedFeature] .
511+ ///
512+ /// This mapper parses the polymorphic list of features and maps them into a structured
513+ /// configuration object. It handles the resolution logic for each feature:
514+ ///
515+ /// 1. **Theme Resolution**: Searches for [SupportedThemeMode] . If missing,
516+ /// it defaults to [ThemeModeConfig.system] (Standard Behavior).
517+ ///
518+ /// 2. **Video Call Resolution**: Searches for [SupportedVideoCall] . If missing,
519+ /// it defaults to `false` (disabled), adhering to a "whitelist" approach where
520+ /// features must be explicitly enabled.
521+ abstract final class SupportedMapper {
522+ /// Maps a list of [SupportedFeature] s to a [SupportedConfig] .
523+ static SupportedConfig map (List <SupportedFeature > supportedFeatures) {
524+ final themeFeature =
525+ supportedFeatures.firstWhere ((e) => e is SupportedThemeMode , orElse: () => const SupportedFeature .themeMode ())
526+ as SupportedThemeMode ;
527+
528+ final videoCallFeature =
529+ supportedFeatures.firstWhere (
530+ (e) => e is SupportedVideoCall ,
531+ orElse: () => const SupportedFeature .videoCall (enabled: false ),
532+ )
533+ as SupportedVideoCall ;
534+
535+ final configThemeMode = switch (themeFeature.mode) {
536+ ThemeModeConfig .auto => ThemeMode .system,
537+ ThemeModeConfig .light => ThemeMode .light,
538+ ThemeModeConfig .dark => ThemeMode .dark,
539+ };
540+
541+ return SupportedConfig (themeMode: configThemeMode, isVideoCallEnabled: videoCallFeature.enabled);
542+ }
543+ }
544+
505545class FeatureChecker {
506546 const FeatureChecker (this ._access);
507547
0 commit comments