1차 최종

This commit is contained in:
eld_master 2025-01-22 19:51:36 +09:00
parent b34802b894
commit 7278c6e06e
24 changed files with 1143 additions and 1060 deletions

View File

@ -20,8 +20,8 @@ android {
applicationId "com.allscore_app" applicationId "com.allscore_app"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 34 targetSdkVersion 34
versionCode 1 versionCode 4
versionName "1.0" versionName "1.0.3"
} }
// ... // ...

View File

@ -5,6 +5,7 @@ class Config {
static const String realAdUnitId = 'ca-app-pub-6461991944599918~9492697896'; static const String realAdUnitId = 'ca-app-pub-6461991944599918~9492697896';
// ID // ID
static const String adUnitId = 'ca-app-pub-6461991944599918~9492697896'; static const String adUnitId = 'ca-app-pub-6461991944599918~9492697896';
// static const String adUnitId = 'ca-app-pub-3940256099942544/6300978111';
// //
static const String baseUrl = 'https://eldsoft.com:8097'; static const String baseUrl = 'https://eldsoft.com:8097';
// //

View File

@ -64,8 +64,9 @@ class _ScoreEditDialogState extends State<ScoreEditDialog> {
void _onDelta(int delta) { void _onDelta(int delta) {
setState(() { setState(() {
newScore += delta; newScore += delta;
if (newScore < 0) newScore = 0; // 0 // if (newScore < 0) newScore = 0; // 0
if (newScore > 999999) newScore = 999999; // if (newScore > 999999) newScore = 999999; //
if (newScore < -999999) newScore = -999999; //
}); });
} }
@ -122,17 +123,24 @@ class _ScoreEditDialogState extends State<ScoreEditDialog> {
], ],
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Wrap( SizedBox(
spacing: 4, // height: 120, //
runSpacing: 4, child: GridView.count(
children: [ crossAxisCount: 2, // 3
_buildDeltaButton(-100), mainAxisSpacing: 8,
_buildDeltaButton(-10), crossAxisSpacing: 8,
_buildDeltaButton(-1), childAspectRatio: 2.0, // :
_buildDeltaButton(1), shrinkWrap: true,
_buildDeltaButton(10), physics: const NeverScrollableScrollPhysics(),
_buildDeltaButton(100), children: [
], _buildDeltaButton(-100),
_buildDeltaButton(100),
_buildDeltaButton(-10),
_buildDeltaButton(10),
_buildDeltaButton(-1),
_buildDeltaButton(1),
],
),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),

View File

@ -121,7 +121,7 @@ class _TeamNameEditModalState extends State<TeamNameEditModal> {
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
SizedBox( SizedBox(
width: 100, width: 80,
child: ElevatedButton( child: ElevatedButton(
onPressed: _onUpdateTeamName, onPressed: _onUpdateTeamName,
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
@ -130,7 +130,7 @@ class _TeamNameEditModalState extends State<TeamNameEditModal> {
), ),
), ),
SizedBox( SizedBox(
width: 100, width: 80,
child: ElevatedButton( child: ElevatedButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),

View File

@ -23,7 +23,7 @@ class UserInfoBasicDialog extends StatelessWidget {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text('유저 정보 (진행중-개인전)', const Text('유저 정보',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12), const SizedBox(height: 12),

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'response_dialog.dart'; import 'response_dialog.dart';
import '../../plugins/api.dart'; import '../../plugins/api.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:auto_size_text/auto_size_text.dart';
class UserInfoPrivateDialog extends StatefulWidget { class UserInfoPrivateDialog extends StatefulWidget {
final Map<String, dynamic> userData; final Map<String, dynamic> userData;
@ -24,6 +26,10 @@ class _UserInfoPrivateDialogState extends State<UserInfoPrivateDialog> {
late String participantType; // 'ADMIN' or 'PLAYER' late String participantType; // 'ADMIN' or 'PLAYER'
late String introduceMyself; late String introduceMyself;
//
double scaleFactor = 1.0;
double buttonScaleFactor = 1.0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -32,6 +38,22 @@ class _UserInfoPrivateDialogState extends State<UserInfoPrivateDialog> {
introduceMyself = widget.userData['introduce_myself'] ?? ''; introduceMyself = widget.userData['introduce_myself'] ?? '';
} }
@override
void didChangeDependencies() {
super.didChangeDependencies();
_updateScaleFactor();
}
//
void _updateScaleFactor() {
final screenWidth = MediaQuery.of(context).size.width;
const baseWidth = 450.0;
setState(() {
scaleFactor = (screenWidth / baseWidth).clamp(0.8, 1.2);
buttonScaleFactor = (screenWidth / baseWidth).clamp(0.6, 1.2);
});
}
/// API ( ) /// API ( )
Future<void> _onUpdateUserInfo() async { Future<void> _onUpdateUserInfo() async {
// //
@ -71,6 +93,13 @@ class _UserInfoPrivateDialogState extends State<UserInfoPrivateDialog> {
Future<void> _onKickParticipant() async { Future<void> _onKickParticipant() async {
// -> return // -> return
if (!widget.isRoomMaster) return; if (!widget.isRoomMaster) return;
//
final prefs = await SharedPreferences.getInstance();
final mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0';
if (widget.userData['user_seq'] == mySeq) {
await showResponseDialog(context, '오류', '방장은 추방할 수 없습니다.');
return;
}
final reqBody = { final reqBody = {
"room_seq": "${widget.roomSeq}", "room_seq": "${widget.roomSeq}",
@ -116,7 +145,7 @@ class _UserInfoPrivateDialogState extends State<UserInfoPrivateDialog> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text( const Text(
'유저 정보 (개인전)', '유저 정보',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
@ -224,34 +253,40 @@ class _UserInfoPrivateDialogState extends State<UserInfoPrivateDialog> {
children: [ children: [
// (D-1) // (D-1)
SizedBox( SizedBox(
width: 90, width: scaleFactor==0.8 ? 50 : 90,
child: ElevatedButton( child: ElevatedButton(
onPressed: _onUpdateUserInfo, onPressed: _onUpdateUserInfo,
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: FittedBox( child: AutoSizeText(
child: Text('수정하기', style: TextStyle(color: Colors.white)), scaleFactor==0.8 ? '수정' : '수정하기',
maxLines: 1,
style: TextStyle(color: Colors.white),
), ),
), ),
), ),
// (D-2) // (D-2)
SizedBox( SizedBox(
width: 90, width: scaleFactor==0.8 ? 50 : 90,
child: ElevatedButton( child: ElevatedButton(
onPressed: _onKickParticipant, onPressed: _onKickParticipant,
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: FittedBox( child: AutoSizeText(
child: Text('추방하기', style: TextStyle(color: Colors.white)), scaleFactor==0.8 ? '추방' : '추방하기',
maxLines: 1,
style: TextStyle(color: Colors.white),
), ),
), ),
), ),
// (D-3) // (D-3)
SizedBox( SizedBox(
width: 90, width: scaleFactor==0.8 ? 50 : 90,
child: ElevatedButton( child: ElevatedButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: FittedBox( child: AutoSizeText(
child: Text('확인', style: TextStyle(color: Colors.white)), '확인',
maxLines: 1,
style: TextStyle(color: Colors.white),
), ),
), ),
), ),
@ -261,7 +296,11 @@ class _UserInfoPrivateDialogState extends State<UserInfoPrivateDialog> {
ElevatedButton( ElevatedButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: const Text('확인', style: TextStyle(color: Colors.white)), child: AutoSizeText(
'확인',
maxLines: 1,
style: TextStyle(color: Colors.white),
),
), ),
], ],
], ],

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'response_dialog.dart'; import 'response_dialog.dart';
import '../../plugins/api.dart'; import '../../plugins/api.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:auto_size_text/auto_size_text.dart';
class UserInfoTeamDialog extends StatefulWidget { class UserInfoTeamDialog extends StatefulWidget {
final Map<String, dynamic> userData; final Map<String, dynamic> userData;
@ -27,6 +29,10 @@ class _UserInfoTeamDialogState extends State<UserInfoTeamDialog> {
late String teamName; // 'A'/'B'/'WAIT' late String teamName; // 'A'/'B'/'WAIT'
late String introduceMyself; // late String introduceMyself; //
//
double scaleFactor = 1.0;
double buttonScaleFactor = 1.0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -45,6 +51,22 @@ class _UserInfoTeamDialogState extends State<UserInfoTeamDialog> {
} }
} }
@override
void didChangeDependencies() {
super.didChangeDependencies();
_updateScaleFactor();
}
//
void _updateScaleFactor() {
final screenWidth = MediaQuery.of(context).size.width;
const baseWidth = 450.0;
setState(() {
scaleFactor = (screenWidth / baseWidth).clamp(0.8, 1.2);
buttonScaleFactor = (screenWidth / baseWidth).clamp(0.6, 1.2);
});
}
// (1) / API ( ) // (1) / API ( )
Future<void> _onUpdateUserInfo() async { Future<void> _onUpdateUserInfo() async {
// -> return // -> return
@ -85,6 +107,13 @@ class _UserInfoTeamDialogState extends State<UserInfoTeamDialog> {
Future<void> _onKickParticipant() async { Future<void> _onKickParticipant() async {
// //
if (!widget.isRoomMaster) return; if (!widget.isRoomMaster) return;
//
final prefs = await SharedPreferences.getInstance();
final mySeq = prefs.getInt('my_user_seq')?.toString() ?? '0';
if (widget.userData['user_seq'] == mySeq) {
await showResponseDialog(context, '오류', '방장은 추방할 수 없습니다.');
return;
}
final reqBody = { final reqBody = {
"room_seq": "${widget.roomSeq}", "room_seq": "${widget.roomSeq}",
@ -124,12 +153,13 @@ class _UserInfoTeamDialogState extends State<UserInfoTeamDialog> {
return Dialog( return Dialog(
backgroundColor: Colors.white, backgroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
insetPadding: const EdgeInsets.symmetric(horizontal: 20),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text('유저 정보 (팀전)', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const Text('유저 정보', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12), const SizedBox(height: 12),
// (A) // (A)
@ -257,44 +287,41 @@ class _UserInfoTeamDialogState extends State<UserInfoTeamDialog> {
children: [ children: [
// //
SizedBox( SizedBox(
width: 90, width: scaleFactor==0.8 ? 75 : 90,
child: ElevatedButton( child: ElevatedButton(
onPressed: _onUpdateUserInfo, onPressed: _onUpdateUserInfo,
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
// () FittedBox // () FittedBox
child: FittedBox( child: AutoSizeText(
child: Text( scaleFactor==0.8 ? '수정' : '수정하기',
'수정하기', maxLines: 1,
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
),
), ),
), ),
), ),
// //
SizedBox( SizedBox(
width: 90, width: scaleFactor==0.8 ? 75 : 90,
child: ElevatedButton( child: ElevatedButton(
onPressed: _onKickParticipant, onPressed: _onKickParticipant,
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: FittedBox( child: AutoSizeText(
child: Text( scaleFactor==0.8 ? '추방' : '추방하기',
'추방하기', maxLines: 1,
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
),
), ),
), ),
), ),
// //
SizedBox( SizedBox(
width: 90, width: scaleFactor==0.8 ? 75 : 90,
child: ElevatedButton( child: ElevatedButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: FittedBox( child: AutoSizeText(
child: Text( '확인',
'확인', maxLines: 1,
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
),
), ),
), ),
), ),
@ -305,7 +332,11 @@ class _UserInfoTeamDialogState extends State<UserInfoTeamDialog> {
ElevatedButton( ElevatedButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(backgroundColor: Colors.black), style: ElevatedButton.styleFrom(backgroundColor: Colors.black),
child: const Text('확인', style: TextStyle(color: Colors.white)), child: AutoSizeText(
'확인',
maxLines: 1,
style: TextStyle(color: Colors.white),
),
), ),
], ],
], ],

85
lib/plugins/admob.dart Normal file
View File

@ -0,0 +1,85 @@
import 'package:flutter/material.dart';
// import 'package:google_mobile_ads/google_mobile_ads.dart';
// import '../config/config.dart';
/*
// ================== ( ) ==================
// class AdBannerWidget extends StatefulWidget {
// const AdBannerWidget({Key? key}) : super(key: key);
// @override
// State<AdBannerWidget> createState() => _AdBannerWidgetState();
// }
// class _AdBannerWidgetState extends State<AdBannerWidget> {
// BannerAd? _bannerAd; //
// @override
// void initState() {
// super.initState();
// _initBannerAd();
// }
// @override
// void dispose() {
// _bannerAd?.dispose();
// super.dispose();
// }
// /// &
// void _initBannerAd() {
// _bannerAd = BannerAd(
// size: AdSize.banner, // ()
// adUnitId: Config.adUnitId, // ID (Config에서 )
// listener: BannerAdListener(
// onAdLoaded: (Ad ad) {
// // : _bannerAd를 .
// setState(() {/* 굳이 아무 것도 안 해도 됨 */});
// },
// onAdFailedToLoad: (Ad ad, LoadAdError error) {
// // : & null
// ad.dispose();
// setState(() {
// _bannerAd = null;
// });
// },
// ),
// request: const AdRequest(),
// );
// //
// _bannerAd!.load();
// }
// @override
// Widget build(BuildContext context) {
// // / _bannerAd가 null
// if (_bannerAd == null) {
// return const SizedBox.shrink();
// }
// // Container에 AdWidget으로
// return Container(
// color: Colors.white, //
// width: _bannerAd!.size.width.toDouble(),
// height: _bannerAd!.size.height.toDouble(),
// child: AdWidget(ad: _bannerAd!),
// );
// }
// }
*/
// ================== / ==================
class AdBannerWidget extends StatelessWidget {
const AdBannerWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// () 50dp
// or return SizedBox.shrink()
return const SizedBox(
height: 50, //
child: ColoredBox(color: Colors.white), //
);
}
}

View File

@ -130,7 +130,7 @@ class _SurveyPageState extends State<SurveyPage> {
} }
final requestBody = { final requestBody = {
"QNA": qnaList.toString(), "QNA": qnaList,
}; };
try { try {

View File

@ -7,7 +7,7 @@ import 'pw_finding_page.dart';
import 'signup_page.dart'; import 'signup_page.dart';
// //
import 'package:google_mobile_ads/google_mobile_ads.dart'; import '../../plugins/admob.dart';
// //
import '../../config/config.dart'; import '../../config/config.dart';
@ -27,11 +27,6 @@ class _IdFindingPageState extends State<IdFindingPage> {
String foundIdMessage = ''; String foundIdMessage = '';
String authId = ''; String authId = '';
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
Future<void> _findId(String nickname, String email) async { Future<void> _findId(String nickname, String email) async {
@ -100,30 +95,10 @@ class _IdFindingPageState extends State<IdFindingPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initBannerAd();
}
void _initBannerAd() {
_bannerAd = BannerAd(
// / ID
adUnitId: adUnitId,
size: AdSize.banner,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
setState(() => _isBannerReady = true);
},
onAdFailedToLoad: (ad, error) {
ad.dispose();
},
),
);
_bannerAd?.load();
} }
@override @override
void dispose() { void dispose() {
_bannerAd?.dispose();
super.dispose(); super.dispose();
} }
@ -349,14 +324,7 @@ class _IdFindingPageState extends State<IdFindingPage> {
), ),
// (3) // (3)
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
); );
} }
} }

View File

@ -369,7 +369,7 @@ class _LoginPageState extends State<LoginPage> {
. .
7. 7.
: eld_yeojh@naver.com : eldyeojh@gmail.com
8. 8.
, . , .

View File

@ -7,7 +7,7 @@ import 'signup_page.dart'; // 회원가입 페이지 임포트 추가
import 'id_finding_page.dart'; // ID import 'id_finding_page.dart'; // ID
// //
import 'package:google_mobile_ads/google_mobile_ads.dart'; import '../../plugins/admob.dart';
// //
import '../../config/config.dart'; import '../../config/config.dart';
@ -25,11 +25,6 @@ class _PwFindingPageState extends State<PwFindingPage> {
String emailErrorMessage = ''; // String emailErrorMessage = ''; //
String idErrorMessage = ''; // ID String idErrorMessage = ''; // ID
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
Future<void> _findPassword(String id, String email) async { Future<void> _findPassword(String id, String email) async {
// PW // PW
@ -125,30 +120,10 @@ class _PwFindingPageState extends State<PwFindingPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initBannerAd();
}
void _initBannerAd() {
_bannerAd = BannerAd(
// / ID
adUnitId: adUnitId,
size: AdSize.banner,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
setState(() => _isBannerReady = true);
},
onAdFailedToLoad: (ad, error) {
ad.dispose();
},
),
);
_bannerAd?.load();
} }
@override @override
void dispose() { void dispose() {
_bannerAd?.dispose();
super.dispose(); super.dispose();
} }
@ -254,14 +229,7 @@ class _PwFindingPageState extends State<PwFindingPage> {
), ),
// (3) // (3)
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
); );
} }
} }

View File

@ -253,8 +253,7 @@ class _SignUpPageState extends State<SignUpPage> {
'이용자는 개인정보 수집 및 이용에 대한 동의를 거부할 권리가 있습니다.\n' '이용자는 개인정보 수집 및 이용에 대한 동의를 거부할 권리가 있습니다.\n'
'그러나 필수 항목에 대한 동의를 거부하실 경우 서비스 이용이 제한될 수 있습니다.\n\n' '그러나 필수 항목에 대한 동의를 거부하실 경우 서비스 이용이 제한될 수 있습니다.\n\n'
'7. 개인정보 보호책임자\n' '7. 개인정보 보호책임자\n'
'이름: 여정훈\n' '연락처: eldyeojh@gmail.com\n\n'
'연락처: eld_yeojh@naver.com\n\n'
'8. 개인정보의 안전성 확보 조치\n' '8. 개인정보의 안전성 확보 조치\n'
'회사는 개인정보의 안전한 처리를 위하여 기술적, 관리적 보호조치를 시행하고 있습니다.\n' '회사는 개인정보의 안전한 처리를 위하여 기술적, 관리적 보호조치를 시행하고 있습니다.\n'
'개인정보의 암호화\n' '개인정보의 암호화\n'

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
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 'package:google_mobile_ads/google_mobile_ads.dart'; // AdMob
// import... // import...
import '../../dialogs/settings_dialog.dart'; import '../../dialogs/settings_dialog.dart';
@ -25,6 +24,9 @@ import '../../config/config.dart';
// //
import '../../dialogs/survey_dialog.dart'; import '../../dialogs/survey_dialog.dart';
//
import '../../plugins/admob.dart';
class MainPage extends StatefulWidget { class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key); const MainPage({Key? key}) : super(key: key);
@ -33,11 +35,6 @@ class MainPage extends StatefulWidget {
} }
class _MainPageState extends State<MainPage> { class _MainPageState extends State<MainPage> {
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
// //
DateTime? _lastPressedTime; DateTime? _lastPressedTime;
@ -55,38 +52,13 @@ class _MainPageState extends State<MainPage> {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_checkLandingMainPageInfo(); _checkLandingMainPageInfo();
}); });
// (C)
_initBannerAd();
} }
@override @override
void dispose() { void dispose() {
_bannerAd?.dispose();
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);
},
onAdFailedToLoad: (Ad ad, LoadAdError err) {
ad.dispose();
},
),
request: const AdRequest(),
);
// load()
_bannerAd?.load();
}
Future<bool> _onWillPop() async { Future<bool> _onWillPop() async {
final now = DateTime.now(); final now = DateTime.now();
if (_lastPressedTime == null || if (_lastPressedTime == null ||
@ -202,14 +174,7 @@ class _MainPageState extends State<MainPage> {
], ],
), ),
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? 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,

View File

@ -9,8 +9,8 @@ import '../../plugins/api.dart';
import '../../dialogs/response_dialog.dart'; 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 '../../plugins/admob.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import '../../config/config.dart'; import '../../config/config.dart';
class PlayingPrivatePage extends StatefulWidget { class PlayingPrivatePage extends StatefulWidget {
@ -58,14 +58,12 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
String mySeq = '0'; String mySeq = '0';
//
String myParticipantType = 'PLAYER';
// 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.adUnitId;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -73,8 +71,6 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
FirebaseDatabase.instance.goOnline(); FirebaseDatabase.instance.goOnline();
roomTitle = widget.roomTitle; roomTitle = widget.roomTitle;
// (C)
_initBannerAd();
// (D) // (D)
_initFirebase(); _initFirebase();
} }
@ -86,27 +82,6 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
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);
},
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';
@ -192,6 +167,10 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
'introduce_myself': uData['introduce_myself'] ?? '', 'introduce_myself': uData['introduce_myself'] ?? '',
'is_my_score': (uSeq.toString() == mySeq) ? 'Y' : 'N', 'is_my_score': (uSeq.toString() == mySeq) ? 'Y' : 'N',
}); });
if (uSeq.toString() == mySeq) {
myParticipantType = (uData['participant_type'] ?? '').toString().toUpperCase();
}
}); });
// //
@ -386,11 +365,13 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
}, },
); );
if (confirm != true) return false; if (confirm != true) {
return false;
}
} }
// userList => false // userList => false
final userRef = _roomRef.child('userList').child(mySeq); final userRef = _roomRef.child('userList').child('_$mySeq');
await userRef.set(false); await userRef.set(false);
if (!mounted) return false; if (!mounted) return false;
@ -449,8 +430,7 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
} }
Future<void> _onTapUser(Map<String, dynamic> userData) async { Future<void> _onTapUser(Map<String, dynamic> userData) async {
final pType = (userData['participant_type'] ?? '').toString().toUpperCase(); if (myParticipantType == 'ADMIN') {
if (pType == 'ADMIN') {
// //
await showDialog( await showDialog(
context: context, context: context,
@ -460,16 +440,6 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
userData: userData, userData: userData,
), ),
); );
} else if (roomMasterYn == 'Y') {
// (PLAYER)
await showDialog(
context: context,
builder: (_) => ScoreEditDialog(
roomSeq: widget.roomSeq,
roomType: 'PRIVATE',
userData: userData,
),
);
} else { } else {
// //
await showDialog( await showDialog(
@ -552,14 +522,7 @@ class _PlayingPrivatePageState extends State<PlayingPrivatePage> {
), ),
], ],
), ),
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
), ),
); );
} }

