feat(ads): 네이티브 광고 적용 및 디버그 스위치 이동

This commit is contained in:
JiWoong Sul
2025-12-03 17:25:00 +09:00
parent 5cae033977
commit d733bf664b
19 changed files with 461 additions and 168 deletions

View File

@@ -12,6 +12,7 @@ import 'package:lunchpick/domain/entities/restaurant.dart';
import 'package:lunchpick/domain/entities/share_device.dart';
import 'package:lunchpick/presentation/providers/ad_provider.dart';
import 'package:lunchpick/presentation/providers/bluetooth_provider.dart';
import 'package:lunchpick/presentation/providers/debug_share_preview_provider.dart';
import 'package:lunchpick/presentation/providers/restaurant_provider.dart';
import 'package:lunchpick/presentation/widgets/native_ad_placeholder.dart';
import 'package:uuid/uuid.dart';
@@ -85,9 +86,9 @@ class _ShareScreenState extends ConsumerState<ShareScreen> {
bool _isScanning = false;
List<ShareDevice>? _nearbyDevices;
StreamSubscription<String>? _dataSubscription;
ProviderSubscription<bool>? _debugPreviewSub;
final _uuid = const Uuid();
bool _debugPreviewEnabled = false;
bool _debugPreviewProcessing = false;
Timer? _debugPreviewTimer;
@override
@@ -97,11 +98,25 @@ class _ShareScreenState extends ConsumerState<ShareScreen> {
_dataSubscription = bluetoothService.onDataReceived.listen((payload) {
_handleIncomingData(payload);
});
_debugPreviewEnabled = ref.read(debugSharePreviewProvider);
if (_debugPreviewEnabled) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_handleDebugToggleChange(true);
});
}
_debugPreviewSub = ref.listenManual<bool>(debugSharePreviewProvider, (
previous,
next,
) {
if (previous == next) return;
_handleDebugToggleChange(next);
});
}
@override
void dispose() {
_dataSubscription?.cancel();
_debugPreviewSub?.close();
ref.read(bluetoothServiceProvider).stopListening();
_debugPreviewTimer?.cancel();
super.dispose();
@@ -132,10 +147,6 @@ class _ShareScreenState extends ConsumerState<ShareScreen> {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (kDebugMode) ...[
_buildDebugToggle(isDark),
const SizedBox(height: 16),
],
_ShareCard(
isDark: isDark,
icon: Icons.upload_rounded,
@@ -146,7 +157,7 @@ class _ShareScreenState extends ConsumerState<ShareScreen> {
child: _buildSendSection(isDark),
),
const SizedBox(height: 16),
const NativeAdPlaceholder(),
const NativeAdPlaceholder(height: 220),
const SizedBox(height: 16),
_ShareCard(
isDark: isDark,
@@ -577,87 +588,16 @@ class _ShareScreenState extends ConsumerState<ShareScreen> {
);
}
Widget _buildDebugToggle(bool isDark) {
return Card(
color: isDark ? AppColors.darkSurface : AppColors.lightSurface,
elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(14),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: AppColors.lightPrimary.withOpacity(0.1),
shape: BoxShape.circle,
),
child: const Icon(
Icons.science_outlined,
color: AppColors.lightPrimary,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'테스트 토글 (디버그 전용)',
style: AppTypography.body1(
isDark,
).copyWith(fontWeight: FontWeight.w600),
),
const SizedBox(height: 4),
Text(
_debugPreviewEnabled
? '샘플 코드·기기와 수신 데이터가 자동으로 표시됩니다.'
: '토글을 켜면 광고/권한 없이 공유 UI를 미리 볼 수 있습니다.',
style: AppTypography.caption(isDark),
),
],
),
),
const SizedBox(width: 8),
if (_debugPreviewProcessing)
const SizedBox(
width: 22,
height: 22,
child: CircularProgressIndicator(strokeWidth: 2),
),
const SizedBox(width: 8),
Switch.adaptive(
value: _debugPreviewEnabled,
onChanged: _debugPreviewProcessing
? null
: (value) {
_toggleDebugPreview(value);
},
activeColor: AppColors.lightPrimary,
),
],
),
),
);
}
Future<void> _toggleDebugPreview(bool enabled) async {
if (_debugPreviewProcessing) return;
Future<void> _handleDebugToggleChange(bool enabled) async {
if (!mounted) return;
setState(() {
_debugPreviewProcessing = true;
_debugPreviewEnabled = enabled;
});
if (enabled) {
await _startDebugPreviewFlow();
} else {
_stopDebugPreviewFlow();
}
if (!mounted) return;
setState(() {
_debugPreviewEnabled = enabled;
_debugPreviewProcessing = false;
});
}
Future<void> _startDebugPreviewFlow() async {