mirror of
https://github.com/haorendashu/nowser.git
synced 2025-12-17 01:44:19 +01:00
try to add linux webview support
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
|
||||||
|
|
||||||
import '../../data/browser_history.dart';
|
import '../../data/browser_history.dart';
|
||||||
|
import 'webview_controller_interface.dart';
|
||||||
|
|
||||||
class WebInfo {
|
class WebInfo {
|
||||||
String id;
|
String id;
|
||||||
@@ -9,7 +9,7 @@ class WebInfo {
|
|||||||
|
|
||||||
WebInfo(this.id, this.url);
|
WebInfo(this.id, this.url);
|
||||||
|
|
||||||
InAppWebViewController? controller;
|
WebviewControllerInterface? controller;
|
||||||
|
|
||||||
String? title;
|
String? title;
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class _WebViewComponent extends State<WebViewComponent>
|
|||||||
iframeAllow: "camera; microphone",
|
iframeAllow: "camera; microphone",
|
||||||
iframeAllowFullscreen: true,
|
iframeAllowFullscreen: true,
|
||||||
userAgent:
|
userAgent:
|
||||||
"${Base.APP_NAME} ${PlatformUtil.getPlatformName()} ${Base.VERSION_NAME}",
|
Base.USER_AGENT,
|
||||||
);
|
);
|
||||||
|
|
||||||
PullToRefreshController? pullToRefreshController;
|
PullToRefreshController? pullToRefreshController;
|
||||||
|
|||||||
61
lib/component/webview/webview_controller.dart
Normal file
61
lib/component/webview/webview_controller.dart
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
|
import 'package:nowser/component/webview/webview_controller_interface.dart';
|
||||||
|
|
||||||
|
class WebviewController extends WebviewControllerInterface {
|
||||||
|
|
||||||
|
InAppWebViewController controller;
|
||||||
|
|
||||||
|
WebviewController(this.controller);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> reload() async {
|
||||||
|
await controller.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> goBack() async {
|
||||||
|
await controller.goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> canGoBack() async {
|
||||||
|
return await controller.canGoBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> goForward() async {
|
||||||
|
await controller.goForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Uri?> getUrl() async {
|
||||||
|
var webUrl = await controller.getUrl();
|
||||||
|
try {
|
||||||
|
if (webUrl != null) {
|
||||||
|
return webUrl.uriValue;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> getFavicon() async {
|
||||||
|
var favicons = await controller.getFavicons();
|
||||||
|
if (favicons.isNotEmpty) {
|
||||||
|
return favicons.first.url.toString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> loadUrl(String url) async {
|
||||||
|
await controller.loadUrl(urlRequest: URLRequest(url: WebUri(url)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> getTitle() async {
|
||||||
|
return controller.getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
20
lib/component/webview/webview_controller_interface.dart
Normal file
20
lib/component/webview/webview_controller_interface.dart
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
abstract class WebviewControllerInterface {
|
||||||
|
|
||||||
|
Future<void> reload();
|
||||||
|
|
||||||
|
Future<void> goBack();
|
||||||
|
|
||||||
|
Future<bool> canGoBack();
|
||||||
|
|
||||||
|
Future<void> goForward();
|
||||||
|
|
||||||
|
Future<Uri?> getUrl();
|
||||||
|
|
||||||
|
Future<String?> getFavicon();
|
||||||
|
|
||||||
|
Future<void> loadUrl(String url);
|
||||||
|
|
||||||
|
Future<String?> getTitle();
|
||||||
|
|
||||||
|
}
|
||||||
420
lib/component/webview/webview_linux_component.dart
Normal file
420
lib/component/webview/webview_linux_component.dart
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nostr_sdk/event.dart';
|
||||||
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
|
import 'package:nowser/component/webview/web_info.dart';
|
||||||
|
import 'package:nowser/const/app_type.dart';
|
||||||
|
import 'package:nowser/const/auth_type.dart';
|
||||||
|
import 'package:nowser/main.dart';
|
||||||
|
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||||
|
import 'package:webview_cef/webview_cef.dart';
|
||||||
|
import 'package:webview_cef/src/webview_inject_user_script.dart';
|
||||||
|
|
||||||
|
import '../../data/app.dart';
|
||||||
|
|
||||||
|
class WebViewLinuxComponent extends StatefulWidget {
|
||||||
|
WebInfo webInfo;
|
||||||
|
|
||||||
|
Function(WebInfo, WebViewController) onWebViewCreated;
|
||||||
|
|
||||||
|
Function(WebInfo, WebViewController, String?) onTitleChanged;
|
||||||
|
|
||||||
|
Function(WebInfo, WebViewController, String?) onUrlChanged;
|
||||||
|
|
||||||
|
Function(WebInfo, WebViewController) onLoadStop;
|
||||||
|
|
||||||
|
WebViewLinuxComponent(
|
||||||
|
this.webInfo,
|
||||||
|
this.onWebViewCreated,
|
||||||
|
this.onTitleChanged,
|
||||||
|
this.onUrlChanged,
|
||||||
|
this.onLoadStop,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
return _WebViewLinuxComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WebViewLinuxComponent extends State<WebViewLinuxComponent>
|
||||||
|
with PermissionCheckMixin {
|
||||||
|
late WebViewController controller;
|
||||||
|
|
||||||
|
double progress = 0;
|
||||||
|
|
||||||
|
Set<JavascriptChannel> javascriptChannels = {};
|
||||||
|
|
||||||
|
InjectUserScripts injectScript = InjectUserScripts();
|
||||||
|
|
||||||
|
String url = "";
|
||||||
|
|
||||||
|
String title = "";
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
initInjectScript();
|
||||||
|
initJSHandle();
|
||||||
|
|
||||||
|
controller = WebviewManager().createWebView(
|
||||||
|
loading: const Text("Loading"),
|
||||||
|
injectUserScripts: injectScript);
|
||||||
|
controller.setWebviewListener(WebviewEventsListener(
|
||||||
|
onTitleChanged: (title) {
|
||||||
|
title = title;
|
||||||
|
widget.onTitleChanged(widget.webInfo, controller, title);
|
||||||
|
},
|
||||||
|
onUrlChanged: (url) {
|
||||||
|
url = url;
|
||||||
|
widget.onUrlChanged(widget.webInfo, controller, url);
|
||||||
|
},
|
||||||
|
onConsoleMessage: (int level, String message, String source, int line) {
|
||||||
|
print("$level $source $line $message");
|
||||||
|
},
|
||||||
|
// onLoadStart: (controller, url) {
|
||||||
|
// },
|
||||||
|
onLoadEnd: (controller, url) {
|
||||||
|
widget.onLoadStop(widget.webInfo, controller);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
controller.initialize(widget.webInfo.url).then((v) {
|
||||||
|
controller.setJavaScriptChannels(javascriptChannels);
|
||||||
|
setState(() {
|
||||||
|
inited = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// controller.openDevTools();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var inited = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
child: inited ? controller.webviewWidget : controller.loadingWidget,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> nip07Reject(String resultId, String contnet) async {
|
||||||
|
var script = "window.nostr.reject(\"$resultId\", \"${contnet}\");";
|
||||||
|
await controller.executeJavaScript(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initJSHandle() {
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSgetPublicKey",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSgetPublicKey $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.GET_PUBLIC_KEY,
|
||||||
|
(app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) {
|
||||||
|
print("confirm get pubkey");
|
||||||
|
var pubkey = app.pubkey;
|
||||||
|
var script = "window.nostr.callback(\"$resultId\", \"$pubkey\");";
|
||||||
|
controller.executeJavaScript(script);
|
||||||
|
});
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSsignEvent",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSsignEvent $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
var content = jsonObj["msg"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var eventObj = jsonDecode(content);
|
||||||
|
var eventKind = eventObj["kind"];
|
||||||
|
if (eventKind is int) {
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.SIGN_EVENT,
|
||||||
|
eventKind: eventKind, authDetail: content, (app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) async {
|
||||||
|
var tags = eventObj["tags"];
|
||||||
|
Event? event = Event(app.pubkey!, eventObj["kind"], tags ?? [],
|
||||||
|
eventObj["content"],
|
||||||
|
createdAt: eventObj["created_at"]);
|
||||||
|
event = await signer.signEvent(event);
|
||||||
|
if (event == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var eventResultStr = jsonEncode(event.toJson());
|
||||||
|
// TODO this method to handle " may be error
|
||||||
|
eventResultStr = eventResultStr.replaceAll("\"", "\\\"");
|
||||||
|
var script =
|
||||||
|
"window.nostr.callback(\"$resultId\", JSON.parse(\"$eventResultStr\"));";
|
||||||
|
controller.executeJavaScript(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
nip07Reject(resultId, "Sign fail");
|
||||||
|
}
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSgetRelays",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSgetRelays $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.GET_RELAYS, (app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) {
|
||||||
|
// TODO handle getRelays
|
||||||
|
// var app = appProvider.getApp(AppType.WEB, code);
|
||||||
|
// if (app != null) {
|
||||||
|
// var relayMaps = {};
|
||||||
|
// var relayAddrs = relayProvider.relayAddrs;
|
||||||
|
// for (var relayAddr in relayAddrs) {
|
||||||
|
// relayMaps[relayAddr] = {"read": true, "write": true};
|
||||||
|
// }
|
||||||
|
// var resultStr = jsonEncode(relayMaps);
|
||||||
|
// resultStr = resultStr.replaceAll("\"", "\\\"");
|
||||||
|
// var script =
|
||||||
|
// "window.nostr.callback(\"$resultId\", JSON.parse(\"$resultStr\"));";
|
||||||
|
// webViewController!.evaluateJavascript(source: script);
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSnip04encrypt",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSnip04encrypt $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
var msg = jsonObj["msg"];
|
||||||
|
if (msg != null && msg is Map) {
|
||||||
|
var pubkey = msg["pubkey"];
|
||||||
|
var plaintext = msg["plaintext"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.NIP04_ENCRYPT,
|
||||||
|
(app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) async {
|
||||||
|
var resultStr = await signer.encrypt(pubkey, plaintext);
|
||||||
|
if (StringUtil.isBlank(resultStr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var script =
|
||||||
|
"window.nostr.callback(\"$resultId\", \"$resultStr\");";
|
||||||
|
controller.executeJavaScript(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSnip04decrypt",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSnip04decrypt $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
var msg = jsonObj["msg"];
|
||||||
|
if (msg != null && msg is Map) {
|
||||||
|
var pubkey = msg["pubkey"];
|
||||||
|
var ciphertext = msg["ciphertext"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.NIP04_DECRYPT,
|
||||||
|
(app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) async {
|
||||||
|
var app = appProvider.getApp(AppType.WEB, code);
|
||||||
|
if (app != null) {
|
||||||
|
var resultStr = await signer.decrypt(pubkey, ciphertext);
|
||||||
|
if (StringUtil.isBlank(resultStr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var script =
|
||||||
|
"window.nostr.callback(\"$resultId\", \"$resultStr\");";
|
||||||
|
controller.executeJavaScript(script);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSnip44encrypt",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSnip44encrypt $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
var msg = jsonObj["msg"];
|
||||||
|
if (msg != null && msg is Map) {
|
||||||
|
var pubkey = msg["pubkey"];
|
||||||
|
var plaintext = msg["plaintext"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.NIP44_ENCRYPT,
|
||||||
|
(app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) async {
|
||||||
|
var resultStr = await signer.nip44Encrypt(pubkey, plaintext);
|
||||||
|
if (StringUtil.isBlank(resultStr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var script =
|
||||||
|
"window.nostr.callback(\"$resultId\", \"$resultStr\");";
|
||||||
|
controller.executeJavaScript(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
javascriptChannels.add(JavascriptChannel(name: "NowserJSnip44decrypt",
|
||||||
|
onMessageReceived: (javascriptMessage) async {
|
||||||
|
var jsMsg = javascriptMessage.message;
|
||||||
|
print("NowserJSnip44decrypt $jsMsg");
|
||||||
|
var jsonObj = jsonDecode(jsMsg);
|
||||||
|
var resultId = jsonObj["resultId"];
|
||||||
|
var msg = jsonObj["msg"];
|
||||||
|
if (msg != null && msg is Map) {
|
||||||
|
var pubkey = msg["pubkey"];
|
||||||
|
var ciphertext = msg["ciphertext"];
|
||||||
|
|
||||||
|
String? code = await getCode();
|
||||||
|
if (code == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.WEB, code, AuthType.NIP44_DECRYPT,
|
||||||
|
(app) {
|
||||||
|
nip07Reject(resultId, "Forbid");
|
||||||
|
}, (app, signer) async {
|
||||||
|
var resultStr = await signer.nip44Decrypt(pubkey, ciphertext);
|
||||||
|
if (StringUtil.isBlank(resultStr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var script =
|
||||||
|
"window.nostr.callback(\"$resultId\", \"$resultStr\");";
|
||||||
|
controller.executeJavaScript(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initInjectScript() {
|
||||||
|
injectScript.add(UserScript("""
|
||||||
|
window.nostr = {
|
||||||
|
_call(channel, message) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var resultId = "callbackResult_" + Math.floor(Math.random() * 100000000);
|
||||||
|
var arg = {"resultId": resultId};
|
||||||
|
if (message) {
|
||||||
|
arg["msg"] = message;
|
||||||
|
}
|
||||||
|
// var argStr = JSON.stringify(arg);
|
||||||
|
// window.flutter_inappwebview
|
||||||
|
// .callHandler(channel, argStr);
|
||||||
|
channel(arg);
|
||||||
|
window.nostr._requests[resultId] = {resolve, reject}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_requests: {},
|
||||||
|
callback(resultId, message) {
|
||||||
|
window.nostr._requests[resultId].resolve(message);
|
||||||
|
},
|
||||||
|
reject(resultId, message) {
|
||||||
|
window.nostr._requests[resultId].reject(message);
|
||||||
|
},
|
||||||
|
async getPublicKey() {
|
||||||
|
return window.nostr._call(NowserJSgetPublicKey);
|
||||||
|
},
|
||||||
|
async signEvent(event) {
|
||||||
|
return window.nostr._call(NowserJSsignEvent, JSON.stringify(event));
|
||||||
|
},
|
||||||
|
async getRelays() {
|
||||||
|
return window.nostr._call(NowserJSgetRelays);
|
||||||
|
},
|
||||||
|
nip04: {
|
||||||
|
async encrypt(pubkey, plaintext) {
|
||||||
|
return window.nostr._call(NowserJSnip04encrypt, {"pubkey": pubkey, "plaintext": plaintext});
|
||||||
|
},
|
||||||
|
async decrypt(pubkey, ciphertext) {
|
||||||
|
return window.nostr._call(NowserJSnip04decrypt, {"pubkey": pubkey, "ciphertext": ciphertext});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nip44: {
|
||||||
|
async encrypt(pubkey, plaintext) {
|
||||||
|
return window.nostr._call(NowserJSnip44encrypt, {"pubkey": pubkey, "plaintext": plaintext});
|
||||||
|
},
|
||||||
|
async decrypt(pubkey, ciphertext) {
|
||||||
|
return window.nostr._call(NowserJSnip44decrypt, {"pubkey": pubkey, "ciphertext": ciphertext});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
""", ScriptInjectTime.LOAD_START));
|
||||||
|
// injectScript.add(UserScript("console.log(window.nostr);", ScriptInjectTime.LOAD_END));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getCode() async {
|
||||||
|
if (StringUtil.isBlank(url)) {
|
||||||
|
url = widget.webInfo.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtil.isNotBlank(url)) {
|
||||||
|
var uri = Uri.parse(url);
|
||||||
|
return uri.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<App> getApp(int appType, String code) async {
|
||||||
|
String? name = title;
|
||||||
|
String? image;
|
||||||
|
// var favicons = await webViewController!.getFavicons();
|
||||||
|
// if (favicons.isNotEmpty) {
|
||||||
|
// image = favicons.first.url.toString();
|
||||||
|
// }
|
||||||
|
return App(appType: appType, code: code, name: name, image: image);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
70
lib/component/webview/webview_linux_controller.dart
Normal file
70
lib/component/webview/webview_linux_controller.dart
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:webview_cef/webview_cef.dart';
|
||||||
|
|
||||||
|
import 'webview_controller_interface.dart';
|
||||||
|
|
||||||
|
class WebviewLinuxController extends WebviewControllerInterface {
|
||||||
|
|
||||||
|
WebViewController controller;
|
||||||
|
|
||||||
|
WebviewLinuxController(this.controller);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> reload() async {
|
||||||
|
await controller.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> goBack() async {
|
||||||
|
await controller.goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> canGoBack() async {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> goForward() async {
|
||||||
|
await controller.goForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Uri?> getUrl() async {
|
||||||
|
try {
|
||||||
|
if (url != null) {
|
||||||
|
return Uri.parse(url!);
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> getFavicon() async {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> loadUrl(String url) async {
|
||||||
|
await controller.loadUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> getTitle() async {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? title;
|
||||||
|
|
||||||
|
String? url;
|
||||||
|
|
||||||
|
void setTitle(String title) {
|
||||||
|
title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUrl(String url) {
|
||||||
|
url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:nostr_sdk/utils/platform_util.dart';
|
||||||
|
|
||||||
class Base {
|
class Base {
|
||||||
static const APP_NAME = "Nowser";
|
static const APP_NAME = "Nowser";
|
||||||
|
|
||||||
@@ -8,4 +10,6 @@ class Base {
|
|||||||
static const double BASE_PADDING_HALF = 6;
|
static const double BASE_PADDING_HALF = 6;
|
||||||
|
|
||||||
static double BASE_FONT_SIZE = 15;
|
static double BASE_FONT_SIZE = 15;
|
||||||
|
|
||||||
|
static String USER_AGENT = "${Base.APP_NAME} ${PlatformUtil.getPlatformName()} ${Base.VERSION_NAME}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:bot_toast/bot_toast.dart';
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -34,6 +35,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:quick_actions/quick_actions.dart';
|
import 'package:quick_actions/quick_actions.dart';
|
||||||
import 'package:receive_intent/receive_intent.dart' as receiveIntent;
|
import 'package:receive_intent/receive_intent.dart' as receiveIntent;
|
||||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
|
import 'package:webview_cef/webview_cef.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
import 'const/base.dart';
|
import 'const/base.dart';
|
||||||
@@ -105,6 +107,10 @@ Future<void> main() async {
|
|||||||
print(e);
|
print(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Platform.isLinux) {
|
||||||
|
WebviewManager().initialize(userAgent: Base.USER_AGENT);
|
||||||
|
}
|
||||||
|
|
||||||
await doInit();
|
await doInit();
|
||||||
|
|
||||||
mediaDataCache = MediaDataCache();
|
mediaDataCache = MediaDataCache();
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:nostr_sdk/utils/string_util.dart';
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
@@ -161,21 +163,26 @@ class WebProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
String? urlStr;
|
||||||
var url = await webInfo.controller!.getUrl();
|
var url = await webInfo.controller!.getUrl();
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
|
if (Platform.isLinux) {
|
||||||
|
urlStr = webInfo.url;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
urlStr = url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlStr == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var title = await webInfo.controller!.getTitle();
|
var title = await webInfo.controller!.getTitle();
|
||||||
var favicons = await webInfo.controller!.getFavicons();
|
String? favicon = await webInfo.controller!.getFavicon();
|
||||||
String? favicon;
|
|
||||||
if (favicons.isNotEmpty) {
|
|
||||||
favicon = favicons.first.url.toString();
|
|
||||||
}
|
|
||||||
var browserHistory = BrowserHistory(
|
var browserHistory = BrowserHistory(
|
||||||
title: title,
|
title: title,
|
||||||
favicon: favicon,
|
favicon: favicon,
|
||||||
url: url.toString(),
|
url: urlStr,
|
||||||
createdAt: DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
createdAt: DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||||
);
|
);
|
||||||
if (webInfo.browserHistory != null &&
|
if (webInfo.browserHistory != null &&
|
||||||
@@ -226,7 +233,7 @@ class WebProvider extends ChangeNotifier {
|
|||||||
webInfo.url = url;
|
webInfo.url = url;
|
||||||
webInfo.title = null;
|
webInfo.title = null;
|
||||||
if (webInfo.controller != null) {
|
if (webInfo.controller != null) {
|
||||||
webInfo.controller!.loadUrl(urlRequest: URLRequest(url: WebUri(url)));
|
webInfo.controller!.loadUrl(url);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
updateWebInfo(webInfo);
|
updateWebInfo(webInfo);
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:nostr_sdk/utils/string_util.dart';
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
import 'package:nowser/component/webview/web_info.dart';
|
import 'package:nowser/component/webview/web_info.dart';
|
||||||
import 'package:nowser/component/webview/webview_component.dart';
|
import 'package:nowser/component/webview/webview_component.dart';
|
||||||
|
import 'package:nowser/component/webview/webview_controller.dart';
|
||||||
|
import 'package:nowser/component/webview/webview_linux_component.dart';
|
||||||
|
import 'package:nowser/component/webview/webview_linux_controller.dart';
|
||||||
import 'package:nowser/const/base.dart';
|
import 'package:nowser/const/base.dart';
|
||||||
import 'package:nowser/const/router_path.dart';
|
import 'package:nowser/const/router_path.dart';
|
||||||
import 'package:nowser/main.dart';
|
import 'package:nowser/main.dart';
|
||||||
@@ -53,17 +58,48 @@ class _IndexWebComponent extends State<IndexWebComponent> {
|
|||||||
return WebHomeComponent(webInfo);
|
return WebHomeComponent(webInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
var webComp = WebViewComponent(
|
Widget? webComp;
|
||||||
|
if (!Platform.isLinux) {
|
||||||
|
webComp = WebViewComponent(
|
||||||
webInfo,
|
webInfo,
|
||||||
(webInfo, controller) {
|
(webInfo, controller) {
|
||||||
webInfo.controller = controller;
|
webInfo.controller = WebviewController(controller);
|
||||||
webProvider.updateWebInfo(webInfo);
|
webProvider.updateWebInfo(webInfo);
|
||||||
},
|
},
|
||||||
onTitleChanged,
|
onTitleChanged,
|
||||||
(webInfo, controller) {
|
(webInfo, controller) {
|
||||||
webInfo.controller = controller;
|
webInfo.controller = WebviewController(controller);
|
||||||
webProvider.onLoadStop(webInfo);
|
webProvider.onLoadStop(webInfo);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
webComp = WebViewLinuxComponent(
|
||||||
|
webInfo,
|
||||||
|
(webInfo, controller) {
|
||||||
|
webInfo.controller = WebviewLinuxController(controller);
|
||||||
|
webProvider.updateWebInfo(webInfo);
|
||||||
|
},
|
||||||
|
(webInfo, controller, title) {
|
||||||
|
if (webInfo.controller is WebviewLinuxController && StringUtil.isNotBlank(title)) {
|
||||||
|
(webInfo.controller as WebviewLinuxController).setTitle(title!);
|
||||||
|
webInfo.title = title;
|
||||||
|
webProvider.updateWebInfo(webInfo);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(webInfo, controller, url) {
|
||||||
|
if (webInfo.controller is WebviewLinuxController && StringUtil.isNotBlank(url)) {
|
||||||
|
print("url change! $url");
|
||||||
|
(webInfo.controller as WebviewLinuxController).setUrl(url!);
|
||||||
|
webInfo.url = url;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(webInfo, controller) async {
|
||||||
|
webInfo.controller ??= WebviewLinuxController(controller);
|
||||||
|
var title = await webInfo.controller!.getTitle();
|
||||||
|
webInfo.title = title;
|
||||||
|
webProvider.onLoadStop(webInfo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var main = webComp;
|
var main = webComp;
|
||||||
|
|
||||||
@@ -78,7 +114,7 @@ class _IndexWebComponent extends State<IndexWebComponent> {
|
|||||||
|
|
||||||
void onTitleChanged(
|
void onTitleChanged(
|
||||||
WebInfo webInfo, InAppWebViewController controller, String? title) {
|
WebInfo webInfo, InAppWebViewController controller, String? title) {
|
||||||
webInfo.controller = controller;
|
webInfo.controller = WebviewController(controller);
|
||||||
webInfo.title = title;
|
webInfo.title = title;
|
||||||
webProvider.updateWebInfo(webInfo);
|
webProvider.updateWebInfo(webInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ class _WebTabsSelectItemComponent extends State<WebTabsSelectItemComponent> {
|
|||||||
|
|
||||||
Future<void> loadFavicon() async {
|
Future<void> loadFavicon() async {
|
||||||
if (widget.webInfo.controller != null) {
|
if (widget.webInfo.controller != null) {
|
||||||
var favicons = await widget.webInfo.controller!.getFavicons();
|
var favicon = await widget.webInfo.controller!.getFavicon();
|
||||||
if (favicons.isNotEmpty) {
|
if (StringUtil.isNotBlank(favicon)) {
|
||||||
setState(() {
|
setState(() {
|
||||||
faviconUrl = favicons.first.url.toString();
|
faviconUrl = favicon;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||||
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
||||||
|
#include <webview_cef/webview_cef_plugin.h>
|
||||||
#include <window_manager/window_manager_plugin.h>
|
#include <window_manager/window_manager_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
@@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =
|
g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
|
||||||
screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
|
screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) webview_cef_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "WebviewCefPlugin");
|
||||||
|
webview_cef_plugin_register_with_registrar(webview_cef_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||||
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
flutter_secure_storage_linux
|
flutter_secure_storage_linux
|
||||||
screen_retriever_linux
|
screen_retriever_linux
|
||||||
|
webview_cef
|
||||||
window_manager
|
window_manager
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
#include <webview_cef/webview_cef_plugin.h>
|
||||||
#include "my_application.h"
|
#include "my_application.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
initCEFProcesses(argc, argv);
|
||||||
g_autoptr(MyApplication) app = my_application_new();
|
g_autoptr(MyApplication) app = my_application_new();
|
||||||
return g_application_run(G_APPLICATION(app), argc, argv);
|
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
#include <webview_cef/webview_cef_plugin.h>
|
||||||
|
|
||||||
struct _MyApplication {
|
struct _MyApplication {
|
||||||
GtkApplication parent_instance;
|
GtkApplication parent_instance;
|
||||||
@@ -54,6 +55,8 @@ static void my_application_activate(GApplication* application) {
|
|||||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||||
|
|
||||||
FlView* view = fl_view_new(project);
|
FlView* view = fl_view_new(project);
|
||||||
|
g_signal_connect(view, "key_press_event", G_CALLBACK(processKeyEventForCEF), nullptr);
|
||||||
|
g_signal_connect(view, "key_release_event", G_CALLBACK(processKeyEventForCEF), nullptr);
|
||||||
gtk_widget_show(GTK_WIDGET(view));
|
gtk_widget_show(GTK_WIDGET(view));
|
||||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import path_provider_foundation
|
|||||||
import screen_retriever_macos
|
import screen_retriever_macos
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite_darwin
|
import sqflite_darwin
|
||||||
|
import webview_cef
|
||||||
import window_manager
|
import window_manager
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
@@ -24,5 +25,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
|
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
|
WebviewCefPlugin.register(with: registry.registrar(forPlugin: "WebviewCefPlugin"))
|
||||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
50
pubspec.lock
50
pubspec.lock
@@ -133,10 +133,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.19.0"
|
version: "1.18.0"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -431,10 +431,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_slidable
|
name: flutter_slidable
|
||||||
sha256: ab7dbb16f783307c9d7762ede2593ce32c220ba2ba0fd540a3db8e9a3acba71a
|
sha256: a857de7ea701f276fd6a6c4c67ae885b60729a3449e42766bb0e655171042801
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "3.1.2"
|
||||||
flutter_socks_proxy:
|
flutter_socks_proxy:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -529,18 +529,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
|
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.7"
|
version: "10.0.5"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
|
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.8"
|
version: "3.0.5"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -863,10 +863,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: searchfield
|
name: searchfield
|
||||||
sha256: "9d091c2731868926e2aeb9ac551d1b9116a4533a424373119509d754ae0d0f45"
|
sha256: "8d23d53967ac5b0774611150b286dacd70c9c5de74d3db433bda2104b4803755"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.4"
|
version: "1.2.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -927,7 +927,7 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.99"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1012,10 +1012,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.12.0"
|
version: "1.11.1"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1028,10 +1028,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.2.0"
|
||||||
string_validator:
|
string_validator:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1060,10 +1060,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.3"
|
version: "0.7.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1100,10 +1100,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.3.0"
|
version: "14.2.5"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1128,6 +1128,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.1"
|
||||||
|
webview_cef:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: webview_cef
|
||||||
|
sha256: "2e660bf593dc1168beb7b765dd477a703e0b29968669f017e178c2c716f6437f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.2"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1177,5 +1185,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.6.0 <4.0.0"
|
dart: ">=3.5.3 <4.0.0"
|
||||||
flutter: ">=3.27.0"
|
flutter: ">=3.24.0"
|
||||||
|
|||||||
@@ -50,12 +50,13 @@ dependencies:
|
|||||||
flutter_secure_storage: ^9.2.2
|
flutter_secure_storage: ^9.2.2
|
||||||
pretty_qr_code: ^3.3.0
|
pretty_qr_code: ^3.3.0
|
||||||
qr_code_scanner: ^1.0.1
|
qr_code_scanner: ^1.0.1
|
||||||
flutter_slidable: ^4.0.0
|
flutter_slidable: ^3.1.1
|
||||||
window_manager: ^0.4.2
|
window_manager: ^0.4.2
|
||||||
quick_actions: ^1.0.8
|
quick_actions: ^1.0.8
|
||||||
flutter_pinned_shortcut_plus: ^0.0.2
|
flutter_pinned_shortcut_plus: ^0.0.2
|
||||||
flutter_cache_manager: ^3.4.1
|
flutter_cache_manager: ^3.4.1
|
||||||
searchfield: ^1.2.4
|
searchfield: 1.2.0
|
||||||
|
webview_cef: ^0.2.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_launcher_icons: ^0.13.1
|
flutter_launcher_icons: ^0.13.1
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||||
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
|
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
|
||||||
|
#include <webview_cef/webview_cef_plugin_c_api.h>
|
||||||
#include <window_manager/window_manager_plugin.h>
|
#include <window_manager/window_manager_plugin.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
@@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||||
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
|
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
|
||||||
|
WebviewCefPluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("WebviewCefPluginCApi"));
|
||||||
WindowManagerPluginRegisterWithRegistrar(
|
WindowManagerPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
flutter_inappwebview_windows
|
flutter_inappwebview_windows
|
||||||
flutter_secure_storage_windows
|
flutter_secure_storage_windows
|
||||||
screen_retriever_windows
|
screen_retriever_windows
|
||||||
|
webview_cef
|
||||||
window_manager
|
window_manager
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user