View File

@ -9,8 +9,7 @@ import '../../plugins/api.dart';
import '../../dialogs/response_dialog.dart'; 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 '../../plugins/admob.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import '../../config/config.dart'; import '../../config/config.dart';
class PlayingTeamPage extends StatefulWidget { class PlayingTeamPage extends StatefulWidget {
@ -60,14 +59,12 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
// userListMap: { seq: true/false } // userListMap: { seq: true/false }
Map<String, bool> _userListMap = {}; Map<String, bool> _userListMap = {};
//
String myParticipantType = 'PLAYER';
// //
String scoreOpenRange = 'ALL'; String scoreOpenRange = 'ALL';
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -75,8 +72,6 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
FirebaseDatabase.instance.goOnline(); FirebaseDatabase.instance.goOnline();
roomTitle = widget.roomTitle; roomTitle = widget.roomTitle;
// (C)
_initBannerAd();
// (D) // (D)
_initFirebase(); _initFirebase();
} }
@ -88,27 +83,6 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
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);
},
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';
@ -191,6 +165,9 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
'team_name': (uData['team_name'] ?? '').toString().toUpperCase(), 'team_name': (uData['team_name'] ?? '').toString().toUpperCase(),
'score': uData['score'] ?? 0, 'score': uData['score'] ?? 0,
}); });
if (uSeq.toString() == mySeq) {
myParticipantType = (uData['participant_type'] ?? '').toString().toUpperCase();
}
}); });
// & // &
@ -415,7 +392,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
} }
// userList => false // userList => false
final userRef = _roomRef.child('userList').child(mySeq); final userRef = _roomRef.child('userList').child('_$mySeq');
await userRef.set(false); await userRef.set(false);
if (!mounted) return false; if (!mounted) return false;
@ -510,14 +487,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
), ),
], ],
), ),
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
), ),
); );
} }
@ -616,17 +586,7 @@ class _PlayingTeamPageState extends State<PlayingTeamPage> {
} }
Future<void> _onTapUser(Map<String, dynamic> userData) async { Future<void> _onTapUser(Map<String, dynamic> userData) async {
final pType = (userData['participant_type'] ?? '').toString().toUpperCase(); if (myParticipantType == 'ADMIN') {
if (pType == 'ADMIN') {
await showDialog(
context: context,
builder: (_) => ScoreEditDialog(
roomSeq: widget.roomSeq,
roomType: 'TEAM',
userData: userData,
),
);
} else if (roomMasterYn == 'Y') {
await showDialog( await showDialog(
context: context, context: context,
builder: (_) => ScoreEditDialog( builder: (_) => ScoreEditDialog(

View File

@ -5,7 +5,7 @@ import 'room_search_list_page.dart';
import '../../config/config.dart'; import '../../config/config.dart';
// //
import 'package:google_mobile_ads/google_mobile_ads.dart'; // AdMob import '../../plugins/admob.dart';
class RoomSearchHomePage extends StatefulWidget { class RoomSearchHomePage extends StatefulWidget {
const RoomSearchHomePage({Key? key}) : super(key: key); const RoomSearchHomePage({Key? key}) : super(key: key);
@ -15,43 +15,32 @@ class RoomSearchHomePage extends StatefulWidget {
} }
class _RoomSearchHomePageState extends State<RoomSearchHomePage> { class _RoomSearchHomePageState extends State<RoomSearchHomePage> {
BannerAd? _bannerAd; //
bool _isBannerReady = false; // double scaleFactor = 1.0;
String adUnitId = Config.adUnitId;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// (C)
_initBannerAd();
} }
@override @override
void dispose() { void dispose() {
_bannerAd?.dispose();
super.dispose(); super.dispose();
} }
/// @override
void _initBannerAd() { void didChangeDependencies() {
_bannerAd = BannerAd( super.didChangeDependencies();
size: AdSize.banner, // _updateScaleFactor();
// adUnitId: 'ca-app-pub-3940256099942544/6300978111' () }
adUnitId: adUnitId, // / ID
listener: BannerAdListener(
onAdLoaded: (Ad ad) {
setState(() => _isBannerReady = true);
},
onAdFailedToLoad: (Ad ad, LoadAdError err) {
//
},
),
request: const AdRequest(),
);
// load() //
_bannerAd?.load(); void _updateScaleFactor() {
final screenWidth = MediaQuery.of(context).size.width;
const baseWidth = 450.0;
setState(() {
scaleFactor = (screenWidth / baseWidth).clamp(0.8, 1.2);
});
} }
@override @override
@ -70,14 +59,7 @@ class _RoomSearchHomePageState extends State<RoomSearchHomePage> {
), ),
// //
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
// : 3 ( / / ) // : 3 ( / / )
body: Center( body: Center(
@ -102,8 +84,8 @@ class _RoomSearchHomePageState extends State<RoomSearchHomePage> {
required String status, required String status,
}) { }) {
return SizedBox( return SizedBox(
width: 100, width: 100 * scaleFactor,
height: 100, height: 100 * scaleFactor,
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () {
// RoomSearchListPage로 , roomStatus // RoomSearchListPage로 , roomStatus

View File

@ -14,7 +14,7 @@ import '../room/finish_team_page.dart';
import '../../config/config.dart'; import '../../config/config.dart';
// //
import 'package:google_mobile_ads/google_mobile_ads.dart'; // AdMob import '../../plugins/admob.dart';
class RoomSearchListPage extends StatefulWidget { class RoomSearchListPage extends StatefulWidget {
final String roomStatus; // WAIT / RUNNING / FINISH final String roomStatus; // WAIT / RUNNING / FINISH
@ -37,20 +37,12 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
late ScrollController _scrollController; late ScrollController _scrollController;
//
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_scrollController = ScrollController()..addListener(_onScroll); _scrollController = ScrollController()..addListener(_onScroll);
_fetchRoomList(isRefresh: true); _fetchRoomList(isRefresh: true);
// (C)
_initBannerAd();
} }
@override @override
@ -58,31 +50,9 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
_scrollController.removeListener(_onScroll); _scrollController.removeListener(_onScroll);
_scrollController.dispose(); _scrollController.dispose();
_searchController.dispose(); _searchController.dispose();
_bannerAd?.dispose();
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);
},
onAdFailedToLoad: (Ad ad, LoadAdError err) {
ad.dispose();
},
),
request: const AdRequest(),
);
// load()
_bannerAd?.load();
}
void _onScroll() { void _onScroll() {
if (!_scrollController.hasClients) return; if (!_scrollController.hasClients) return;
final thresholdPixels = 200; final thresholdPixels = 200;
@ -236,14 +206,8 @@ class _RoomSearchListPageState extends State<RoomSearchListPage> {
), ),
), ),
// //
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? 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(
children: [ children: [
// //

View File

@ -12,10 +12,12 @@ 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 '../../plugins/admob.dart';
// //
import '../../config/config.dart'; import '../../config/config.dart';
//
import 'package:auto_size_text/auto_size_text.dart';
class WaitingRoomPrivatePage extends StatefulWidget { class WaitingRoomPrivatePage extends StatefulWidget {
final int roomSeq; final int roomSeq;
@ -74,14 +76,13 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
bool _roomTimeOut = false; bool _roomTimeOut = false;
String _roomExitYn = 'N'; String _roomExitYn = 'N';
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
// SEQ // SEQ
String _masterSeqString = '0'; String _masterSeqString = '0';
//
double scaleFactor = 1.0;
double buttonScaleFactor = 1.0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -89,8 +90,6 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
FirebaseDatabase.instance.goOnline(); FirebaseDatabase.instance.goOnline();
// (B) // (B)
_initRoomRef(); _initRoomRef();
// (C)
_initBannerAd();
} }
@override @override
@ -100,25 +99,20 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
super.dispose(); super.dispose();
} }
/// @override
void _initBannerAd() { void didChangeDependencies() {
_bannerAd = BannerAd( super.didChangeDependencies();
size: AdSize.banner, // _updateScaleFactor();
// 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(); void _updateScaleFactor() {
final screenWidth = MediaQuery.of(context).size.width;
const baseWidth = 450.0;
setState(() {
scaleFactor = (screenWidth / baseWidth).clamp(0.8, 1.2);
buttonScaleFactor = (screenWidth / baseWidth).clamp(0.6, 1.2);
});
} }
Future<void> _initRoomRef() async { Future<void> _initRoomRef() async {
@ -328,7 +322,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
final response = await Api.serverRequest(uri: '/room/score/game/leave', body: reqBody); final response = await Api.serverRequest(uri: '/room/score/game/leave', body: reqBody);
// result ok -> // result ok ->
} catch (e) { } catch (e) {
// await showResponseDialog(context, '오류', '방 나가기 처리 실패');
} }
if (mounted) { if (mounted) {
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false); Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (_) => const MainPage()), (route) => false);
@ -410,7 +404,7 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
final me = _userList.firstWhere((u) => (u['user_seq'].toString() ?? '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 = '준비';
final btnStyle = ElevatedButton.styleFrom( final btnStyle = ElevatedButton.styleFrom(
backgroundColor: Colors.white, backgroundColor: Colors.white,
@ -428,7 +422,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _onOpenRoomSetting, onPressed: _onOpenRoomSetting,
child: const Text('방 설정'), child: AutoSizeText(
'방 설정',
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor),
),
), ),
), ),
), ),
@ -438,7 +436,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _readyButtonEnabled ? _onToggleReady : null, onPressed: _readyButtonEnabled ? _onToggleReady : null,
child: Text(readyLabel), child: AutoSizeText(
readyLabel,
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor, color: isReady ? Colors.red : Colors.black),
),
), ),
), ),
), ),
@ -448,7 +450,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _onGameStart, onPressed: _onGameStart,
child: const Text('게임 시작'), child: AutoSizeText(
scaleFactor==0.8 ? '시작' : '게임 시작',
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor),
),
), ),
), ),
), ),
@ -464,7 +470,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _onOpenRoomSetting, onPressed: _onOpenRoomSetting,
child: const Text('방 설정'), child: AutoSizeText(
'방 설정',
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor),
),
), ),
), ),
), ),
@ -474,7 +484,11 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _readyButtonEnabled ? _onToggleReady : null, onPressed: _readyButtonEnabled ? _onToggleReady : null,
child: Text(readyLabel), child: AutoSizeText(
readyLabel,
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor, color: isReady ? Colors.red : Colors.black),
),
), ),
), ),
), ),
@ -619,14 +633,8 @@ class _WaitingRoomPrivatePageState extends State<WaitingRoomPrivatePage> {
onPressed: () => _onLeaveRoom(), onPressed: () => _onLeaveRoom(),
), ),
), ),
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
body: _isLoading body: _isLoading
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: SingleChildScrollView( : SingleChildScrollView(

View File

@ -18,10 +18,12 @@ 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 '../../plugins/admob.dart';
// //
import '../../config/config.dart'; import '../../config/config.dart';
//
import 'package:auto_size_text/auto_size_text.dart';
class WaitingRoomTeamPage extends StatefulWidget { class WaitingRoomTeamPage extends StatefulWidget {
final int roomSeq; final int roomSeq;
@ -76,24 +78,37 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
bool _roomTimeOut = false; bool _roomTimeOut = false;
String _roomExitYn = 'N'; String _roomExitYn = 'N';
/// (1)
BannerAd? _bannerAd;
bool _isBannerReady = false; //
String adUnitId = Config.adUnitId;
// SEQ // SEQ
String _masterSeqString = '0'; String _masterSeqString = '0';
//
double scaleFactor = 1.0;
double buttonScaleFactor = 1.0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
FirebaseDatabase.instance.goOnline(); FirebaseDatabase.instance.goOnline();
// (C)
_initBannerAd();
// (D) // (D)
_initRoomRef(); _initRoomRef();
} }
@override
void didChangeDependencies() {
super.didChangeDependencies();
_updateScaleFactor();
}
//
void _updateScaleFactor() {
final screenWidth = MediaQuery.of(context).size.width;
const baseWidth = 450.0;
setState(() {
scaleFactor = (screenWidth / baseWidth).clamp(0.8, 1.2);
buttonScaleFactor = (screenWidth / baseWidth).clamp(0.6, 1.2);
});
}
Future<void> _initRoomRef() async { Future<void> _initRoomRef() 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';
@ -118,27 +133,6 @@ 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);
},
onAdFailedToLoad: (Ad ad, LoadAdError 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) {
@ -416,7 +410,7 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
final me = _userList.firstWhere((u) => (u['user_seq'].toString() ?? '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 = '준비';
final btnStyle = ElevatedButton.styleFrom( final btnStyle = ElevatedButton.styleFrom(
backgroundColor: Colors.white, backgroundColor: Colors.white,
@ -433,7 +427,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _onOpenRoomSetting, onPressed: _onOpenRoomSetting,
child: const Text('방 설정'), child: AutoSizeText(
'방 설정',
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor),
),
), ),
), ),
), ),
@ -443,7 +441,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _readyButtonEnabled ? _onToggleReady : null, onPressed: _readyButtonEnabled ? _onToggleReady : null,
child: Text(readyLabel), child: AutoSizeText(
readyLabel,
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor, color: isReady ? Colors.red : Colors.black),
),
), ),
), ),
), ),
@ -455,7 +457,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
onPressed: _isServerRequestLoading ? null : _onGameStart, onPressed: _isServerRequestLoading ? null : _onGameStart,
child: _isServerRequestLoading child: _isServerRequestLoading
? const CircularProgressIndicator() ? const CircularProgressIndicator()
: const Text('게임 시작'), : AutoSizeText(
scaleFactor==0.8 ? '시작' : '게임 시작',
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor),
),
), ),
), ),
), ),
@ -470,7 +476,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _onOpenRoomSetting, onPressed: _onOpenRoomSetting,
child: const Text('방 설정'), child: AutoSizeText(
'방 설정',
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor),
),
), ),
), ),
), ),
@ -480,7 +490,11 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
child: ElevatedButton( child: ElevatedButton(
style: btnStyle, style: btnStyle,
onPressed: _readyButtonEnabled ? _onToggleReady : null, onPressed: _readyButtonEnabled ? _onToggleReady : null,
child: Text(readyLabel), child: AutoSizeText(
readyLabel,
maxLines: 1,
style: TextStyle(fontSize: 14 * scaleFactor, color: isReady ? Colors.red : Colors.black),
),
), ),
), ),
), ),
@ -637,14 +651,8 @@ class _WaitingRoomTeamPageState extends State<WaitingRoomTeamPage> {
onPressed: () => _onLeaveRoom(), onPressed: () => _onLeaveRoom(),
), ),
), ),
bottomNavigationBar: _isBannerReady && _bannerAd != null bottomNavigationBar: AdBannerWidget(),
? Container(
color: Colors.white,
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
)
: SizedBox.shrink(), // or
body: _isLoading body: _isLoading
? const Center(child: CircularProgressIndicator()) ? const Center(child: CircularProgressIndicator())
: SingleChildScrollView( : SingleChildScrollView(

File diff suppressed because it is too large Load Diff

View File

@ -15,9 +15,8 @@ class WithdrawalPage extends StatefulWidget {
} }
class _WithdrawalPageState extends State<WithdrawalPage> { class _WithdrawalPageState extends State<WithdrawalPage> {
bool _isAgreed = false; // bool _isAgreed = false; //
final TextEditingController _passwordController = TextEditingController(); // final TextEditingController _passwordController = TextEditingController(); //
String _oauthType = 'idpw'; String _oauthType = 'idpw';
@override @override
@ -36,7 +35,10 @@ class _WithdrawalPageState extends State<WithdrawalPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// oauth_type == 'google' => //
final screenWidth = MediaQuery.of(context).size.width;
// oauth_type == 'google'
final isGoogleUser = (_oauthType.toLowerCase() == 'google'); final isGoogleUser = (_oauthType.toLowerCase() == 'google');
return Scaffold( return Scaffold(
@ -49,87 +51,105 @@ class _WithdrawalPageState extends State<WithdrawalPage> {
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
), ),
), ),
body: Padding( // SingleChildScrollView
padding: const EdgeInsets.all(16.0), body: SingleChildScrollView(
child: Column( child: Padding(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.all(16.0),
children: [ // Column이
const Text( child: Column(
'회원탈퇴를 진행합니다.\n현재 비밀번호를 입력해주세요.', crossAxisAlignment: CrossAxisAlignment.start,
textAlign: TextAlign.center, children: [
style: TextStyle(fontSize: 18), const SizedBox(height: 20),
), const Center(
const SizedBox(height: 20), child: Text(
// '회원탈퇴를 진행합니다.\n현재 비밀번호를 입력해주세요.',
if (!isGoogleUser) ...[ textAlign: TextAlign.center,
TextField( style: TextStyle(fontSize: 18),
controller: _passwordController, ),
obscureText: true, ),
decoration: InputDecoration( const SizedBox(height: 20),
hintText: '비밀번호 입력',
border: OutlineInputBorder( //
borderRadius: BorderRadius.circular(10), if (!isGoogleUser) ...[
borderSide: const BorderSide(color: Colors.black), TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(
hintText: '비밀번호 입력',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: Colors.black),
),
contentPadding: const EdgeInsets.all(10),
),
),
const SizedBox(height: 20),
],
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black54, width: 1),
borderRadius: BorderRadius.circular(10),
),
padding: const EdgeInsets.all(16.0),
child: const Text(
'[회원 탈퇴 안내]\n'
'회원 탈퇴를 진행하시겠습니까?\n'
' - 회원 탈퇴 시 등록하신 모든 개인정보(ID, 비밀번호, 닉네임, 이메일 주소, 소속, 자기소개 등)는 즉시 삭제되며 복구가 불가능합니다.\n'
' - 탈퇴 후 동일한 아이디로 재가입이 불가능할 수 있습니다.\n'
' - 관련 법령에 따라 일정 기간 보관이 필요한 경우 해당 기간 동안 법령이 허용하는 범위 내에서만 보관됩니다.\n'
'탈퇴를 원하시면 아래의 "동의" 버튼을 눌러주시기 바랍니다.',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 12),
),
),
const SizedBox(height: 20),
Row(
children: [
Checkbox(
value: _isAgreed,
activeColor: Colors.black,
checkColor: Colors.white,
onChanged: (value) {
setState(() {
_isAgreed = value ?? false;
});
},
),
const Expanded(
child: Text(
'회원탈퇴에 동의합니다.',
style: TextStyle(fontSize: 16),
),
),
],
),
const SizedBox(height: 20),
// "탈퇴하기"
Center(
child: ElevatedButton(
onPressed: () {
_requestWithdrawal(_passwordController.text, _isAgreed);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black54,
//
padding: EdgeInsets.symmetric(
vertical: 12,
horizontal: screenWidth * 0.15,
),
),
child: const Text(
'탈퇴하기',
style: TextStyle(color: Colors.white, fontSize: 16),
), ),
contentPadding: const EdgeInsets.all(10),
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
Container( ),
decoration: BoxDecoration(
border: Border.all(color: Colors.black54, width: 1), //
borderRadius: BorderRadius.circular(10), //
),
padding: const EdgeInsets.all(16.0), //
child: const Text(
'[회원 탈퇴 안내]\n'
'회원 탈퇴를 진행하시겠습니까?\n'
' - 회원 탈퇴 시 등록하신 모든 개인정보(ID, 비밀번호, 닉네임, 이메일 주소, 소속, 자기소개 등)는 즉시 삭제되며 복구가 불가능합니다.\n'
' - 탈퇴 후 동일한 아이디로 재가입이 불가능할 수 있습니다.\n'
' - 관련 법령에 따라 일정 기간 보관이 필요한 경우 해당 기간 동안 법령이 허용하는 범위 내에서만 보관됩니다.\n'
'탈퇴를 원하시면 아래의 "동의" 버튼을 눌러주시기 바랍니다.',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 12),
),
),
const SizedBox(height: 20),
Row(
children: [
Checkbox(
value: _isAgreed, //
activeColor: Colors.black, //
checkColor: Colors.white, //
onChanged: (value) {
setState(() {
_isAgreed = value ?? false; //
});
},
),
const Expanded(
child: Text(
'회원탈퇴에 동의합니다.',
style: TextStyle(fontSize: 16),
),
),
],
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
//
_requestWithdrawal(_passwordController.text, _isAgreed);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black54, //
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 60), //
),
child: const Text(
'탈퇴하기',
style: TextStyle(color: Colors.white, fontSize: 16), //
),
),
],
), ),
), ),
); );
@ -137,19 +157,17 @@ class _WithdrawalPageState extends State<WithdrawalPage> {
Future<void> _requestWithdrawal(String password, bool isAgreed) async { Future<void> _requestWithdrawal(String password, bool isAgreed) async {
if (!isAgreed) { if (!isAgreed) {
//
showResponseDialog(context, '회원탈퇴 동의 확인', '회원탈퇴 동의 체크가 필요합니다.'); showResponseDialog(context, '회원탈퇴 동의 확인', '회원탈퇴 동의 체크가 필요합니다.');
return; return;
} }
// //
if (_oauthType != 'google' && password.isEmpty) { if (_oauthType != 'google' && password.isEmpty) {
//
showResponseDialog(context, '비밀번호 확인', '비밀번호를 입력해야 합니다.'); showResponseDialog(context, '비밀번호 확인', '비밀번호를 입력해야 합니다.');
return; return;
} }
// // ''
if (password.isEmpty) { if (password.isEmpty) {
password = ''; password = '';
} }
@ -157,7 +175,7 @@ class _WithdrawalPageState extends State<WithdrawalPage> {
final response = await Api.serverRequest( final response = await Api.serverRequest(
uri: '/user/withdraw/user', uri: '/user/withdraw/user',
body: { body: {
'user_pw': Utils.hashPassword(password), // 'user_pw': Utils.hashPassword(password),
'oauth_type': _oauthType, 'oauth_type': _oauthType,
}, },
); );
@ -165,17 +183,20 @@ class _WithdrawalPageState extends State<WithdrawalPage> {
if (response['result'] == 'OK') { if (response['result'] == 'OK') {
final serverResponse = response['response']; final serverResponse = response['response'];
if (serverResponse['result'] == 'OK') { if (serverResponse['result'] == 'OK') {
// // &
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.remove('auth_token'); // await prefs.remove('auth_token');
await showResponseDialog(context, '회원탈퇴 완료', '회원탈퇴가 완료되었습니다.'); await showResponseDialog(context, '회원탈퇴 완료', '회원탈퇴가 완료되었습니다.');
Navigator.pushReplacement( Navigator.pushReplacement(
context, context,
MaterialPageRoute(builder: (context) => const LoginPage()), // MaterialPageRoute(builder: (context) => const LoginPage()),
); );
} else { } else {
showResponseDialog(context, serverResponse['response_info']['msg_title'], serverResponse['response_info']['msg_content']); showResponseDialog(
context,
serverResponse['response_info']['msg_title'],
serverResponse['response_info']['msg_content'],
);
} }
} else { } else {
showResponseDialog(context, '회원탈퇴 실패', '서버에 문제가 있습니다. 관리자에게 문의해주세요.'); showResponseDialog(context, '회원탈퇴 실패', '서버에 문제가 있습니다. 관리자에게 문의해주세요.');

View File

@ -41,6 +41,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
auto_size_text:
dependency: "direct main"
description:
name: auto_size_text
sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:

View File

@ -1,7 +1,7 @@
name: allscore_app name: allscore_app
description: "A new Flutter project." description: "A new Flutter project."
publish_to: 'none' publish_to: 'none'
version: 1.0.0+1 version: 1.0.3+4
environment: environment:
sdk: ^3.6.0 sdk: ^3.6.0
@ -26,6 +26,7 @@ dependencies:
fluttertoast: ^8.0.9 fluttertoast: ^8.0.9
flutter_launcher_icons: ^0.12.0 flutter_launcher_icons: ^0.12.0
flutter_native_splash: ^2.2.15 flutter_native_splash: ^2.2.15
auto_size_text: ^3.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: