diff --git a/userfront/lib/core/services/auth_token_store_web.dart b/userfront/lib/core/services/auth_token_store_web.dart index 8fb4f26b..9e076351 100644 --- a/userfront/lib/core/services/auth_token_store_web.dart +++ b/userfront/lib/core/services/auth_token_store_web.dart @@ -1,6 +1,16 @@ -// ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use +// ignore_for_file: avoid_web_libraries_in_flutter -import 'dart:html' as html; +import 'dart:js_interop'; + +@JS('window.localStorage') +external _JSStorage get _localStorage; + +@JS() +extension type _JSStorage(JSObject _) implements JSObject { + external String? getItem(String key); + external void setItem(String key, String value); + external void removeItem(String key); +} class AuthTokenStore { static const _tokenKey = 'baron_auth_token'; @@ -8,43 +18,77 @@ class AuthTokenStore { static const _cookieModeKey = 'baron_auth_cookie_mode'; static const _pendingProviderKey = 'baron_auth_pending_provider'; - String? getToken() => html.window.localStorage[_tokenKey]; + String? getToken() { + try { + return _localStorage.getItem(_tokenKey); + } catch (_) { + return null; + } + } - String? getProvider() => html.window.localStorage[_providerKey]; + String? getProvider() { + try { + return _localStorage.getItem(_providerKey); + } catch (_) { + return null; + } + } - bool usesCookie() => html.window.localStorage[_cookieModeKey] == '1'; + bool usesCookie() { + try { + return _localStorage.getItem(_cookieModeKey) == '1'; + } catch (_) { + return false; + } + } void setToken(String token, {String? provider}) { - html.window.localStorage[_tokenKey] = token; - html.window.localStorage.remove(_cookieModeKey); - if (provider != null) { - html.window.localStorage[_providerKey] = provider; + try { + _localStorage.setItem(_tokenKey, token); + _localStorage.removeItem(_cookieModeKey); + if (provider != null) { + _localStorage.setItem(_providerKey, provider); + } + } catch (e) { + print("[AuthTokenStore] CRITICAL - Failed to set token: $e"); } } void setCookieMode({String? provider}) { - html.window.localStorage[_cookieModeKey] = '1'; - html.window.localStorage.remove(_tokenKey); - if (provider != null) { - html.window.localStorage[_providerKey] = provider; + try { + _localStorage.setItem(_cookieModeKey, '1'); + _localStorage.removeItem(_tokenKey); + if (provider != null) { + _localStorage.setItem(_providerKey, provider); + } + } catch (_) {} + } + + String? getPendingProvider() { + try { + return _localStorage.getItem(_pendingProviderKey); + } catch (_) { + return null; } } - String? getPendingProvider() => html.window.localStorage[_pendingProviderKey]; - void setPendingProvider(String? provider) { - if (provider == null || provider.isEmpty) { - html.window.localStorage.remove(_pendingProviderKey); - return; - } - html.window.localStorage[_pendingProviderKey] = provider; + try { + if (provider == null || provider.isEmpty) { + _localStorage.removeItem(_pendingProviderKey); + return; + } + _localStorage.setItem(_pendingProviderKey, provider); + } catch (_) {} } void clear() { - html.window.localStorage.remove(_tokenKey); - html.window.localStorage.remove(_providerKey); - html.window.localStorage.remove(_cookieModeKey); - html.window.localStorage.remove(_pendingProviderKey); + try { + _localStorage.removeItem(_tokenKey); + _localStorage.removeItem(_providerKey); + _localStorage.removeItem(_cookieModeKey); + _localStorage.removeItem(_pendingProviderKey); + } catch (_) {} } } diff --git a/userfront/lib/core/services/web_window.dart b/userfront/lib/core/services/web_window.dart index 1fe2792d..1283b271 100644 --- a/userfront/lib/core/services/web_window.dart +++ b/userfront/lib/core/services/web_window.dart @@ -1 +1 @@ -export 'web_window_stub.dart' if (dart.library.html) 'web_window_web.dart'; +export 'web_window_web.dart'; diff --git a/userfront/lib/core/services/web_window_web.dart b/userfront/lib/core/services/web_window_web.dart index fc1659be..dbd56548 100644 --- a/userfront/lib/core/services/web_window_web.dart +++ b/userfront/lib/core/services/web_window_web.dart @@ -1,11 +1,45 @@ // ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use - import 'dart:html' as html; import 'package:flutter/foundation.dart'; +// ignore_for_file: avoid_web_libraries_in_flutter +import 'dart:async'; +import 'dart:js_interop'; + +@JS('window') +external _JSWindow get _window; + +@JS('document') +external _JSDocument get _document; + +@JS() +extension type _JSWindow(JSObject _) implements JSObject { + external void alert(JSString message); + external void close(); + external JSObject? get opener; + external _JSLocation get location; +} + +@JS() +extension type _JSDocument(JSObject _) implements JSObject { + external set title(JSString value); +} + +@JS() +extension type _JSOpener(JSObject _) implements JSObject { + external _JSLocation get location; +} + +@JS() +extension type _JSLocation(JSObject _) implements JSObject { + external set href(JSString value); +} + class WebWindow { void setTitle(String title) { - html.document.title = title; + try { + _document.title = title.toJS; + } catch (_) {} } void redirectTo(String url) { @@ -28,7 +62,17 @@ class WebWindow { "[WebWindow] redirectTo start: current=$currentHref, target=$url, target_host=${targetUri?.host ?? ''}, target_path=${targetUri?.path ?? ''}, same_origin=$sameOrigin", ); - html.window.location.href = url; + print("[WebWindow] FINAL REDIRECT ATTEMPT. URL: $url"); + // Explicitly use the href setter on the window.location object. + // This is the most standard-compliant way for JS Interop in WASM. + Future.delayed(Duration.zero, () { + try { + print("[WebWindow] Executing JS href assignment for: $url"); + _window.location.href = url.toJS; + } catch (e) { + print("[WebWindow] CRITICAL JS ERROR: $e"); + } + }); // 이동이 차단되거나 즉시 원위치되는 경우를 추적하기 위한 후속 로그입니다. Future.delayed(const Duration(milliseconds: 800), () { @@ -54,24 +98,30 @@ class WebWindow { } void alert(String message) { - html.window.alert(message); + try { + _window.alert(message.toJS); + } catch (_) {} } void close() { - html.window.close(); + try { + _window.close(); + } catch (_) {} } bool hasOpener() { - return html.window.opener != null; + try { + return _window.opener != null; + } catch (_) { + return false; + } } bool redirectOpenerTo(String url) { - final opener = html.window.opener; - if (opener == null) { - return false; - } try { - opener.location.href = url; + final opener = _window.opener; + if (opener == null) return false; + (_JSOpener(opener)).location.href = url.toJS; return true; } catch (_) { return false;