팀전 대기방 완료
This commit is contained in:
parent
eab0597573
commit
3cca3401ac
@ -1 +1 @@
|
|||||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"allscore-344c2","appId":"1:70449524223:android:94ffb9ec98e508313e4bca","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"allscore-344c2","configurations":{"android":"1:70449524223:android:94ffb9ec98e508313e4bca","ios":"1:70449524223:ios:98ebdbaa616a807f3e4bca","macos":"1:70449524223:ios:98ebdbaa616a807f3e4bca","web":"1:70449524223:web:e9c27da6646d655f3e4bca","windows":"1:70449524223:web:479dd789b837f54c3e4bca"}}}}}}
|
{"flutter":{"platforms":{"android":{"default":{"projectId":"allscore-29edf","appId":"1:452355332155:android:152995468604d10d13e41e","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"allscore-29edf","configurations":{"android":"1:452355332155:android:152995468604d10d13e41e","ios":"1:452355332155:ios:a7b2fc75e3513e3413e41e","macos":"1:452355332155:ios:a7b2fc75e3513e3413e41e","web":"1:452355332155:web:5407f79d500818e713e41e","windows":"1:452355332155:web:5e08c9caf8d07e2c13e41e"}}}}}}
|
@ -41,54 +41,57 @@ class DefaultFirebaseOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const FirebaseOptions web = FirebaseOptions(
|
static const FirebaseOptions web = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyCnZuHtj5oUe_YS9nv3nlQIKWYCCfYFysU',
|
apiKey: 'AIzaSyCZx2yNaMmMXSFcdNGpl29NerG2PweszWI',
|
||||||
appId: '1:70449524223:web:e9c27da6646d655f3e4bca',
|
appId: '1:452355332155:web:5407f79d500818e713e41e',
|
||||||
messagingSenderId: '70449524223',
|
messagingSenderId: '452355332155',
|
||||||
projectId: 'allscore-344c2',
|
projectId: 'allscore-29edf',
|
||||||
authDomain: 'allscore-344c2.firebaseapp.com',
|
authDomain: 'allscore-29edf.firebaseapp.com',
|
||||||
databaseURL: 'https://allscore-344c2-default-rtdb.asia-southeast1.firebasedatabase.app',
|
databaseURL: 'https://allscore-29edf-default-rtdb.asia-southeast1.firebasedatabase.app',
|
||||||
storageBucket: 'allscore-344c2.firebasestorage.app',
|
storageBucket: 'allscore-29edf.firebasestorage.app',
|
||||||
measurementId: 'G-50Q1W265RY',
|
measurementId: 'G-63H3D8MNM8',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions android = FirebaseOptions(
|
static const FirebaseOptions android = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyAJEItMxO-TemHGlveSKySG-eNaTD9XJI0',
|
apiKey: 'AIzaSyB6hil7Nrk8wslHDfRNRRyw6rQktY16tTc',
|
||||||
appId: '1:70449524223:android:94ffb9ec98e508313e4bca',
|
appId: '1:452355332155:android:152995468604d10d13e41e',
|
||||||
messagingSenderId: '70449524223',
|
messagingSenderId: '452355332155',
|
||||||
projectId: 'allscore-344c2',
|
projectId: 'allscore-29edf',
|
||||||
databaseURL: 'https://allscore-344c2-default-rtdb.asia-southeast1.firebasedatabase.app',
|
databaseURL: 'https://allscore-29edf-default-rtdb.asia-southeast1.firebasedatabase.app',
|
||||||
storageBucket: 'allscore-344c2.firebasestorage.app',
|
storageBucket: 'allscore-29edf.firebasestorage.app',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions ios = FirebaseOptions(
|
static const FirebaseOptions ios = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyDq2y-BRlthl6BHs4B7FByiUnpyOfPPZQk',
|
apiKey: 'AIzaSyBL1ceaAYfhTpRU2C__HwKkF7cJHhxlpPg',
|
||||||
appId: '1:70449524223:ios:98ebdbaa616a807f3e4bca',
|
appId: '1:452355332155:ios:a7b2fc75e3513e3413e41e',
|
||||||
messagingSenderId: '70449524223',
|
messagingSenderId: '452355332155',
|
||||||
projectId: 'allscore-344c2',
|
projectId: 'allscore-29edf',
|
||||||
databaseURL: 'https://allscore-344c2-default-rtdb.asia-southeast1.firebasedatabase.app',
|
databaseURL: 'https://allscore-29edf-default-rtdb.asia-southeast1.firebasedatabase.app',
|
||||||
storageBucket: 'allscore-344c2.firebasestorage.app',
|
storageBucket: 'allscore-29edf.firebasestorage.app',
|
||||||
|
androidClientId: '452355332155-t29ceato8o62c9kq9drefe7b6hd1ka1d.apps.googleusercontent.com',
|
||||||
|
iosClientId: '452355332155-fo49j1u3qfup1sa3gj33bko6q269pqo4.apps.googleusercontent.com',
|
||||||
iosBundleId: 'com.example.allscoreApp',
|
iosBundleId: 'com.example.allscoreApp',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions macos = FirebaseOptions(
|
static const FirebaseOptions macos = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyDq2y-BRlthl6BHs4B7FByiUnpyOfPPZQk',
|
apiKey: 'AIzaSyBL1ceaAYfhTpRU2C__HwKkF7cJHhxlpPg',
|
||||||
appId: '1:70449524223:ios:98ebdbaa616a807f3e4bca',
|
appId: '1:452355332155:ios:a7b2fc75e3513e3413e41e',
|
||||||
messagingSenderId: '70449524223',
|
messagingSenderId: '452355332155',
|
||||||
projectId: 'allscore-344c2',
|
projectId: 'allscore-29edf',
|
||||||
databaseURL: 'https://allscore-344c2-default-rtdb.asia-southeast1.firebasedatabase.app',
|
databaseURL: 'https://allscore-29edf-default-rtdb.asia-southeast1.firebasedatabase.app',
|
||||||
storageBucket: 'allscore-344c2.firebasestorage.app',
|
storageBucket: 'allscore-29edf.firebasestorage.app',
|
||||||
|
androidClientId: '452355332155-t29ceato8o62c9kq9drefe7b6hd1ka1d.apps.googleusercontent.com',
|
||||||
|
iosClientId: '452355332155-fo49j1u3qfup1sa3gj33bko6q269pqo4.apps.googleusercontent.com',
|
||||||
iosBundleId: 'com.example.allscoreApp',
|
iosBundleId: 'com.example.allscoreApp',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions windows = FirebaseOptions(
|
static const FirebaseOptions windows = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyCnZuHtj5oUe_YS9nv3nlQIKWYCCfYFysU',
|
apiKey: 'AIzaSyCZx2yNaMmMXSFcdNGpl29NerG2PweszWI',
|
||||||
appId: '1:70449524223:web:479dd789b837f54c3e4bca',
|
appId: '1:452355332155:web:5e08c9caf8d07e2c13e41e',
|
||||||
messagingSenderId: '70449524223',
|
messagingSenderId: '452355332155',
|
||||||
projectId: 'allscore-344c2',
|
projectId: 'allscore-29edf',
|
||||||
authDomain: 'allscore-344c2.firebaseapp.com',
|
authDomain: 'allscore-29edf.firebaseapp.com',
|
||||||
databaseURL: 'https://allscore-344c2-default-rtdb.asia-southeast1.firebasedatabase.app',
|
databaseURL: 'https://allscore-29edf-default-rtdb.asia-southeast1.firebasedatabase.app',
|
||||||
storageBucket: 'allscore-344c2.firebasestorage.app',
|
storageBucket: 'allscore-29edf.firebasestorage.app',
|
||||||
measurementId: 'G-S9J5WDYJZM',
|
measurementId: 'G-MWXRMG174T',
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
@ -18,7 +18,9 @@ void main() async {
|
|||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
// 파이어베이스 초기화
|
// 파이어베이스 초기화
|
||||||
await Firebase.initializeApp();
|
await Firebase.initializeApp(
|
||||||
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
|
);
|
||||||
|
|
||||||
// 모바일 광고 초기화
|
// 모바일 광고 초기화
|
||||||
MobileAds.instance.initialize();
|
MobileAds.instance.initialize();
|
||||||
|
@ -104,10 +104,8 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
listener: BannerAdListener(
|
listener: BannerAdListener(
|
||||||
onAdLoaded: (ad) {
|
onAdLoaded: (ad) {
|
||||||
setState(() => _isBannerReady = true);
|
setState(() => _isBannerReady = true);
|
||||||
print('로그인페이지 배너 광고 로드 완료');
|
|
||||||
},
|
},
|
||||||
onAdFailedToLoad: (ad, error) {
|
onAdFailedToLoad: (ad, error) {
|
||||||
print('로그인페이지 배너 광고 로드 실패: $error');
|
|
||||||
ad.dispose();
|
ad.dispose();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -155,7 +153,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
await prefs.setString('oauth_type', 'idpw');
|
await prefs.setString('oauth_type', 'idpw');
|
||||||
await prefs.setBool('auto_login', true);
|
await prefs.setBool('auto_login', true);
|
||||||
await prefs.setString('jwt_token', resp['auth']['token'].toString());
|
await prefs.setString('jwt_token', resp['auth']['token'].toString());
|
||||||
await prefs.setString('user_seq', resp['auth']['user_seq'].toString());
|
await prefs.setInt('my_user_seq', resp['auth']['user_seq']);
|
||||||
|
|
||||||
// 메인 페이지 이동
|
// 메인 페이지 이동
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
@ -225,7 +223,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
await prefs.setString('oauth_type', 'google');
|
await prefs.setString('oauth_type', 'google');
|
||||||
await prefs.setBool('auto_login', true);
|
await prefs.setBool('auto_login', true);
|
||||||
await prefs.setString('jwt_token', resp['auth']['token'].toString());
|
await prefs.setString('jwt_token', resp['auth']['token'].toString());
|
||||||
await prefs.setString('user_seq', resp['auth']['user_seq'].toString());
|
await prefs.setInt('my_user_seq', resp['auth']['user_seq']);
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => const MainPage()),
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
@ -348,7 +348,7 @@ class _CreateRoomPageState extends State<CreateRoomPage> {
|
|||||||
|
|
||||||
// 방 생성 성공 → 대기 방으로 이동
|
// 방 생성 성공 → 대기 방으로 이동
|
||||||
if (_isTeamGame) {
|
if (_isTeamGame) {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => WaitingRoomTeamPage(
|
builder: (_) => WaitingRoomTeamPage(
|
||||||
@ -356,9 +356,10 @@ class _CreateRoomPageState extends State<CreateRoomPage> {
|
|||||||
roomType: 'team',
|
roomType: 'team',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => WaitingRoomPrivatePage(
|
builder: (_) => WaitingRoomPrivatePage(
|
||||||
@ -366,6 +367,7 @@ class _CreateRoomPageState extends State<CreateRoomPage> {
|
|||||||
roomType: 'private',
|
roomType: 'private',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -437,7 +439,6 @@ class _CreateRoomPageState extends State<CreateRoomPage> {
|
|||||||
return {'result': 'FAIL'};
|
return {'result': 'FAIL'};
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('serverResponse 오류: $e');
|
|
||||||
return {'result': 'FAIL'};
|
return {'result': 'FAIL'};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@ import '../../dialogs/response_dialog.dart';
|
|||||||
// 뒤로가기
|
// 뒤로가기
|
||||||
import 'package:fluttertoast/fluttertoast.dart'; // 뒤로가기 안내 문구에 Toast 등 사용
|
import 'package:fluttertoast/fluttertoast.dart'; // 뒤로가기 안내 문구에 Toast 등 사용
|
||||||
|
|
||||||
|
// 설정
|
||||||
|
import '../../config/config.dart';
|
||||||
|
|
||||||
class MainPage extends StatefulWidget {
|
class MainPage extends StatefulWidget {
|
||||||
const MainPage({Key? key}) : super(key: key);
|
const MainPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@ -30,6 +33,7 @@ class _MainPageState extends State<MainPage> {
|
|||||||
/// (1) 광고 배너 관련 변수
|
/// (1) 광고 배너 관련 변수
|
||||||
BannerAd? _bannerAd;
|
BannerAd? _bannerAd;
|
||||||
bool _isBannerReady = false; // 광고 로드 완료 여부
|
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||||
|
String adUnitId = Config.testAdUnitId;
|
||||||
|
|
||||||
// 뒤로가기 처리
|
// 뒤로가기 처리
|
||||||
DateTime? _lastPressedTime;
|
DateTime? _lastPressedTime;
|
||||||
@ -53,12 +57,18 @@ class _MainPageState extends State<MainPage> {
|
|||||||
_initBannerAd();
|
_initBannerAd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_bannerAd?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
/// 배너 광고 초기화
|
/// 배너 광고 초기화
|
||||||
void _initBannerAd() {
|
void _initBannerAd() {
|
||||||
_bannerAd = BannerAd(
|
_bannerAd = BannerAd(
|
||||||
size: AdSize.banner, // 일반 배너 사이즈
|
size: AdSize.banner, // 일반 배너 사이즈
|
||||||
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' (테스트용)
|
||||||
adUnitId: 'ca-app-pub-3940256099942544/6300978111', // 예시: 구글 테스트 배너ID
|
adUnitId: adUnitId, // 실제/테스트 배너 광고 단위 ID
|
||||||
listener: BannerAdListener(
|
listener: BannerAdListener(
|
||||||
onAdLoaded: (Ad ad) {
|
onAdLoaded: (Ad ad) {
|
||||||
setState(() => _isBannerReady = true);
|
setState(() => _isBannerReady = true);
|
||||||
@ -76,12 +86,6 @@ class _MainPageState extends State<MainPage> {
|
|||||||
_bannerAd?.load();
|
_bannerAd?.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_bannerAd?.dispose(); // ★ 광고 자원 해제
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _onWillPop() async {
|
Future<bool> _onWillPop() async {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
if (_lastPressedTime == null ||
|
if (_lastPressedTime == null ||
|
||||||
@ -243,26 +247,6 @@ class _MainPageState extends State<MainPage> {
|
|||||||
style: TextStyle(color: Colors.black),
|
style: TextStyle(color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// 디버그용 임시버튼
|
|
||||||
Center(
|
|
||||||
child: OutlinedButton(
|
|
||||||
onPressed: () {
|
|
||||||
// TODO
|
|
||||||
},
|
|
||||||
style: OutlinedButton.styleFrom(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
side: const BorderSide(color: Colors.black54, width: 1),
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 60),
|
|
||||||
),
|
|
||||||
child: const Text(
|
|
||||||
'방 생성 완료 이동(임시)',
|
|
||||||
style: TextStyle(color: Colors.black, fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -3,8 +3,13 @@ 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';
|
||||||
|
|
||||||
|
// 메인 페이지
|
||||||
import 'main_page.dart';
|
import 'main_page.dart';
|
||||||
|
|
||||||
|
// API
|
||||||
import '../../plugins/api.dart';
|
import '../../plugins/api.dart';
|
||||||
|
|
||||||
|
// 대화 창
|
||||||
import '../../dialogs/response_dialog.dart';
|
import '../../dialogs/response_dialog.dart';
|
||||||
import '../../dialogs/yes_no_dialog.dart';
|
import '../../dialogs/yes_no_dialog.dart';
|
||||||
import '../../dialogs/room_setting_dialog.dart';
|
import '../../dialogs/room_setting_dialog.dart';
|
||||||
@ -12,6 +17,12 @@ import '../../dialogs/user_info_team_dialog.dart';
|
|||||||
import '../../dialogs/team_name_edit_dialog.dart';
|
import '../../dialogs/team_name_edit_dialog.dart';
|
||||||
import 'playing_team_page.dart';
|
import 'playing_team_page.dart';
|
||||||
|
|
||||||
|
// 광고
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
|
||||||
|
// 설정
|
||||||
|
import '../../config/config.dart';
|
||||||
|
|
||||||
class WaitingRoomTeamPage extends StatefulWidget {
|
class WaitingRoomTeamPage extends StatefulWidget {
|
||||||
final int roomSeq;
|
final int roomSeq;
|
||||||
final String roomType; // "team"
|
final String roomType; // "team"
|
||||||
@ -43,12 +54,17 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
|
|
||||||
|
// 서버 요청 로딩중
|
||||||
|
bool _isServerRequestLoading = false;
|
||||||
|
|
||||||
late DatabaseReference _roomRef;
|
late DatabaseReference _roomRef;
|
||||||
Stream<DatabaseEvent>? _roomStream;
|
Stream<DatabaseEvent>? _roomStream;
|
||||||
StreamSubscription<DatabaseEvent>? _roomStreamSubscription;
|
StreamSubscription<DatabaseEvent>? _roomStreamSubscription;
|
||||||
|
|
||||||
bool _movedToRunningPage = false;
|
bool _movedToRunningPage = false;
|
||||||
bool _kickedOut = false;
|
bool _kickedOut = false;
|
||||||
|
bool _roomTimeOut = false;
|
||||||
|
String _roomTimeOutMsg = '';
|
||||||
|
|
||||||
String mySeq = '0';
|
String mySeq = '0';
|
||||||
|
|
||||||
@ -57,10 +73,21 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
Duration _remaining = const Duration(hours: 1);
|
Duration _remaining = const Duration(hours: 1);
|
||||||
DateTime? _createDt;
|
DateTime? _createDt;
|
||||||
|
|
||||||
|
/// (1) 광고 배너 관련 변수
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
bool _isBannerReady = false; // 광고 로드 완료 여부
|
||||||
|
String adUnitId = Config.testAdUnitId;
|
||||||
|
|
||||||
|
// 방장 SEQ 저장
|
||||||
|
String _masterSeqString = '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
FirebaseDatabase.instance.goOnline();
|
FirebaseDatabase.instance.goOnline();
|
||||||
|
// (C) 배너 광고 초기화
|
||||||
|
_initBannerAd();
|
||||||
|
// (D) 방 정보 초기화
|
||||||
_initRoomRef();
|
_initRoomRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +113,29 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
super.dispose();
|
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);
|
||||||
|
debugPrint('배너 광고 로드 완료');
|
||||||
|
},
|
||||||
|
onAdFailedToLoad: (Ad ad, LoadAdError err) {
|
||||||
|
debugPrint('배너 광고 로드 실패: $err');
|
||||||
|
ad.dispose();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
request: const AdRequest(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// load() 호출로 광고 요청
|
||||||
|
_bannerAd?.load();
|
||||||
|
}
|
||||||
|
|
||||||
void _listenRoomData() {
|
void _listenRoomData() {
|
||||||
_roomStream = _roomRef.onValue;
|
_roomStream = _roomRef.onValue;
|
||||||
_roomStreamSubscription = _roomStream?.listen((event) {
|
_roomStreamSubscription = _roomStream?.listen((event) {
|
||||||
@ -101,7 +151,28 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
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 userInfoData = data['userInfo'] as Map<dynamic, dynamic>? ?? {};
|
||||||
|
final userInfoDynamic = data['userInfo']; // 이건 List일 수 있음
|
||||||
|
|
||||||
|
final tempList = <Map<String, dynamic>>[];
|
||||||
|
// userList
|
||||||
|
if (userInfoDynamic is Map) {
|
||||||
|
userInfoDynamic.forEach((key, val) {
|
||||||
|
if (val is Map) {
|
||||||
|
tempList.add({
|
||||||
|
'user_seq': val['user_seq'].toString() ?? '0',
|
||||||
|
'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(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final roomStatus = (roomInfoData['room_status'] ?? 'WAIT').toString().toUpperCase();
|
final roomStatus = (roomInfoData['room_status'] ?? 'WAIT').toString().toUpperCase();
|
||||||
|
|
||||||
@ -130,21 +201,12 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
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'] ?? '유저',
|
|
||||||
'team_name': userMap['team_name'] ?? '',
|
|
||||||
'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;
|
||||||
});
|
});
|
||||||
@ -152,7 +214,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
// 진행중 -> 이동
|
// 진행중 -> 이동
|
||||||
if (roomStatus == 'RUNNING' && !_movedToRunningPage) {
|
if (roomStatus == 'RUNNING' && !_movedToRunningPage) {
|
||||||
_movedToRunningPage = true;
|
_movedToRunningPage = true;
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => PlayingTeamPage(
|
builder: (_) => PlayingTeamPage(
|
||||||
@ -160,16 +222,28 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
roomTitle: roomTitle,
|
roomTitle: roomTitle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (C) create_dt 파싱 -> 1시간 카운트다운
|
// (C) create_dt 파싱 -> 1시간 카운트다운
|
||||||
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);
|
||||||
|
print('isoStr: $isoStr');
|
||||||
|
|
||||||
|
final dt1 = DateTime.tryParse(createDtStr);
|
||||||
|
print('dt1: $dt1');
|
||||||
|
final dt = DateTime.tryParse(isoStr);
|
||||||
|
print('dt: $dt');
|
||||||
|
final dt2 = DateTime.parse(isoStr);
|
||||||
|
print('dt2: $dt2');
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
|
setState(() {
|
||||||
_createDt = dt;
|
_createDt = dt;
|
||||||
|
});
|
||||||
_startCountdownTimer();
|
_startCountdownTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,11 +252,17 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
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) {
|
||||||
|
_roomTimeOutMsg = '방장이 나갔습니다.';
|
||||||
|
} else if (_kickedOut) {
|
||||||
|
_roomTimeOutMsg = '강퇴되었습니다.';
|
||||||
|
}
|
||||||
Future.delayed(Duration.zero, () async {
|
Future.delayed(Duration.zero, () async {
|
||||||
await showResponseDialog(context, '안내', '강퇴되었습니다.');
|
await showResponseDialog(context, '안내', _roomTimeOutMsg);
|
||||||
Navigator.pushReplacement(
|
Navigator.pushAndRemoveUntil(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (_) => const MainPage()),
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -202,7 +282,8 @@ 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);
|
||||||
|
|
||||||
@ -220,6 +301,9 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
void _onAutoTimeout() {
|
void _onAutoTimeout() {
|
||||||
// 자동 종료 -> 방장=나가기(방삭제), 일반=나가기
|
// 자동 종료 -> 방장=나가기(방삭제), 일반=나가기
|
||||||
|
setState(() {
|
||||||
|
_roomTimeOut = true;
|
||||||
|
});
|
||||||
_requestLeaveRoom();
|
_requestLeaveRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +316,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => const MainPage()));
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => const MainPage()),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +390,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
Widget _buildTopButtons() {
|
Widget _buildTopButtons() {
|
||||||
if (_isLoading) return const SizedBox();
|
if (_isLoading) return const SizedBox();
|
||||||
|
|
||||||
final me = _userList.firstWhere((u) => (u['user_seq'] ?? '0') == mySeq, orElse: () => {});
|
final me = _userList.firstWhere((u) => (u['user_seq'].toString() ?? '0') == mySeq, orElse: () => {});
|
||||||
final myReadyYn = (me['ready_yn'] ?? 'N').toString().toUpperCase();
|
final myReadyYn = (me['ready_yn'] ?? 'N').toString().toUpperCase();
|
||||||
final bool isReady = (myReadyYn == 'Y');
|
final bool isReady = (myReadyYn == 'Y');
|
||||||
final readyLabel = isReady ? '준비완료' : '준비';
|
final readyLabel = isReady ? '준비완료' : '준비';
|
||||||
@ -341,8 +429,10 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
style: btnStyle,
|
style: btnStyle,
|
||||||
onPressed: _onGameStart,
|
onPressed: _isServerRequestLoading ? null : _onGameStart,
|
||||||
child: const Text('게임 시작'),
|
child: _isServerRequestLoading
|
||||||
|
? const CircularProgressIndicator()
|
||||||
|
: const Text('게임 시작'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -378,7 +468,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
|
|
||||||
Future<void> _onToggleReady() async {
|
Future<void> _onToggleReady() async {
|
||||||
try {
|
try {
|
||||||
final me = _userList.firstWhere((u) => (u['user_seq'] ?? '') == mySeq, orElse: () => {});
|
final me = _userList.firstWhere((u) => (u['user_seq'].toString() ?? '') == mySeq, orElse: () => {});
|
||||||
final myReadyYn = (me['ready_yn'] ?? 'N').toString().toUpperCase();
|
final myReadyYn = (me['ready_yn'] ?? 'N').toString().toUpperCase();
|
||||||
final isReady = (myReadyYn == 'Y');
|
final isReady = (myReadyYn == 'Y');
|
||||||
final newYn = isReady ? 'N' : 'Y';
|
final newYn = isReady ? 'N' : 'Y';
|
||||||
@ -386,7 +476,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
final userRef = _roomRef.child('userInfo').child(mySeq);
|
final userRef = _roomRef.child('userInfo').child(mySeq);
|
||||||
await userRef.update({"ready_yn": newYn});
|
await userRef.update({"ready_yn": newYn});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('READY 설정 실패: $e');
|
showResponseDialog(context, '오류', 'READY 설정에 실패했습니다.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,9 +507,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onGameStart() async {
|
Future<void> _onGameStart() async {
|
||||||
|
setState(() => _isServerRequestLoading = true);
|
||||||
final notReady = _userList.any((u) => (u['ready_yn'] ?? 'N').toString().toUpperCase() != 'Y');
|
final notReady = _userList.any((u) => (u['ready_yn'] ?? 'N').toString().toUpperCase() != 'Y');
|
||||||
if (notReady) {
|
if (notReady) {
|
||||||
showResponseDialog(context, '안내', 'READY되지 않은 참가자가 있습니다(방장 포함).');
|
showResponseDialog(context, '안내', '아직 준비되지 않은 참가자가 있습니다(방장 포함).');
|
||||||
|
setState(() => _isServerRequestLoading = false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,13 +526,18 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
if (resp['result'] == 'OK') {
|
if (resp['result'] == 'OK') {
|
||||||
print('게임 시작 요청 성공(팀전)');
|
print('게임 시작 요청 성공(팀전)');
|
||||||
} else {
|
} else {
|
||||||
// ...
|
// 게임 시작 요청 실패
|
||||||
|
showResponseDialog(context, '오류', '게임 시작 요청에 실패했습니다.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ...
|
// 게임 시작 요청 실패
|
||||||
|
showResponseDialog(context, '오류', '게임 시작 요청에 실패했습니다.');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ...
|
// 게임 시작 요청 실패
|
||||||
|
showResponseDialog(context, '오류', '게임 시작 요청에 실패했습니다.');
|
||||||
|
} finally {
|
||||||
|
setState(() => _isServerRequestLoading = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,25 +558,34 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
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(
|
||||||
@ -490,10 +596,10 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
_buildTopButtons(),
|
_buildTopButtons(),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
const Text('사회자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black)),
|
// const Text('사회자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black)),
|
||||||
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, color: Colors.black)),
|
const Text('팀별 참가자', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black)),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@ -507,34 +613,35 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAdminSection() {
|
// Widget _buildAdminSection() {
|
||||||
final adminList = _userList.where((u) {
|
// final adminList = _userList.where((u) {
|
||||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
// final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||||
return pType == 'ADMIN';
|
// return pType == '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('사회자가 없습니다.', style: TextStyle(color: Colors.black))
|
// ? const Text('사회자가 없습니다.', style: TextStyle(color: Colors.black))
|
||||||
: Wrap(
|
// : Wrap(
|
||||||
spacing: 16,
|
// spacing: 16,
|
||||||
runSpacing: 8,
|
// runSpacing: 8,
|
||||||
children: adminList.map(_buildSeat).toList(),
|
// children: adminList.map(_buildSeat).toList(),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
Widget _buildTeamSection() {
|
Widget _buildTeamSection() {
|
||||||
final players = _userList.where((u) {
|
// final players = _userList.where((u) {
|
||||||
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
// final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||||
return (pType != 'ADMIN');
|
// return (pType != 'ADMIN');
|
||||||
}).toList();
|
// }).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) {
|
||||||
@ -619,7 +726,7 @@ 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();
|
final pType = (u['participant_type'] ?? '').toString().toUpperCase();
|
||||||
if (pType == 'ADMIN') return false;
|
// 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.isEmpty || tName == 'WAIT');
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -662,6 +769,24 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
final bool isDisconnected = (connectYn == 'N');
|
final bool isDisconnected = (connectYn == 'N');
|
||||||
final bool isMaster = (roomMasterYn == 'Y');
|
final bool isMaster = (roomMasterYn == 'Y');
|
||||||
|
|
||||||
|
// user가 방장인지 확인
|
||||||
|
final isRoomMasterUser = (user['user_seq']?.toString() ?? '') == _masterSeqString;
|
||||||
|
// user가 사회자인지 확인
|
||||||
|
final participantType = (user['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(
|
||||||
@ -738,7 +863,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(userName, style: const TextStyle(fontSize: 12, color: Colors.black)),
|
Text(displayName, style: const TextStyle(fontSize: 12, color: Colors.black)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user