@yuneta/gobj-ui 7.26.20 → 7.26.21

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.
@@ -74386,6 +74386,16 @@ function mt_destroy$1(gobj) {
74386
74386
  /***************************
74387
74387
  * Local Methods
74388
74388
  ***************************/
74389
+ /************************************************************
74390
+ * THE name rule of timeranger2 and treedb
74391
+ * (tranger2_name_is_identifier(), SDK 7.26.9): a topic or a column
74392
+ * name is a directory and a key, so it cannot be "." or "..", nor hold
74393
+ * '/' or the path delimiter '`'. Said here, before the backend answers
74394
+ * a generic "cannot create topic".
74395
+ ************************************************************/
74396
+ function name_breaks_the_rule(name) {
74397
+ return name === "." || name === ".." || name.includes("/") || name.includes("`");
74398
+ }
74389
74399
  /***************************************************************
74390
74400
  * The frame: a toolbar that never changes place, a notice line
74391
74401
  * for what the whole view has to say, and one body the screens
@@ -77898,6 +77908,10 @@ function ac_save_column(gobj, event, kw, src) {
77898
77908
  yui_shell_show_error(yui_shell_of(gobj), "a column needs a name", { t: i18next.t });
77899
77909
  return -1;
77900
77910
  }
77911
+ if (kw.creating && name_breaks_the_rule(String(values.value).trim())) {
77912
+ yui_shell_show_error(yui_shell_of(gobj), "a name cannot be . or .., nor hold / or `", { t: i18next.t });
77913
+ return -1;
77914
+ }
77901
77915
  if (kw.creating && find_col(priv.model, priv.treedb_id, kw.topic, String(values.value).trim())) {
77902
77916
  yui_shell_show_error(yui_shell_of(gobj), "that column is already there", { t: i18next.t });
77903
77917
  return -1;
@@ -78152,6 +78166,10 @@ function ac_save_topic(gobj, event, kw, src) {
78152
78166
  yui_shell_show_error(yui_shell_of(gobj), "a topic needs a name", { t: i18next.t });
78153
78167
  return -1;
78154
78168
  }
78169
+ if (name_breaks_the_rule(name)) {
78170
+ yui_shell_show_error(yui_shell_of(gobj), "a name cannot be . or .., nor hold / or `", { t: i18next.t });
78171
+ return -1;
78172
+ }
78155
78173
  if (find_topic(priv.model, priv.treedb_id, name)) {
78156
78174
  yui_shell_show_error(yui_shell_of(gobj), "that topic is already there", { t: i18next.t });
78157
78175
  return -1;
@@ -74381,6 +74381,16 @@ function mt_destroy$1(gobj) {
74381
74381
  /***************************
74382
74382
  * Local Methods
74383
74383
  ***************************/
74384
+ /************************************************************
74385
+ * THE name rule of timeranger2 and treedb
74386
+ * (tranger2_name_is_identifier(), SDK 7.26.9): a topic or a column
74387
+ * name is a directory and a key, so it cannot be "." or "..", nor hold
74388
+ * '/' or the path delimiter '`'. Said here, before the backend answers
74389
+ * a generic "cannot create topic".
74390
+ ************************************************************/
74391
+ function name_breaks_the_rule(name) {
74392
+ return name === "." || name === ".." || name.includes("/") || name.includes("`");
74393
+ }
74384
74394
  /***************************************************************
74385
74395
  * The frame: a toolbar that never changes place, a notice line
74386
74396
  * for what the whole view has to say, and one body the screens
@@ -77893,6 +77903,10 @@ function ac_save_column(gobj, event, kw, src) {
77893
77903
  yui_shell_show_error(yui_shell_of(gobj), "a column needs a name", { t });
77894
77904
  return -1;
77895
77905
  }
77906
+ if (kw.creating && name_breaks_the_rule(String(values.value).trim())) {
77907
+ yui_shell_show_error(yui_shell_of(gobj), "a name cannot be . or .., nor hold / or `", { t });
77908
+ return -1;
77909
+ }
77896
77910
  if (kw.creating && find_col(priv.model, priv.treedb_id, kw.topic, String(values.value).trim())) {
77897
77911
  yui_shell_show_error(yui_shell_of(gobj), "that column is already there", { t });
77898
77912
  return -1;
@@ -78147,6 +78161,10 @@ function ac_save_topic(gobj, event, kw, src) {
78147
78161
  yui_shell_show_error(yui_shell_of(gobj), "a topic needs a name", { t });
78148
78162
  return -1;
78149
78163
  }
78164
+ if (name_breaks_the_rule(name)) {
78165
+ yui_shell_show_error(yui_shell_of(gobj), "a name cannot be . or .., nor hold / or `", { t });
78166
+ return -1;
78167
+ }
78150
78168
  if (find_topic(priv.model, priv.treedb_id, name)) {
78151
78169
  yui_shell_show_error(yui_shell_of(gobj), "that topic is already there", { t });
78152
78170
  return -1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.26.20",
3
+ "version": "7.26.21",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -361,6 +361,18 @@ function mt_destroy(gobj)
361
361
 
362
362
 
363
363
 
364
+ /************************************************************
365
+ * THE name rule of timeranger2 and treedb
366
+ * (tranger2_name_is_identifier(), SDK 7.26.9): a topic or a column
367
+ * name is a directory and a key, so it cannot be "." or "..", nor hold
368
+ * '/' or the path delimiter '`'. Said here, before the backend answers
369
+ * a generic "cannot create topic".
370
+ ************************************************************/
371
+ function name_breaks_the_rule(name)
372
+ {
373
+ return name === "." || name === ".." || name.includes("/") || name.includes("`");
374
+ }
375
+
364
376
  /***************************************************************
365
377
  * The frame: a toolbar that never changes place, a notice line
366
378
  * for what the whole view has to say, and one body the screens
@@ -4026,6 +4038,10 @@ function ac_save_column(gobj, event, kw, src)
4026
4038
  yui_shell_show_error(yui_shell_of(gobj), "a column needs a name", {t: t});
4027
4039
  return -1;
4028
4040
  }
4041
+ if(kw.creating && name_breaks_the_rule(String(values.value).trim())) {
4042
+ yui_shell_show_error(yui_shell_of(gobj), "a name cannot be . or .., nor hold / or `", {t: t});
4043
+ return -1;
4044
+ }
4029
4045
  if(kw.creating && find_col(priv.model, priv.treedb_id, kw.topic, String(values.value).trim())) {
4030
4046
  yui_shell_show_error(yui_shell_of(gobj), "that column is already there", {t: t});
4031
4047
  return -1;
@@ -4333,6 +4349,10 @@ function ac_save_topic(gobj, event, kw, src)
4333
4349
  yui_shell_show_error(yui_shell_of(gobj), "a topic needs a name", {t: t});
4334
4350
  return -1;
4335
4351
  }
4352
+ if(name_breaks_the_rule(name)) {
4353
+ yui_shell_show_error(yui_shell_of(gobj), "a name cannot be . or .., nor hold / or `", {t: t});
4354
+ return -1;
4355
+ }
4336
4356
  if(find_topic(priv.model, priv.treedb_id, name)) {
4337
4357
  yui_shell_show_error(yui_shell_of(gobj), "that topic is already there", {t: t});
4338
4358
  return -1;
@@ -0,0 +1,51 @@
1
+ /***********************************************************************
2
+ * g6_long_press_clock.test.js
3
+ *
4
+ * The long press of the G6 graphs is measured on a MONOTONIC clock
5
+ * (yunovatios REV-CLOUD.md V11.4 / V12.4). press_arbiter.test.js
6
+ * injects the time into classify_press(), so it passes whatever
7
+ * clock the handler reads; this drives the handler itself, with the
8
+ * wall clock set back an hour in the middle of the press -- an NTP
9
+ * step -- while the monotonic one moves on as a finger does.
10
+ *
11
+ * Copyright (c) 2026, ArtGins.
12
+ * All Rights Reserved.
13
+ ***********************************************************************/
14
+ import {describe, test, expect, vi, afterEach} from "vitest";
15
+ import {install_dom_double} from "../test/dom_double.js";
16
+
17
+ install_dom_double();
18
+
19
+ const {CommonEvent} = await import("@antv/g6");
20
+ const {install_long_press_contextmenu} = await import("./g6_touch_gestures.js");
21
+ const {LONG_PRESS_MS} = await import("./press_arbiter.js");
22
+
23
+ afterEach(() => {
24
+ vi.restoreAllMocks();
25
+ });
26
+
27
+ describe("the long press of a G6 graph and the clocks", () => {
28
+ test("a wall clock set back mid-press does not turn a long press into a tap", () => {
29
+ const handlers = {};
30
+ const emitted = [];
31
+ const graph = {
32
+ on(name, fn) { handlers[name] = fn; },
33
+ off() {},
34
+ emit(name) { emitted.push(name); },
35
+ };
36
+ let mono = 1000;
37
+ let wall = 1_800_000_000_000;
38
+ vi.spyOn(performance, "now").mockImplementation(() => mono);
39
+ vi.spyOn(Date, "now").mockImplementation(() => wall);
40
+
41
+ install_long_press_contextmenu(graph, {});
42
+ handlers[CommonEvent.POINTER_DOWN]({
43
+ pointerType: "touch", client: {x: 10, y: 10}, targetType: "node"
44
+ });
45
+ mono += LONG_PRESS_MS + 100; /* the finger stays long enough */
46
+ wall -= 3600 * 1000; /* and the wall clock steps back */
47
+ handlers[CommonEvent.POINTER_UP]({client: {x: 10, y: 10}});
48
+
49
+ expect(emitted).toContain(CommonEvent.CONTEXT_MENU);
50
+ });
51
+ });