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.
PatientApp-KKUMC/lib/pages/conference/conference_button_bar.dart

239 lines
6.6 KiB
Dart

import 'dart:async';
import 'package:after_layout/after_layout.dart';
import 'package:diplomaticquarterapp/pages/conference/widgets/circle_button.dart';
import 'package:flutter/material.dart';
class ConferenceButtonBar extends StatefulWidget {
final VoidCallback? onVideoEnabled;
final VoidCallback? onAudioEnabled;
final VoidCallback? onHangup;
final VoidCallback? onSwitchCamera;
final VoidCallback? onPersonAdd;
final VoidCallback? onPersonRemove;
final void Function(double)? onHeight;
final VoidCallback? onHide;
final VoidCallback? onShow;
final Stream<bool> videoEnabled;
final Stream<bool> audioEnabled;
const ConferenceButtonBar({
Key? key,
this.onVideoEnabled,
this.onAudioEnabled,
this.onHangup,
this.onSwitchCamera,
this.onPersonAdd,
this.onPersonRemove,
required this.videoEnabled,
required this.audioEnabled,
this.onHeight,
this.onHide,
this.onShow,
}) : assert(videoEnabled != null),
assert(audioEnabled != null),
super(key: key);
@override
_ConferenceButtonBarState createState() => _ConferenceButtonBarState();
}
class _ConferenceButtonBarState extends State<ConferenceButtonBar> with AfterLayoutMixin<ConferenceButtonBar> {
var _bottom = -100.0;
late Timer _timer;
late int _remaining;
var _videoEnabled = true;
var _audioEnabled = true;
late double _hidden;
late double _visible;
final _keyButtonBarHeight = GlobalKey();
final Duration timeout = const Duration(seconds: 5);
final Duration ms = const Duration(milliseconds: 1);
final Duration periodicDuration = const Duration(milliseconds: 100);
Timer startTimeout([int? milliseconds]) {
final duration = milliseconds == null ? timeout : ms * milliseconds;
_remaining = duration.inMilliseconds;
return Timer.periodic(periodicDuration, (Timer timer) {
_remaining -= periodicDuration.inMilliseconds;
if (_remaining <= 0) {
timer.cancel();
_toggleBar();
}
});
}
void _pauseTimer() {
if (_timer == null) {
return;
}
_timer.cancel();
// _timer = null;
}
void _resumeTimer() {
// resume the timer only when there is no timer active or when
// the bar is not already hidden.
if ((_timer != null && _timer.isActive) || _bottom == _hidden) {
return;
}
_timer = startTimeout(_remaining);
}
void _toggleBar() {
setState(() {
_bottom = _bottom == _visible ? _hidden : _visible;
if (_bottom == _visible && widget.onShow != null) {
widget.onShow!();
}
if (_bottom == _hidden && widget.onHide != null) {
widget.onHide!();
}
});
}
void _toggleBarOnEnd() {
if (_timer != null) {
if (_timer.isActive) {
_timer.cancel();
}
// _timer = null;
}
if (_bottom == 0) {
_timer = startTimeout();
}
}
@override
void initState() {
super.initState();
_timer = startTimeout();
}
@override
void didChangeDependencies() {
_visible = MediaQuery.of(context).viewPadding.bottom;
super.didChangeDependencies();
}
@override
void afterFirstLayout(BuildContext context) {
final heightButtonBar = _keyButtonBarHeight.currentContext!.size!.height;
//Changed by Aamir
// Because the `didChangeDependencies` fires before the `afterFirstLayout`, we can use the `_visible` property here.
_hidden = -(heightButtonBar + _visible);
widget.onHeight!(heightButtonBar);
_toggleBar();
}
@override
void dispose() {
super.dispose();
if (_timer != null && _timer.isActive) {
_timer.cancel();
}
}
@override
Widget build(BuildContext context) {
return Positioned(
top: 0,
left: 0,
right: 0,
bottom: 0,
child: GestureDetector(
key: Key('show-hide-button-bar-gesture'),
behavior: HitTestBehavior.translucent,
onTapDown: (_) => _pauseTimer(),
onTapUp: (_) => _toggleBar(),
onTapCancel: () => _resumeTimer(),
child: Stack(
children: <Widget>[
AnimatedPositioned(
key: Key('button-bar'),
bottom: _bottom,
left: 0,
right: 0,
duration: const Duration(milliseconds: 300),
curve: Curves.linear,
child: _buildRow(context),
onEnd: _toggleBarOnEnd,
),
],
),
),
);
}
void _onPressed(VoidCallback callback) {
if (callback != null) {
callback();
}
if (_timer != null && _timer.isActive) {
_timer.cancel();
}
_timer = startTimeout();
}
Widget _buildRow(BuildContext context) {
return Padding(
key: _keyButtonBarHeight,
padding: const EdgeInsets.only(bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
CircleButton(
child: StreamBuilder<bool>(
stream: widget.videoEnabled,
initialData: _videoEnabled,
builder: (context, snapshot) {
_videoEnabled = snapshot.data!;
return Icon(
_videoEnabled ? Icons.videocam : Icons.videocam_off,
color: Colors.white,
);
}),
key: Key('camera-button'),
onPressed: () => _onPressed(widget.onVideoEnabled!),
),
CircleButton(
child: StreamBuilder<bool>(
stream: widget.audioEnabled,
initialData: _audioEnabled,
builder: (context, snapshot) {
_audioEnabled = snapshot.data!;
return Icon(
_audioEnabled ? Icons.mic : Icons.mic_off,
color: Colors.white,
);
}),
key: Key('microphone-button'),
onPressed: () => _onPressed(widget.onAudioEnabled!),
),
CircleButton(
child: const Icon(Icons.switch_camera, color: Colors.white),
key: Key('switch-camera-button'),
onPressed: () => _onPressed(widget.onSwitchCamera!),
),
CircleButton(
radius: 35,
child: const RotationTransition(
turns: AlwaysStoppedAnimation<double>(135 / 360),
child: Icon(
Icons.phone,
color: Colors.white,
size: 40,
),
),
color: Colors.red.withAlpha(200),
key: Key('hangup-button'),
onPressed: () => _onPressed(widget.onHangup!),
),
],
),
);
}
}