ã…감정표현 2회 재생 후 기본값으로 ë³돌 변경

This commit is contained in:
2026-06-24 17:55:03 +09:00
parent 44100e387b
commit 68db5b7b45
10 changed files with 41 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 MiB

After

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 928 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

View File

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
import '../models/chat_message.dart'; import '../models/chat_message.dart';
import '../services/chat_service.dart'; import '../services/chat_service.dart';
import 'dart:math'; //26.06.24 추가 import 'dart:math';
class ChatScreen extends StatefulWidget { class ChatScreen extends StatefulWidget {
@@ -32,39 +32,36 @@ class _ChatScreenState extends State<ChatScreen> {
_addInitialMessage(); _addInitialMessage();
} }
//26.06.24 추가 시작 (String, int) _getVideoInfo(int emotionCategory) {
String _getVideoFileName(int emotionCategory) {
switch(emotionCategory) { switch(emotionCategory) {
case 1: case 1:
return 'default.mp4'; // DEFAULT return ('default.mp4', 10); // DEFAULT
case 2: case 2:
return 'joy.mp4'; // JOY return ('joy.mp4', 8); // JOY
case 3: case 3:
return 'thinking.mp4'; // THINKING return ('thinking.mp4', 10); // THINKING
case 4: case 4:
return 'realization.mp4'; // REALIZATION return ('realization.mp4', 10); // REALIZATION
case 5: case 5:
return 'angry.mp4'; // ANGER return ('angry.mp4', 10); // ANGER
case 6: case 6:
return 'thirst.mp4'; // THIRST return ('thirst.mp4', 10); // THIRST
case 7: case 7:
return 'cold.mp4'; // COLD return ('cold.mp4', 8); // COLD
default: default:
return 'default.mp4'; // 기본값 return ('default.mp4', 10); // 기본값
} }
} }
void _initializeVideo(int emotionCategory) { void _initializeVideo(int emotionCategory) {
final videoFileName = _getVideoFileName(emotionCategory); final (videoFileName, duration) = _getVideoInfo(emotionCategory);
print('비디오 변경: emotion=$emotionCategory$videoFileName'); print('비디오 변경: emotion=$emotionCategory$videoFileName (${duration}초)');
// 새 비디오 컨트롤러 생성 // 새 비디오 컨트롤러 생성
final newController = VideoPlayerController.asset('assets/videos/$videoFileName'); final newController = VideoPlayerController.asset('assets/videos/$videoFileName');
// 새 비디오를 먼저 로드
newController.initialize().then((_) { newController.initialize().then((_) {
// 로드 완료 후에 기존 컨트롤러 교체
try { try {
if (_videoController.hasListeners) { if (_videoController.hasListeners) {
_videoController.dispose(); _videoController.dispose();
@@ -73,7 +70,6 @@ class _ChatScreenState extends State<ChatScreen> {
print('기존 컨트롤러 dispose 스킵: $e'); print('기존 컨트롤러 dispose 스킵: $e');
} }
// 새 컨트롤러로 교체
_videoController = newController; _videoController = newController;
_videoController.setLooping(true); _videoController.setLooping(true);
_videoController.setVolume(0.0); _videoController.setVolume(0.0);
@@ -86,7 +82,6 @@ class _ChatScreenState extends State<ChatScreen> {
print('비디오 로드 오류: $error'); print('비디오 로드 오류: $error');
}); });
} }
//26.06.24 추가 끝
void _addInitialMessage() { void _addInitialMessage() {
setState(() { setState(() {
@@ -101,7 +96,6 @@ class _ChatScreenState extends State<ChatScreen> {
}); });
} }
//26.06.24 추가 시작
void _sendMessage(String text) async { void _sendMessage(String text) async {
if (text.isEmpty) return; if (text.isEmpty) return;
@@ -148,15 +142,27 @@ class _ChatScreenState extends State<ChatScreen> {
if (emotionCategory != _currentEmotion) { if (emotionCategory != _currentEmotion) {
print('감정 변경! $emotionCategory로 비디오 교체'); print('감정 변경! $emotionCategory로 비디오 교체');
_currentEmotion = emotionCategory; _currentEmotion = emotionCategory;
// 백그라운드에서 비디오 로드 (화면 깜빡임 없음) _isVideoInitialized = false;
_initializeVideo(_currentEmotion); _initializeVideo(_currentEmotion);
// 영상별 길이에 맞춰 DEFAULT로 복원
final (_, duration) = _getVideoInfo(emotionCategory);
final delaySeconds = duration * 2; // 2번 재생
Future.delayed(Duration(seconds: delaySeconds), () {
if (mounted) {
print('DEFAULT로 복원');
_currentEmotion = 1; // DEFAULT = 1
_initializeVideo(1);
}
});
} }
_messages.add( _messages.add(
ChatMessage( ChatMessage(
text: responseMessage, text: responseMessage,
isUser: false, isUser: false,
timestamp: DateTime.now(), timestamp: DateTime.now(),
emotionCategory: emotionCategory, // ← 추가 emotionCategory: emotionCategory,
), ),
); );
_isLoading = false; _isLoading = false;
@@ -165,13 +171,13 @@ class _ChatScreenState extends State<ChatScreen> {
} catch (e) { } catch (e) {
print('메시지 전송 오류: $e'); print('메시지 전송 오류: $e');
setState(() { setState(() {
_messages.removeLast(); // ← 로딩 메시지 제거 _messages.removeLast();
_messages.add( _messages.add(
ChatMessage( ChatMessage(
text: '오류가 발생했습니다. 다시 시도해주세요.', text: '오류가 발생했습니다. 다시 시도해주세요.',
isUser: false, isUser: false,
timestamp: DateTime.now(), timestamp: DateTime.now(),
emotionCategory: _currentEmotion, // ← 추가 emotionCategory: _currentEmotion,
), ),
); );
_isLoading = false; _isLoading = false;
@@ -179,7 +185,6 @@ class _ChatScreenState extends State<ChatScreen> {
_scrollToBottom(); _scrollToBottom();
} }
} }
//26.06.24 추가 끝
void _scrollToBottom() { void _scrollToBottom() {
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
@@ -213,7 +218,7 @@ class _ChatScreenState extends State<ChatScreen> {
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage('assets/images/background1.png'), image: AssetImage('assets/images/background.png'),
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
@@ -223,7 +228,6 @@ class _ChatScreenState extends State<ChatScreen> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withOpacity(0.8), // 투명도 넣기 color: Colors.white.withOpacity(0.8), // 투명도 넣기
borderRadius: BorderRadius.circular(36), // 모서리 둥글게 borderRadius: BorderRadius.circular(36), // 모서리 둥글게
// border: Border.all(color: Color(0xFFE0E0E0), width: 1),
), ),
child: Row( child: Row(
children: [ children: [
@@ -232,14 +236,6 @@ class _ChatScreenState extends State<ChatScreen> {
flex: 5, flex: 5,
child: Container( child: Container(
margin: const EdgeInsets.fromLTRB(30, 0, 30, 50), margin: const EdgeInsets.fromLTRB(30, 0, 30, 50),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(30),
// border: Border.all(
// color: Color(0xFFE0E0E0),
// width: 1,
// ),
// ),
child: Column( child: Column(
children: [ children: [
// 헤더 // 헤더
@@ -353,7 +349,7 @@ class _ChatScreenState extends State<ChatScreen> {
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 55),
// 캐릭터 정보 + 설명 문구 // 캐릭터 정보 + 설명 문구
// 1. 가장 바깥쪽 박스 추가 // 1. 가장 바깥쪽 박스 추가
Container( Container(
@@ -431,7 +427,12 @@ class _ChatScreenState extends State<ChatScreen> {
Expanded( Expanded(
flex: 5, flex: 5,
child: Container( child: Container(
margin: const EdgeInsets.all(50), margin: const EdgeInsets.only(
top: 50,
bottom: 50,
right: 50,
left: 10,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0xFFfbfdf8), color: Color(0xFFfbfdf8),
borderRadius: BorderRadius.circular(30), borderRadius: BorderRadius.circular(30),
@@ -533,7 +534,6 @@ class _ChatScreenState extends State<ChatScreen> {
controller: _scrollController, controller: _scrollController,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
itemCount: _messages.length, itemCount: _messages.length,
//26.06.24 추가 시작
itemBuilder: (context, index) { itemBuilder: (context, index) {
final message = _messages[index]; final message = _messages[index];
final isLoadingMessage = _isLoading && final isLoadingMessage = _isLoading &&
@@ -544,7 +544,6 @@ class _ChatScreenState extends State<ChatScreen> {
isLoading: isLoadingMessage, isLoading: isLoadingMessage,
); );
}, },
//26.06.24 추가 끝
), ),
), ),
), ),
@@ -822,7 +821,7 @@ class _ChatScreenState extends State<ChatScreen> {
// Layer 이미지 (화면 전체) // Layer 이미지 (화면 전체)
IgnorePointer( IgnorePointer(
child: Image.asset( child: Image.asset(
'assets/images/layer_img1.png', 'assets/images/layer_img.png',
fit: BoxFit.cover, fit: BoxFit.cover,
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
@@ -836,11 +835,11 @@ class _ChatScreenState extends State<ChatScreen> {
class _ChatBubble extends StatelessWidget { class _ChatBubble extends StatelessWidget {
final ChatMessage message; final ChatMessage message;
final bool isLoading; //26.06.24 추가 final bool isLoading;
const _ChatBubble({ const _ChatBubble({
required this.message, required this.message,
this.isLoading = false //26.06.24 추가 this.isLoading = false
}); });
String _formatTime(DateTime dateTime) { String _formatTime(DateTime dateTime) {
@@ -911,7 +910,6 @@ class _ChatBubble extends StatelessWidget {
), ),
], ],
), ),
// 26.06.24 추가 시작
child: isLoading child: isLoading
? _LoadingAnimation() // 로딩 중 ? _LoadingAnimation() // 로딩 중
: SelectableText( : SelectableText(
@@ -924,7 +922,6 @@ class _ChatBubble extends StatelessWidget {
height: 1.4, height: 1.4,
), ),
), ),
// 26.06.24 추가 끝
), ),
), ),
if (!message.isUser) const SizedBox(width: 8), if (!message.isUser) const SizedBox(width: 8),
@@ -942,7 +939,6 @@ class _ChatBubble extends StatelessWidget {
} }
} }
//26.06.24 추가 시작
class _LoadingAnimation extends StatefulWidget { class _LoadingAnimation extends StatefulWidget {
const _LoadingAnimation(); const _LoadingAnimation();
@@ -1061,7 +1057,3 @@ class _DotPainter extends CustomPainter {
@override @override
bool shouldRepaint(_DotPainter oldDelegate) => false; bool shouldRepaint(_DotPainter oldDelegate) => false;
} }
//26.06.24 추가 끝
//26.06.24 추가 시작
//26.06.24

View File

@@ -72,17 +72,9 @@ flutter:
- assets/images/profile.png - assets/images/profile.png
- assets/images/background.png - assets/images/background.png
- assets/images/background1.png
- assets/images/background2.png
- assets/images/background3.png
- assets/images/send.png
- assets/images/layer_img.png - assets/images/layer_img.png
- assets/images/layer_img1.png
- assets/images/layer_img2.png
- assets/images/chat_img.png - assets/images/chat_img.png
- assets/images/send.png
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
# assets: # assets: