yumi-flutter/lib/modules/room/background/room_background_preview_page.dart

435 lines
12 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:yumi/app/constants/sc_global_config.dart';
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
import 'package:yumi/app_localizations.dart';
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
import 'package:yumi/ui_kit/widgets/room/room_bottom_widget.dart';
import 'package:yumi/ui_kit/widgets/room/room_head_widget.dart';
import 'package:yumi/ui_kit/widgets/room/room_online_user_widget.dart';
class RoomBackgroundPreviewPage extends StatelessWidget {
const RoomBackgroundPreviewPage({super.key, this.backgroundPath});
final String? backgroundPath;
@override
Widget build(BuildContext context) {
final bottomPadding = MediaQuery.of(context).padding.bottom;
final localizations = SCAppLocalizations.of(context)!;
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: [
Positioned.fill(child: _PreviewBackground(path: backgroundPath)),
Positioned.fill(child: _PreviewRoomLayer()),
Positioned(
left: 24.w,
right: 24.w,
bottom: 148.w + bottomPadding,
child: _PreviewPrimaryButton(
text: localizations.endPreview,
onTap: () => SCNavigatorUtils.goBackWithParams(context, true),
),
),
Positioned(
left: 24.w,
right: 24.w,
bottom: 90.w + bottomPadding,
child: _PreviewSecondaryButton(
text: localizations.selectAgain,
onTap: () => SCNavigatorUtils.goBackWithParams(context, false),
),
),
],
),
);
}
}
class _PreviewBackground extends StatelessWidget {
const _PreviewBackground({this.path});
final String? path;
@override
Widget build(BuildContext context) {
final value = (path ?? "").trim();
if (value.startsWith("http://") || value.startsWith("https://")) {
return Image.network(
value,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const _DefaultPreviewBackground(),
);
}
if (value.startsWith("assets/") || value.startsWith("sc_images/")) {
return Image.asset(
value,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const _DefaultPreviewBackground(),
);
}
if (value.isNotEmpty) {
final file = File(value);
if (file.existsSync()) {
return Image.file(
file,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => const _DefaultPreviewBackground(),
);
}
}
return const _DefaultPreviewBackground();
}
}
class _DefaultPreviewBackground extends StatelessWidget {
const _DefaultPreviewBackground();
@override
Widget build(BuildContext context) {
return Image.asset(
SCGlobalConfig.businessLogicStrategy.getVoiceRoomDefaultBackgroundImage(),
fit: BoxFit.cover,
);
}
}
class _PreviewRoomLayer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(height: ScreenUtil().setWidth(42)),
IgnorePointer(child: RoomHeadWidget()),
SizedBox(height: 5.w),
const IgnorePointer(child: RoomOnlineUserWidget()),
const IgnorePointer(child: _PreviewSeat10()),
Expanded(child: _PreviewChatArea()),
const IgnorePointer(child: RoomBottomWidget()),
],
);
}
}
class _PreviewSeat10 extends StatelessWidget {
const _PreviewSeat10();
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 3.w, left: 10.w, right: 10.w),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: List.generate(
5,
(index) => Expanded(
child: _PreviewSeatItem(index: index, locked: index == 1),
),
),
),
Row(
children: List.generate(5, (index) {
final seatIndex = index + 5;
return Expanded(
child: _PreviewSeatItem(
index: seatIndex,
locked: seatIndex == 6,
),
);
}),
),
],
),
);
}
}
class _PreviewSeatItem extends StatelessWidget {
const _PreviewSeatItem({required this.index, required this.locked});
final int index;
final bool locked;
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 55.w,
height: 55.w,
child: Image.asset(
locked
? "sc_images/room/sc_icon_seat_lock.png"
: "sc_images/room/sc_icon_seat_open.png",
width: 52.w,
height: 52.w,
),
),
SizedBox(
height: 16.w,
child: Center(
child: Text(
"NO.${index + 1}",
style: TextStyle(
color: Colors.white,
fontSize: 10.sp,
fontWeight: FontWeight.w600,
),
),
),
),
],
);
}
}
class _PreviewChatArea extends StatefulWidget {
@override
State<_PreviewChatArea> createState() => _PreviewChatAreaState();
}
class _PreviewChatAreaState extends State<_PreviewChatArea> {
int _selectedTabIndex = 0;
void _selectTab(int index) {
if (_selectedTabIndex == index) {
return;
}
setState(() {
_selectedTabIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
left: 0,
right: 0,
top: 0,
child: _PreviewChatTabs(
selectedIndex: _selectedTabIndex,
onTap: _selectTab,
),
),
Positioned(
left: 24.w,
right: 24.w,
bottom: 166.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
_PreviewChatBubble(text: "Hello My Friends!"),
SizedBox(height: 12.w),
_PreviewGiftBubble(),
],
),
),
],
);
}
}
class _PreviewChatTabs extends StatelessWidget {
const _PreviewChatTabs({required this.selectedIndex, required this.onTap});
final int selectedIndex;
final ValueChanged<int> onTap;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 32.w,
child: ListView.builder(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 8.w),
itemCount: 3,
itemBuilder: (context, index) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => onTap(index),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.w),
child: Center(
child: Image.asset(
_assetFor(index, selectedIndex == index),
height: 26.w,
fit: BoxFit.contain,
),
),
),
);
},
),
);
}
String _assetFor(int index, bool selected) {
switch (index) {
case 0:
return selected
? "sc_images/room/sc_icon_room_chat_tab_all_selected.png"
: "sc_images/room/sc_icon_room_chat_tab_all_unselected.png";
case 1:
return selected
? "sc_images/room/sc_icon_room_chat_tab_chat_selected.png"
: "sc_images/room/sc_icon_room_chat_tab_chat_unselected.png";
case 2:
default:
return selected
? "sc_images/room/sc_icon_room_chat_tab_gift_selected.png"
: "sc_images/room/sc_icon_room_chat_tab_gift_unselected.png";
}
}
}
class _PreviewChatBubble extends StatelessWidget {
const _PreviewChatBubble({required this.text});
final String text;
@override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints(maxWidth: 276.w),
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 10.w),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.42),
borderRadius: BorderRadius.circular(10.w),
),
child: Text(
text,
style: TextStyle(
color: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w700,
),
),
);
}
}
class _PreviewGiftBubble extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints(maxWidth: 300.w),
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.w),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.44),
borderRadius: BorderRadius.circular(10.w),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
"Send To User Name2",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w700,
),
),
),
SizedBox(width: 10.w),
ClipOval(
child: Image.asset(
"sc_images/general/sc_icon_avar_defalt.png",
width: 32.w,
height: 32.w,
fit: BoxFit.cover,
),
),
SizedBox(width: 6.w),
Text(
"*1",
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
fontWeight: FontWeight.w800,
),
),
],
),
);
}
}
class _PreviewPrimaryButton extends StatelessWidget {
const _PreviewPrimaryButton({required this.text, required this.onTap});
final String text;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: Container(
height: 48.w,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(999.w),
gradient: LinearGradient(
colors: [SocialChatTheme.primaryLight, const Color(0xff8BF2D0)],
),
),
child: Text(
text,
style: TextStyle(
color: const Color(0xff0B2823),
fontSize: 18.sp,
fontWeight: FontWeight.w700,
),
),
),
);
}
}
class _PreviewSecondaryButton extends StatelessWidget {
const _PreviewSecondaryButton({required this.text, required this.onTap});
final String text;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: Container(
height: 48.w,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xff06372F).withValues(alpha: 0.9),
borderRadius: BorderRadius.circular(999.w),
border: Border.all(color: SocialChatTheme.primaryLight, width: 1.w),
),
child: Text(
text,
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.w700,
),
),
),
);
}
}