Extension to return old Twitter layout from 2015.
1let user = {};
2let tlCursor = null;
3let end = false;
4let linkColors = {};
5let activeTweet;
6let subpage = new URLSearchParams(location.search).get('page');
7let nid = new URLSearchParams(location.search).get('nid');
8
9function updateUserData() {
10 API.account.verifyCredentials().then(async u => {
11 user = u;
12 userDataFunction(u);
13 renderUserData();
14 }).catch(e => {
15 if (e === "Not logged in") {
16 window.location.href = "https://twitter.com/i/flow/login?newtwitter=true";
17 }
18 console.error(e);
19 });
20}
21// Render
22function renderUserData() {
23 document.getElementById('user-name').innerText = user.name;
24 document.getElementById('user-name').classList.toggle('user-verified', user.verified);
25 document.getElementById('user-name').classList.toggle('user-protected', user.protected);
26
27 document.getElementById('user-handle').innerText = `@${user.screen_name}`;
28 document.getElementById('user-tweets').innerText = Number(user.statuses_count).toLocaleString().replace(/\s/g, ',');
29 if(user.statuses_count >= 100000) {
30 let style = document.createElement('style');
31 style.innerText = `
32 .user-stat-div > h1 { font-size: 18px !important }
33 .user-stat-div > h2 { font-size: 13px !important }
34 `;
35 document.head.appendChild(style);
36 }
37 document.getElementById('user-following').innerText = Number(user.friends_count).toLocaleString().replace(/\s/g, ',');
38 document.getElementById('user-followers').innerText = Number(user.followers_count).toLocaleString().replace(/\s/g, ',');
39 document.getElementById('user-banner').src = user.profile_banner_url;
40 document.getElementById('user-avatar').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", "_400x400");
41 document.getElementById('wtf-viewall').href = `https://twitter.com/i/connect_people?newtwitter=true&user_id=${user.id_str}`;
42 document.getElementById('user-avatar-link').href = `https://twitter.com/${user.screen_name}`;
43 document.getElementById('user-info').href = `https://twitter.com/${user.screen_name}`;
44
45 document.getElementById('loading-box').hidden = true;
46 if(vars.enableTwemoji) twemoji.parse(document.getElementById('user-name'));
47
48 if(document.getElementById('user-stats').clientWidth > 300) {
49 let style = document.createElement('style');
50 style.innerHTML = `.user-stat-div > h2 { font-size: 10px !important }`;
51 document.head.appendChild(style);
52 }
53}
54async function renderDeviceNotificationTimeline(cursor) {
55 let tl = await API.notifications.getDeviceFollowTweets(cursor);
56 let container = document.getElementById('timeline');
57 if (tl.cursor) {
58 tlCursor = tl.cursor;
59 } else {
60 end = true;
61 }
62 tl = tl.list;
63 if(tl.length === 0 && cursor) {
64 end = true;
65 return;
66 }
67 for (let i = 0; i < tl.length; i++) {
68 let t = tl[i];
69 if (t.retweeted_status) {
70 await appendTweet(t.retweeted_status, container, {
71 bigFont: false,
72 top: {
73 text: `<a href="https://twitter.com/${t.user.screen_name}">${escapeHTML(t.user.name)}</a> ${LOC.retweeted.message}`,
74 icon: "\uf006",
75 color: "#77b255",
76 class: 'retweet-label'
77 }
78 });
79 } else {
80 await appendTweet(t, container, {
81 bigFont: t.full_text.length < 75
82 });
83 }
84 }
85}
86async function renderLikesTimeline() {
87 document.getElementById("itl-header").innerText = LOC.likes.message;
88 document.getElementsByTagName('title')[0].innerText = `${LOC.likes.message} - OldTwitter`;
89 let tl = await API.notifications.view(nid);
90 let tweetContainer = document.getElementById('timeline');
91 let userContainer = document.getElementById('user-list');
92 for(let i in tl) {
93 let d = tl[i];
94 if(d.type === 'tweet') {
95 if (d.data.retweeted_status) {
96 await appendTweet(d.data.retweeted_status, tweetContainer, {
97 bigFont: false,
98 top: {
99 text: `<a href="https://twitter.com/${d.data.user.screen_name}">${escapeHTML(d.data.user.name)}</a> ${LOC.retweeted.message}`,
100 icon: "\uf006",
101 color: "#77b255",
102 class: 'retweet-label'
103 }
104 });
105 } else {
106 await appendTweet(d.data, tweetContainer, {
107 bigFont: d.data.full_text.length < 75
108 });
109 }
110 } else if(d.type === 'user') {
111 await appendUser(d.data, userContainer);
112 }
113 }
114}
115
116let lastScroll = Date.now();
117let loadingNewTweets = false;
118let lastTweetDate = 0;
119
120setTimeout(async () => {
121 if(!vars) {
122 await loadVars();
123 }
124
125 if(!subpage || !['likes', 'device_follow'].includes(subpage) || (subpage === 'likes' && !nid)) {
126 location.href = 'https://twitter.com/home';
127 }
128
129 // weird bug
130 try {
131 document.getElementById('wtf-refresh').addEventListener('click', async () => {
132 renderDiscovery(false);
133 });
134 } catch(e) {
135 setTimeout(() => location.reload(), 500);
136 console.error(e);
137 return;
138 }
139 document.addEventListener('scroll', async () => {
140 lastScroll = Date.now();
141 // find active tweet by scroll amount
142 if(Date.now() - lastTweetDate > 50) {
143 lastTweetDate = Date.now();
144 let tweets = Array.from(document.getElementsByClassName('tweet'));
145
146 let scrollPoint = scrollY + innerHeight/2;
147 let newActiveTweet = tweets.find(t => scrollPoint > t.offsetTop && scrollPoint < t.offsetTop + t.offsetHeight);
148 if(!activeTweet || (newActiveTweet && !activeTweet.className.startsWith(newActiveTweet.className))) {
149 if(activeTweet) {
150 activeTweet.classList.remove('tweet-active');
151 }
152 if(newActiveTweet) newActiveTweet.classList.add('tweet-active');
153 if(vars.autoplayVideos && !document.getElementsByClassName('modal')[0]) {
154 if(activeTweet) {
155 let video = activeTweet.querySelector('.tweet-media > video[controls]');
156 if(video) {
157 video.pause();
158 }
159 }
160 if(newActiveTweet) {
161 let newVideo = newActiveTweet.querySelector('.tweet-media > video[controls]');
162 let newVideoOverlay = newActiveTweet.querySelector('.tweet-media > .tweet-media-video-overlay');
163 if(newVideo && !newVideo.ended) {
164 newVideo.play();
165 } else if(newVideoOverlay && !newVideoOverlay.style.display) {
166 newVideoOverlay.click();
167 }
168 }
169 }
170 activeTweet = newActiveTweet;
171 }
172 }
173
174 // loading new tweets
175 if (subpage === 'device_follow' && (window.innerHeight + window.scrollY) >= document.body.offsetHeight - 500 && !end) {
176 if (loadingNewTweets) return;
177 loadingNewTweets = true;
178 await renderDeviceNotificationTimeline(tlCursor);
179 setTimeout(() => {
180 loadingNewTweets = false;
181 }, 250);
182 }
183 }, { passive: true });
184
185 // Run
186 updateUserData();
187 renderDiscovery();
188 renderTrends();
189 if(subpage === 'device_follow') renderDeviceNotificationTimeline();
190 else if(subpage === 'likes') renderLikesTimeline();
191 setInterval(updateUserData, 60000 * 3);
192 setInterval(() => renderDiscovery(false), 60000 * 15);
193 setInterval(renderTrends, 60000 * 5);
194}, 50);