add UI controller,finalasie chat
Signed-off-by: weboko <anon@mail.com>
This commit is contained in:
parent
4fddc02896
commit
190bd7af63
|
@ -4,30 +4,182 @@
|
||||||
<meta charset='UTF-8'/>
|
<meta charset='UTF-8'/>
|
||||||
<meta content='width=device-width, initial-scale=1.0' name='viewport'/>
|
<meta content='width=device-width, initial-scale=1.0' name='viewport'/>
|
||||||
<title>JS-Waku light chat</title>
|
<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>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h2>Status</h2>
|
<div class="content">
|
||||||
<div id='status'>Connecting... | Connected | Disconnected</div>
|
<div class="header">
|
||||||
|
<h3>Status: <span id='status'></span></h3>
|
||||||
|
|
||||||
<h2>Local Peer Id</h2>
|
<details>
|
||||||
<div id='peer-id'></div>
|
<summary>Peer's information</summary>
|
||||||
|
|
||||||
<h2>Remote Peer Id</h2>
|
<h4>Content topic</h4>
|
||||||
<div id='remote-peer-id'></div>
|
<p id='contentTopic'></p>
|
||||||
|
|
||||||
<h2>Remote peer's multiaddr</h2>
|
<h4>Local Peer Id</h4>
|
||||||
<div id='remote-multiaddr'></div>
|
<p id='localPeerId'></p>
|
||||||
|
|
||||||
<div id="messages"></div>
|
<h4>Remote Peer Id</h4>
|
||||||
|
<p id='remotePeerId'></p>
|
||||||
|
|
||||||
<div class="inputArea">
|
<h4>Remote peer's multiaddr</h4>
|
||||||
<input type="text" />
|
<p id='remoteMultiAddr'></p>
|
||||||
</div>
|
</details>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="controls">
|
<div id="messages"></div>
|
||||||
<button>Send</button>
|
|
||||||
<button>Exit chat</button>
|
<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>
|
</div>
|
||||||
|
|
||||||
<script src="//cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js"></script>
|
<script src="//cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js"></script>
|
||||||
|
|
|
@ -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 CONTENT_TOPIC = "/toy-chat/2/huilong/proto";
|
||||||
const PROTOCOLS = ["filter", "lightpush"];
|
const PROTOCOLS = ["filter", "lightpush"];
|
||||||
|
|
||||||
const { sendMessage, unsubscribeFromMessages } = await initializeWakuContext({
|
runApp().catch((err) => {
|
||||||
protocols: PROTOCOLS,
|
console.error(err);
|
||||||
multiAddr: MULTI_ADDR,
|
|
||||||
contentTopic: CONTENT_TOPIC,
|
|
||||||
onMessageReceived: ({ nick, timestamp, text }) => {
|
|
||||||
console.log(timestamp, '\t', nick, ": ", text);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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,
|
multiAddr,
|
||||||
protocols,
|
protocols,
|
||||||
contentTopic,
|
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 {
|
return {
|
||||||
unsubscribeFromMessages,
|
unsubscribeFromMessages,
|
||||||
|
info: {
|
||||||
|
multiAddr,
|
||||||
|
contentTopic,
|
||||||
|
localPeerId,
|
||||||
|
remotePeerId,
|
||||||
|
},
|
||||||
sendMessage: async ({ text, nick }) => {
|
sendMessage: async ({ text, nick }) => {
|
||||||
|
if (!text || !nick) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const protoMessage = ChatMessage.create({
|
const protoMessage = ChatMessage.create({
|
||||||
nick,
|
nick,
|
||||||
timestamp: Date.now(),
|
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 = "";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue