mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-05-24 05:34:06 +02:00
280 lines
8.0 KiB
JavaScript
280 lines
8.0 KiB
JavaScript
//
|
|
// Functions: Responds to updating $TDX properties.
|
|
//
|
|
(function(){
|
|
let callbacks = [];
|
|
|
|
window.TDGF_registerPropertyUpdateCallback = function(callback){
|
|
callbacks.push(callback);
|
|
};
|
|
|
|
window.TDGF_onPropertiesUpdated = function(){
|
|
callbacks.forEach(func => func($TDX));
|
|
};
|
|
})();
|
|
|
|
//
|
|
// Function: Injects custom HTML into mustache templates.
|
|
//
|
|
window.TDGF_injectMustache = function(name, operation, search, custom){
|
|
let replacement;
|
|
|
|
switch(operation){
|
|
case "replace": replacement = custom; break;
|
|
case "append": replacement = search + custom; break;
|
|
case "prepend": replacement = custom + search; break;
|
|
default: throw "Invalid mustache injection operation. Only 'replace', 'append', 'prepend' are supported.";
|
|
}
|
|
|
|
const prev = TD.mustaches && TD.mustaches[name];
|
|
|
|
if (!prev){
|
|
crashDebug("Mustache injection is referencing an invalid mustache: " + name);
|
|
return false;
|
|
}
|
|
|
|
TD.mustaches[name] = prev.replace(search, replacement);
|
|
|
|
if (prev === TD.mustaches[name]){
|
|
crashDebug("Mustache injection had no effect: " + name);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
//
|
|
// Function: Pushes the newest jQuery event to the beginning of the event handler list.
|
|
//
|
|
window.TDGF_prioritizeNewestEvent = function(element, event){
|
|
const events = $._data(element, "events");
|
|
|
|
const handlers = events[event];
|
|
const newHandler = handlers[handlers.length - 1];
|
|
|
|
for(let index = handlers.length - 1; index > 0; index--){
|
|
handlers[index] = handlers[index - 1];
|
|
}
|
|
|
|
handlers[0] = newHandler;
|
|
};
|
|
|
|
//
|
|
// Function: Returns a display name for a column object.
|
|
//
|
|
window.TDGF_getColumnName = (function(){
|
|
const titles = {
|
|
"icon-home": "Home",
|
|
"icon-mention": "Mentions",
|
|
"icon-message": "Messages",
|
|
"icon-notifications": "Notifications",
|
|
"icon-follow": "Followers",
|
|
"icon-activity": "Activity",
|
|
"icon-favorite": "Likes",
|
|
"icon-user": "User",
|
|
"icon-search": "Search",
|
|
"icon-list": "List",
|
|
"icon-custom-timeline": "Timeline",
|
|
"icon-dataminr": "Dataminr",
|
|
"icon-play-video": "Live video",
|
|
"icon-schedule": "Scheduled"
|
|
};
|
|
|
|
return function(column){
|
|
return titles[column._tduck_icon] || "";
|
|
};
|
|
})();
|
|
|
|
//
|
|
// Function: Adds a search column with the specified query.
|
|
//
|
|
onAppReady.push(() => execSafe(function setupSearchFunction(){
|
|
const context = $._data(document, "events")["uiSearchInputSubmit"][0].handler.context;
|
|
|
|
window.TDGF_performSearch = function(query){
|
|
context.performSearch({ query, tduckResetInput: true });
|
|
};
|
|
}, function(){
|
|
window.TDGF_performSearch = function(){
|
|
alert("error|This feature is not available due to an internal error.");
|
|
};
|
|
}));
|
|
|
|
//
|
|
// Function: Plays sound notification.
|
|
//
|
|
window.TDGF_playSoundNotification = function(){
|
|
document.getElementById("update-sound").play();
|
|
};
|
|
|
|
//
|
|
// Function: Plays video using the internal player.
|
|
//
|
|
window.TDGF_playVideo = function(videoUrl, tweetUrl, username){
|
|
return if !videoUrl;
|
|
|
|
$TD.playVideo(videoUrl, tweetUrl || videoUrl, username || null, function(){
|
|
$('<div id="td-video-player-overlay" class="ovl" style="display:block"></div>').on("click contextmenu", function(){
|
|
$TD.stopVideo();
|
|
}).appendTo(app);
|
|
});
|
|
};
|
|
|
|
//
|
|
// Function: Shows tweet detail, used in notification context menu.
|
|
//
|
|
execSafe(function setupShowTweetDetail(){
|
|
ensurePropertyExists(TD, "ui", "updates", "showDetailView");
|
|
ensurePropertyExists(TD, "controller", "columnManager", "showColumn");
|
|
ensurePropertyExists(TD, "controller", "columnManager", "getByApiid");
|
|
ensurePropertyExists(TD, "controller", "clients", "getPreferredClient");
|
|
|
|
const showTweetDetailInternal = function(column, chirp){
|
|
TD.ui.updates.showDetailView(column, chirp, column.findChirp(chirp) || chirp);
|
|
TD.controller.columnManager.showColumn(column.model.privateState.key);
|
|
|
|
$(document).trigger("uiGridClearSelection");
|
|
};
|
|
|
|
window.TDGF_showTweetDetail = function(columnId, chirpId, fallbackUrl){
|
|
if (!TD.ready){
|
|
onAppReady.push(function(){
|
|
window.TDGF_showTweetDetail(columnId, chirpId, fallbackUrl);
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
const column = TD.controller.columnManager.getByApiid(columnId);
|
|
|
|
if (!column){
|
|
if (confirm("error|The column which contained the tweet no longer exists. Would you like to open the tweet in your browser instead?")){
|
|
$TD.openBrowser(fallbackUrl);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
const chirp = column.findMostInterestingChirp(chirpId);
|
|
|
|
if (chirp){
|
|
showTweetDetailInternal(column, chirp);
|
|
}
|
|
else{
|
|
TD.controller.clients.getPreferredClient().show(chirpId, function(chirp){
|
|
showTweetDetailInternal(column, chirp);
|
|
}, function(){
|
|
if (confirm("error|Could not retrieve the requested tweet. Would you like to open the tweet in your browser instead?")){
|
|
$TD.openBrowser(fallbackUrl);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}, function(){
|
|
window.TDGF_showTweetDetail = function(){
|
|
alert("error|This feature is not available due to an internal error.");
|
|
};
|
|
});
|
|
|
|
//
|
|
// Function: Screenshots tweet to clipboard.
|
|
//
|
|
execSafe(function setupTweetScreenshot(){
|
|
window.TDGF_triggerScreenshot = function(){
|
|
const hovered = getHoveredTweet();
|
|
return if !hovered;
|
|
|
|
const columnWidth = $(hovered.column.ele).width();
|
|
const tweet = hovered.wrap || hovered.obj;
|
|
|
|
const html = $(tweet.render({
|
|
withFooter: false,
|
|
withTweetActions: false,
|
|
isInConvo: false,
|
|
isFavorite: false,
|
|
isRetweeted: false, // keeps retweet mark above tweet
|
|
isPossiblySensitive: false,
|
|
mediaPreviewSize: hovered.column.obj.getMediaPreviewSize()
|
|
}));
|
|
|
|
html.find("footer").last().remove(); // apparently withTweetActions breaks for certain tweets, nice
|
|
html.find(".td-screenshot-remove").remove();
|
|
|
|
html.find("p.link-complex-target,p.txt-mute").filter(function(){
|
|
return $(this).text() === "Show this thread";
|
|
}).remove();
|
|
|
|
html.addClass($(document.documentElement).attr("class"));
|
|
html.addClass($(document.body).attr("class"));
|
|
|
|
html.css("background-color", getClassStyleProperty("stream-item", "background-color"));
|
|
html.css("border", "none");
|
|
|
|
for(let selector of [ ".js-quote-detail", ".js-media-preview-container", ".js-media" ]){
|
|
const ele = html.find(selector);
|
|
|
|
if (ele.length){
|
|
ele[0].style.setProperty("margin-bottom", "2px", "important");
|
|
break;
|
|
}
|
|
}
|
|
|
|
const gif = html.find(".js-media-gif-container");
|
|
|
|
if (gif.length){
|
|
gif.css("background-image", 'url("'+tweet.getMedia()[0].small()+'")');
|
|
}
|
|
|
|
const type = tweet.getChirpType();
|
|
|
|
if ((type.startsWith("favorite") || type.startsWith("retweet")) && tweet.isAboutYou()){
|
|
html.addClass("td-notification-padded");
|
|
}
|
|
|
|
$TD.screenshotTweet(html[0].outerHTML, columnWidth);
|
|
};
|
|
}, function(){
|
|
window.TDGF_triggerScreenshot = function(){
|
|
alert("error|This feature is not available due to an internal error.");
|
|
};
|
|
});
|
|
|
|
//
|
|
// Function: Apply ROT13 to input selection.
|
|
//
|
|
window.TDGF_applyROT13 = function(){
|
|
const ele = document.activeElement;
|
|
return if !ele || !ele.value;
|
|
|
|
const selection = ele.value.substring(ele.selectionStart, ele.selectionEnd);
|
|
return if !selection;
|
|
|
|
document.execCommand("insertText", false, selection.replace(/[a-zA-Z]/g, function(chr){
|
|
const code = chr.charCodeAt(0);
|
|
const start = code <= 90 ? 65 : 97;
|
|
return String.fromCharCode(start + (code - start + 13) % 26);
|
|
}));
|
|
};
|
|
|
|
//
|
|
// Function: Reloads all columns.
|
|
//
|
|
if (checkPropertyExists(TD, "controller", "columnManager", "getAll")){
|
|
window.TDGF_reloadColumns = function(){
|
|
Object.values(TD.controller.columnManager.getAll()).forEach(column => column.reloadTweets());
|
|
};
|
|
}
|
|
else{
|
|
window.TDGF_reloadColumns = function(){};
|
|
}
|
|
|
|
//
|
|
// Function: Reloads the website with memory cleanup.
|
|
//
|
|
window.TDGF_reload = function(){
|
|
window.gc && window.gc();
|
|
window.location.reload();
|
|
|
|
window.TDGF_reload = function(){}; // redefine to prevent reloading multiple times
|
|
};
|