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.
- package/#/345/233/275/351/231/205/345/214/226.yml +18 -0
- package/coms/basic/data.js +14 -1
- package/coms/basic/size.js +3 -2
- package/coms/compile/Javascript.js +4 -1
- package/coms/compile/Javascript_test.js +4 -0
- package/coms/frame/ChatRTC.js +136 -0
- package/coms/frame/chat-rtc.xht +275 -0
- package/coms/frame/chat.html +6 -0
- package/coms/frame/chat.js +246 -9
- package/coms/frame/chat.less +4 -0
- package/coms/zimoli/drag.js +9 -4
- package/coms/zimoli/fullscreen.js +7 -1
- package/coms/zimoli/move.js +6 -2
- package/package.json +1 -1
- package/public/efront.js +1 -1
|
@@ -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
|
|
package/coms/basic/data.js
CHANGED
|
@@ -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
|
|
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;
|
package/coms/basic/size.js
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
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
|
+
<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>
|
package/coms/frame/chat.html
CHANGED
|
@@ -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
|
<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>
|