diff --git a/chat-signaling-server/static/index.css b/chat-signaling-server/static/index.css
index e7da6c2..9f7d427 100644
--- a/chat-signaling-server/static/index.css
+++ b/chat-signaling-server/static/index.css
@@ -9,6 +9,7 @@
#message-list {
width: 100%;
flex-grow: 1;
+ max-height: 100%;
overflow-y: scroll;
}
diff --git a/chat-signaling-server/static/style.css b/chat-signaling-server/static/style.css
index f3b05a8..07d2c10 100644
--- a/chat-signaling-server/static/style.css
+++ b/chat-signaling-server/static/style.css
@@ -11,4 +11,6 @@ body {
#content {
width: 100%;
flex-grow: 1;
+ max-height: 100%;
+ overflow: hidden;
}
\ No newline at end of file
diff --git a/chat-signaling-server/templates/index.html b/chat-signaling-server/templates/index.html
index 20ff16a..ef0b3b7 100644
--- a/chat-signaling-server/templates/index.html
+++ b/chat-signaling-server/templates/index.html
@@ -13,6 +13,7 @@
+
{% endblock %}
@@ -22,6 +23,7 @@
let message_list = document.getElementById("message-list")
let peers = document.getElementById("peers")
let inputbox = document.getElementById("message-input")
+ let sendfile = document.getElementById("sendfile")
let search = new URLSearchParams(location.search);
let sender = search.get("name") || "";
@@ -41,10 +43,62 @@
const MessageSessionAnswer = "SessionAnswer";
const MessageICECandidate = "IceCandidate";
- const display = (message) => {
- let newNode = document.createElement("div")
- newNode.innerHTML = `${new Date().toTimeString()}: ${message}`;
- message_list.appendChild(newNode)
+ let updateSendfile = () => {
+ if (peers.value != "") {
+ sendfile.removeAttribute("disabled")
+ } else {
+ sendfile.setAttribute("disabled", "")
+ }
+ }
+ peers.addEventListener("change", updateSendfile)
+ sendfile.addEventListener("change", async (ev) => {
+ let file = sendfile.files[0]
+ sendfile.value = ""
+
+ let peer = peerMap.get(peers.value)
+ if (!peer) {
+ return
+ }
+ display(`你给 ${peers.value} 传了一个文件: ${file.name}。传输中...`)
+
+ let reader = new FileReader()
+ let dc = peer.createDataChannel(`file:${file.name}`)
+ reader.addEventListener("load", (ev) => {
+ dc.send(reader.result)
+ dc.close()
+ })
+ dc.addEventListener("open", () => {
+ reader.readAsArrayBuffer(file)
+ })
+ })
+
+ const createNode = (tag, ...children) => {
+ let node = document.createElement(tag)
+ children.forEach(child => {
+ if(typeof child === "string") {
+ let inner = document.createElement("span")
+ inner.innerHTML = child
+ node.appendChild(inner)
+ } else if (child instanceof HTMLElement) {
+ node.appendChild(child)
+ } else {
+ console.log("child is not a node: ", child, typeof child)
+ }
+ })
+ return node
+ }
+
+ const display = (...message) => {
+ let scrollToBottom = Math.abs(message_list.scrollHeight - message_list.scrollTop - message_list.clientHeight) < 1;
+ message_list.appendChild(createNode("div",
+ `${new Date().toTimeString()}: `,
+ ...message
+ ))
+ if(scrollToBottom) {
+ message_list.scrollTo({
+ top: message_list.scrollHeight
+ })
+ }
}
inputbox.addEventListener("keyup", (e) => {
@@ -59,30 +113,34 @@
return
}
- console.log(`You -> ${peers.value}: ${inputbox.value}`)
- display(`You -> ${peers.value}: ${inputbox.value}`)
+ display(`你 -> ${peers.value}: ${inputbox.value}`)
channel.send(inputbox.value)
inputbox.value = ""
})
const addPeer = (peerName) => {
+ display(`连接上了 ${peerName}`)
+
let newNode = document.createElement("option")
newNode.id = peerName
newNode.setAttribute("value", peerName)
- newNode.innerText = peerName;
newNode.innerHTML = peerName;
peers.appendChild(newNode)
+
+ updateSendfile()
}
const removePeer = (peerName) => {
+ display(`${peerName} 走了...`)
let el = document.getElementById(peerName);
if(el) el.remove()
+
+ updateSendfile()
}
let timeout;
let reconnect = () => {
if(ws && (ws.readyState == WebSocket.CONNECTING || ws.readyState == WebSocket.OPEN)) {
- console.log("ws ok", ws)
return;
}
@@ -99,7 +157,7 @@
handle_ws_message(JSON.parse(data))
})
ws.addEventListener("open", () => {
- display("server connected. waiting for a name to be assigned for you...")
+ display("服务器连上啦。你等等,给你起个名字...")
ws.send(JSON.stringify({
message: {
type: MessageBootstrap,
@@ -108,7 +166,6 @@
sender,
}))
})
- console.log("connecting...")
}
let handle_ws_message = (wsMessage) => {
@@ -154,17 +211,37 @@
console.log("gather", peer.iceGatheringState)
})
peer.addEventListener("datachannel", ({channel}) => {
- channelMap.set(peerName, channel);
- channel.addEventListener("open", (ev) => {
- display("connected in event")
- addPeer(peerName)
- })
- channel.addEventListener("message", (ev) => {
- display(`${peerName} -> You: ${ev.data}`)
- })
- channel.addEventListener("close", () => {
- removePeer(peerName)
- })
+ if(channel.label === "chat") {
+ channelMap.set(peerName, channel);
+ channel.addEventListener("open", (ev) => {
+ addPeer(peerName)
+ })
+ channel.addEventListener("message", (ev) => {
+ display(`${peerName} -> You: ${ev.data}`)
+ })
+ channel.addEventListener("close", () => {
+ removePeer(peerName)
+ })
+ } else if (channel.label.startsWith("file:")) {
+ let filename = channel.label.substr(5)
+ let buffers = [];
+ channel.addEventListener("open", ev => {
+ display(`${peerName} 给你发了一个文件: ${filename}。 接收中...`)
+ })
+ channel.addEventListener("message", ev => {
+ buffers.push(ev.data)
+ })
+ channel.addEventListener("close", () => {
+ var link = document.createElement('a');
+ link.href = window.URL.createObjectURL(new Blob(buffers));
+ link.download = filename;
+ link.innerHTML = filename
+ display(
+ "文件:",
+ link,
+ )
+ })
+ }
})
peerMap.set(peerName, peer);
@@ -175,11 +252,10 @@
if(wsMessage.message.type === MessageDiscoverResponse) {
let channel = peer.createDataChannel("chat");
channel.addEventListener("open", (ev) => {
- display("connected in event")
addPeer(peerName)
})
channel.addEventListener("message", (ev) => {
- display(`${peerName} -> You: ${ev.data}`)
+ display(`${peerName} -> 你: ${ev.data}`)
})
channel.addEventListener("close", () => {
removePeer(peerName)
@@ -225,10 +301,10 @@
room,
sender: wsMessage.sender,
}))
- display(`You are ${sender}. Searching for peers...`)
+ display(`决定了,就叫 ${sender}. 我们等等小伙伴吧...`)
break;
case MessageDiscoverRequest:
- display("connecting to peer " + wsMessage.sender)
+ display(`正在尝试连接 ${wsMessage.sender}`)
ws.send(JSON.stringify({
message: {
type: MessageDiscoverResponse,
@@ -245,7 +321,6 @@
recreateAndSetupPeer(wsMessage.sender)
break
case MessageSessionAnswer:
- display("receiving connection to peer: " + wsMessage.sender)
console.log("set remote answer")
peer.setRemoteDescription(JSON.parse(wsMessage.message.sdp))
peer.restartIce()
@@ -261,7 +336,6 @@
}
reconnect()
- console.log("document loaded")
})()
{% endblock %}
\ No newline at end of file