"Updated InfoPage, Home, and PrimaryControls widgets with new layout and functionality changes."

This commit is contained in:
OkaykOrhmn 2024-11-23 15:24:52 +03:30
parent 2663a8b98e
commit 5b37c89801
4 changed files with 271 additions and 160 deletions

View File

@ -7,6 +7,7 @@ import 'package:didvan/views/ai/info_state.dart';
import 'package:didvan/views/widgets/didvan/divider.dart'; import 'package:didvan/views/widgets/didvan/divider.dart';
import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/hoshan_app_bar.dart'; import 'package:didvan/views/widgets/hoshan_app_bar.dart';
import 'package:didvan/views/widgets/state_handlers/empty_connection.dart';
import 'package:didvan/views/widgets/video/chat_video_player.dart'; import 'package:didvan/views/widgets/video/chat_video_player.dart';
import 'package:didvan/views/widgets/video/primary_controls.dart'; import 'package:didvan/views/widgets/video/primary_controls.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -37,6 +38,11 @@ class _InfoPageState extends State<InfoPage> {
), ),
); );
} }
if (state.appState == AppState.failed) {
return Center(
child: EmptyConnection(onRetry: state.getTools),
);
}
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [

View File

@ -7,6 +7,9 @@ import 'package:didvan/services/network/request_helper.dart';
class InfoState extends CoreProvier { class InfoState extends CoreProvier {
late InfoModel infoModel; late InfoModel infoModel;
void getTools() async { void getTools() async {
appState = AppState.busy;
update();
final service = RequestService( final service = RequestService(
RequestHelper.info(), RequestHelper.info(),
); );

View File

@ -209,6 +209,18 @@ class _HomeState extends State<Home>
confrimTitle: 'بله', confrimTitle: 'بله',
dismissTitle: 'خیر', dismissTitle: 'خیر',
)); ));
} else if (context.read<HomeState>().tabController.index == 2) {
switch (context.read<AiState>().page) {
case 1:
context.read<AiState>().goToAi();
break;
case 2:
context.read<AiState>().goToTools();
break;
default:
_tabController.animateTo(0);
}
} else { } else {
_tabController.animateTo(0); _tabController.animateTo(0);
} }

View File

