Source: webview.js

  1. import { libwebview } from 'libwebview-nodejs';
  2. /** Class representing a Webview. */
  3. export class Webview {
  4. /** Create a webview.
  5. * @constructor
  6. * @param {boolean} debug enable DevTools and other debug features.
  7. * @param target the destination window handle. set it to null if you want to create a new window
  8. */
  9. constructor(debug = false, target = null) {
  10. this.webview = libwebview.webview_create(debug ? 1 : 0, target);
  11. this.isDebug = debug;
  12. if (!this.webview) {
  13. throw new Error("Failed to create webview");
  14. }
  15. }
  16. /** Updates the title of the native window.
  17. * Must be called from the UI thread.
  18. * @param v the new title
  19. */
  20. title(v) {
  21. libwebview.webview_set_title(this.webview, v);
  22. }
  23. /** Navigates webview to the given URL
  24. * URL may be a data URI, i.e. "data:text/text,...". It is often ok not to url-encode it properly, webview will re-encode it for you. Same as [navigate]
  25. * @param url the URL or URI
  26. * */
  27. navigate(url) {
  28. libwebview.webview_navigate(this.webview, url);
  29. }
  30. /** Set webview HTML directly.
  31. * @param v the HTML content
  32. */
  33. html(v) {
  34. libwebview.webview_set_html(this.webview, v);
  35. }
  36. /**
  37. * Updates the size of the native window.
  38. * Accepts a WEBVIEW_HINT
  39. * @param hints can be one of `NONE(=0)`, `MIN(=1)`, `MAX(=2)` or `FIXED(=3)`
  40. */
  41. size(width, height, hints = SizeHint.None) {
  42. libwebview.webview_set_size(this.webview, width, height, hints);
  43. }
  44. /**
  45. * Injects JS code at the initialization of the new page.
  46. * Every time the webview will open a new page - this initialization code will be executed. It is guaranteed that code is executed before window.onload.
  47. * @param js the JS code
  48. */
  49. init(js) {
  50. libwebview.webview_init(this.webview, js);
  51. }
  52. /** Evaluates arbitrary JS code in browser.
  53. * Evaluation happens asynchronously, also the result of the expression is ignored. Use the `bind` function if you want to receive notifications about the results of the evaluation.
  54. * @param js the JS code
  55. */
  56. eval(js) {
  57. libwebview.webview_eval(this.webview, js);
  58. }
  59. /** Binds a native NodeJS callback so that it will appear under the given name as a global webview's JS function.
  60. * Callback receives an Array from browser's JS. Request string is a JSON array of all the arguments passed to the JS function.
  61. * @param name the name of the global browser's JS function
  62. * @param fn the callback function receives the request parameter in webview browser and return the response(=[isSuccess,result]), both in JSON string. If isSuccess=false, it wll reject the Promise.
  63. */
  64. bindRaw(name, fn) {
  65. let callback = (seq, req, _arg) => {
  66. const [isError, result] = fn(this, req);
  67. libwebview.webview_return(this.webview, seq, isError, result);
  68. };
  69. libwebview.webview_bind(this.webview, name, null, callback);
  70. process.on('exit', function () { callback; }); // Avoid GC
  71. }
  72. /** Binds a Node.js callback so that it will appear under the given name as a global JS function in webview .
  73. * Example: `bind("sumInNodeJS",(webview, a,b) => { return a+b; });` in webview browser, you should call `await sumInNodeJS(1,2)` and get `3`
  74. * @param name the name of the global browser's JS function
  75. * @param fn the callback function which receives the parameter and return the result to Webview. Any exception happened in Node.js here will reject the `Promise` instead of crash the program.
  76. */
  77. bind(name, fn) {
  78. this.bindRaw(name, (w, req) => {
  79. var _a;
  80. let args = JSON.parse(req);
  81. try {
  82. const resultValue = (_a = fn(w, ...args)) !== null && _a !== void 0 ? _a : null; // convert undefined to null
  83. const result = JSON.stringify(resultValue);
  84. if (result === undefined) {
  85. // need JSON.stringify to wrap string in quotes
  86. return [1, JSON.stringify(`JSON.stringify failed for return value ${resultValue}`)];
  87. }
  88. return [0, result];
  89. }
  90. catch (error) {
  91. // JSON.stringify(error) returns "[object Object]", call String to get message, need JSON.stringify to wrap string in quotes
  92. return [1, JSON.stringify(String(error))];
  93. }
  94. });
  95. }
  96. /**
  97. * Posts a function to be executed on the main thread.
  98. * It safely schedules the callback to be run on the main thread on the next main loop iteration.
  99. * @param fn the function to be executed on the main thread.
  100. */
  101. dispatch(fn) {
  102. throw "Not Implemeted";
  103. // let callback = Callback('void',['pointer','pointer'], (_,arg) => {
  104. // fn(this);
  105. // });
  106. // libwebview.webview_dispatch(this.webview ,callback);
  107. // process.on('exit', function() { callback; });
  108. }
  109. /** Removes a callback that was previously set by `webview_bind`.
  110. * @param name the name of JS function used in `webview_bind`
  111. */
  112. unbind(name) {
  113. libwebview.webview_unbind(this.webview, name);
  114. }
  115. /** Runs the main loop and destroy it when terminated.
  116. * This will block the thread. Functions like `setInterval` won't work.
  117. */
  118. show() {
  119. this.start();
  120. this.terminate();
  121. this.destroy();
  122. }
  123. /** Runs the main loop until it's terminated. **After this function exits - you must destroy the webview**.
  124. * This will block the thread.
  125. */
  126. start() {
  127. libwebview.webview_run(this.webview);
  128. }
  129. /** Destroy the webview and close the native window.
  130. * You must destroy the webview after [run]
  131. */
  132. destroy() {
  133. libwebview.webview_destroy(this.webview);
  134. this.webview = null;
  135. }
  136. /** Stops the main loop.
  137. * It is safe to call this function from other background thread.
  138. */
  139. terminate() {
  140. libwebview.webview_terminate(this.webview);
  141. }
  142. /** An **unsafe** pointer to the webview
  143. */
  144. get unsafeHandle() {
  145. return this.webview;
  146. }
  147. /** An **unsafe** pointer to the webviews platform specific native window handle.
  148. * An unsafe pointer to the webviews platform specific native window handle.
  149. * When using GTK backend the pointer is `GtkWindow` pointer, when using Cocoa
  150. * backend the pointer is `NSWindow` pointer, when using Win32 backend the
  151. * pointer is `HWND` pointer.
  152. */
  153. get unsafeWindowHandle() {
  154. return libwebview.webview_get_window(this.webview);
  155. }
  156. }
  157. /** Window size hints */
  158. const SizeHint = new Proxy(
  159. {
  160. /** Width and height are default size */
  161. None: 0,
  162. /** Width and height are minimum bounds */
  163. Min: 1,
  164. /** Width and height are maximum bounds */
  165. Max: 2,
  166. /** Window size can not be changed by a user */
  167. Fixed:3
  168. },
  169. {
  170. get(obj, prop) {
  171. if (!obj.hasOwnProperty(prop)) {
  172. throw new Error(`"${prop}" does not exist in the SizeHint enum`)
  173. }
  174. return obj[prop]
  175. },
  176. set(obj, prop, value) {
  177. throw new Error('Cannot add a new value to an enum')
  178. }
  179. }
  180. )