let user = {};
let pageUser = {};
let timeline = {
data: [],
dataToUpdate: [],
toBeUpdated: 0
}
let seenThreads = [];
let averageLikeCount = 1;
let pinnedTweet, followersYouFollow;
let previousLastTweet, stopLoad = false;
let tweetsCursor, favoritesCursor, followingCursor, followersCursor, followersYouKnowCursor, mediaCursor;
let cssEligibleAuto = false, cssEligible = false;
// Util
let subpage;
let user_handle = location.pathname.slice(1).split("?")[0].split('#')[0];
user_handle = user_handle.split('/')[0];
let user_protected = false;
let user_blocked_by = false;
let user_blocking = false;
function updateSubpage() {
previousLastTweet = undefined; stopLoad = false;
averageLikeCount = 1;
user_handle = location.pathname.slice(1).split("?")[0].split('#')[0];
if(user_handle.split('/').length === 1) {
subpage = 'profile';
} else {
if(user_handle.endsWith('/with_replies')) {
subpage = 'replies';
} else if(user_handle.endsWith('/media')) {
subpage = 'media';
} else if(user_handle.endsWith('/likes')) {
subpage = 'likes';
} else if(user_handle.endsWith('/following')) {
subpage = 'following';
} else if(user_handle.endsWith('/followers')) {
subpage = 'followers';
} else if(user_handle.endsWith('/followers_you_follow')) {
subpage = 'followers_you_follow';
} else if(user_handle.endsWith('/lists')) {
subpage = 'lists';
}
}
user_handle = user_handle.split('/')[0];
}
function updateSelection() {
document.getElementById('style-hide-retweets').innerHTML = '';
document.getElementById('tweet-nav-more-menu-hr').checked = false;
document.getElementById('tweet-nav-more-menu-hnr').checked = false;
let activeStats = Array.from(document.getElementsByClassName('profile-stat-active'));
for(let i in activeStats) {
if(activeStats[i].classList.contains('profile-stat-active')) {
activeStats[i].classList.remove('profile-stat-active');
}
}
let activeNavs = Array.from(document.getElementsByClassName('tweet-nav-active'));
for(let i in activeNavs) {
if(activeNavs[i].classList.contains('tweet-nav-active')) {
activeNavs[i].classList.remove('tweet-nav-active');
}
}
if(subpage === "profile") {
document.getElementById('tweet-nav').hidden = false;
document.getElementById('timeline').hidden = false;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-tweets-link').classList.add('profile-stat-active');
document.getElementById('tweet-nav-tweets').classList.add('tweet-nav-active');
} else if(subpage === "likes") {
document.getElementById('tweet-nav').hidden = false;
document.getElementById('timeline').hidden = false;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-favorites-link').classList.add('profile-stat-active');
} else if(subpage === "replies") {
document.getElementById('tweet-nav').hidden = false;
document.getElementById('timeline').hidden = false;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-tweets-link').classList.add('profile-stat-active');
document.getElementById('tweet-nav-replies').classList.add('tweet-nav-active');
} else if(subpage === "media") {
document.getElementById('tweet-nav').hidden = false;
document.getElementById('timeline').hidden = false;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-media-link').classList.add('profile-stat-active');
document.getElementById('tweet-nav-media').classList.add('tweet-nav-active');
} else if(subpage === "following") {
document.getElementById('tweet-nav').hidden = true;
document.getElementById('timeline').hidden = true;
document.getElementById('following-list').hidden = false;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = false;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-following-link').classList.add('profile-stat-active');
} else if(subpage === "followers") {
document.getElementById('tweet-nav').hidden = true;
document.getElementById('timeline').hidden = true;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = false;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = false;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-followers-link').classList.add('profile-stat-active');
} else if(subpage === "followers_you_follow") {
document.getElementById('tweet-nav').hidden = true;
document.getElementById('timeline').hidden = true;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = false;
document.getElementById('followers_you_follow-more').hidden = false;
document.getElementById('lists-list').hidden = true;
document.getElementById('profile-stat-followers-link').classList.add('profile-stat-active');
} else if(subpage === "lists") {
document.getElementById('tweet-nav').hidden = true;
document.getElementById('timeline').hidden = true;
document.getElementById('following-list').hidden = true;
document.getElementById('followers-list').hidden = true;
document.getElementById('following-more').hidden = true;
document.getElementById('followers-more').hidden = true;
document.getElementById('followers_you_follow-list').hidden = true;
document.getElementById('followers_you_follow-more').hidden = true;
document.getElementById('lists-list').hidden = false;
}
document.getElementById('profile-stat-tweets-link').href = `https://twitter.com/${pageUser.screen_name}`;
document.getElementById('profile-stat-following-link').href = `https://twitter.com/${pageUser.screen_name}/following`;
document.getElementById('profile-stat-followers-link').href = `https://twitter.com/${pageUser.screen_name}/followers`;
document.getElementById('profile-stat-favorites-link').href = `https://twitter.com/${pageUser.screen_name}/likes`;
document.getElementById('profile-stat-media-link').href = `https://twitter.com/${pageUser.screen_name}/media`;
document.getElementById('tweet-nav-tweets').href = `https://twitter.com/${pageUser.screen_name}`;
document.getElementById('tweet-nav-replies').href = `https://twitter.com/${pageUser.screen_name}/with_replies`;
document.getElementById('tweet-nav-media').href = `https://twitter.com/${pageUser.screen_name}/media`;
if(pageUser.statuses_count === 0 && !( pageUser.blocked_by || pageUser.blocking || pageUser.protected ) && (subpage === 'profile' || subpage === 'replies')) {
document.getElementById('trends').hidden = true;
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `
${LOC.hasnt_tweeted.message.replace('$SCREEN_NAME$', `${pageUser.screen_name} `)}
${LOC.when_theyll_tweet.message}
`;
} else {
document.getElementById('trends').hidden = false;
document.getElementById('no-tweets').hidden = true;
document.getElementById('no-tweets').innerHTML = ``;
}
}
function updateUserData() {
return new Promise(async (resolve, reject) => {
document.getElementsByTagName('title')[0].innerText = `${user_handle} - ` + LOC.twitter.message;
let [pageUserData, followersYouFollowData, oldUser, u] = await Promise.allSettled([
API.user.getV2(user_handle),
API.user.friendsFollowing(user_handle, false),
API.user.get(user_handle, false),
API.account.verifyCredentials()
]).catch(e => {
document.getElementById('loading-box').hidden = false;
if(String(e).includes('User has been suspended.')) {
return document.getElementById('loading-box-error').innerHTML = `${LOC.user_was_suspended.message}${LOC.go_homepage.message} `;
}
if(String(e).includes("reading 'result'")) {
return document.getElementById('loading-box-error').innerHTML = `${LOC.user_was_not_found.message}${LOC.go_homepage.message} `;
}
return document.getElementById('loading-box-error').innerHTML = `${String(e)}.${LOC.go_homepage.message} `;
});
if(oldUser.reason) {
let e = oldUser.reason;
if(String(e).includes('User has been suspended.')) {
document.getElementById('loading-box').hidden = false;
return document.getElementById('loading-box-error').innerHTML = `${LOC.user_was_suspended.message}${LOC.go_homepage.message} `;
}
}
if(pageUserData.reason) {
let e = pageUserData.reason;
document.getElementById('loading-box').hidden = false;
if(String(e).includes("reading 'result'")) {
return document.getElementById('loading-box-error').innerHTML = `${LOC.user_was_not_found.message}${LOC.go_homepage.message} `;
}
return document.getElementById('loading-box-error').innerHTML = `${String(e)}.${LOC.go_homepage.message} `;
}
followersYouFollowData = followersYouFollowData.value;
oldUser = oldUser.value;
u = u.value;
user = u;
pageUserData = pageUserData.value;
//default value
user_blocked_by = false;
user_blocking = false;
user_protected = false;
if (pageUserData.blocked_by) {
user_blocked_by = true;
}
if (pageUserData.blocking) {
user_blocking = true;
}
if (pageUserData.protected && !pageUserData.following && pageUserData.id_str !== user.id_str) {
user_protected = true;
}
userDataFunction(u);
const event2 = new CustomEvent('updatePageUserData', { detail: oldUser });
document.dispatchEvent(event2);
pageUser = pageUserData;
pageUser.protected = oldUser.protected;
let r = document.querySelector(':root');
let usedProfileColor = vars && vars.linkColor ? vars.linkColor : '#4595B5';
r.style.setProperty('--link-color', usedProfileColor);
let sc = makeSeeableColor(oldUser.profile_link_color);
if(oldUser.profile_link_color && oldUser.profile_link_color !== '1DA1F2') {
customSet = true;
r.style.setProperty('--link-color', sc);
usedProfileColor = oldUser.profile_link_color;
document.getElementById('color-years-ago').hidden = false;
} else {
document.getElementById('color-years-ago').hidden = true;
}
const profileLinkColor = document.getElementById('profile-link-color');
const colorPreviewLight = document.getElementById('color-preview-light');
const colorPreviewDark = document.getElementById('color-preview-dark');
const colorPreviewBlack = document.getElementById('color-preview-black');
const darkModeVars = document.getElementById('dark-mode-vars');
const lightModeVars = document.getElementById('light-mode-vars');
const cssTextArea = document.getElementById('profile-css-textarea');
profileLinkColor.value = `#${usedProfileColor}`;
profileLinkColor.addEventListener('input', () => {
let color = profileLinkColor.value;
if(color.startsWith('#')) color = color.slice(1);
let sc = makeSeeableColor(color);
customSet = true;
r.style.setProperty('--link-color', sc);
colorPreviewLight.style.color = makeSeeableColor(`#${color}`, "#ffffff");
colorPreviewDark.style.color = makeSeeableColor(`#${color}`, "#1b2836");
colorPreviewBlack.style.color = makeSeeableColor(`#${color}`, "#000000");
});
colorPreviewLight.style.color = makeSeeableColor(`#${usedProfileColor}`, "#ffffff");
colorPreviewDark.style.color = makeSeeableColor(`#${usedProfileColor}`, "#1b2836");
colorPreviewBlack.style.color = makeSeeableColor(`#${usedProfileColor}`, "#000000");
let profileCustomCSSData = {};
let pccss = await new Promise(resolve => {
chrome.storage.local.get(["profileCustomCSS"], async data => {
if(!data.profileCustomCSS) {
data.profileCustomCSS = {};
}
profileCustomCSSData = data.profileCustomCSS;
if(data.profileCustomCSS[pageUser.id_str]) {
resolve(data.profileCustomCSS[pageUser.id_str]);
} else {
resolve({});
}
});
});
if(pccss.darkModeVars && isDarkModeEnabled) {
let vars = parseVariables(pccss.darkModeVars);
for(let i in vars) {
r.style.setProperty(i, vars[i]);
}
} else if(pccss.lightModeVars && !isDarkModeEnabled) {
let vars = parseVariables(pccss.lightModeVars);
for(let i in vars) {
r.style.setProperty(i, vars[i]);
}
} else {
await switchDarkMode(isDarkModeEnabled);
}
if(pccss.css) {
if(!customCSS) {
customCSS = document.createElement('style');
customCSS.id = 'oldtwitter-custom-css';
document.head.appendChild(customCSS);
}
customCSS.innerHTML = pccss.css;
} else {
updateCustomCSS();
}
getLinkColors(pageUserData.id_str).then(data => {
let color = data[0];
if(color) color = color.color;
if(color && color !== 'none') {
let sc = makeSeeableColor(color);
customSet = true;
r.style.setProperty('--link-color', sc);
usedProfileColor = color;
}
fetch("https://dimden.dev/services/twitter_link_colors/v2/get_data/"+pageUserData.id_str).then(r => r.json()).then(async data => {
if(data.color !== 'none' && data.color !== '4595b5') {
if(data.color !== color) {
chrome.storage.local.get(["linkColors"], async lc => {
let linkColors = lc.linkColors || {};
linkColors[pageUserData.id_str] = data.color;
chrome.storage.local.set({ linkColors });
});
let sc = makeSeeableColor(data.color);
customSet = true;
usedProfileColor = data.color;
r.style.setProperty('--link-color', sc);
}
let pc = `#${data.color}`;
profileLinkColor.value = pc;
colorPreviewLight.style.color = makeSeeableColor(pc, "#ffffff");
colorPreviewDark.style.color = makeSeeableColor(pc, "#1b2836");
colorPreviewBlack.style.color = makeSeeableColor(pc, "#000000");
}
chrome.storage.local.get(["adminpass"], async a => {
if(a.adminpass) {
let adminControls = document.getElementById('admin-controls');
if(adminControls) adminControls.remove();
adminControls = document.createElement('div');
adminControls.id = 'admin-controls';
console.log(data.css_eligible);
adminControls.innerHTML = `
Eligible for custom profile CSS: ${data.css_eligible ? 'yes' : 'no'}
Can get access automatically: ${data.css_eligible_auto ? 'yes' : 'no'}
Has custom profile CSS: ${data.css || data.css_vars_dark || data.css_vars_light ? 'yes' : 'no'}
Has custom color: ${data.color !== 'none' ? 'yes' : 'no'}
Switch
`;
document.getElementById('about').appendChild(adminControls);
document.getElementById('admin-controls-switch').addEventListener('click', () => {
fetch(`https://dimden.dev/services/twitter_link_colors/v2/admin/switch_access`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
password: a.adminpass,
user: pageUserData.id_str
})
}).then(r => r.json()).then(data => {
if(data.error) {
return alert(data.error);
}
if(data.eligible) {
document.getElementById('admin-css-eligible').innerText = 'yes';
document.getElementById('admin-css-eligible-auto').innerText = 'no';
} else {
document.getElementById('admin-css-eligible').innerText = 'no';
document.getElementById('admin-css-eligible-auto').innerText = 'no';
}
});
});
}
});
if(data.css_eligible && !vars.disableProfileCustomizations) {
if(pccss.css !== data.css || pccss.darkModeVars !== data.css_vars_dark || pccss.lightModeVars !== data.css_vars_light) {
pccss.css = data.css;
pccss.darkModeVars = data.css_vars_dark;
pccss.lightModeVars = data.css_vars_light;
profileCustomCSSData[pageUser.id_str] = pccss;
chrome.storage.local.set({ profileCustomCSS: profileCustomCSSData });
}
let styled = false;
if(data.css) {
styled = true;
profileCSS = true;
if(!customCSS) {
customCSS = document.createElement('style');
customCSS.id = 'oldtwitter-custom-css';
document.head.appendChild(customCSS);
}
customCSS.innerHTML = data.css;
} else {
profileCSS = false;
updateCustomCSS();
}
if(data.css_vars_dark && isDarkModeEnabled) {
styled = true;
let vars = parseVariables(data.css_vars_dark);
for(let i in vars) {
r.style.setProperty(i, vars[i]);
}
} else if(data.css_vars_light && !isDarkModeEnabled) {
styled = true;
let vars = parseVariables(data.css_vars_light);
for(let i in vars) {
r.style.setProperty(i, vars[i]);
}
} else {
await switchDarkMode(isDarkModeEnabled);
}
if(pageUser.id_str !== user.id_str && styled) {
let additionalThing = document.createElement("span");
additionalThing.innerHTML = `${LOC.styled_profile.message} `;
additionalThing.className = "profile-additional-thing profile-additional-styled";
document.getElementById("profile-additional").appendChild(additionalThing);
}
} else {
profileCSS = false;
if(profileCustomCSSData[pageUser.id_str]) {
delete profileCustomCSSData[pageUser.id_str];
chrome.storage.local.set({ profileCustomCSS: profileCustomCSSData });
}
updateCustomCSS();
await switchDarkMode(isDarkModeEnabled);
}
if(pageUserData.id_str === user.id_str) {
darkModeVars.value = data.css_vars_dark || '';
lightModeVars.value = data.css_vars_light || '';
cssTextArea.value = data.css || '';
cssEligibleAuto = data.css_eligible_auto;
cssEligible = data.css_eligible;
if(data.css_eligible || (data.css_eligible_auto && user.followers_count >= 5000)) {
document.getElementById('custom-css-eligible').hidden = false;
document.getElementById('custom-css-not-eligible').hidden = true;
if(!vars.acknowledgedCssAccess && !data.css && !data.css_vars_dark && !data.css_vars_light) {
let modal = createModal(`
${LOC.pccss_congrats.message}
${LOC.yay.message}
`, 'css-congrats-modal', () => {
chrome.storage.sync.set({ acknowledgedCssAccess: true });
}, () => false);
modal.querySelector('button').addEventListener('click', () => {
modal.removeModal();
});
}
} else {
document.getElementById('custom-css-eligible').hidden = true;
document.getElementById('custom-css-not-eligible').hidden = false;
}
} else {
document.getElementById('custom-css-eligible').hidden = true;
document.getElementById('custom-css-not-eligible').hidden = true;
}
});
});
if(pageUser.id_str !== user.id_str) {
followersYouFollow = followersYouFollowData;
document.getElementById('profile-friends-text').style.display = 'unset';
} else {
followersYouFollow = undefined;
document.getElementById('profile-friends-text').style.display = 'none';
}
renderProfile();
resolve(u);
}).catch(e => {
if (e === "Not logged in") {
window.location.href = "https://twitter.com/i/flow/login?newtwitter=true";
}
console.error(e);
reject(e);
});
}
async function updateTimeline() {
seenThreads = [];
if (timeline.data.length === 0) document.getElementById('timeline').innerHTML = `
`;
let tl;
if(subpage === "likes") {
let data = await API.user.getFavorites(pageUser.id_str);
tl = data.tl;
favoritesCursor = data.cursor;
} else {
try {
if (!user_protected && !user_blocked_by) {
if (subpage === "media") {
tl = await API.user.getMediaTweets(pageUser.id_str);
mediaCursor = tl.cursor;
tl = tl.tweets;
} else {
tl = await API.user.getTweetsV2(
pageUser.id_str,
undefined,
subpage !== "profile"
);
pinnedTweet = tl.pinnedTweet;
tweetsCursor = tl.cursor;
tl = tl.tweets;
}
} else if(user_blocked_by) {
document.getElementById("timeline").innerHTML = `${LOC.blocked_by_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)} ${LOC.why_you_cant_see_block_user.message.replaceAll("$SCREEN_NAME$",pageUser.screen_name)}
`;
return;
}else if(user_protected) {
document.getElementById("timeline").innerHTML = `${LOC.user_protected.message} ${LOC.follow_to_see.message.replace("$SCREEN_NAME$",pageUser.screen_name)}
`;
return;
}/*else if(user_blocking) {
document.getElementById("timeline").innerHTML = `${LOC.you_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)} ${LOC.do_you_want_see_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)}
`;
return;
}*/
} catch(e) {
console.error(e);
document.getElementById('timeline').innerHTML = `${escapeHTML(String(e))}
`;
return;
}
// if(subpage === 'media') {
// tl = tl.filter(t => t.extended_entities && t.extended_entities.media && t.extended_entities.media.length > 0 && !t.retweeted_status);
// }
}
if(tl.error === "Not authorized.") {
document.getElementById('tweet-nav').hidden = true;
document.getElementById('loading-box').hidden = true;
document.getElementById('timeline').innerHTML = pageUser.statuses_count === 0 ? '' : `${LOC.timeline_not_authorized.message}
`;
return;
}
tl.forEach(t => {
let oldTweet = timeline.data.find(tweet => tweet.id_str === t.id_str);
let tweetElement = document.getElementById(`tweet-${t.id_str}`);
if (oldTweet) {
oldTweet.favorite_count = t.favorite_count;
oldTweet.retweet_count = t.retweet_count;
oldTweet.reply_count = t.reply_count;
oldTweet.favorited = t.favorited;
oldTweet.retweeted = t.retweeted;
}
if (tweetElement) {
tweetElement.querySelector('.tweet-interact-favorite ').innerText = t.favorite_count;
tweetElement.querySelector('.tweet-interact-retweet').innerText = t.retweet_count;
tweetElement.querySelector('.tweet-interact-reply').innerText = t.reply_count;
tweetElement.querySelector('.tweet-interact-favorite').classList.toggle('tweet-interact-favorited', t.favorited);
tweetElement.querySelector('.tweet-interact-retweet').classList.toggle('tweet-interact-retweeted', t.retweeted);
}
});
// first update
timeline.data = tl;
averageLikeCount = timeline.data.filter(t => !t.retweeted_status).map(t => t.favorite_count).sort((a, b) => a - b)[Math.floor(timeline.data.length/2)];
renderTimeline();
previousLastTweet = timeline.data[timeline.data.length - 1];
}
async function renderFollowing(clear = true, cursor) {
loadingFollowing = true;
let userList = document.getElementById('following-list');
if(clear) {
if(pageUser.id_str === user.id_str) {
userList.innerHTML = `
${LOC.unfollowings.message}
`;
} else {
userList.innerHTML = ``;
}
}
let following;
try {
following = await API.user.getFollowing(pageUser.id_str, cursor);
} catch(e) {
loadingFollowing = false;
followingMoreBtn.innerText = LOC.load_more.message;
console.error(e);
return;
}
followingCursor = following.cursor;
following = following.list;
if(following.length === 0) {
followingMoreBtn.hidden = true;
} else {
followingMoreBtn.hidden = false;
}
following.forEach(u => {
appendUser(u, userList);
});
document.getElementById('loading-box').hidden = true;
loadingFollowing = false;
followingMoreBtn.innerText = LOC.load_more.message;
}
async function renderFollowers(clear = true, cursor) {
loadingFollowers = true;
let userList = document.getElementById('followers-list');
if(clear) {
if(pageUser.id_str === user.id_str) {
userList.innerHTML = `
${LOC.unfollowers.message}
`;
} else {
userList.innerHTML = ``;
}
}
let following;
try {
following = await API.user.getFollowers(pageUser.id_str, cursor)
} catch(e) {
loadingFollowers = false;
followersMoreBtn.innerText = LOC.load_more.message;
console.error(e);
return;
}
followersCursor = following.cursor;
following = following.list;
if(following.length === 0) {
followersMoreBtn.hidden = true;
} else {
followersMoreBtn.hidden = false;
}
following.forEach(u => {
appendUser(u, userList);
});
document.getElementById('loading-box').hidden = true;
loadingFollowers = false;
followersMoreBtn.innerText = LOC.load_more.message;
}
async function renderFollowersYouFollow(clear = true, cursor) {
loadingFollowersYouKnow = true;
let userList = document.getElementById('followers_you_follow-list');
if(clear) {
if(LOC.followers_you_know.message.includes("$NUMBER$")) {
userList.innerHTML = ``;
} else {
userList.innerHTML = ``;
}
}
let following;
try {
following = await API.user.getFollowersYouFollow(pageUser.id_str, cursor);
} catch(e) {
console.error(e);
loadingFollowersYouKnow = false;
followersYouFollowMoreBtn.innerText = LOC.load_more.message;
return;
}
followersYouKnowCursor = following.cursor;
following = following.list;
if(following.length === 0) {
followersYouFollowMoreBtn.hidden = true;
} else {
followersYouFollowMoreBtn.hidden = false;
}
following.forEach(u => {
appendUser(u, userList);
});
document.getElementById('loading-box').hidden = true;
loadingFollowersYouKnow = false;
followersYouFollowMoreBtn.innerText = LOC.load_more.message;
}
async function renderLists() {
let lists = pageUser.id_str === user.id_str ? await API.list.getMyLists() : await API.user.getLists(pageUser.id_str);
let listsList = document.getElementById('lists-list');
listsList.innerHTML = ``;
if(pageUser.id_str === user.id_str) {
listsList.innerHTML += ``;
document.getElementById('create-list').addEventListener('click', () => {
let modal = createModal(`
${LOC.name.message}:
${LOC.description.message}:
${LOC.is_private.message}:
${LOC.create.message}
`, 'list-creator-modal');
document.getElementById('list-btn-create').addEventListener('click', async () => {
let list;
try {
list = await API.list.create(document.getElementById('list-name-input').value, document.getElementById('list-description-input').value, document.getElementById('list-private-input').checked);
} catch(e) {
return document.getElementById('list-editor-error').innerText = e && e.message ? e.message : e;
}
location.href = `https://twitter.com/i/lists/${list.id_str}`;
});
});
}
for(let i in lists) {
let l = lists[i];
if(!l) continue;
let listElement = document.createElement('div');
listElement.classList.add('list-item');
listElement.innerHTML = `
`;
listsList.appendChild(listElement);
}
document.getElementById('loading-box').hidden = true;
}
let months = [];
let everAddedAdditional = false;
let toAutotranslate = false;
async function renderProfile() {
document.getElementById('profile-banner').src = pageUser.profile_banner_url ? pageUser.profile_banner_url : 'https://abs.twimg.com/images/themes/theme1/bg.png';
let attempts = 0;
document.getElementById('profile-avatar').addEventListener('error', () => {
if(attempts > 3) return document.getElementById('profile-avatar').src = `${vars.useOldDefaultProfileImage ? chrome.runtime.getURL(`images/default_profile_images/default_profile_400x400.png`) : 'https://abs.twimg.com/sticky/default_profile_images/default_profile_400x400.png'}`;
attempts++;
setTimeout(() => {
document.getElementById('profile-avatar').src = `${(pageUser.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(pageUser.id_str) % 7}_normal.png`): pageUser.profile_image_url_https}`.replace('_normal.', '_400x400.');
}, 500);
});
let autotranslateProfiles = await new Promise(resolve => {
chrome.storage.sync.get(['autotranslateProfiles'], data => {
resolve(data.autotranslateProfiles);
});
});
if(!autotranslateProfiles) {
autotranslateProfiles = [];
}
toAutotranslate = autotranslateProfiles.includes(pageUser.id_str);
document.getElementById('profile-avatar').src = `${(pageUser.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(pageUser.id_str) % 7}_normal.png`): pageUser.profile_image_url_https}`.replace('_normal.', '_400x400.');
document.getElementById('nav-profile-avatar').src = `${(pageUser.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(pageUser.id_str) % 7}_normal.png`): pageUser.profile_image_url_https}`.replace('_normal.', '_bigger.');
document.getElementById('profile-name').innerText = pageUser.name.replace(/\n/g, ' ');
document.getElementById('nav-profile-name').innerText = pageUser.name.replace(/\n/g, ' ');
document.getElementById('profile-avatar-link').href = `${(pageUser.default_profile_image && vars.useOldDefaultProfileImage) ? chrome.runtime.getURL(`images/default_profile_images/default_profile_${Number(pageUser.id_str) % 7}_normal.png`): pageUser.profile_image_url_https}`.replace('_normal.', '_400x400.');
if(LOC.tweet_to.message.includes("$SCREEN_NAME$")) {
document.getElementById('tweet-to').innerText = LOC.tweet_to.message.replace("$SCREEN_NAME$", pageUser.screen_name.replace(/\n/g, ' '));
} else {
document.getElementById('tweet-to').innerText = `${LOC.tweet_to.message} ${pageUser.name.replace(/\n/g, ' ')}`;
}
if(vars.heartsNotStars) {
document.getElementById('profile-stat-text-favorites').innerText = LOC.likes.message;
}
let stats = Array.from(document.getElementsByClassName('profile-stat'));
stats.forEach(s => {
s.classList.toggle('profile-stat-disabled', (pageUser.protected && !pageUser.following) && pageUser.id_str !== user.id_str); //BUG:pageUser.blocked_by works strangly only here...
});
document.getElementById('profile-name').className = "";
if(pageUser.verified || pageUser.verified_type || pageUser.id_str === '1123203847776763904') {
if(!(!vars.twitterBlueCheckmarks && pageUser.verified_type === "Blue")) document.getElementById('profile-name').classList.add('user-verified');
if(pageUser.id_str === '1123203847776763904') document.getElementById('profile-name').classList.add('user-verified-green');
if(vars.twitterBlueCheckmarks && pageUser.verified_type === "Blue") document.getElementById('profile-name').classList.add('user-verified-blue');
if(pageUser.verified_type === "Government") document.getElementById('profile-name').classList.add('user-verified-gray');
if(pageUser.verified_type === "Business") document.getElementById('profile-name').classList.add('user-verified-yellow');
}
if(pageUser.protected) {
document.getElementById('profile-name').classList.add('user-protected');
}
if(pageUser.muting) {
document.getElementById('profile-name').classList.add('user-muted');
}
document.getElementById('profile-username').innerText = `@${pageUser.screen_name}`;
document.getElementById('nav-profile-username').innerText = `@${pageUser.screen_name}`;
document.getElementById('profile-media-text').href = `https://twitter.com/${pageUser.screen_name}/media`;
updateSelection();
document.getElementById('profile-bio').innerHTML = escapeHTML(pageUser.description).replace(/\n\n\n\n/g, "\n").replace(/((http|https|ftp):\/\/[\w?=.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '$1 ').replace(/(?@$1`).replace(hashtagRegex, `#$2 `).replace(/\n/g, ' ');
let strippedDownText = pageUser.description
.replace(/(?:https?|ftp):\/\/[\n\S]+/g, '') //links
.replace(/(? 60 && detectedLanguage.languages[0].language.startsWith(LANGUAGE);
let at = false;
if(!isEnglish) {
let translateBtn = document.createElement('span');
translateBtn.className = "translate-bio";
translateBtn.addEventListener('click', async () => {
if(at) return;
at = true;
let translated = await API.user.translateBio(pageUser.id_str);
let span = document.createElement('span');
let translatedMessage;
if(LOC.translated_from.message.includes("$LANGUAGE$")) {
translatedMessage = LOC.translated_from.message.replace("$LANGUAGE$", `[${translated.localizedSourceLanguage}]`);
} else {
translatedMessage = `${LOC.translated_from.message} [${translated.localizedSourceLanguage}]`;
}
span.innerHTML = `
${translatedMessage}:
${escapeHTML(translated.translation).replace(/((http|https|ftp):\/\/[\w?=.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '$1 ').replace(/(?@$1`).replace(hashtagRegex, `#$2 `).replace(/\n/g, ' ')}
`;
translateBtn.hidden = true;
document.getElementById('profile-bio').append(span);
let links = Array.from(span.getElementsByTagName('a'));
links.forEach(link => {
let realLink = pageUser.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;
}
});
if(vars.enableTwemoji) twemoji.parse(span);
});
translateBtn.innerText = LOC.translate_bio.message;
document.getElementById('profile-bio').append(document.createElement('br'), translateBtn);
}
if(vars.enableTwemoji) twemoji.parse(document.getElementById('profile-name'));
document.getElementById('profile-stat-tweets-value').innerText = Number(pageUser.statuses_count).toLocaleString().replace(/\s/g, ',');
document.getElementById('profile-stat-following-value').innerText = Number(pageUser.friends_count).toLocaleString().replace(/\s/g, ',');
document.getElementById('profile-stat-followers-value').innerText = Number(pageUser.followers_count).toLocaleString().replace(/\s/g, ',');
document.getElementById('profile-stat-favorites-value').innerText = Number(pageUser.favourites_count).toLocaleString().replace(/\s/g, ',');
document.getElementById('profile-stat-media-value').innerText = Number(pageUser.media_count).toLocaleString().replace(/\s/g, ',');
document.getElementById('tweet-nav').hidden = pageUser.statuses_count === 0 || user_blocked_by || user_protected || !(subpage === 'profile' || subpage === 'replies' || subpage === 'media');
document.getElementById('profile-stat-tweets-link').hidden = pageUser.statuses_count === 0;
document.getElementById('profile-stat-following-link').hidden = pageUser.friends_count === 0;
document.getElementById('profile-stat-followers-link').hidden = pageUser.followers_count === 0;
document.getElementById('profile-stat-favorites-link').hidden = pageUser.favourites_count === 0;
document.getElementById('profile-stat-media-link').hidden = pageUser.media_count === 0 || !vars.showMediaCount;
if((pageUser.statuses_count === 0 && (subpage === 'profile' || subpage === 'replies' || subpage === 'media')) || ((pageUser.protected || pageUser.blocked_by) && !pageUser.following && pageUser.id_str !== user.id_str)) {
document.getElementById('trends').hidden = true;
setTimeout(() => {
let list = document.getElementById('wtf-list');
while(list.childElementCount > 3) list.removeChild(list.lastChild);
}, 500);
} else {
document.getElementById('trends').hidden = false;
}
if(pageUser.statuses_count === 0 && !( pageUser.blocked_by || pageUser.blocking || pageUser.protected ) && (subpage === 'profile' || subpage === 'replies' || subpage === 'media')) {
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `
${LOC.hasnt_tweeted.message.replace('$SCREEN_NAME$', `${pageUser.screen_name} `)}
${LOC.when_theyll_tweet.message}
`;
} else {
document.getElementById('no-tweets').hidden = true;
document.getElementById('no-tweets').innerHTML = ``;
}
if(pageUser.blocking && !pageUser.blocked_by) {
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `${LOC.you_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)} ${LOC.do_you_want_see_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)}
`;
document.getElementById('timeline').hidden = true;
document.getElementById('tweet-nav').hidden = true;
document.getElementById('see-tweet-btn').addEventListener('click', async () => {
if(pageUser.statuses_count === 0 && !( pageUser.blocked_by || pageUser.blocking || pageUser.protected ) && (subpage === 'profile' || subpage === 'replies' || subpage === 'media')) {
document.getElementById('trends').hidden = true;
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `
${LOC.hasnt_tweeted.message.replace('$SCREEN_NAME$', `${pageUser.screen_name} `)}
${LOC.when_theyll_tweet.message}
`;
}
else {
document.getElementById('no-tweets').hidden = true;
document.getElementById('no-tweets').innerHTML = ``;
document.getElementById('timeline').hidden = false;
if(!pageUser.protected){
document.getElementById('trends').hidden = false;
document.getElementById('tweet-nav').hidden = false;
}
}
});
}
if(pageUser.followed_by) {
document.getElementById('follows-you').hidden = false;
} else {
document.getElementById('follows-you').hidden = true;
}
if(followersYouFollow && followersYouFollow.total_count > 0) {
let friendsFollowing = document.getElementById('profile-friends-following');
let friendsFollowingList = document.getElementById('profile-friends-div');
let friendsFollowingText = document.getElementById('profile-friends-text');
if(LOC.followers_you_know.message.includes("$NUMBER$")) {
friendsFollowingText.innerText = LOC.followers_you_know.message.replace("$NUMBER$", followersYouFollow.total_count);
} else {
friendsFollowingText.innerText = `${followersYouFollow.total_count} ${LOC.followers_you_know.message}`;
}
friendsFollowingText.href = `https://twitter.com/${pageUser.screen_name}/followers_you_follow`;
friendsFollowingText
followersYouFollow.users.forEach(u => {
let a = document.createElement('a');
a.href = `/${u.screen_name}`;
let avatar = document.createElement('img');
avatar.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}`.replace('_normal', '_bigger');
avatar.width = 45;
avatar.height = 45;
avatar.title = u.name + ' (@' + u.screen_name + ')';
avatar.classList.add('profile-friends-avatar');
a.append(avatar);
friendsFollowingList.append(a);
});
friendsFollowing.hidden = false;
} else {
let friendsFollowing = document.getElementById('profile-friends-following');
friendsFollowing.hidden = true;
}
let buttonsElement = document.getElementById('profile-nav-buttons');
document.getElementById('pin-profile').classList.toggle('menu-active', pageUser.id_str === user.id_str && !location.pathname.includes('/lists'));
document.getElementById('pin-lists').classList.toggle('menu-active', location.pathname.startsWith(`/${pageUser.screen_name}/lists`));
let styling = document.getElementById('styling');
if(pageUser.id_str === user.id_str) {
buttonsElement.innerHTML = /*html*/`
${LOC.edit_profile.message}
`;
let profileStyleActive = false;
let profileStyle = document.getElementById('profile-style');
profileStyle.addEventListener('click', () => {
profileStyle.classList.toggle('profile-style-active');
profileStyleActive = !profileStyleActive;
styling.hidden = !profileStyleActive;
});
chrome.storage.local.get(['otPrivateTokens'], data => {
document.getElementById('private-profile-warn').hidden = !user.protected || (data.otPrivateTokens && data.otPrivateTokens[user.id_str]);
});
} else {
document.getElementById('private-profile-warn').hidden = true;
styling.hidden = true;
document.getElementById('tweet-to-bg').hidden = false;
buttonsElement.innerHTML = /*html*/`
${pageUser.following || (pageUser.protected && pageUser.follow_request_sent) ? ((pageUser.protected && pageUser.follow_request_sent) ? LOC.follow_request_sent.message : LOC.following_btn.message) : LOC.follow.message}
${LOC.unblock.message}
`;
if(!pageUser.following) {
pageUser.want_retweets = true;
}
let blockUserText, unblockUserText;
if(LOC.block_user.message.includes('$SCREEN_NAME$') && LOC.unblock_user.message.includes('$SCREEN_NAME$')) {
blockUserText = `${LOC.block_user.message.replace('$SCREEN_NAME$', pageUser.screen_name)}`;
unblockUserText = `${LOC.unblock_user.message.replace('$SCREEN_NAME$', pageUser.screen_name)}`;
} else {
blockUserText = `${LOC.block_user.message} @${pageUser.screen_name}`;
unblockUserText = `${LOC.unblock_user.message} @${pageUser.screen_name}`;
}
buttonsElement.innerHTML += /*html*/`
`;
let messageUser = document.getElementById('message-user');
messageUser.addEventListener('click', () => {
let event = new CustomEvent('messageUser', { detail: { id: `${user.id_str}-${pageUser.id_str}`, user: pageUser } });
document.dispatchEvent(event);
});
let clicked = false;
let controlFollow = document.getElementById('control-follow');
controlFollow.addEventListener('click', async () => {
if (controlFollow.className.includes('following')) {
try {
pageUser.protected && pageUser.follow_request_sent ? await API.user.cancelFollowRequest(pageUser.screen_name) : await API.user.unfollow(pageUser.screen_name);
} catch(e) {
console.error(e);
alert(e);
return;
}
controlFollow.classList.remove('following');
controlFollow.classList.add('follow');
controlFollow.innerText = LOC.follow.message;
pageUser.following = false;
document.getElementById("profile-settings-retweets").hidden = true;
document.getElementById('profile-stat-followers-value').innerText = Number(parseInt(document.getElementById('profile-stat-followers-value').innerText.replace(/\s/g, '').replace(/,/g, '')) - 1).toLocaleString().replace(/\s/g, ',');
document.getElementById('profile-settings-notifications').hidden = true;
} else {
try {
await API.user.follow(pageUser.screen_name);
} catch(e) {
console.error(e);
alert(e);
return;
}
controlFollow.classList.add('following');
controlFollow.classList.remove('follow');
controlFollow.innerText = pageUser.protected ? LOC.follow_request_sent.message : LOC.following_btn.message;
pageUser.following = true;
if(!pageUser.protected) {
document.getElementById('profile-settings-notifications').hidden = false;
document.getElementById("profile-settings-retweets").hidden = false;
document.getElementById('profile-stat-followers-value').innerText = Number(parseInt(document.getElementById('profile-stat-followers-value').innerText.replace(/\s/g, '').replace(/,/g, '')) + 1).toLocaleString().replace(/\s/g, ',');
}
}
});
document.getElementById('profile-settings-retweets').addEventListener('click', async e => {
if(pageUser.want_retweets) {
await API.user.switchRetweetsVisibility(pageUser.id_str, false);
pageUser.want_retweets = false;
e.target.innerText = LOC.turn_on_retweets.message;
} else {
await API.user.switchRetweetsVisibility(pageUser.id_str, true);
pageUser.want_retweets = true;
e.target.innerText = LOC.turn_off_retweets.message;
}
});
document.getElementById('profile-settings').addEventListener('click', () => {
document.getElementById('profile-settings-div').hidden = false;
setTimeout(() => {
if(clicked) return;
clicked = true;
document.addEventListener('click', () => {
setTimeout(() => {
clicked = false;
document.getElementById('profile-settings-div').hidden = true;
}, 100);
}, { once: true });
}, 100);
});
document.getElementById('profile-settings-notifications').addEventListener('click', async () => {
if(!pageUser.notifications) {
await API.user.receiveNotifications(pageUser.id_str, true);
pageUser.notifications = true;
document.getElementById('profile-settings-notifications').classList.remove('profile-settings-notifications');
document.getElementById('profile-settings-notifications').classList.add('profile-settings-offnotifications');
document.getElementById('profile-settings-notifications').innerText = LOC.stop_notifications.message;
} else {
await API.user.receiveNotifications(pageUser.id_str, false);
pageUser.notifications = false;
document.getElementById('profile-settings-notifications').classList.remove('profile-settings-offnotifications');
document.getElementById('profile-settings-notifications').classList.add('profile-settings-notifications');
document.getElementById('profile-settings-notifications').innerText = LOC.stop_notifications.message;
}
});
document.getElementById('profile-settings-block').addEventListener('click', async () => {
if(pageUser.blocking) {
await API.user.unblock(pageUser.id_str);
pageUser.blocking = false;
document.getElementById('profile-settings-block').classList.remove('profile-settings-unblock');
document.getElementById('profile-settings-block').classList.add('profile-settings-block');
if(LOC.block_user.message.includes("$SCREEN_NAME$")) {
document.getElementById('profile-settings-block').innerText = LOC.block_user.message.replace("$SCREEN_NAME$", pageUser.screen_name);
} else {
document.getElementById('profile-settings-block').innerText = `${LOC.block_user.message} @${pageUser.screen_name}`;
}
document.getElementById('control-unblock').hidden = true;
if(!pageUser.blocked_by) {
document.getElementById('control-follow').hidden = false;
document.getElementById("profile-settings-notifications").hidden = false;
document.getElementById("profile-settings-mute").hidden = false;
document.getElementById('message-user').hidden = !pageUser.can_dm;
//enable timeline
//recycle no-tweets
if(pageUser.statuses_count === 0 && !( pageUser.blocked_by || pageUser.blocking || pageUser.protected ) && (subpage === 'profile' || subpage === 'replies' || subpage === 'media')) {
document.getElementById('trends').hidden = true;
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `
${LOC.hasnt_tweeted.message.replace('$SCREEN_NAME$', `${pageUser.screen_name} `)}
${LOC.when_theyll_tweet.message}
`;
}
else {
document.getElementById('trends').hidden = false;
document.getElementById('no-tweets').hidden = true;
document.getElementById('no-tweets').innerHTML = ``;
document.getElementById('timeline').hidden = false;
if(!pageUser.protected)
document.getElementById('tweet-nav').hidden = false;
}
}
} else {
let blockMessage;
if(LOC.block_sure.message.includes("$SCREEN_NAME$")) {
blockMessage = LOC.block_sure.message.replace("$SCREEN_NAME$", pageUser.screen_name);
} else {
blockMessage = `${LOC.block_sure.message} @${pageUser.screen_name}?`;
}
let blockMessageDesc;
if(LOC.block_sure_desc.message.includes("$SCREEN_NAME$")) {
blockMessageDesc = LOC.block_sure_desc.message.replace("$SCREEN_NAME$", pageUser.screen_name);
} else {
blockMessageDesc = `${LOC.block_sure_desc.message} @${pageUser.screen_name}?`;
}
let modal = createModal(`
${LOC.block.message}
`)
modal.getElementsByClassName('nice-button')[0].addEventListener('click', async () => {
await API.user.block(pageUser.id_str);
pageUser.blocking = true;
document.getElementById('profile-settings-block').classList.add('profile-settings-unblock');
document.getElementById('profile-settings-block').classList.remove('profile-settings-block');
if(LOC.unblock_user.message.includes("$SCREEN_NAME$")) {
document.getElementById('profile-settings-block').innerText = LOC.unblock_user.message.replace("$SCREEN_NAME$", pageUser.screen_name);
} else {
document.getElementById('profile-settings-block').innerText = `${LOC.unblock_user.message} @${pageUser.screen_name}`;
}
document.getElementById('control-unblock').hidden = false;
document.getElementById('control-follow').hidden = true;
document.getElementById('message-user').hidden = true;
document.getElementById("profile-settings-notifications").hidden = true;
document.getElementById("profile-settings-mute").hidden = true;
if(!pageUser.blocked_by) {
//disable timeline
//recycle no-tweets
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `${LOC.you_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)} ${LOC.do_you_want_see_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)}
`;
document.getElementById('timeline').hidden = true;
document.getElementById('tweet-nav').hidden = true;
document.getElementById('see-tweet-btn').addEventListener('click', async () => {
if(pageUser.statuses_count === 0 && !( pageUser.blocked_by || pageUser.blocking || pageUser.protected ) && (subpage === 'profile' || subpage === 'replies' || subpage === 'media')) {
document.getElementById('trends').hidden = true;
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `
${LOC.hasnt_tweeted.message.replace('$SCREEN_NAME$', `${pageUser.screen_name} `)}
${LOC.when_theyll_tweet.message}
`;
}
else {
document.getElementById('no-tweets').hidden = true;
document.getElementById('no-tweets').innerHTML = ``;
document.getElementById('timeline').hidden = false;
if(!pageUser.protected){
document.getElementById('trends').hidden = false;
document.getElementById('tweet-nav').hidden = false;
}
}
});
}
modal.removeModal();
});
}
});
document.getElementById('control-unblock').addEventListener('click', async () => {
if(pageUser.blocking) {
await API.user.unblock(pageUser.id_str);
pageUser.blocking = false;
document.getElementById('profile-settings-block').classList.remove('profile-settings-unblock');
document.getElementById('profile-settings-block').classList.add('profile-settings-block');
if(LOC.block_user.message.includes("$SCREEN_NAME$")) {
document.getElementById('profile-settings-block').innerText = LOC.block_user.message.replace("$SCREEN_NAME$", pageUser.screen_name);
} else {
document.getElementById('profile-settings-block').innerText = `${LOC.block_user.message} @${pageUser.screen_name}`;
}
document.getElementById('control-unblock').hidden = true;
if(!pageUser.blocked_by) {
document.getElementById('control-follow').hidden = false;
document.getElementById("profile-settings-notifications").hidden = false;
document.getElementById("profile-settings-mute").hidden = false;
document.getElementById('message-user').hidden = !pageUser.can_dm;
//enable timeline
//recycle no-tweets
if(pageUser.statuses_count === 0 && !( pageUser.blocked_by || pageUser.blocking || pageUser.protected ) && (subpage === 'profile' || subpage === 'replies' || subpage === 'media')) {
document.getElementById('trends').hidden = true;
document.getElementById('no-tweets').hidden = false;
document.getElementById('no-tweets').innerHTML = `
${LOC.hasnt_tweeted.message.replace('$SCREEN_NAME$', `${pageUser.screen_name} `)}
${LOC.when_theyll_tweet.message}
`;
}
else {
document.getElementById('trends').hidden = false;
document.getElementById('no-tweets').hidden = true;
document.getElementById('no-tweets').innerHTML = ``;
document.getElementById('timeline').hidden = false;
if(!pageUser.protected)
document.getElementById('tweet-nav').hidden = false;
}
}
} else {
}
});
document.getElementById('profile-settings-autotranslate').addEventListener('click', async () => {
let autotranslateProfiles = await new Promise(resolve => {
chrome.storage.sync.get(['autotranslateProfiles'], data => {
resolve(data.autotranslateProfiles);
});
});
if(!autotranslateProfiles) {
autotranslateProfiles = [];
}
if(autotranslateProfiles.includes(pageUser.id_str)) {
autotranslateProfiles.splice(autotranslateProfiles.indexOf(pageUser.id_str), 1);
document.getElementById('profile-settings-autotranslate').innerText = LOC.dont_autotranslate.message;
toAutotranslate = false;
} else {
autotranslateProfiles.push(pageUser.id_str);
document.getElementById('profile-settings-autotranslate').innerText = LOC.autotranslate_tweets.message;
toAutotranslate = true;
}
chrome.storage.sync.set({ autotranslateProfiles });
setTimeout(() => {
location.reload();
}, 100)
});
document.getElementById('profile-settings-mute').addEventListener('click', async () => {
if(pageUser.muting) {
await API.user.unmute(pageUser.id_str);
pageUser.muting = false;
document.getElementById('profile-settings-mute').classList.remove('profile-settings-unmute');
document.getElementById('profile-settings-mute').classList.add('profile-settings-mute');
document.getElementById('profile-settings-mute').innerText = LOC.mute.message;
document.getElementById('profile-name').classList.remove('user-muted');
} else {
await API.user.mute(pageUser.id_str);
pageUser.muting = true;
document.getElementById('profile-settings-mute').classList.add('profile-settings-unmute');
document.getElementById('profile-settings-mute').classList.remove('profile-settings-mute');
document.getElementById('profile-settings-mute').innerText = LOC.unmute.message;
document.getElementById('profile-name').classList.add('user-muted');
}
});
if(document.getElementById('profile-settings-removefollowing')) document.getElementById('profile-settings-removefollowing').addEventListener('click', async () => {
let modal = createModal(`
${LOC.able_in_future.message}
${LOC.remove_from_followers_warn.message}
${LOC.remove_from_followers_button.message}
`.replace('$SCREEN_NAME$', pageUser.screen_name));
modal.getElementsByClassName('nice-button')[0].addEventListener('click', async () => {
await API.user.removeFollower(pageUser.id_str);
pageUser.followed_by = false;
document.getElementById('profile-settings-removefollowing').hidden = true;
document.getElementById('follows-you').hidden = true;
modal.removeModal();
});
});
document.getElementById('profile-settings-lists-action').addEventListener('click', async () => {
let lists = await API.list.getOwnerships(user.id_str, pageUser.id_str);
let modal = createModal(`
`);
let container = document.getElementById('modal-lists');
for(let i in lists) {
let l = lists[i];
let listElement = document.createElement('div');
listElement.classList.add('list-item');
listElement.innerHTML = `
${l.is_member ? LOC.remove.message : LOC.add.message}
`;
container.appendChild(listElement);
listElement.getElementsByClassName('nice-button')[0].addEventListener('click', async () => {
if(l.is_member) {
await API.list.removeMember(l.id_str, pageUser.id_str);
l.is_member = false;
listElement.getElementsByClassName('nice-button')[0].innerText = LOC.add.message;
} else {
await API.list.addMember(l.id_str, pageUser.id_str);
l.is_member = true;
listElement.getElementsByClassName('nice-button')[0].innerText = LOC.remove.message;
}
l.is_member = !l.is_member;
});
}
});
document.getElementById('profile-settings-lists').addEventListener('mousedown', e => {
if(e.button === 1) {
openInNewTab(`https://twitter.com/${pageUser.screen_name}/lists`);
}
});
document.getElementById('profile-settings-lists').addEventListener('click', async () => {
// document.getElementById('loading-box').hidden = false;
history.pushState({}, null, `https://twitter.com/${pageUser.screen_name}/lists`);
everAddedAdditional = false;
mediaToUpload = [];
document.getElementById('profile-media-div').innerHTML = '';
document.getElementById('tweet-to-bg').hidden = true;
document.getElementById('profile-additional').innerHTML = '';
document.getElementById('profile-friends-div').innerHTML = '';
updateSubpage();
updateSelection();
renderLists();
});
document.getElementById('profile-settings-share').addEventListener('click', async () => {
navigator.share({ url: `https://twitter.com/${pageUser.screen_name}` });
});
document.getElementById('profile-settings-copy').addEventListener('click', async () => {
navigator.clipboard.writeText(`https://twitter.com/${pageUser.screen_name}`);
});
if(document.getElementById('profile-settings-copy-id')) document.getElementById('profile-settings-copy-id').addEventListener('click', async () => {
navigator.clipboard.writeText(pageUser.id_str);
});
}
let links = Array.from(document.getElementById('profile-bio').getElementsByTagName('a'));
links.forEach(link => {
let realLink = pageUser.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;
}
});
if(everAddedAdditional) return;
everAddedAdditional = true;
let additionalInfo = document.getElementById('profile-additional');
if(pageUser.location) {
let location = document.createElement('span');
location.classList.add('profile-additional-thing', 'profile-additional-location');
location.innerText = pageUser.location.replace(/\n\n\n\n/g, "\n");
additionalInfo.appendChild(location);
if(vars.enableTwemoji) twemoji.parse(location);
}
if(pageUser.affiliates_highlighted_label) {
let aff = document.createElement('span');
aff.classList.add('profile-additional-thing', 'profile-additional-affiliates');
aff.innerHTML = `
${pageUser.affiliates_highlighted_label.description}
`;
additionalInfo.appendChild(aff);
}
if(pageUser.url) {
let url = document.createElement('a');
url.classList.add('profile-additional-thing', 'profile-additional-url');
let realUrl = pageUser.entities.url.urls[0];
url.innerText = realUrl.display_url;
url.href = realUrl.expanded_url;
if(!url.href.startsWith('https://twitter.com/')) url.target = "_blank";
additionalInfo.appendChild(url);
}
if(pageUser.professional && pageUser.professional.category && pageUser.professional.category[0]) {
let prof = document.createElement('span');
prof.classList.add('profile-additional-thing', 'profile-additional-professional');
prof.innerText = pageUser.professional.category[0].name;
additionalInfo.appendChild(prof);
if(vars.enableTwemoji) twemoji.parse(prof);
}
let joined = document.createElement('span');
joined.classList.add('profile-additional-thing', 'profile-additional-joined');
joined.innerText = `${LOC.joined.message} ${new Date(pageUser.created_at).toLocaleDateString(LANGUAGE.replace("_", "-"), {month: 'long', year: 'numeric', day: 'numeric'})}`;
additionalInfo.appendChild(joined);
if(pageUser.birthdate) {
let birth = document.createElement('span');
birth.classList.add('profile-additional-thing', 'profile-additional-birth');
if(user.id_str === pageUser.id_str) {
birth.classList.add('profile-additional-birth-me');
}
if(pageUser.birthdate.year && typeof pageUser.birthdate.month === 'number') {
birth.innerText = `${LOC.born.message} ${months[pageUser.birthdate.month-1].replace("$NUMBER$", pageUser.birthdate.day)}, ${pageUser.birthdate.year}`;
} else if(typeof pageUser.birthdate.month === 'number') {
birth.innerText = `${LOC.born.message} ${months[pageUser.birthdate.month-1].replace("$NUMBER$", pageUser.birthdate.day)}`;
} else if(pageUser.birthdate.year) {
birth.innerText = `${LOC.born.message} ${pageUser.birthdate.year}`;
}
let date = new Date();
if(pageUser.birthdate.month-1 === date.getMonth() && pageUser.birthdate.day === date.getDate()) {
birth.innerText += ' ' + LOC.birthday_today.message;
birth.classList.add('profile-additional-birth-today');
}
additionalInfo.appendChild(birth);
}
setTimeout(() => {
document.getElementById('loading-box').hidden = true;
}, 10);
};
async function renderTimeline(append = false, sliceAmount = 0) {
let timelineContainer = document.getElementById('timeline');
if(!append) timelineContainer.innerHTML = '';
let data = timeline.data.slice(sliceAmount, timeline.data.length);;
if(pinnedTweet && subpage === "profile" && !append) await appendTweet(pinnedTweet, timelineContainer, {
top: {
text: LOC.pinned_tweet.message,
icon: "\uf003",
color: "var(--link-color)",
class: 'pinned'
},
bigFont: false
})
for(let i in data) {
let t = data[i];
if(!t) continue;
if(pinnedTweet && t.id_str === pinnedTweet.id_str) continue;
if (t.retweeted_status) {
if(pageUser.id_str === user.id_str) t.retweeted_status.current_user_retweet = t;
await appendTweet(t.retweeted_status, timelineContainer, {
top: {
text: `${escapeHTML(t.user.name)} ${LOC.retweeted.message}`,
icon: "\uf006",
color: "#77b255",
class: 'retweet-label'
}
});
} else {
if (t.self_thread) {
let selfThreadTweet = timeline.data.find(tweet => tweet.id_str === t.self_thread.id_str);
if (selfThreadTweet && selfThreadTweet.id_str !== t.id_str && seenThreads.indexOf(selfThreadTweet.id_str) === -1) {
await appendTweet(selfThreadTweet, timelineContainer, {
selfThreadContinuation: true,
bigFont: selfThreadTweet.favorite_count > averageLikeCount*1.2 && selfThreadTweet.favorite_count > 3 && (!selfThreadTweet.full_text || selfThreadTweet.full_text.length < 250)
});
await appendTweet(t, timelineContainer, {
noTop: true,
bigFont: t.favorite_count > averageLikeCount*1.2 && t.favorite_count > 3 && (!t.full_text || t.full_text.length < 250)
});
seenThreads.push(selfThreadTweet.id_str);
} else {
await appendTweet(t, timelineContainer, {
selfThreadButton: true,
bigFont: t.favorite_count > averageLikeCount*1.2 && t.favorite_count > 3 && (!t.full_text || t.full_text.length < 250)
});
}
} else {
await appendTweet(t, timelineContainer, {
bigFont: t.favorite_count > averageLikeCount*1.2 && t.favorite_count > 3 && (!t.full_text || t.full_text.length < 250)
});
}
}
};
document.getElementById('loading-box').hidden = true;
loadingNewTweets = false;
return true;
}
function renderNewTweetsButton() {
if (timeline.toBeUpdated > 0) {
document.getElementById('new-tweets').hidden = false;
document.getElementById('new-tweets').innerText = LOC.see_new_tweets.message;
} else {
document.getElementById('new-tweets').hidden = true;
}
}
document.addEventListener('clearActiveTweet', () => {
if(activeTweet) {
activeTweet.classList.remove('tweet-active');
}
activeTweet = undefined;
});
document.addEventListener('findActiveTweet', () => {
let tweets = Array.from(document.getElementsByClassName('tweet'));
if(activeTweet) {
activeTweet.classList.remove('tweet-active');
}
let scrollPoint = scrollY + innerHeight/2;
activeTweet = tweets.find(t => scrollPoint > t.offsetTop && scrollPoint < t.offsetTop + t.offsetHeight);
if(activeTweet) {
activeTweet.classList.add('tweet-active');
}
});
let loadingNewTweets = true;
let lastTweetDate = 0;
let activeTweet;
let tweetsToLoad = {};
let lastScroll = Date.now();
let loadingFollowing = false;
let loadingFollowers = false;
let loadingFollowersYouKnow = false;
let followingMoreBtn, followersMoreBtn, followersYouFollowMoreBtn;
setTimeout(async () => {
if(!vars) {
await loadVars();
}
while(!LOC || !LOC.january) {
await sleep(10);
}
months = [LOC.january.message, LOC.february.message, LOC.march.message, LOC.april.message, LOC.may.message, LOC.june.message, LOC.july.message, LOC.august.message, LOC.september.message, LOC.october.message, LOC.november.message, LOC.december.message];
// weird bug
if(!document.getElementById('new-tweets')) {
return setTimeout(() => location.reload(), 500);
}
try {
document.getElementById('new-tweets').addEventListener('click', () => {
timeline.toBeUpdated = 0;
timeline.data = timeline.dataToUpdate;
timeline.dataToUpdate = [];
renderNewTweetsButton();
renderTimeline();
});
} catch(e) {
setTimeout(() => location.reload(), 500);
console.error(e);
return;
}
// mouse
let banner = document.getElementById('profile-banner');
let navProfileInfo = document.getElementById('nav-profile-info');
document.addEventListener('scroll', async () => {
lastScroll = Date.now();
// find active tweet by scroll amount
if(Date.now() - lastTweetDate > 50) {
lastTweetDate = Date.now();
let tweets = Array.from(document.getElementsByClassName('tweet'));
let scrollPoint = scrollY + innerHeight/2;
let newActiveTweet = tweets.find(t => scrollPoint > t.offsetTop && scrollPoint < t.offsetTop + t.offsetHeight);
if(!activeTweet || (newActiveTweet && !activeTweet.className.startsWith(newActiveTweet.className))) {
if(activeTweet) {
activeTweet.classList.remove('tweet-active');
}
if(newActiveTweet) newActiveTweet.classList.add('tweet-active');
if(vars.autoplayVideos && !document.getElementsByClassName('modal')[0]) {
if(activeTweet) {
let video = activeTweet.querySelector('.tweet-media > video[controls]');
if(video) {
video.pause();
}
}
if(newActiveTweet) {
let newVideo = newActiveTweet.querySelector('.tweet-media > video[controls]');
let newVideoOverlay = newActiveTweet.querySelector('.tweet-media > .tweet-media-video-overlay');
if(newVideo && !newVideo.ended) {
newVideo.play();
} else if(newVideoOverlay && !newVideoOverlay.style.display) {
newVideoOverlay.click();
}
}
}
activeTweet = newActiveTweet;
}
}
// make user nav appear
if(window.scrollY >= 600) {
if(!navProfileInfo.style.opacity) {
navProfileInfo.style.opacity = 1;
}
} else {
if(navProfileInfo.style.opacity) {
navProfileInfo.style.opacity = '';
}
}
// banner scroll
banner.style.top = `${5+Math.min(window.scrollY/4, 470/4)}px`;
// load more stuff
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 1000) {
if(subpage === 'following') {
if(!loadingFollowing) followingMoreBtn.click();
return;
}
if(subpage === 'followers') {
if(!loadingFollowers) followersMoreBtn.click();
return;
}
if(subpage === 'followers_you_follow') {
if(!loadingFollowersYouKnow) followersYouFollowMoreBtn.click();
return;
}
if (loadingNewTweets || timeline.data.length === 0 || stopLoad) return;
loadingNewTweets = true;
let tl;
try {
if (!user_protected && !user_blocked_by) {
if(subpage === "likes") {
let data = await API.user.getFavorites(pageUser.id_str, favoritesCursor);
tl = data.tl;
favoritesCursor = data.cursor;
} else {
if(subpage === 'media') {
tl = await API.user.getMediaTweets(pageUser.id_str, mediaCursor);
mediaCursor = tl.cursor;
tl = tl.tweets;
} else {
tl = await API.user.getTweetsV2(pageUser.id_str, tweetsCursor, subpage !== 'profile');
tweetsCursor = tl.cursor;
tl = tl.tweets;
}
}
} else if (user_blocked_by) {
document.getElementById("timeline").innerHTML = `${LOC.blocked_by_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)} ${LOC.why_you_cant_see_block_user.message.replaceAll("$SCREEN_NAME$",pageUser.screen_name)}
`;
return;
} else if (user_protected) {
document.getElementById("timeline").innerHTML = `${LOC.user_protected.message} ${LOC.follow_to_see.message.replace("$SCREEN_NAME$",pageUser.screen_name)}
`;
return;
} /*else if (user_blocking) {
document.getElementById("timeline").innerHTML = `${LOC.you_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)} ${LOC.do_you_want_see_blocked_user.message.replace("$SCREEN_NAME$",pageUser.screen_name)}
`;
return;
}*/
} catch (e) {
console.error(e);
loadingNewTweets = false;
return;
}
let originalLength = timeline.data.length;
timeline.data = timeline.data.concat(tl);
averageLikeCount = timeline.data.filter(t => !t.retweeted_status).map(t => t.favorite_count).sort((a, b) => a - b)[Math.floor(timeline.data.length/2)];
if(subpage === 'profile') {
if(!tweetsCursor) {
stopLoad = true;
}
} else {
if(previousLastTweet && previousLastTweet.id_str === timeline.data[timeline.data.length - 1].id_str) return stopLoad = true;
}
previousLastTweet = timeline.data[timeline.data.length - 1];
await renderTimeline(true, originalLength);
}
}, { passive: true });
// document.addEventListener('mousemove', e => {
// if(Date.now() - lastScroll > 10) {
// let t = e.target;
// if(t.className.includes('tweet ') || t.className === 'tweet-interact' || t.className === 'tweet-body' || t.className === 'tweet-media') {
// if(t.className === 'tweet-interact' || t.className === 'tweet-media') t = t.parentElement.parentElement;
// else if(t.className === 'tweet-body') t = t.parentElement;
// let id = t.className.split('id-')[1];
// if(!id) return;
// id = id.split(' ')[0];
// if(!tweetsToLoad[id]) tweetsToLoad[id] = 1;
// else tweetsToLoad[id]++;
// if(tweetsToLoad[id] === 15) {
// API.tweet.getRepliesV2(id);
// API.tweet.getLikers(id);
// t.classList.add('tweet-preload');
// console.log(`Preloading ${id}`);
// }
// }
// }
// });
// buttons
document.getElementById('tweet-to').addEventListener('click', () => {
document.getElementById('navbar-tweet-button').click();
setTimeout(() => {
document.getElementsByClassName('navbar-new-tweet-text')[0].value = `@${pageUser.screen_name} `;
}, 10);
});
let tweetNavMoreMenu = document.getElementById('tweet-nav-more-menu');
let tweetNavClicked = false;
let tweetNavMoreMenuHR = document.getElementById('tweet-nav-more-menu-hr');
let tweetNavMoreMenuHNR = document.getElementById('tweet-nav-more-menu-hnr');
document.getElementById('tweet-nav-more').addEventListener('click', () => {
if (tweetNavMoreMenu.hidden) {
tweetNavMoreMenu.hidden = false;
if(subpage === 'replies') {
tweetNavMoreMenu.style.height = '77px';
tweetNavMoreMenuHNR.hidden = false;
document.getElementById('tweet-nav-more-menu-hnr-label').hidden = false;
}
}
if(tweetNavClicked) return;
tweetNavClicked = true;
setTimeout(() => {
function closeMenu(e) {
if(e.target.closest('#tweet-nav-more-menu')) {
return;
}
tweetNavClicked = false;
setTimeout(() => {
tweetNavMoreMenu.hidden = true;
tweetNavMoreMenu.style.height = '';
tweetNavMoreMenuHNR.hidden = true;
document.getElementById('tweet-nav-more-menu-hnr-label').hidden = true;
}, 50);
document.body.removeEventListener('click', closeMenu);
}
document.body.addEventListener('click', closeMenu);
}, 50);
});
function updateHideStyle() {
let style = '';
if(tweetNavMoreMenuHR.checked) {
style += `.tweet-top-retweet-label { display: none !important; }`;
}
if(tweetNavMoreMenuHNR.checked) {
style += `.tweet-non-reply { display: none !important; }`;
}
document.getElementById('style-hide-retweets').innerHTML = style;
}
tweetNavMoreMenuHR.addEventListener('change', updateHideStyle);
tweetNavMoreMenuHNR.addEventListener('change', updateHideStyle);
document.getElementById('wtf-refresh').addEventListener('click', async () => {
renderDiscovery(false);
});
followingMoreBtn = document.getElementById('following-more');
followingMoreBtn.addEventListener('click', async e => {
if(!followingCursor || loadingFollowing) return;
e.target.innerText = LOC.loading.message;
renderFollowing(false, followingCursor);
});
followersMoreBtn = document.getElementById('followers-more');
followersMoreBtn.addEventListener('click', async e => {
if(!followersCursor || loadingFollowers) return;
e.target.innerText = LOC.loading.message;
renderFollowers(false, followersCursor);
});
followersYouFollowMoreBtn = document.getElementById('followers_you_follow-more');
followersYouFollowMoreBtn.addEventListener('click', async e => {
if(!followersYouKnowCursor || loadingFollowersYouKnow) return;
e.target.innerText = LOC.loading.message;
renderFollowersYouFollow(false, followersYouKnowCursor);
});
function updatePath(e) {
if(e.target.closest('.tweet-nav-active') || e.target.classList.contains('profile-stat-active') || e.target.closest('.profile-stat-disabled')) {
return e.preventDefault();
}
e.preventDefault();
let el = e.target;
if(!el) return;
if(!el.href) el = el.parentElement;
history.pushState({}, null, el.href);
updateSubpage();
updateSelection();
timeline = {
data: [],
dataToUpdate: [],
toBeUpdated: 0
}
seenThreads = [];
pinnedTweet = undefined;
tweetsCursor = undefined;
favoritesCursor = undefined;
followersCursor = undefined;
followingCursor = undefined;
followersYouKnowCursor = undefined;
mediaCursor = undefined;
if(window.scrollY > 400) window.scrollTo(0, 400);
if(subpage === 'following') {
renderFollowing();
} else if(subpage === 'followers') {
renderFollowers();
} else if(subpage === 'followers_you_follow') {
renderFollowersYouFollow();
} else if(subpage === 'lists') {
renderLists();
} else {
loadingNewTweets = true;
updateTimeline();
}
}
document.getElementById('tweet-nav-tweets').addEventListener('click', updatePath);
document.getElementById('tweet-nav-replies').addEventListener('click', updatePath);
document.getElementById('tweet-nav-media').addEventListener('click', updatePath);
if(document.getElementById('profile-media-text')) document.getElementById('profile-media-text').addEventListener('click', updatePath);
document.getElementById('profile-stat-tweets-link').addEventListener('click', updatePath);
document.getElementById('profile-stat-following-link').addEventListener('click', updatePath);
document.getElementById('profile-stat-followers-link').addEventListener('click', updatePath);
document.getElementById('profile-stat-favorites-link').addEventListener('click', updatePath);
document.getElementById('profile-stat-media-link').addEventListener('click', updatePath);
document.getElementById('profile-friends-text').addEventListener('click', updatePath);
document.addEventListener('click', async e => {
let el = e.target;
if(!el) return;
if(el.tagName !== 'A') el = el.closest('a');
if(!el) return;
if(el.tagName === "A") {
let path;
try {
let url = new URL(el.href);
path = url.pathname;
if(url.hostname !== 'twitter.com') return;
} catch(e) {
return;
}
if(/^\/[A-z-0-9-_]{1,15}$/.test(path) && ["/home", "/", "/notifications", "/messages", "/settings", "/search", "/explore", "/login", "/register", "/logout"].indexOf(path) === -1) {
if(document.querySelector(".modal")) return;
e.preventDefault();
window.scrollTo(0, 0);
mediaToUpload = [];
loadingNewTweets = true;
document.getElementById('loading-box').hidden = false;
everAddedAdditional = false;
document.getElementById('timeline').innerHTML = `
`;
document.getElementById('profile-media-div').innerHTML = '';
document.getElementById('tweet-to-bg').hidden = true;
document.getElementById('profile-additional').innerHTML = '';
document.getElementById('profile-friends-div').innerHTML = '';
history.pushState({}, null, `https://twitter.com/${path.substring(1)}`);
updateSubpage();
updateSelection();
await updateUserData();
updateTimeline();
renderDiscovery();
}
}
});
window.addEventListener("popstate", async () => {
if(document.querySelector('.tweet-viewer')) return;
let path = location.pathname;
if(path.endsWith("/")) path = path.substring(0, path.length - 1);
if(isProfilePath(path) || (path.split('/').length === 3 && location.pathname.endsWith('/following') || location.pathname.endsWith('/followers') || location.pathname.endsWith('/followers_you_follow') || location.pathname.endsWith('/lists') || location.pathname.endsWith('/media') || location.pathname.endsWith('/likes') || location.pathname.endsWith('/with_replies'))) {
document.getElementById('loading-box').hidden = false;
everAddedAdditional = false;
loadingNewTweets = true;
mediaToUpload = [];
document.getElementById('profile-media-div').innerHTML = '';
document.getElementById('tweet-to-bg').hidden = true;
document.getElementById('profile-additional').innerHTML = '';
document.getElementById('profile-friends-div').innerHTML = '';
updateSubpage();
updateSelection();
document.getElementById('timeline').innerHTML = '';
await updateUserData();
updateTimeline();
renderDiscovery();
}
});
document.getElementById('user-search-input').addEventListener('keydown', e => {
if(e.key === 'Enter') {
document.getElementById('user-search-icon').click();
}
});
document.getElementById('user-search-icon').addEventListener("click", () => {
document.getElementById('search-input').value = document.getElementById('user-search-input').value + ` from:${pageUser.screen_name}`;
document.getElementById('search-icon').click();
})
let mediaDiv = document.getElementById('profile-media-div');
let mediaText = document.getElementById('profile-media-text');
let mediaObserver = new MutationObserver(() => {
mediaText.hidden = mediaDiv.childElementCount === 0;
})
mediaObserver.observe(mediaDiv, {
childList: true
});
// Update dates every minute
setInterval(() => {
let tweetDates = Array.from(document.getElementsByClassName('tweet-time'));
let tweetQuoteDates = Array.from(document.getElementsByClassName('tweet-time-quote'));
let all = [...tweetDates, ...tweetQuoteDates];
all.forEach(date => {
date.innerText = timeElapsed(+date.dataset.timestamp);
});
}, 60000);
// Custom events
document.addEventListener('newTweet', e => {
if(pageUser.id_str === user.id_str) {
let tweet = e.detail;
if(pinnedTweet) {
let firstTweet = document.getElementById('timeline').firstChild;
appendTweet(tweet, document.getElementById('timeline'), { after: firstTweet, disableAfterReplyCounter: true, bigFont: tweet.favorite_count > averageLikeCount*1.2 && tweet.favorite_count > 3 });
} else {
appendTweet(tweet, document.getElementById('timeline'), { prepend: true, bigFont: tweet.favorite_count > averageLikeCount*1.2 && tweet.favorite_count > 3 });
}
}
});
// Customization
let r = document.querySelector(':root');
let profileLinkColor = document.getElementById('profile-link-color');
let colorSyncButton = document.getElementById('color-sync-button');
let cssSyncButton = document.getElementById('css-sync-button');
let cssLoadButton = document.getElementById('css-load-button');
let darkModeVars = document.getElementById('dark-mode-vars');
let lightModeVars = document.getElementById('light-mode-vars');
let cssTextArea = document.getElementById('profile-css-textarea');
let saveDraft = document.getElementById('save-draft');
let loadDraft = document.getElementById('load-draft');
darkModeVars.addEventListener('change', async () => {
if(isDarkModeEnabled) {
await switchDarkMode(true);
let vars = parseVariables(darkModeVars.value);
for(let i in vars) {
if(r.style.getPropertyValue(i)) r.style.setProperty(i, vars[i]);
}
}
});
lightModeVars.addEventListener('change', async () => {
if(!isDarkModeEnabled) {
await switchDarkMode(false);
let vars = parseVariables(lightModeVars.value);
for(let i in vars) {
if(r.style.getPropertyValue(i)) r.style.setProperty(i, vars[i]);
}
}
});
cssTextArea.addEventListener('change', () => {
if(!customCSS) {
customCSS = document.createElement('style');
customCSS.id = 'oldtwitter-custom-css';
document.head.appendChild(customCSS);
}
customCSS.innerHTML = cssTextArea.value;
});
darkModeVars.addEventListener('keydown', async e => {
if(e.keyCode === 83 && e.ctrlKey) {
e.preventDefault();
e.stopImmediatePropagation();
if(isDarkModeEnabled) {
await switchDarkMode(true);
let vars = parseVariables(darkModeVars.value);
for(let i in vars) {
if(r.style.getPropertyValue(i)) r.style.setProperty(i, vars[i]);
}
}
}
});
lightModeVars.addEventListener('keydown', async e => {
if(e.keyCode === 83 && e.ctrlKey) {
e.preventDefault();
e.stopImmediatePropagation();
if(!isDarkModeEnabled) {
await switchDarkMode(false);
let vars = parseVariables(lightModeVars.value);
for(let i in vars) {
if(r.style.getPropertyValue(i)) r.style.setProperty(i, vars[i]);
}
}
}
});
cssTextArea.addEventListener('keydown', e => {
if(e.key === "Tab") {
e.preventDefault();
e.stopImmediatePropagation();
let pos = cssTextArea.selectionStart;
cssTextArea.value = cssTextArea.value.slice(0, pos) + " " + cssTextArea.value.slice(pos);
cssTextArea.selectionStart = cssTextArea.selectionEnd = pos + 2;
} else if(e.keyCode === 83 && e.ctrlKey) {
e.preventDefault();
e.stopImmediatePropagation();
if(!customCSS) {
customCSS = document.createElement('style');
customCSS.id = 'oldtwitter-custom-css';
document.head.appendChild(customCSS);
}
customCSS.innerHTML = cssTextArea.value;
}
});
saveDraft.addEventListener('click', () => {
chrome.storage.local.set({
cssDraft: {
darkVars: darkModeVars.value,
lightVars: lightModeVars.value,
css: cssTextArea.value
}
});
toast.info(LOC.draft_saved.message);
});
loadDraft.addEventListener('click', () => {
chrome.storage.local.get(['cssDraft'], async d => {
if(d.cssDraft) {
if(!d.cssDraft.darkVars && !d.cssDraft.lightVars && !d.cssDraft.css) return toast.error(LOC.no_draft.message);
darkModeVars.value = d.cssDraft.darkVars;
lightModeVars.value = d.cssDraft.lightVars;
cssTextArea.value = d.cssDraft.css;
toast.info(LOC.draft_loaded.message);
if(!customCSS) {
customCSS = document.createElement('style');
customCSS.id = 'oldtwitter-custom-css';
document.head.appendChild(customCSS);
}
customCSS.innerHTML = cssTextArea.value;
if(isDarkModeEnabled) {
await switchDarkMode(true);
let vars = parseVariables(darkModeVars.value);
for(let i in vars) {
if(r.style.getPropertyValue(i)) r.style.setProperty(i, vars[i]);
}
} else {
await switchDarkMode(false);
let vars = parseVariables(lightModeVars.value);
for(let i in vars) {
if(r.style.getPropertyValue(i)) r.style.setProperty(i, vars[i]);
}
}
} else {
toast.error(LOC.no_draft.message);
}
});
});
cssSyncButton.addEventListener('click', async () => {
cssSyncButton.disabled = true;
try {
let res = await fetch(`https://dimden.dev/services/twitter_link_colors/v2/setcss`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
css: cssTextArea.value,
dark_mode_vars: darkModeVars.value,
light_mode_vars: lightModeVars.value,
private_token: await getOtAuthToken(!(user.followers_count >= 5000 && cssEligibleAuto && !cssEligible))
})
}).then(i => i.text());
if(res === 'auth_error') {
chrome.storage.local.get(["otPrivateTokens"], data => {
delete data.otPrivateTokens[pageUser.id_str];
chrome.storage.local.set({ otPrivateTokens: data.otPrivateTokens });
cssSyncButton.disabled = false;
alert(LOC.invalid_auth_token.message);
});
} else if(res === 'set') {
chrome.storage.local.get(["profileCustomCSS"], async data => {
if(!data.profileCustomCSS) {
data.profileCustomCSS = {};
}
data.profileCustomCSS[pageUser.id_str] = {
css: cssTextArea.value,
darkModeVars: darkModeVars.value,
lightModeVars: lightModeVars.value
};
chrome.storage.local.set({ profileCustomCSS: data.profileCustomCSS });
});
alert(LOC.css_set.message);
} else {
alert(res);
}
} catch(e) {
console.error(e);
alert(LOC.error_setting_css.message);
} finally {
cssSyncButton.disabled = false;
}
});
cssLoadButton.addEventListener('click', async () => {
fetch(`https://dimden.dev/services/twitter_link_colors/v2/get_data/${pageUser.id_str}`).then(r => r.json()).then(data => {
cssTextArea.value = data.css;
darkModeVars.value = data.css_vars_dark;
lightModeVars.value = data.css_vars_light;
if(data.css) {
if(!customCSS) {
customCSS = document.createElement('style');
customCSS.id = 'oldtwitter-custom-css';
document.head.appendChild(customCSS);
}
customCSS.innerHTML = data.css;
}
if(data.css_vars_dark && isDarkModeEnabled) {
let vars = parseVariables(data.css_vars_dark);
for(let i in vars) {
r.style.setProperty(i, vars[i]);
}
} else if(data.css_vars_light && !isDarkModeEnabled) {
let vars = parseVariables(data.css_vars_light);
for(let i in vars) {
r.style.setProperty(i, vars[i]);
}
} else {
switchDarkMode(isDarkModeEnabled);
}
});
});
colorSyncButton.addEventListener('click', async () => {
colorSyncButton.disabled = true;
let color = profileLinkColor.value;
if(color.startsWith('#')) color = color.slice(1);
try {
let res = await fetch(`https://dimden.dev/services/twitter_link_colors/v2/setcolor`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
color,
private_token: await getOtAuthToken()
})
}).then(i => i.text());
if(res === 'auth_error') {
chrome.storage.local.get(["otPrivateTokens"], data => {
delete data.otPrivateTokens[pageUser.id_str];
chrome.storage.local.set({ otPrivateTokens: data.otPrivateTokens });
colorSyncButton.disabled = false;
alert(LOC.invalid_auth_token.message);
});
} else if(res === 'error') {
alert(LOC.error_setting_color.message);
} else {
alert(LOC.link_color_set.message);
chrome.storage.local.get(["linkColors"], async lc => {
let linkColors = lc.linkColors || {};
linkColors[user.id_str] = color;
chrome.storage.local.set({ linkColors });
});
}
} catch(e) {
console.error(e);
alert(LOC.error_setting_color.message);
} finally {
colorSyncButton.disabled = false;
}
});
// Run
updateSubpage();
await updateUserData();
if(subpage !== 'following' && subpage !== 'followers' && subpage !== 'followers_you_follow' && subpage !== 'lists') updateTimeline();
else if(subpage === 'following') {
renderFollowing();
} else if(subpage === 'followers') {
renderFollowers();
} else if(subpage === 'followers_you_follow') {
renderFollowersYouFollow();
} else if(subpage === 'lists') {
renderLists();
}
if(location.hash === "#dm") {
setTimeout(() => {
let event = new CustomEvent('messageUser', { detail: { id: `${user.id_str}-${pageUser.id_str}`, user: pageUser } });
document.dispatchEvent(event);
location.hash = "";
}, 1000);
}
renderDiscovery();
renderTrends(true);
setInterval(() => renderDiscovery(false), 60000 * 5);
setInterval(() => renderTrends(true), 60000 * 5);
}, 50);