@ -20,6 +20,8 @@ class PrimaryControls extends StatefulWidget {
class _PrimaryControlsState extends State<PrimaryControls> { class _PrimaryControlsState extends State<PrimaryControls> {
late ChewieController chewieController; late ChewieController chewieController;
bool isAnimating = false; bool isAnimating = false;
bool isAnimatingForward = false;
bool isAnimatingBackward = false;
// bool isSpeedMenuOpen = false; // bool isSpeedMenuOpen = false;
double opacity = 1; double opacity = 1;
@ -67,187 +69,275 @@ class _PrimaryControlsState extends State<PrimaryControls> {
opacity = 0; opacity = 0;
} }
isAnimating = true; isAnimating = true;
isAnimating = true;
}); });
_startHideControlsTimer(); // Restart the timer on tap _startHideControlsTimer(); // Restart the timer on tap
} }
} }
void onClickScreen() {
if (opacity == 0) {
setState(() {
opacity = 1;
});
_startHideControlsTimer(); // Restart the timer on tap
} else {
setState(() {
opacity = 0;
});
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: AnimatedOpacity( child: Stack(
duration: const Duration(milliseconds: 400), children: [
opacity: opacity, forwardBtn(),
child: InkWell( backwardBtn(),
onTap: () { AnimatedOpacity(
if (opacity == 0) { duration: const Duration(milliseconds: 400),
setState(() { opacity: opacity,
opacity = 1;
});
_startHideControlsTimer(); // Restart the timer on tap
} else {
setState(() {
opacity = 0;
});
}
},
child: IgnorePointer(
ignoring: opacity == 0,
child: Stack( child: Stack(
children: [ children: [
Positioned( seekPositions(),
top: 0, IgnorePointer(
right: 0, ignoring: opacity == 0,
left: 0, child: Stack(
child: Container( children: [
padding: const EdgeInsets.symmetric( forground(),
horizontal: 12, vertical: 12), playAndPause(),
decoration: const BoxDecoration( ],
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.black,
Colors.black87,
Colors.black54,
Colors.black45,
Colors.black26,
Color.fromARGB(10, 0, 0, 0)
])),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
width: 120,
child: CustomDropdown<double>(
closedHeaderPadding: EdgeInsets.zero,
itemsListPadding: EdgeInsets.zero,
items: const [
0.25,
0.5,
0.75,
1,
1.25,
1.5,
1.75,
2
],
initialItem: 1,
listItemPadding: EdgeInsets.zero,
expandedHeaderPadding: EdgeInsets.zero,
hideSelectedFieldWhenExpanded: false,
// overlayHeight:
// chewieController.isFullScreen ? null : 54 * 8,
decoration: const CustomDropdownDecoration(
closedSuffixIcon: SizedBox(),
closedFillColor: Colors.transparent,
expandedBorderRadius:
DesignConfig.lowBorderRadius),
// hintText: "سرعت ویدیو",
listItemBuilder:
(context, item, isSelected, onItemSelect) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
child: Column(
children: [
DidvanText('x$item'),
if (item != 2)
const DidvanDivider(
verticalPadding: 8,
)
],
));
},
headerBuilder: (context, selectedItem, enabled) =>
const Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.more_vert_rounded,
size: 32,
color: Colors.white,
),
],
),
hintBuilder: (context, hint, enabled) =>
const SizedBox(),
onChanged: (value) async {
// isSpeedMenuOpen = false;
await chewieController.videoPlayerController
.setPlaybackSpeed(value!);
_startHideControlsTimer();
},
),
),
],
),
)),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 12),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black,
Colors.black87,
Colors.black54,
Colors.black45,
Colors.black26,
Color.fromARGB(10, 0, 0, 0)
])),
child: Row(
children: [
// _buildPlayPause(),
_buildProgressIndicator(),
_buildFullScreenToggle(),
],
),
), ),
), ),
Positioned.fill(
child: Center(
child: InkWell(
onTap: _handlePlay,
child: PlayBtnAnimation(
alwaysAnimate: false,
isAnimating: isAnimating,
onEnd: () => setState(
() => isAnimating = false,
),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withOpacity(0.4)),
child: Icon(
chewieController.isPlaying
? CupertinoIcons.pause_fill
: CupertinoIcons.play_fill,
color: Colors.white,
size: 32,
),
),
),
)))
], ],
), ),
), ),
],
),
);
}
Positioned seekPositions() {
return Positioned.fill(
child: Row(
children: [
Expanded(
child: InkWell(
onTap: onClickScreen,
onDoubleTap: () async {
if (position.value.inSeconds < 1) return;
setState(() => isAnimatingBackward = true);
Duration backward = Duration(seconds: position.value.inSeconds - 1);
await chewieController.videoPlayerController.seekTo(backward);
},
)),
Expanded(
child: InkWell(
onTap: onClickScreen,
onDoubleTap: () async {
if (position.value.inSeconds >
chewieController
.videoPlayerController.value.duration.inSeconds -
1) return;
setState(() => isAnimatingForward = true);
Duration forward = Duration(seconds: position.value.inSeconds + 1);
await chewieController.videoPlayerController.seekTo(forward);
},
)),
],
));
}
Positioned playAndPause() {
return Positioned.fill(
child: Center(
child: InkWell(
onTap: _handlePlay,
child: Opacity(
opacity: isAnimatingBackward || isAnimatingForward ? 0 : 1,
child: PlayBtnAnimation(
alwaysAnimate: false,
isAnimating: isAnimating,
onEnd: () => setState(
() => isAnimating = false,
),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.black.withOpacity(0.4)),
child: Icon(
chewieController.isPlaying
? CupertinoIcons.pause_fill
: CupertinoIcons.play_fill,
color: Colors.white,
size: 32,
),
),
),
),
)));
}
Positioned forwardBtn() {
return Positioned.fill(
child: Center(
child: Opacity(
opacity: isAnimatingForward ? 1 : 0,
child: PlayBtnAnimation(
alwaysAnimate: false,
isAnimating: isAnimatingForward,
onEnd: () => setState(
() => isAnimatingForward = false,
),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.black.withOpacity(0.4)),
child: const Icon(
Icons.forward_5_rounded,
color: Colors.white,
size: 32,
),
),
),
)));
}
Positioned backwardBtn() {
return Positioned.fill(
child: Center(
child: Opacity(
opacity: isAnimatingBackward ? 1 : 0,
child: PlayBtnAnimation(
alwaysAnimate: false,
isAnimating: isAnimatingBackward,
onEnd: () => setState(
() => isAnimatingBackward = false,
),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.black.withOpacity(0.4)),
child: const Icon(
Icons.replay_5_rounded,
color: Colors.white,
size: 32,
),
),
),
)));
}
Positioned forground() {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black,
Colors.black87,
Colors.black54,
Colors.black45,
Colors.black26,
Color.fromARGB(10, 0, 0, 0)
])),
child: Row(
children: [
// _buildPlayPause(),
_buildProgressIndicator(),
_buildFullScreenToggle(),
],
), ),
), ),
); );
} }
Positioned speedPlayBackButtons() {
return Positioned(
top: 0,
right: 0,
left: 0,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.black,
Colors.black87,
Colors.black54,
Colors.black45,
Colors.black26,
Color.fromARGB(10, 0, 0, 0)
])),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
width: 120,
child: CustomDropdown<double>(
closedHeaderPadding: EdgeInsets.zero,
itemsListPadding: EdgeInsets.zero,
items: const [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
initialItem: 1,
listItemPadding: EdgeInsets.zero,
expandedHeaderPadding: EdgeInsets.zero,
hideSelectedFieldWhenExpanded: false,
// overlayHeight:
// chewieController.isFullScreen ? null : 54 * 8,
decoration: const CustomDropdownDecoration(
closedSuffixIcon: SizedBox(),
closedFillColor: Colors.transparent,
expandedBorderRadius: DesignConfig.lowBorderRadius),
// hintText: "سرعت ویدیو",
listItemBuilder: (context, item, isSelected, onItemSelect) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
child: Column(
children: [
DidvanText('x$item'),
if (item != 2)
const DidvanDivider(
verticalPadding: 8,
)
],
));
},
headerBuilder: (context, selectedItem, enabled) => const Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.more_vert_rounded,
size: 32,
color: Colors.white,
),
],
),
hintBuilder: (context, hint, enabled) => const SizedBox(),
onChanged: (value) async {
// isSpeedMenuOpen = false;
await chewieController.videoPlayerController
.setPlaybackSpeed(value!);
_startHideControlsTimer();
},
),
),
],
),
));
}
Widget _buildProgressIndicator() { Widget _buildProgressIndicator() {
return Expanded( return Expanded(
child: ValueListenableBuilder<Duration>( child: ValueListenableBuilder<Duration>(