아이폰 근접센서 주머니 감시, 학생 목록 타일 UI, 학교 서버 주소 반영
- iOS는 조도 센서/백그라운드 서비스가 불가능해서 근접센서(UIDevice proximityMonitoring) + 가이드 접근 안내로 대체 구현 (Core NFC와 마찬가지로 네이티브 플러그인 필요해서 ProximityMonitorPlugin.swift 추가) - 교사 대시보드 실시간 출석 현황: 모바일 리스트/데스크톱 표를 타일 그리드로 통일해서 한눈에 보기 쉽게 변경 - 서버를 학교 자체 서버(Cloudflare Tunnel, api.backsanhi.shop)로 이전하면서 기본 BASE_URL 갱신 - Firebase CLI 로컬 캐시(.firebase/)는 소스가 아니라 gitignore 처리 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// 📲 자습실 NFC 출석체크 화면 (UI 전용). 태깅 상태 화면/팝업/스낵바만 그린다.
|
||||
// NFC 세션, 서버 통신, 백그라운드 감시 연동은
|
||||
// lib/function/nfc_pocket_checkin_controller.dart가 담당한다.
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter/material.dart';
|
||||
import '../function/nfc_pocket_checkin_controller.dart';
|
||||
|
||||
@@ -31,6 +33,7 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
|
||||
onMessage: _handleMessage,
|
||||
onCheckInSuccess: _showSuccessDialog,
|
||||
onViolationDetected: _showViolationDialog,
|
||||
onNeedGuidedAccessSetup: _showGuidedAccessDialog,
|
||||
);
|
||||
_controller.init();
|
||||
}
|
||||
@@ -85,6 +88,37 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
|
||||
).then((_) => _isDialogOpen = false);
|
||||
}
|
||||
|
||||
/// 🛡️ iOS 전용: 근접센서 감시가 화면 잠금으로 끊기지 않도록, "가이드 접근"을
|
||||
/// 직접 켜달라고 안내하는 팝업. 학생이 켰다고 확인해야 실제 감시가 시작된다.
|
||||
void _showGuidedAccessDialog(String pocketNumber) {
|
||||
if (!mounted) return;
|
||||
_closeAnyOpenDialog();
|
||||
_isDialogOpen = true;
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text("🛡️ 감시 모드 켜기 전에"),
|
||||
content: const Text(
|
||||
"iOS는 화면을 잠그면 감시가 끊겨요. 아래 순서로 '가이드 접근'을 먼저 켜주세요.\n\n"
|
||||
"1. 사이드(또는 홈) 버튼 3번 빠르게 누르기\n"
|
||||
"2. 목록에서 '가이드 접근' 선택 → 화면 오른쪽 아래 '시작' 누르기\n\n"
|
||||
"다 켜셨으면 아래 버튼을 눌러 감시를 시작하세요.\n"
|
||||
"(감시를 끝낼 땐 먼저 사이드 버튼 3번으로 가이드 접근을 끈 다음 다시 태깅하세요.)",
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
_controller.beginIosProximityWatch(pocketNumber);
|
||||
},
|
||||
child: const Text("가이드 접근 켰어요"),
|
||||
),
|
||||
],
|
||||
),
|
||||
).then((_) => _isDialogOpen = false);
|
||||
}
|
||||
|
||||
/// 🎊 출석 성공 알림창
|
||||
void _showSuccessDialog(String pocketNumber) {
|
||||
if (!mounted) return;
|
||||
@@ -222,10 +256,12 @@ class _NfcPocketCheckInScreenState extends State<NfcPocketCheckInScreen> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
"📴 화면을 꺼도 감시는 계속됩니다.\n알림바에서 상태를 확인할 수 있어요.\n(폰을 꺼내 다시 태깅하면 반출 처리됩니다)",
|
||||
Text(
|
||||
!kIsWeb && Platform.isIOS
|
||||
? "🔒 가이드 접근을 켠 채로 화면만 잠기도록 두세요.\n(임의로 앱을 나가면 감시가 끊깁니다)\n감시를 끝내려면 가이드 접근을 먼저 끄고 다시 태깅하세요."
|
||||
: "📴 화면을 꺼도 감시는 계속됩니다.\n알림바에서 상태를 확인할 수 있어요.\n(폰을 꺼내 다시 태깅하면 반출 처리됩니다)",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.white38, fontSize: 13),
|
||||
style: const TextStyle(color: Colors.white38, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user