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.
		
		
		
		
		
			
		
			
				
	
	
		
			174 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Dart
		
	
import 'dart:async';
 | 
						|
import 'dart:io';
 | 
						|
 | 
						|
import 'package:diplomaticquarterapp/pages/conference/clipped_video.dart';
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
 | 
						|
class DraggablePublisher extends StatefulWidget {
 | 
						|
  final Size availableScreenSize;
 | 
						|
  final Widget child;
 | 
						|
  final double scaleFactor;
 | 
						|
  final Stream<bool> onButtonBarVisible;
 | 
						|
  final Stream<double> onButtonBarHeight;
 | 
						|
 | 
						|
  const DraggablePublisher({
 | 
						|
    Key key,
 | 
						|
    @required this.availableScreenSize,
 | 
						|
    this.child,
 | 
						|
    @required this.onButtonBarVisible,
 | 
						|
    @required this.onButtonBarHeight,
 | 
						|
 | 
						|
    /// The portion of the screen the DraggableWidget should use.
 | 
						|
    this.scaleFactor = .25,
 | 
						|
  })  : assert(scaleFactor != null && scaleFactor > 0 && scaleFactor <= .4),
 | 
						|
        assert(availableScreenSize != null),
 | 
						|
        assert(onButtonBarVisible != null),
 | 
						|
        assert(onButtonBarHeight != null),
 | 
						|
        super(key: key);
 | 
						|
 | 
						|
  @override
 | 
						|
  _DraggablePublisherState createState() => _DraggablePublisherState();
 | 
						|
}
 | 
						|
 | 
						|
