feat: 全屏选择合集
This commit is contained in:
@ -11,6 +11,7 @@ class EpisodeBottomSheet {
|
|||||||
final Function changeFucCall;
|
final Function changeFucCall;
|
||||||
final int? cid;
|
final int? cid;
|
||||||
final double? sheetHeight;
|
final double? sheetHeight;
|
||||||
|
bool isFullScreen = false;
|
||||||
|
|
||||||
EpisodeBottomSheet({
|
EpisodeBottomSheet({
|
||||||
required this.episodes,
|
required this.episodes,
|
||||||
@ -20,6 +21,7 @@ class EpisodeBottomSheet {
|
|||||||
required this.changeFucCall,
|
required this.changeFucCall,
|
||||||
this.cid,
|
this.cid,
|
||||||
this.sheetHeight,
|
this.sheetHeight,
|
||||||
|
this.isFullScreen = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget buildEpisodeListItem(
|
Widget buildEpisodeListItem(
|
||||||
@ -74,60 +76,69 @@ class EpisodeBottomSheet {
|
|||||||
'合集(${episodes.length})',
|
'合集(${episodes.length})',
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: !isFullScreen
|
||||||
IconButton(
|
? [
|
||||||
icon: const Icon(Icons.close, size: 20),
|
IconButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
icon: const Icon(Icons.close, size: 20),
|
||||||
),
|
onPressed: () => Navigator.pop(context),
|
||||||
const SizedBox(width: 14),
|
),
|
||||||
],
|
const SizedBox(width: 14),
|
||||||
|
]
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildShowContent(BuildContext context) {
|
||||||
|
final ItemScrollController itemScrollController = ItemScrollController();
|
||||||
|
int currentIndex = episodes.indexWhere((dynamic e) => e.cid == currentCid);
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (BuildContext context, StateSetter setState) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
itemScrollController.jumpTo(index: currentIndex);
|
||||||
|
});
|
||||||
|
return Container(
|
||||||
|
height: sheetHeight,
|
||||||
|
color: Theme.of(context).colorScheme.background,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
buildTitle(),
|
||||||
|
Expanded(
|
||||||
|
child: Material(
|
||||||
|
child: PageStorage(
|
||||||
|
bucket: PageStorageBucket(),
|
||||||
|
child: ScrollablePositionedList.builder(
|
||||||
|
itemScrollController: itemScrollController,
|
||||||
|
itemCount: episodes.length + 1,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
bool isLastItem = index == episodes.length;
|
||||||
|
bool isCurrentIndex = currentIndex == index;
|
||||||
|
return isLastItem
|
||||||
|
? SizedBox(
|
||||||
|
height:
|
||||||
|
MediaQuery.of(context).padding.bottom + 20,
|
||||||
|
)
|
||||||
|
: buildEpisodeListItem(
|
||||||
|
episodes[index],
|
||||||
|
index,
|
||||||
|
isCurrentIndex,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// The [BuildContext] of the widget that calls the bottom sheet.
|
/// The [BuildContext] of the widget that calls the bottom sheet.
|
||||||
PersistentBottomSheetController show(BuildContext context) {
|
PersistentBottomSheetController show(BuildContext context) {
|
||||||
final ItemScrollController itemScrollController = ItemScrollController();
|
|
||||||
int currentIndex = episodes.indexWhere((dynamic e) => e.cid == currentCid);
|
|
||||||
final PersistentBottomSheetController btmSheetCtr = showBottomSheet(
|
final PersistentBottomSheetController btmSheetCtr = showBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return StatefulBuilder(
|
return buildShowContent(context);
|
||||||
builder: (BuildContext context, StateSetter setState) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
itemScrollController.jumpTo(index: currentIndex);
|
|
||||||
});
|
|
||||||
return Container(
|
|
||||||
height: sheetHeight,
|
|
||||||
color: Theme.of(context).colorScheme.background,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
buildTitle(),
|
|
||||||
Expanded(
|
|
||||||
child: Material(
|
|
||||||
child: ScrollablePositionedList.builder(
|
|
||||||
itemScrollController: itemScrollController,
|
|
||||||
itemCount: episodes.length + 1,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
bool isLastItem = index == episodes.length;
|
|
||||||
bool isCurrentIndex = currentIndex == index;
|
|
||||||
return isLastItem
|
|
||||||
? SizedBox(
|
|
||||||
height:
|
|
||||||
MediaQuery.of(context).padding.bottom + 20,
|
|
||||||
)
|
|
||||||
: buildEpisodeListItem(
|
|
||||||
episodes[index],
|
|
||||||
index,
|
|
||||||
isCurrentIndex,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return btmSheetCtr;
|
return btmSheetCtr;
|
||||||
|
|||||||
@ -15,6 +15,10 @@ import 'package:pilipala/utils/id_utils.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
|
import '../../../common/pages_bottom_sheet.dart';
|
||||||
|
import '../../../models/common/video_episode_type.dart';
|
||||||
|
import '../../../utils/drawer.dart';
|
||||||
|
|
||||||
class BangumiIntroController extends GetxController {
|
class BangumiIntroController extends GetxController {
|
||||||
// 视频bvid
|
// 视频bvid
|
||||||
String bvid = Get.parameters['bvid']!;
|
String bvid = Get.parameters['bvid']!;
|
||||||
@ -291,4 +295,29 @@ class BangumiIntroController extends GetxController {
|
|||||||
int aid = episodes[nextIndex].aid!;
|
int aid = episodes[nextIndex].aid!;
|
||||||
changeSeasonOrbangu(bvid, cid, aid);
|
changeSeasonOrbangu(bvid, cid, aid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 播放器底栏 选集 回调
|
||||||
|
void showEposideHandler() {
|
||||||
|
late List episodes = bangumiDetail.value.episodes!;
|
||||||
|
VideoEpidoesType dataType = VideoEpidoesType.bangumiEpisode;
|
||||||
|
if (episodes.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VideoDetailController videoDetailCtr =
|
||||||
|
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||||
|
DrawerUtils.showRightDialog(
|
||||||
|
child: EpisodeBottomSheet(
|
||||||
|
episodes: episodes,
|
||||||
|
currentCid: videoDetailCtr.cid.value,
|
||||||
|
dataType: dataType,
|
||||||
|
context: Get.context!,
|
||||||
|
sheetHeight: Get.size.height,
|
||||||
|
isFullScreen: true,
|
||||||
|
changeFucCall: (item, index) {
|
||||||
|
changeSeasonOrbangu(item.bvid, item.cid, item.aid);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
},
|
||||||
|
).buildShowContent(Get.context!),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,9 @@ import 'package:pilipala/utils/id_utils.dart';
|
|||||||
import 'package:pilipala/utils/storage.dart';
|
import 'package:pilipala/utils/storage.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
|
import '../../../../common/pages_bottom_sheet.dart';
|
||||||
|
import '../../../../models/common/video_episode_type.dart';
|
||||||
|
import '../../../../utils/drawer.dart';
|
||||||
import '../related/index.dart';
|
import '../related/index.dart';
|
||||||
import 'widgets/group_panel.dart';
|
import 'widgets/group_panel.dart';
|
||||||
|
|
||||||
@ -54,7 +57,7 @@ class VideoIntroController extends GetxController {
|
|||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
String heroTag = '';
|
String heroTag = '';
|
||||||
late ModelResult modelResult;
|
late ModelResult modelResult;
|
||||||
late PersistentBottomSheetController? bottomSheetController;
|
PersistentBottomSheetController? bottomSheetController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@ -562,4 +565,48 @@ class VideoIntroController extends GetxController {
|
|||||||
hiddenEpisodeBottomSheet() {
|
hiddenEpisodeBottomSheet() {
|
||||||
bottomSheetController?.close();
|
bottomSheetController?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 播放器底栏 选集 回调
|
||||||
|
void showEposideHandler() {
|
||||||
|
late List episodes;
|
||||||
|
VideoEpidoesType dataType = VideoEpidoesType.videoEpisode;
|
||||||
|
if (videoDetail.value.ugcSeason != null) {
|
||||||
|
dataType = VideoEpidoesType.videoEpisode;
|
||||||
|
final List<SectionItem> sections = videoDetail.value.ugcSeason!.sections!;
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
final List<EpisodeItem> episodesList = sections[i].episodes!;
|
||||||
|
for (int j = 0; j < episodesList.length; j++) {
|
||||||
|
if (episodesList[j].cid == lastPlayCid.value) {
|
||||||
|
episodes = episodesList;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (videoDetail.value.pages != null &&
|
||||||
|
videoDetail.value.pages!.length > 1) {
|
||||||
|
dataType = VideoEpidoesType.videoPart;
|
||||||
|
episodes = videoDetail.value.pages!;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawerUtils.showRightDialog(
|
||||||
|
child: EpisodeBottomSheet(
|
||||||
|
episodes: episodes,
|
||||||
|
currentCid: lastPlayCid.value,
|
||||||
|
dataType: dataType,
|
||||||
|
context: Get.context!,
|
||||||
|
sheetHeight: Get.size.height,
|
||||||
|
isFullScreen: true,
|
||||||
|
changeFucCall: (item, index) {
|
||||||
|
if (dataType == VideoEpidoesType.videoEpisode) {
|
||||||
|
changeSeasonOrbangu(IdUtils.av2bv(item.aid), item.cid, item.aid);
|
||||||
|
}
|
||||||
|
if (dataType == VideoEpidoesType.videoPart) {
|
||||||
|
changeSeasonOrbangu(bvid, item.cid, null);
|
||||||
|
}
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
},
|
||||||
|
).buildShowContent(Get.context!),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -373,7 +373,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
/// 点赞收藏转发
|
/// 点赞收藏转发
|
||||||
actionGrid(context, videoIntroController),
|
actionGrid(context, videoIntroController),
|
||||||
// 合集
|
// 合集 videoPart 简洁
|
||||||
if (widget.videoDetail!.ugcSeason != null) ...[
|
if (widget.videoDetail!.ugcSeason != null) ...[
|
||||||
Obx(
|
Obx(
|
||||||
() => SeasonPanel(
|
() => SeasonPanel(
|
||||||
@ -383,11 +383,16 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
: widget.videoDetail!.pages!.first.cid,
|
: widget.videoDetail!.pages!.first.cid,
|
||||||
sheetHeight: sheetHeight,
|
sheetHeight: sheetHeight,
|
||||||
changeFuc: (bvid, cid, aid) =>
|
changeFuc: (bvid, cid, aid) =>
|
||||||
videoIntroController.changeSeasonOrbangu(bvid, cid, aid),
|
videoIntroController.changeSeasonOrbangu(
|
||||||
|
bvid,
|
||||||
|
cid,
|
||||||
|
aid,
|
||||||
|
),
|
||||||
videoIntroCtr: videoIntroController,
|
videoIntroCtr: videoIntroController,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
// 合集 videoEpisode
|
||||||
if (widget.videoDetail!.pages != null &&
|
if (widget.videoDetail!.pages != null &&
|
||||||
widget.videoDetail!.pages!.length > 1) ...[
|
widget.videoDetail!.pages!.length > 1) ...[
|
||||||
Obx(
|
Obx(
|
||||||
|
|||||||
@ -60,6 +60,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void changeFucCall(item, i) async {
|
void changeFucCall(item, i) async {
|
||||||
|
print('pages changeFucCall');
|
||||||
widget.changeFuc?.call(item.cid);
|
widget.changeFuc?.call(item.cid);
|
||||||
currentIndex.value = i;
|
currentIndex.value = i;
|
||||||
_bottomSheetController?.close();
|
_bottomSheetController?.close();
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class SeasonPanel extends StatefulWidget {
|
|||||||
class _SeasonPanelState extends State<SeasonPanel> {
|
class _SeasonPanelState extends State<SeasonPanel> {
|
||||||
late List<EpisodeItem> episodes;
|
late List<EpisodeItem> episodes;
|
||||||
late int cid;
|
late int cid;
|
||||||
late int currentIndex;
|
late RxInt currentIndex = (-1).obs;
|
||||||
final String heroTag = Get.arguments['heroTag'];
|
final String heroTag = Get.arguments['heroTag'];
|
||||||
late VideoDetailController _videoDetailController;
|
late VideoDetailController _videoDetailController;
|
||||||
final ItemScrollController itemScrollController = ItemScrollController();
|
final ItemScrollController itemScrollController = ItemScrollController();
|
||||||
@ -57,11 +57,10 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 取对应 season_id 的 episodes
|
/// 取对应 season_id 的 episodes
|
||||||
currentIndex = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
currentIndex.value = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
||||||
_videoDetailController.cid.listen((int p0) {
|
_videoDetailController.cid.listen((int p0) {
|
||||||
cid = p0;
|
cid = p0;
|
||||||
setState(() {});
|
currentIndex.value = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
||||||
currentIndex = episodes.indexWhere((EpisodeItem e) => e.cid == cid);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,9 +70,8 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
item.cid,
|
item.cid,
|
||||||
item.aid,
|
item.aid,
|
||||||
);
|
);
|
||||||
currentIndex = i;
|
currentIndex.value = i;
|
||||||
_bottomSheetController?.close();
|
_bottomSheetController?.close();
|
||||||
setState(() {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildEpisodeListItem(
|
Widget buildEpisodeListItem(
|
||||||
@ -148,10 +146,10 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
|||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Text(
|
Obx(() => Text(
|
||||||
'${currentIndex + 1}/${episodes.length}',
|
'${currentIndex.value + 1}/${episodes.length}',
|
||||||
style: Theme.of(context).textTheme.labelMedium,
|
style: Theme.of(context).textTheme.labelMedium,
|
||||||
),
|
)),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
const Icon(
|
const Icon(
|
||||||
Icons.arrow_forward_ios_outlined,
|
Icons.arrow_forward_ios_outlined,
|
||||||
|
|||||||
@ -178,6 +178,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
if (isFullScreen) {
|
if (isFullScreen) {
|
||||||
vdCtr.hiddenReplyReplyPanel();
|
vdCtr.hiddenReplyReplyPanel();
|
||||||
videoIntroController.hiddenEpisodeBottomSheet();
|
videoIntroController.hiddenEpisodeBottomSheet();
|
||||||
|
vdCtr.bottomList.insert(3, BottomControlType.episode);
|
||||||
|
} else {
|
||||||
|
vdCtr.bottomList.removeAt(3);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -294,17 +297,20 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
() {
|
() {
|
||||||
return !vdCtr.autoPlay.value
|
return !vdCtr.autoPlay.value
|
||||||
? const SizedBox()
|
? const SizedBox()
|
||||||
: PLVideoPlayer(
|
: Obx(
|
||||||
controller: plPlayerController!,
|
() => PLVideoPlayer(
|
||||||
headerControl: vdCtr.headerControl,
|
controller: plPlayerController!,
|
||||||
danmuWidget: Obx(
|
headerControl: vdCtr.headerControl,
|
||||||
() => PlDanmaku(
|
danmuWidget: PlDanmaku(
|
||||||
key: Key(vdCtr.danmakuCid.value.toString()),
|
key: Key(vdCtr.danmakuCid.value.toString()),
|
||||||
cid: vdCtr.danmakuCid.value,
|
cid: vdCtr.danmakuCid.value,
|
||||||
playerController: plPlayerController!,
|
playerController: plPlayerController!,
|
||||||
),
|
),
|
||||||
|
bottomList: vdCtr.bottomList,
|
||||||
|
showEposideCb: () => vdCtr.videoType == SearchType.video
|
||||||
|
? videoIntroController.showEposideHandler()
|
||||||
|
: bangumiIntroController.showEposideHandler(),
|
||||||
),
|
),
|
||||||
bottomList: vdCtr.bottomList,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ enum BottomControlType {
|
|||||||
next,
|
next,
|
||||||
time,
|
time,
|
||||||
space,
|
space,
|
||||||
|
episode,
|
||||||
fit,
|
fit,
|
||||||
speed,
|
speed,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
|
|||||||
@ -37,6 +37,7 @@ class PLVideoPlayer extends StatefulWidget {
|
|||||||
this.bottomList,
|
this.bottomList,
|
||||||
this.customWidget,
|
this.customWidget,
|
||||||
this.customWidgets,
|
this.customWidgets,
|
||||||
|
this.showEposideCb,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ class PLVideoPlayer extends StatefulWidget {
|
|||||||
|
|
||||||
final Widget? customWidget;
|
final Widget? customWidget;
|
||||||
final List<Widget>? customWidgets;
|
final List<Widget>? customWidgets;
|
||||||
|
final Function? showEposideCb;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PLVideoPlayer> createState() => _PLVideoPlayerState();
|
State<PLVideoPlayer> createState() => _PLVideoPlayerState();
|
||||||
@ -267,6 +269,24 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
/// 空白占位
|
/// 空白占位
|
||||||
BottomControlType.space: const Spacer(),
|
BottomControlType.space: const Spacer(),
|
||||||
|
|
||||||
|
/// 选集
|
||||||
|
BottomControlType.episode: SizedBox(
|
||||||
|
height: 30,
|
||||||
|
width: 30,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
widget.showEposideCb?.call();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'选集',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
/// 画面比例
|
/// 画面比例
|
||||||
BottomControlType.fit: SizedBox(
|
BottomControlType.fit: SizedBox(
|
||||||
height: 30,
|
height: 30,
|
||||||
|
|||||||
39
lib/utils/drawer.dart
Normal file
39
lib/utils/drawer.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
|
|
||||||
|
class DrawerUtils {
|
||||||
|
static void showRightDialog({
|
||||||
|
required Widget child,
|
||||||
|
double width = 400,
|
||||||
|
bool useSystem = false,
|
||||||
|
}) {
|
||||||
|
SmartDialog.show(
|
||||||
|
alignment: Alignment.topRight,
|
||||||
|
animationBuilder: (controller, child, animationParam) {
|
||||||
|
return SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
|
begin: const Offset(1, 0),
|
||||||
|
end: Offset.zero,
|
||||||
|
).animate(controller.view),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
useSystem: useSystem,
|
||||||
|
maskColor: Colors.black.withOpacity(0.5),
|
||||||
|
animationTime: const Duration(milliseconds: 200),
|
||||||
|
builder: (context) => Container(
|
||||||
|
width: width,
|
||||||
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
child: SafeArea(
|
||||||
|
left: false,
|
||||||
|
right: false,
|
||||||
|
bottom: false,
|
||||||
|
child: MediaQuery(
|
||||||
|
data: const MediaQueryData(padding: EdgeInsets.zero),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user