Wix release the new wix-realtime which allow developers to build interactive apps like chat app, multi-player game etc.
So, In this example i will discuss how we can build a chat app where a user can send a message to person B and person B immediatly get the message.
If you want to test it live here is the link:
https://test.salman2301.com
Overview
Front-end we use custom element, which allows to show the message side by side and also with custome element, we can have a fix height and scroll bar so user can scroll to previous messages. We can use repeater for this but we need to use pagination or infinite scrolling which is why i didn't. On the Backend, we use wix-realtime API with datahook - datahook runs the code when a new row is inserted in the database.
- realtime API allow us to do pub/sub ( publish/ subscriber) where sender or publisher send message to a channel and the reciever or subscriber can reciver the message.
Dataflow
If a user Person A send a message to Person B, the message will be inserted in the database and this runs the afterInsert data hook and the data hook use realtime api to publish to a channel, the name of the channel is same as the Person B user id. In this way, only the person B recieve the message and On the front-end, let's assume that the person B is online and we subscribe to the channel and the name of the channel Is the current user id. We get the user id from wix-user module wixUser.currentUser.id.
Database
Database Name: message Fields:
field_key data
from - USER_ID
to - USER_ID
message - Message
Code
// backend/data.js
import {publish} from 'wix-realtime-backend';
// datahook runs when a new row is inserted in the database
// item contains inserted row information { from: "uuid", to:"uuid", message:"hello"}
export function message_afterInsert(item, context) {
const { from, to, message, _id } = item;
const channel = { name : to};
let data = {
message,
from,
_id
};
// publish which take a channel name and data.
publish(channel, data, {includePublisher: true});
return item;
}
// Page code
import * as realtime from "wix-realtime";
import wixUsers from "wix-users";
import wixData from "wix-data";
import { getUsers, getMe } from "backend/getUsers.jsw";
let lastUserId, lastLoginEmail, lastPicture;
let userId = wixUsers.currentUser.id;
let owner;
$w.onReady(function () {
// $w('#dataset1').onReady(init);
init();
$w("#inSearch").onKeyPress((e) => {
setTimeout(() => {
if (e.key === "Enter") filterMem();
if (e.key === "Escape") {
$w("#inSearch").value = "";
filterMem();
}
}, 40);
});
$w("#ChatElement").setAttribute(
"append-msg",
JSON.stringify({
user: {
name: "salman",
},
msg: " Hello this is a test",
date: new Date().toISOString(),
isOwner: true,
})
);
getMe().then((data) => {
owner = data;
});
});
function init() {
// wix real time
const channel = { name: userId };
realtime.subscribe(channel, newMessage);
// update UI
filterMem();
// events
$w("#repeaterUser").onItemReady(($item, itemData, i) => {
let { loginEmail, picture } = itemData;
$item("#image1").src = picture;
$item("#textEmail").text = loginEmail;
});
$w("#containerUser").onClick((e) => {
switchUser(e.context.itemId);
});
$w("#btnSend").onClick(sendMessage);
$w("#inMessage").onKeyPress((e) => {
const { ctrlKey, key } = e;
if (key === "Enter" && !ctrlKey) {
sendMessage();
}
});
}
async function filterMem() {
let inMember = $w("#inSearch").value || undefined;
getUsers(inMember)
.then((data) => {
$w("#repeaterUser").data = data.items;
if (!lastUserId) {
switchUser(data.items[0]._id);
}
})
.catch(console.error);
}
async function switchUser(toUserId) {
lastUserId = toUserId;
$w("#repeaterUser").onItemReady(($item, itemData, i) => {
let { _id, loginEmail, picture } = itemData;
if (_id === toUserId) {
$item("#imgCurrUser").show();
$w("#textHeadUser").text = `Connected to ${loginEmail}`;
lastLoginEmail = loginEmail;
lastPicture = picture;
refreshMsg();
} else {
$item("#imgCurrUser").hide();
}
});
}
async function newMessage({ payload }) {
appendMsg(payload._id);
}
async function refreshMsg() {
$w("#ChatElement").setAttribute("messages", "[]");
let resMsgs = await wixData
.query("message")
.eq("from", userId)
.eq("to", lastUserId)
.or(wixData.query("message").eq("from", lastUserId).eq("to", userId))
.ascending("_createdDate")
.find();
let msg = resMsgs.items;
let username = lastLoginEmail.split("@")[0];
msg = msg.map((el) => {
let isOwner = userId === el.from;
let userImage = isOwner ? owner.picture : lastPicture;
userImage = encodeURI(userImage);
if (!userImage.startsWith("https://")) userImage = undefined;
return {
_id: el._id,
isOwner: isOwner,
user: {
name: username,
image: userImage,
},
msg: el.message,
date: el._createdDate,
data: el,
};
});
$w("#ChatElement").setAttribute("messages", JSON.stringify(msg));
if (msg.length === 0) {
$w("#textNoMsg").show();
} else {
$w("#textNoMsg").hide();
}
}
async function appendMsg(msgId) {
let resMsgs = await wixData.query("message").eq("_id", msgId).find();
let message = resMsgs.items[0];
console.log({ resMsgs });
let username = lastLoginEmail.split("@")[0];
let isOwner = userId === message.from;
let userImage = isOwner ? owner.picture : lastPicture;
userImage = encodeURI(userImage);
if (!userImage.startsWith("https://")) userImage = undefined;
let msg = {
_id: message._id,
isOwner: isOwner,
user: {
name: username,
image: userImage,
},
msg: message.message,
date: message._createdDate,
data: message,
};
if (!(lastUserId === message.from || lastUserId === message.to)) {
console.error(" No for the current user show alert!");
return;
}
$w("#ChatElement").setAttribute("append-msg", JSON.stringify(msg));
}
async function sendMessage() {
try {
$w("#btnSend").disable();
let msg = $w("#inMessage").value;
if (!msg) return;
let toInsert = {
from: userId,
to: lastUserId,
message: msg,
};
let inserted = await wixData.insert("message", toInsert);
appendMsg(inserted._id);
$w("#btnSend").enable();
$w("#inMessage").value = "";
} catch (e) {
console.log("ERROR : ", e.message);
$w("#btnSend").enable();
$w("#inMessage").value = "";
}
}
For the custome element check my github
https://github.com/Salman2301/wix-chat-component
Wow, your information is nice we will try this soon and thanks for posting this and keep it up.
_____________________________________
from:- cheap digitizing embroidery
how do i set up the front end elements? please help me
Excellent. Will try.