class _DraggablePublisherState extends State<DraggablePublisher> {
 | 
						|
  bool _isButtonBarVisible = true;
 | 
						|
  double _buttonBarHeight = 0;
 | 
						|
  double _width;
 | 
						|
  double _height;
 | 
						|
  double _top;
 | 
						|
  double _left;
 | 
						|
  double _viewPaddingTop;
 | 
						|
  double _viewPaddingBottom;
 | 
						|
  final double _padding = 8.0;
 | 
						|
  final Duration _duration300ms = const Duration(milliseconds: 300);
 | 
						|
  final Duration _duration0ms = const Duration(milliseconds: 0);
 | 
						|
  Duration _duration;
 | 
						|
  StreamSubscription _streamSubscription;
 | 
						|
  StreamSubscription _streamHeightSubscription;
 | 
						|
 | 
						|
  @override
 | 
						|
  void initState() {
 | 
						|
    super.initState();
 | 
						|
    _duration = _duration300ms;
 | 
						|
    _width = widget.availableScreenSize.width * widget.scaleFactor;
 | 
						|
    _height = _width * (widget.availableScreenSize.height / widget.availableScreenSize.width);
 | 
						|
    _top = widget.availableScreenSize.height - (_buttonBarHeight + _padding) - _height;
 | 
						|
    _left = widget.availableScreenSize.width - _padding - _width;
 | 
						|
 | 
						|
    _streamSubscription = widget.onButtonBarVisible.listen(_buttonBarVisible);
 | 
						|
    _streamHeightSubscription = widget.onButtonBarHeight.listen(_getButtonBarHeight);
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  void didChangeDependencies() {
 | 
						|
    final mediaQuery = MediaQuery.of(context);
 | 
						|
    _viewPaddingTop = mediaQuery.viewPadding.top;
 | 
						|
    _viewPaddingBottom = mediaQuery.viewPadding.bottom;
 | 
						|
    super.didChangeDependencies();
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  void dispose() {
 | 
						|
    _streamSubscription.cancel();
 | 
						|
    _streamHeightSubscription.cancel();
 | 
						|
    super.dispose();
 | 
						|
  }
 | 
						|
 | 
						|
  void _getButtonBarHeight(double height) {
 | 
						|
    setState(() {
 | 
						|
      _buttonBarHeight = height;
 | 
						|
      _positionWidget();
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  void _buttonBarVisible(bool visible) {
 | 
						|
    if (!mounted) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    setState(() {
 | 
						|
      _isButtonBarVisible = visible;
 | 
						|
      if (_duration == _duration300ms) {
 | 
						|
        // only position the widget when we are not currently dragging it around
 | 
						|
        _positionWidget();
 | 
						|
      }
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    return AnimatedPositioned(
 | 
						|
      top: _top,
 | 
						|
      left: _left,
 | 
						|
      width: _width,
 | 
						|
      height: _height,
 | 
						|
      duration: _duration,
 | 
						|
      child: Listener(
 | 
						|
        onPointerDown: (_) => _duration = _duration0ms,
 | 
						|
        onPointerMove: (PointerMoveEvent event) {
 | 
						|
          setState(() {
 | 
						|
            _left = (_left + event.delta.dx).roundToDouble();
 | 
						|
            _top = (_top + event.delta.dy).roundToDouble();
 | 
						|
          });
 | 
						|
        },
 | 
						|
        onPointerUp: (_) => _positionWidget(),
 | 
						|
        onPointerCancel: (_) => _positionWidget(),
 | 
						|
        child: ClippedVideo(
 | 
						|
          height: _height,
 | 
						|
          width: _width,
 | 
						|
          child: widget.child,
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  double _getCurrentStatusBarHeight() {
 | 
						|
    if (_isButtonBarVisible) {
 | 
						|
      return _viewPaddingTop;
 | 
						|
    }
 | 
						|
    final _defaultViewPaddingTop = Platform.isIOS ? 20.0 : Platform.isAndroid ? 24.0 : 0.0;
 | 
						|
    if (_viewPaddingTop > _defaultViewPaddingTop) {
 | 
						|
      // There must be a hardware notch in the display.
 | 
						|
      return _viewPaddingTop;
 | 
						|
    }
 | 
						|
    return 0.0;
 | 
						|
  }
 | 
						|
 | 
						|
  double _getCurrentButtonBarHeight() {
 | 
						|
    if (_isButtonBarVisible) {
 | 
						|
      return _buttonBarHeight + _viewPaddingBottom;
 | 
						|
    }
 | 
						|
    return _viewPaddingBottom;
 | 
						|
  }
 | 
						|
 | 
						|
  void _positionWidget() {
 | 
						|
    // Determine the center of the object being dragged so we can decide
 | 
						|
    // in which corner the object should be placed.
 | 
						|
    var dx = (_width / 2) + _left;
 | 
						|
    dx = dx < 0 ? 0 : dx >= widget.availableScreenSize.width ? widget.availableScreenSize.width - 1 : dx;
 | 
						|
    var dy = (_height / 2) + _top;
 | 
						|
    dy = dy < 0 ? 0 : dy >= widget.availableScreenSize.height ? widget.availableScreenSize.height - 1 : dy;
 | 
						|
    final draggableCenter = Offset(dx, dy);
 | 
						|
 | 
						|
    setState(() {
 | 
						|
      _duration = _duration300ms;
 | 
						|
      if (Rect.fromLTRB(0, 0, widget.availableScreenSize.width / 2, widget.availableScreenSize.height / 2).contains(draggableCenter)) {
 | 
						|
        // Top-left
 | 
						|
        _top = _getCurrentStatusBarHeight() + _padding;
 | 
						|
        _left = _padding;
 | 
						|
      } else if (Rect.fromLTRB(widget.availableScreenSize.width / 2, 0, widget.availableScreenSize.width, widget.availableScreenSize.height / 2).contains(draggableCenter)) {
 | 
						|
        // Top-right
 | 
						|
        _top = _getCurrentStatusBarHeight() + _padding;
 | 
						|
        _left = widget.availableScreenSize.width - _padding - _width;
 | 
						|
      } else if (Rect.fromLTRB(0, widget.availableScreenSize.height / 2, widget.availableScreenSize.width / 2, widget.availableScreenSize.height).contains(draggableCenter)) {
 | 
						|
        // Bottom-left
 | 
						|
        _top = widget.availableScreenSize.height - (_getCurrentButtonBarHeight() + _padding) - _height;
 | 
						|
        _left = _padding;
 | 
						|
      } else if (Rect.fromLTRB(widget.availableScreenSize.width / 2, widget.availableScreenSize.height / 2, widget.availableScreenSize.width, widget.availableScreenSize.height).contains(draggableCenter)) {
 | 
						|
        // Bottom-right
 | 
						|
        _top = widget.availableScreenSize.height - (_getCurrentButtonBarHeight() + _padding) - _height;
 | 
						|
        _left = widget.availableScreenSize.width - _padding - _width;
 | 
						|
      }
 | 
						|
    });
 | 
						|
  }
 | 
						|
}
 |