진행중 페이지까지 완료
This commit is contained in:
parent
3cca3401ac
commit
f416094820
@ -190,6 +190,15 @@ class _MainPageState extends State<MainPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||||
|
? Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!),
|
||||||
|
)
|
||||||
|
: SizedBox.shrink(), // 로딩 전엔 빈 공간 or 원하는 위젯
|
||||||
|
|
||||||
body: Column(
|
body: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@ -225,28 +234,6 @@ class _MainPageState extends State<MainPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// 광고 영역 교체
|
|
||||||
// (기존) Container(...) 대신 _bannerAd 위젯 사용
|
|
||||||
if (_isBannerReady && _bannerAd != null)
|
|
||||||
Container(
|
|
||||||
width: _bannerAd!.size.width.toDouble(),
|
|
||||||
height: _bannerAd!.size.height.toDouble(),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: AdWidget(ad: _bannerAd!),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
// 로딩중이거나 오류시 대체영역
|
|
||||||
Container(
|
|
||||||
width: 300,
|
|
||||||
height: 50,
|
|
||||||
color: Colors.grey.shade400,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: const Text(
|
|
||||||
'광고 로딩중',
|
|
||||||
style: TextStyle(color: Colors.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:async';
|
||||||
import 'package:firebase_database/firebase_database.dart';
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@ -9,6 +10,9 @@ import '../../dialogs/response_dialog.dart';
|
|||||||
import '../../dialogs/score_edit_dialog.dart'; // 점수 수정 모달
|
import '../../dialogs/score_edit_dialog.dart'; // 점수 수정 모달
|
||||||
import '../../dialogs/user_info_basic_dialog.dart'; // 일반 유저 정보 모달
|
import '../../dialogs/user_info_basic_dialog.dart'; // 일반 유저 정보 모달
|
||||||
|
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../../config/config.dart';
|
||||||
|
|
||||||
class PlayingPrivatePage extends StatefulWidget {
|
class PlayingPrivatePage extends StatefulWidget {
|
||||||
final int roomSeq;
|
final int roomSeq;
|
||||||
final String roomTitle;
|
final String roomTitle;
|
||||||
@ -24,8 +28,20 @@ class PlayingPrivatePage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
||||||
|
|
||||||
|
// FRD
|
||||||
late DatabaseReference _roomRef;
|
late DatabaseReference _roomRef;
|
||||||
Stream<DatabaseEvent>? _roomStream;
|
Stream<DatabaseEvent>? _roomStream;
|
||||||
|
StreamSubscription<DatabaseEvent>? _roomStreamSubscription;
|
||||||
|
// ─────────────────────────────────────────
|
||||||
|
// 운영시간 카운트다운
|
||||||
|
// ─────────────────────────────────────────
|
||||||
|
Timer? _countdownTimer;
|
||||||
|
Duration _remaining = const Duration(hours: 1); // 기본 1시간
|
||||||
|
DateTime? _roomStartDt; // FRD의 roomInfo.room_start_dt
|
||||||
|
String _roomRunningTime = '0'; // 운영시간
|
||||||
|
bool _roomTimeOut = false;
|
||||||
|
String _roomExitYn = 'N';
|
||||||
|
|
||||||
String roomMasterYn = 'N';
|
String roomMasterYn = 'N';
|
||||||
String roomTitle = '';
|
String roomTitle = '';
|
||||||
@ -34,11 +50,22 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
List<Map<String, dynamic>> _scoreList = [];
|
List<Map<String, dynamic>> _scoreList = [];
|
||||||
|
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
|
// 종료 페이지 이동 중복 방지
|
||||||
|
bool _movedToFinishPage = false;
|
||||||
|
|
||||||
|
// 점수 공개 범위
|
||||||
|
String scoreOpenRange = 'ALL';
|
||||||
|
|
||||||
String mySeq = '0';
|
String mySeq = '0';
|
||||||
|
|
||||||
// userListMap: { userSeq: true/false }
|
// userListMap: { userSeq: true/false }
|
||||||
Map<String, bool> _userListMap = {};
|
Map<String, bool> _userListMap = {};
|
||||||
|
|
||||||
|
/// (1) 광고 배너 관련 변수
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||||
|
String adUnitId = Config.testAdUnitId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -46,9 +73,40 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
FirebaseDatabase.instance.goOnline();
|
FirebaseDatabase.instance.goOnline();
|
||||||
|
|
||||||
roomTitle = widget.roomTitle;
|
roomTitle = widget.roomTitle;
|
||||||
|
// (C) 배너 광고 초기화
|
||||||
|
_initBannerAd();
|
||||||
|
// (D) 방 정보 초기화
|
||||||
_initFirebase();
|
_initFirebase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_countdownTimer?.cancel();
|
||||||
|
_roomStreamSubscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 배너 광고 초기화
|
||||||
|
void _initBannerAd() {
|
||||||
|
_bannerAd = BannerAd(
|
||||||
|
size: AdSize.banner, // 일반 배너 사이즈
|
||||||
|
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
||||||
|
adUnitId: adUnitId, // 실제/테스트 배너 광고 단위 ID
|
||||||
|
listener: BannerAdListener(
|
||||||
|
onAdLoaded: (Ad ad) {
|
||||||
|
setState(() => _isBannerReady = true);
|
||||||
|
},
|
||||||
|
onAdFailedToLoad: (Ad ad, LoadAdError err) {
|
||||||
|
ad.dispose();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
request: const AdRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// load() 호출로 광고 요청
|
||||||
|
_bannerAd?.load();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _initFirebase() async {
|
Future<void> _initFirebase() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0';
|
mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0';
|
||||||
@ -83,15 +141,20 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
if (roomStatus == 'FINISH') {
|
if (roomStatus == 'FINISH') {
|
||||||
// 종료 페이지
|
// 종료 페이지
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => FinishPrivatePage(roomSeq: widget.roomSeq)),
|
MaterialPageRoute(builder: (_) => FinishPrivatePage(roomSeq: widget.roomSeq)),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
// 운영시간 입력
|
||||||
|
_roomRunningTime = roomInfoData['running_time'] ?? '0';
|
||||||
|
// 점수 공개 범위
|
||||||
|
scoreOpenRange = roomInfoData['score_open_range'] ?? 'ALL';
|
||||||
// 방장 여부
|
// 방장 여부
|
||||||
final masterSeq = roomInfoData['master_user_seq'];
|
final masterSeq = roomInfoData['master_user_seq'];
|
||||||
roomMasterYn = (masterSeq != null && masterSeq.toString() == mySeq) ? 'Y' : 'N';
|
roomMasterYn = (masterSeq != null && masterSeq.toString() == mySeq) ? 'Y' : 'N';
|
||||||
@ -111,6 +174,10 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
// 전체 유저 목록
|
// 전체 유저 목록
|
||||||
final List<Map<String, dynamic>> rawList = [];
|
final List<Map<String, dynamic>> rawList = [];
|
||||||
userInfoData.forEach((uSeq, uData) {
|
userInfoData.forEach((uSeq, uData) {
|
||||||
|
// 방장 표시
|
||||||
|
if (uSeq.toString() == roomInfoData['master_user_seq'].toString()) uData['nickname'] = '★' + (uData['nickname'] ?? '유저');
|
||||||
|
// 관리자 표시
|
||||||
|
if ((uData['participant_type'] ?? '').toString().toUpperCase() == 'ADMIN') uData['nickname'] = '☆' + (uData['nickname'] ?? '유저');
|
||||||
rawList.add({
|
rawList.add({
|
||||||
'user_seq': uSeq,
|
'user_seq': uSeq,
|
||||||
'participant_type': (uData['participant_type'] ?? '').toString().toUpperCase(),
|
'participant_type': (uData['participant_type'] ?? '').toString().toUpperCase(),
|
||||||
@ -132,7 +199,7 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ADMIN 제외
|
// ADMIN 제외
|
||||||
final playerList = rawList.where((u) => u['participant_type'] != 'ADMIN').toList();
|
final playerList = rawList.toList();
|
||||||
// 점수 내림차순
|
// 점수 내림차순
|
||||||
playerList.sort((a, b) {
|
playerList.sort((a, b) {
|
||||||
final scoreA = a['score'] ?? 0;
|
final scoreA = a['score'] ?? 0;
|
||||||
@ -145,6 +212,33 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
|
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 종료 => 이동
|
||||||
|
if (roomStatus == 'FINISH' && !_movedToFinishPage) {
|
||||||
|
_movedToFinishPage = true;
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => FinishPrivatePage(
|
||||||
|
roomSeq: widget.roomSeq,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 운영시간 카운트다운 위한 room_start_dt 파싱
|
||||||
|
final roomStartDtStr = (roomInfoData['start_dt'] ?? '') as String;
|
||||||
|
if (roomStartDtStr.isNotEmpty) {
|
||||||
|
final dt = DateTime.tryParse(roomStartDtStr);
|
||||||
|
if (dt != null) {
|
||||||
|
setState(() {
|
||||||
|
_roomStartDt = dt;
|
||||||
|
});
|
||||||
|
_startCountdownTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
}, onError: (err) {
|
}, onError: (err) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
@ -153,6 +247,43 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 운영시간 카운트다운 타이머
|
||||||
|
void _startCountdownTimer() {
|
||||||
|
if (_countdownTimer != null && _countdownTimer!.isActive) {
|
||||||
|
return; // 이미 실행중이면 중복 실행 방지
|
||||||
|
}
|
||||||
|
if (_roomStartDt == null) return;
|
||||||
|
|
||||||
|
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
// 목표시각: roomStartDt + 운영시간
|
||||||
|
final endTime = _roomStartDt!.add(Duration(hours: int.parse(_roomRunningTime)));
|
||||||
|
final now = DateTime.now();
|
||||||
|
final diff = endTime.difference(now);
|
||||||
|
|
||||||
|
if (diff.isNegative) {
|
||||||
|
// 이미 시간이 지남 -> 자동 종료 로직
|
||||||
|
timer.cancel();
|
||||||
|
_remaining = const Duration(seconds: 0);
|
||||||
|
_onAutoTimeout();
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_remaining = diff;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 운영시간 만료 후 자동 종료
|
||||||
|
void _onAutoTimeout() {
|
||||||
|
// 방장 => 방 삭제 (leave API)
|
||||||
|
// 일반 => 그냥 나가기
|
||||||
|
setState(() {
|
||||||
|
_roomTimeOut = true;
|
||||||
|
_roomExitYn = 'Y';
|
||||||
|
});
|
||||||
|
_requestFinish();
|
||||||
|
}
|
||||||
|
|
||||||
/// 방장이면 Finish API
|
/// 방장이면 Finish API
|
||||||
Future<void> _requestFinish() async {
|
Future<void> _requestFinish() async {
|
||||||
final reqBody = {
|
final reqBody = {
|
||||||
@ -258,14 +389,15 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
await userRef.set(false);
|
await userRef.set(false);
|
||||||
|
|
||||||
if (!mounted) return false;
|
if (!mounted) return false;
|
||||||
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const MainPage()));
|
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 참가자 카드
|
/// 참가자 카드
|
||||||
Widget _buildScoreItem(Map<String, dynamic> user) {
|
Widget _buildScoreItem(Map<String, dynamic> user) {
|
||||||
final userSeq = user['user_seq'].toString();
|
final userSeq = user['user_seq'].toString();
|
||||||
final score = user['score'] ?? 0;
|
final tempScore = user['score'] ?? 0;
|
||||||
|
final score = (scoreOpenRange == 'ALL') ? tempScore : '-';
|
||||||
final nickname = user['nickname'] ?? '유저';
|
final nickname = user['nickname'] ?? '유저';
|
||||||
|
|
||||||
final bool isActive = _userListMap[userSeq] ?? true;
|
final bool isActive = _userListMap[userSeq] ?? true;
|
||||||
@ -342,8 +474,16 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (★) 카운트다운 표시용
|
||||||
|
String _formatDuration(Duration d) {
|
||||||
|
final mm = d.inMinutes.remainder(60).toString().padLeft(2, '0');
|
||||||
|
final ss = d.inSeconds.remainder(60).toString().padLeft(2, '0');
|
||||||
|
return '$mm:$ss';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final countdownStr = _formatDuration(_remaining);
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: _onWillPop,
|
onWillPop: _onWillPop,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
@ -355,9 +495,20 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||||
onPressed: () => _onWillPop(),
|
onPressed: () => _onWillPop(),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Row(
|
||||||
roomTitle.isNotEmpty ? roomTitle : '진행중 (개인전)',
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// 왼쪽: 방 제목
|
||||||
|
Text(
|
||||||
|
roomTitle.isNotEmpty ? roomTitle : '방 제목',
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
// 오른쪽: 남은시간
|
||||||
|
Text(
|
||||||
|
countdownStr, // 예: "10:23"
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
if (roomMasterYn == 'Y')
|
if (roomMasterYn == 'Y')
|
||||||
@ -394,18 +545,16 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
|
||||||
height: 50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
border: Border.all(color: Colors.black, width: 1),
|
|
||||||
),
|
|
||||||
child: const Center(
|
|
||||||
child: Text('구글 광고'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||||
|
? Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!),
|
||||||
|
)
|
||||||
|
: SizedBox.shrink(), // 로딩 전엔 빈 공간 or 원하는 위젯
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'dart:async';
|
||||||
import 'package:firebase_database/firebase_database.dart';
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@ -9,6 +10,9 @@ import '../../dialogs/response_dialog.dart';
|
|||||||
import '../../dialogs/score_edit_dialog.dart';
|
import '../../dialogs/score_edit_dialog.dart';
|
||||||
import '../../dialogs/user_info_basic_dialog.dart';
|
import '../../dialogs/user_info_basic_dialog.dart';
|
||||||
|
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../../config/config.dart';
|
||||||
|
|
||||||
class PlayingTeamPage extends StatefulWidget {
|
class PlayingTeamPage extends StatefulWidget {
|
||||||
final int roomSeq;
|
final int roomSeq;
|
||||||
final String roomTitle;
|
final String roomTitle;
|
||||||
@ -24,8 +28,19 @@ class PlayingTeamPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
||||||
|
// FRD
|
||||||
late DatabaseReference _roomRef;
|
late DatabaseReference _roomRef;
|
||||||
Stream<DatabaseEvent>? _roomStream;
|
Stream<DatabaseEvent>? _roomStream;
|
||||||
|
StreamSubscription<DatabaseEvent>? _roomStreamSubscription;
|
||||||
|
// ─────────────────────────────────────────
|
||||||
|
// 운영시간 카운트다운
|
||||||
|
// ─────────────────────────────────────────
|
||||||
|
Timer? _countdownTimer;
|
||||||
|
Duration _remaining = const Duration(hours: 1); // 기본 1시간
|
||||||
|
DateTime? _roomStartDt; // FRD의 roomInfo.room_start_dt
|
||||||
|
String _roomRunningTime = '0'; // FRD의 roomInfo.running_time
|
||||||
|
bool _roomTimeOut = false;
|
||||||
|
String _roomExitYn = 'N';
|
||||||
|
|
||||||
String roomMasterYn = 'N';
|
String roomMasterYn = 'N';
|
||||||
String roomTitle = '';
|
String roomTitle = '';
|
||||||
@ -37,11 +52,22 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
Map<String, List<Map<String, dynamic>>> _teamMap = {};
|
Map<String, List<Map<String, dynamic>>> _teamMap = {};
|
||||||
|
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
|
// 종료 페이지 이동 중복 방지
|
||||||
|
bool _movedToFinishPage = false;
|
||||||
|
|
||||||
String mySeq = '0';
|
String mySeq = '0';
|
||||||
|
|
||||||
// userListMap: { seq: true/false }
|
// userListMap: { seq: true/false }
|
||||||
Map<String, bool> _userListMap = {};
|
Map<String, bool> _userListMap = {};
|
||||||
|
|
||||||
|
// 점수 공개 범위
|
||||||
|
String scoreOpenRange = 'ALL';
|
||||||
|
|
||||||
|
/// (1) 광고 배너 관련 변수
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||||
|
String adUnitId = Config.testAdUnitId;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -49,9 +75,40 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
FirebaseDatabase.instance.goOnline();
|
FirebaseDatabase.instance.goOnline();
|
||||||
|
|
||||||
roomTitle = widget.roomTitle;
|
roomTitle = widget.roomTitle;
|
||||||
|
// (C) 배너 광고 초기화
|
||||||
|
_initBannerAd();
|
||||||
|
// (D) 방 정보 초기화
|
||||||
_initFirebase();
|
_initFirebase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_countdownTimer?.cancel();
|
||||||
|
_roomStreamSubscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 배너 광고 초기화
|
||||||
|
void _initBannerAd() {
|
||||||
|
_bannerAd = BannerAd(
|
||||||
|
size: AdSize.banner, // 일반 배너 사이즈
|
||||||
|
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
||||||
|
adUnitId: adUnitId, // 실제/테스트 배너 광고 단위 ID
|
||||||
|
listener: BannerAdListener(
|
||||||
|
onAdLoaded: (Ad ad) {
|
||||||
|
setState(() => _isBannerReady = true);
|
||||||
|
},
|
||||||
|
onAdFailedToLoad: (Ad ad, LoadAdError err) {
|
||||||
|
ad.dispose();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
request: const AdRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// load() 호출로 광고 요청
|
||||||
|
_bannerAd?.load();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _initFirebase() async {
|
Future<void> _initFirebase() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0';
|
mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0';
|
||||||
@ -87,15 +144,22 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
if (roomStatus == 'FINISH') {
|
if (roomStatus == 'FINISH') {
|
||||||
// 종료화면
|
// 종료화면
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => FinishTeamPage(roomSeq: widget.roomSeq)),
|
MaterialPageRoute(builder: (_) => FinishTeamPage(roomSeq: widget.roomSeq)),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
// 운영시간 입력
|
||||||
|
_roomRunningTime = roomInfoData['running_time'] ?? '0';
|
||||||
|
|
||||||
|
// 점수 공개 범위
|
||||||
|
scoreOpenRange = roomInfoData['score_open_range'] ?? 'ALL';
|
||||||
|
|
||||||
final masterSeq = roomInfoData['master_user_seq'];
|
final masterSeq = roomInfoData['master_user_seq'];
|
||||||
roomMasterYn = (masterSeq != null && masterSeq.toString() == mySeq) ? 'Y' : 'N';
|
roomMasterYn = (masterSeq != null && masterSeq.toString() == mySeq) ? 'Y' : 'N';
|
||||||
|
|
||||||
@ -112,6 +176,13 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
// 전체 유저
|
// 전체 유저
|
||||||
final List<Map<String, dynamic>> rawList = [];
|
final List<Map<String, dynamic>> rawList = [];
|
||||||
userInfoData.forEach((uSeq, uData) {
|
userInfoData.forEach((uSeq, uData) {
|
||||||
|
// 방장 표시
|
||||||
|
if (uSeq.toString() == roomInfoData['master_user_seq'].toString()) {
|
||||||
|
uData['nickname'] = '★' + (uData['nickname'] ?? '유저');
|
||||||
|
} else if ((uData['participant_type'] ?? '').toString().toUpperCase() == 'ADMIN') {
|
||||||
|
// 관리자 표시
|
||||||
|
uData['nickname'] = '☆' + (uData['nickname'] ?? '유저');
|
||||||
|
}
|
||||||
rawList.add({
|
rawList.add({
|
||||||
'user_seq': uSeq,
|
'user_seq': uSeq,
|
||||||
'participant_type': (uData['participant_type'] ?? '').toString().toUpperCase(),
|
'participant_type': (uData['participant_type'] ?? '').toString().toUpperCase(),
|
||||||
@ -151,7 +222,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
for (var user in rawList) {
|
for (var user in rawList) {
|
||||||
final pType = user['participant_type'];
|
final pType = user['participant_type'];
|
||||||
final tName = (user['team_name'] ?? 'WAIT');
|
final tName = (user['team_name'] ?? 'WAIT');
|
||||||
if (pType == 'ADMIN') continue;
|
// if (pType == 'ADMIN') continue;
|
||||||
if (tName == 'WAIT') continue;
|
if (tName == 'WAIT') continue;
|
||||||
|
|
||||||
tMap.putIfAbsent(tName, () => []);
|
tMap.putIfAbsent(tName, () => []);
|
||||||
@ -173,6 +244,33 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
|
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 종료 => 이동
|
||||||
|
if (roomStatus == 'FINISH' && !_movedToFinishPage) {
|
||||||
|
_movedToFinishPage = true;
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => FinishTeamPage(
|
||||||
|
roomSeq: widget.roomSeq,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 운영시간 카운트다운 위한 room_start_dt 파싱
|
||||||
|
final roomStartDtStr = (roomInfoData['start_dt'] ?? '') as String;
|
||||||
|
if (roomStartDtStr.isNotEmpty) {
|
||||||
|
final dt = DateTime.tryParse(roomStartDtStr);
|
||||||
|
if (dt != null) {
|
||||||
|
setState(() {
|
||||||
|
_roomStartDt = dt;
|
||||||
|
});
|
||||||
|
_startCountdownTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
}, onError: (err) {
|
}, onError: (err) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
@ -181,6 +279,43 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 운영시간 카운트다운 타이머
|
||||||
|
void _startCountdownTimer() {
|
||||||
|
if (_countdownTimer != null && _countdownTimer!.isActive) {
|
||||||
|
return; // 이미 실행중이면 중복 실행 방지
|
||||||
|
}
|
||||||
|
if (_roomStartDt == null) return;
|
||||||
|
|
||||||
|
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
// 목표시각: roomStartDt + 운영시간
|
||||||
|
final endTime = _roomStartDt!.add(Duration(hours: int.parse(_roomRunningTime)));
|
||||||
|
final now = DateTime.now();
|
||||||
|
final diff = endTime.difference(now);
|
||||||
|
|
||||||
|
if (diff.isNegative) {
|
||||||
|
// 이미 시간이 지남 -> 자동 종료 로직
|
||||||
|
timer.cancel();
|
||||||
|
_remaining = const Duration(seconds: 0);
|
||||||
|
_onAutoTimeout();
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_remaining = diff;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 운영시간 만료 후 자동 종료
|
||||||
|
void _onAutoTimeout() {
|
||||||
|
// 방장 => 방 삭제 (leave API)
|
||||||
|
// 일반 => 그냥 나가기
|
||||||
|
setState(() {
|
||||||
|
_roomTimeOut = true;
|
||||||
|
_roomExitYn = 'Y';
|
||||||
|
});
|
||||||
|
_requestFinish();
|
||||||
|
}
|
||||||
|
|
||||||
/// 게임종료
|
/// 게임종료
|
||||||
Future<void> _requestFinish() async {
|
Future<void> _requestFinish() async {
|
||||||
final body = {
|
final body = {
|
||||||
@ -282,20 +417,39 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
await userRef.set(false);
|
await userRef.set(false);
|
||||||
|
|
||||||
if (!mounted) return false;
|
if (!mounted) return false;
|
||||||
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const MainPage()));
|
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (★) 카운트다운 표시용
|
||||||
|
String _formatDuration(Duration d) {
|
||||||
|
final mm = d.inMinutes.remainder(60).toString().padLeft(2, '0');
|
||||||
|
final ss = d.inSeconds.remainder(60).toString().padLeft(2, '0');
|
||||||
|
return '$mm:$ss';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final countdownStr = _formatDuration(_remaining);
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: _onWillPop,
|
onWillPop: _onWillPop,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Row(
|
||||||
roomTitle.isNotEmpty ? roomTitle : '진행중 (팀전)',
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// 왼쪽: 방 제목
|
||||||
|
Text(
|
||||||
|
roomTitle.isNotEmpty ? roomTitle : '방 제목',
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
// 오른쪽: 남은시간
|
||||||
|
Text(
|
||||||
|
countdownStr, // 예: "10:23"
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@ -352,19 +506,16 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Container(
|
|
||||||
height: 50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
border: Border.all(color: Colors.black, width: 1),
|
|
||||||
),
|
|
||||||
child: const Center(
|
|
||||||
child: Text('구글 광고', style: TextStyle(color: Colors.black)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||||
|
? Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!),
|
||||||
|
)
|
||||||
|
: SizedBox.shrink(), // 로딩 전엔 빈 공간 or 원하는 위젯
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -372,7 +523,8 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
Widget _buildTeamSection(String teamName) {
|
Widget _buildTeamSection(String teamName) {
|
||||||
final upperName = teamName.toUpperCase();
|
final upperName = teamName.toUpperCase();
|
||||||
final members = _teamMap[upperName] ?? [];
|
final members = _teamMap[upperName] ?? [];
|
||||||
final teamScore = _teamScoreMap[upperName] ?? 0;
|
final tempTeamScore = _teamScoreMap[upperName] ?? 0;
|
||||||
|
final teamScore = (scoreOpenRange == 'TEAM' || scoreOpenRange == 'ALL') ? tempTeamScore : '-';
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@ -407,7 +559,8 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
|
|||||||
|
|
||||||
Widget _buildTeamMemberItem(Map<String, dynamic> userData) {
|
Widget _buildTeamMemberItem(Map<String, dynamic> userData) {
|
||||||
final userSeq = userData['user_seq'].toString();
|
final userSeq = userData['user_seq'].toString();
|
||||||
final score = userData['score'] ?? 0;
|
final tempScore = userData['score'] ?? 0;
|
||||||
|
final score = (scoreOpenRange == 'ALL') ? tempScore : '-';
|
||||||
final nickname= userData['nickname'] ?? '유저';
|
final nickname= userData['nickname'] ?? '유저';
|
||||||
|
|
||||||
final bool isActive = _userListMap[userSeq] ?? true;
|
final bool isActive = _userListMap[userSeq] ?? true;
|
||||||
|
@ -11,6 +11,12 @@ import '../../dialogs/room_setting_dialog.dart';
|
|||||||
import '../../dialogs/user_info_private_dialog.dart';
|
import '../../dialogs/user_info_private_dialog.dart';
|
||||||
import 'playing_private_page.dart';
|
import 'playing_private_page.dart';
|
||||||
|
|
||||||
|
// 광고
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
|
||||||
|
// 설정
|
||||||
|
import '../../config/config.dart';
|
||||||
|
|
||||||
class WaitingRoomPrivatePage extends StatefulWidget {
|
class WaitingRoomPrivatePage extends StatefulWidget {
|
||||||
final int roomSeq;
|
final int roomSeq;
|
||||||
final String roomType; // "private"
|
final String roomType; // "private"
|
||||||
@ -62,13 +68,54 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
Timer? _countdownTimer;
|
Timer? _countdownTimer;
|
||||||
Duration _remaining = const Duration(hours: 1); // 기본 1시간
|
Duration _remaining = const Duration(hours: 1); // 기본 1시간
|
||||||
DateTime? _createDt; // FRD의 roomInfo.create_dt
|
DateTime? _createDt; // FRD의 roomInfo.create_dt
|
||||||
|
bool _roomTimeOut = false;
|
||||||
|
String _roomExitYn = 'N';
|
||||||
|
|
||||||
|
/// (1) 광고 배너 관련 변수
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||||
|
String adUnitId = Config.testAdUnitId;
|
||||||
|
|
||||||
|
// 방장 SEQ 저장
|
||||||
|
String _masterSeqString = '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// FRD 연결 복원
|
// FRD 연결 복원
|
||||||
FirebaseDatabase.instance.goOnline();
|
FirebaseDatabase.instance.goOnline();
|
||||||
|
// (B) 방 정보 초기화
|
||||||
_initRoomRef();
|
_initRoomRef();
|
||||||
|
// (C) 배너 광고 초기화
|
||||||
|
_initBannerAd();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_countdownTimer?.cancel();
|
||||||
|
_roomStreamSubscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 배너 광고 초기화
|
||||||
|
void _initBannerAd() {
|
||||||
|
_bannerAd = BannerAd(
|
||||||
|
size: AdSize.banner, // 일반 배너 사이즈
|
||||||
|
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
||||||
|
adUnitId: adUnitId, // 실제/테스트 배너 광고 단위 ID
|
||||||
|
listener: BannerAdListener(
|
||||||
|
onAdLoaded: (Ad ad) {
|
||||||
|
setState(() => _isBannerReady = true);
|
||||||
|
},
|
||||||
|
onAdFailedToLoad: (Ad ad, LoadAdError err) {
|
||||||
|
ad.dispose();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
request: const AdRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// load() 호출로 광고 요청
|
||||||
|
_bannerAd?.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initRoomRef() async {
|
Future<void> _initRoomRef() async {
|
||||||
@ -80,7 +127,9 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
|
|
||||||
// onDisconnect + connect_yn='Y'
|
// onDisconnect + connect_yn='Y'
|
||||||
final myUserRef = _roomRef.child('userInfo').child(mySeq);
|
final myUserRef = _roomRef.child('userInfo').child(mySeq);
|
||||||
|
if (_roomRef.child('userList').child(mySeq) == true) {
|
||||||
myUserRef.onDisconnect().update({'connect_yn': 'N'});
|
myUserRef.onDisconnect().update({'connect_yn': 'N'});
|
||||||
|
}
|
||||||
await myUserRef.update({'connect_yn': 'Y'});
|
await myUserRef.update({'connect_yn': 'Y'});
|
||||||
|
|
||||||
_listenRoomData();
|
_listenRoomData();
|
||||||
@ -96,15 +145,39 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
roomTitle = '방 정보 없음';
|
roomTitle = '방 정보 없음';
|
||||||
_userList = [];
|
_userList = [];
|
||||||
});
|
});
|
||||||
|
_roomMasterLeave();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final data = snapshot.value as Map<dynamic, dynamic>? ?? {};
|
final data = snapshot.value as Map<dynamic, dynamic>? ?? {};
|
||||||
final roomInfoData = data['roomInfo'] as Map<dynamic, dynamic>? ?? {};
|
final roomInfoData = data['roomInfo'] as Map<dynamic, dynamic>? ?? {};
|
||||||
final userInfoData = data['userInfo'] as Map<dynamic, dynamic>? ?? {};
|
final userInfoDynamic = data['userInfo']; // 이건 List일 수 있음
|
||||||
|
|
||||||
final roomStatus = (roomInfoData['room_status'] ?? 'WAIT').toString().toUpperCase();
|
final roomStatus = (roomInfoData['room_status'] ?? 'WAIT').toString().toUpperCase();
|
||||||
|
|
||||||
|
final tempList = <Map<String, dynamic>>[];
|
||||||
|
// userList
|
||||||
|
if (userInfoDynamic is Map) {
|
||||||
|
userInfoDynamic.forEach((key, val) {
|
||||||
|
if (val is Map) {
|
||||||
|
final tempUserSeq = val['user_seq'] ?? '0';
|
||||||
|
if (tempUserSeq != '0') {
|
||||||
|
tempList.add({
|
||||||
|
'user_seq': tempUserSeq,
|
||||||
|
'participant_type': val['participant_type'] ?? '',
|
||||||
|
'nickname': val['nickname'] ?? '유저',
|
||||||
|
'team_name': val['team_name'] ?? '',
|
||||||
|
'score': val['score'] ?? 0,
|
||||||
|
'profile_img': val['profile_img'] ?? '',
|
||||||
|
'introduce_myself': val['introduce_myself'] ?? '',
|
||||||
|
'ready_yn': (val['ready_yn'] ?? 'N').toString().toUpperCase(),
|
||||||
|
'connect_yn': (val['connect_yn'] ?? 'Y').toString().toUpperCase(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// (A) roomInfo 갱신
|
// (A) roomInfo 갱신
|
||||||
setState(() {
|
setState(() {
|
||||||
roomTitle = (roomInfoData['room_title'] ?? '') as String;
|
roomTitle = (roomInfoData['room_title'] ?? '') as String;
|
||||||
@ -122,20 +195,12 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
roomMasterYn = 'Y';
|
roomMasterYn = 'Y';
|
||||||
}
|
}
|
||||||
|
|
||||||
// userList
|
if (masterSeq != null) {
|
||||||
final tempList = <Map<String, dynamic>>[];
|
_masterSeqString = masterSeq.toString();
|
||||||
userInfoData.forEach((userSeq, userMap) {
|
} else {
|
||||||
tempList.add({
|
_masterSeqString = '';
|
||||||
'user_seq': userSeq,
|
}
|
||||||
'participant_type': userMap['participant_type'] ?? '',
|
|
||||||
'nickname': userMap['nickname'] ?? '유저',
|
|
||||||
'score': userMap['score'] ?? 0,
|
|
||||||
'profile_img': userMap['profile_img'] ?? '',
|
|
||||||
'introduce_myself': userMap['introduce_myself'] ?? '',
|
|
||||||
'ready_yn': (userMap['ready_yn'] ?? 'N').toString().toUpperCase(),
|
|
||||||
'connect_yn': (userMap['connect_yn'] ?? 'Y').toString().toUpperCase(),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
_userList = tempList;
|
_userList = tempList;
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
@ -143,7 +208,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
// (B) 진행중 => 이동
|
// (B) 진행중 => 이동
|
||||||
if (roomStatus == 'RUNNING' && !_movedToRunningPage) {
|
if (roomStatus == 'RUNNING' && !_movedToRunningPage) {
|
||||||
_movedToRunningPage = true;
|
_movedToRunningPage = true;
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => PlayingPrivatePage(
|
builder: (_) => PlayingPrivatePage(
|
||||||
@ -151,6 +216,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
roomTitle: roomTitle,
|
roomTitle: roomTitle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -158,10 +224,14 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
// (C) 1시간 카운트다운 위한 create_dt 파싱
|
// (C) 1시간 카운트다운 위한 create_dt 파싱
|
||||||
// 예: "2025-01-07T06:38:10.123456"
|
// 예: "2025-01-07T06:38:10.123456"
|
||||||
final createDtStr = (roomInfoData['create_dt'] ?? '') as String;
|
final createDtStr = (roomInfoData['create_dt'] ?? '') as String;
|
||||||
if (createDtStr.isNotEmpty && createDtStr.contains('T')) {
|
if (createDtStr.isNotEmpty) {
|
||||||
final dt = DateTime.tryParse(createDtStr);
|
final dotIndex = createDtStr.indexOf('.');
|
||||||
|
final isoStr = createDtStr.substring(0, dotIndex);
|
||||||
|
final dt = DateTime.tryParse(isoStr);
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
|
setState(() {
|
||||||
_createDt = dt;
|
_createDt = dt;
|
||||||
|
});
|
||||||
_startCountdownTimer();
|
_startCountdownTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,11 +240,25 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
final amIStillHere = _userList.any((u) => u['user_seq'].toString() == mySeq);
|
final amIStillHere = _userList.any((u) => u['user_seq'].toString() == mySeq);
|
||||||
if (!amIStillHere && !_kickedOut && roomMasterYn != 'Y') {
|
if (!amIStillHere && !_kickedOut && roomMasterYn != 'Y') {
|
||||||
_kickedOut = true;
|
_kickedOut = true;
|
||||||
|
if (_roomExitYn == 'N') {
|
||||||
|
showResponseDialog(context, '안내', '강퇴되었습니다.');
|
||||||
|
}
|
||||||
Future.delayed(Duration.zero, () async {
|
Future.delayed(Duration.zero, () async {
|
||||||
await showResponseDialog(context, '안내', '강퇴되었습니다.');
|
Navigator.pushAndRemoveUntil(
|
||||||
Navigator.pushReplacement(
|
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => const MainPage()),
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// (D) 방 제한시간 종료
|
||||||
|
if (_roomTimeOut) {
|
||||||
|
showResponseDialog(context, '안내', '방 제한시간이 종료되었습니다.');
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -186,6 +270,18 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 방장이 나갔을 때
|
||||||
|
void _roomMasterLeave() {
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
|
await showResponseDialog(context, '안내', '방장이 나갔습니다.');
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 1시간 카운트다운 타이머
|
// 1시간 카운트다운 타이머
|
||||||
void _startCountdownTimer() {
|
void _startCountdownTimer() {
|
||||||
if (_countdownTimer != null && _countdownTimer!.isActive) {
|
if (_countdownTimer != null && _countdownTimer!.isActive) {
|
||||||
@ -216,11 +312,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
void _onAutoTimeout() {
|
void _onAutoTimeout() {
|
||||||
// 방장 => 방 삭제 (leave API)
|
// 방장 => 방 삭제 (leave API)
|
||||||
// 일반 => 그냥 나가기
|
// 일반 => 그냥 나가기
|
||||||
if (roomMasterYn == 'Y') {
|
setState(() {
|
||||||
|
_roomTimeOut = true;
|
||||||
|
_roomExitYn = 'Y';
|
||||||
|
});
|
||||||
_requestLeaveRoom();
|
_requestLeaveRoom();
|
||||||
} else {
|
|
||||||
_requestLeaveRoom();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _requestLeaveRoom() async {
|
Future<void> _requestLeaveRoom() async {
|
||||||
@ -232,17 +328,10 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const MainPage()));
|
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_countdownTimer?.cancel();
|
|
||||||
_roomStreamSubscription?.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 뒤로가기 → 방 나가기
|
/// 뒤로가기 → 방 나가기
|
||||||
Future<void> _onLeaveRoom() async {
|
Future<void> _onLeaveRoom() async {
|
||||||
if (roomMasterYn == 'Y') {
|
if (roomMasterYn == 'Y') {
|
||||||
@ -292,9 +381,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
if (confirm != true) return;
|
if (confirm != true) return;
|
||||||
|
|
||||||
// leave API
|
// leave API
|
||||||
|
setState(() {_roomExitYn = 'Y';});
|
||||||
await _requestLeaveRoom();
|
await _requestLeaveRoom();
|
||||||
} else {
|
} else {
|
||||||
// 일반
|
// 일반
|
||||||
|
setState(() {_roomExitYn = 'Y';});
|
||||||
await _requestLeaveRoom();
|
await _requestLeaveRoom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,25 +563,34 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
// 방 제목 + 남은시간 표시
|
// 방 제목 + 남은시간 표시
|
||||||
title: Text(
|
title: Row(
|
||||||
(roomTitle.isNotEmpty ? roomTitle : '방 제목') + ' [$countdownStr]',
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
// 왼쪽: 방 제목
|
||||||
|
Text(
|
||||||
|
roomTitle.isNotEmpty ? roomTitle : '방 제목',
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
|
// 오른쪽: 남은시간
|
||||||
|
Text(
|
||||||
|
countdownStr, // 예: "10:23"
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||||
onPressed: _onLeaveRoom,
|
onPressed: _onLeaveRoom,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomNavigationBar: Container(
|
bottomNavigationBar: _isBannerReady && _bannerAd != null
|
||||||
height: 50,
|
? Container(
|
||||||
decoration: BoxDecoration(
|
color: Colors.white,
|
||||||
color: Colors.grey.shade300,
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
border: Border.all(color: Colors.black, width: 1),
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
),
|
child: AdWidget(ad: _bannerAd!),
|
||||||
child: const Center(
|
)
|
||||||
child: Text('구글 광고', style: TextStyle(color: Colors.black)),
|
: SizedBox.shrink(), // 로딩 전엔 빈 공간 or 원하는 위젯
|
||||||
),
|
|
||||||
),
|
|
||||||
body: _isLoading
|
body: _isLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: SingleChildScrollView(
|
: SingleChildScrollView(
|
||||||
@ -502,10 +602,10 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
_buildTopButtons(),
|
_buildTopButtons(),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
const Text('사회자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
// const Text('사회자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||||
const SizedBox(height: 8),
|
// const SizedBox(height: 8),
|
||||||
_buildAdminSection(),
|
// _buildAdminSection(),
|
||||||
const SizedBox(height: 20),
|
// const SizedBox(height: 20),
|
||||||
|
|
||||||
const Text('참가자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
const Text('참가자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -516,36 +616,38 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAdminSection() {
|
// Widget _buildAdminSection() {
|
||||||
final adminList = _userList.where((u) {
|
// final adminList = _userList.where((u) {
|
||||||
final t = (u['participant_type'] ?? '').toString().toUpperCase();
|
// final t = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||||
return t == 'ADMIN';
|
// return t == 'ADMIN';
|
||||||
}).toList();
|
// }).toList();
|
||||||
|
|
||||||
return Container(
|
// return Container(
|
||||||
padding: const EdgeInsets.all(8),
|
// padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
border: Border.all(color: Colors.black),
|
// border: Border.all(color: Colors.black),
|
||||||
borderRadius: BorderRadius.circular(8),
|
// borderRadius: BorderRadius.circular(8),
|
||||||
),
|
// ),
|
||||||
child: adminList.isEmpty
|
// child: adminList.isEmpty
|
||||||
? const Text('사회자가 없습니다.')
|
// ? const Text('사회자가 없습니다.')
|
||||||
: Wrap(
|
// : Wrap(
|
||||||
spacing: 16,
|
// spacing: 16,
|
||||||
runSpacing: 8,
|
// runSpacing: 8,
|
||||||
children: adminList.map(_buildSeat).toList(),
|
// children: adminList.map(_buildSeat).toList(),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
Widget _buildPlayerSection() {
|
Widget _buildPlayerSection() {
|
||||||
final playerList = _userList.where((u) {
|
final playerList = _userList.where((u) {
|
||||||
final t = (u['participant_type'] ?? '').toString().toUpperCase();
|
final t = (u['user_seq'] ?? null);
|
||||||
return t != 'ADMIN';
|
return t != null;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
// final playerList = _userList;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@ -574,6 +676,24 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
final bool isDisconnected = (connectYn == 'N');
|
final bool isDisconnected = (connectYn == 'N');
|
||||||
final bool isMaster = (roomMasterYn == 'Y');
|
final bool isMaster = (roomMasterYn == 'Y');
|
||||||
|
|
||||||
|
// user가 방장인지 확인
|
||||||
|
final isRoomMasterUser = (userData['user_seq']?.toString() ?? '') == _masterSeqString;
|
||||||
|
// user가 사회자인지 확인
|
||||||
|
final participantType = (userData['participant_type'] ?? '').toString().toUpperCase();
|
||||||
|
final isAdmin = (participantType == 'ADMIN');
|
||||||
|
|
||||||
|
// 아이콘 붙이기
|
||||||
|
String roleIcon = '';
|
||||||
|
if (isRoomMasterUser) {
|
||||||
|
// 방장
|
||||||
|
roleIcon = '★ ';
|
||||||
|
} else if (isAdmin) {
|
||||||
|
// 사회자
|
||||||
|
roleIcon = '☆ ';
|
||||||
|
}
|
||||||
|
|
||||||
|
final displayName = '$roleIcon$userName';
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final result = await showDialog(
|
final result = await showDialog(
|
||||||
@ -648,7 +768,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(userName, style: const TextStyle(fontSize: 12)),
|
Text(displayName, style: const TextStyle(fontSize: 12, color: Colors.black)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -63,8 +63,6 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
bool _movedToRunningPage = false;
|
bool _movedToRunningPage = false;
|
||||||
bool _kickedOut = false;
|
bool _kickedOut = false;
|
||||||
bool _roomTimeOut = false;
|
|
||||||
String _roomTimeOutMsg = '';
|
|
||||||
|
|
||||||
String mySeq = '0';
|
String mySeq = '0';
|
||||||
|
|
||||||
@ -72,6 +70,8 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
Timer? _countdownTimer;
|
Timer? _countdownTimer;
|
||||||
Duration _remaining = const Duration(hours: 1);
|
Duration _remaining = const Duration(hours: 1);
|
||||||
DateTime? _createDt;
|
DateTime? _createDt;
|
||||||
|
bool _roomTimeOut = false;
|
||||||
|
String _roomExitYn = 'N';
|
||||||
|
|
||||||
/// (1) 광고 배너 관련 변수
|
/// (1) 광고 배너 관련 변수
|
||||||
BannerAd? _bannerAd;
|
BannerAd? _bannerAd;
|
||||||
@ -100,7 +100,9 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
// onDisconnect + connect_yn='Y'
|
// onDisconnect + connect_yn='Y'
|
||||||
final myUserRef = _roomRef.child('userInfo').child(mySeq);
|
final myUserRef = _roomRef.child('userInfo').child(mySeq);
|
||||||
|
if (_roomRef.child('userList').child(mySeq) == true) {
|
||||||
myUserRef.onDisconnect().update({'connect_yn': 'N'});
|
myUserRef.onDisconnect().update({'connect_yn': 'N'});
|
||||||
|
}
|
||||||
await myUserRef.update({'connect_yn': 'Y'});
|
await myUserRef.update({'connect_yn': 'Y'});
|
||||||
|
|
||||||
_listenRoomData();
|
_listenRoomData();
|
||||||
@ -146,6 +148,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
roomTitle = '방 정보 없음';
|
roomTitle = '방 정보 없음';
|
||||||
_userList = [];
|
_userList = [];
|
||||||
});
|
});
|
||||||
|
_roomMasterLeave();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +157,14 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
// final userInfoData = data['userInfo'] as Map<dynamic, dynamic>? ?? {};
|
// final userInfoData = data['userInfo'] as Map<dynamic, dynamic>? ?? {};
|
||||||
final userInfoDynamic = data['userInfo']; // 이건 List일 수 있음
|
final userInfoDynamic = data['userInfo']; // 이건 List일 수 있음
|
||||||
|
|
||||||
|
final roomStatus = (roomInfoData['room_status'] ?? 'WAIT').toString().toUpperCase();
|
||||||
|
|
||||||
final tempList = <Map<String, dynamic>>[];
|
final tempList = <Map<String, dynamic>>[];
|
||||||
// userList
|
// userList
|
||||||
if (userInfoDynamic is Map) {
|
if (userInfoDynamic is Map) {
|
||||||
userInfoDynamic.forEach((key, val) {
|
userInfoDynamic.forEach((key, val) {
|
||||||
|
final tempUserSeq = val['user_seq'] ?? '0';
|
||||||
|
if (tempUserSeq != '0') {
|
||||||
if (val is Map) {
|
if (val is Map) {
|
||||||
tempList.add({
|
tempList.add({
|
||||||
'user_seq': val['user_seq'].toString() ?? '0',
|
'user_seq': val['user_seq'].toString() ?? '0',
|
||||||
@ -171,11 +178,10 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
'connect_yn': (val['connect_yn'] ?? 'Y').toString().toUpperCase(),
|
'connect_yn': (val['connect_yn'] ?? 'Y').toString().toUpperCase(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final roomStatus = (roomInfoData['room_status'] ?? 'WAIT').toString().toUpperCase();
|
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
roomTitle = (roomInfoData['room_title'] ?? '') as String;
|
roomTitle = (roomInfoData['room_title'] ?? '') as String;
|
||||||
roomIntro = (roomInfoData['room_intro'] ?? '') as String;
|
roomIntro = (roomInfoData['room_intro'] ?? '') as String;
|
||||||
@ -232,14 +238,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
if (createDtStr.isNotEmpty) {
|
if (createDtStr.isNotEmpty) {
|
||||||
final dotIndex = createDtStr.indexOf('.');
|
final dotIndex = createDtStr.indexOf('.');
|
||||||
final isoStr = createDtStr.substring(0, dotIndex);
|
final isoStr = createDtStr.substring(0, dotIndex);
|
||||||
print('isoStr: $isoStr');
|
|
||||||
|
|
||||||
final dt1 = DateTime.tryParse(createDtStr);
|
|
||||||
print('dt1: $dt1');
|
|
||||||
final dt = DateTime.tryParse(isoStr);
|
final dt = DateTime.tryParse(isoStr);
|
||||||
print('dt: $dt');
|
|
||||||
final dt2 = DateTime.parse(isoStr);
|
|
||||||
print('dt2: $dt2');
|
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_createDt = dt;
|
_createDt = dt;
|
||||||
@ -248,17 +247,25 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 강퇴판별
|
// (D) 내가 목록에서 사라졌는지 => 강퇴 판별
|
||||||
final amIStillHere = _userList.any((u) => u['user_seq'].toString() == mySeq);
|
final amIStillHere = _userList.any((u) => u['user_seq'].toString() == mySeq);
|
||||||
if (!amIStillHere && !_kickedOut && roomMasterYn != 'Y') {
|
if (!amIStillHere && !_kickedOut && roomMasterYn != 'Y') {
|
||||||
_kickedOut = true;
|
_kickedOut = true;
|
||||||
if (_roomTimeOut) {
|
if (_roomExitYn == 'N') {
|
||||||
_roomTimeOutMsg = '방장이 나갔습니다.';
|
showResponseDialog(context, '안내', '강퇴되었습니다.');
|
||||||
} else if (_kickedOut) {
|
|
||||||
_roomTimeOutMsg = '강퇴되었습니다.';
|
|
||||||
}
|
}
|
||||||
Future.delayed(Duration.zero, () async {
|
Future.delayed(Duration.zero, () async {
|
||||||
await showResponseDialog(context, '안내', _roomTimeOutMsg);
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// (D) 방 제한시간 종료
|
||||||
|
if (_roomTimeOut) {
|
||||||
|
showResponseDialog(context, '안내', '방 제한시간이 종료되었습니다.');
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
Navigator.pushAndRemoveUntil(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => const MainPage()),
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
@ -274,6 +281,18 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 방장이 나갔을 때
|
||||||
|
void _roomMasterLeave() {
|
||||||
|
Future.delayed(Duration.zero, () async {
|
||||||
|
await showResponseDialog(context, '안내', '방장이 나갔습니다.');
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 카운트다운
|
// 카운트다운
|
||||||
void _startCountdownTimer() {
|
void _startCountdownTimer() {
|
||||||
if (_countdownTimer != null && _countdownTimer!.isActive) {
|
if (_countdownTimer != null && _countdownTimer!.isActive) {
|
||||||
@ -282,8 +301,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
if (_createDt == null) return;
|
if (_createDt == null) return;
|
||||||
|
|
||||||
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
// final endTime = _createDt!.add(const Duration(hours: 1));
|
final endTime = _createDt!.add(const Duration(hours: 1));
|
||||||
final endTime = _createDt!.add(const Duration(minutes: 1));
|
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final diff = endTime.difference(now);
|
final diff = endTime.difference(now);
|
||||||
|
|
||||||
@ -303,6 +321,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
// 자동 종료 -> 방장=나가기(방삭제), 일반=나가기
|
// 자동 종료 -> 방장=나가기(방삭제), 일반=나가기
|
||||||
setState(() {
|
setState(() {
|
||||||
_roomTimeOut = true;
|
_roomTimeOut = true;
|
||||||
|
_roomExitYn = 'Y';
|
||||||
});
|
});
|
||||||
_requestLeaveRoom();
|
_requestLeaveRoom();
|
||||||
}
|
}
|
||||||
@ -371,8 +390,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
);
|
);
|
||||||
if (confirm != true) return;
|
if (confirm != true) return;
|
||||||
|
|
||||||
|
// leave API
|
||||||
|
setState(() {_roomExitYn = 'Y';});
|
||||||
await _requestLeaveRoom();
|
await _requestLeaveRoom();
|
||||||
} else {
|
} else {
|
||||||
|
setState(() {_roomExitYn = 'Y';});
|
||||||
await _requestLeaveRoom();
|
await _requestLeaveRoom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -514,6 +536,13 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
setState(() => _isServerRequestLoading = false);
|
setState(() => _isServerRequestLoading = false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 팀 배정 안되어있는 사람 있는지 확인
|
||||||
|
final notTeam = _userList.any((u) => (u['team_name'] ?? '').toString().toUpperCase() == 'WAIT');
|
||||||
|
if (notTeam) {
|
||||||
|
showResponseDialog(context, '안내', '팀 배정이 안된 참가자가 있습니다.');
|
||||||
|
setState(() => _isServerRequestLoading = false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final requestBody = {
|
final requestBody = {
|
||||||
"room_seq": "${widget.roomSeq}",
|
"room_seq": "${widget.roomSeq}",
|
||||||
@ -527,11 +556,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
print('게임 시작 요청 성공(팀전)');
|
print('게임 시작 요청 성공(팀전)');
|
||||||
} else {
|
} else {
|
||||||
// 게임 시작 요청 실패
|
// 게임 시작 요청 실패
|
||||||
showResponseDialog(context, '오류', '게임 시작 요청에 실패했습니다.');
|
showResponseDialog(context, response['response_info']['msg_title'], response['response_info']['msg_content']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 게임 시작 요청 실패
|
// 게임 시작 요청 실패
|
||||||
showResponseDialog(context, '오류', '게임 시작 요청에 실패했습니다.');
|
showResponseDialog(context, response['response_info']['msg_title'], response['response_info']['msg_content']);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 게임 시작 요청 실패
|
// 게임 시작 요청 실패
|
||||||
@ -637,14 +666,15 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
Widget _buildTeamSection() {
|
Widget _buildTeamSection() {
|
||||||
// final players = _userList.where((u) {
|
final players = _userList.where((u) {
|
||||||
// final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
final t = (u['user_seq'] ?? null);
|
||||||
// return (pType != 'ADMIN');
|
return t != null;
|
||||||
// }).toList();
|
}).toList();
|
||||||
final players = _userList.toList();
|
// final players = _userList.toList();
|
||||||
|
|
||||||
final Map<String, List<Map<String, dynamic>>> teamMap = {};
|
final Map<String, List<Map<String, dynamic>>> teamMap = {};
|
||||||
for (final tName in _teamNameList) {
|
for (final tName in _teamNameList) {
|
||||||
|
if (tName == 'WAIT') continue;
|
||||||
teamMap[tName] = [];
|
teamMap[tName] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,6 +700,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _teamNameList.map((teamName) {
|
children: _teamNameList.map((teamName) {
|
||||||
|
if (teamName == 'WAIT') return const SizedBox();
|
||||||
final members = teamMap[teamName]!;
|
final members = teamMap[teamName]!;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
@ -725,10 +756,8 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
Widget _buildWaitSection() {
|
Widget _buildWaitSection() {
|
||||||
final waitList = _userList.where((u) {
|
final waitList = _userList.where((u) {
|
||||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
|
||||||
// if (pType == 'ADMIN') return false;
|
|
||||||
final tName = (u['team_name'] ?? '').toString().toUpperCase();
|
final tName = (u['team_name'] ?? '').toString().toUpperCase();
|
||||||
return (tName.isEmpty || tName == 'WAIT');
|
return tName == 'WAIT';
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
if (waitList.isEmpty) return const SizedBox();
|
if (waitList.isEmpty) return const SizedBox();
|
||||||
|
Loading…
Reference in New Issue
Block a user