add UI controller,finalasie chat

Signed-off-by: weboko <anon@mail.com>
This commit is contained in:
weboko 2022-12-09 00:21:08 +01:00 committed by weboko
parent 4fddc02896
commit 190bd7af63
No known key found for this signature in database
2 changed files with 280 additions and 23 deletions

View File

@ -4,30 +4,182 @@
<meta charset='UTF-8'/>
<meta content='width=device-width, initial-scale=1.0' name='viewport'/>
<title>JS-Waku light chat</title>
<style>
* {
margin: 0;
padding: 0;
word-wrap: break-word;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
}
html {
font-size: 16px;
overflow: hidden;
}
body {
display: flex;
align-items: center;
padding: 10px;
justify-content: center;
}
details {
margin-bottom: 15px;
}
details p {
margin-bottom: 10px;
}
summary {
cursor: pointer;
max-width: 100%;
margin-bottom: 5px;
}
span {
font-weight: 300;
}
input, textarea {
line-height: 1rem;
padding: 5px;
}
textarea {
min-height: 3rem;
}
h3 {
margin-bottom: 5px;
}
.content {
width: 800px;
min-width: 300px;
max-width: 800px;
height: 100%;
display: flex;
flex-direction: column;
align-content: space-between;
}
#messages {
overflow-y: scroll;
overflow-x: hidden;
}
.message + .message {
margin-top: 15px;
}
.message :first-child {
font-weight: bold;
}
.message p + p {
margin-top: 5px;
}
.message span {
font-size: 0.8rem;
}
.inputArea {
display: flex;
gap: 10px;
flex-direction: column;
margin-top: 20px;
}
.controls {
margin-top: 10px;
display: flex;
gap: 10px;
}
.controls button {
flex-grow: 1;
cursor: pointer;
padding: 10px;
}
#send {
background-color: #32d1a0;
border: none;
color: white;
}
#send:hover {
background-color: #3abd96;
}
#send:active {
background-color: #3ba183;
}
#exit {
color: white;
border: none;
background-color: #ff3a31;
}
#exit:hover {
background-color: #e4423a;
}
#exit:active {
background-color: #c84740;
}
.footer {
display: flex;
width: 100%;
flex-direction: column;
align-self: flex-end;
}
</style>
</head>
<body>
<h2>Status</h2>
<div id='status'>Connecting... | Connected | Disconnected</div>
<div class="content">
<div class="header">
<h3>Status: <span id='status'></span></h3>
<h2>Local Peer Id</h2>
<div id='peer-id'></div>
<details>
<summary>Peer's information</summary>
<h2>Remote Peer Id</h2>
<div id='remote-peer-id'></div>
<h4>Content topic</h4>
<p id='contentTopic'></p>
<h2>Remote peer's multiaddr</h2>
<div id='remote-multiaddr'></div>
<h4>Local Peer Id</h4>
<p id='localPeerId'></p>
<div id="messages"></div>
<h4>Remote Peer Id</h4>
<p id='remotePeerId'></p>
<div class="inputArea">
<input type="text" />
</div>
<h4>Remote peer's multiaddr</h4>
<p id='remoteMultiAddr'></p>
</details>
</div>
<div class="controls">
<button>Send</button>
<button>Exit chat</button>
<div id="messages"></div>
<div class="footer">
<div class="inputArea">
<input type="text" id="nickText" placeholder="Nickname" />
<textarea id="messageText" placeholder="Message"></textarea>
</div>
<div class="controls">
<button id="send">Send</button>
<button id="exit">Exit chat</button>
</div>
</div>
</div>
<script src="//cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js"></script>

View File

@ -7,16 +7,41 @@ const MULTI_ADDR = "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/
const CONTENT_TOPIC = "/toy-chat/2/huilong/proto";
const PROTOCOLS = ["filter", "lightpush"];
const { sendMessage, unsubscribeFromMessages } = await initializeWakuContext({
protocols: PROTOCOLS,
multiAddr: MULTI_ADDR,
contentTopic: CONTENT_TOPIC,
onMessageReceived: ({ nick, timestamp, text }) => {
console.log(timestamp, '\t', nick, ": ", text);
},
runApp().catch((err) => {
console.error(err);
});
async function initializeWakuContext({
async function runApp() {
const ui = initUI();
ui.setStatus("connecting...");
const { info, sendMessage, unsubscribeFromMessages } = await initWakuContext({
protocols: PROTOCOLS,
multiAddr: MULTI_ADDR,
contentTopic: CONTENT_TOPIC,
onMessageReceived: ui.renderMessage,
});
ui.setStatus("connected");
ui.setLocalPeer(info.localPeerId);
ui.setRemotePeer(info.remotePeerId);
ui.setRemoteMultiAddr(info.multiAddr);
ui.setContentTopic(info.contentTopic);
ui.onSendMessage(sendMessage);
ui.onExit(() => {
ui.setStatus("disconnecting...");
unsubscribeFromMessages().then(() => {
ui.setStatus("disconnected");
ui.resetMessages();
});
});
}
async function initWakuContext({
multiAddr,
protocols,
contentTopic,
@ -46,9 +71,24 @@ async function initializeWakuContext({
});
});
const localPeerId = node.libp2p.peerId.toString();
const remotePeers = await node.libp2p.peerStore.all();
const remotePeerId = remotePeers[0].id.toString();
return {
unsubscribeFromMessages,
info: {
multiAddr,
contentTopic,
localPeerId,
remotePeerId,
},
sendMessage: async ({ text, nick }) => {
if (!text || !nick) {
return;
}
const protoMessage = ChatMessage.create({
nick,
timestamp: Date.now(),
@ -61,3 +101,68 @@ async function initializeWakuContext({
}
};
}
// UI adapter
function initUI() {
const exitButton = document.getElementById("exit");
const sendButton = document.getElementById("send");
const statusBlock = document.getElementById("status");
const localPeerBlock = document.getElementById("localPeerId");
const remotePeerId = document.getElementById("remotePeerId");
const remoteMultiAddr = document.getElementById("remoteMultiAddr");
const contentTopicBlock = document.getElementById("contentTopic");
const messagesBlock = document.getElementById("messages");
const nickText = document.getElementById("nickText");
const messageText = document.getElementById("messageText");
return {
// UI events
onExit: (cb) => {
exitButton.addEventListener("click", cb);
},
onSendMessage: (cb) => {
sendButton.addEventListener("click", () => {
cb({
nick: nickText.value,
text: messageText.value,
}).then(() => {
messageText.value = "";
});
});
},
// UI renderers
setStatus: (value) => {
statusBlock.innerText = value.toString();
},
setLocalPeer: (id) => {
localPeerBlock.innerText = id.toString();
},
setRemotePeer: (id) => {
remotePeerId.innerText = id.toString();
},
setRemoteMultiAddr: (multiAddr) => {
remoteMultiAddr.innerText = multiAddr.toString();
},
setContentTopic: (topic) => {
contentTopicBlock.innerText = topic.toString();
},
renderMessage: (messageObj) => {
const { nick, text, timestamp } = messageObj;
const date = new Date(timestamp);
// WARNING: XSS vulnerable
messagesBlock.innerHTML += `
<div class="message">
<p>${nick} <span>(${date.toDateString()})</span>:</p>
<p>${text}</p>
<div>
`;
},
resetMessages: () => {
messagesBlock.innerHTML = "";
},
};
}