diff --git a/src/App.js b/src/App.js
index 3b59325ff..1ac0055f8 100644
--- a/src/App.js
+++ b/src/App.js
@@ -3,7 +3,7 @@ import Form from "./components/Form";
import FilterButton from "./components/FilterButton";
import Todo from "./components/Todo";
import { nanoid } from "nanoid";
-import HybridWebView from './hybridwebview/HybridWebView.js';
+import './hybridwebview/HybridWebView.js';
function usePrevious(value) {
const ref = useRef();
@@ -22,9 +22,15 @@ const FILTER_MAP = {
const FILTER_NAMES = Object.keys(FILTER_MAP);
function App(props) {
- const [tasks, setTasks] = useState([]);
+ const [tasks, setTasks] = useState(props.tasks);
const [filter, setFilter] = useState("All");
const [isLoading, setIsLoading] = useState(true);
+ const HybridWebView = window.HybridWebView;
+
+ function HybridWebViewSendInvokeMessageToDotNet(methodName, args) {
+ const jsonArgs = JSON.stringify(args);
+ HybridWebView.SendRawMessage("Invoke:" + methodName + ":" + jsonArgs);
+ }
function toggleTaskCompleted(id) {
const updatedTasks = tasks.map((task) => {
@@ -36,13 +42,13 @@ function App(props) {
}
return task;
});
- HybridWebView.SendInvokeMessageToDotNet("ToggleCompletedTask", [id]);
+ HybridWebViewSendInvokeMessageToDotNet("ToggleCompletedTask", [id]);
setTasks(updatedTasks);
}
function deleteTask(id) {
const remainingTasks = tasks.filter((task) => id !== task.id);
- HybridWebView.SendInvokeMessageToDotNet("DeleteTask", [id]);
+ HybridWebViewSendInvokeMessageToDotNet("DeleteTask", [id]);
setTasks(remainingTasks);
}
@@ -55,7 +61,7 @@ function App(props) {
}
return task;
});
- HybridWebView.SendInvokeMessageToDotNet("EditTask", [id, newName]);
+ HybridWebViewSendInvokeMessageToDotNet("EditTask", [id, newName]);
setTasks(editedTaskList);
}
@@ -84,7 +90,7 @@ function App(props) {
function addTask(name) {
const newTask = { id: "todo-" + nanoid(), name: name, completed: false };
- HybridWebView.SendInvokeMessageToDotNet("AddTask", [newTask]);
+ HybridWebViewSendInvokeMessageToDotNet("AddTask", [newTask]);
setTasks([...tasks, newTask]);
}
@@ -94,11 +100,11 @@ function App(props) {
const listHeadingRef = useRef(null);
const prevTaskLength = usePrevious(tasks.length);
- window.globalSetData = function(newData)
- {
+ window.globalSetData = function (newData) {
setIsLoading(false);
setTasks(newData);
console.log("New data arrived with " + newData.length + " item(s)");
+ return "null";
};
useEffect(() => {
@@ -108,35 +114,23 @@ function App(props) {
// Start initial data load
console.log("Start loading...");
- HybridWebView.SendInvokeMessageToDotNet("StartTaskLoading");
+ HybridWebViewSendInvokeMessageToDotNet("StartTaskLoading");
}, [tasks.length, prevTaskLength]);
-
- //window.setTimeout(function() { setIsLoading(false);}, 2000);
-
- if (isLoading) {
- return (
-
-
Loading items...
-
- );
- }
- else {
- return (
-
-
-
{filterList}
-
- {headingText}
-
-
-
- );
- }
+ return (
+
+
+
{filterList}
+
+ {headingText}
+
+
+
+ );
}
export default App;
diff --git a/src/hybridwebview/HybridWebView.js b/src/hybridwebview/HybridWebView.js
index 7e5ab312c..0ac7af11a 100644
--- a/src/hybridwebview/HybridWebView.js
+++ b/src/hybridwebview/HybridWebView.js
@@ -1,38 +1,80 @@
// Standard methods for HybridWebView
-export default class HybridWebView {
+window.HybridWebView = {
+ "Init": function () {
+ function DispatchHybridWebViewMessage(message) {
+ const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } });
+ window.dispatchEvent(event);
+ }
- static SendRawMessageToDotNet = function (message) {
- this.SendMessageToDotNet(0, message);
- }
+ if (window.chrome && window.chrome.webview) {
+ // Windows WebView2
+ window.chrome.webview.addEventListener('message', arg => {
+ DispatchHybridWebViewMessage(arg.data);
+ });
+ }
+ else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
+ // iOS and MacCatalyst WKWebView
+ window.external = {
+ "receiveMessage": message => {
+ DispatchHybridWebViewMessage(message);
+ }
+ };
+ }
+ else {
+ // Android WebView
+ window.addEventListener('message', arg => {
+ DispatchHybridWebViewMessage(arg.data);
+ });
+ }
+ },
+
+ "SendRawMessage": function (message) {
+ window.HybridWebView.__SendMessageInternal('RawMessage', message);
+ },
+
+ "__SendMessageInternal": function (type, message) {
- static SendInvokeMessageToDotNet = function (methodName, paramValues) {
- if (typeof paramValues !== 'undefined') {
- if (!Array.isArray(paramValues)) {
- paramValues = [paramValues];
+ const messageToSend = type + '|' + message;
+
+ if (window.chrome && window.chrome.webview) {
+ // Windows WebView2
+ window.chrome.webview.postMessage(messageToSend);
+ }
+ else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
+ // iOS and MacCatalyst WKWebView
+ window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
}
- for (var i = 0; i < paramValues.length; i++) {
- paramValues[i] = JSON.stringify(paramValues[i]);
+ else {
+ // Android WebView
+ window.hybridWebViewHost.sendMessage(messageToSend);
}
- }
+ },
- this.SendMessageToDotNet(1, JSON.stringify({ "MethodName": methodName, "ParamValues": paramValues }));
- }
+ "InvokeMethod": function (taskId, methodName, args) {
+ if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
+ // For async methods, we need to call the method and then trigger the callback when it's done
+ const asyncPromise = methodName(...args);
+ asyncPromise
+ .then(asyncResult => {
+ window.HybridWebView.__TriggerAsyncCallback(taskId, asyncResult);
+ })
+ .catch(error => console.error(error));
+ } else {
+ // For sync methods, we can call the method and trigger the callback immediately
+ const syncResult = methodName(...args);
+ window.HybridWebView.__TriggerAsyncCallback(taskId, syncResult);
+ }
+ },
- static SendMessageToDotNet = function (messageType, messageContent) {
- var message = JSON.stringify({ "MessageType": messageType, "MessageContent": messageContent });
-
- if (window.chrome && window.chrome.webview) {
- // Windows WebView2
- window.chrome.webview.postMessage(message);
- }
- else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
- // iOS and MacCatalyst WKWebView
- window.webkit.messageHandlers.webwindowinterop.postMessage(message);
- }
- else {
- // Android WebView
- window.hybridWebViewHost.sendMessage(message);
- }
+ "__TriggerAsyncCallback": function (taskId, result) {
+ // Make sure the result is a string
+ if (result && typeof (result) !== 'string') {
+ result = JSON.stringify(result);
+ }
+
+ window.HybridWebView.__SendMessageInternal('InvokeMethodCompleted', taskId + '|' + result);
}
-};
+}
+
+window.HybridWebView.Init();