sunrize 1.11.0 → 1.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,9 +51,10 @@ module .exports = new class BrowserFrame extends Dialog
51
51
 
52
52
  this .numerator = $("<input></input>")
53
53
  .attr ("type", "number")
54
+ .attr ("min", 1)
54
55
  .attr ("step", "1")
55
56
  .css ("width", "calc((100% - 20px) / 2)")
56
- .on ("change", () => this .onchange ());
57
+ .on ("change input", () => this .onchange ());
57
58
 
58
59
  const slash = $("<span></span>")
59
60
  .css ({ "display": "inline-block", "width": "20px", "text-align": "center" })
@@ -61,9 +62,10 @@ module .exports = new class BrowserFrame extends Dialog
61
62
 
62
63
  this .denominator = $("<input></input>")
63
64
  .attr ("type", "number")
65
+ .attr ("min", 1)
64
66
  .attr ("step", "1")
65
67
  .css ("width", "calc((100% - 20px) / 2)")
66
- .on ("change", () => this .onchange ());
68
+ .on ("change input", () => this .onchange ());
67
69
 
68
70
  $("<tr></tr>")
69
71
  .append ($("<th></th>")
@@ -91,7 +93,7 @@ module .exports = new class BrowserFrame extends Dialog
91
93
 
92
94
  configure ()
93
95
  {
94
- super .configure ({ size: [400, 127] });
96
+ super .configure ({ size: [388, 147] });
95
97
 
96
98
  this .connect (Editor .getWorldInfo (this .browser .currentScene));
97
99
  this .updateInputs ();
@@ -5,6 +5,7 @@ const
5
5
  $ = require ("jquery"),
6
6
  electron = require ("electron"),
7
7
  Interface = require ("../Application/Interface"),
8
+ util = require ("util"),
8
9
  _ = require ("../Application/GetText");
9
10
 
10
11
  module .exports = class Console extends Interface
@@ -31,34 +32,103 @@ module .exports = class Console extends Interface
31
32
  this .history = [ ];
32
33
  this .addMessageCallback = this .addMessage .bind (this);
33
34
 
34
- this .console = element;
35
- this .left = $("<div></div>") .addClass ("console-left") .appendTo (this .console);
36
- this .toolbar = $("<div></div>") .addClass (["toolbar", "vertical-toolbar", "console-toolbar"]) .appendTo (this .console);
37
- this .output = $("<div></div>") .addClass (["console-output", "output"]) .attr ("tabindex", 0) .appendTo (this .left);
38
- this .input = $("<div></div>") .addClass ("console-input") .appendTo (this .left);
35
+ this .console = element;
36
+ this .left = $("<div></div>") .addClass ("console-left") .appendTo (this .console);
37
+ this .toolbar = $("<div></div>") .addClass (["toolbar", "vertical-toolbar", "console-toolbar"]) .appendTo (this .console);
38
+
39
+ this .output = $("<div></div>")
40
+ .addClass (["console-output", "output"])
41
+ .attr ("tabindex", 0)
42
+ .on ("keydown", event => this .outputKey (event))
43
+ .appendTo (this .left);
44
+
45
+ this .input = $("<div></div>")
46
+ .addClass ("console-input")
47
+ .appendTo (this .left);
48
+
49
+ // Search Widget
50
+
51
+ this .search = $("<div></div>")
52
+ .addClass ("console-search")
53
+ .appendTo (this .left)
54
+ .hide ();
55
+
56
+ this .search .resizable({
57
+ handles: "w",
58
+ minWidth: 285,
59
+ resize: () => this .config .file .searchWidth = this .search .width (),
60
+ });
61
+
62
+ this .searchInputElements = $("<div></div>")
63
+ .addClass ("console-search-input-elements")
64
+ .appendTo (this .search);
65
+
66
+ this .searchInput = $("<input></input>")
67
+ .attr ("type", "text")
68
+ .attr ("placeholder", _("Find"))
69
+ .addClass ("console-search-input")
70
+ .on ("input", () => this .searchString ())
71
+ .on ("keydown", event => this .searchKey (event))
72
+ .appendTo (this .searchInputElements);
73
+
74
+ this .searchCaseSensitiveButton = $("<div></div>")
75
+ .addClass (["codicon", "codicon-case-sensitive", "console-search-case-sensitive"])
76
+ .on ("click", () => this .searchCaseSensitive (!this .config .file .searchCaseSensitive))
77
+ .appendTo (this .searchInputElements);
78
+
79
+ this .searchStatus = $("<div></div>")
80
+ .addClass ("console-search-status")
81
+ .text ("No results")
82
+ .appendTo (this .search);
83
+
84
+ this .searchPreviousButton = $("<div></div>")
85
+ .addClass (["search-previous", "codicon", "codicon-arrow-up", "disabled"])
86
+ .attr ("tabindex", 0)
87
+ .on ("click", () => this .searchPrevious ())
88
+ .appendTo (this .search);
89
+
90
+ this .searchNextButton = $("<div></div>")
91
+ .addClass (["search-next", "codicon", "codicon-arrow-down", "disabled"])
92
+ .attr ("tabindex", 0)
93
+ .on ("click", () => this .searchNext ())
94
+ .appendTo (this .search);
95
+
96
+ // Toolbar
97
+
98
+ this .searchButton = $("<span></span>")
99
+ .addClass ("material-icons")
100
+ .css ("transform", "scale(1.2)")
101
+ .attr ("title", _("Show search widget."))
102
+ .text ("search")
103
+ .on ("click", () => this .toggleSearch (!this .config .file .search))
104
+ .appendTo (this .toolbar);
105
+
106
+ $("<span></span>") .addClass ("separator") .appendTo (this .toolbar);
39
107
 
40
108
  this .suspendButton = $("<span></span>")
41
109
  .addClass ("material-icons")
42
110
  .attr ("title", _("Suspend console output."))
43
- .text ("cancel")
44
- .appendTo (this .toolbar)
45
- .on ("click", () => this .setSuspendConsole (!this .suspendConsole));
111
+ .text ("pause_circle")
112
+ .on ("click", () => this .setSuspendConsole (!this .suspendConsole))
113
+ .appendTo (this .toolbar);
46
114
 
47
115
  this .clearButton = $("<span></span>")
48
116
  .addClass ("material-icons")
49
117
  .attr ("title", _("Clear console."))
50
118
  .text ("delete_forever")
51
- .appendTo (this .toolbar)
52
- .on ("click", () => this .clearConsole ());
119
+ .on ("click", () => this .clearConsole ())
120
+ .appendTo (this .toolbar);
53
121
 
54
122
  $("<span></span>") .addClass ("separator") .appendTo (this .toolbar);
55
123
 
124
+ // Input
125
+
56
126
  this .textarea = $("<textarea></textarea>")
57
127
  .attr ("placeholder", _("Evaluate X3D Script code here, e.g. type `Browser.name`."))
58
128
  .attr ("tabindex", 0)
59
- .appendTo (this .input)
60
129
  .on ("keydown", event => this .onkeydown (event))
61
- .on ("keyup", event => this .onkeyup (event));
130
+ .on ("keyup", event => this .onkeyup (event))
131
+ .appendTo (this .input);
62
132
 
63
133
  if (this .console .attr ("id") !== "console")
64
134
  {
@@ -75,10 +145,21 @@ module .exports = class Console extends Interface
75
145
  {
76
146
  super .configure ();
77
147
 
78
- this .config .file .setDefaultValues ({ history: [ ] });
148
+ this .config .file .setDefaultValues ({
149
+ history: [ ],
150
+ search: false,
151
+ searchWidth: 285,
152
+ searchCaseSensitive: false,
153
+ });
79
154
 
80
155
  this .history = this .config .file .history .slice (-this .HISTORY_MAX);
81
156
  this .historyIndex = this .history .length;
157
+
158
+ this .output .scrollTop (this .output .prop ("scrollHeight"));
159
+
160
+ this .search .width (this .config .file .searchWidth);
161
+ this .toggleSearch (this .config .file .search);
162
+ this .searchCaseSensitive ();
82
163
  }
83
164
 
84
165
  async set_browser_initialized ()
@@ -97,6 +178,9 @@ module .exports = class Console extends Interface
97
178
  // Add strings to exclude here:
98
179
  excludes = [
99
180
  "The vm module of Node.js is unsupported",
181
+ "Uncaught TypeError: Cannot read properties of null (reading 'removeChild')",
182
+ "aria-hidden",
183
+ "<line>",
100
184
  // "Invalid asm.js: Invalid member of stdlib",
101
185
  ];
102
186
 
@@ -107,8 +191,14 @@ module .exports = class Console extends Interface
107
191
 
108
192
  const
109
193
  classes = [this .logLevels [level] ?? "log", this .logClasses [level]],
110
- title = sourceId ? `${sourceId}:${line}`: "",
111
- text = $("<p></p>") .addClass (classes) .attr ("title", title) .text (message);
194
+ title = sourceId ? `${sourceId}:${line}`: "";
195
+
196
+ const text = $(message .split ("\n")
197
+ .map (line => $("<p></p>")
198
+ .addClass (classes)
199
+ .attr ("title", title)
200
+ .text (line)
201
+ .get (0)));
112
202
 
113
203
  if (this .messageTime && performance .now () - this .messageTime > 1000)
114
204
  this .output .append ($("<p></p>") .addClass ("splitter"));
@@ -131,6 +221,8 @@ module .exports = class Console extends Interface
131
221
 
132
222
  this .output .append (text);
133
223
  this .output .scrollTop (this .output .prop ("scrollHeight"));
224
+
225
+ this .findElements (text, this .currentElement, false);
134
226
  }
135
227
 
136
228
  setSuspendConsole (value)
@@ -157,6 +249,7 @@ module .exports = class Console extends Interface
157
249
 
158
250
  this .output .empty ();
159
251
  this .addMessage (null, "info", __filename, 0, `Console cleared at ${new Date () .toLocaleTimeString ()}.`);
252
+ this .searchString ();
160
253
  }
161
254
 
162
255
  onkeydown (event)
@@ -243,13 +336,156 @@ module .exports = class Console extends Interface
243
336
 
244
337
  try
245
338
  {
246
- console .debug (String (this .scriptNode .evaluate (text)));
339
+ console .debug (this .scriptNode .evaluate (text));
247
340
  }
248
341
  catch (error)
249
342
  {
250
- console .error (`${error .name}: ${error .message}`);
343
+ console .error (error);
251
344
  }
252
345
 
253
346
  this .textarea .val ("");
254
347
  }
