You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			198 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			198 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Dart
		
	
import 'dart:ui';
 | 
						|
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
 | 
						|
class ParticipantBuffer {
 | 
						|
  final bool audioEnabled;
 | 
						|
  final String id;
 | 
						|
 | 
						|
  ParticipantBuffer({
 | 
						|
    @required this.audioEnabled,
 | 
						|
    @required this.id,
 | 
						|
  })  : assert(audioEnabled != null),
 | 
						|
        assert(id != null);
 | 
						|
}
 | 
						|
 | 
						|
class ParticipantWidget extends StatelessWidget {
 | 
						|
  final Widget child;
 | 
						|
  final String id;
 | 
						|
  final bool audioEnabled;
 | 
						|
  final bool videoEnabled;
 | 
						|
  final bool isRemote;
 | 
						|
  final bool isDummy;
 | 
						|
  final bool isDominant;
 | 
						|
 | 
						|
  const ParticipantWidget({
 | 
						|
    Key key,
 | 
						|
    @required this.child,
 | 
						|
    @required this.audioEnabled,
 | 
						|
    @required this.videoEnabled,
 | 
						|
    @required this.id,
 | 
						|
    @required this.isRemote,
 | 
						|
    this.isDominant = false,
 | 
						|
    this.isDummy = false,
 | 
						|
  })  : assert(child != null),
 | 
						|
        assert(audioEnabled != null),
 | 
						|
        assert(videoEnabled != null),
 | 
						|
        assert(isRemote != null),
 | 
						|
        assert(isDominant != null),
 | 
						|
        assert(isDummy != null),
 | 
						|
        super(key: key);
 | 
						|
 | 
						|
  ParticipantWidget copyWith({
 | 
						|
    Widget child,
 | 
						|
    bool audioEnabled,
 | 
						|
    bool videoEnabled,
 | 
						|
    bool isDominant,
 | 
						|
  }) {
 | 
						|
    return ParticipantWidget(
 | 
						|
      id: id,
 | 
						|
      child: child ?? this.child,
 | 
						|
      audioEnabled: audioEnabled ?? this.audioEnabled,
 | 
						|
      videoEnabled: videoEnabled ?? this.videoEnabled,
 | 
						|
      isDominant: isDominant ?? this.isDominant,
 | 
						|
      isRemote: isRemote,
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final children = <Widget>[];
 | 
						|
    final icons = <Widget>[];
 | 
						|
    if (!videoEnabled) {
 | 
						|
      icons.add(_buildVideoEnabledIcon());
 | 
						|
      children.add(
 | 
						|
        ClipRect(
 | 
						|
          // Need to clip this BackdropFilter, otherwise it will blur the entire screen
 | 
						|
          child: BackdropFilter(
 | 
						|
            filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
 | 
						|
            child: Container(
 | 
						|
              decoration: BoxDecoration(color: Colors.black.withOpacity(.1)),
 | 
						|
              child: child,
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
      );
 | 
						|
    } else {
 | 
						|
      children.add(child);
 | 
						|
    }
 | 
						|
    children.add(Padding(
 | 
						|
      padding: const EdgeInsets.all(8.0),
 | 
						|
      child: AnimatedOpacity(
 | 
						|
        duration: Duration(milliseconds: 500),
 | 
						|
        opacity: isDominant ? 1 : 0,
 | 
						|
        child: Icon(
 | 
						|
          Icons.volume_up,
 | 
						|
          color: Colors.white,
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    ));
 | 
						|
    if (!audioEnabled) {
 | 
						|
      icons.add(_buildAudioEnabledIcon());
 | 
						|
    }
 | 
						|
    if (icons.isNotEmpty) {
 | 
						|
      if (isRemote) {
 | 
						|
        final rows = <Widget>[];
 | 
						|
        rows.add(_buildRow(icons));
 | 
						|
        if (!audioEnabled && !videoEnabled) {
 | 
						|
          rows.add(_buildRow(_fitText('The camera and microphone are off', Colors.white24)));
 | 
						|
        } else if (!audioEnabled) {
 | 
						|
          rows.add(_buildRow(_fitText('The microphone is off', Colors.black26)));
 | 
						|
        } else if (!videoEnabled) {
 | 
						|
          rows.add(_buildRow(_fitText('The camera is off', Colors.white24)));
 | 
						|
        }
 | 
						|
        children.add(
 | 
						|
          Column(
 | 
						|
            mainAxisAlignment: MainAxisAlignment.center,
 | 
						|
            crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
						|
            children: rows,
 | 
						|
          ),
 | 
						|
        );
 | 
						|
      } else {
 | 
						|
        children.add(Column(
 | 
						|
          mainAxisAlignment: MainAxisAlignment.spaceAround,
 | 
						|
          crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
						|
          children: icons,
 | 
						|
        ));
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return Stack(
 | 
						|
      children: children,
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  List<Widget> _fitText(String text, Color color) {
 | 
						|
    return [
 | 
						|
      Flexible(
 | 
						|
        child: FittedBox(
 | 
						|
          fit: BoxFit.scaleDown,
 | 
						|
          child: Padding(
 | 
						|
            padding: const EdgeInsets.only(left: 8.0, right: 8.0),
 | 
						|
            child: Text(text, maxLines: 1, style: _buildTextStyle(color)),
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    ];
 | 
						|
  }
 | 
						|
 | 
						|
  TextStyle _buildTextStyle(Color color) {
 | 
						|
    return TextStyle(
 | 
						|
      color: color,
 | 
						|
      shadows: <Shadow>[
 | 
						|
        Shadow(
 | 
						|
          blurRadius: 1.0,
 | 
						|
          color: Color.fromARGB(255, 0, 0, 0),
 | 
						|
        ),
 | 
						|
        Shadow(
 | 
						|
          blurRadius: 1.0,
 | 
						|
          color: Color.fromARGB(24, 255, 255, 255),
 | 
						|
        ),
 | 
						|
      ],
 | 
						|
      fontSize: 15,
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  Widget _buildRow(List<Widget> children) {
 | 
						|
    return Row(
 | 
						|
      mainAxisAlignment: MainAxisAlignment.center,
 | 
						|
      crossAxisAlignment: CrossAxisAlignment.center,
 | 
						|
      children: children,
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  Widget _buildAudioEnabledIcon() {
 | 
						|
    return Padding(
 | 
						|
      padding: const EdgeInsets.all(8),
 | 
						|
      child: CircleAvatar(
 | 
						|
        maxRadius: 15,
 | 
						|
        child: FittedBox(
 | 
						|
          child: Icon(
 | 
						|
            Icons.mic_off,
 | 
						|
            color: Colors.black,
 | 
						|
            key: Key('microphone-off-icon'),
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
        backgroundColor: Colors.white24,
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  Widget _buildVideoEnabledIcon() {
 | 
						|
    return Padding(
 | 
						|
      padding: const EdgeInsets.all(8),
 | 
						|
      child: CircleAvatar(
 | 
						|
        maxRadius: 15,
 | 
						|
        child: FittedBox(
 | 
						|
          child: Icon(
 | 
						|
            Icons.videocam_off,
 | 
						|
            color: Colors.black,
 | 
						|
            key: Key('videocam-off-icon'),
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
        backgroundColor: Colors.white24,
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |