mirror of https://gitgud.io/fatchan/jschan.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
6.9 KiB
206 lines
6.9 KiB
!localStorage.getItem('live') ? localStorage.setItem('live', true) : void 0;
|
|
!localStorage.getItem('notifications') ? localStorage.setItem('notifications', false) : void 0;
|
|
!localStorage.getItem('scroll') ? localStorage.setItem('scroll', false) : void 0;
|
|
|
|
const isThread = /\/\w+\/thread\/\d+.html/.test(window.location.pathname);
|
|
let socket;
|
|
|
|
window.addEventListener('settingsReady', function(event) { //after domcontentloaded
|
|
|
|
const livecolor = document.getElementById('livecolor');
|
|
const livetext = isThread ? document.getElementById('livetext').childNodes[1] : null;
|
|
const updateLive = (message, color) => {
|
|
livecolor.style.backgroundColor = color;
|
|
livetext.nodeValue = message;
|
|
}
|
|
|
|
const startLive = () => {
|
|
const anchors = document.getElementsByClassName('anchor');
|
|
if (anchors.length === 0) {
|
|
return; //url matches, but on a 404 page so dont bother with the rest
|
|
}
|
|
let lastPostId = anchors[anchors.length - 1].id;
|
|
const newPost = (data) => {
|
|
console.log('got new post');
|
|
lastPostId = data.postId;
|
|
const postData = data;
|
|
//create a new post
|
|
const postHtml = post({ post: postData });
|
|
//add it to the end of the thread
|
|
thread.insertAdjacentHTML('beforeend', postHtml);
|
|
for (let j = 0; j < postData.quotes.length; j++) {
|
|
const quoteData = postData.quotes[j];
|
|
//add backlink to quoted posts
|
|
const quotedPost = document.getElementById(quoteData.postId).nextSibling;
|
|
let replies = quotedPost.querySelector('.replies');
|
|
if (!replies) {
|
|
const quotedPostData = quotedPost.querySelector('.post-data');
|
|
const newRepliesDiv = document.createElement('div');
|
|
newRepliesDiv.textContent = 'Replies: ';
|
|
['replies', 'mt-5', 'ml-5'].forEach(c => {
|
|
newRepliesDiv.classList.add(c);
|
|
});
|
|
quotedPostData.appendChild(newRepliesDiv);
|
|
replies = newRepliesDiv;
|
|
}
|
|
if (new RegExp(`>>${postData.postId}(\s|$)`).test(replies.innerText)) {
|
|
//reply link already exists (probably from a late catch up
|
|
continue;
|
|
}
|
|
const newReply = document.createElement('a');
|
|
const space = document.createTextNode(' ');
|
|
newReply.href = `${window.location.pathname}#${postData.postId}`;
|
|
newReply.textContent = `>>${postData.postId}`;
|
|
newReply.classList.add('quote');
|
|
replies.appendChild(newReply);
|
|
replies.appendChild(space);
|
|
}
|
|
const newPostAnchor = document.getElementById(postData.postId);
|
|
const newPost = newPostAnchor.nextSibling;
|
|
if (scrollEnabled) {
|
|
newPostAnchor.scrollIntoView(); //scroll to post if enabled;
|
|
}
|
|
if (notificationsEnabled) {
|
|
new Notification(document.title, {
|
|
body: postData.nomarkup.substring(0,100)
|
|
});
|
|
}
|
|
const newPostEvent = new CustomEvent('addPost', {
|
|
detail: {
|
|
post: newPost,
|
|
postId: postData.postId
|
|
}
|
|
});
|
|
//dispatch the event so quote click handlers, image expand, etc can be added in separate scripts by listening to the event
|
|
window.dispatchEvent(newPostEvent);
|
|
}
|
|
const jsonPath = window.location.pathname.replace(/\.html$/, '.json');
|
|
const jsonCatchup = async () => {
|
|
console.log('catching up after reconnect');
|
|
updateLive('Checking for missed posts...', 'yellow');
|
|
let json;
|
|
try {
|
|
json = await fetch(jsonPath).then(res => res.json());
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
if (json && json.replies && json.replies.length > 0) {
|
|
const newPosts = json.replies.filter(r => r.postId > lastPostId); //filter to only newer posts
|
|
if (newPosts.length > 0) {
|
|
for (let i = 0; i < newPosts.length; i++) {
|
|
newPost(newPosts[i]);
|
|
}
|
|
}
|
|
}
|
|
setTimeout(() => {
|
|
updateLive('Connected for live posts', '#0de600');
|
|
}, 1000);
|
|
}
|
|
const roomParts = window.location.pathname.replace(/\.html$/, '').split('/');
|
|
const room = `${roomParts[1]}-${roomParts[3]}`;
|
|
const thread = document.querySelector('.thread');
|
|
socket = io({ transports: ['websocket'] }); //no polling
|
|
socket.on('connect', () => {
|
|
console.log('joined room', room);
|
|
updateLive('Connected for live posts', '#0de600');
|
|
socket.emit('room', room);
|
|
});
|
|
socket.on('pong', (latency) => {
|
|
if (socket.connected) {
|
|
updateLive(`Connected for live posts (${latency}ms)`, '#0de600');
|
|
}
|
|
});
|
|
socket.on('reconnect_error', () => {
|
|
updateLive('Error reconnecting', 'orange');
|
|
});
|
|
socket.on('reconnect_attempt', () => {
|
|
updateLive('Attempting to reconnect...', 'yellow');
|
|
});
|
|
socket.on('disconnect', () => {
|
|
console.log('lost connection to room');
|
|
updateLive('Disconnected', 'red');
|
|
});
|
|
socket.on('reconnect', () => {
|
|
console.log('reconnected to room');
|
|
jsonCatchup();
|
|
});
|
|
socket.on('newPost', newPost);
|
|
}
|
|
|
|
let liveEnabled = localStorage.getItem('live') == 'true';
|
|
let notificationsEnabled = localStorage.getItem('notifications') == 'true';
|
|
let scrollEnabled = localStorage.getItem('scroll') == 'true';
|
|
|
|
const liveSetting = document.getElementById('live-setting');
|
|
const notificationSetting = document.getElementById('notification-setting');
|
|
const scrollSetting = document.getElementById('scroll-setting');
|
|
|
|
const toggleLive = () => {
|
|
if (isThread) {
|
|
if (socket && liveEnabled) {
|
|
socket.disconnect();
|
|
updateLive('Live posts disabled', 'red');
|
|
} else if (!socket) {
|
|
startLive();
|
|
} else {
|
|
socket.connect();
|
|
}
|
|
}
|
|
liveEnabled = !liveEnabled;
|
|
if (!liveEnabled) {
|
|
//disable notifications and scroll when live off because they wont work
|
|
if (notificationsEnabled) {
|
|
notificationSetting.checked = false;
|
|
toggleNotifications(null, true);
|
|
}
|
|
if (scrollEnabled) {
|
|
scrollSetting.checked = false;
|
|
toggleScroll(null, true);
|
|
}
|
|
}
|
|
console.log('toggling live posts', liveEnabled);
|
|
localStorage.setItem('live', liveEnabled);
|
|
}
|
|
liveSetting.checked = liveEnabled;
|
|
liveSetting.addEventListener('change', toggleLive, false);
|
|
|
|
const toggleNotifications = async (change, changeFromConflict) => {
|
|
notificationsEnabled = !notificationsEnabled;
|
|
if (notificationsEnabled) {
|
|
const result = await Notification.requestPermission()
|
|
if (result != 'granted') {
|
|
//user denied permission popup
|
|
notificationsEnabled = false;
|
|
}
|
|
}
|
|
console.log('toggling notifications', notificationsEnabled);
|
|
localStorage.setItem('notifications', notificationsEnabled);
|
|
if (!liveEnabled && !changeFromConflict) {
|
|
liveSetting.checked = true;
|
|
toggleLive();
|
|
}
|
|
}
|
|
notificationSetting.checked = notificationsEnabled;
|
|
notificationSetting.addEventListener('change', toggleNotifications, false);
|
|
|
|
const toggleScroll = (change, changeFromConflict) => {
|
|
scrollEnabled = !scrollEnabled;
|
|
console.log('toggling post scrolling', scrollEnabled);
|
|
localStorage.setItem('scroll', scrollEnabled);
|
|
if (!liveEnabled && !changeFromConflict) {
|
|
liveSetting.checked = true;
|
|
toggleLive();
|
|
}
|
|
}
|
|
scrollSetting.checked = scrollEnabled;
|
|
scrollSetting.addEventListener('change', toggleScroll, false);
|
|
|
|
if (isThread) {
|
|
if (liveEnabled) {
|
|
startLive();
|
|
} else {
|
|
updateLive('Live posts disabled', 'red');
|
|
}
|
|
}
|
|
|
|
});
|
|
|