diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 38b9359f..49607d5f 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -644,5 +644,6 @@
"nonexistent_user": { "message": "This account doesn't exist" },
"nonexistent_user_desc": { "message": "Try searching for another." },
"suspended_user": { "message": "Account suspended" },
- "suspended_user_desc": { "message": "The profile you are trying to view has been suspended." }
+ "suspended_user_desc": { "message": "The profile you are trying to view has been suspended." },
+ "show_boring_indicators": { "message": "Show indicator in followers/following page if last tweet of person is a retweet/quote/non-existent" }
}
diff --git a/layouts/header/style.css b/layouts/header/style.css
index 8153a442..3a42b5d7 100644
--- a/layouts/header/style.css
+++ b/layouts/header/style.css
@@ -2087,6 +2087,29 @@ emoji-picker {
font-weight: 100;
}
+.user-indicator-no-status::after {
+ content: "\f045";
+ color: #dd2b2b;
+ font-family: var(--icon-font);
+ margin-left: 5px;
+ font-weight: 100;
+}
+
+.user-indicator-retweeted::after {
+ content: "\f152";
+ color: #5c913b;
+ font-family: var(--icon-font);
+ margin-left: 5px;
+ font-weight: 100;
+}
+
+.user-indicator-quoted::after {
+ content: "\f157";
+ color: #4a9fc7;
+ font-family: var(--icon-font);
+ margin-left: 5px;
+ font-weight: 100;
+}
.tweet-media-video-overlay {
position: absolute;
diff --git a/layouts/profile/script.js b/layouts/profile/script.js
index 8abaf551..57fd0a42 100644
--- a/layouts/profile/script.js
+++ b/layouts/profile/script.js
@@ -729,7 +729,17 @@ async function renderFollowing(clear = true, cursor) {
if(vars.showUserFollowerCountsInLists) {
label = `${formatLargeNumber(u.followers_count)} ${vars.modernUI ? LOC.followers.message : LOC.followers.message.toLowerCase()}`;
}
- appendUser(u, userList, label);
+ let usernameClass = '';
+ if(!u.status) {
+ usernameClass = 'user-indicator-no-status';
+ } else if(u.status) {
+ if(u.status.retweeted_status) {
+ usernameClass = 'user-indicator-retweeted';
+ } else if(u.status.quoted_status_id_str) {
+ usernameClass = 'user-indicator-quoted';
+ }
+ }
+ appendUser(u, userList, label, usernameClass);
});
document.getElementById('loading-box').hidden = true;
loadingFollowing = false;
@@ -1003,7 +1013,17 @@ async function renderFollowers(clear = true, cursor) {
if(vars.showUserFollowerCountsInLists) {
label = `${formatLargeNumber(u.followers_count)} ${vars.modernUI ? LOC.followers.message : LOC.followers.message.toLowerCase()}`;
}
- appendUser(u, userList, label);
+ let usernameClass = '';
+ if(!u.status) {
+ usernameClass = 'user-indicator-no-status';
+ } else if(u.status) {
+ if(u.status.retweeted_status) {
+ usernameClass = 'user-indicator-retweeted';
+ } else if(u.status.quoted_status_id_str) {
+ usernameClass = 'user-indicator-quoted';
+ }
+ }
+ appendUser(u, userList, label, usernameClass);
});
document.getElementById('loading-box').hidden = true;
loadingFollowers = false;
diff --git a/layouts/settings/index.html b/layouts/settings/index.html
index d3062450..97c30017 100644
--- a/layouts/settings/index.html
+++ b/layouts/settings/index.html
@@ -223,6 +223,9 @@
__MSG_mobile__
__MSG_advanced_options__
+
+
+
diff --git a/layouts/settings/script.js b/layouts/settings/script.js
index a26e1c8c..c069d0f5 100644
--- a/layouts/settings/script.js
+++ b/layouts/settings/script.js
@@ -333,6 +333,7 @@ setTimeout(async () => {
let showUserFollowerCountsInLists = document.getElementById('show-user-follower-counts-in-lists');
let hideUnfollowersPage = document.getElementById('hide-unfollowers-page');
let transitionProfileBanner = document.getElementById('transition-profile-banner');
+ let showBoringIndicators = document.getElementById('show-boring-indicators');
let root = document.querySelector(":root");
{
@@ -733,6 +734,12 @@ setTimeout(async () => {
renderTrends(false, false);
});
});
+ showBoringIndicators.addEventListener('change', () => {
+ vars.showBoringIndicators = showBoringIndicators.checked;
+ chrome.storage.sync.set({
+ showBoringIndicators: showBoringIndicators.checked
+ }, () => { });
+ });
hideTrends.addEventListener('change', () => {
vars.hideTrends = hideTrends.checked;
hideStuff();
@@ -1059,6 +1066,7 @@ setTimeout(async () => {
showQuoteCount.checked = !!vars.showQuoteCount;
hideUnfollowersPage.checked = !!vars.hideUnfollowersPage;
transitionProfileBanner.checked = !!vars.transitionProfileBanner;
+ showBoringIndicators.checked = !!vars.showBoringIndicators;
if(vars.customCSS) {
writeCSSToDB(vars.customCSS)
}
diff --git a/sandbox.html b/sandbox.html
index a6b42e78..a9cbfc60 100644
--- a/sandbox.html
+++ b/sandbox.html
@@ -20,7 +20,6 @@
return;
}
let data = event.data;
- console.log('iframe message', data);
if (data.action === 'init') {
try {
let animsDiv = document.getElementById('anims');
diff --git a/scripts/apis.js b/scripts/apis.js
index 953d30dc..a4e38358 100644
--- a/scripts/apis.js
+++ b/scripts/apis.js
@@ -2169,6 +2169,52 @@ const API = {
});
},
getFollowing: (id, cursor) => {
+ return new Promise((resolve, reject) => {
+ fetch(`https://${location.hostname}/i/api/1.1/friends/list.json?user_id=${id}&count=100${cursor ? `&cursor=${cursor}` : ""}`, {
+ headers: {
+ "authorization": OLDTWITTER_CONFIG.oauth_key,
+ "x-csrf-token": OLDTWITTER_CONFIG.csrf,
+ "x-twitter-auth-type": "OAuth2Session",
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
+ },
+ credentials: "include"
+ }).then(i => i.json()).then(data => {
+ if (data.errors && data.errors[0]) {
+ return reject(data.errors[0].message);
+ }
+ resolve({
+ list: data.users,
+ cursor: data.next_cursor_str !== "0" ? data.next_cursor_str : null
+ });
+ }).catch(e => {
+ reject(e);
+ });
+ });
+ },
+ getFollowers: (id, cursor, count = 100) => {
+ return new Promise((resolve, reject) => {
+ fetch(`https://${location.hostname}/i/api/1.1/followers/list.json?user_id=${id}&count=${count}${cursor ? `&cursor=${cursor}` : ""}`, {
+ headers: {
+ "authorization": OLDTWITTER_CONFIG.oauth_key,
+ "x-csrf-token": OLDTWITTER_CONFIG.csrf,
+ "x-twitter-auth-type": "OAuth2Session",
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
+ },
+ credentials: "include"
+ }).then(i => i.json()).then(data => {
+ if (data.errors && data.errors[0]) {
+ return reject(data.errors[0].message);
+ }
+ resolve({
+ list: data.users,
+ cursor: data.next_cursor_str !== "0" ? data.next_cursor_str : null
+ });
+ }).catch(e => {
+ reject(e);
+ });
+ });
+ },
+ getFollowingV2: (id, cursor) => {
return new Promise((resolve, reject) => {
let obj = {
"userId": id,
@@ -2185,7 +2231,7 @@ const API = {
},
credentials: "include"
}).then(i => i.json()).then(data => {
- debugLog('user.getFollowing', 'start', {id, cursor, data});
+ debugLog('user.getFollowingV2', 'start', {id, cursor, data});
if (data.errors && data.errors[0].code === 32) {
return reject("Not logged in");
}
@@ -2206,14 +2252,14 @@ const API = {
}).filter(e => e),
cursor: list.find(e => e.entryId.startsWith('cursor-bottom-')).content.value
}
- debugLog('user.getFollowing', 'end', out);
+ debugLog('user.getFollowingV2', 'end', out);
resolve(out);
}).catch(e => {
reject(e);
});
});
},
- getFollowers: (id, cursor, count = 100) => {
+ getFollowersV2: (id, cursor, count = 100) => {
return new Promise((resolve, reject) => {
let obj = {
"userId": id,
@@ -2247,7 +2293,7 @@ const API = {
},
credentials: "include"
}).then(i => i.json()).then(data => {
- debugLog('user.getFollowers', 'start', {id, cursor, data});
+ debugLog('user.getFollowersV2', 'start', {id, cursor, data});
if (data.errors && data.errors[0].code === 32) {
return reject("Not logged in");
}
@@ -2267,7 +2313,7 @@ const API = {
}),
cursor: list.find(e => e.entryId.startsWith('cursor-bottom-')).content.value
};
- debugLog('user.getFollowers', 'end', out);
+ debugLog('user.getFollowersV2', 'end', out);
resolve(out);
}).catch(e => {
reject(e);
diff --git a/scripts/config.js b/scripts/config.js
index 2b6e83ee..a7a561f5 100644
--- a/scripts/config.js
+++ b/scripts/config.js
@@ -32,7 +32,8 @@ async function loadVars() {
'acknowledgedCustomizationButton', 'modernUI', 'showExactValues', 'hideTimelineTypes', 'autotranslateLanguages',
'autotranslationMode', 'muteVideos', 'dontPauseVideos', 'showUserPreviewsOnMobile', 'systemDarkMode', 'localizeDigit',
'disableRetweetHotkey', 'disableLikeHotkey', 'disableFindHotkey', 'extensionCompatibilityMode', 'disableDataSaver', 'disableAcceptType',
- 'showUserFollowerCountsInLists', 'showQuoteCount', 'hideUnfollowersPage', 'transitionProfileBanner', 'customDownloadTemplate'
+ 'showUserFollowerCountsInLists', 'showQuoteCount', 'hideUnfollowersPage', 'transitionProfileBanner', 'customDownloadTemplate',
+ 'showBoringIndicators'
], data => {
// default variables
if(typeof(data.linkColorsInTL) !== 'boolean') {
diff --git a/scripts/helpers.js b/scripts/helpers.js
index 2e601a66..842de21b 100644
--- a/scripts/helpers.js
+++ b/scripts/helpers.js
@@ -1500,7 +1500,7 @@ function renderMedia(t) {
return _html;
}
-async function appendUser(u, container, label) {
+async function appendUser(u, container, label, usernameClass = '') {
let userElement = document.createElement('div');
userElement.classList.add('user-item');
if(vars.twitterBlueCheckmarks && u.ext && u.ext.isBlueVerified && u.ext.isBlueVerified.r && u.ext.isBlueVerified.r.ok) {
@@ -1518,7 +1518,7 @@ async function appendUser(u, container, label) {
-
+
@${u.screen_name}
${u.followed_by ? `${LOC.follows_you.message}` : ''}
${label ? `
${escapeHTML(label)}` : ''}
diff --git a/scripts/twchallenge.js b/scripts/twchallenge.js
index 8c399e93..7a554855 100644
--- a/scripts/twchallenge.js
+++ b/scripts/twchallenge.js
@@ -33,7 +33,6 @@ function solveChallenge(path, method) {
solveQueue.push({ id, path, method })
} else {
try {
- console.log("sending challenge to solver", solverIframe.contentWindow, path);
solverIframe.contentWindow.postMessage({ action: 'solve', id, path, method }, '*');
} catch(e) {
console.error(`Error sending challenge to solver:`, e);