10
|
1 'use strict';
|
|
2
|
18
|
3 let title = document.title;
|
10
|
4 let currentChatId = null;
|
12
|
5 let eventSource;
|
30
|
6 let lastUpdate;
|
31
|
7 let hasUnseen = false;
|
35
|
8 let userId;
|
10
|
9
|
16
|
10 function evalEvent(event) {
|
17
|
11 // console.log(event);
|
16
|
12 eval(event.data);
|
|
13 }
|
|
14
|
15
|
15 function setUserEventSource(userId) {
|
|
16 let userEventSource = new EventSource(`${location.origin}/user/${userId}`);
|
16
|
17 userEventSource.onmessage = evalEvent;
|
15
|
18 }
|
|
19
|
10
|
20 function selectChat(div) {
|
27
|
21 document.querySelector('div[content]').setAttribute('show','posts');
|
10
|
22 let chatId = div.getAttribute('chat');
|
|
23 if( chatId === currentChatId )
|
|
24 return;
|
|
25 let selected = div.parentNode.querySelector('[selected]');
|
|
26 if( selected ) selected.removeAttribute('selected');
|
|
27 div.setAttribute('selected','');
|
|
28 ajax(`get_chat.js?chat=${chatId}`);
|
|
29 currentChatId = chatId;
|
34
|
30 let email = div.querySelector('[email]').textContent;
|
|
31 history.replaceState(null,null,`?with=${email}`);
|
12
|
32
|
|
33 if(eventSource) eventSource.close();
|
|
34 eventSource = new EventSource(`${location.origin}/chat/${chatId}`);
|
16
|
35 eventSource.onmessage = evalEvent;
|
12
|
36 }
|
|
37
|
27
|
38 function back() {
|
|
39 document.querySelector('div[content]').setAttribute('show','chats');
|
|
40 }
|
|
41
|
12
|
42 function gotChat(html) {
|
|
43 document.querySelector('div[posts]').innerHTML = html;
|
19
|
44 fixPosts();
|
12
|
45 document.querySelector('div[input] textarea').focus();
|
|
46 document.querySelector('div[input]').scrollIntoView({block: 'end'});
|
10
|
47 }
|
|
48
|
|
49 function fixTextarea(event) {
|
|
50 let textarea = event.target;
|
|
51 textarea.style.height = 'initial';
|
|
52 textarea.style.height = (textarea.scrollHeight+2) + 'px';
|
|
53 textarea.scrollIntoViewIfNeeded(false);
|
|
54 }
|
|
55
|
|
56 const isMobile = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
|
|
57
|
|
58 function addPost() {
|
|
59 let textarea = document.querySelector('div[input] textarea');
|
|
60 let text = textarea.value;
|
|
61 if( text.trim() === '' )
|
|
62 return;
|
24
|
63 ajax(`add_post.js?chat=${currentChatId}`,`content=${encodeURIComponent(text)}`);
|
10
|
64 textarea.value = '';
|
|
65 }
|
|
66
|
|
67 function textareaKey(event) {
|
|
68 if( event.keyCode===13 && !event.shiftKey && !event.ctrlKey && !isMobile ) {
|
|
69 event.preventDefault();
|
|
70 addPost();
|
|
71 }
|
|
72 }
|
|
73
|
19
|
74 function fixPosts() {
|
35
|
75 let divs = document.querySelectorAll('div[post][fix]');
|
19
|
76 for( let div of divs ) {
|
35
|
77 let whenSpan = div.querySelector('span[when]');
|
39
|
78 whenSpan.textContent = new Date(Number(whenSpan.textContent)).toLocaleString([],{dateStyle:'short',timeStyle:'short'});
|
35
|
79 let textDiv = div.querySelector('div[text]');
|
|
80 textDiv.innerHTML = urlsToLinks(textDiv.innerHTML);
|
|
81 if( div.getAttribute('author') === userId )
|
|
82 div.querySelector('span[pulldown]').innerHTML = document.querySelector('div[hidden] span[pulldown]').innerHTML;
|
19
|
83 div.removeAttribute('fix');
|
|
84 }
|
10
|
85 }
|
11
|
86
|
|
87 function deleteChat() {
|
20
|
88 let dialog = document.querySelector('dialog[delete_chat]');
|
|
89 openModal(dialog);
|
|
90 }
|
|
91
|
|
92 function doDeleteChat(el) {
|
|
93 closeModal(el);
|
11
|
94 ajax(`delete_chat.js?chat=${currentChatId}`);
|
|
95 }
|
12
|
96
|
23
|
97 let currentPostId;
|
|
98
|
38
|
99 function getPostId(el) {
|
|
100 while(true) {
|
|
101 let postId = el.getAttribute('post');
|
|
102 if( postId )
|
|
103 return postId;
|
|
104 el = el.parentNode;
|
|
105 }
|
|
106 }
|
|
107
|
|
108 function deletePost(el) {
|
|
109 currentPostId = getPostId(el);
|
23
|
110 let dialog = document.querySelector('dialog[delete_post]');
|
|
111 openModal(dialog);
|
|
112 }
|
|
113
|
|
114 function doDeletePost(el) {
|
|
115 closeModal(el);
|
|
116 ajax(`delete_post.js?post=${currentPostId}`);
|
|
117 }
|
|
118
|
|
119 function deleted(postId) {
|
|
120 let div = document.querySelector(`div[post="${postId}"]`);
|
|
121 if( div )
|
|
122 div.outerHTML = '';
|
|
123 }
|
|
124
|
38
|
125 function editPost(el) {
|
|
126 ajax(`edit_post.js?post=${getPostId(el)}`);
|
24
|
127 }
|
|
128
|
|
129 function openEditPost(postId,text) {
|
|
130 currentPostId = postId;
|
|
131 let dialog = document.querySelector('dialog[edit_post]');
|
|
132 let textarea = dialog.querySelector('textarea');
|
|
133 textarea.value = text;
|
|
134 openModal(dialog);
|
|
135 }
|
|
136
|
|
137 function savePost(el) {
|
|
138 let text = document.querySelector('dialog[edit_post] textarea').value;
|
|
139 closeModal(el);
|
|
140 ajax(`save_post.js?post=${currentPostId}`,`content=${encodeURIComponent(text)}`);
|
|
141 }
|
|
142
|
|
143 function edited(postId,html) {
|
|
144 let div = document.querySelector(`div[post="${postId}"]`);
|
|
145 if( div ) {
|
|
146 div.outerHTML = html;
|
|
147 fixPosts();
|
|
148 }
|
|
149 }
|
|
150
|
12
|
151 function added(html) {
|
|
152 let input = document.querySelector('div[input]');
|
|
153 input.insertAdjacentHTML('beforebegin',html);
|
19
|
154 fixPosts();
|
12
|
155 input.scrollIntoView({block: 'end'});
|
|
156 }
|
15
|
157
|
30
|
158 function getChats(chatId,updated) {
|
15
|
159 let first = document.querySelector('div[chat]');
|
|
160 if( !first || first.getAttribute('chat') != chatId ) {
|
|
161 // console.log('getChats');
|
|
162 ajax('get_chats.js');
|
|
163 }
|
30
|
164 if( updated )
|
|
165 lastUpdate = updated;
|
31
|
166 if( !document.hasFocus() && !hasUnseen ) {
|
|
167 document.title = title + ' *';
|
|
168 notify();
|
|
169 hasUnseen = true;
|
|
170 }
|
15
|
171 }
|
|
172
|
|
173 function gotChats(html) {
|
|
174 document.querySelector('div[chats]').innerHTML = html;
|
|
175 if( currentChatId ) {
|
|
176 let current = document.querySelector(`div[chat="${currentChatId}"]`);
|
16
|
177 if( current ) {
|
|
178 current.setAttribute('selected','');
|
|
179 current.scrollIntoViewIfNeeded(false);
|
|
180 } else {
|
|
181 currentChatId = null;
|
|
182 document.querySelector('div[posts]').innerHTML = '';
|
|
183 }
|
15
|
184 }
|
|
185 }
|
18
|
186
|
|
187 window.onfocus = function() {
|
33
|
188 // console.log('onfocus');
|
18
|
189 document.title = title;
|
31
|
190 hasUnseen = false;
|
18
|
191 };
|
19
|
192
|
|
193 let urlRegex = /(^|\s)(https?:\/\/\S+)/g;
|
|
194
|
|
195 function urlsToLinks(text) {
|
|
196 return text.replace( urlRegex, '$1<a href="$2">$2</a>' );
|
|
197 }
|
22
|
198
|
|
199 let currentPulldown = null;
|
|
200 let newPulldown = null;
|
|
201
|
|
202 function clickMenu(clicked,display) {
|
|
203 //console.log("clickMenu");
|
|
204 let pulldown = clicked.parentNode.querySelector('div');
|
|
205 if( pulldown !== currentPulldown ) {
|
|
206 pulldown.style.display = display || "block";
|
|
207 newPulldown = pulldown;
|
|
208 window.onclick = function() {
|
|
209 //console.log("window.onclick");
|
|
210 if( currentPulldown ) {
|
|
211 currentPulldown.style.display = "none";
|
|
212 if( !newPulldown )
|
|
213 window.onclick = null;
|
|
214 }
|
|
215 currentPulldown = newPulldown;
|
|
216 newPulldown = null;
|
|
217 };
|
|
218 pulldown.scrollIntoViewIfNeeded(false);
|
|
219 }
|
|
220 }
|
30
|
221
|
|
222 setInterval(function(){
|
33
|
223 showOnline();
|
30
|
224 ajax(`heartbeat.js?last_update=${lastUpdate}`);
|
33
|
225 }, 10000 );
|
30
|
226
|
31
|
227 let sound = new Audio('/images/notify.mp3');
|
|
228 function notify() {
|
|
229 sound.play();
|
|
230 }
|
|
231
|
33
|
232 let online = {};
|
|
233
|
|
234 function setOnline(userId) {
|
|
235 online[userId] = Date.now();
|
|
236 }
|
|
237
|
|
238 function showOnline() {
|
|
239 let old = Date.now() - 20000;
|
|
240 for( let id of Object.keys(online) ) {
|
|
241 if( online[id] < old )
|
|
242 delete online[id];
|
|
243 }
|
|
244 let a = [];
|
|
245 for( let id in online ) {
|
|
246 a.push( `span[online="${id}"]` );
|
|
247 }
|
|
248 let style = document.querySelector('style[online]');
|
|
249 if( a.length === 0 ) {
|
|
250 style.innerHTML = '';
|
|
251 } else {
|
|
252 style.innerHTML = `
|
|
253 ${a.join(', ')} {
|
|
254 background-color: green;
|
|
255 }
|
|
256 ` ;
|
|
257 }
|
|
258 }
|