348
+
349
+ toggleSearch (visible)
350
+ {
351
+ this .config .file .search = visible;
352
+
353
+ if (visible)
354
+ {
355
+ this .searchButton .addClass ("active");
356
+ this .search .show ();
357
+ this .searchInput .trigger ("focus");
358
+
359
+ this .searchString ();
360
+ }
361
+ else
362
+ {
363
+ this .searchButton .removeClass ("active");
364
+ this .search .hide ();
365
+ this .output .find (".selected") .removeClass ("selected");
366
+ }
367
+ }
368
+
369
+ searchString ()
370
+ {
371
+ this .foundElements = [ ];
372
+
373
+ this .findElements (this .output .children (), 0, true);
374
+ }
375
+
376
+ findElements (elements, currentElement, scroll)
377
+ {
378
+ if (this .search .is (":hidden"))
379
+ return;
380
+
381
+ const
382
+ toString = this .searchCaseSensitiveButton .hasClass ("active") ? "toString" : "toLowerCase",
383
+ string = this .searchInput .val () [toString] ();
384
+
385
+ if (!string)
386
+ return;
387
+
388
+ this .foundElements = this .foundElements .concat (Array .from (elements, element => $(element))
389
+ .filter (element => element .text () [toString] () .includes (string)));
390
+
391
+ this .updateCurrentElement (currentElement, scroll);
392
+ }
393
+
394
+ searchKey (event)
395
+ {
396
+ switch (event .key)
397
+ {
398
+ case "Enter":
399
+ {
400
+ if (!this .foundElements .length)
401
+ break;
402
+
403
+ if (event .shiftKey)
404
+ this .searchPrevious ();
405
+ else
406
+ this .searchNext ();
407
+
408
+ break;
409
+ }
410
+ }
411
+ }
412
+
413
+ searchCaseSensitive (value = this .config .file .searchCaseSensitive)
414
+ {
415
+ this .config .file .searchCaseSensitive = value;
416
+
417
+ if (this .config .file .searchCaseSensitive)
418
+ this .searchCaseSensitiveButton .addClass ("active");
419
+ else
420
+ this .searchCaseSensitiveButton .removeClass ("active");
421
+
422
+ this .searchInput .trigger ("focus");
423
+
424
+ this .searchString ();
425
+ }
426
+
427
+ searchPrevious ()
428
+ {
429
+ this .updateCurrentElement (this .currentElement - 1);
430
+ }
431
+
432
+ searchNext ()
433
+ {
434
+ this .updateCurrentElement (this .currentElement + 1);
435
+ }
436
+
437
+ updateCurrentElement (value, scroll = true)
438
+ {
439
+ if (value < 0)
440
+ value = this .foundElements .length - 1;
441
+
442
+ if (value >= this .foundElements .length)
443
+ value = 0;
444
+
445
+ this .currentElement = value;
446
+
447
+ this .output .find (".selected") .removeClass ("selected");
448
+
449
+ if (this .foundElements .length)
450
+ {
451
+ const element = this .foundElements [this .currentElement];
452
+
453
+ element .addClass ("selected");
454
+
455
+ if (scroll)
456
+ {
457
+ element .get (0) .scrollIntoView ({ block: "center", inline: "start", behavior: "smooth" });
458
+ $(window) .scrollTop (0);
459
+ }
460
+
461
+ this .searchStatus .text (util .format (_("%d of %d"), this .currentElement + 1, this .foundElements .length));
462
+ this .searchPreviousButton .removeClass ("disabled");
463
+ this .searchNextButton .removeClass ("disabled");
464
+ }
465
+ else
466
+ {
467
+ this .searchStatus .text (`No results`);
468
+ this .searchPreviousButton .addClass ("disabled");
469
+ this .searchNextButton .addClass ("disabled");
470
+ }
471
+ }
472
+
473
+ outputKey (event)
474
+ {
475
+ switch (event .key)
476
+ {
477
+ case "f":
478
+ {
479
+ if (event .ctrlKey || event .metaKey)
480
+ {
481
+ this .searchInput .val (window .getSelection () .toString ());
482
+ this .searchInput .trigger ("select");
483
+
484
+ this .toggleSearch (true);
485
+ }
486
+
487
+ break;
488
+ }
489
+ }
490
+ }
255
491
  };
