let headerGotUser = false;
let savedSearches = [], lastSearches = [];
let inboxData = [];
let followRequestsData = [];
let customSet = false;
let menuFn;
let isDarkModeEnabled = typeof vars !== 'undefined' ? (vars.darkMode || (vars.timeMode && isDark())) : false;
const keysHeld = {};
const notificationBus = new BroadcastChannel('notification_bus');
notificationBus.onmessage = function (e) {
if(e.data.type === 'markAsRead') {
let notifElement = document.getElementById('notifications-count');
let icon = document.getElementById('site-icon');
notifElement.hidden = true;
icon.href = chrome.runtime.getURL(`images/logo32${vars.useNewIcon ? '_new' : ''}.png`);
if(document.title.startsWith("(")) {
document.title = document.title.split(') ').slice(1).join(') ');
}
}
};
const customCSSBus = new BroadcastChannel('custom_css_bus');
customCSSBus.onmessage = function (e) {
if(e.data.type === 'vars') {
switchDarkMode(isDarkModeEnabled);
} else if(e.data.type === 'css') {
updateCustomCSS();
} else if(e.data.type === 'color') {
if(typeof customSet === 'undefined' || !customSet) {
document.querySelector(':root').style.setProperty('--link-color', e.data.color);
}
}
};
const themeBus = new BroadcastChannel('theme_bus');
themeBus.onmessage = function (e) {
isDarkModeEnabled = e.data[0];
vars.pitchBlack = e.data[1];
switchDarkMode(isDarkModeEnabled);
}
const roundAvatarBus = new BroadcastChannel('round_avatar_bus');
roundAvatarBus.onmessage = function (e) {
switchRoundAvatars(e.data);
}
let roundAvatarsEnabled = false;
function switchRoundAvatars(enabled) {
roundAvatarsEnabled = enabled;
if(enabled) {
let style = document.createElement('style');
style.id = 'round-avatars';
style.innerHTML = `
.navbar-user-account-avatar,
.search-result-item-avatar,
.inbox-message-avatar,
.message-header-avatar,
#user-avatar,
.tweet-avatar,
.tweet-avatar-quote,
#profile-avatar,
#navbar-user-avatar,
.tweet-footer-favorites-img,
#list-avatar,
.message-element > a > img,
.notification-avatar-img,
#nav-profile-avatar {
border-radius: 50% !important;
}
`;
document.head.appendChild(style);
} else {
let style = document.getElementById('round-avatars');
if(style) style.remove();
}
}
function hideStuff() {
let hs = document.getElementById('hide-style');
if(hs) hs.remove();
let hideStyle = document.createElement('style');
hideStyle.id = 'hide-style';
if(vars.hideTrends) {
hideStyle.innerHTML += '#trends { display: none !important; }';
}
if(vars.hideWtf) {
hideStyle.innerHTML += '#wtf { display: none !important; }';
}
if(vars.hideLikes) {
hideStyle.innerHTML += `
.tweet-interact-favorite { color: var(--background-color) !important }
.tweet-interact-retweet { color: var(--background-color) !important }
.tweet-interact-reply { color: var(--background-color) !important }
.tweet:hover .tweet-interact-favorite { color: var(--dark-background-color) !important }
.tweet:hover .tweet-interact-retweet { color: var(--dark-background-color) !important }
.tweet:hover .tweet-interact-reply { color: var(--dark-background-color) !important }
`;
}
if(vars.hideFollowers) {
hideStyle.innerHTML += `
#user-followers-div { display: none !important; }
#profile-stat-followers-link { display: none !important; }
`;
}
if(hideStyle.innerHTML !== '') {
document.head.appendChild(hideStyle);
}
}
let userDataFunction = async user => {
if(headerGotUser || Object.keys(user).length === 0) return;
headerGotUser = true;
let userAvatar = document.getElementById('navbar-user-avatar');
userAvatar.src = `${(user.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(user.id_str) % 7}_normal.png`): user.profile_image_url_https}`.replace('_normal.', '_bigger.');
document.getElementById('navbar-user-menu-profile').href = `/${user.screen_name}`;
document.getElementById('navbar-user-menu-lists').href = `/${user.screen_name}/lists`;
let menuUserName = document.getElementById('navbar-user-menu-username');
menuUserName.innerText = user.name;
document.getElementById('pin-profile').hidden = !vars.pinProfileOnNavbar;
document.getElementById('pin-bookmarks').hidden = !vars.pinBookmarksOnNavbar;
document.getElementById('pin-lists').hidden = !vars.pinListsOnNavbar;
document.getElementById('pin-profile').href = `/${user.screen_name}`;
document.getElementById('pin-lists').href = `/${user.screen_name}/lists`;
if(vars.enableTwemoji) twemoji.parse(menuUserName);
let root = document.querySelector(":root");
if(!customSet && vars.linkColor) {
root.style.setProperty('--link-color', vars.linkColor);
}
if(vars.font) {
root.style.setProperty('--font', `"${vars.font}"`);
}
if(vars.tweetFont) {
root.style.setProperty('--tweet-font', `"${vars.tweetFont}"`);
}
if(vars.heartsNotStars) {
root.style.setProperty('--favorite-icon-content', '"\\f148"');
root.style.setProperty('--favorite-icon-content-notif', '"\\f015"');
root.style.setProperty('--favorite-icon-color', 'rgb(249, 24, 128)');
}
if(vars.roundAvatars) {
switchRoundAvatars(true);
}
if(vars.disableHotkeys) {
document.getElementById('navbar-tweet-button').title = '';
document.getElementById('search').title = '';
}
// util
let firstTime = false;
async function updateUnread() {
let unread = await API.notifications.getUnreadCount(firstTime);
if(!firstTime) firstTime = true;
let dms = unread.dm_unread_count;
let notifs = unread.ntab_unread_count;
let total = unread.total_unread_count;
let dmsElement = document.getElementById('messages-count');
let notifElement = document.getElementById('notifications-count');
let icon = document.getElementById('site-icon');
if(location.pathname.startsWith('/notifications')) {
notifs = 0;
}
let inboxModal = document.getElementsByClassName('inbox-modal')[0];
if(inboxModal) {
dms = 0;
}
total = dms + notifs;
if(dms > 0) {
dmsElement.hidden = false;
dmsElement.innerText = dms;
} else {
dmsElement.hidden = true;
}
if(notifs > 0) {
notifElement.hidden = false;
notifElement.innerText = notifs;
} else {
notifElement.hidden = true;
}
icon.href = total > 0 ? chrome.runtime.getURL(`images/logo32${vars.useNewIcon ? '_new' : ''}_notification.png`) : chrome.runtime.getURL(`images/logo32${vars.useNewIcon ? '_new' : ''}.png`);
if(total > 0) {
let newTitle = document.title;
if(document.title.startsWith('(')) {
newTitle = document.title.split(') ')[1];
}
newTitle = `(${total}) ${newTitle}`;
if(document.title !== newTitle) {
document.title = newTitle;
}
} else {
if(document.title.startsWith('(')) {
document.title = document.title.split(') ').slice(1).join(') ');
}
}
}
async function updateAccounts() {
let accounts = (await API.account.getAccounts()).users;
let accountsElement = document.getElementById('navbar-user-accounts');
accountsElement.innerHTML = '';
accounts.forEach(account => {
let accountElement = document.createElement('div');
accountElement.classList.add('navbar-user-account');
accountElement.innerHTML = `
${account.screen_name}`;
accountElement.addEventListener('click', async () => {
if(account.screen_name === user.screen_name) return alert("You're already on this account!");
try {
await API.account.switch(account.user_id);
window.location.reload();
} catch(e) {
if((typeof(e) === 'string' && e.includes('User not found.')) || e.errors[0].code === 50) {
window.location = 'https://twitter.com/account/switch?newtwitter=true';
} else {
alert(e);
}
console.error(e);
}
});
accountsElement.appendChild(accountElement, document.createElement('br'));
});
document.getElementById('navbar-user-menu-logout').addEventListener('click', async () => {
let modal = createModal(/*html*/`
${LOC.logout_desc_1.message}
${LOC.logout_desc_2.message}
`);
let button = modal.querySelector('button');
button.addEventListener('click', async () => {
await API.account.logout();
window.location.reload();
});
});
}
async function updateInboxData() {
inboxData = await API.inbox.get();
if(inboxData.status === "HAS_MORE" && !cursor) {
cursor = inboxData.min_entry_id;
} else {
cursor = undefined;
};
return true;
}
// follow requests
if(user.protected) {
let followRequests = document.getElementById('navbar-user-menu-requests');
let followRequestsCount = document.getElementById('follow-request-count');
followRequests.style.display = 'flex';
async function updateFollowRequests() {
let list = document.querySelector('.follow-requests-list');
let newUserData = await Promise.all(followRequestsData.ids.filter(i => typeof i === 'string').map(i => API.user.get(i)));
for(let i = 0; i < newUserData.length; i++) {
followRequestsData.ids[i] = newUserData[i];
}
for(let i in followRequestsData.ids) {
let u = followRequestsData.ids[i];
let userElement = document.createElement('div');
userElement.classList.add('follow-requests-user');
userElement.innerHTML = /*html*/`
`;
userElement.querySelector('.accept').addEventListener('click', async () => {
try {
await API.user.acceptFollowRequest(u.id_str);
} catch(e) {
console.error(e);
alert(e);
return;
}
userElement.remove();
data.ids.splice(i, 1);
let count;
if(data.total_count) {
count = --data.total_count;
} else {
count = data.ids.length;
}
if(count > 0) {
followRequestsCount.hidden = false;
followRequestsCount.innerText = count;
} else {
followRequestsCount.hidden = true;
}
});
userElement.querySelector('.decline').addEventListener('click', async () => {
try {
await API.user.declineFollowRequest(u.id_str);
} catch(e) {
console.error(e);
alert(e);
return;
}
userElement.remove();
data.ids.splice(i, 1);
let count;
if(data.total_count) {
count = --data.total_count;
} else {
count = data.ids.length;
}
if(count > 0) {
followRequestsCount.hidden = false;
followRequestsCount.innerText = count;
} else {
followRequestsCount.hidden = true;
}
});
list.appendChild(userElement);
}
}
followRequests.addEventListener('click', async () => {
let modal = createModal(/*html*/`
${LOC.load_more.message}
`, 'follow-requests-modal');
let loadMoreBtn = modal.querySelector('.requests-load-more');
if(followRequestsData.next_cursor_str !== '0') {
loadMoreBtn.hidden = false;
loadMoreBtn.addEventListener('click', async () => {
loadMoreBtn.innerText = LOC.loading.message;
loadMoreBtn.disabled = true;
API.user.getFollowRequests(followRequestsData.next_cursor_str).then(data => {
followRequestsData.ids = followRequestsData.ids.concat(data.ids);
followRequestsData.next_cursor_str = data.next_cursor_str;
updateFollowRequests();
});
});
} else {
loadMoreBtn.hidden = true;
}
updateFollowRequests();
});
API.user.getFollowRequests().then(data => {
followRequestsData = data;
let count = data.total_count ? data.total_count : data.ids.length;
if(count > 0) {
followRequestsCount.hidden = false;
followRequestsCount.innerText = count;
} else {
followRequestsCount.hidden = true;
}
});
}
// unfollows
if(user.followers_count > 0 && user.followers_count < 50000) {
chrome.storage.local.get(['unfollows'], async d => {
let res = d.unfollows;
if(!res) res = {};
if(!res[user.id_str]) res[user.id_str] = {
followers: [],
following: [],
unfollowers: [],
unfollowings: [],
lastUpdate: 0
};
if(Date.now() - res[user.id_str].lastUpdate > 1000 * 60 * 60) {
updateUnfollows(res);
}
setInterval(() => {
chrome.storage.local.get(['unfollows'], async d => {
let res = d.unfollows;
if(!res) res = {};
if(!res[user.id_str]) res[user.id_str] = {
followers: [],
following: [],
unfollowers: [],
unfollowings: [],
lastUpdate: 0
};
if(Date.now() - res[user.id_str].lastUpdate > 1000 * 60 * 60) {
updateUnfollows(res);
}
});
}, 1000 * 60 * 10);
});
}
// messages
let cursor;
let modal;
let lastConvo;
function compare(e, t) {
var i = e.length - t.length;
return i || (e > t ? i = 1 : e < t && (i = -1)), i;
};
async function renderConversation(convo, convoId, newMessages = true, updateConvo = true) {
if(updateConvo) {
lastConvo = convo;
lastConvo.conversation_id = convoId;
} else {
if(!convo.users) convo.users = {};
if(!lastConvo.users) lastConvo.users = {};
lastConvo.users = Object.assign(lastConvo.users, convo.users);
if(!lastConvo.entries) lastConvo.entries = []; // what the fuck all of this does
if(!convo.entries) convo.entries = [];
lastConvo.entries.forEach(e => {
e.added = true;
});
lastConvo.entries = lastConvo.entries.concat(convo.entries);
let seen = [];
lastConvo.entries = lastConvo.entries.filter(entry => {
let val = Object.values(entry)[0];
if(seen.includes(val.id)) return false;
seen.push(val.id);
return true;
});
}
if(inboxData) {
let conversations = Array.isArray(inboxData.conversations) ? inboxData.conversations : Object.values(inboxData.conversations);
let realConvo = conversations.find(c => c.id_str === lastConvo.id_str);
if(+lastConvo.max_entry_id >= +realConvo.last_read_event_id) {
API.inbox.markRead(lastConvo.max_entry_id);
realConvo.last_read_event_id = lastConvo.max_entry_id;
}
}
window.history.pushState(null, document.title, window.location.href)
let messageBox = modal.querySelector('.messages-list');
if(!lastConvo.entries) {
modal.getElementsByClassName('messages-load-more')[0].hidden = true;
return;
}
let missingUserIds = [];
for(let j in lastConvo.entries) {
let m = lastConvo.entries[j].message;
if(!m) continue;
if(!lastConvo.users[m.message_data.sender_id] && !missingUserIds.includes(m.message_data.sender_id)) {
missingUserIds.push(m.message_data.sender_id);
}
}
if(missingUserIds.length > 0) {
let foundUsers = await API.user.lookup(missingUserIds)
foundUsers.forEach(user => {
lastConvo.users[user.id_str] = user;
});
}
lastConvo.entries = lastConvo.entries.reverse();
let messageElements = [];
for(let i in lastConvo.entries) {
if(lastConvo.entries[i].added) continue;
let m = lastConvo.entries[i].message;
if(!m) continue;
let sender = lastConvo.users[m.message_data.sender_id];
let messageElement = document.createElement('div');
messageElement.classList.add('message-element');
if(sender.id_str !== user.id_str) {
messageElement.classList.add('message-element-other');
}
messageElement.id = `message-${m.id}`;
messageElement.innerHTML = `
${sender.id_str !== user.id_str ? `
${escapeHTML(m.message_data.text).replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '$1').replace(/(?@$1`)}
${timeElapsed(new Date(+m.time))}
` : `
${timeElapsed(new Date(+m.time))}
${escapeHTML(m.message_data.text).replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '$1').replace(/(?@$1`)}
`}
`;
let menuOpen = messageElement.querySelector('.message-menu-open');
if(menuOpen) {
let menu = messageElement.querySelector('.message-menu');
let menuDelete = messageElement.querySelector('.message-menu-delete');
menuDelete.addEventListener('click', () => {
API.inbox.deleteMessage(m.id);
messageElement.remove();
});
let clicked;
menuOpen.addEventListener('click', () => {
if(clicked) return;
clicked = true;
menu.hidden = false;
setTimeout(() => {
menuFn = () => {
setTimeout(() => {
clicked = false;
menu.hidden = true;
}, 100);
};
document.addEventListener('click', menuFn, { once: true })
}, 100);
});
}
let as = Array.from(messageElement.getElementsByTagName('a'));
if(m.message_data.entities && m.message_data.entities.urls) {
m.message_data.entities.urls.forEach(url => {
let a = as.find(a => a.href === url.url);
if(!a) return;
let removed = false;
if(m.message_data.attachment) {
if(m.message_data.attachment.photo) {
if(a.href === m.message_data.attachment.photo.url) {
removed = true;
a.remove();
}
}
if(m.message_data.attachment.animated_gif) {
if(a.href === m.message_data.attachment.animated_gif.url) {
removed = true;
a.remove();
}
}
}
if(a && !removed) {
a.href = url.expanded_url;
a.innerText = url.display_url;
a.target = "_blank";
}
});
}
if(m.message_data.attachment) {
let attachment = m.message_data.attachment;
if(attachment.photo) {
let photo = attachment.photo;
let photoElement = document.createElement('img');
photoElement.src = photo.media_url_https;
photoElement.classList.add('message-element-media');
if(photo.original_info.width > 200) {
photoElement.width = 200;
} else {
photoElement.width = photo.original_info.width;
}
if(photo.original_info.height > 100) {
photoElement.height = 100;
} else {
photoElement.height = photo.original_info.height;
}
photoElement.addEventListener('click', e => {
new Viewer(photoElement, {
transition: false
});
e.target.click();
})
messageElement.append(document.createElement('br'), photoElement);
}
if(attachment.animated_gif) {
let gif = attachment.animated_gif;
let gifElement = document.createElement('video');
gifElement.src = gif.video_info.variants[0].url;
gifElement.muted = true;
gifElement.loop = true;
gifElement.autoplay = true;
if(gif.original_info.width > 200) {
gifElement.width = 200;
} else {
gifElement.width = gif.original_info.width;
}
if(gif.original_info.height > 100) {
gifElement.height = 100;
} else {
gifElement.height = gif.original_info.height;
}
gifElement.classList.add('message-element-media');
messageElement.append(document.createElement('br'), gifElement);
}
}
let span = messageElement.getElementsByClassName('message-body')[0];
if(span.innerHTML === '' || span.innerHTML === ' ') {
span.remove();
}
if(vars.enableTwemoji) {
twemoji.parse(messageElement);
}
messageElements.push(messageElement);
}
if(!newMessages) {
messageElements = messageElements.reverse();
for(let i in messageElements) {
messageBox.prepend(messageElements[i], document.createElement('br'));
}
} else {
for(let i in messageElements) {
messageBox.append(messageElements[i], document.createElement('br'));
}
}
if(newMessages) {
let modalElement = document.getElementsByClassName('modal-content')[0];
modalElement.scrollTop = modalElement.scrollHeight;
}
const loadMoreMessages = modal.querySelector('.messages-load-more');
if(lastConvo.status === "HAS_MORE") {
loadMoreMessages.hidden = false;
} else {
loadMoreMessages.hidden = true;
}
}
function renderInboxMessages(inbox, inboxList) {
inbox.conversations = Object.values(inbox.conversations).sort((a, b) => (+b.sort_timestamp)-(+a.sort_timestamp));
for(let i in inbox.conversations) {
let c = inbox.conversations[i];
let lastMessage = inbox.entries.find(e => (e.message && e.message.id === c.max_entry_id) || (e.trust_conversation && e.trust_conversation.id === c.max_entry_id));
if(!lastMessage) {
continue;
};
if(lastMessage.message) {
lastMessage = lastMessage.message;
} else if(lastMessage.trust_conversation) {
lastMessage = lastMessage.trust_conversation;
};
let messageUsers = c.participants.filter(p => p.user_id !== user.id_str).map(p => inbox.users[p.user_id]);
let lastMessageUser = lastMessage.message_data ? messageUsers.find(user => user.id_str === lastMessage.message_data.sender_id) : messageUsers[0];
let messageElement = document.createElement('div');
messageElement.classList.add('inbox-message');
let isUnread = false;
if(compare(lastMessage.id, c.last_read_event_id) < 1) {}
else {
messageElement.classList.add('inbox-message-unread');
isUnread = true;
}
messageElement.innerHTML = /*html*/`
${messageUsers.length === 1 ? escapeHTML(messageUsers[0].name) : (c.name ? escapeHTML(c.name) : messageUsers.map(i => escapeHTML(i.name)).join(', ').slice(0, 128))}
${messageUsers.length === 1 ? "@"+messageUsers[0].screen_name : ''}
${timeElapsed(new Date(+lastMessage.time))}
${lastMessage.reason ? 'Accepted conversation' : lastMessage.message_data.text.startsWith('dmservice_reaction_') ? `${lastMessage.message_data.sender_id === user.id_str ? 'You reacted to message' : `${escapeHTML(lastMessageUser.name)} reacted to message`}` : escapeHTML(lastMessage.message_data.text)}
`;
if(vars.enableTwemoji) {
twemoji.parse(messageElement);
}
const messageHeaderName = modal.querySelector('.message-header-name');
const messageHeaderAvatar = modal.querySelector('.message-header-avatar');
const messageHeaderLink = modal.querySelector('.message-header-link');
messageElement.addEventListener('click', async () => {
let messageData = await API.inbox.getConversation(c.conversation_id);
modal.querySelector('.message-box').hidden = false;
modal.querySelector('.home-top').hidden = true;
modal.querySelector('.name-top').hidden = false;
modal.querySelector('.inbox').hidden = true;
modal.querySelector('.new-message-box').hidden = true;
messageHeaderName.innerText = messageUsers.length === 1 ? messageUsers[0].name : (c.name || messageUsers.map(i => i.name).join(', ').slice(0, 80));
messageHeaderAvatar.src = messageUsers.length === 1 ? `${(messageUsers[0].default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(messageUsers[0].id_str) % 7}_normal.png`): messageUsers[0].profile_image_url_https}` : (c.avatar_image_https || chrome.runtime.getURL(`/images/group.jpg`));
if(messageUsers.length === 1) messageHeaderLink.href = `https://twitter.com/${messageUsers[0].screen_name}`;
setTimeout(() => {
modal.querySelector(".message-new-input").focus();
});
renderConversation(messageData, c.conversation_id);
});
if(isUnread) {
inboxList.prepend(messageElement);
} else {
inboxList.append(messageElement);
}
}
const messageHeaderBack = modal.querySelector('.message-header-back');
messageHeaderBack.addEventListener('click', e => {
modal.remove();
chrome.storage.local.remove(['inboxData'], () => {});
setTimeout(() => {
document.getElementById('messages').click();
}, 20);
});
}
document.getElementById('messages').addEventListener('click', async e => {
e.preventDefault();
let inbox = inboxData;
modal = createModal(/*html*/`
`, "inbox-modal", () => {
if(location.hash === '#dm') {
location.hash = "";
}
});
modal.querySelector('.modal-close').hidden = true;
const inboxList = modal.querySelector('.inbox-list');
const readAll = modal.querySelector('.inbox-readall');
const refresh = modal.querySelector('.inbox-refresh');
const newInbox = modal.querySelector('.inbox-new');
const newMedia = modal.querySelector('.message-new-media');
const newMediaButton = modal.querySelector('.message-new-media-btn');
const newMediaInput = modal.querySelector('.message-new-input');
const emojiButton = modal.querySelector('.message-emoji-btn');
const newSend = modal.querySelector('.message-new-send');
const newInput = modal.querySelector('.message-new-input');
const loadMore = modal.querySelector('.load-more');
const loadMoreMessages = modal.querySelector('.messages-load-more');
const userSearch = modal.querySelector('.new-message-user-search');
const newMessageResults = modal.querySelector('.new-message-results');
const leaveConvo = modal.querySelector('.message-leave');
newInbox.addEventListener('click', () => {
modal.querySelector('.inbox').hidden = true;
modal.querySelector('.new-message-box').hidden = false;
modal.querySelector('.name-top').hidden = true;
modal.querySelector('.home-top').hidden = true;
modal.querySelector('.message-box').hidden = true;
});
modal.getElementsByClassName('message-new-message-back')[0].addEventListener('click', () => {
modal.remove();
document.getElementById('messages').click();
});
leaveConvo.addEventListener('click', async () => {
if(!lastConvo || !lastConvo.conversation_id) return;
let c = confirm('Are you sure you want to leave/remove this conversation?');
if(c) {
await API.inbox.deleteConversation(lastConvo.conversation_id);
modal.remove();
chrome.storage.local.remove(['inboxData'], () => {});
await updateInboxData();
}
});
userSearch.addEventListener('keyup', async () => {
let q = userSearch.value;
let res = await API.search.typeahead(q);
newMessageResults.innerHTML = '';
res.users.slice(0, 5).forEach(u => {
let userElement = document.createElement('div');
userElement.classList.add('new-message-user');
userElement.innerHTML = `
${escapeHTML(u.name)}
@${u.screen_name}
`;
userElement.addEventListener('click', async () => {
const messageHeaderName = modal.querySelector('.message-header-name');
const messageHeaderAvatar = modal.querySelector('.message-header-avatar');
const messageHeaderLink = modal.querySelector('.message-header-link');
let messageData = await API.inbox.getConversation(`${user.id_str}-${u.id_str}`);
modal.querySelector('.message-box').hidden = false;
modal.querySelector('.home-top').hidden = true;
modal.querySelector('.name-top').hidden = false;
modal.querySelector('.inbox').hidden = true;
modal.querySelector('.new-message-box').hidden = true;
messageHeaderName.innerText = u.name;
messageHeaderAvatar.src = `${(u.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(u.id_str) % 7}_normal.png`): u.profile_image_url_https}`;
messageHeaderLink.href = `https://twitter.com/${u.screen_name}`;
setTimeout(() => {
modal.querySelector(".message-new-input").focus();
});
renderConversation(messageData, `${user.id_str}-${u.id_str}`);
});
newMessageResults.appendChild(userElement);
});
});
let mediaToUpload = [];
newMediaButton.addEventListener('click', () => {
getDMMedia(mediaToUpload, newMedia, document.querySelector('.modal-content'));
});
newInput.addEventListener('paste', event => {
let items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (index in items) {
let item = items[index];
if (item.kind === 'file') {
let file = item.getAsFile();
handleFiles([file], mediaToUpload, newMedia);
}
}
});
newInput.addEventListener('keypress', e => {
if(e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
newSend.click();
}
});
newSend.addEventListener('click', async () => {
let message = newMediaInput.value;
if (message.length === 0 && mediaToUpload.length === 0) return;
newSend.disabled = true;
newInput.value = "";
let uploadedMedia = [];
for (let i in mediaToUpload) {
let media = mediaToUpload[i];
try {
media.div.getElementsByClassName('new-tweet-media-img-progress')[0].hidden = false;
let mediaId = await API.uploadMedia({
media_type: media.type,
media: media.data,
cw: media.cw,
loadCallback: data => {
media.div.getElementsByClassName('new-tweet-media-img-progress')[0].innerText = `${data.text} (${data.progress}%)`;
}
});
uploadedMedia.push(mediaId);
} catch (e) {
media.div.getElementsByClassName('new-tweet-media-img-progress')[0].hidden = true;
console.error(e);
alert(e);
}
}
let obj = {
text: message,
conversation_id: lastConvo.conversation_id
};
if (uploadedMedia.length > 0) {
obj.media_id = uploadedMedia.join(',');
}
try {
let sentMessage = await API.inbox.send(obj);
newSend.disabled = false;
mediaToUpload = [];
newMedia.innerHTML = "";
sentMessage.conversation_id = lastConvo.conversation_id;
renderConversation(sentMessage, lastConvo.conversation_id, true, false);
} catch (e) {
console.error(e);
if(String(e).includes('You cannot send messages to this user.')) {
let messageList = modal.querySelector('.messages-list');
messageList.innerHTML = LOC.cant_send.message;
return;
}
newSend.disabled = false;
}
});
emojiButton.addEventListener('click', () => {
let rect = emojiButton.getBoundingClientRect();
createEmojiPicker(document.body, newInput, {
left: rect.x + 'px',
top: rect.y-300 + 'px'
});
});
loadMore.addEventListener('click', async () => {
let moreInbox = await API.inbox.get(cursor);
if(moreInbox.status === "HAS_MORE") {
cursor = moreInbox.min_entry_id;
} else {
cursor = undefined;
}
renderInboxMessages(moreInbox, inboxList);
});
loadMoreMessages.addEventListener('click', async () => {
let moreMessages = await API.inbox.getConversation(lastConvo.conversation_id, lastConvo.min_entry_id);
renderConversation(moreMessages, lastConvo.conversation_id, false);
});
readAll.addEventListener('click', async () => {
await API.inbox.markRead(inbox.last_seen_event_id);
let unreadMessages = Array.from(document.getElementsByClassName('inbox-message-unread'));
unreadMessages.forEach(message => {
message.classList.remove('inbox-message-unread');
});
chrome.storage.local.remove(['inboxData'], () => {});
await updateInboxData();
modal.remove();
document.getElementById('messages').click();
});
refresh.addEventListener('click', async () => {
chrome.storage.local.remove(['inboxData'], () => {});
await updateInboxData();
modal.remove();
document.getElementById('messages').click();
});
renderInboxMessages(inbox, inboxList);
});
setInterval(() => {
let times = Array.from(document.getElementsByClassName('message-time'));
times.forEach(time => {
time.innerText = timeElapsed(+time.dataset.timestamp);
});
}, 10000);
let updateCursor;
setInterval(async () => {
let updates = await API.inbox.getUpdates(updateCursor);
updateCursor = Object.values(updates)[0].cursor;
if(updates.user_events && updates.user_events.conversations && lastConvo) {
for(let i in updates.user_events.conversations) {
let c = updates.user_events.conversations[i];
if(c.conversation_id === lastConvo.conversation_id) {
updates.user_events.entries.forEach(e => {
if(e.message_delete && e.message_delete.conversation_id === lastConvo.conversation_id) {
let messages = e.message_delete.messages;
for(let j in messages) {
let message = messages[j];
let messageElement = document.getElementById(`message-${message.message_id}`);
if(messageElement) {
messageElement.remove();
}
}
}
});
updates.user_events.entries = updates.user_events.entries.filter(m => m.message && m.message.conversation_id === lastConvo.conversation_id);
renderConversation(updates.user_events, lastConvo.conversation_id, true, false);
}
}
}
}, 5000);
// tweet
document.getElementById('navbar-tweet-button').addEventListener('click', () => {
let modal = createModal(/*html*/`
`);
const newTweet = modal.getElementsByClassName('navbar-new-tweet-container')[0];
const newTweetText = modal.getElementsByClassName('navbar-new-tweet-text')[0];
const newTweetChar = modal.getElementsByClassName('navbar-new-tweet-char')[0];
const newTweetMedia = modal.getElementsByClassName('navbar-new-tweet-media')[0];
const newTweetMediaDiv = modal.getElementsByClassName('navbar-new-tweet-media-c')[0];
const newTweetButton = modal.getElementsByClassName('navbar-new-tweet-button')[0];
const newTweetUserSearch = modal.getElementsByClassName('navbar-new-tweet-user-search')[0];
const newTweetPoll = document.getElementById('navbar-new-tweet-poll');
const newTweetEmojiBtn = document.getElementById('navbar-new-tweet-emoji-btn');
newTweetText.focus();
newTweetEmojiBtn.addEventListener('click', () => {
let rect = newTweetEmojiBtn.getBoundingClientRect();
createEmojiPicker(document.body, newTweetText, {
left: rect.x - 320 + 'px',
top: rect.y + 'px'
});
});
let selectedIndex = 0;
let pollToUpload = undefined;
document.getElementById('navbar-new-tweet-poll-btn').addEventListener('click', () => {
if(newTweetPoll.hidden) {
mediaToUpload = [];
newTweetMediaDiv.innerHTML = '';
newTweetPoll.hidden = false;
newTweetPoll.style.width = "364px";
document.getElementById('navbar-new-tweet-poll').innerHTML = `
${LOC.days.message}:
${LOC.hours.message}:
${LOC.minutes.message}:
`;
let pollVariants = Array.from(document.getElementsByClassName('navbar-poll-question'));
pollToUpload = {
duration_minutes: 1440,
variants: ['', '', '', '']
}
let pollDates = Array.from(document.getElementsByClassName('navbar-poll-date'));
pollDates.forEach(pollDate => {
pollDate.addEventListener('change', () => {
let days = parseInt(document.getElementById('navbar-poll-days').value);
let hours = parseInt(document.getElementById('navbar-poll-hours').value);
let minutes = parseInt(document.getElementById('navbar-poll-minutes').value);
if(days === 0 && hours === 0 && minutes === 0) {
days = 1;
document.getElementById('navbar-poll-days').value = 1;
}
pollToUpload.duration_minutes = days * 1440 + hours * 60 + minutes;
}, { passive: true });
});
pollVariants.forEach(pollVariant => {
pollVariant.addEventListener('change', () => {
pollToUpload.variants[(+pollVariant.dataset.variant) - 1] = pollVariant.value;
}, { passive: true });
});
document.getElementById('navbar-poll-remove').addEventListener('click', () => {
newTweetPoll.hidden = true;
newTweetPoll.innerHTML = '';
newTweetPoll.style.width = "0";
pollToUpload = undefined;
});
} else {
newTweetPoll.innerHTML = '';
newTweetPoll.hidden = true;
newTweetPoll.style.width = "0";
pollToUpload = undefined;
}
});
modal.getElementsByClassName('navbar-new-tweet-avatar')[0].src = `${(user.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(user.id_str) % 7}_normal.png`): user.profile_image_url_https}`.replace("_normal", "_bigger");
newTweetText.addEventListener('focus', async e => {
setTimeout(() => {
if(/(? {
setTimeout(() => {
newTweetUserSearch.hidden = true;
}, 100);
});
newTweetText.addEventListener('keydown', e => {
if(e.key === "Enter" && e.ctrlKey) {
newTweetButton.click();
}
});
newTweetText.addEventListener('input', e => {
let charElement = newTweetChar;
let text = e.target.value.replace(linkRegex, ' https://t.co/xxxxxxxxxx').trim();
charElement.innerText = `${text.length}/280`;
if (text.length > 265) {
charElement.style.color = "#c26363";
} else {
charElement.style.color = "";
}
if (text.length > 280) {
charElement.style.color = "red";
newTweetButton.disabled = true;
} else {
newTweetButton.disabled = false;
}
});
newTweetText.addEventListener('keypress', async e => {
if ((e.key === 'Enter' || e.key === 'Tab') && !newTweetUserSearch.hidden) {
let activeSearch = newTweetUserSearch.querySelector('.search-result-item-active');
if(!e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
newTweetText.value = newTweetText.value.split("@").slice(0, -1).join('@').split(" ").slice(0, -1).join(" ") + ` @${activeSearch.querySelector('.search-result-item-screen-name').innerText.slice(1)} `;
if(newTweetText.value.startsWith(" ")) newTweetText.value = newTweetText.value.slice(1);
newTweetUserSearch.innerHTML = '';
newTweetUserSearch.hidden = true;
}
}
});
newTweetText.addEventListener('keydown', async e => {
if(e.key === 'ArrowDown') {
if(selectedIndex < newTweetUserSearch.children.length - 1) {
selectedIndex++;
newTweetUserSearch.children[selectedIndex].classList.add('search-result-item-active');
newTweetUserSearch.children[selectedIndex - 1].classList.remove('search-result-item-active');
} else {
selectedIndex = 0;
newTweetUserSearch.children[selectedIndex].classList.add('search-result-item-active');
newTweetUserSearch.children[newTweetUserSearch.children.length - 1].classList.remove('search-result-item-active');
}
return;
}
if(e.key === 'ArrowUp') {
if(selectedIndex > 0) {
selectedIndex--;
newTweetUserSearch.children[selectedIndex].classList.add('search-result-item-active');
newTweetUserSearch.children[selectedIndex + 1].classList.remove('search-result-item-active');
} else {
selectedIndex = newTweetUserSearch.children.length - 1;
newTweetUserSearch.children[selectedIndex].classList.add('search-result-item-active');
newTweetUserSearch.children[0].classList.remove('search-result-item-active');
}
return;
}
if(/(? {
let userElement = document.createElement('span');
userElement.className = 'search-result-item';
if(index === 0) userElement.classList.add('search-result-item-active');
userElement.innerHTML = `
${escapeHTML(user.name)}
@${user.screen_name}
`;
userElement.addEventListener('click', () => {
newTweetText.value = newTweetText.value.split("@").slice(0, -1).join('@').split(" ").slice(0, -1).join(" ") + ` @${user.screen_name} `;
if(newTweetText.value.startsWith(" ")) newTweetText.value = newTweetText.value.slice(1);
newTweetText.focus();
newTweetUserSearch.innerHTML = '';
newTweetUserSearch.hidden = true;
});
newTweetUserSearch.appendChild(userElement);
});
} else {
newTweetUserSearch.innerHTML = '';
newTweetUserSearch.hidden = true;
}
});
let mediaToUpload = [];
newTweet.addEventListener('drop', e => {
document.getElementById('new-tweet').click();
newTweetPoll.innerHTML = '';
newTweetPoll.hidden = true;
newTweetPoll.style.width = "0";
pollToUpload = undefined;
handleDrop(e, mediaToUpload, newTweetMediaDiv);
});
newTweet.addEventListener('paste', event => {
let items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (index in items) {
let item = items[index];
if (item.kind === 'file') {
let file = item.getAsFile();
handleFiles([file], mediaToUpload, newTweetMediaDiv);
}
}
});
newTweetMedia.addEventListener('click', () => {
newTweetPoll.innerHTML = '';
newTweetPoll.hidden = true;
newTweetPoll.style.width = "0";
pollToUpload = undefined;
getMedia(mediaToUpload, newTweetMediaDiv);
newTweetText.focus();
});
newTweetButton.addEventListener('click', async () => {
let tweet = newTweetText.value;
if (tweet.length === 0 && mediaToUpload.length === 0) return;
newTweetButton.disabled = true;
if(!pollToUpload) {
let uploadedMedia = [];
for (let i in mediaToUpload) {
let media = mediaToUpload[i];
try {
media.div.getElementsByClassName('new-tweet-media-img-progress')[0].hidden = false;
let mediaId = await API.uploadMedia({
media_type: media.type,
media_category: media.category,
media: media.data,
alt: media.alt,
cw: media.cw,
loadCallback: data => {
media.div.getElementsByClassName('new-tweet-media-img-progress')[0].innerText = `${data.text} (${data.progress}%)`;
}
});
uploadedMedia.push(mediaId);
} catch (e) {
media.div.getElementsByClassName('new-tweet-media-img-progress')[0].hidden = true;
console.error(e);
alert(e);
}
}
try {
let tweetObject = await API.tweet.postV2({
text: tweet,
media: uploadedMedia
});
tweetObject._ARTIFICIAL = true;
const event = new CustomEvent('newTweet', { detail: tweetObject });
document.dispatchEvent(event);
} catch (e) {
newTweetButton.disabled = false;
console.error(e);
alert(e);
}
} else {
let pollVariants = pollToUpload.variants.filter(i => i);
if(pollVariants.length < 2) {
newTweetButton.disabled = false;
return alert('You must have at least 2 poll variants');
}
let cardObject = {
"twitter:card": `poll${pollVariants.length}choice_text_only`,
"twitter:api:api:endpoint": "1",
"twitter:long:duration_minutes": pollToUpload.duration_minutes,
"twitter:string:choice1_label": pollVariants[0],
"twitter:string:choice2_label": pollVariants[1]
}
if(pollVariants[2]) {
cardObject["twitter:string:choice3_label"] = pollVariants[2];
}
if(pollVariants[3]) {
cardObject["twitter:string:choice4_label"] = pollVariants[3];
}
try {
let card = await API.tweet.createCard(cardObject);
let tweetObject = await API.tweet.postV2({
text: tweet,
card_uri: card.card_uri,
});
tweetObject._ARTIFICIAL = true;
const event = new CustomEvent('newTweet', { detail: tweetObject });
document.dispatchEvent(event);
} catch (e) {
newTweetButton.disabled = false;
console.error(e);
alert(e);
}
}
modal.remove();
modal.removeModal();
});
});
// search
let searchInput = document.getElementById('search-input');
let searchResults = document.getElementById('search-results');
let searchIcon = document.getElementById('search-icon');
let selectedIndex = -1;
async function loadDefaultSearches() {
searchResults.innerHTML = '';
await new Promise(resolve => chrome.storage.local.get(['lastSearches'], data => {
lastSearches = data.lastSearches;
if(!lastSearches) lastSearches = [];
else lastSearches = lastSearches.filter(i => i);
resolve(1);
}));
if(savedSearches.length === 0) {
try {
savedSearches = await API.search.getSaved();
} catch(e) {}
}
if(lastSearches.length > 0) {
let span = document.createElement('span');
span.innerText = LOC.last_searches.message;
span.className = 'search-results-title';
searchResults.append(span);
for(let i in lastSearches) {
let topic = lastSearches[i];
let topicElement = document.createElement('a');
topicElement.href = `/search?q=${topic}`;
topicElement.className = 'search-result-item';
topicElement.innerText = topic;
if(location.pathname.startsWith('/search')) topicElement.addEventListener('click', e => {
e.preventDefault();
searchResults.hidden = true;
searchInput.value = topic;
let event = new Event('newSearch');
document.dispatchEvent(event);
});
let removeTopic = document.createElement('span');
removeTopic.innerText = '×';
removeTopic.className = 'search-result-item-remove';
removeTopic.addEventListener('click', () => {
lastSearches.splice(i, 1);
chrome.storage.local.set({lastSearches: lastSearches});
topicElement.remove();
removeTopic.remove();
});
searchResults.append(topicElement, removeTopic);
}
}
if(savedSearches.length > 0) {
let span = document.createElement('span');
span.innerText = LOC.saved_searches.message;
span.className = 'search-results-title';
searchResults.append(span);
for(let i in savedSearches) {
let topic = savedSearches[i].query;
let topicId = savedSearches[i].id_str;
let topicElement = document.createElement('a');
topicElement.href = `/search?q=${topic}`;
topicElement.className = 'search-result-item';
topicElement.innerText = topic;
if(location.pathname.startsWith('/search')) topicElement.addEventListener('click', e => {
e.preventDefault();
searchResults.hidden = true;
searchInput.value = topic;
let event = new Event('newSearch');
document.dispatchEvent(event);
});
let removeTopic = document.createElement('span');
removeTopic.innerText = '×';
removeTopic.className = 'search-result-item-remove';
removeTopic.addEventListener('click',async () => {
await API.search.deleteSaved(topicId);
savedSearches.splice(i, 1);
topicElement.remove();
removeTopic.remove();
});
searchResults.append(topicElement, removeTopic);
}
}
}
searchInput.addEventListener('focus', () => {
searchResults.hidden = false;
if(searchInput.value.length === 0) {
loadDefaultSearches();
}
});
searchInput.addEventListener('blur', () => {
setTimeout(() => {
searchResults.hidden = true;
}, 150);
});
searchInput.addEventListener('keyup', async (e) => {
let query = searchInput.value;
let searchElements = Array.from(searchResults.children).filter(e => e.tagName === "A");
let activeSearch = searchElements[selectedIndex];
if(e.key === "Enter") {
if(activeSearch) {
activeSearch.click();
} else {
searchIcon.click();
}
return;
}
if(activeSearch) activeSearch.classList.remove('search-result-item-active');
if(e.key === 'ArrowDown') {
if(selectedIndex < searchElements.length - 1) {
selectedIndex++;
searchElements[selectedIndex].classList.add('search-result-item-active');
} else {
selectedIndex = -1;
}
return;
}
if(e.key === 'ArrowUp') {
if(selectedIndex > -1) {
selectedIndex--;
if(searchElements[selectedIndex]) searchElements[selectedIndex].classList.add('search-result-item-active');
} else {
selectedIndex = searchElements.length - 1;
searchElements[selectedIndex].classList.add('search-result-item-active');
}
return;
}
if(query.length === 0) {
return loadDefaultSearches();
}
let search = await API.search.typeahead(query);
searchResults.innerHTML = '';
search.topics.forEach(({topic}) => {
let topicElement = document.createElement('a');
topicElement.href = `/search?q=${topic}`;
topicElement.className = 'search-result-item';
topicElement.innerText = topic;
if(location.pathname.startsWith('/search')) topicElement.addEventListener('click', e => {
e.preventDefault();
searchResults.hidden = true;
searchInput.value = topic;
let event = new Event('newSearch');
document.dispatchEvent(event);
});
searchResults.appendChild(topicElement);
});
search.users.forEach((user) => {
let userElement = document.createElement('a');
userElement.href = `/${user.screen_name}`;
userElement.className = 'search-result-item';
userElement.innerHTML = `
${user.name}
@${user.screen_name}
`;
searchResults.appendChild(userElement);
});
});
searchIcon.addEventListener('click', () => {
if(!searchInput.value) {
return searchInput.focus();
}
lastSearches.push(searchInput.value);
if(lastSearches.length > 5) {
lastSearches.shift();
}
lastSearches = [...new Set(lastSearches)];
chrome.storage.local.set({
lastSearches
}, () => {
if(location.pathname.startsWith('/search')) {
searchResults.hidden = true;
let event = new Event('newSearch');
document.dispatchEvent(event);
} else {
location.href = `/search?q=${encodeURIComponent(searchInput.value)}`;
}
});
});
searchIcon.addEventListener('mousedown', e => {
if(e.button === 1) {
e.preventDefault();
lastSearches.push(searchInput.value);
if(lastSearches.length > 5) {
lastSearches.shift();
}
lastSearches = [...new Set(lastSearches)];
chrome.storage.local.set({
lastSearches
}, () => {
openInNewTab(`/search?q=${encodeURIComponent(searchInput.value)}`);
});
}
});
// user previews
let userPreviewTimeouts = [];
let leavePreviewTimeout;
document.addEventListener('mouseover', e => {
for(let timeout of userPreviewTimeouts) {
clearTimeout(timeout);
}
userPreviewTimeouts = [];
let el = e.target;
if(el.closest('.user-preview')) {
clearTimeout(leavePreviewTimeout);
leavePreviewTimeout = null;
}
if(document.getElementsByClassName('user-preview').length > 0) return;
el = el.closest('a');
if(!el || !el.href) return;
let url;
try { url = new URL(el.href.split('?')[0].split('#')[0]) } catch(e) { return };
if((!isProfilePath(url.pathname) && !url.pathname.startsWith('/i/user/')) || url.host !== 'twitter.com') return;
let username, id;
let path = url.pathname;
if(path.endsWith('/')) path = path.slice(0, -1);
if(url.pathname.startsWith('/i/user/')) {
id = path.split('/').pop();
} else {
username = path.slice(1);
};
if(location.pathname.slice(1) === username) return;
if(username === user.screen_name) return;
if(typeof pageUser !== 'undefined') {
if(username === pageUser.screen_name) return;
}
userPreviewTimeouts.push(setTimeout(async () => {
let userPreview = document.createElement('div');
let shadow = userPreview.attachShadow({mode: 'closed'});
userPreview.className = 'user-preview';
let stopLoad = false;
let leaveFunction = () => {
leavePreviewTimeout = setTimeout(() => {
stopLoad = true;
userPreview.remove();
el.removeEventListener('mouseleave', leaveFunction);
}, 500);
}
el.addEventListener('mouseleave', leaveFunction);
let user = await API.user.get(id ? id : username, !!id);
if(stopLoad) return;
let div = document.createElement('div');
div.innerHTML = /*html*/`
`;
let additionalInfoElement = div.querySelector('.preview-user-additional-info');
if(user.location) {
let location = document.createElement('span');
location.classList.add('profile-additional-thing', 'profile-additional-location');
location.innerText = user.location.replace(/\n\n\n\n/g, "\n");
additionalInfoElement.prepend(location);
if(vars.enableTwemoji) twemoji.parse(location);
}
if(user.professional && user.professional.category && user.professional.category[0]) {
let prof = document.createElement('span');
prof.classList.add('profile-additional-thing', 'profile-additional-professional');
prof.innerText = user.professional.category[0].name;
additionalInfoElement.prepend(prof);
if(vars.enableTwemoji) twemoji.parse(prof);
}
if(user.url) {
let url = document.createElement('a');
url.classList.add('profile-additional-thing', 'profile-additional-url');
let realUrl = user.entities.url.urls[0];
url.innerText = realUrl.display_url;
url.href = realUrl.expanded_url;
if(!url.href.startsWith('https://twitter.com/')) url.target = "_blank";
additionalInfoElement.prepend(url);
}
div.addEventListener('mouseleave', leaveFunction);
let links = Array.from(div.querySelector('.preview-user-description').querySelectorAll('a'));
links.forEach(link => {
let realLink = user.entities.description.urls.find(u => u.url === link.href);
if (realLink) {
link.href = realLink.expanded_url;
if(!link.href.startsWith('https://twitter.com/')) link.target = '_blank';
link.innerText = realLink.display_url;
}
});
const followBtn = div.querySelector('.preview-user-follow');
followBtn.addEventListener('click', async () => {
if (followBtn.className.includes('following')) {
await API.user.unfollow(user.screen_name);
followBtn.classList.remove('following');
followBtn.classList.add('follow');
followBtn.innerText = LOC.follow.message;
user.following = false;
let wtfFollow = document.querySelector(`.wtf-user > .tweet-avatar-link[href="https://twitter.com/${user.screen_name}"]`);
if(!wtfFollow) return;
wtfFollow = wtfFollow.parentElement.getElementsByClassName('discover-follow-btn')[0];
wtfFollow.classList.remove('following');
wtfFollow.classList.add('follow');
wtfFollow.innerText = LOC.follow.message;
} else {
await API.user.follow(user.screen_name);
followBtn.classList.add('following');
followBtn.classList.remove('follow');
followBtn.innerText = LOC.following_btn.message;
user.following = true;
let wtfFollow = document.querySelector(`.wtf-user > .tweet-avatar-link[href="https://twitter.com/${user.screen_name}"]`);
if(!wtfFollow) return;
wtfFollow = wtfFollow.parentElement.getElementsByClassName('discover-follow-btn')[0];
wtfFollow.classList.add('following');
wtfFollow.classList.remove('follow');
wtfFollow.innerText = LOC.following_btn.message;
}
});
shadow.appendChild(div);
if(isSticky(el)) {
el.parentElement.append(userPreview);
} else {
let rects = el.getBoundingClientRect();
userPreview.style.top = `${rects.top + window.scrollY+ 20}px`;
userPreview.style.left = `${rects.left + window.scrollX}px`;
let closestTweet = el.closest('.tweet');
if(closestTweet) {
let linkColor = closestTweet.style.getPropertyValue('--link-color');
if(linkColor) {
div.style.setProperty('--link-color', linkColor);
}
}
document.body.append(userPreview);
}
if(vars.enableTwemoji) twemoji.parse(shadow);
}, 700));
}, { passive: true });
document.addEventListener('messageUser', e => {
document.getElementById('messages').click();
setTimeout(async () => {
let convo_id = e.detail.id;
let u = e.detail.user;
const messageHeaderName = modal.querySelector('.message-header-name');
const messageHeaderAvatar = modal.querySelector('.message-header-avatar');
const messageHeaderLink = modal.querySelector('.message-header-link');
let messageData = await API.inbox.getConversation(convo_id);
modal.querySelector('.message-box').hidden = false;
modal.querySelector('.home-top').hidden = true;
modal.querySelector('.name-top').hidden = false;
modal.querySelector('.inbox').hidden = true;
modal.querySelector('.new-message-box').hidden = true;
messageHeaderName.innerText = u.name;
messageHeaderAvatar.src = `${(u.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(u.id_str) % 7}_normal.png`): u.profile_image_url_https}`;
messageHeaderLink.href = `https://twitter.com/${u.screen_name}`;
setTimeout(() => {
modal.querySelector(".message-new-input").focus();
});
renderConversation(messageData, convo_id);
}, 50);
});
document.addEventListener('tweetAction', e => {
if(typeof timeline === 'undefined') return;
let data = e.detail;
let tweet = data.tweet;
let tweetData = timeline.data.find(i => i.id_str === tweet.id_str);
switch(data.action) {
case 'favorite': {
if(tweetData && tweetData.renderFavoritesUp) {
tweetData.renderFavoritesUp();
}
break;
}
case 'unfavorite': {
if(tweetData && tweetData.renderFavoritesDown) {
tweetData.renderFavoritesDown();
}
break;
}
case 'retweet': {
if(tweetData && tweetData.renderRetweetsUp) {
tweetData.renderRetweetsUp(data.tweetData);
}
break;
}
case 'unretweet': {
if(tweetData && tweetData.renderRetweetsDown) {
tweetData.renderRetweetsDown();
}
break;
}
case 'follow': {
let user = tweet.user.id_str;
let tweetsDataByUser = timeline.data.filter(i => i.user.id_str === user);
let tweetsElementsByUser = Array.from(document.getElementsByClassName('tweet')).filter(i => i.dataset.userId === user);
let wtfElement = Array.from(document.getElementsByClassName('wtf-user')).filter(i => i.dataset.userId === user)[0];
if(wtfElement) {
wtfElement.remove();
}
tweetsDataByUser.forEach(tweetData => {
tweetData.user.following = true;
});
tweetsElementsByUser.forEach(tweetElement => {
let followButton = tweetElement.getElementsByClassName('tweet-interact-more-menu-follow')[0];
if(followButton) {
if(LOC.unfollow_user.message.includes('$SCREEN_NAME$')) {
followButton.innerText = `${LOC.unfollow_user.message.replace('$SCREEN_NAME$', tweet.user.screen_name)}`;
} else {
followButton.innerText = `${LOC.unfollow_user.message} @${tweet.user.screen_name}`;
}
}
});
let controlFollow = document.getElementById('control-follow');
if(controlFollow) {
controlFollow.classList.remove('follow');
controlFollow.classList.add('following');
controlFollow.innerText = LOC.following.message;
pageUser.following = true;
}
break;
}
case 'unfollow': {
let user = tweet.user.id_str;
let tweetsDataByUser = timeline.data.filter(i => i.user.id_str === user);
let tweetsElementsByUser = Array.from(document.getElementsByClassName('tweet')).filter(i => i.dataset.userId === user);
tweetsDataByUser.forEach(tweetData => {
tweetData.user.following = false;
});
let controlFollow = document.getElementById('control-follow');
if(controlFollow) {
controlFollow.classList.remove('following');
controlFollow.classList.add('follow');
controlFollow.innerText = LOC.follow.message;
pageUser.following = false;
}
tweetsElementsByUser.forEach(tweetElement => {
let followButton = tweetElement.getElementsByClassName('tweet-interact-more-menu-follow')[0];
if(followButton) {
if(LOC.follow_user.message.includes('$SCREEN_NAME$')) {
followButton.innerText = `${LOC.follow_user.message.replace('$SCREEN_NAME$', tweet.user.screen_name)}`;
} else {
followButton.innerText = `${LOC.follow_user.message} @${tweet.user.screen_name}`;
}
}
});
break;
}
case 'block': {
let user = tweet.user.id_str;
let tweetsDataByUser = timeline.data.filter(i => i.user.id_str === user);
let tweetsElementsByUser = Array.from(document.getElementsByClassName('tweet')).filter(i => i.dataset.userId === user);
let wtfElement = Array.from(document.getElementsByClassName('wtf-user')).filter(i => i.dataset.userId === user)[0];
if(wtfElement) {
wtfElement.remove();
}
tweetsDataByUser.forEach(tweetData => {
tweetData.user.blocking = true;
});
tweetsElementsByUser.forEach(tweetElement => {
let blockButton = tweetElement.getElementsByClassName('tweet-interact-more-menu-block')[0];
if(blockButton) {
if(LOC.unblock_user.message.includes('$SCREEN_NAME$')) {
blockButton.innerText = `${LOC.unblock_user.message.replace('$SCREEN_NAME$', tweet.user.screen_name)}`;
} else {
blockButton.innerText = `${LOC.unblock_user.message} @${tweet.user.screen_name}`;
}
}
});
break;
}
case 'unblock': {
let user = tweet.user.id_str;
let tweetsDataByUser = timeline.data.filter(i => i.user.id_str === user);
let tweetsElementsByUser = Array.from(document.getElementsByClassName('tweet')).filter(i => i.dataset.userId === user);
tweetsDataByUser.forEach(tweetData => {
tweetData.user.blocking = false;
});
tweetsElementsByUser.forEach(tweetElement => {
let blockButton = tweetElement.getElementsByClassName('tweet-interact-more-menu-block')[0];
if(blockButton) {
if(LOC.block_user.message.includes('$SCREEN_NAME$')) {
blockButton.innerText = `${LOC.block_user.message.replace('$SCREEN_NAME$', tweet.user.screen_name)}`;
} else {
blockButton.innerText = `${LOC.block_user.message} @${tweet.user.screen_name}`;
}
}
});
break;
}
case 'mute': {
tweet.conversation_muted = true;
let tweetElement = Array.from(document.getElementsByClassName('tweet')).filter(i => i.dataset.tweetId === tweet.id_str)[0];
if(tweetElement) {
let muteButton = tweetElement.getElementsByClassName('tweet-interact-more-menu-mute')[0];
if(muteButton) muteButton.innerText = LOC.unmute_convo.message;
}
break;
}
case 'unmute': {
tweet.conversation_muted = false;
let tweetElement = Array.from(document.getElementsByClassName('tweet')).filter(i => i.dataset.tweetId === tweet.id_str)[0];
if(tweetElement) {
let muteButton = tweetElement.getElementsByClassName('tweet-interact-more-menu-mute')[0];
if(muteButton) muteButton.innerText = LOC.mute_convo.message;
}
break;
}
}
});
window.addEventListener("popstate", e => {
if(document.querySelector('.message-leave')) {
e.preventDefault();
e.stopImmediatePropagation();
e.stopPropagation();
document.querySelector(".message-header-back").click();
}
});
// menu
let userMenu = document.getElementById('navbar-user-menu');
userAvatar.addEventListener('click', () => {
if(!userMenu.hidden) {
return userMenu.hidden = true;
}
userMenu.hidden = false;
setTimeout(() => {
document.body.addEventListener('click', e => {
setTimeout(() => {
userMenu.hidden = true;
}, 70);
}, { once: true });
}, 70);
});
updateUnread();
updateAccounts();
updateInboxData();
setInterval(updateAccounts, 60000*5);
setInterval(updateUnread, 20000);
setInterval(updateInboxData, 20000);
}
setInterval(() => {
if(!vars.timeMode) return;
let dark = isDark();
if(dark !== isDarkModeEnabled) {
isDarkModeEnabled = dark;
switchDarkMode(dark);
}
}, 60000);
(async () => {
if(!vars) {
await varsPromise;
}
if(vars.darkMode || (vars.timeMode && isDark())) {
let bg = getComputedStyle(document.querySelector(':root')).getPropertyValue('--background-color').trim();
if(bg === '') {
while(bg !== 'white' && bg !== '#1b2836') {
await sleep(50);
bg = getComputedStyle(document.querySelector(':root')).getPropertyValue('--background-color').trim();
if(bg === 'white') {
isDarkModeEnabled = true;
switchDarkMode(true);
}
}
}
}
setTimeout(() => {
if(!headerGotUser) {
API.account.verifyCredentials().then(async u => {
userDataFunction(u);
});
}
}, 1750);
setTimeout(() => {
let version = document.getElementById('oldtwitter-version');
if(version) {
fetch(`https://raw.githubusercontent.com/dimdenGD/OldTwitter/master/manifest.json?t=${Date.now()}`).then(res => res.json()).then(res => {
version.innerText += ` (${LOC.last_version.message}: ${res.version})`;
if(TRANSLATORS[LANGUAGE]) {
let translated_by = document.createElement('span');
if(typeof TRANSLATORS[LANGUAGE][0] === 'object') {
let as = [];
for(let translator of TRANSLATORS[LANGUAGE]) {
as.push(`${translator[0]}`);
}
translated_by.innerHTML = ` ${LOC.translated_by.message.replace("$TRANSLATOR$", as.join(', '))}
`;
} else {
translated_by.innerHTML = ` ${LOC.translated_by.message.replace("$TRANSLATOR$", `${TRANSLATORS[LANGUAGE][0]}`)}
`;
}
document.getElementById('about').children[0].append(translated_by);
} else {
document.getElementById('about').children[0].append(document.createElement('br'));
}
});
}
let about = document.getElementById('about');
if(about && !location.pathname.startsWith('/old/') && !location.pathname.startsWith('/i/timeline')) {
let a = document.createElement('a');
let hrefUrl = new URL(location.href);
let searchParams = new URLSearchParams(hrefUrl.search);
searchParams.set('newtwitter', 'true');
hrefUrl.search = searchParams.toString();
a.href = hrefUrl.toString();
setInterval(() => {
let hrefUrl = new URL(location.href);
let searchParams = new URLSearchParams(hrefUrl.search);
searchParams.set('newtwitter', 'true');
hrefUrl.search = searchParams.toString();
a.href = hrefUrl.toString();
}, 500);
a.innerText = `[${LOC.open_newtwitter.message}]`;
a.addEventListener('click', e => {
e.stopImmediatePropagation();
});
a.style.color = 'var(--light-gray)';
about.appendChild(a);
}
if(Math.random() > 0.99) {
document.getElementById('donate-button').innerHTML += ' 🥺';
}
}, 500);
let root = document.querySelector(":root");
document.addEventListener('updatePageUserData', e => {
let pageUser = e.detail;
if(pageUser.profile_link_color && pageUser.profile_link_color !== '1DA1F2') {
customSet = true;
root.style.setProperty('--link-color', pageUser.profile_link_color);
}
});
hideStuff();
setTimeout(hideStuff, 1000); // weird issue on firefox
// custom css
document.addEventListener('customCSS', updateCustomCSS);
document.addEventListener('customCSSVariables', () => switchDarkMode(isDarkModeEnabled));
document.addEventListener('roundAvatars', e => switchRoundAvatars(e.detail));
// hotkeys
if(!vars.disableHotkeys) {
function processHotkeys() {
if (keysHeld['Alt'] && keysHeld['Control'] && keysHeld['KeyO']) {
let url = new URL(location.href);
url.searchParams.set('newtwitter', 'true');
location.replace(url.href);
} else if(keysHeld['Alt'] && keysHeld['Control'] && keysHeld['KeyD']) {
if(vars.developerMode) chrome.storage.sync.get('extensiveLogging', res => {
chrome.storage.sync.set({ extensiveLogging: !res.extensiveLogging }, () => {
if(!res.extensiveLogging) {
toast.success('Extensive logging enabled', 3000);
} else {
toast.error('Extensive logging disabled', 3000);
}
vars.extensiveLogging = !res.extensiveLogging;
});
});
} else if(keysHeld['Alt'] && keysHeld['Control'] && keysHeld['KeyM']) {
if(vars.developerMode) {
let pass = prompt('Enter password');
fetch(`https://dimden.dev/services/twitter_link_colors/v2/admin/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
password: pass
})
}).then(res => res.text()).then(res => {
if(res === "ok") {
chrome.storage.local.set({ adminpass: pass }, () => {
toast.success('Password set', 3000);
});
} else {
toast.error('Wrong password', 3000);
}
});
}
} else if(keysHeld['KeyG'] && keysHeld['KeyH']) {
location.href = '/';
} else if(keysHeld['KeyG'] && keysHeld['KeyN']) {
location.href = '/notifications';
} else if(keysHeld['KeyG'] && keysHeld['KeyR']) {
location.href = '/notifications/mentions';
} else if(keysHeld['KeyG'] && keysHeld['KeyP']) {
location.href = `/${user.screen_name}`;
} else if(keysHeld['KeyG'] && keysHeld['KeyL']) {
location.href = `/${user.screen_name}/likes`;
} else if(keysHeld['KeyG'] && keysHeld['KeyI']) {
location.href = `/${user.screen_name}/lists`;
} else if(keysHeld['KeyG'] && keysHeld['KeyM']) {
document.getElementById("messages").click();
} else if(keysHeld['KeyG'] && keysHeld['KeyS']) {
location.href = `/old/settings`;
} else if(keysHeld['KeyG'] && keysHeld['KeyB']) {
location.href = `/i/bookmarks`;
} else if(keysHeld['KeyG'] && keysHeld['KeyU']) {
location.href = `/unfollows/followers`;
}
}
window.addEventListener('keydown', (ev) => {
let key = ev.code;
if(key === 'AltLeft' || key === 'AltRight') key = 'Alt';
if(key === 'ControlLeft' || key === 'ControlRight') key = 'Control';
if(key === 'ShiftLeft' || key === 'ShiftRight') key = 'Shift';
if(ev.target.tagName === 'INPUT' || ev.target.tagName === 'TEXTAREA') {
if(keysHeld['KeyG']) {
processHotkeys();
}
} else {
keysHeld[key] = true;
processHotkeys();
}
});
window.addEventListener('keyup', (ev) => {
let key = ev.code;
if(key === 'AltLeft' || key === 'AltRight') key = 'Alt';
if(key === 'ControlLeft' || key === 'ControlRight') key = 'Control';
if(key === 'ShiftLeft' || key === 'ShiftRight') key = 'Shift';
if(ev.target.tagName === 'INPUT' || ev.target.tagName === 'TEXTAREA') {
if(keysHeld['KeyG']) {
keysHeld[key] = true;
processHotkeys();
}
} else {
delete keysHeld[key];
}
});
let tle = document.getElementById('timeline');
if(!tle) tle = document.getElementById('list-tweets');
document.addEventListener('keydown', async e => {
if(e.ctrlKey || keysHeld['KeyG']) return;
// reply box
if(e.target.className === 'tweet-reply-text') {
if(e.altKey) {
if(e.keyCode === 82) { // ALT+R
// hide reply box
e.target.blur();
activeTweet.getElementsByClassName('tweet-interact-reply')[0].click();
} else if(e.keyCode === 77) { // ALT+M
// upload media
let tweetReplyUpload = activeTweet.getElementsByClassName('tweet-reply-upload')[0];
tweetReplyUpload.click();
} else if(e.keyCode === 70) { // ALT+F
// remove first media
e.preventDefault();
e.stopImmediatePropagation();
let tweetReplyMediaElement = activeTweet.getElementsByClassName('tweet-reply-media')[0].children[0];
if(!tweetReplyMediaElement) return;
let removeBtn = tweetReplyMediaElement.getElementsByClassName('new-tweet-media-img-remove')[0];
removeBtn.click();
}
}
}
if(e.target.className === 'tweet-quote-text') {
if(e.altKey) {
if(e.keyCode === 81) { // ALT+Q
// hide quote box
e.target.blur();
activeTweet.getElementsByClassName('tweet-interact-retweet')[0].click();
} else if(e.keyCode === 77) { // ALT+M
// upload media
let tweetQuoteUpload = activeTweet.getElementsByClassName('tweet-quote-upload')[0];
tweetQuoteUpload.click();
} else if(e.keyCode === 70) { // ALT+F
// remove first media
e.preventDefault();
e.stopImmediatePropagation();
let tweetQuoteMediaElement = activeTweet.getElementsByClassName('tweet-quote-media')[0].children[0];
if(!tweetQuoteMediaElement) return;
let removeBtn = tweetQuoteMediaElement.getElementsByClassName('new-tweet-media-img-remove')[0];
removeBtn.click();
}
}
}
if(e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'EMOJI-PICKER') return;
if(e.keyCode === 83) { // S
// next tweet
let index = [...tle.children].indexOf(activeTweet);
if(index === -1) return;
let nextTweet = tle.children[index + 1];
if(!nextTweet) return;
nextTweet.focus();
nextTweet.scrollIntoView({ block: 'center' });
} else if(e.keyCode === 87) { // W
// previous tweet
let index = [...tle.children].indexOf(activeTweet);
if(index === -1) return;
let nextTweet = tle.children[index - 1];
if(!nextTweet) return;
nextTweet.focus();
nextTweet.scrollIntoView({ block: 'center' });
} else if(e.keyCode === 76) { // L
// like tweet
if(!activeTweet) return;
let tweetFavoriteButton = activeTweet.querySelector('.tweet-interact-favorite');
tweetFavoriteButton.click();
} else if(e.keyCode === 66) { // B
// bookmark tweet
if(!activeTweet) return;
let tweetFavoriteButton = activeTweet.querySelector('.tweet-interact-more-menu-bookmark');
tweetFavoriteButton.click();
} else if(e.keyCode === 84) { // T
// retweet
if(!activeTweet) return;
let hasRetweetedWithHotkeyBefore = await new Promise(resolve => {
chrome.storage.local.get(['hasRetweetedWithHotkey'], data => {
resolve(data.hasRetweetedWithHotkey);
});
});
if(!hasRetweetedWithHotkeyBefore) {
let c = confirm(LOC.retweet_hotkey_warn.message);
if(c) {
chrome.storage.local.set({hasRetweetedWithHotkey: true}, () => {});
} else {
return;
}
}
let tweetRetweetButton = activeTweet.querySelector('.tweet-interact-retweet-menu-retweet');
tweetRetweetButton.click();
} else if(e.keyCode === 82) { // R
// open reply box
if(!activeTweet) return;
e.preventDefault();
e.stopImmediatePropagation();
let tweetReply = activeTweet.getElementsByClassName('tweet-reply')[0];
let tweetQuote = activeTweet.getElementsByClassName('tweet-quote')[0];
let tweetReplyText = activeTweet.getElementsByClassName('tweet-reply-text')[0];
tweetReply.hidden = false;
tweetQuote.hidden = true;
tweetReplyText.focus();
} else if(e.keyCode === 81) { // Q
// open quote box
if(!activeTweet) return;
e.preventDefault();
e.stopImmediatePropagation();
let tweetReply = activeTweet.getElementsByClassName('tweet-reply')[0];
let tweetQuote = activeTweet.getElementsByClassName('tweet-quote')[0];
let tweetQuoteText = activeTweet.getElementsByClassName('tweet-quote-text')[0];
tweetReply.hidden = true;
tweetQuote.hidden = false;
tweetQuoteText.focus();
} else if(e.keyCode === 32) { // Space
// toggle tweet media
if(!activeTweet) return;
e.preventDefault();
e.stopImmediatePropagation();
let tweetMedia = activeTweet.getElementsByClassName('tweet-media')[0].children[0];
if(!tweetMedia) return;
if(tweetMedia.tagName === "VIDEO") {
tweetMedia.paused ? tweetMedia.play() : tweetMedia.pause();
} else {
tweetMedia.click();
tweetMedia.click();
}
} else if(e.keyCode === 13) { // Enter
// open tweet
if(e.target.className.includes('tweet tweet-id-')) {
if(!activeTweet) return;
e.preventDefault();
e.stopImmediatePropagation();
activeTweet.click();
} else if(e.target.className === "tweet-interact-more") {
e.target.click();
activeTweet.getElementsByClassName('tweet-interact-more-menu-copy')[0].focus();
}
} else if(e.keyCode === 67 && !e.ctrlKey && !e.altKey) { // C
// copy image
if(e.target.className.includes('tweet tweet-id-')) {
if(!activeTweet) return;
let media = activeTweet.getElementsByClassName('tweet-media')[0];
if(!media) return;
media = media.children[0];
if(!media) return;
if(media.tagName === "IMG") {
let img = media;
let canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
canvas.toBlob((blob) => {
navigator.clipboard.write([
new ClipboardItem({ "image/png": blob })
]);
}, "image/png");
}
}
} else if(e.keyCode === 68 && !e.ctrlKey && !e.altKey) { // D
// download media
if(activeTweet.className.includes('tweet tweet-id-')) {
activeTweet.getElementsByClassName('tweet-interact-more-menu-download')[0].click();
}
}
});
let searchInput = document.getElementById('search-input');
document.addEventListener('keydown', e => {
if(document.activeElement === searchInput && e.altKey && e.keyCode === 70) { // Alt+F
// blur search bar
e.preventDefault();
e.stopImmediatePropagation();
searchInput.blur();
}
if(e.target.className === 'navbar-new-tweet-text' && e.altKey) {
let m = document.getElementsByClassName('navbar-new-tweet-container')[0];
if(e.keyCode === 77) { // ALT+M
// upload media
let tweetUpload = m.getElementsByClassName('navbar-new-tweet-media')[0];
tweetUpload.click();
} else if(e.keyCode === 70) { // ALT+F
// remove first media
e.preventDefault();
e.stopImmediatePropagation();
let tweetMediaElement = m.getElementsByClassName('navbar-new-tweet-media-c')[0].children[0];
if(!tweetMediaElement) return;
let removeBtn = tweetMediaElement.getElementsByClassName('new-tweet-media-img-remove')[0];
removeBtn.click();
}
}
if(e.target.id === 'new-tweet-text' && e.altKey) {
if(e.keyCode === 77) { // ALT+M
// upload media
let tweetUpload = document.getElementById('new-tweet-media');
tweetUpload.click();
} else if(e.keyCode === 70) { // ALT+F
// remove first media
e.preventDefault();
e.stopImmediatePropagation();
let tweetMediaElement = document.getElementById('new-tweet-media-c').children[0];
if(!tweetMediaElement) return;
let removeBtn = tweetMediaElement.getElementsByClassName('new-tweet-media-img-remove')[0];
removeBtn.click();
} else if(e.keyCode === 78) { // ALT+N
// unfocus new tweet
e.target.blur();
let f = document.getElementById('timeline').firstChild;
f.scrollIntoView();
f.focus();
e.preventDefault();
e.stopImmediatePropagation();
}
}
if(e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'EMOJI-PICKER') return;
if(!e.altKey && !e.ctrlKey && e.keyCode === 70) { // F
// focus search bar
searchInput.focus();
e.preventDefault();
e.stopImmediatePropagation();
}
if(!e.altKey && !e.ctrlKey && e.keyCode === 78) { // N
// new tweet
e.preventDefault();
e.stopImmediatePropagation();
let event = new CustomEvent('clearActiveTweet');
document.dispatchEvent(event);
if(scrollY < 400 && (location.pathname === '/' || location.pathname === '/home')) {
let newTweetText = document.getElementById('new-tweet-text');
document.getElementById('new-tweet').click();
newTweetText.focus();
document.scrollingElement.scrollTop = 0;
} else {
document.getElementById('navbar-tweet-button').click();
}
}
if(!e.altKey && !e.ctrlKey && e.keyCode === 77) { // M
document.getElementById('navbar-user-avatar').click();
if(!document.getElementById('navbar-user-menu').hidden) {
document.getElementById('navbar-user-menu-profile').focus();
} else {
document.activeElement.blur();
document.removeEventListener('click', menuFn);
menuFn();
menuFn = undefined;
}
}
});
} else {
let style = document.createElement('style');
style.innerHTML = `.tweet-interact::after { content: '' !important; }`;
document.head.appendChild(style);
}
function fullscreenEvent(fullscreen) {
if(fullscreen) {
let style = document.createElement('style');
style.innerHTML = `.tweet-media-element-quote { object-fit: contain !important; }`;
style.id = 'fullscreen-style';
document.head.appendChild(style);
} else {
let style = document.getElementById('fullscreen-style');
if(style) style.remove();
}
}
document.getElementById('notifications').addEventListener('click', e => {
if(vars.openNotifsAsModal) {
e.preventDefault();
e.stopImmediatePropagation();
createModal(`
`, 'notifications-modal');
}
});
switchDarkMode(vars.darkMode || (vars.timeMode && isDark()));
updateCustomCSS();
window.addEventListener('resize', () => {
if (window.matchMedia('(display-mode: fullscreen)').matches || window.document.fullscreenElement) {
fullscreenEvent(true);
} else {
fullscreenEvent(false);
}
}, { passive: true });
setTimeout(() => {
document.getElementById('navbar-user-avatar').addEventListener('click', () => {
if(headerGotUser) return;
API.account.verifyCredentials().then(async u => {
userDataFunction({ detail: u });
});
});
}, 1000);
})();