Files
neomer_kiosk_flutter/lib/main.dart
T
picshbj 84ba0a57c3 Initial commit: kiosk_webview Flutter app
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 12:05:04 +09:00

139 lines
3.9 KiB
Dart
Executable File

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter/services.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'dart:async';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// final String url = "https://kiosk.azmo.kr/e3b10";
final String url = "https://v2.azmo.kr/B00130";
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: KioskWebView(url: url),
);
}
}
class KioskWebView extends StatefulWidget {
final String url;
const KioskWebView({Key? key, required this.url}) : super(key: key);
@override
State<KioskWebView> createState() => _KioskWebViewState();
}
class _KioskWebViewState extends State<KioskWebView> {
WebViewController? _controller;
bool _isConnected = false;
bool _isLoading = true;
StreamSubscription<ConnectivityResult>? _connectivitySub;
Timer? _retryTimer;
final allowedDomain = "kiosk.azmo.kr";
@override
void initState() {
super.initState();
_checkConnection();
_connectivitySub = Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) {
_checkConnection();
});
}
void _checkConnection() async {
final result = await Connectivity().checkConnectivity();
final hasConnection = result != ConnectivityResult.none;
if (hasConnection != _isConnected) {
setState(() {
_isConnected = hasConnection;
_isLoading = true;
});
if (hasConnection) {
_initWebView();
}
}
}
void _initWebView() {
final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (request) {
final uri = Uri.parse(request.url);
return uri.host == allowedDomain
? NavigationDecision.navigate
: NavigationDecision.prevent;
},
onPageStarted: (_) {
setState(() => _isLoading = true);
},
onPageFinished: (_) {
setState(() => _isLoading = false);
},
onWebResourceError: (_) {
_retryTimer?.cancel();
_retryTimer = Timer(const Duration(seconds: 5), () {
_controller?.loadRequest(Uri.parse(widget.url));
});
setState(() => _isLoading = true);
},
),
)
..loadRequest(Uri.parse(widget.url));
setState(() => _controller = controller);
}
@override
void dispose() {
_connectivitySub?.cancel();
_retryTimer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: [
if (_isConnected && _controller != null)
WebViewWidget(controller: _controller!),
if (!_isConnected || _isLoading)
Container(
color: Colors.black,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(color: Colors.white),
const SizedBox(height: 20),
Text(
_isConnected ? '연결 중...' : '인터넷 연결이 필요합니다',
style:
const TextStyle(color: Colors.white, fontSize: 18),
),
],
),
),
),
],
),
),
);
}
}