1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747 |
- /*
- Verification Process:
- - Start verification from other device.
- - Run: `window.mClient.getVerificationRequestsToDeviceInProgress(userId)[0].accept();`
- - The other device will then ask about doing a QR or emoji thing. Select emoji.
- - Run `window.mClient.getVerificationRequestsToDeviceInProgress(userId)[0].verifier.doVerification();`
- - Once you see the emojis on the other device, the emoji data will appear in `window.mClient.getVerificationRequestsToDeviceInProgress(userId)[0].verifier.sasEvent.sas.emoji`. There is also a `.decimal` prop in the `sas` object.
- - Probably should display those emojis to so you can compare.
- - Run `window.mClient.getVerificationRequestsToDeviceInProgress(userId)[0].verifier.sasEvent.confirm();`
- - You're verified!
- */
- const LOCAL_STORAGE_SESSION_KEY = 'matrix-session';
- var initSync = false;
- var highlightedRoom = 0;
- var rooms = [];
- var highlightedMsg;
- var page = 'login';
- var currentRoom;
- var highlightedLoginInput = 0;
- var scrollMsg;
- var editingEvent;
- var replyingToEvent;
- var previousConv;
- var mainMenu = [];
- var highlightedMenuItem = 0;
- var verificationPhase = null;
- var currentlyWatching = null;
- var previousPage = 'rooms';
- var loadingMessagesIndex = 0;
- const swapMiddle = () => {
- document.getElementById('middle').innerHTML = 'REPLAY';
- };
- const backToChat = () => {
- const chat = document.getElementById('chat');
- chat.style.display = 'flex';
- document.getElementById('chat-textbox').focus();
- }
- const parseBody = (body) => {
- if(body) {
- const reg = /\b(https|http)?:\/\/\S+/gi;
- const urls = body.match(reg);
- const withoutUrls = body.split(reg);
- var i = -1;
- const parsedBody = withoutUrls.reduce((a, str) => {
- if(str === 'https' || str === 'http') {
- i++;
- return a + `<a target="_blank" href="${urls[i]}">${urls[i]}</a>`;
- } else {
- return a + str;
- }
- }, '');
- return parsedBody;
- }
- return body;
- }
- const getFormattedBody = (content = {}) => {
- if(content.formatted_body && content.formatted_body.indexOf('<mx-reply>') > -1) {
- const fBodyformattedBody = content.formatted_body;
- const mxReplyIndex = fBodyformattedBody.indexOf('</mx-reply>');
- const body = fBodyformattedBody && fBodyformattedBody.slice(mxReplyIndex + 11);
- const formattedBody = fBodyformattedBody && fBodyformattedBody.substring(0, mxReplyIndex).substring(10) + '<br/>' + body;
- return [formattedBody, body];
- }
- const parsedBody = parseBody(content.body);
- return [parsedBody, content.body];
- };
- const ALLOWED_BLOB_MIMETYPES = [
- 'image/jpeg',
- 'image/gif',
- 'image/png',
- 'image/apng',
- 'image/webp',
- 'image/avif',
- 'video/mp4',
- 'video/webm',
- 'video/ogg',
- 'video/quicktime',
- 'audio/mp4',
- 'audio/webm',
- 'audio/aac',
- 'audio/mpeg',
- 'audio/ogg',
- 'audio/wave',
- 'audio/wav',
- 'audio/x-wav',
- 'audio/x-pn-wav',
- 'audio/flac',
- 'audio/x-flac',
- ];
- const getBlobSafeMimeType = (mimetype) => {
- if (!ALLOWED_BLOB_MIMETYPES.includes(mimetype)) {
- return 'application/octet-stream';
- }
- return mimetype;
- };
- const getBlobData = (id, url, content, type) => {
- let file;
- let mimetype;
- if(type === 'image') {
- mimetype = content.info.mimetype ? content.info.mimetype.split(";")[0].trim() : '';
- file = content.file;
- } else if(type === 'video') {
- mimetype = content.info.thumbnail_info.mimetype ? content.info.thumbnail_info.mimetype.split(";")[0].trim() : '';
- file = content.info.thumbnail_file;
- } else if (type === 'audio') {
- mimetype = content.info.mimetype ? content.info.mimetype.split(";")[0].trim() : '';
- file = content.file;
- } else {
- return;
- }
- fetch(url).then((res) => {
- res.arrayBuffer().then((a) => {
- decryptAttachment(a, file).then((dataArray) => {
- mimetype = getBlobSafeMimeType(mimetype);
- const blob = new Blob([dataArray], { type: mimetype });
- const blobUrl = URL.createObjectURL(blob);
- const image = document.getElementById(`image-${id}`);
- image.src = blobUrl;
- if(type === 'video') {
- image.setAttribute('video', JSON.stringify(content));
- } else if( type === 'audio') {
- image.setAttribute('audio', JSON.stringify(content));
- }
- });
- })
- });
- };
- const messageBuilder = (event, room) => {
- const content = event.getContent();
- const sender = event.getSender();
- const date = event.getDate();
- const dateString = date.toLocaleString();
- const relation = event.getRelation();
- const members = room ? room.getMembers() : [];
- const shouldDisplayName = sender !== window.mClient.getUserId() && members.length > 2;
- const user = shouldDisplayName && room.getMember(sender);
- const floatDirection = sender === window.mClient.getUserId() ?
- 'align-self:flex-end;margin-right:10px;background-color:#4dc860' :
- 'align-self:flex-start;margin-left:10px;background-color:white';
- const dateDirection = sender === window.mClient.getUserId() ?
- 'text-align:right;margin-right:10px;' :
- 'text-align:left;margin-left:10px;';
- const reactDirection = sender === window.mClient.getUserId() ?
- 'justify-content:flex-end;margin-right:10px;' :
- 'justify-content:flex-start;margin-left:10px;';
- const [formattedBody, realBody] = getFormattedBody(content);
- const isSending = event.getId().indexOf(currentRoom) > -1;
- const dateOrSending = isSending ? `<p id="datetime-${event.getId()}" style="font-size:10px;color:gray;${dateDirection}" datetime="${dateString}">Sending...</p>`: `<p id="datetime-${event.getId()}" style="font-size:10px;color:gray;${dateDirection}">${dateString}</p>`;
- const nameOrNothing = user ? `<p id="name-${event.getId()}" style="font-size:10px;color:gray;${dateDirection}" datetime="${dateString}">${user.name}</p>` : '';
- window.mClient.sendReadReceipt(event, "m.read");
- if(content.msgtype === 'm.image') {
- const imageUrl = content.url ? window.mClient.mxcUrlToHttp(content.url) : window.mClient.mxcUrlToHttp(content.file.url);
- if (!content.url) {
- getBlobData(event.getId(), imageUrl, content, 'image');
- }
- return `
- <div id="msg-${event.getId()}" class="msgItem" sender="${sender}">
- <div id="innermsg-${event.getId()}" class="msgInnerItem" style="${floatDirection}">
- <img id="image-${event.getId()}" src="${imageUrl}" height=100 o_h="${content.info.h}" o_w="${content.info.w}" alt="${content.body}">
- </img>
- </div>
- ${dateOrSending}
- <div id="reactions-${event.getId()}" class="reactions" style="${reactDirection}"></div>
- </div>
- `;
- } else if(content.msgtype === 'm.video') {
- const imageUrl = content.info.thumbnail_file ? window.mClient.mxcUrlToHttp(content.info.thumbnail_file.url) : window.mClient.mxcUrlToHttp(content.info.thumbnail_url);
- if (content.info.thumbnail_file) {
- getBlobData(event.getId(), imageUrl, content, 'video');
- } else {
- setTimeout(() => {
- const image = document.getElementById(`image-${event.getId()}`);
- image.setAttribute('video', JSON.stringify(content));
- }, 200);
- }
- return `
- <div id="msg-${event.getId()}" class="msgItem" sender="${sender}">
- ${nameOrNothing}
- <div id="innermsg-${event.getId()}" class="msgInnerItem" style="${floatDirection}">
- <div class="play-button-container">
- <div class="play-button">
- ▶
- </div>
- </div>
- <img id="image-${event.getId()}" src="${imageUrl}" height=100 alt="${content.body}">
- </img>
- </div>
- ${dateOrSending}
- <div id="reactions-${event.getId()}" class="reactions" style="${reactDirection}"></div>
- </div>
- `;
- } else if(content.msgtype === 'm.audio') {
- const imageUrl = content.url ? window.mClient.mxcUrlToHttp(content.url) : window.mClient.mxcUrlToHttp(content.file.url);
- if (!content.url) {
- getBlobData(event.getId(), imageUrl, content, 'audio');
- } else {
- setTimeout(() => {
- const image = document.getElementById(`image-${event.getId()}`);
- image.setAttribute('audio', JSON.stringify(content));
- }, 200);
- }
- return `
- <div id="msg-${event.getId()}" class="msgItem" sender="${sender}">
- ${nameOrNothing}
- <div id="innermsg-${event.getId()}" class="msgInnerItem" style="${floatDirection}">
- <pre id="image-${event.getId()}" audio="${JSON.stringify(content)}">
- ▶ ${content.body}
- </pre>
- </div>
- ${dateOrSending}
- <div id="reactions-${event.getId()}" class="reactions" style="${reactDirection}"></div>
- </div>
- `;
- } else {
- return `
- <div id="msg-${event.getId()}" class="msgItem" sender="${sender}">
- ${nameOrNothing}
- <div id="innermsg-${event.getId()}" class="msgInnerItem" style="${floatDirection}" body="${realBody}">
- <pre>
- ${formattedBody}
- </pre>
- </div>
- ${dateOrSending}
- <div id="reactions-${event.getId()}" class="reactions" style="${reactDirection}"></div>
- </div>
- `
- }
- };
- const gotoRoomView = () => {
- if(initSync) {
- highlightedRoom = 0;
- }
- const roomz = window.mClient.getRooms();
- const roomList = roomz.sort((roomA, roomB) => {
- return roomA.name.localeCompare(roomB.name);
- }).reduce((a, room) => {
- if (a === '<div>') {
- return a + `
- <div id="room-${room.roomId}" class="roomItem active">
- ${room.name}
- </div>
- <br/>
- `;
- } else {
- return a + `
- <div id="room-${room.roomId}" class="roomItem">
- ${room.name}
- </div>
- <br/>
- `;
- }
- }, '<div>'); + '</div>'
- document.getElementById('room-menu').style = 'display: unset';
- document.getElementById('chat').style = 'display: none';
- document.getElementById('menu').style = 'display: none';
- document.getElementById('chat-textbox').value = '';
- document.getElementById('chat-textbox').selectionStart = 0
- document.getElementById('chat-textbox').style.height = '24px';
- document.getElementById('conversation').style.height = '100%';
- document.getElementById('editing').style.bottom = '55px';
- document.getElementById('replying').style.bottom = '55px';
- document.getElementById('login').style = 'display: none';
- document.getElementById("left").innerHTML = "";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "SELECT";
- document.getElementById("title-text").innerHTML = 'Rooms';
- document.getElementById("room-menu").innerHTML = roomList;
- initSync = true;
- rooms = document.getElementsByClassName('roomItem');
- page = 'rooms';
- highlightedMsg = null;
- };
- const markReaction = (event, relation) => {
- const {
- event_id,
- rel_type,
- key
- } = relation;
- const msgItem = document.getElementById(`msg-${event_id}`);
- const reactionsEl = document.getElementById(`reactions-${event_id}`);
- if(msgItem && reactionsEl) {
- reactionsEl.innerHTML = reactionsEl.innerHTML + `
- <div id="react-${event.getId()}" class="${relation.key} ${event.getSender()}" style="font-size:16px;">
- ${relation.key}
- </div>
- `
- // if the last message gets reacted, scroll down to see it
- const msgs = document.getElementsByClassName('msgItem');
- if(msgItem === msgs[msgs.length - 1]) {
- const conversationEl = document.getElementById("conversation");
- conversationEl.scrollTo(0, conversationEl.scrollHeight);
- }
- }
- };
- const removeReaction = (eventId) => {
- const reaction = document.getElementById(`react-${eventId}`);
- if(reaction)
- reaction.remove();
- };
- const replaceBody = (event, relation) => {
- const content = event.getContent();
- const innerMsgItem = document.getElementById(`innermsg-${relation.event_id}`);
- const newBody = content['m.new_content'].body;
- const hasFormattedBody = innerMsgItem.innerHTML.indexOf('blockquote') > -1;
- const parsedBody = parseBody(newBody);
- const allOfIt = parsedBody + '<br/><b class="edited-marker" style="color:black">(edited)</b>';
- if(innerMsgItem) {
- innerMsgItem.setAttribute('body', newBody);
- if(hasFormattedBody) {
- const blockquote = innerMsgItem.getElementsByTagName('blockquote')[0];
- innerMsgItem.innerHTML = `
- <pre>
- ${blockquote.outerHTML}
- <br/>
- ${allOfIt}
- `;
- } else {
- innerMsgItem.innerHTML = `
- <pre>
- ${allOfIt}
- </pre>
- `;
- }
- }
- };
- var timeout;
- const prepareSession = (client) => {
- document.getElementById("room-menu").innerHTML = "Loading..."
- document.getElementById("title-text").innerHTML = 'Rooms';
- document.getElementById("left").innerHTML = "";
- document.getElementById("right").innerHTML = "";
- document.getElementById("middle").innerHTML = "SELECT";
- window.mClient = window.matrixcs.createClient({
- baseUrl: client.baseUrl,
- accessToken: client.access_token,
- userId: client.user_id,
- deviceId: client.device_id,
- sessionStore: new window.matrixcs.WebStorageSessionStore(localStorage),
- });
- window.mClient.on("sync", function(event) {
- if(!initSync) {
- gotoRoomView();
- }
- });
- window.mClient.on("crypto.verification.request", function(event, room, toStartOfTimeline) {
- if(verificationPhase === 'accept') {
- verificationPhase = 'sas';
- event.accept().then(() => {
- alert('Accepted verification! On the other device, select emoji verification, then press ok here.');
- event.waitFor((e) => {
- if(e.verifier && verificationPhase) {
- verificationPhase = 'sas';
- e.verifier.doVerification();
- setTimeout(() => {
- if(e.verifier.sasEvent) {
- const emojis = e.verifier.sasEvent.sas.emoji.reduce((a, em) => {
- return a + em[0] + ' ' + em[1] + '\n';
- }, '');
- if(confirm('Match?\n' + emojis)) {
- e.verifier.sasEvent.confirm();
- } else {
- e.verifier.sasEvent.mismatch();
- }
- }
- }, 3000);
- clearTimeout(timeout);
- }
- });
- timeout = setTimeout(() => {
- verificationPhase = null;
- }, 2 * 60 * 1000); // you get 2 minutes
- }).catch(() => {
- alert('Failed to accept verification!');
- verificationPhase = null;
- });
- }
- });
- window.mClient.on("Room.timeline", function(event, room, toStartOfTimeline) {
- window.mClient.decryptEventIfNeeded(event).then(() => {
- const eventType = event.getType();
- const relation = event.getRelation();
- if (page === 'chat' && currentRoom === room.roomId ) {
- switch(eventType) {
- case 'm.room.message': {
- if(!relation) {
- const newMsg = messageBuilder(event, room);
- const conversationEl = document.getElementById("conversation");
- const typing = document.getElementsByClassName('typing');
- let newTyping = '';
- for(var i = 0; i < typing.length; i++) {
- const div = typing[i];
- div.remove();
- newTyping = newTyping + div.outerHTML;
- }
- if(loadingMessagesIndex > 0) {
- conversationEl.innerHTML = newMsg + conversationEl.innerHTML + newTyping;
- loadingMessagesIndex = loadingMessagesIndex - 1;
- highlightedMsg = highlightedMsg + 1;
- } else {
- conversationEl.innerHTML = conversationEl.innerHTML + newMsg + newTyping;
- }
- if(document.activeElement.id === 'chat-textbox') {
- conversationEl.scrollTo(0, conversationEl.scrollHeight);
- } else if(loadingMessagesIndex === 0) {
- const cur = document.getElementsByClassName('msgItem msgItem-selected')[0];
- cur.scrollIntoView({
- behavor: 'smooth',
- block: 'bottom',
- inline: 'nearest'
- });
- }
- } else {
- if(relation.rel_type === 'm.replace')
- replaceBody(event, relation);
- }
- return;
- }
- case 'm.reaction': {
- if(loadingMessagesIndex > 0) {
- loadingMessagesIndex = loadingMessagesIndex - 1;
- }
- if(relation && relation.rel_type === 'm.annotation') {
- markReaction(event, relation);
- }
- return;
- }
- case 'm.room.redaction': {
- if(loadingMessagesIndex > 0) {
- loadingMessagesIndex = loadingMessagesIndex - 1;
- }
- removeReaction(event.event.redacts);
- return;
- }
- }
- }
- });
- });
- window.mClient.on("RoomMember.typing", function(event, member) {
- const room = window.mClient.getRoom(currentRoom);
- if(room) {
- const members = room.getMembers().map(({userId}) => userId);
- if (page === 'chat' && members.indexOf(member.userId) > -1) {
- if (member.typing) {
- const typingDiv = `<div id="typing-${member.userId}" class="typing">${member.name} is typing...</div>`;
- const conv = document.getElementById('conversation');
- conv.innerHTML = conv.innerHTML + typingDiv;
- // if(conv.clientHeight - conv.scrollTop < 20) {
- // conv.scrollTo(0, conv.scrollHeight);
- // }
- }
- else {
- const typingDiv = document.getElementById(`typing-${member.userId}`);
- if(typingDiv)
- typingDiv.remove();
- }
- }
- }
- });
- // window.mClient.on("Room.receipt", function(event, member) {
- // const content = event.getContent();
- // const reads = Object.keys(content);
- // reads.forEach((eventId) => {
- // if(page === 'chat') {
- // const msg = document.getElementById(`msg-${eventId}`);
- // if(member.userId !== msg.getAttribute('sender')) {
- // const dateTime = document.getElementById(`datetime-${eventId}`);
- // if(dateTime)
- // dateTime.innerHTML = 'read <br/>' + dateTime.innerHTML;
- // }
- // }
- // })
- // })
- window.mClient.initCrypto().then(() => {
- window.mClient.startClient({
- initialSyncLimit: 10,
- lazyLoadMembers: true,
- });
- });
- };
- const login = (baseUrl, user, password) => {
- const client = window.matrixcs.createClient(baseUrl);
- client.loginWithPassword(user, password).then((d) => {
- const session = {...d, baseUrl};
- localStorage.setItem(LOCAL_STORAGE_SESSION_KEY, JSON.stringify(session));
- prepareSession(session);
- }).catch((e) => {
- console.error(e);
- alert('Login error! Check all inputs.')
- document.getElementById('middle').innerHTML = 'LOGIN';
- });
- };
- const sendReaction = (emoji) => {
- const el = document.getElementsByClassName('msgItem msgItem-selected')[0];
- if(el) {
- if(el.innerHTML.indexOf(emoji) > -1) { // has one already
- const react = el.getElementsByClassName(`${emoji} ${window.mClient.getUserId()}`)[0];
- if (react) {
- const eventId = react.id.substring(6);
- return window.mClient.redactEvent(currentRoom, eventId).then(() => {
- console.log('redacted!');
- }).catch((e) => {
- console.log(e);
- alert('Failed to redact reaction to message: ', JSON.stringify(e));
- });
- }
- }
- const event_id = el.id.substring(4);
- const content = {
- 'm.relates_to': {
- key: emoji,
- event_id,
- rel_type: 'm.annotation',
- }
- };
- const date = new Date();
- const tnxId = date.getTime()/1000;
- window.mClient.sendEvent(currentRoom, "m.reaction", content, tnxId).then(({event_id}) => {
- const room = window.mClient.getRoom(currentRoom);
- const newReact = document.getElementById(`react-~${room.roomId}:${tnxId}`);
- newReact.id = `react-${event_id}`;
- }).catch((e) => {
- console.log(e);
- alert(e.message);
- });
- }
- };
- const killSession = () => {
- window.mClient.stopClient();
- localStorage.removeItem(LOCAL_STORAGE_SESSION_KEY);
- close();
- };
- const verifyDevice = () => {
- if(confirm('Before starting the verification process on the other device, press okay here and wait.')) {
- verificationPhase = 'accept';
- }
- }
- const verifyDevices = () => {
- if(confirm('If this error was because of unverified devices, would you like to verify all devices in this room?')) {
- const members = window.mClient.getRoom(currentRoom).getMembers();
- Promise.all(members.map((member) => {
- const userId = member.userId;
- const devices = window.mClient.getStoredDevicesForUser(userId);
- devices.filter(({verified}) => verified === 0).map((dev) => {
- return window.mClient.setDeviceVerified(userId, dev.deviceId, true);
- });
- })).then(() => {
- alert('All devices in this room are now marked as verified!');
- }).catch(() => {
- alert('An error occurred while marking devices as verified.');
- });
- }
- }
- const openMenu = () => {
- page = 'menu';
- document.getElementById("left").innerHTML = "";
- document.getElementById("right").innerHTML = "Back";
- document.getElementById("middle").innerHTML = "SELECT";
- const menuList = mainMenu && mainMenu.reduce((a, item) => {
- if (a === '') {
- return a + `
- <div id="menu-${item.label}" class="menuItem active">
- ${item.label}
- </div>
- <br/>
- `;
- } else {
- return a + `
- <div id="menu-${item.label}" class="menuItem">
- ${item.label}
- </div>
- <br/>
- `;
- }
- }, '');
- const menu = document.getElementById('menu');
- const room = document.getElementById('room-menu');
- const chat = document.getElementById('chat');
- const input = document.getElementById('chat-textbox');
- menu.style.display = 'unset';
- room.style.display = 'none';
- chat.style.display = 'none';
- input.blur();
- menu.innerHTML = menuList;
- };
- const closeMenu = (goBack) => {
- page = previousPage;
- const menu = document.getElementById('menu');
- menu.style.display = 'none';
- goBack();
- };
- const progressHandler = ({loaded, total}) => {
- const percent = Math.round(loaded / total * 100);
- const uploading = document.getElementById('uploading');
- uploading.style.bottom = "55px";
- uploading.style.display = "unset";
- uploading.innerHTML = percent + "%";
- };
- const loadingHandler = () => {
- const chatBox = document.getElementById('chat-textbox');
- const uploading = document.getElementById('uploading');
- uploading.style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- uploading.style.display = "unset";
- uploading.innerHTML = "Loading...";
- };
- const uploadContent = (file, img) => {
- const uploading = document.getElementById('uploading');
- return new Promise((res, rej) => {
- if(window.mClient.isRoomEncrypted(currentRoom)) {
- const reader = new FileReader();
- reader.onload = () => {
- const attachment = encryptAttachment(reader.result).then((encryptedResult) => {
- const blob = new Blob([encryptedResult.data]);
- window.mClient.uploadContent(blob, {
- includeFilename: false,
- progressHandler,
- }).then((url) => {
- uploading.style.display = "none";
- let content;
- if(file.type.indexOf('image') > -1) {
- content = {
- msgtype: 'm.image',
- body: file.name,
- info: {
- h: img.height,
- w: img.width,
- mimetype: file.type,
- size: file.size,
- },
- file: {
- ...encryptedResult.info,
- url,
- }
- };
- } else if(file.type.indexOf('video') > -1) {
- content = {
- msgtype: 'm.video',
- body: file.name,
- info: {
- mimetype: file.type,
- size: file.size,
- },
- file: {
- ...encryptedResult.info,
- url,
- }
- };
- } else if(file.type.indexOf('audio') > -1) {
- content = {
- msgtype: 'm.audio',
- body: file.name,
- info: {
- mimetype: file.type,
- size: file.size,
- },
- file: {
- ...encryptedResult.info,
- url,
- }
- };
- }
- res(content);
- }).catch((e) => {
- uploading.style.display = "none";
- alert('Failed to upload file!');
- });
- });
- };
- reader.readAsArrayBuffer(file);
- } else {
- window.mClient.uploadContent(file, {
- progressHandler,
- }).then((url) => {
- uploading.style.display = "none";
- let content;
- if(file.type.indexOf('image') > -1) {
- content = {
- msgtype: 'm.image',
- body: file.name,
- url,
- info: {
- h: img.height,
- w: img.width,
- mimetype: file.type,
- size: file.size,
- }
- };
- } else if(file.type.indexOf('video') > -1) {
- content = {
- msgtype: 'm.video',
- body: file.name,
- url,
- info: {
- mimetype: file.type,
- size: file.size,
- }
- };
- } else if(file.type.indexOf('audio') > -1) {
- content = {
- msgtype: 'm.audio',
- body: file.name,
- url,
- info: {
- mimetype: file.type,
- size: file.size,
- }
- };
- }
- res(content);
- }).catch((e) => {
- uploading.style.display = "none";
- alert('Failed to upload file!');
- });
- }
- });
- }
- const insertIntoTextbox = (v) => () => {
- const chatBox = document.getElementById('chat-textbox');
- chatBox.value = chatBox.value + v;
- closeMenu(backToChat);
- };
- const keydownListener = (e) => {
- const chatBox = document.getElementById('chat-textbox');
- if(page === 'login') {
- if(e.key === 'ArrowUp') {
- var inputs = document.getElementsByClassName('login-text');
- inputs[highlightedLoginInput].blur();
- highlightedLoginInput = highlightedLoginInput - 1;
- if(highlightedLoginInput === -1) {
- highlightedLoginInput = inputs.length - 1;
- }
- inputs[highlightedLoginInput].focus();
- } else if (e.key === 'ArrowDown') {
- var inputs = document.getElementsByClassName('login-text');
- inputs[highlightedLoginInput].blur();
- highlightedLoginInput = highlightedLoginInput + 1;
- if(highlightedLoginInput === inputs.length) {
- highlightedLoginInput = 0
- }
- inputs[highlightedLoginInput].focus();
- } else if (e.key === 'Enter' && document.getElementById('middle').innerHTML !== 'Loading...') {
- var baseUrl = document.getElementById('homeserver').value;
- var user = document.getElementById('user').value;
- var password = document.getElementById('password').value;
- document.getElementById('middle').innerHTML = 'Loading...'
- login(baseUrl, user, password);
- }
- return e;
- } else if(document.activeElement === chatBox) {
- const editing = document.getElementById('editing');
- const replying = document.getElementById('replying');
- const uploading = document.getElementById('uploading');
- if(e.key === 'End' || e.key === 'EndCall') {
- const chatBox = document.getElementById('chat-textbox');
- if(chatBox && chatBox.value !== '') {
- if(confirm('Are you sure you want to close the app?')) {
- window.mClient.stopClient();
- close();
- }
- return;
- }
- return;
- } else if(e.key === 'ArrowUp' && chatBox.selectionStart === 0) {
- chatBox.blur();
- var msgs = document.getElementsByClassName('msgItem');
- const cur = document.getElementsByClassName('msgItem msgItem-selected')[0];
- highlightedMsg = msgs.length - 1;
- msgs[highlightedMsg].className = 'msgItem msgItem-selected';
- msgs[highlightedMsg].scrollIntoView({
- behavor: 'smooth',
- block: 'center',
- inline: 'nearest'
- });
- if(cur)
- cur.className = 'msgItem';
- } else if (e.key === 'Call' || e.key === 'F1') {
- var msgs = document.getElementsByClassName('msgItem');
- if(msgs[highlightedMsg]) {
- chatBox.blur();
- highlightedMsg = highlightedMsg - 1;
- msgs[highlightedMsg].scrollIntoView({
- behavor: 'smooth',
- block: 'center',
- inline: 'nearest'
- });
- }
- } else if(e.key === 'Backspace' && chatBox.selectionStart === 0) {
- e.preventDefault();
- chatBox.blur();
- gotoRoomView(chatBox);
- } else if ((e.key === "SoftLeft" || e.key === "Control") && page === 'chat' && document.getElementById("left").innerHTML !== '') {
- if (editing.style.display === 'unset') { // editing
- const body = document.getElementById('chat-textbox').value.trim();
- const content = {
- body: ' * ' + body,
- msgtype: "m.text",
- 'm.relates_to': {
- event_id: editingEvent,
- rel_type: 'm.replace',
- },
- 'm.new_content': {
- body,
- msgtype: 'm.text',
- }
- };
- if (body !== '') {
- const date = new Date();
- const tnxId = date.getTime()/1000;
- loadingHandler();
- window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "ENTER";
- document.getElementById("chat-textbox").value = '';
- document.getElementById("chat-textbox").disabled = false;
- document.getElementById("chat-textbox").style.height = "24px";
- document.getElementById('chat-textbox').selectionStart = 0
- document.getElementById('conversation').style.height = '100%';
- document.getElementById('editing').style.bottom = "55px";
- editing.style.display = 'none';
- uploading.style.display = 'none';
- editingEvent = null;
- // const msg = document.getElementsByClassName('msgItem msgItem-selected')[0];
- // msg.className = 'msgItem';
- // highlightedMsg = null;
- // const room = window.mClient.getRoom(currentRoom);
- // const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
- // const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
- // newMsg.id = `msg-${event_id}`;
- // newInnerMsg.id = `innermsg-${event_id}`;
- return;
- }).catch((err) => {
- alert('Failed to send message: ' + err.message);
- if(err.name === 'UnknownDeviceError') {
- verifyDevices();
- }
- console.log(err);
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "ENTER";
- document.getElementById("chat-textbox").disabled = false;
- document.getElementById("chat-textbox").focus();
- });
- }
- } else if (replying.style.display === 'unset') { // replying
- const body = document.getElementById('chat-textbox').value.trim();
- const content = {
- body: `> <${replyingToEvent.sender}> ${replyingToEvent.body}` + '\n\n' + body,
- format: 'org.matrix.custom.html',
- formatted_body: `<mx-reply><blockquote><a href=\"https://matrix.to/#/${currentRoom}/${replyingToEvent.eventId}">In reply to</a> <a href="https://matrix.to/#/${replyingToEvent.sender}">${replyingToEvent.sender}</a><br>${replyingToEvent.body}</blockquote></mx-reply>${body}`,
- msgtype: "m.text",
- 'm.relates_to': {
- 'm.in_reply_to': {
- event_id: replyingToEvent.eventId,
- },
- },
- };
- if (body !== '') {
- const date = new Date();
- const tnxId = date.getTime()/1000;
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "ENTER";
- window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
- const room = window.mClient.getRoom(currentRoom);
- const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
- const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
- const datetimeMsg = document.getElementById(`datetime-~${room.roomId}:${tnxId}`);
- newMsg.id = `msg-${event_id}`;
- newInnerMsg.id = `innermsg-${event_id}`;
- datetimeMsg.id = `datetime-${event_id}`;
- datetimeMsg.innerHTML = datetimeMsg.getAttribute('datetime');
- return;
- }).catch((err) => {
- alert('Failed to send message: ' + err.message);
- if(err.name === 'UnknownDeviceError') {
- verifyDevices();
- }
- console.log(err);
- });
- document.getElementById('chat-textbox').value = '';
- document.getElementById("chat-textbox").style.height = "24px";
- document.getElementById('chat-textbox').selectionStart = 0
- document.getElementById('conversation').style.height = '100%';
- document.getElementById('editing').style.bottom = "55px";
- replying.style.display = 'none';
- replyingToEvent = null;
- }
- } else {
- const body = document.getElementById('chat-textbox').value.trim();
- const content = {
- body,
- msgtype: "m.text"
- };
- if (body !== '') {
- // document.getElementById("chat-textbox").blur();
- // document.getElementById("chat-textbox").disabled = true;
- // document.getElementById("left").innerHTML = "";
- // document.getElementById("right").innerHTML = "";
- // document.getElementById("middle").innerHTML = "SENDING...";
- const date = new Date();
- const tnxId = date.getTime()/1000;
- window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
- const room = window.mClient.getRoom(currentRoom);
- const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
- const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
- const datetimeMsg = document.getElementById(`datetime-~${room.roomId}:${tnxId}`);
- newMsg.id = `msg-${event_id}`;
- newInnerMsg.id = `innermsg-${event_id}`;
- datetimeMsg.id = `datetime-${event_id}`;
- datetimeMsg.innerHTML = datetimeMsg.getAttribute('datetime');
- return;
- }).catch((err) => {
- alert('Failed to send message: ' + err.message);
- if(err.name === 'UnknownDeviceError') {
- verifyDevices();
- }
- });
- document.getElementById('chat-textbox').value = '';
- document.getElementById("chat-textbox").style.height = "24px";
- document.getElementById('chat-textbox').selectionStart = 0
- document.getElementById('conversation').style.height = '100%';
- document.getElementById('replying').style.bottom = "55px";
- }
- }
- } else if ((e.key === "SoftRight" || e.key === "Shift") && page === 'chat' && document.getElementById("right").innerHTML !== '') { // cancel edit
- if(editing.style.display === 'unset' || replying.style.display === 'unset') {
- editing.style.display = 'none';
- replying.style.display = 'none';
- document.getElementById('chat-textbox').value = '';
- document.getElementById('chat-textbox').selectionStart = 0
- document.getElementById("chat-textbox").style.height = "24px";
- document.getElementById('editing').style.bottom = "55px";
- document.getElementById('replying').style.bottom = "55px";
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "ENTER";
- editingEvent = null;
- replyingToEvent = null;
- const msg = document.getElementsByClassName('msgItem msgItem-selected')[0];
- msg.className = 'msgItem';
- highlightedMsg = null;
- } else {
- mainMenu = [
- {
- label: 'Send Attachment',
- fn: () => {
- new Promise((res, rej) => {
- try {
- const file = new MozActivity({name: 'pick'});
- file.onsuccess = function () {
- const f = this.result;
- res(f);
- };
- reader.onerror = function(e) {
- alert('Failed to read file.');
- };
- file.onerror = function() {
- alert('Failed to select file.');
- };
- } catch {
- var input = document.createElement('input');
- input.type = 'file';
- input.onchange = e => {
- var f = e.target.files[0];
- res(f);
- }
- input.click();
- }
- }).then((f) => {
- new Promise((res, rej) => {
- if(f.type.indexOf('image') > -1) {
- const reader = new FileReader();
- reader.onload = () => {
- const img = new Image();
- img.onload = () => {
- return res(img);
- };
- img.src = reader.result;
- };
- reader.readAsDataURL(f);
- } else {
- res(null);
- }
- }).then((img) => {
- closeMenu(backToChat);
- uploadContent(f, img).then((content) => {
- const date = new Date();
- const tnxId = date.getTime()/1000;
- window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
- const room = window.mClient.getRoom(currentRoom);
- const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
- const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
- const img = document.getElementById(`image-~${room.roomId}:${tnxId}`);
- const datetimeMsg = document.getElementById(`datetime-~${room.roomId}:${tnxId}`);
- newMsg.id = `msg-${event_id}`;
- newInnerMsg.id = `innermsg-${event_id}`;
- datetimeMsg.id = `datetime-${event_id}`;
- datetimeMsg.innerHTML = datetimeMsg.getAttribute('datetime');
- img.id = `image-${event_id}`
- }).catch((e) => {
- console.log(e);
- });
- });
- });
- });
- },
- },
- {
- label: 'Insert ☺️',
- fn: insertIntoTextbox('☺️'),
- },
- {
- label: 'Insert 😛️',
- fn: insertIntoTextbox('😛️️'),
- },
- {
- label: 'Insert 😕️',
- fn: insertIntoTextbox('😕️️'),
- },
- {
- label: 'Insert 👉👈',
- fn: insertIntoTextbox('👉👈'),
- },
- {
- label: 'Insert 👀',
- fn: insertIntoTextbox('👀'),
- },
- {
- label: 'Insert 🤔',
- fn: insertIntoTextbox('🤔'),
- },
- ];
- previousPage = 'chat';
- openMenu();
- }
- }
- } else {
- e.preventDefault();
- switch (e.key) {
- case "F1":
- case "Call": {
- if(page === 'chat') {
- const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
- if(msgItem) {
- const eventId = msgItem.id.substring(4);
- const innerMsg = document.getElementById(`innermsg-${eventId}`);
- let msg = innerMsg.innerText.trim();
- if(innerMsg.getElementsByClassName('edited-marker').length > 0) {
- msg = msg.slice(0, -9); // removed the "\n(edited)" part
- }
- const replying = document.getElementById('replying');
- replying.style.display = 'unset';
- replyingToEvent = {
- eventId,
- sender: msgItem.getAttribute('sender'),
- body: msg,
- };
- const chatBox = document.getElementById('chat-textbox');
- chatBox.focus();
- highlightedMsg += 1;
- if(chatBox.scrollHeight < 122) {
- chatBox.style.height = "auto";
- chatBox.style.height = (chatBox.scrollHeight) + "px";
- document.getElementById('editing').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- document.getElementById('replying').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- }
- }
- }
- return;
- }
- case "End":
- case "EndCall": {
- const chatBox = document.getElementById('chat-textbox');
- if(chatBox && chatBox.value !== '') {
- if(confirm('Are you sure you want to close the app?')) {
- window.mClient.stopClient();
- close();
- }
- return;
- }
- window.mClient.stopClient();
- close();
- return;
- }
- case "Backspace": {
- if(page === 'chat') {
- if(navigator.b2g && navigator.b2g.virtualCursor.enabled) {
- navigator.b2g.virtualCursor.disable();
- } else {
- gotoRoomView();
- }
- } else if (page === 'image') {
- const player = document.getElementById('big-video');
- if(player) {
- if(document.fullscreenElement && document.fullscreenElement !== null) {
- return document.exitFullscreen();
- }
- player.removeEventListener('ended', swapMiddle);
- }
- const conv = document.getElementById('conversation');
- conv.innerHTML = previousConv;
- previousConv = null;
- page = 'chat'
- if(currentlyWatching) {
- URL.revokeObjectURL(currentlyWatching);
- currentlyWatching = null;
- }
- const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
- if(msgItem) {
- msgItem.scrollIntoView({
- behavor: 'smooth',
- block: 'center',
- inline: 'nearest'
- });
- }
- document.getElementById("left").innerHTML = "Reply";
- document.getElementById("right").innerHTML = "Edit";
- document.getElementById("middle").innerHTML = "SELECT";
- } else if (page === 'menu') {
- if(previousPage === 'rooms') {
- closeMenu(gotoRoomView);
- } else {
- closeMenu(backToChat)
- }
- }
- return;
- }
- case "Enter": {
- if(page === 'rooms') {
- gotoChat();
- page = 'chat';
- } else if(page === 'chat') {
- const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
- if(msgItem) {
- const eventId = msgItem.id.substring(4);
- const image = document.getElementById(`image-${eventId}`)
- if(image) {
- const video = image.getAttribute('video');
- const audio = image.getAttribute('audio');
- if(video) {
- document.getElementById('left').innerHTML = 'Fullscreen'
- document.getElementById('middle').innerHTML = 'PLAY'
- document.getElementById('right').innerHTML = 'Mute'
- const content = JSON.parse(video);
- const imageUrl = content.url ? window.mClient.mxcUrlToHttp(content.url) : window.mClient.mxcUrlToHttp(content.file.url);
- loadingHandler();
- fetch(imageUrl).then((res) => {
- res.arrayBuffer().then((a) => {
- const uploading = document.getElementById('uploading');
- if(uploading) {
- uploading.style.display = 'none';
- }
- if(content.file) {
- decryptAttachment(a, content.file).then((dataArray) => {
- let mimetype = content.info.mimetype ? content.info.mimetype.split(";")[0].trim() : '';
- mimetype = getBlobSafeMimeType(mimetype);
- const blob = new Blob([dataArray], { type: mimetype });
- const blobUrl = URL.createObjectURL(blob);
- currentlyWatching = blobUrl;
- const conv = document.getElementById('conversation');
- previousConv = conv.innerHTML;
- conv.innerHTML = `
- <video id="big-video"/>
- <source src="${blobUrl}">
- Unsupported Video
- </video>
- `;
- page = 'image';
- });
- } else {
- let mimetype = content.info.mimetype ? content.info.mimetype.split(";")[0].trim() : '';
- mimetype = getBlobSafeMimeType(mimetype);
- const blob = new Blob([a], { type: mimetype });
- const blobUrl = URL.createObjectURL(blob);
- currentlyWatching = blobUrl;
- const conv = document.getElementById('conversation');
- previousConv = conv.innerHTML;
- conv.innerHTML = `
- <video id="big-video"/>
- <source src="${blobUrl}">
- Unsupported Video
- </video>
- `;
- page = 'image';
- }
- });
- });
- } else if (audio) {
- const content = JSON.parse(audio);
- const imageUrl = content.url ? window.mClient.mxcUrlToHttp(content.url) : window.mClient.mxcUrlToHttp(content.file.url);
- document.getElementById('left').innerHTML = 'Fullscreen'
- document.getElementById('middle').innerHTML = 'PLAY'
- document.getElementById('right').innerHTML = 'Mute'
- loadingHandler();
- fetch(imageUrl).then((res) => {
- res.arrayBuffer().then((a) => {
- const uploading = document.getElementById('uploading');
- if(uploading) {
- uploading.style.display = 'none';
- }
- if(content.file) {
- decryptAttachment(a, content.file).then((dataArray) => {
- let mimetype = content.info.mimetype ? content.info.mimetype.split(";")[0].trim() : '';
- mimetype = getBlobSafeMimeType(mimetype);
- const blob = new Blob([dataArray], { type: mimetype });
- const blobUrl = URL.createObjectURL(blob);
- currentlyWatching = blobUrl;
- const conv = document.getElementById('conversation');
- previousConv = conv.innerHTML;
- conv.innerHTML = `
- <audio id="big-video"/>
- <source src="${blobUrl}">
- Unsupported Video
- </audio>
- `;
- page = 'image';
- });
- } else {
- let mimetype = content.info.mimetype ? content.info.mimetype.split(";")[0].trim() : '';
- mimetype = getBlobSafeMimeType(mimetype);
- const blob = new Blob([a], { type: mimetype });
- const blobUrl = URL.createObjectURL(blob);
- currentlyWatching = blobUrl;
- const conv = document.getElementById('conversation');
- previousConv = conv.innerHTML;
- conv.innerHTML = `
- <audio id="big-video"/>
- <source src="${blobUrl}">
- Unsupported Video
- </audio>
- `;
- page = 'image';
- }
- })
- });
- } else {
- const imageUrl = image.getAttribute('src');
- const conv = document.getElementById('conversation');
- previousConv = conv.innerHTML;
- conv.innerHTML = `<img id="big-image" src="${imageUrl}"/>`;
- page = 'image';
- document.getElementById('left').innerHTML = 'Zoom Out'
- document.getElementById('middle').innerHTML = ''
- document.getElementById('right').innerHTML = 'Zoom In'
- }
- } else {
- navigator.b2g.virtualCursor.enable();
- }
- }
- } else if(page === 'menu') {
- const item = mainMenu[highlightedMenuItem];
- if(item) {
- item.fn();
- }
- } else if(page === 'image') {
- const player = document.getElementById('big-video');
- if(player) {
- if(player.paused) {
- document.getElementById('middle').innerHTML = 'PAUSE';
- player.play();
- player.addEventListener('ended', swapMiddle)
- } else {
- document.getElementById('middle').innerHTML = 'PLAY';
- player.pause();
- player.removeEventListener('ended', swapMiddle)
- }
- }
- }
- return;
- }
- case "ArrowUp": {
- if(page === 'rooms') {
- const cur = rooms[highlightedRoom];
- let num = highlightedRoom - 1
- if(num < 0) {
- num = rooms.length - 1;
- }
- const next = rooms[num];
- cur.className = "roomItem";
- next.className = "roomItem active";
- highlightedRoom = num;
- } else if(page === 'chat') {
- var msgs = document.getElementsByClassName('msgItem');
- if (highlightedMsg === 0) {
- document.getElementById('left').innerHTML = ''
- document.getElementById('middle').innerHTML = 'Loading...'
- document.getElementById('right').innerHTML = ''
- const room = window.mClient.getRoom(currentRoom);
- const timeline = room.getLiveTimeline();
- const originalLength = msgs.length;
- loadingMessagesIndex = 10;
- window.mClient.paginateEventTimeline(timeline, {backwards: true, limit: 10}).then(() => {
- document.getElementById('left').innerHTML = 'Reply'
- document.getElementById('middle').innerHTML = 'SELECT';
- document.getElementById('right').innerHTML = 'Edit'
- });
- return;
- } else if(highlightedMsg !== msgs.length) {
- msgs[highlightedMsg].className = 'msgItem';
- }
- highlightedMsg = highlightedMsg - 1;
- msgs[highlightedMsg].className = 'msgItem msgItem-selected';
- msgs[highlightedMsg].scrollIntoView({
- behavor: 'smooth',
- block: 'nearest',
- inline: 'nearest'
- });
- } else if (page === 'image') {
- const conv = document.getElementById('conversation');
- conv.scrollBy({
- top: -100,
- });
- } else if (page === 'menu') {
- const menuItems = document.getElementsByClassName('menuItem');
- const cur = menuItems[highlightedMenuItem];
- let num = highlightedMenuItem - 1
- if(num < 0) {
- num = menuItems.length - 1;
- }
- const next = menuItems[num];
- cur.className = "menuItem";
- next.className = "menuItem active";
- highlightedMenuItem = num;
- }
- return;
- }
- case "ArrowDown": {
- if(page === 'rooms') {
- const cur = rooms[highlightedRoom];
- let num = highlightedRoom + 1
- if(num > rooms.length - 1) {
- num = 0;
- }
- const next = rooms[num];
- cur.className = "roomItem";
- next.className = "roomItem active";
- highlightedRoom = num;
- } else if (page === 'chat') {
- var msgs = document.getElementsByClassName('msgItem');
- var mNext = highlightedMsg + 1;
- if(mNext === msgs.length && !scrollMsg) {
- msgs[highlightedMsg].className = 'msgItem';
- highlightedMsg = msgs.length;
- document.getElementById('chat-textbox').focus();
- } else {
- if ((msgs[mNext] && msgs[mNext].clientHeight > document.getElementById('conversation').clientHeight) || scrollMsg) {
- if(!scrollMsg) {
- scrollMsg = msgs[mNext].clientHeight;
- document.getElementById('conversation').scrollBy({
- top: 100,
- left: 0,
- behavor: 'smooth',
- });
- scrollMsg = scrollMsg - 100;
- } else if(scrollMsg <= document.getElementById('conversation').clientHeight - 100) {
- scrollMsg = null;
- } else {
- document.getElementById('conversation').scrollBy({
- top: 100,
- left: 0,
- behavor: 'smooth',
- });
- scrollMsg = scrollMsg - 100;
- return;
- }
- }
- if (mNext >= msgs.length) {
- msgs[highlightedMsg].className = 'msgItem';
- document.getElementById('chat-textbox').focus();
- } else {
- msgs[highlightedMsg].className = 'msgItem';
- highlightedMsg = mNext
- msgs[highlightedMsg].className = 'msgItem msgItem-selected';
- msgs[highlightedMsg].scrollIntoView({
- behavor: 'smooth',
- block: 'nearest',
- inline: 'nearest'
- });
- }
- }
- } else if (page === 'image') {
- const conv = document.getElementById('conversation');
- conv.scrollBy({
- top: 100,
- });
- } else if (page === 'menu') {
- const menuItems = document.getElementsByClassName('menuItem');
- const cur = menuItems[highlightedMenuItem];
- let num = highlightedMenuItem + 1
- if(num === menuItems.length) {
- num = 0
- }
- const next = menuItems[num];
- cur.className = "menuItem";
- next.className = "menuItem active";
- highlightedMenuItem = num;
- }
- return;
- }
- case "ArrowLeft": {
- if (page === 'image') {
- const conv = document.getElementById('conversation');
- conv.scrollBy({
- left: -100,
- });
- }
- return;
- }
- case "ArrowRight": {
- if (page === 'image') {
- const conv = document.getElementById('conversation');
- conv.scrollBy({
- left: 100,
- });
- }
- return;
- }
- case "Shift":
- case "SoftRight": {
- if(page === 'chat') {
- const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
- if(msgItem) {
- const eventId = msgItem.id.substring(4);
- const innerMsg = document.getElementById(`innermsg-${eventId}`);
- if(innerMsg.style['align-self'] === 'flex-end') {
- let msg = innerMsg.getAttribute('body').trim();
- document.getElementById('chat-textbox').value = msg;
- const editing = document.getElementById('editing');
- editing.style.display = 'unset';
- editingEvent = eventId;
- const chatBox = document.getElementById('chat-textbox');
- chatBox.focus();
- highlightedMsg += 1;
- if(chatBox.scrollHeight < 122) {
- chatBox.style.height = "auto";
- chatBox.style.height = (chatBox.scrollHeight) + "px";
- document.getElementById('editing').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- document.getElementById('replying').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- }
- }
- }
- } else if (page === 'image') {
- const image = document.getElementById('big-image');
- const player = document.getElementById('big-video');
- if(image) {
- const height = Number(image.getAttribute('height'));
- image.setAttribute('height', 25 + (height ? height : image.scrollHeight))
- const width = Number(image.getAttribute('width'));
- image.setAttribute('width', 25 + (width ? width : image.scrollWidth));
- } else if(player) {
- if(player.muted) {
- document.getElementById("right").innerHTML = "Mute";
- player.muted = false;
- } else {
- document.getElementById("right").innerHTML = "Unmute";
- player.muted = true;
- }
- }
- } else if (page === 'rooms') {
- mainMenu = [
- {
- label: 'Verify Device',
- fn: verifyDevice,
- },
- {
- label: 'Logout',
- fn: killSession,
- },
- ];
- previousPage = 'rooms';
- openMenu();
- } else if (page === 'menu') {
- if(previousPage === 'rooms') {
- closeMenu(gotoRoomView);
- } else {
- closeMenu(backToChat);
- }
- }
- return;
- }
- case "Control":
- case "SoftLeft": {
- if(page === 'chat') {
- const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
- if(msgItem) {
- const eventId = msgItem.id.substring(4);
- const innerMsg = document.getElementById(`innermsg-${eventId}`);
- let msg = innerMsg.innerText.trim();
- if(innerMsg.getElementsByClassName('edited-marker').length > 0) {
- msg = msg.slice(0, -9); // removed the "\n(edited)" part
- }
- const replying = document.getElementById('replying');
- replying.style.display = 'unset';
- replyingToEvent = {
- eventId,
- sender: msgItem.getAttribute('sender'),
- body: msg,
- };
- const chatBox = document.getElementById('chat-textbox');
- chatBox.focus();
- highlightedMsg += 1;
- if(chatBox.scrollHeight < 122) {
- chatBox.style.height = "auto";
- chatBox.style.height = (chatBox.scrollHeight) + "px";
- document.getElementById('editing').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- document.getElementById('replying').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
- }
- }
- } else if (page === 'image') {
- const image = document.getElementById('big-image');
- const player = document.getElementById('big-video');
- if(image) {
- const height = Number(image.getAttribute('height'));
- image.setAttribute('height', (height ? height : image.scrollHeight) - 25 )
- const width = Number(image.getAttribute('width'));
- image.setAttribute('width', (width ? width : image.scrollWidth) - 25);
- } else if (player) {
- if(document.fullscreenElement && document.fullscreenElement !== null) {
- document.exitFullscreen();
- } else {
- player.requestFullscreen();
- }
- }
- }
- return;
- }
- case "1": {
- sendReaction('👍');
- return;
- }
- case "2": {
- sendReaction('👎');
- return;
- }
- case "3": {
- sendReaction('❤️');
- return;
- }
- case "4": {
- sendReaction('🔥');
- return;
- }
- case "5": {
- sendReaction('😁');
- return;
- }
- case "6": {
- sendReaction('🎉');
- return;
- }
- case "7": {
- sendReaction('🤣');
- return;
- }
- case "8": {
- sendReaction('🤔');
- return;
- }
- case "9": {
- sendReaction('🤯');
- return;
- }
- case "0": {
- sendReaction('👀');
- return;
- }
- case "#": {
- sendReaction('😭');
- return;
- }
- case "*": {
- sendReaction('💩');
- return;
- }
- }
- }
- };
- document.addEventListener("DOMContentLoaded", async () => {
- const session = localStorage.getItem(LOCAL_STORAGE_SESSION_KEY);
- if(session) {
- const client = JSON.parse(session);
- prepareSession(client);
- } else {
- document.getElementById("title-text").innerHTML = 'Login';
- document.getElementById("login").style = 'display: unset';
- document.getElementById("left").innerHTML = "";
- document.getElementById("right").innerHTML = "";
- document.getElementById("middle").innerHTML = "LOGIN";
- document.getElementById('homeserver').focus();
- }
- const chatBox = document.getElementById('chat-textbox');
- chatBox.addEventListener("focus", (e) => {
- const editing = document.getElementById('editing');
- const replying = document.getElementById('replying');
- if(editing.style.display === 'unset') { // is editting
- document.getElementById("left").innerHTML = "Save";
- document.getElementById("right").innerHTML = "Discard";
- document.getElementById("middle").innerHTML = "ENTER";
- } else if (replying.style.display === 'unset') {
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Discard";
- document.getElementById("middle").innerHTML = "ENTER";
- } else { // new msg
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "ENTER";
- const scrollHeight = document.getElementById("conversation").scrollHeight;
- document.getElementById("conversation").scrollTo(0, scrollHeight);
- }
- });
- chatBox.addEventListener("blur", (e) => {
- if(page === 'chat') {
- document.getElementById("left").innerHTML = "Reply";
- document.getElementById("right").innerHTML = "Edit";
- document.getElementById("middle").innerHTML = "SELECT";
- }
- });
- // auto resize the text boxes
- const tx = document.getElementsByTagName("textarea");
- for (let i = 0; i < tx.length; i++) {
- tx[i].setAttribute("style", "height:24px;overflow-y:hidden;");
- tx[i].addEventListener("input", OnInput, false);
- };
- function OnInput() {
- if(this.scrollHeight < 122) {
- this.style.height = "auto";
- this.style.height = (this.scrollHeight) + "px";
- const conv = document.getElementById("conversation");
- conv.style.height = `calc(100% - ${this.scrollHeight + 52}px)`;
- if(document.getElementById('editing').style.display === 'none'
- &&
- document.getElementById('replying').style.display === 'none') {
- conv.scrollTo(0, conv.scrollHeight);
- }
- document.getElementById('editing').style.bottom = (this.scrollHeight + 55 - 29) + "px";
- document.getElementById('replying').style.bottom = (this.scrollHeight + 55 - 29) + "px";
- }
- };
- });
- const gotoChat = () => {
- const roomEl = document.getElementsByClassName('roomItem active')[0];
- const id = roomEl.id.substring(5);
- const room = window.mClient.getRoom(id);
- // const timeline = room.getLiveTimeline();
- // const rest = window.mClient.paginateEventTimeline(timeline, {backwards: true}).then((d) => {
- const events = window.mClient.getRoom(id).timeline;
- var relations = [];
- const eventList = events.reduce((a, event) => {
- const relation = event.getRelation();
- if(relation) {
- relations.push({event, relation});
- return a + '';
- }
- if (event.getType() === 'm.room.message') {
- // window.mClient.decryptEventIfNeeded(event, {isRetry: false, emit: true}).then((d) => {
- // const events = window.mClient.getRoom(id).timeline;
- // console.log('DECRYPTED: ', d);
- // })
- return a + messageBuilder(event, room);
- }
- return a + '';
- }, '');
- document.getElementById("conversation").innerHTML = eventList;
- relations.forEach(({event, relation}) => {
- const {
- event_id,
- rel_type,
- } = relation;
- const msgItem = document.getElementById(`msg-${event_id}`);
- if(msgItem) {
- if(rel_type === 'm.annotation') {
- markReaction(event, relation);
- } else if(rel_type === 'm.replace') {
- replaceBody(event, relation);
- }
- }
- return;
- });
- document.getElementById('room-menu').style = 'display: none';
- document.getElementById('chat').style = 'display: flex';
- document.getElementById('chat-textbox').value = '';
- document.getElementById('chat-textbox').focus();
- document.getElementById("title-text").innerHTML = room.name;
- document.getElementById("left").innerHTML = "Send";
- document.getElementById("right").innerHTML = "Menu";
- document.getElementById("middle").innerHTML = "ENTER";
- setTimeout(() => {
- const scrollHeight = document.getElementById("conversation").scrollHeight;
- document.getElementById("conversation").scrollTo(0, scrollHeight);
- }, 500);
- currentRoom = id;
- };
- document.addEventListener("keydown", keydownListener);
- document.addEventListener('click', (event) => {
- if(event.target.localName === 'a') {
- if(confirm('Open in popup?')) {
- event.preventDefault();
- window.open(event.target.href);
- }
- }
- });
|