efront 4.33.3 → 4.34.1

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.
@@ -11,7 +11,7 @@ function clickfile(event) {
11
11
  }
12
12
 
13
13
  function msg(elem, { m }, parentScopes) {
14
- if (m.sender === parentScopes[parentScopes.length - 1].localid) {
14
+ if (m.sender === parentScopes[parentScopes.length - 1].cid) {
15
15
  elem.setAttribute("self", "");
16
16
  }
17
17
  if (m) switch (m.type) {
@@ -33,20 +33,24 @@ function msg(elem, { m }, parentScopes) {
33
33
  elem.innerText = m.content;
34
34
  }
35
35
  }
36
- var userManager = function (users, map) {
37
- for (var cx = 0, dx = users.length; cx < dx; cx++) {
36
+ var userManager = function (users, map, page) {
37
+ for (var cx = users.length - 1; cx >= 0; cx--) {
38
38
  var u = users[cx];
39
39
  if (u.id in map) {
40
40
  var m = map[u.id];
41
41
  if (m.deleted) users.splice(cx, 1);
42
42
  else Object.assign(u, m);
43
- delete map[u.id];
44
- return;
43
+ if (!u.shake) delete map[u.id];
44
+ else users.splice(cx, 1);
45
45
  }
46
46
  }
47
47
  var ms = Object.keys(map).map(k => map[k]);
48
- for (var u of ms) u.msgread = 0;
49
- users.push.apply(users, ms);
48
+ var us = ms.filter(a => !a.shake);
49
+ for (var u of us) {
50
+ u.msgread = 0;
51
+ }
52
+ users.push.apply(users, us);
53
+ return ms.filter(a => a.shake);
50
54
  };
51
55
  var saved_event, moving = null;
52
56
  var dragpage = {
@@ -113,8 +117,8 @@ var getRtc = function (userid) {
113
117
  return rtc;
114
118
  }
115
119
  async function pullFileWithRTC(scope, file) {
116
- var userid = scope.user.id;
117
- var rtc = getRtc(userid);
120
+ var rid = scope.remoteUser.cid;
121
+ var rtc = getRtc(rid);
118
122
  var h = await window.showSaveFilePicker({ suggestedName: file.name });
119
123
  var writable = await h.createWritable();
120
124
  var channel = await rtc.createChannel();
@@ -156,7 +160,7 @@ async function pullFileWithRTC(scope, file) {
156
160
  // <!-- console.log('接收端异常',event) -->
157
161
  };
158
162
  var ondate = function (date) {
159
- scope.send("didate", date, userid);
163
+ scope.send("didate", date, rid);
160
164
  };
161
165
  var offer = await rtc.init(ondate);
162
166
  scope.send('accept', { file: file.id, channel: channel.id, offer })
@@ -217,6 +221,24 @@ async function pushFileWithRTC(scope, file, msg) {
217
221
  // <!-- console.log("发送端打开") -->
218
222
  };
219
223
  }
224
+ var shakeing = [];
225
+ var shakeUser = async function (page, shakes) {
226
+ if (shakeing.length) return shakeing.push.apply(shakeing, shakes);
227
+ shakeing.push.apply(shakeing, shakes);
228
+ while (shakeing.length) {
229
+ var user = shakeing.shift();
230
+ if (page.autoAllow);
231
+ else {
232
+ var options = [i18n`允许`, i18n`不允许` + '#danger'];
233
+ var res = await confirm(i18n`是否允许来自${user.name}(${user.id})的公网会话?`, options);
234
+ if (res === options[1]) continue;
235
+ }
236
+ delete user.shake;
237
+ page.push([user]);
238
+ await wait(function () { return page.localUser }, 10000);
239
+ page.send(page.localUser, 'user', user.cid);
240
+ }
241
+ }
220
242
 
221
243
 
222
244
  function chat(title = '会话窗口') {
@@ -224,7 +246,6 @@ function chat(title = '会话窗口') {
224
246
  page.innerHTML = template;
225
247
  drag.on(page.firstElementChild, page);
226
248
  resize.on(page);
227
- var localid = title.id || (new Date / 1000 | 0) + Math.sin(Math.random());
228
249
  var users = [];
229
250
  var addToMsgList = function (list, msgs) {
230
251
  list.push.apply(list, msgs);
@@ -234,7 +255,7 @@ function chat(title = '会话窗口') {
234
255
  if (msgs.length && (!lastmsg || lastmsg.offsetTop + lastmsg.offsetHeight === chat.scrollHeight)) {
235
256
  chat.go(list.length ? list.length - 1 : 0);
236
257
  }
237
- if (ps.user) ps.user.msgread = list.length;
258
+ if (ps.remoteUser) ps.remoteUser.msgread = list.length;
238
259
  }
239
260
  else {
240
261
  ps.totalunread += msgs.length;
@@ -243,8 +264,41 @@ function chat(title = '会话窗口') {
243
264
  var msgTemp = Object.create(null);
244
265
  page.push = function (msgs) {
245
266
  var { msglist } = ps;
246
- var userMap = null;
247
267
  var cached = [], cachedi = 0;
268
+ var userMap = null;
269
+ var cidMap = null;
270
+ var addUser = function (m) {
271
+
272
+ if (!userMap) {
273
+ cidMap = Object.create(null);
274
+ users.forEach((u, i) => {
275
+ cidMap[u.cid] = i;
276
+ })
277
+ userMap = Object.create(null);
278
+ }
279
+ if (m.cid in cidMap) {
280
+ var ci = cidMap[m.cid];
281
+ var c = users[ci];
282
+ if (c.shaking) {
283
+ delete userMap[m.id];
284
+ cidMap[m.cid] = m;
285
+ users[ci] = m;
286
+ if (ps.localUser === c) ps.localUser = m;
287
+ if (ps.remoteUser === c) ps.remoteUser = m;
288
+ }
289
+ else if (m.shaking) m = cidMap[m.cid];
290
+ }
291
+ if (!m.icon) {
292
+ if (m.shaking) {
293
+ m.name = "正在开启..";
294
+ m.id = 'loading';
295
+ m.icon = 'chrm';
296
+ }
297
+ else if (m.id) m.icon = m.id.replace(/[\.\d]+$/, '');
298
+ }
299
+ cidMap[m.cid] = m;
300
+ userMap[m.id] = m;
301
+ };
248
302
  msgs = msgs.filter(m => {
249
303
  if (!m) return false;
250
304
  if (isString(m)) {
@@ -271,11 +325,7 @@ function chat(title = '会话窗口') {
271
325
  return true;
272
326
  }
273
327
  switch (m.type) {
274
- case 'user':
275
- if (!userMap) userMap = Object.create(null);
276
- if (!m.icon) m.icon = m.id.replace(/[\.\d]+$/, '');
277
- userMap[m.id] = m;
278
- break;
328
+ case 'user': addUser(m); break;
279
329
  }
280
330
  return false;
281
331
  });
@@ -287,12 +337,20 @@ function chat(title = '会话窗口') {
287
337
  ps.pushFile(m.content);
288
338
  return false;
289
339
  }
340
+ if (m.type === "user") {
341
+ addUser(m);
342
+ return false;
343
+ }
290
344
  return true;
291
345
  });
292
346
  if (userMap) {
293
- userManager(users, userMap);
294
- if (users.indexOf(ps.user) < 0) ps.user = users[0];
347
+ var shakes = userManager(users, userMap, send1);
348
+ shakeUser(page, shakes);
349
+ if (users.indexOf(ps.remoteUser) < 0) ps.remoteUser = users[0];
295
350
  if (users.length > 0 && ps.showList === 0) ps.showList = true;
351
+ for (let u of users) {
352
+ if (u.cid === ps.cid) ps.localUser = u;
353
+ }
296
354
  }
297
355
  if (msgs.length) {
298
356
  var msgMap = Object.create(null);
@@ -328,9 +386,9 @@ function chat(title = '会话窗口') {
328
386
  }
329
387
  }
330
388
  if (users.length) for (var u of users) {
331
- if (u.id in msgMap) {
389
+ if (u.cid in msgMap) {
332
390
  if (!u.msglist) u.msglist = [];
333
- addToMsgList(u.msglist, msgMap[u.id]);
391
+ addToMsgList(u.msglist, msgMap[u.cid]);
334
392
  }
335
393
  }
336
394
  else {
@@ -341,13 +399,14 @@ function chat(title = '会话窗口') {
341
399
  page.$renders = [function () {
342
400
  ps.resize(ps.body);
343
401
  }];
344
- page.localid = localid;
345
- Object.defineProperty(page, 'userid', {
402
+
403
+ Object.defineProperty(page, 'rid', {
346
404
  get() {
347
- var user = ps.user;
348
- if (user) return user.id;
405
+ var user = ps.remoteUser;
406
+ if (user) return user.cid;
349
407
  }
350
408
  });
409
+
351
410
  page.setAttribute('ng-class', "{showList:showList}");
352
411
  var fid = 0;
353
412
  var filesMap = Object.create(null);
@@ -357,19 +416,20 @@ function chat(title = '会话窗口') {
357
416
  ps.send('rtc-video', data);
358
417
  break;
359
418
  case "hangup":
360
- ps.send('rtc-close', "", ps.remote);
419
+ ps.send('rtc-close', "", ps.remoteRtc);
361
420
  break;
362
421
  case "accept":
363
- ps.send('rtc-accept', data, ps.remote);
422
+ ps.send('rtc-accept', data, ps.remoteRtc);
364
423
  break;
365
424
  case "didate":
366
- ps.send('rtc-didate', data, ps.remote);
425
+ ps.send('rtc-didate', data, ps.remoteRtc);
367
426
  break;
368
427
  }
369
428
  }
370
429
  function send1(msg, sendto) {
371
430
  cast(page, 'send', [sendto, msg]);
372
431
  }
432
+ page.autoAllow = true;
373
433
  var ps = {
374
434
  chat: zimoli$list,
375
435
  title,
@@ -377,45 +437,92 @@ function chat(title = '会话窗口') {
377
437
  showList: 0,
378
438
  users,
379
439
  text: '',
440
+ get autoAllow() {
441
+ return page.autoAllow;
442
+ },
443
+ set autoAllow(v) {
444
+ return page.autoAllow = v;
445
+ },
380
446
  calling: null,
381
- remote: null,
382
- localid,
447
+ remoteRtc: null,
448
+ get localUser() {
449
+ return page.localUser
450
+ },
451
+ set localUser(v) {
452
+ page.localUser = v;
453
+ },
454
+ get shaking() {
455
+ var u = this.remoteUser;
456
+ if (u) return u.shaking;
457
+ },
458
+ get localid() {
459
+ return page.clientid;
460
+ },
461
+ set localid(v) {
462
+ page.clientid = v;
463
+ },
464
+ get cid() {
465
+ return this.localid;
466
+ },
467
+ get rid() {
468
+ if (this.remoteUser) return this.remoteUser.cid;
469
+ },
470
+ text: '',
383
471
  totalunread: 0,
384
- _user: null,
385
- call(remote = this.user, offer) {
472
+ get linkurl() {
473
+ var href = location.href.replace(/[?#][\s\S]*$/, '') + "?" + this.cid;
474
+ return href;
475
+ },
476
+ async qr(canvas) {
477
+ var qrcode = await init("thirdParty$qrcode");
478
+ var qr = qrcode(0, 'L');
479
+ var href = this.linkurl;
480
+ qr.addData(href);
481
+ qr.make();
482
+ var size = qr.getModuleCount();
483
+ canvas.width = canvas.height = size;
484
+ while (size < 128) size = size << 1;
485
+ css(canvas, { width: size, height: size });
486
+ qr.renderTo2dContext(canvas.getContext("2d"), 1);
487
+ },
488
+ cplink() {
489
+ copyToClipboard(this.linkurl);
490
+ },
491
+ call(remote = this.rid, offer) {
386
492
  if (this.calling) return;
387
- this.remote = isObject(remote) ? remote.id : remote;
493
+ this.remoteRtc = isObject(remote) ? remote.cid : remote;
494
+ console.log(remote)
388
495
  if (typeof remote === 'string') {
389
496
  for (var u of this.users) {
390
- if (u.id === remote) {
497
+ if (u.cid === remote) {
391
498
  remote = u;
392
499
  break;
393
500
  }
394
501
  }
395
502
  }
396
503
  if (!remote) return;
397
- var c = chatRtc(remote, this.localid, offer);
504
+ var c = chatRtc(remote, this.cid, offer);
398
505
  this.calling = c;
399
506
 
400
507
  on('remove')(c, function () {
401
508
  ps.calling = null;
402
- ps.remote = null;
509
+ ps.remoteRtc = null;
403
510
  })
404
511
  care(c, rtcMessage);
405
512
  popup(c);
406
513
  },
407
514
  fileIcon: shapes$file,
408
- set user(v) {
515
+ set remoteUser(v) {
409
516
  if (!v.msglist) v.msglist = []
410
517
  if (v.msgread !== v.msglist.length) {
411
518
  v.msgread = v.msglist.length;
412
519
  this.totalunread -= v.msglist.length - v.msgread;
413
520
  }
414
521
  this.msglist = v.msglist;
415
- this._user = v;
522
+ page.remoteUser = v;
416
523
  },
417
- get user() {
418
- return this._user;
524
+ get remoteUser() {
525
+ return page.remoteUser;
419
526
  },
420
527
  msg,
421
528
  remove() {
@@ -470,10 +577,15 @@ function chat(title = '会话窗口') {
470
577
  body.resizeCell(textarea, 'top', textarea.clientHeight - targetHeight - 2);
471
578
  },
472
579
 
473
- send(type, content, sendto = page.userid) {
474
- var msg = {
580
+ send(type, content, sendto = page.rid) {
581
+ console.log(type, content, 'send', sendto, this.text)
582
+ if (type instanceof Object) {
583
+ var msg = type;
584
+ if (!msg.type) msg.type = content;
585
+ }
586
+ else var msg = {
475
587
  type,
476
- sender: this.localid,
588
+ sender: this.localUser.cid,
477
589
  content,
478
590
  };
479
591
  var data = JSAM.stringify(msg);
@@ -481,7 +593,7 @@ function chat(title = '会话窗口') {
481
593
  if (data.length > 16000) {
482
594
  return alert("信息太长,无法发送!");
483
595
  }
484
- if (this.user && this.user.id !== this.localid) a: {
596
+ if (this.remoteUser && this.remoteUser.cid !== this.cid) a: {
485
597
  switch (type) {
486
598
  case "accept":
487
599
  case "didate":
@@ -505,7 +617,7 @@ function chat(title = '会话窗口') {
505
617
  else {
506
618
  send1(data, sendto);
507
619
  }
508
- this.body.lastElementChild.focus();
620
+ if (this.body) this.body.lastElementChild.focus();
509
621
  this.text = '';
510
622
  }
511
623
  };
@@ -520,5 +632,6 @@ function chat(title = '会话窗口') {
520
632
  }
521
633
  });
522
634
  moveupon(page, dragpage);
635
+ page.send = ps.send.bind(ps);
523
636
  return page;
524
637
  }
@@ -25,6 +25,36 @@
25
25
  max-height: 100%;
26
26
  }
27
27
 
28
+ .fade {
29
+ filter: grayscale(1);
30
+ opacity: .5;
31
+ }
32
+
33
+ .qrcode {
34
+ position: relative;
35
+ height: 0;
36
+ overflow: visible;
37
+ z-index: 2;
38
+ padding: 0;
39
+ width: 100%;
40
+ text-align: center;
41
+ margin-bottom: -52px;
42
+
43
+ >p {
44
+ background: #fff;
45
+ }
46
+
47
+ >canvas {
48
+ background: #fff;
49
+ border: 10px solid #fff;
50
+ image-rendering: pixelated;
51
+ display: block;
52
+ margin: 52px auto 10px auto;
53
+ width: 256px;
54
+ height: 256px;
55
+ }
56
+ }
57
+
28
58
  >list {
29
59
  width: @leftwidth;
30
60
  position: absolute;
@@ -0,0 +1,46 @@
1
+ var ClipboardItem = window.ClipboardItem;
2
+
3
+ async function copyToClipboard(text, mime = 'text/plain') {
4
+ mime = mime.toLowerCase();
5
+ if (ClipboardItem && ClipboardItem.supports(mime)) {
6
+ const clipboardItem = new ClipboardItem({ [mime]: text });
7
+ try {
8
+ await navigator.clipboard.write([clipboardItem]);
9
+ alert("已复制");
10
+ return;
11
+ } catch (e) { console.log(e) };
12
+ }
13
+ var span = document.createElement('span');
14
+ span.setAttribute('user-select', 'all');
15
+ setOpacity(span, 0);
16
+ css(span, "position:absolute;top:-1000000px;left:-1000000px;")
17
+ switch (mime) {
18
+ case "text/plain": span.innerText = text; break;
19
+ case "text/html": span.innerHTML = text; removeUnsafeTags(span); break;
20
+ default:
21
+ if (/^image\//i.test(mime)) {
22
+ span.innerHTML = `<img src=${strings.encode(text)}/>`;
23
+ }
24
+ else {
25
+ return alert(i18n`复制失败!`, 'error');
26
+ }
27
+
28
+ }
29
+ document.body.appendChild(span);
30
+ var selection = document.getSelection();
31
+ var ranges = [];
32
+ for (var cx = 0, dx = selection.rangeCount; cx < dx; cx++) {
33
+ var range = selection.getRangeAt(cx);
34
+ ranges.push(range);
35
+ }
36
+ selection.removeAllRanges();
37
+ document.getSelection().setBaseAndExtent(span, 0, span, 1);
38
+ var res = document.execCommand('copy');
39
+ selection.removeAllRanges();
40
+ for (var range of ranges) {
41
+ selection.addRange(range);
42
+ }
43
+ remove(span);
44
+ if (res) alert("已复制");
45
+
46
+ }
@@ -0,0 +1,21 @@
1
+ function removeJavascript(a, attr) {
2
+ if (!a.hasAttribute(attr)) return;
3
+ var value = a.getAttribute(attr);
4
+ if (/^javascript\:/i.test(value)) a.removeAttribute(attr);
5
+ }
6
+ function removeTags(a, tagName) {
7
+ var scripts = a.getElementsByTagName(tagName);
8
+ remove(scripts);
9
+ }
10
+ function removeUnsafeTags(a) {
11
+ removeTags(a, 'script');
12
+ removeTags(a, 'iframe');
13
+ removeTags(a, 'style');
14
+ removeTags(a, 'meta');
15
+ if (a.hasAttribute('onload')) a.removeAttribute('onload');
16
+ if (a.hasAttribute('onerror')) a.removeAttribute('onerror');
17
+ removeJavascript(a, 'src');
18
+ removeJavascript(a, 'href');
19
+ for (var c of a.children) removeUnsafeTags(c);
20
+ return a;
21
+ }
@@ -675,8 +675,17 @@ var gtValue = function () { return this.value };
675
675
  var stValue = function (v) { this.value = v };
676
676
  var gtChecked = function () { return this.checked };
677
677
  var stChecked = function (v) { this.checked = v };
678
- var gtHtml = function () { return this.innerHTML };
679
- var stHtml = function (v) { this.innerHTML = v };
678
+ var gtHtml = function () {
679
+ removeUnsafeTags(this);
680
+ return this.innerHTML;
681
+ };
682
+ var stHtml = function (v) {
683
+ var span = document.createElement('span');
684
+ span.innerHTML = v;
685
+ removeUnsafeTags(span);
686
+ this.innerHTML = '';
687
+ appendChild(this, span.childNodes);
688
+ };
680
689
  class Model {
681
690
  constructor(getScope, setScope, target) {
682
691
  this.gs = getScope;
@@ -713,6 +722,7 @@ class Model {
713
722
  return;
714
723
  }
715
724
  this.ss.call(this.target, value);
725
+ console.log(value, this.value, this.gs.call(this.target))
716
726
  this.value = value;
717
727
  this.bd.value = this.gs.call(this.target, value);
718
728
  if (isFunction(this.emit?.call)) {
@@ -734,7 +744,7 @@ class Model {
734
744
  }
735
745
  }
736
746
  var createSetter = function (elem, search) {
737
- return $$eval.bind(elem, search + "=arguments[2]", scopeList, elem);
747
+ return $$eval.bind(elem, search + "=arguments[1]", scopeList, elem);
738
748
  };
739
749
  var directives = {
740
750
  text: createBinder2(function (value) {
@@ -812,6 +822,14 @@ var binders = {
812
822
  ""(attr, search) {
813
823
  var getter = createGetter(this, search);
814
824
  var oldValue;
825
+ if (/contenteditable/i.test(attr)) {
826
+ var v = this.value;
827
+ Object.defineProperty(this, 'value', {
828
+ get: gtHtml,
829
+ set: stHtml
830
+ });
831
+ if (isHandled(v)) this.value = v;
832
+ }
815
833
  var hook = function () {
816
834
  var value = getter(this);
817
835
  if (deepEqual(value, oldValue)) return;
@@ -1138,21 +1156,49 @@ var getDeepContext = function (deep) {
1138
1156
  var length = deep;
1139
1157
  var deepL = deepcontexts.length;
1140
1158
  while (deep-- > deepL) {
1141
- deepcontexts[deep] = `with($parentScopes[${deep}])`;
1159
+ deepcontexts[deep] = `with($$[${deep}])`;
1142
1160
  }
1143
1161
  return deepcontexts.slice(0, length).join('');
1144
1162
  }
1145
- var createEval = function (deep) {
1146
- return new Function("$parentScopes", "code", "event", `${getDeepContext(deep)}return eval(code)`);
1163
+ var isRowCode = function (code) {
1164
+ var reg = /["';]/g;
1165
+ reg.lastIndex = 0;
1166
+ var reg1 = /\\[\s\S]|'/g;
1167
+ var reg2 = /\\[\s\S]|"/g;
1168
+ do {
1169
+ var r = reg.exec(code)
1170
+ if (!r) return true;
1171
+ var regtmp = null;
1172
+ if (r) switch (r[0]) {
1173
+ case "'": regtmp = reg1; break;
1174
+ case `"`: regtmp = reg2; break;
1175
+ case ";": return false;
1176
+ }
1177
+ if (regtmp) {
1178
+ regtmp.lastIndex = reg.lastIndex;
1179
+ do {
1180
+ var r = regtmp.exec(code);
1181
+ if (r) {
1182
+ r = r[0];
1183
+ if (r.length === 1) break;
1184
+ }
1185
+ } while (r);
1186
+ reg.lastIndex = regtmp.lastIndex;
1187
+ }
1188
+ } while (r);
1189
+ return true;
1190
+ }
1191
+ var createEval = function (deep, code) {
1192
+ if (isRowCode(code)) code = `return ${code}`;
1193
+ else code = `{${code}}`;
1194
+ return new Function("$$", 'event', `${getDeepContext(deep)}${code}`);
1147
1195
  };
1148
1196
 
1149
- var evalcontexts = [createEval(0)];
1150
1197
 
1151
1198
  function $$eval(search, scopes, target = this, event) {
1152
1199
  var length = scopes.length;
1153
- var eval2 = evalcontexts[length];
1154
- if (!eval2) eval2 = evalcontexts[length] = createEval(length);
1155
- var res = eval2.call(target, scopes, search, event);
1200
+ var eval2 = createEval(length, search);
1201
+ var res = eval2.call(target, scopes, event);
1156
1202
  return res;
1157
1203
  }
1158
1204
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "efront",
3
- "version": "4.33.3",
3
+ "version": "4.34.1",
4
4
  "description": "一个开发环境,提供一种自由的前端开发模式,也可作为辅助工具使用。",
5
5
  "main": "public/efront.js",
6
6
  "directories": {