// ignore_for_file: library_private_types_in_public_api, deprecated_member_use, avoid_print import 'package:didvan/constants/assets.dart'; import 'package:didvan/services/auth/token_storage.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class WebView extends StatefulWidget { final String src; const WebView({Key? key, required this.src}) : super(key: key); @override _WebViewState createState() => _WebViewState(); } class _WebViewState extends State { late WebViewController controller; bool loading = true; int progress = 0; final Set> gestureRecognizers = { Factory( () => VerticalDragGestureRecognizer()) }; void _onProgress(int progress) { print('🌐 WebView loading progress: $progress%'); // Add logging setState(() { this.progress = progress; }); } void _onPageFinished(String url) async { print('✅ WebView finished loading: $url'); // Add logging await Future.delayed(const Duration(seconds: 2)); setState(() { if (progress == 100) loading = false; }); } /// قبل از باز کردنِ URL، توکنِ Keycloak را به‌صورتِ کوکی روی دامنه /// `.didvan.com` ست می‌کنیم تا سایت‌های پنل (مثل `app.didvan.com`) کاربر /// را همان لحظه لاگین‌شده ببینند و لاگین مجدد نخواهد. Future _injectAuthCookies() async { final access = TokenStorage.accessToken; final refresh = TokenStorage.refreshToken; if (access == null || access.isEmpty) return; final cookieManager = WebViewCookieManager(); Future setCookie(String name, String value, String domain) async { try { await cookieManager.setCookie(WebViewCookie( name: name, value: value, domain: domain, path: '/', )); } catch (e) { print('⚠️ failed to set cookie $name on $domain: $e'); } } // برای پوششِ همه‌ی ساب‌دامین‌ها، روی هم `.didvan.com` و دامنه‌ی // مقصد را ست می‌کنیم. final host = Uri.tryParse(widget.src)?.host ?? ''; await setCookie('access_token', access, '.didvan.com'); if (host.isNotEmpty) { await setCookie('access_token', access, host); } if (refresh != null && refresh.isNotEmpty) { await setCookie('refresh_token', refresh, '.didvan.com'); if (host.isNotEmpty) { await setCookie('refresh_token', refresh, host); } } } @override void initState() { print('🔄 Initializing WebView with URL: ${widget.src}'); // Add logging controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setNavigationDelegate( NavigationDelegate( onProgress: _onProgress, onPageStarted: (String url) { print('▶️ WebView started loading: $url'); // Add logging }, onPageFinished: _onPageFinished, onHttpError: (HttpResponseError error) { // print('❌ WebView HTTP error: ${error.statusCode} on ${error.url}'); // Add logging }, onWebResourceError: (WebResourceError error) { // print('❌ WebView resource error: ${error.description} on ${error.failingUrl}'); // Add logging }, onNavigationRequest: (NavigationRequest request) { print('🔀 WebView navigation request to: ${request.url}'); // Add logging return NavigationDecision.navigate; }, ), ); // ابتدا کوکی‌های احراز هویت را تزریق می‌کنیم، سپس URL را لود می‌کنیم. _injectAuthCookies().whenComplete(() { controller.loadRequest(Uri.parse(widget.src)); }); super.initState(); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { if (await controller.canGoBack()) { await controller.goBack(); return false; } else { return true; } }, child: Scaffold( resizeToAvoidBottomInset: true, appBar: AppBar( title: const DidvanText( 'بازگشت', ), leading: const BackButton(), ), body: loading ? Center( child: Image.asset( Assets.loadingAnimation, width: 60, height: 60, ), ) : LayoutBuilder(builder: (context, constraints) { return SizedBox( width: MediaQuery.sizeOf(context).width, height: MediaQuery.sizeOf(context).height, child: WebViewWidget( controller: controller, gestureRecognizers: gestureRecognizers, ), ); }), )); } }