@@ -27,7 +27,7 @@ module .exports = new class Library extends Dialog
27
27
 
28
28
  configure ()
29
29
  {
30
- super .configure ({ size: [600, 400] });
30
+ super .configure ({ size: [600, 400], minSize: [400, 300] });
31
31
 
32
32
  // Set default config values.
33
33
 
@@ -26,7 +26,7 @@ module .exports = class Materials extends LibraryPane
26
26
 
27
27
  this .#list = $("<ul></ul>")
28
28
  .appendTo (this .output)
29
- .addClass ("library-list");
29
+ .addClass (["library-list", "materials"]);
30
30
 
31
31
  const
32
32
  canvas = $("<x3d-canvas preserveDrawingBuffer='true' xrSessionMode='NONE'></x3d-canvas>"),
@@ -51,9 +51,11 @@ module .exports = class Materials extends LibraryPane
51
51
 
52
52
  nodes .push ($("<li></li>")
53
53
  .addClass (["node", "icon"])
54
- .text (`${group .getNodeName ()} ${c + 1}`)
55
54
  .attr ("group", g)
56
55
  .attr ("child", c)
56
+ .append ($("<span></span>")
57
+ .addClass ("text")
58
+ .text (`${group .getNodeName ()} ${c + 1}`))
57
59
  .appendTo (this .#list)
58
60
  .on ("dblclick", () => this .importX3D (material .getNodeName (), material .toXMLString ())));
59
61
  }
@@ -65,7 +67,7 @@ module .exports = class Materials extends LibraryPane
65
67
  .css ({ "position": "absolute", "visibility": "hidden" })
66
68
  .prependTo ($("body"));
67
69
 
68
- await browser .resize (25, 25);
70
+ await browser .resize (256, 256);
69
71
  await browser .replaceWorld (scene);
70
72
 
71
73
  for (const element of Array .from (this .output .find (".node"), e => $(e)))