435 lines
12 KiB
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,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|