efront 4.26.2 → 4.27.0

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.
@@ -40,6 +40,24 @@
40
40
  - zh-CN: 英语
41
41
  en: English
42
42
 
43
+ - zh-CN: 无法打开媒体设备
44
+ en: Unable to open media device
45
+
46
+ - zh-CN: 通话中
47
+ en: During the call
48
+
49
+ - zh-CN: 无应答
50
+ en: no response
51
+
52
+ - zh-CN: 正在呼叫
53
+ en: Calling in progress
54
+
55
+ - zh-CN: $1天
56
+ en: $1 day
57
+
58
+ - zh-CN: 正在通话中..
59
+ en: In a call
60
+
43
61
  - zh-CN: 大写锁定已打开
44
62
  en: Capitalization lock turned on
45
63
 
@@ -839,6 +839,17 @@ var data = {
839
839
  return datas.concat.apply([], datas);
840
840
  }));
841
841
  },
842
+ wait(ref, params, parse) {
843
+ var response = this.from(ref, params, parse);
844
+ var loading = response.loading;
845
+ if (!("timeout" in loading)) {
846
+ loading.then(function () {
847
+ response.loading.timeout = 0;
848
+ });
849
+ }
850
+ loading.timeout = 0;
851
+ return response;
852
+ },
842
853
  from(ref, params, parse) {
843
854
  if (params instanceof Function) {
844
855
  parse = params;
@@ -933,12 +944,14 @@ var data = {
933
944
  asyncInstance(sid, params, parse) {
934
945
  // 不同参数的请求互不影响
935
946
  if (typeof sid !== "string") throw new Error(i18n`serviceId 只能是字符串`);
936
- var p = privates.getApi(sid).then((api) => {
947
+ var p0 = privates.getApi(sid);
948
+ var p = p0.then((api) => {
937
949
  params = privates.pack(sid, params);
938
950
  var p = privates.fromApi(api, params);
939
951
  p.loading = response.loading = p.loading;
940
952
  return p;
941
953
  }, oncatch);
954
+ p.loading = p0;
942
955
  if (isEmpty(params)) p.id = sid;
943
956
  var response = this.createResponse(p, parse);
944
957
  return response;
@@ -1,8 +1,9 @@
1
1
  var KMGT = 'KMGT';
2
2
  "use ./KMGT.txt"
3
- module.exports = function (f) {
3
+ module.exports = function (f, fix) {
4
4
  var log = Math.log(f) / Math.LN2 / 10 | 0;
5
5
  f /= Math.pow(2, log * 10);
6
- f = +f.toFixed(2);
6
+ f = f.toFixed(fix >= 0 ? fix : 2);
7
+ if (!fix) f = +f;
7
8
  return f + KMGT.charAt(log - 1) + "B";
8
9
  };
@@ -771,7 +771,10 @@ var removeExport = function (c, i, code) {
771
771
  }
772
772
  return;
773
773
  }
774
- var [dec, map, o] = getDeclared(n.next, 'export');
774
+ if (n.type === STRAP && n.text === 'async') n = n.next;
775
+ var s = n.next;
776
+ if (s.type === STAMP && s.text === "*") s = s.next;
777
+ var [dec, map, o] = getDeclared(s, 'export');
775
778
  if (/^(class|function)$/.test(n.text)) {
776
779
  var exports = used.exports;
777
780
  if (!exports) {
@@ -21,6 +21,10 @@ testFix(`import "windows.inc"`, 'require("windows.inc")');
21
21
  testFix(`import "windows.inc";import "abc.inc";`, 'require("windows.inc"); require("abc.inc");');
22
22
  testFix(`import "windows.inc";\r\nimport "abc.inc";`, 'require("windows.inc");\r\nrequire("abc.inc");');
23
23
  testFix(`console.log(import.meta)`, `console.log(import_meta)`);
24
+ testFix(`export async function a(){}`, 'exports.a = async function a() {}');
25
+ testFix(`export async function *a(){}`, 'exports.a = async function *a() {}');
26
+ testFix(`export function *a(){}`, 'exports.a = function *a() {}');
27
+ testFix(`export var a = async()=>{}`, 'exports.a = async () => {}');
24
28
  var testDetour = function (a, e) {
25
29
  var c = scanner2(a);
26
30
  c.break();
@@ -0,0 +1,136 @@
1
+ var {
2
+ RTCPeerConnection,
3
+ RTCDataChannel,
4
+ RTCSessionDescription,
5
+ RTCIceCandidate,
6
+ } = window;
7
+ var port = location.port;
8
+ if (!port) port = /^https\:/.test(location.href) ? 443 : 80;
9
+ var configuration = {
10
+ iceServers: [
11
+ // { urls: "stun:stun.stunprotocol.org:3478" },
12
+ { urls: "stun:" + location.host + ":" + port }
13
+ ],
14
+ };
15
+
16
+ var enabled = !!RTCPeerConnection;
17
+ class ChatRTC {
18
+ static enabled = enabled;
19
+ enabled = enabled;
20
+ local = null;
21
+ remote = null;
22
+ channel = null;
23
+ localStream = null;
24
+ /**
25
+ * @type {RTCPeerConnection}
26
+ */
27
+ peerConnection = null;
28
+ candidates = [];
29
+ constructor() {
30
+ this.peerConnection = new RTCPeerConnection(configuration);
31
+ }
32
+ async setAnswer(answer) {
33
+ await this.peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
34
+ flushDidate(this);
35
+ }
36
+ async addDidate(candidate) {
37
+ candidate = candidate ? new RTCIceCandidate(candidate) : { candidate: '' };
38
+ if (!this.candidates) {
39
+ await this.peerConnection.addIceCandidate(candidate);
40
+ }
41
+ else {
42
+ this.candidates.push(candidate);
43
+ }
44
+ }
45
+ // 开始获取本地媒体
46
+ async initMedia(audioOnly) {
47
+ var localStream = this.localStream;
48
+ if (!localStream) localStream = this.localStream = await navigator.mediaDevices.getUserMedia({ video: !audioOnly, audio: true });
49
+ var local = this.local;
50
+ local.srcObject = localStream;
51
+ local.play();
52
+ addTracks(this.peerConnection, localStream);
53
+ }
54
+ async createChannel(id, options) {
55
+ return this.peerConnection.createDataChannel(id, options);
56
+ }
57
+ waitChannel() {
58
+ return new Promise((ok) => {
59
+ if (this.channel) return ok(this.channel);
60
+ this.peerConnection.ondatachannel = (event) => {
61
+ this.channel = event.channel;
62
+ ok(this.channel);
63
+ };
64
+ });
65
+ }
66
+ async init(ondate, offer) {
67
+ var peerConnection = this.peerConnection;
68
+ peerConnection.emitDidate = ondate;
69
+ peerConnection.onicecandidate = oncandidate;
70
+ peerConnection.ondatachannel = event => this.channel = event.channel;
71
+ if (offer) return takeOffer(this, offer);
72
+ offer = await peerConnection.createOffer();
73
+ await peerConnection.setLocalDescription(offer);
74
+ return offer;
75
+ }
76
+ async call(ondate, offer) {
77
+ await this.initMedia();
78
+ var peerConnection = this.peerConnection;
79
+ // 处理 ICE 候选
80
+ peerConnection.remote = this.remote;
81
+ peerConnection.ontrack = ontrack;
82
+ return this.init(ondate, offer);
83
+ };
84
+ async hangup() {
85
+ var { peerConnection, localStream, local, remote } = this;
86
+ if (peerConnection) peerConnection.close();
87
+ stopTracks(localStream);
88
+ this.tracks = null;
89
+ this.candidates = null;
90
+ if (local) local.srcObject = null;
91
+ if (remote) remote.srcObject = null;
92
+ };
93
+ }
94
+ async function takeOffer(rtc, offer) {
95
+ var pc = rtc.peerConnection;
96
+ await pc.setRemoteDescription(new RTCSessionDescription(offer));
97
+ var answer = await pc.createAnswer();
98
+ await pc.setLocalDescription(answer);
99
+ flushDidate(rtc);
100
+ return answer;
101
+ }
102
+
103
+ /**
104
+ * @param {ChatRtc} rtc
105
+ */
106
+ function flushDidate(rtc) {
107
+ if (rtc.candidates) {
108
+ var cds = rtc.candidates;
109
+ rtc.candidates = null;
110
+ var peerConnection = rtc.peerConnection;
111
+ for (var d of cds) peerConnection.addIceCandidate(d);
112
+ }
113
+ }
114
+ var ontrack = function (event) {
115
+ var remote = this.remote;
116
+ remote.srcObject = event.streams[0];
117
+ };
118
+ var addTracks = function (peerConnection, localStream) {
119
+ var tracks = localStream?.getTracks();
120
+ // 将本地流添加到 PeerConnection
121
+ if (tracks) for (var track of tracks) {
122
+ peerConnection.addTrack(track, localStream);
123
+ }
124
+ };
125
+ var stopTracks = function (localStream) {
126
+ var tracks = localStream?.getTracks();
127
+ if (tracks) for (var track of tracks) {
128
+ track.stop();
129
+ }
130
+ }
131
+ var oncandidate = function (event) {
132
+ var candidate = event.candidate;
133
+ if (!candidate) return this.emitDidate(null);
134
+ var { sdpMid, candidate, sdpMLineIndex, usernameFragment } = candidate;
135
+ this.emitDidate({ sdpMid, candidate, sdpMLineIndex, usernameFragment });
136
+ }
@@ -0,0 +1,275 @@
1
+ <style>
2
+ & {
3
+ width: 100%;
4
+ height: 100%;
5
+ position: fixed;
6
+ left: 0;
7
+ top: 0;
8
+ right: 0;
9
+ bottom: 0;
10
+ background: #111;
11
+ }
12
+
13
+ dv {
14
+ border: 1px solid;
15
+ width: 240px;
16
+ height: 180px;
17
+ right: 10px;
18
+ bottom: 10px;
19
+ display: block;
20
+ position: absolute;
21
+ color: #fff9;
22
+ background: #222;
23
+ z-index: 1;
24
+
25
+ >span {
26
+ position: relative;
27
+ }
28
+
29
+ &[full] {
30
+ z-index: 0 !important;
31
+ width: auto !important;
32
+ height: auto !important;
33
+ left: 0 !important;
34
+ right: 0 !important;
35
+ bottom: 0 !important;
36
+ top: 0 !important;
37
+ margin: 0 !important;
38
+ padding: 0 !important;
39
+ border: none;
40
+ }
41
+
42
+ &:after {
43
+ display: block;
44
+ content: "";
45
+ left: 0;
46
+ bottom: 0;
47
+ right: 0;
48
+ top: 0;
49
+ position: absolute;
50
+ }
51
+
52
+ >video {
53
+ display: block;
54
+ position: absolute;
55
+ left: 0;
56
+ right: 0;
57
+ bottom: 0;
58
+ top: 0;
59
+ width: 100%;
60
+ height: 100%;
61
+ }
62
+ }
63
+
64
+ btn.button {
65
+ display: block;
66
+ position: absolute;
67
+ width: 60px;
68
+ line-height: 60px;
69
+ height: 60px;
70
+ border-radius: 30px;
71
+ margin: -23px;
72
+ z-index: 2;
73
+ }
74
+
75
+ [accept] {
76
+ left: 50%;
77
+ top: 50%;
78
+ background: #fff2;
79
+ }
80
+
81
+ [hangup] {
82
+ left: 50%;
83
+ bottom: 30px;
84
+ background: #913;
85
+ }
86
+
87
+ [info],
88
+ [error] {
89
+ display: block;
90
+ position: absolute;
91
+ top: 50%;
92
+ z-index: 1;
93
+ left: 0;
94
+ right: 0;
95
+ text-align: center;
96
+ line-height: 40px;
97
+ margin-top: -20px;
98
+ color: #fff;
99
+ }
100
+
101
+ [error] {
102
+ display: none;
103
+ }
104
+
105
+ &[error] {
106
+
107
+ [info],
108
+ [accept] {
109
+ display: none;
110
+ }
111
+
112
+ [error] {
113
+ display: block;
114
+ }
115
+ }
116
+ </style>
117
+ <div>
118
+ <dv full>
119
+ <video playsinline autoplay webkit-playsinline ondblclick="preventDefault"></video>
120
+ <span -bind="remoteUser.name"></span>
121
+ </dv>
122
+ <dv style="opacity: 0">
123
+ <video muted playsinline webkit-playsinline ondblclick="preventDefault"></video>
124
+ <span></span>
125
+ </dv>
126
+ <btn danger hangup @click="hangup">挂断</btn>
127
+ <btn accept -show="isRemote&&!started" @click="accept()">接听</btn>
128
+ <span error>${i18n`无法打开媒体设备`}</span>
129
+ <span info -show="started">
130
+ <span -bind="status()"></span>
131
+ &nbsp;<time></time>
132
+ </span>
133
+ </div>
134
+ <script>
135
+ var chatrtc = new ChatRTC;
136
+ // fullscreen.open();
137
+ var status = function () {
138
+ return acceptTime ? i18n`通话中` : rejectTime ? i18n`无应答` : i18n`正在呼叫`
139
+ };
140
+ var btn = button;
141
+ var dvs;
142
+ var callingStart = new Date, acceptTime = 0;
143
+ var started = false;
144
+ var interval = 0;
145
+ var timeNode = document.createTextNode("");
146
+ var rejectTime = 0;
147
+ care(this, function ([type, sender, data]) {
148
+ if (sender !== remoteUser.id) return;
149
+ switch (type) {
150
+ case "rtc-close":
151
+ if (acceptTime) return remove(this);
152
+ rejectTime = new Date;
153
+ if (remoteOffer) return remove(this);
154
+ break;
155
+ case "rtc-accept":
156
+ acceptTime = new Date;
157
+ chatrtc.setAnswer(data);
158
+ break;
159
+ case "rtc-didate":
160
+ chatrtc.addDidate(data);
161
+ break;
162
+ }
163
+ });
164
+ interval = setInterval(function () {
165
+ var toNum2 = a => a < 10 ? "0" + a : a;
166
+ var now = new Date;
167
+ var time = callingStart;
168
+ if (acceptTime) time = acceptTime;
169
+ var time = (new Date - time) / 1000 | 0;
170
+ if (time > 60 && !acceptTime && !rejectTime) {
171
+ rejectTime = time;
172
+ }
173
+ if (rejectTime && now - rejectTime > 16 * 1000) {
174
+ remove(page);
175
+ }
176
+ var value = [0, 0, 0, 0];
177
+ if (time >= 86400) {
178
+ value[0] = time / 86400 | 0;
179
+ time -= value[0] * 86400;
180
+ }
181
+ if (time >= 3600) {
182
+ value[1] = time / 3600 | 0;
183
+ time -= value[1] * 3600;
184
+ }
185
+ if (time >= 60) {
186
+ value[2] = time / 60 | 0;
187
+ time -= value[2] * 60;
188
+ }
189
+ value[3] = time;
190
+ var [date, ...time] = value;
191
+ if (date) timeNode.nodeValue = i18n`${date}天 ` + time.map(toNum2).join(":");
192
+ else if (time[0]) timeNode.nodeValue = time.map(toNum2).join(":");
193
+ else timeNode.nodeValue = time.slice(1).map(toNum2).join(":");
194
+
195
+ }, 20);
196
+ var time = function (elem) {
197
+ elem.appendChild(timeNode);
198
+ };
199
+ on('remove')(this, async function () {
200
+ await chatrtc.hangup();
201
+ chatrtc.send = null;
202
+ fullscreen.close();
203
+ chatrtc.remote = null;
204
+ chatrtc.local = null;
205
+ clearInterval(interval);
206
+ })
207
+ var canplay = function () {
208
+ var dv = this.parentNode;
209
+ var ratio = Math.min(dv.clientWidth / this.videoWidth, dv.clientHeight / this.videoHeight);
210
+ if (ratio) {
211
+ move.setSize(dv, [this.videoWidth * ratio, this.videoHeight * ratio]);
212
+ dv.style.opacity = 1;
213
+ }
214
+ }
215
+ once('mounted')(this, function () {
216
+ var [dv1, dv2, hangup, accept] = this.children;
217
+ dvs = [dv1, dv2];
218
+ drag.on(dv1, false);
219
+ drag.on(dv2, false);
220
+ drag.on(hangup, false);
221
+ drag.on(accept, false);
222
+ on("dblclick")(dv1, dblclick);
223
+ on("dblclick")(dv2, dblclick);
224
+ var v1 = chatrtc.remote = dv1.firstElementChild;
225
+ var v2 = chatrtc.local = dv2.firstElementChild;
226
+ v1.oncanplay = canplay;
227
+ v2.oncanplay = canplay;
228
+ if (!isRemote) start();
229
+ });
230
+ var accept = async function () {
231
+ await start();
232
+ acceptTime = new Date;
233
+ };
234
+ var onCandidate = function (candidate) {
235
+ cast(page, ["didate", candidate]);
236
+ };
237
+ var start = async function () {
238
+ try {
239
+ if (!remoteOffer) {
240
+ var offer = await chatrtc.call(onCandidate, remoteOffer);
241
+ cast(page, ['offer', offer]);
242
+ }
243
+ else {
244
+ var answer = await chatrtc.call(onCandidate, remoteOffer);
245
+ cast(page, ['accept', answer]);
246
+ }
247
+ }
248
+ catch {
249
+ page.setAttribute('error', '');
250
+ }
251
+ finally {
252
+ started = true;
253
+ }
254
+ render.refresh();
255
+ }
256
+ var page = this;
257
+ var hangup = async function () {
258
+ cast(page, ['hangup']);
259
+ remove(page);
260
+ };
261
+ var dblclick = function (a) {
262
+ if (this.hasAttribute('full')) return;
263
+ var style = this.getAttribute('style');
264
+ if (dvs.length !== 2) style = '';
265
+ dvs.forEach(v => {
266
+ if (v === this) v.setAttribute('full', ''), v.nodrag = true;
267
+ else v.removeAttribute('full'), v.nodrag = false, v.setAttribute('style', style), canplay.call(v);
268
+ });
269
+ };
270
+ this.onback = e => false;
271
+ var preventDefault = e => e.preventDefault();
272
+ var [remoteUser, localUser, remoteOffer] = arguments;
273
+ var isRemote = !!remoteOffer;
274
+
275
+ </script>
@@ -1,3 +1,8 @@
1
+ <style>
2
+ [left] {
3
+ float: left;
4
+ }
5
+ </style>
1
6
  <div head mount>
2
7
  <btn -if="users.length>0" class="menubtn" @click="showList=!showList" type_="showList?'default':'white'">
3
8
  <i></i>
@@ -7,6 +12,7 @@
7
12
  <template -if="user">
8
13
  <span -bind="user.name"></span>
9
14
  &nbsp;<span class="id">(<span -bind="user.id"></span>)</span>
15
+ <a left -if="user.id!==localid" @click="call()">呼叫</a>
10
16
  </template>
11
17
  <template -elseif="title" -src="title"> </template>
12
18
  <close @click="remove()"></close>