yumi-flutter/lib/modules/room/background/room_background_upload_page.dart
2026-05-07 10:06:02 +08:00

296 lines
10 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:image_picker/image_picker.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/modules/room/background/room_background_apply_service.dart';
import 'package:yumi/modules/room/background/room_background_assets.dart';
import 'package:yumi/shared/tools/sc_loading_manager.dart';
import 'package:yumi/ui_kit/components/sc_tts.dart';
import 'package:yumi/ui_kit/components/appbar/socialchat_appbar.dart';
import 'package:yumi/ui_kit/theme/socialchat_theme.dart';
class RoomBackgroundUploadPage extends StatefulWidget {
const RoomBackgroundUploadPage({super.key});
@override
State<RoomBackgroundUploadPage> createState() =>
_RoomBackgroundUploadPageState();
}
class _RoomBackgroundUploadPageState extends State<RoomBackgroundUploadPage> {
final ImagePicker _picker = ImagePicker();
File? _selectedImage;
bool _isSaving = false;
Future<void> _pickImage() async {
if (_isSaving) {
return;
}
final pickedFile = await _picker.pickImage(
source: ImageSource.gallery,
imageQuality: 90,
maxWidth: 1920,
maxHeight: 1080,
);
if (pickedFile == null || !mounted) {
return;
}
setState(() {
_selectedImage = File(pickedFile.path);
});
}
Future<void> _saveBackground() async {
final selectedImage = _selectedImage;
if (selectedImage == null || _isSaving) {
return;
}
final localizations = SCAppLocalizations.of(context)!;
setState(() {
_isSaving = true;
});
SCLoadingManager.show(context: context);
try {
final roomBackground = await RoomBackgroundApplyService.apply(
context,
selectedImage.path,
);
if (!mounted) {
return;
}
SCTts.show(localizations.operationSuccessful);
SCNavigatorUtils.goBackWithParams(context, roomBackground);
} catch (e, stackTrace) {
debugPrint("[Room Background Save] failed error=$e");
debugPrint("[Room Background Save] stackTrace=$stackTrace");
if (mounted) {
SCTts.show(localizations.operationFail);
}
} finally {
SCLoadingManager.hide();
if (mounted) {
setState(() {
_isSaving = false;
});
}
}
}
@override
Widget build(BuildContext context) {
final localizations = SCAppLocalizations.of(context)!;
return Stack(
children: [
Image.asset(
SCGlobalConfig.businessLogicStrategy.getLanguagePageBackgroundImage(),
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
fit: BoxFit.fill,
),
Scaffold(
backgroundColor: Colors.transparent,
appBar: SocialChatStandardAppBar(
title: localizations.customBackground,
actions: const [],
backButtonColor: Colors.white,
backgroundColor: Colors.transparent,
),
body: Container(
color: const Color(0xff0F0F0F),
child: SingleChildScrollView(
padding: EdgeInsets.fromLTRB(18.w, 20.w, 18.w, 28.w),
child: Column(
children: [
GestureDetector(
onTap: _pickImage,
child: Container(
width: 132.w,
height: 170.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.w),
color: const Color(0xff143B34),
border: Border.all(
color: SocialChatTheme.primaryLight,
width: 1.w,
),
),
child:
_selectedImage != null
? ClipRRect(
borderRadius: BorderRadius.circular(14.w),
child: Image.file(
_selectedImage!,
fit: BoxFit.cover,
),
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.file_upload_outlined,
color: Colors.white,
size: 28.w,
),
SizedBox(height: 10.w),
Text(
localizations.goToUpload,
style: TextStyle(
color: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w500,
),
),
],
),
),
),
SizedBox(height: 16.w),
Text(
localizations.pleaseUploadAccordingToExample,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white54,
fontSize: 13.sp,
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 20.w),
Text(
localizations.example,
style: TextStyle(
color: SocialChatTheme.primaryLight,
fontSize: 18.sp,
fontWeight: FontWeight.w700,
),
),
SizedBox(height: 16.w),
SizedBox(
height: 300.w,
child: ListView.separated(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 28.w),
itemCount: roomBackgroundExampleAssets.length,
separatorBuilder: (_, __) => SizedBox(width: 16.w),
itemBuilder:
(context, index) => _RoomBackgroundExampleCard(
assetPath: roomBackgroundExampleAssets[index],
),
),
),
SizedBox(height: 16.w),
Text(
localizations.approvedWithinOneMinute,
style: TextStyle(
color: const Color(0xffF26F6F),
fontSize: 13.sp,
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 28.w),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _selectedImage == null ? null : _saveBackground,
child: Opacity(
opacity: _selectedImage == null || _isSaving ? 0.45 : 1,
child: Container(
height: 48.w,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(999.w),
gradient: LinearGradient(
colors: [
SocialChatTheme.primaryLight,
const Color(0xff8BF2D0),
],
),
),
child: Text(
localizations.save,
style: TextStyle(
color: const Color(0xff0B2823),
fontSize: 16.sp,
fontWeight: FontWeight.w700,
),
),
),
),
),
],
),
),
),
),
],
);
}
}
class _RoomBackgroundExampleCard extends StatelessWidget {
const _RoomBackgroundExampleCard({required this.assetPath});
final String assetPath;
@override
Widget build(BuildContext context) {
final localizations = SCAppLocalizations.of(context)!;
return SizedBox(
width: 140.w,
height: 300.w,
child: ClipRRect(
borderRadius: BorderRadius.circular(14.w),
child: Stack(
children: [
Positioned.fill(
child: Image.asset(
assetPath,
fit: BoxFit.cover,
errorBuilder:
(_, __, ___) => Container(
color: const Color(0xff143B34),
alignment: Alignment.center,
child: Icon(
Icons.image_outlined,
size: 42.w,
color: Colors.white.withValues(alpha: 0.12),
),
),
),
),
Positioned(
left: 12.w,
right: 12.w,
bottom: 18.w,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 8.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(999.w),
border: Border.all(
color: SocialChatTheme.primaryLight,
width: 1.w,
),
color: const Color(0xff1B4A40).withValues(alpha: 0.82),
),
child: Text(
localizations.staticOrGifImage,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 11.sp,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
),
);
}
}