Extension to return old Twitter layout from 2015.
1let user = {};
2let customVars = {};
3let linkColor
4
5function getAllCSSVariables() {
6 const vars = {};
7 Array.from(document.styleSheets)
8 .forEach(styleSheet => {
9 if (!styleSheet.href && styleSheet.cssRules) {
10 Array.from(styleSheet.cssRules).forEach(cssRule => {
11 if (cssRule.selectorText === ':root') {
12 const css = cssRule.cssText.split('{')[1].replace('}', '').split(';');
13 for (const cssProp of css) {
14 const [property, value] = cssProp.split(':');
15 if (property.trim().indexOf('--') === 0) {
16 vars[property.trim()] = value.trim();
17 }
18 }
19 }
20 });
21 }
22 });
23 return vars;
24}
25
26function updateUserData() {
27 API.account.verifyCredentials().then(async u => {
28 user = u;
29 userDataFunction(u);
30 renderUserData();
31 }).catch(e => {
32 if (e === "Not logged in") {
33 window.location.href = "https://twitter.com/i/flow/login?newtwitter=true";
34 }
35 console.error(e);
36 });
37}
38// Render
39function renderUserData() {
40 document.getElementById('user-name').innerText = user.name;
41 document.getElementById('user-name').classList.toggle('user-verified', user.verified);
42 document.getElementById('user-name').classList.toggle('user-protected', user.protected);
43
44 document.getElementById('user-handle').innerText = `@${user.screen_name}`;
45 document.getElementById('user-tweets').innerText = Number(user.statuses_count).toLocaleString().replace(/\s/g, ',');
46 if(user.statuses_count >= 100000) {
47 let style = document.createElement('style');
48 style.innerText = `
49 .user-stat-div > h1 { font-size: 18px !important }
50 .user-stat-div > h2 { font-size: 13px !important }
51 `;
52 document.head.appendChild(style);
53 }
54 document.getElementById('user-following').innerText = Number(user.friends_count).toLocaleString().replace(/\s/g, ',');
55 document.getElementById('user-followers').innerText = Number(user.followers_count).toLocaleString().replace(/\s/g, ',');
56 document.getElementById('user-tweets-div').href = `https://twitter.com/${user.screen_name}`;
57 document.getElementById('user-following-div').href = `https://twitter.com/${user.screen_name}/following`;
58 document.getElementById('user-followers-div').href = `https://twitter.com/${user.screen_name}/followers`;
59 document.getElementById('user-banner').src = user.profile_banner_url ? user.profile_banner_url : 'https://abs.twimg.com/images/themes/theme1/bg.png';
60 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");
61 document.getElementById('wtf-viewall').href = `https://twitter.com/i/connect_people?newtwitter=true&user_id=${user.id_str}`;
62 document.getElementById('user-avatar-link').href = `https://twitter.com/${user.screen_name}`;
63 document.getElementById('user-info').href = `https://twitter.com/${user.screen_name}`;
64
65 if(vars.enableTwemoji) twemoji.parse(document.getElementById('user-name'));
66
67 document.getElementById('loading-box').hidden = true;
68
69 if(document.getElementById('user-stats').clientWidth > 300) {
70 let style = document.createElement('style');
71 style.innerHTML = `.user-stat-div > h2 { font-size: 10px !important }`;
72 document.head.appendChild(style);
73 }
74}
75
76setTimeout(async () => {
77 if(!vars) {
78 await loadVars();
79 }
80 // weird bug
81 try {
82 document.getElementById('wtf-refresh').addEventListener('click', async () => {
83 renderDiscovery(false);
84 });
85 } catch(e) {
86 setTimeout(() => location.reload(), 500);
87 console.error(e);
88 return;
89 }
90
91 const fontCheck = new Set([
92 // Windows 10
93 'Arial', 'Arial Black', 'Bahnschrift', 'Calibri', 'Cambria', 'Cambria Math', 'Candara', 'Comic Sans MS', 'Consolas', 'Constantia', 'Corbel', 'Courier New', 'Ebrima', 'Franklin Gothic Medium', 'Gabriola', 'Gadugi', 'Georgia', 'HoloLens MDL2 Assets', 'Impact', 'Ink Free', 'Javanese Text', 'Leelawadee UI', 'Lucida Console', 'Lucida Sans Unicode', 'Malgun Gothic', 'Marlett', 'Microsoft Himalaya', 'Microsoft JhengHei', 'Microsoft New Tai Lue', 'Microsoft PhagsPa', 'Microsoft Sans Serif', 'Microsoft Tai Le', 'Microsoft YaHei', 'Microsoft Yi Baiti', 'MingLiU-ExtB', 'Mongolian Baiti', 'MS Gothic', 'MS UI Gothic', 'MV Boli', 'Myanmar Text', 'Nirmala UI', 'Palatino Linotype', 'Segoe MDL2 Assets', 'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Historic', 'Segoe UI Emoji', 'Segoe UI Symbol', 'SimSun', 'Sitka', 'Sylfaen', 'Symbol', 'Tahoma', 'Times New Roman', 'Trebuchet MS', 'Verdana', 'Webdings', 'Wingdings', 'Yu Gothic',
94 // macOS
95 'American Typewriter', 'Andale Mono', 'Arial', 'Arial Black', 'Arial Narrow', 'Arial Rounded MT Bold', 'Arial Unicode MS', 'Avenir', 'Avenir Next', 'Avenir Next Condensed', 'Baskerville', 'Big Caslon', 'Bodoni 72', 'Bodoni 72 Oldstyle', 'Bodoni 72 Smallcaps', 'Bradley Hand', 'Brush Script MT', 'Chalkboard', 'Chalkboard SE', 'Chalkduster', 'Charter', 'Cochin', 'Comic Sans MS', 'Copperplate', 'Courier', 'Courier New', 'Didot', 'DIN Alternate', 'DIN Condensed', 'Futura', 'Geneva', 'Georgia', 'Gill Sans', 'Helvetica', 'Helvetica Neue', 'Herculanum', 'Hoefler Text', 'Impact', 'Lucida Grande', 'Luminari', 'Marker Felt', 'Menlo', 'Microsoft Sans Serif', 'Monaco', 'Noteworthy', 'Optima', 'Palatino', 'Papyrus', 'Phosphate', 'Rockwell', 'Savoye LET', 'SignPainter', 'Skia', 'Snell Roundhand', 'Tahoma', 'Times', 'Times New Roman', 'Trattatello', 'Trebuchet MS', 'Verdana', 'Zapfino',
96 // other
97 'Terminus', 'Terminus (TTF)', 'Terminus (TTF) for Windows', 'Chirp'
98 ].sort());
99
100 let fonts = await (async() => {
101 await document.fonts.ready;
102
103 const fontAvailable = new Set();
104
105 for (const font of fontCheck.values()) {
106 if (document.fonts.check(`12px "${font}"`)) {
107 fontAvailable.add(font);
108 }
109 }
110
111 return [...fontAvailable.values()];
112 })();
113 let fontElement = document.getElementById('font');
114 let tweetFontElement = document.getElementById('tweet-font');
115 let linkColor = document.getElementById('link-color');
116 let heartsNotStars = document.getElementById('hearts-instead-stars');
117 let linkColorsInTL = document.getElementById('link-colors-in-tl');
118 let enableTwemoji = document.getElementById('enable-twemoji');
119 let enableHashflags = document.getElementById('enable-hashflags');
120 let timelineType = document.getElementById('tl-type');
121 let darkMode = document.getElementById('dark-mode');
122 let pitchBlackMode = document.getElementById('pitch-black-mode');
123 let darkModeText = document.getElementById('dark-mode-text');
124 let timeMode = document.getElementById('time-mode');
125 let showTopicTweets = document.getElementById('show-topic-tweets');
126 let disableHotkeys = document.getElementById('disable-hotkeys');
127 let customCSS = document.getElementById('custom-css');
128 let customCSSSave = document.getElementById('custom-css-save');
129 let savePreferredQuality = document.getElementById('save-preferred-quality');
130 let roundAvatars = document.getElementById('round-avatars-switch');
131 let showOriginalImages = document.getElementById('show-original-images');
132 let noBigFont = document.getElementById('no-big-font');
133 let language = document.getElementById('language');
134 let autoplayVideos = document.getElementById('autoplay-videos');
135 let displaySensitiveContent = document.getElementById('display-sensitive-content');
136 let seeTweetViews = document.getElementById('see-tweet-views');
137 let twitterBlueCheckmarks = document.getElementById('twitter-blue-checkmarks');
138 let developerMode = document.getElementById('developer-mode');
139 let copyLinksAs = document.getElementById('copy-links-as');
140 let useNewIcon = document.getElementById('use-new-icon');
141 let updateTimelineAutomatically = document.getElementById('update-timeline-automatically');
142 let hideTrends = document.getElementById('hide-trends');
143 let hideWtf = document.getElementById('hide-wtf');
144 let hideLikes = document.getElementById('hide-likes');
145 let hideFollowers = document.getElementById('hide-followers');
146 let disablePersonalizedTrends = document.getElementById('disable-personalized-trends');
147 let showBookmarkCount = document.getElementById('show-bookmark-count');
148 let hideCommunityNotes = document.getElementById('hide-community-notes');
149 let disableGifAutoplay = document.getElementById('disable-gif-autoplay');
150 let showMediaCount = document.getElementById('show-media-count');
151 let pinProfileOnNavbar = document.getElementById('pin-profile-on-navbar');
152 let pinBookmarksOnNavbar = document.getElementById('pin-bookmarks-on-navbar');
153 let pinListsOnNavbar = document.getElementById('pin-lists-on-navbar');
154 let useOldDefaultProfileImage = document.getElementById('use-old-default-profile-navbar');
155 let uncensorGraphicViolenceAutomatically = document.getElementById('uncensor-graphic-violence-automatically');
156 let uncensorAdultContentAutomatically = document.getElementById('uncensor-adult-content-automatically');
157 let uncensorSensitiveContentAutomatically = document.getElementById('uncensor-sensitive-content-automatically');
158 let useOldStyleReply = document.getElementById('use-old-style-reply');
159 let linkColorReset = document.getElementById('link-color-reset');
160 let enableAd = document.getElementById('enable-promotion');
161 let disableProfileCustomizations = document.getElementById('disable-profile-customizations');
162 let moveNavbarToBottom = document.getElementById('move-navbar-to-bottom');
163 let openNotifsAsModal = document.getElementById('open-notifs-as-modal');
164
165 let root = document.querySelector(":root");
166 {
167 let option = document.createElement('option');
168 option.value = "_custom";
169 option.innerText = '<CUSTOM FONT>';
170 fontElement.append(option);
171 tweetFontElement.append(option.cloneNode(true));
172 }
173 for(let i in fonts) {
174 let font = fonts[i];
175 let option = document.createElement('option');
176 option.value = font;
177 option.innerText = font;
178 option.style.fontFamily = `"${font}"`;
179 fontElement.append(option);
180 tweetFontElement.append(option.cloneNode(true));
181 }
182 fontElement.addEventListener('change', () => {
183 let font = fontElement.value;
184 if(font === '_custom') {
185 font = prompt('Enter a custom font name');
186 }
187 root.style.setProperty('--font', `"${font}"`);
188 chrome.storage.sync.set({
189 font: font
190 }, () => { });
191 });
192 tweetFontElement.addEventListener('change', () => {
193 let font = tweetFontElement.value;
194 if(font === '_custom') {
195 font = prompt('Enter a custom font name');
196 }
197 root.style.setProperty('--tweet-font', `"${font}"`);
198 chrome.storage.sync.set({
199 tweetFont: font
200 }, () => { });
201 });
202
203 linkColor.addEventListener('input', () => {
204 let color = linkColor.value;
205 root.style.setProperty('--link-color', color);
206 });
207 linkColor.addEventListener('change', () => {
208 let color = linkColor.value;
209 root.style.setProperty('--link-color', color);
210 chrome.storage.sync.set({
211 linkColor: color
212 }, () => {
213 customCSSBus.postMessage({type: 'color', color: color});
214 });
215 });
216 linkColorReset.addEventListener('click', async () => {
217 let color = '#4BACD2';
218 linkColor.value=color;
219 root.style.setProperty('--link-color', color);
220 chrome.storage.sync.set({
221 linkColor: color
222 }, () => {
223 customCSSBus.postMessage({type: 'color', color: color});
224 });
225 });
226 pinProfileOnNavbar.addEventListener('change', () => {
227 chrome.storage.sync.set({
228 pinProfileOnNavbar: pinProfileOnNavbar.checked
229 }, () => {
230 document.getElementById('pin-profile').hidden = !pinProfileOnNavbar.checked;
231 });
232 });
233 pinBookmarksOnNavbar.addEventListener('change', () => {
234 chrome.storage.sync.set({
235 pinBookmarksOnNavbar: pinBookmarksOnNavbar.checked
236 }, () => {
237 document.getElementById('pin-bookmarks').hidden = !pinBookmarksOnNavbar.checked;
238 });
239 });
240 pinListsOnNavbar.addEventListener('change', () => {
241 chrome.storage.sync.set({
242 pinListsOnNavbar: pinListsOnNavbar.checked
243 }, () => {
244 document.getElementById('pin-lists').hidden = !pinListsOnNavbar.checked;
245 });
246 });
247 moveNavbarToBottom.addEventListener('change', () => {
248 chrome.storage.sync.set({
249 moveNavbarToBottom: moveNavbarToBottom.checked
250 }, () => {
251 document.body.classList.toggle('move-navbar-to-bottom', moveNavbarToBottom.checked);
252 });
253 });
254 openNotifsAsModal.addEventListener('change', () => {
255 chrome.storage.sync.set({
256 openNotifsAsModal: openNotifsAsModal.checked
257 }, () => {
258 vars.openNotifsAsModal = openNotifsAsModal.checked;
259 });
260 });
261 heartsNotStars.addEventListener('change', () => {
262 chrome.storage.sync.set({
263 heartsNotStars: heartsNotStars.checked
264 }, () => { });
265 });
266 uncensorAdultContentAutomatically.addEventListener('change', () => {
267 chrome.storage.sync.set({
268 uncensorAdultContentAutomatically: uncensorAdultContentAutomatically.checked
269 }, () => { });
270 });
271 uncensorGraphicViolenceAutomatically.addEventListener('change', () => {
272 chrome.storage.sync.set({
273 uncensorGraphicViolenceAutomatically: uncensorGraphicViolenceAutomatically.checked
274 }, () => { });
275 });
276 uncensorSensitiveContentAutomatically.addEventListener('change', () => {
277 chrome.storage.sync.set({
278 uncensorSensitiveContentAutomatically: uncensorSensitiveContentAutomatically.checked
279 }, () => { });
280 });
281 disableProfileCustomizations.addEventListener('change', () => {
282 chrome.storage.sync.set({
283 disableProfileCustomizations: disableProfileCustomizations.checked
284 }, () => { });
285 });
286 linkColorsInTL.addEventListener('change', () => {
287 chrome.storage.sync.set({
288 linkColorsInTL: linkColorsInTL.checked
289 }, () => { });
290 });
291 enableTwemoji.addEventListener('change', () => {
292 chrome.storage.sync.set({
293 enableTwemoji: enableTwemoji.checked
294 }, () => { });
295 });
296 enableHashflags.addEventListener('change', () => {
297 chrome.storage.sync.set({
298 enableHashflags: enableHashflags.checked
299 }, () => { });
300 });
301 timelineType.addEventListener('change', () => {
302 document.getElementById('stt-div').hidden = timelineType.value !== 'algo' && timelineType.value !== 'algov2';
303 chrome.storage.sync.set({
304 timelineType: timelineType.value
305 }, () => { });
306 });
307 showTopicTweets.addEventListener('change', () => {
308 chrome.storage.sync.set({
309 showTopicTweets: showTopicTweets.checked
310 }, () => { });
311 });
312 useNewIcon.addEventListener('change', () => {
313 vars.useNewIcon = useNewIcon.checked;
314 chrome.storage.sync.set({
315 useNewIcon: useNewIcon.checked
316 }, () => {
317 let icon = document.getElementById('site-icon');
318 icon.href = chrome.runtime.getURL(`images/logo32${vars.useNewIcon ? '_new' : ''}.png`);
319 });
320 });
321 useOldStyleReply.addEventListener('change', () => {
322 vars.useOldStyleReply = useOldStyleReply.checked;
323 chrome.storage.sync.set({
324 useOldStyleReply: useOldStyleReply.checked
325 }, () => { });
326 });
327 enableAd.addEventListener('change', () => {
328 vars.enableAd = enableAd.checked;
329 chrome.storage.sync.set({
330 enableAd: enableAd.checked
331 }, () => { });
332 });
333 useOldDefaultProfileImage.addEventListener('change', () => {
334 vars.useOldDefaultProfileImage = useOldDefaultProfileImage.checked;
335 chrome.storage.sync.set({
336 useOldDefaultProfileImage: useOldDefaultProfileImage.checked
337 }, () => { });
338 });
339 disableHotkeys.addEventListener('change', () => {
340 chrome.storage.sync.set({
341 disableHotkeys: disableHotkeys.checked
342 }, () => { });
343 });
344 savePreferredQuality.addEventListener('change', () => {
345 chrome.storage.sync.set({
346 savePreferredQuality: savePreferredQuality.checked
347 }, () => { });
348 });
349 showOriginalImages.addEventListener('change', () => {
350 chrome.storage.sync.set({
351 showOriginalImages: showOriginalImages.checked
352 }, () => { });
353 });
354 updateTimelineAutomatically.addEventListener('change', () => {
355 chrome.storage.sync.set({
356 updateTimelineAutomatically: updateTimelineAutomatically.checked
357 }, () => { });
358 });
359 roundAvatars.addEventListener('change', () => {
360 chrome.storage.sync.set({
361 roundAvatars: roundAvatars.checked
362 }, () => {
363 switchRoundAvatars(roundAvatars.checked);
364 roundAvatarBus.postMessage(roundAvatars.checked);
365 });
366 });
367 noBigFont.addEventListener('change', () => {
368 chrome.storage.sync.set({
369 noBigFont: noBigFont.checked
370 }, () => { });
371 });
372 autoplayVideos.addEventListener('change', () => {
373 chrome.storage.sync.set({
374 autoplayVideos: autoplayVideos.checked
375 }, () => { });
376 });
377 displaySensitiveContent.addEventListener('change', () => {
378 chrome.storage.sync.set({
379 displaySensitiveContent: displaySensitiveContent.checked
380 }, () => { });
381 });
382 seeTweetViews.addEventListener('change', () => {
383 chrome.storage.sync.set({
384 seeTweetViews: seeTweetViews.checked
385 }, () => { });
386 });
387 twitterBlueCheckmarks.addEventListener('change', () => {
388 chrome.storage.sync.set({
389 twitterBlueCheckmarks: twitterBlueCheckmarks.checked
390 }, () => { });
391 });
392 developerMode.addEventListener('change', () => {
393 chrome.storage.sync.set({
394 developerMode: developerMode.checked
395 }, () => { });
396 });
397 showBookmarkCount.addEventListener('change', () => {
398 chrome.storage.sync.set({
399 showBookmarkCount: showBookmarkCount.checked
400 }, () => { });
401 });
402 hideCommunityNotes.addEventListener('change', () => {
403 chrome.storage.sync.set({
404 hideCommunityNotes: hideCommunityNotes.checked
405 }, () => { });
406 });
407 disableGifAutoplay.addEventListener('change', () => {
408 chrome.storage.sync.set({
409 disableGifAutoplay: disableGifAutoplay.checked
410 }, () => { });
411 });
412 disablePersonalizedTrends.addEventListener('change', () => {
413 vars.disablePersonalizedTrends = disablePersonalizedTrends.checked;
414 chrome.storage.sync.set({
415 disablePersonalizedTrends: disablePersonalizedTrends.checked
416 }, () => {
417 renderTrends(false, false);
418 });
419 });
420 hideTrends.addEventListener('change', () => {
421 vars.hideTrends = hideTrends.checked;
422 hideStuff();
423 chrome.storage.sync.set({
424 hideTrends: hideTrends.checked
425 }, () => {
426 renderTrends();
427 });
428 });
429 hideWtf.addEventListener('change', () => {
430 vars.hideWtf = hideWtf.checked;
431 hideStuff();
432 chrome.storage.sync.set({
433 hideWtf: hideWtf.checked
434 }, () => {
435 renderDiscovery();
436 });
437 });
438 hideLikes.addEventListener('change', () => {
439 vars.hideLikes = hideLikes.checked;
440 hideStuff();
441 chrome.storage.sync.set({
442 hideLikes: hideLikes.checked
443 }, () => { });
444 });
445 hideFollowers.addEventListener('change', () => {
446 vars.hideFollowers = hideFollowers.checked;
447 hideStuff();
448 chrome.storage.sync.set({
449 hideFollowers: hideFollowers.checked
450 }, () => { });
451 });
452 language.addEventListener('change', () => {
453 chrome.storage.sync.set({
454 language: language.value
455 }, () => {
456 location.reload();
457 });
458 });
459 showMediaCount.addEventListener('change', () => {
460 vars.showMediaCount = showMediaCount.checked;
461 chrome.storage.sync.set({
462 showMediaCount: showMediaCount.checked
463 }, () => { });
464 });
465 darkMode.addEventListener('change', () => {
466 themeBus.postMessage([darkMode.checked, pitchBlackMode.checked]);
467 isDarkModeEnabled = darkMode.checked;
468 switchDarkMode(isDarkModeEnabled);
469 chrome.storage.sync.set({
470 darkMode: isDarkModeEnabled
471 }, () => { });
472 });
473 pitchBlackMode.addEventListener('change', () => {
474 vars.pitchBlack = pitchBlackMode.checked;
475 chrome.storage.sync.set({
476 pitchBlack: pitchBlackMode.checked
477 }, () => {});
478 themeBus.postMessage([darkMode.checked, pitchBlackMode.checked]);
479 switchDarkMode(isDarkModeEnabled);
480 });
481 timeMode.addEventListener('change', () => {
482 if(timeMode.checked) {
483 darkMode.disabled = true;
484 chrome.storage.sync.set({
485 darkMode: false
486 }, () => { });
487 darkModeText.style.color = 'var(--darker-gray)';
488 let dark = isDark();
489 darkMode.checked = dark;
490 themeBus.postMessage([dark, pitchBlackMode.checked]);
491 isDarkModeEnabled = dark;
492 switchDarkMode(dark);
493 } else {
494 darkMode.checked = false;
495 darkMode.disabled = false;
496 darkModeText.style.color = 'unset';
497 themeBus.postMessage([false, pitchBlackMode.checked]);
498 isDarkModeEnabled = false;
499 switchDarkMode(false);
500 }
501 vars.timeMode = timeMode.checked;
502 chrome.storage.sync.set({
503 timeMode: timeMode.checked
504 }, () => { });
505 });
506 copyLinksAs.addEventListener('change', () => {
507 let val = copyLinksAs.value;
508 if(val === 'custom') {
509 val = prompt(LOC.copy_tweet_links_as.message);
510 if(!val) {
511 return;
512 }
513 }
514
515 chrome.storage.sync.set({
516 copyLinksAs: val
517 }, () => { });
518 });
519 customCSS.addEventListener('keydown', e => {
520 if(e.key === "Tab") {
521 e.preventDefault();
522 e.stopImmediatePropagation();
523 let pos = customCSS.selectionStart;
524 customCSS.value = customCSS.value.slice(0, pos) + " " + customCSS.value.slice(pos);
525 customCSS.selectionStart = customCSS.selectionEnd = pos + 4;
526 }
527 });
528 customCSSSave.addEventListener('click', () => {
529 chrome.storage.sync.set({
530 customCSS: customCSS.value
531 }, () => {
532 let event = new CustomEvent('customCSS', { detail: customCSS.value });
533 customCSSBus.postMessage({type: 'css'});
534 document.dispatchEvent(event);
535 });
536 });
537 if(vars.linkColor) {
538 linkColor.value = vars.linkColor;
539 root.style.setProperty('--link-color', vars.linkColor);
540 } else {
541 linkColor.value = '#4bacd2';
542 }
543 if(vars.font) {
544 fontElement.value = vars.font;
545 root.style.setProperty('--font', `"${vars.font}"`);
546 }
547 if(vars.tweetFont) {
548 tweetFontElement.value = vars.tweetFont;
549 root.style.setProperty('--tweet-font', `"${vars.tweetFont}"`);
550 }
551 heartsNotStars.checked = !!vars.heartsNotStars;
552 linkColorsInTL.checked = !!vars.linkColorsInTL;
553 enableTwemoji.checked = !!vars.enableTwemoji;
554 enableHashflags.checked = !!vars.enableHashflags;
555 timelineType.value = vars.timelineType ? vars.timelineType : 'chrono';
556 showTopicTweets.checked = !!vars.showTopicTweets;
557 darkMode.checked = !!vars.darkMode;
558 pitchBlackMode.checked = !!vars.pitchBlack;
559 timeMode.checked = !!vars.timeMode;
560 disableHotkeys.checked = !!vars.disableHotkeys;
561 noBigFont.checked = !!vars.noBigFont;
562 autoplayVideos.checked = !!vars.autoplayVideos;
563 displaySensitiveContent.checked = !!vars.displaySensitiveContent;
564 seeTweetViews.checked = !!vars.seeTweetViews;
565 twitterBlueCheckmarks.checked = !!vars.twitterBlueCheckmarks;
566 developerMode.checked = !!vars.developerMode;
567 useNewIcon.checked = !!vars.useNewIcon;
568 updateTimelineAutomatically.checked = !!vars.updateTimelineAutomatically;
569 hideTrends.checked = !!vars.hideTrends;
570 hideWtf.checked = !!vars.hideWtf;
571 hideLikes.checked = !!vars.hideLikes;
572 hideFollowers.checked = !!vars.hideFollowers;
573 disablePersonalizedTrends.checked = !!vars.disablePersonalizedTrends;
574 showBookmarkCount.checked = !!vars.showBookmarkCount;
575 hideCommunityNotes.checked = !!vars.hideCommunityNotes;
576 disableGifAutoplay.checked = !!vars.disableGifAutoplay;
577 showMediaCount.checked = !!vars.showMediaCount;
578 pinProfileOnNavbar.checked = !!vars.pinProfileOnNavbar;
579 pinBookmarksOnNavbar.checked = !!vars.pinBookmarksOnNavbar;
580 pinListsOnNavbar.checked = !!vars.pinListsOnNavbar;
581 useOldDefaultProfileImage.checked = !!vars.useOldDefaultProfileImage;
582 uncensorAdultContentAutomatically.checked = !!vars.uncensorAdultContentAutomatically;
583 uncensorGraphicViolenceAutomatically.checked = !!vars.uncensorGraphicViolenceAutomatically;
584 uncensorSensitiveContentAutomatically.checked = !!vars.uncensorSensitiveContentAutomatically;
585 useOldStyleReply.checked = !!vars.useOldStyleReply;
586 enableAd.checked = !!vars.enableAd;
587 moveNavbarToBottom.checked = !!vars.moveNavbarToBottom;
588 openNotifsAsModal.checked = !!vars.openNotifsAsModal;
589 if(vars.customCSS) {
590 customCSS.value = vars.customCSS;
591 }
592 document.getElementById('stt-div').hidden = vars.timelineType !== 'algo' && vars.timelineType !== 'algov2';
593 savePreferredQuality.checked = !!vars.savePreferredQuality;
594 showOriginalImages.checked = !!vars.showOriginalImages;
595 roundAvatars.checked = !!vars.roundAvatars;
596 language.value = vars.language ? vars.language : 'en';
597 copyLinksAs.value = ['twitter.com', 'fxtwitter.com', 'vxtwitter.com', 'nitter.net'].includes(vars.copyLinksAs) ? vars.copyLinksAs : 'custom';
598 if(vars.timeMode) {
599 darkMode.disabled = true;
600 darkMode.checked = isDark();
601 darkModeText.style.color = 'var(--darker-gray)';
602 }
603
604 document.getElementById('tl-help').addEventListener('click', () => {
605 createModal(`
606 <div style="color:var(--almost-black);max-width:600px" class="help-modal">
607 <h2 class="help-header larger" style="padding-top: 0;margin-bottom: 5px;">${LOC.timeline_type.message}</h2>
608 <div><b>${LOC.chrono.message}</b> - ${LOC.chrono_help.message}</div>
609 <div><b>${LOC.chrono_no_retweets.message}</b> - ${LOC.chrono_no_retweets_help.message}</div>
610 <div><b>${LOC.chrono_retweets.message}</b> - ${LOC.chrono_retweets_help.message}</div>
611 <div><b>${LOC.chrono_social.message}</b> - ${LOC.chrono_social_help.message}</div>
612 <div><b>${LOC.algov2.message}</b> - ${LOC.algov2_help.message}</div>
613 </div>
614 `)
615 });
616 let [LOC_DATA, LOC_EN_DATA] = await Promise.all([
617 fetch(chrome.runtime.getURL(`_locales/${LANGUAGE}/messages.json`)).then(response => response.json()),
618 fetch(chrome.runtime.getURL(`_locales/en/messages.json`)).then(response => response.json())
619 ]);
620 LOC_DATA = Object.keys(LOC_DATA);
621 LOC_EN_DATA = Object.keys(LOC_EN_DATA);
622 let diff = LOC_EN_DATA.length - LOC_DATA.length;
623 if(diff > 5) {
624 document.getElementById('language-warning').hidden = false;
625 } else {
626 document.getElementById('language-warning').hidden = true;
627 }
628 document.getElementById('language-warning-button').addEventListener('click', () => {
629 let lang = document.querySelector(`option[value="${LANGUAGE}"]`).innerText;
630 if(!lang) lang = LANGUAGE.toUpperCase();
631 // Don't translate this
632 createModal(`
633 <div style="color:var(--almost-black);max-width:600px" class="help-modal">
634 <h2 class="help-header larger" style="padding-top: 0;margin-bottom: 5px;">Do you know English?</h2>
635 <div>Do you know English (at least B2) and ${lang}? If so, you can help translate this extension into your language!</div>
636 <div>${lang} currently lacks ${diff} line translations. You can help translating the missing messages <a href="https://github.com/dimdenGD/OldTwitter/tree/master/_locales#readme" target="_blank">here</a>.</div>
637 <div>Thank you for your help!</div>
638 </div>
639 `);
640 });
641
642 document.getElementById('export-settings').addEventListener('click', () => {
643 let varsObj = Object.assign({}, vars);
644 delete varsObj.customCSSVariables;
645 delete varsObj.customCSS;
646 delete varsObj.autotranslateProfiles;
647 delete varsObj.viewedtweets;
648 delete varsObj.linkColor;
649 delete varsObj.font;
650 delete varsObj.tweetFont;
651 delete varsObj.acknowledgedCssAccess;
652
653 let a = document.createElement('a');
654 a.href = URL.createObjectURL(new Blob([JSON.stringify(varsObj)], { type: 'application/json' }));
655 a.download = 'oldtwitter_settings.json';
656
657 a.click();
658 });
659 document.getElementById('import-settings').addEventListener('click', () => {
660 let input = document.createElement('input');
661 input.type = 'file';
662 input.accept = '.json';
663 input.addEventListener('change', () => {
664 let file = input.files[0];
665 if(!file) return;
666 let reader = new FileReader();
667 reader.onload = () => {
668 let json = JSON.parse(reader.result);
669 chrome.storage.sync.set(json, () => {
670 location.reload();
671 });
672 };
673 reader.readAsText(file);
674 });
675 input.click();
676 });
677 document.getElementById('export-style').addEventListener('click', () => {
678 let json = {
679 customCSSVariables: vars.customCSSVariables,
680 customCSS: vars.customCSS,
681 font: vars.font,
682 tweetFont: vars.tweetFont,
683 linkColor: vars.linkColor
684 }
685 let a = document.createElement('a');
686 a.href = URL.createObjectURL(new Blob([JSON.stringify(json)], { type: 'application/json' }));
687 a.download = 'oldtwitter_style.json';
688
689 a.click();
690 });
691 document.getElementById('import-style').addEventListener('click', () => {
692 let input = document.createElement('input');
693 input.type = 'file';
694 input.accept = '.json';
695 input.addEventListener('change', () => {
696 let file = input.files[0];
697 if(!file) return;
698 let reader = new FileReader();
699 reader.onload = () => {
700 let json = JSON.parse(reader.result);
701 chrome.storage.sync.set(json, () => {
702 location.reload();
703 });
704 };
705 reader.readAsText(file);
706 });
707 input.click();
708 });
709 document.getElementById('reset-settings').addEventListener('click', () => {
710 let sure = confirm(LOC.reset_settings_sure.message);
711 if(!sure) return;
712 chrome.storage.sync.clear(() => {
713 location.reload();
714 });
715 });
716 document.getElementById('clear-caches').addEventListener('click', () => {
717 chrome.storage.local.get(['adminpass', 'cssDraft', 'otPrivateTokens', 'extensiveLogging', 'hasRetweetedWithHotkey', 'installed', 'lastSearches', 'lastUserId', 'lastVersion', 'nextPlug', 'unfollows'], async data => {
718 chrome.storage.local.clear(() => {
719 chrome.storage.local.set(data, () => {
720 location.reload();
721 });
722 });
723 });
724 });
725
726 // Colors
727 let colorsDiv = document.getElementById('colors');
728 let theme = getThemeVariables(isDarkModeEnabled);
729 let defaultVars = parseVariables(theme);
730 customVars = parseVariables(vars.customCSSVariables);
731
732 for(let v in defaultVars) {
733 try {
734 let color = parseCssColor(customVars[v] ? customVars[v] : defaultVars[v]);
735 if(!color || v === '--link-color' || v === '--favorite-icon-color') continue;
736
737 let div = document.createElement('div');
738 div.classList.add('color-div');
739 div.innerHTML = /*html*/`
740 <input class="color-value" type="color" data-var="${v}" value="${rgb2hex(...color.values)}">
741 <input class="color-transparency" title="${LOC.transparency.message}" type="range" min="0" max="1" step="0.01" value="${color.alpha}">
742 <span class="color-name">${v[2].toUpperCase() + v.slice(3).replace(/-/g, ' ')}</span>
743 <button class="color-reset nice-button"${!customVars[v] ? ' disabled' : ''}>${LOC.reset.message}</button>
744 `;
745 colorsDiv.append(div);
746 function colorUpdate() {
747 let colorValue = div.querySelector('.color-value');
748 let colorTransparency = div.querySelector('.color-transparency');
749
750 customVars[colorValue.dataset.var] = `rgba(${hex2rgb(colorValue.value).join(', ')}, ${colorTransparency.value})`;
751 let css = Object.entries(customVars).map(([k, v]) => `${k}: ${v};`).join('\n');
752 chrome.storage.sync.set({
753 customCSSVariables: css
754 }, () => {
755 vars.customCSSVariables = css;
756 root.style.setProperty(colorValue.dataset.var, customVars[colorValue.dataset.var]);
757 customCSSBus.postMessage({type: 'vars'});
758 div.querySelector('.color-reset').disabled = false;
759 if(colorValue.dataset.var === '--background-color') {
760 document.getElementById("color-preview-custom").style.color = makeSeeableColor(customVars[colorValue.dataset.var]);
761 document.getElementById("color-preview-custom").hidden = false;
762 }
763 });
764 }
765 div.querySelector('.color-value').addEventListener('change', colorUpdate);
766 div.querySelector('.color-transparency').addEventListener('change', colorUpdate);
767 div.querySelector('.color-reset').addEventListener('click', () => {
768 delete customVars[v];
769 let css = Object.entries(customVars).map(([k, v]) => `${k}: ${v};`).join('\n');
770 chrome.storage.sync.set({
771 customCSSVariables: css
772 }, () => {
773 vars.customCSSVariables = css;
774 root.style.setProperty(v, defaultVars[v]);
775 customCSSBus.postMessage({type: 'vars'});
776 div.querySelector('.color-reset').disabled = true;
777 let defColor = parseCssColor(defaultVars[v]);
778 div.querySelector('.color-value').value = rgb2hex(...defColor.values);
779 div.querySelector('.color-transparency').value = defColor.alpha;
780 if(v === '--background-color') {
781 document.getElementById("color-preview-custom").hidden = true;
782 }
783 });
784 });
785
786 } catch(e) {
787 console.error(e);
788 }
789 }
790 document.getElementById('reset-all-colors').addEventListener('click', () => {
791 let sure = confirm(LOC.reset_colors_sure.message);
792 if(!sure) return;
793 chrome.storage.sync.set({
794 customCSSVariables: ''
795 }, () => {
796 vars.customCSSVariables = '';
797 customCSSBus.postMessage({type: 'vars'});
798 let resetButtons = document.querySelectorAll('.color-reset');
799 for(let i = 0; i < resetButtons.length; i++) {
800 if(!resetButtons[i].disabled) {
801 resetButtons[i].click();
802 }
803 }
804 });
805 });
806 document.getElementById('export-colors').addEventListener('click', () => {
807 let a = document.createElement('a');
808 a.href = URL.createObjectURL(new Blob([vars.customCSSVariables], { type: 'text/css' }));
809 a.download = 'oldtwitter_colors.css';
810 a.click();
811 });
812 document.getElementById('import-colors').addEventListener('click', () => {
813 let input = document.createElement('input');
814 input.type = 'file';
815 input.accept = '.css';
816 input.addEventListener('change', () => {
817 let file = input.files[0];
818 if(!file) return;
819 let reader = new FileReader();
820 reader.onload = () => {
821 let css = reader.result;
822 chrome.storage.sync.set({
823 customCSSVariables: css
824 }, () => {
825 vars.customCSSVariables = css;
826 customCSSBus.postMessage({type: 'vars'});
827 location.reload();
828 });
829 };
830 reader.readAsText(file);
831 });
832 input.click();
833 });
834
835
836 // Run
837 updateUserData();
838 renderDiscovery();
839 renderTrends();
840 document.getElementById('loading-box').hidden = true;
841 setInterval(updateUserData, 60000 * 3);
842 setInterval(() => renderDiscovery(false), 60000 * 15);
843 setInterval(renderTrends, 60000 * 5);
844}, 50);