forked from baron/baron-sso
Flutter Web WASM 빌드 오류 수정 및 라이브러리 마이그레이션
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import 'locale_storage_stub.dart'
|
||||
if (dart.library.html) 'locale_storage_web.dart';
|
||||
if (dart.library.js_interop) 'locale_storage_web.dart';
|
||||
|
||||
abstract class LocaleStorage {
|
||||
static String? read() => localeStorage.read();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter
|
||||
|
||||
import 'dart:html' as html;
|
||||
import 'package:web/web.dart' as web;
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class LocaleStorageImpl {
|
||||
@@ -26,11 +26,11 @@ class LocaleStorageImpl {
|
||||
String? _read(String key) {
|
||||
if (!_forceMemory && !_forceSession) {
|
||||
try {
|
||||
return html.window.localStorage[key];
|
||||
return web.window.localStorage.getItem(key);
|
||||
} catch (_) {
|
||||
// localStorage 접근이 차단된 경우 sessionStorage로 fallback.
|
||||
try {
|
||||
return html.window.sessionStorage[key];
|
||||
return web.window.sessionStorage.getItem(key);
|
||||
} catch (_) {
|
||||
// sessionStorage도 차단된 경우 메모리 fallback 사용.
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class LocaleStorageImpl {
|
||||
}
|
||||
if (!_forceMemory) {
|
||||
try {
|
||||
return html.window.sessionStorage[key];
|
||||
return web.window.sessionStorage.getItem(key);
|
||||
} catch (_) {
|
||||
// sessionStorage도 차단된 경우 메모리 fallback 사용.
|
||||
}
|
||||
@@ -49,12 +49,12 @@ class LocaleStorageImpl {
|
||||
void _write(String key, String value) {
|
||||
if (!_forceMemory && !_forceSession) {
|
||||
try {
|
||||
html.window.localStorage[key] = value;
|
||||
web.window.localStorage.setItem(key, value);
|
||||
return;
|
||||
} catch (_) {
|
||||
// localStorage 접근이 차단된 경우 sessionStorage로 fallback.
|
||||
try {
|
||||
html.window.sessionStorage[key] = value;
|
||||
web.window.sessionStorage.setItem(key, value);
|
||||
return;
|
||||
} catch (_) {
|
||||
// sessionStorage도 차단된 경우 메모리 fallback 사용.
|
||||
@@ -63,7 +63,7 @@ class LocaleStorageImpl {
|
||||
}
|
||||
if (!_forceMemory) {
|
||||
try {
|
||||
html.window.sessionStorage[key] = value;
|
||||
web.window.sessionStorage.setItem(key, value);
|
||||
return;
|
||||
} catch (_) {
|
||||
// sessionStorage도 차단된 경우 메모리 fallback 사용.
|
||||
@@ -75,12 +75,12 @@ class LocaleStorageImpl {
|
||||
void _remove(String key) {
|
||||
if (!_forceMemory && !_forceSession) {
|
||||
try {
|
||||
html.window.localStorage.remove(key);
|
||||
web.window.localStorage.removeItem(key);
|
||||
return;
|
||||
} catch (_) {
|
||||
// localStorage 접근이 차단된 경우 sessionStorage로 fallback.
|
||||
try {
|
||||
html.window.sessionStorage.remove(key);
|
||||
web.window.sessionStorage.removeItem(key);
|
||||
return;
|
||||
} catch (_) {
|
||||
// sessionStorage도 차단된 경우 메모리 fallback 사용.
|
||||
@@ -89,7 +89,7 @@ class LocaleStorageImpl {
|
||||
}
|
||||
if (!_forceMemory) {
|
||||
try {
|
||||
html.window.sessionStorage.remove(key);
|
||||
web.window.sessionStorage.removeItem(key);
|
||||
return;
|
||||
} catch (_) {
|
||||
// sessionStorage도 차단된 경우 메모리 fallback 사용.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'auth_token_store_stub.dart'
|
||||
if (dart.library.html) 'auth_token_store_web.dart';
|
||||
if (dart.library.js_interop) 'auth_token_store_web.dart';
|
||||
|
||||
class AuthTokenStore {
|
||||
static String? getToken() => authTokenStore.getToken();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'web_auth_integration_stub.dart'
|
||||
if (dart.library.html) 'web_auth_integration_web.dart';
|
||||
if (dart.library.js_interop) 'web_auth_integration_web.dart';
|
||||
|
||||
abstract class WebAuthIntegration {
|
||||
static void sendLoginSuccess(String token) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:html' as html;
|
||||
import 'dart:convert';
|
||||
import 'package:web/web.dart' as web;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'dart:js_interop';
|
||||
import 'auth_token_store.dart';
|
||||
|
||||
void implSendLoginSuccess(String token) {
|
||||
@@ -11,7 +13,7 @@ void implSendLoginSuccess(String token) {
|
||||
effectiveToken = AuthTokenStore.getToken() ?? "";
|
||||
}
|
||||
|
||||
final fullUrl = html.window.location.href;
|
||||
final fullUrl = web.window.location.href;
|
||||
final uri = Uri.base;
|
||||
|
||||
// Try to find redirect_uri from standard parsing first, then manual string search
|
||||
@@ -21,8 +23,8 @@ void implSendLoginSuccess(String token) {
|
||||
|
||||
if (redirectUri == null) {
|
||||
// Manual fallback for cases where Uri.base misses params
|
||||
final searchParams = html.window.location.search;
|
||||
if (searchParams != null && searchParams.isNotEmpty) {
|
||||
final searchParams = web.window.location.search;
|
||||
if (searchParams.isNotEmpty) {
|
||||
final sUri = Uri.parse(
|
||||
'?${searchParams.startsWith('?') ? searchParams.substring(1) : searchParams}',
|
||||
);
|
||||
@@ -56,16 +58,18 @@ void implSendLoginSuccess(String token) {
|
||||
final finalUri = target.replace(queryParameters: query);
|
||||
|
||||
debugPrint('Redirecting to: ${finalUri.toString()}');
|
||||
html.window.location.href = finalUri.toString();
|
||||
web.window.location.href = finalUri.toString();
|
||||
return;
|
||||
}
|
||||
|
||||
final message = {'type': 'LOGIN_SUCCESS', 'token': effectiveToken};
|
||||
final opener = html.window.opener;
|
||||
final opener = web.window.opener;
|
||||
|
||||
if (opener != null) {
|
||||
try {
|
||||
opener.postMessage(message, '*');
|
||||
// Use JSON string for safer cross-origin/WASM messaging if direct object fails
|
||||
final jsonMsg = jsonEncode(message);
|
||||
(opener as web.Window).postMessage(jsonMsg.toJS, '*'.toJS);
|
||||
debugPrint('Sent login success message to opener');
|
||||
} catch (e) {
|
||||
debugPrint('Failed to postMessage: $e');
|
||||
@@ -74,7 +78,7 @@ void implSendLoginSuccess(String token) {
|
||||
// Close the popup after a short delay to ensure message sending
|
||||
Timer(const Duration(milliseconds: 500), () {
|
||||
try {
|
||||
html.window.close();
|
||||
web.window.close();
|
||||
} catch (e) {
|
||||
debugPrint('Failed to close window: $e');
|
||||
}
|
||||
@@ -84,9 +88,9 @@ void implSendLoginSuccess(String token) {
|
||||
|
||||
// No opener and no redirect: fall back to local navigation
|
||||
debugPrint('No opener found. Redirecting to /.');
|
||||
html.window.location.href = '/';
|
||||
web.window.location.href = '/';
|
||||
}
|
||||
|
||||
bool implIsPopup() {
|
||||
return html.window.opener != null;
|
||||
return web.window.opener != null;
|
||||
}
|
||||
|
||||
@@ -1,49 +1,17 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use
|
||||
import 'dart:html' as html;
|
||||
import 'package:web/web.dart' as web;
|
||||
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) {
|
||||
try {
|
||||
_document.title = title.toJS;
|
||||
web.document.title = title;
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
void redirectTo(String url) {
|
||||
final currentHref = html.window.location.href;
|
||||
final currentHref = web.window.location.href;
|
||||
Uri? targetUri;
|
||||
try {
|
||||
targetUri = Uri.parse(url);
|
||||
@@ -51,67 +19,55 @@ class WebWindow {
|
||||
debugPrint("[WebWindow] redirectTo parse failed: url=$url");
|
||||
}
|
||||
|
||||
final currentPort = int.tryParse(html.window.location.port);
|
||||
final sameOrigin =
|
||||
targetUri != null &&
|
||||
targetUri.scheme == html.window.location.protocol.replaceAll(':', '') &&
|
||||
targetUri.host == html.window.location.hostname &&
|
||||
(!targetUri.hasPort || targetUri.port == currentPort);
|
||||
|
||||
debugPrint(
|
||||
"[WebWindow] redirectTo start: current=$currentHref, target=$url, target_host=${targetUri?.host ?? ''}, target_path=${targetUri?.path ?? ''}, same_origin=$sameOrigin",
|
||||
"[WebWindow] redirectTo start: current=$currentHref, target=$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.
|
||||
|
||||
// Most direct and safe way for WASM: location.href assignment via package:web
|
||||
Future.delayed(Duration.zero, () {
|
||||
try {
|
||||
print("[WebWindow] Executing JS href assignment for: $url");
|
||||
_window.location.href = url.toJS;
|
||||
web.window.location.href = url;
|
||||
} catch (e) {
|
||||
print("[WebWindow] CRITICAL JS ERROR: $e");
|
||||
}
|
||||
});
|
||||
|
||||
// 이동이 차단되거나 즉시 원위치되는 경우를 추적하기 위한 후속 로그입니다.
|
||||
// Check after delay
|
||||
Future<void>.delayed(const Duration(milliseconds: 800), () {
|
||||
final nowHref = html.window.location.href;
|
||||
final nowHref = web.window.location.href;
|
||||
if (nowHref == currentHref) {
|
||||
debugPrint(
|
||||
"[WebWindow] redirectTo no-op detected: current URL did not change after navigation attempt",
|
||||
);
|
||||
} else {
|
||||
debugPrint(
|
||||
"[WebWindow] redirectTo post-check: location changed to $nowHref",
|
||||
"[WebWindow] redirectTo no-op detected: current URL did not change",
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String currentHref() {
|
||||
return html.window.location.href;
|
||||
return web.window.location.href;
|
||||
}
|
||||
|
||||
String currentSearch() {
|
||||
return html.window.location.search ?? '';
|
||||
return web.window.location.search;
|
||||
}
|
||||
|
||||
void alert(String message) {
|
||||
try {
|
||||
_window.alert(message.toJS);
|
||||
web.window.alert(message);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
void close() {
|
||||
try {
|
||||
_window.close();
|
||||
web.window.close();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
bool hasOpener() {
|
||||
try {
|
||||
return _window.opener != null;
|
||||
return web.window.opener != null;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
@@ -119,9 +75,11 @@ class WebWindow {
|
||||
|
||||
bool redirectOpenerTo(String url) {
|
||||
try {
|
||||
final opener = _window.opener;
|
||||
final opener = web.window.opener;
|
||||
if (opener == null) return false;
|
||||
(_JSOpener(opener)).location.href = url.toJS;
|
||||
// In package:web, Window is not directly accessible from JSObject opener
|
||||
// This is a known tricky part for WASM. We'll use a safer approach.
|
||||
(opener as web.Window).location.href = url;
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user