mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-04-29 11:34:13 +02:00
671 lines
22 KiB
JavaScript
671 lines
22 KiB
JavaScript
(function(){
|
|
//
|
|
// Function: Event callback for a new tweet.
|
|
//
|
|
const onNewTweet = (function(){
|
|
const recentMessages = new Set();
|
|
const recentTweets = new Set();
|
|
let recentTweetTimer = null;
|
|
|
|
const resetRecentTweets = () => {
|
|
recentTweetTimer = null;
|
|
recentTweets.clear();
|
|
};
|
|
|
|
const startRecentTweetTimer = () => {
|
|
recentTweetTimer && window.clearTimeout(recentTweetTimer);
|
|
recentTweetTimer = window.setTimeout(resetRecentTweets, 20000);
|
|
};
|
|
|
|
const checkTweetCache = (set, id) => {
|
|
return true if set.has(id);
|
|
|
|
if (set.size > 50){
|
|
set.clear();
|
|
}
|
|
|
|
set.add(id);
|
|
return false;
|
|
};
|
|
|
|
const isSensitive = (tweet) => {
|
|
const main = tweet.getMainTweet && tweet.getMainTweet();
|
|
return true if main && main.possiblySensitive; // TODO these don't show media badges when hiding sensitive media
|
|
|
|
const related = tweet.getRelatedTweet && tweet.getRelatedTweet();
|
|
return true if related && related.possiblySensitive;
|
|
|
|
const quoted = tweet.quotedTweet;
|
|
return true if quoted && quoted.possiblySensitive;
|
|
|
|
return false;
|
|
};
|
|
|
|
const fixMedia = (html, media) => {
|
|
return html.find("a[data-media-entity-id='" + media.mediaId + "'], .media-item").first().removeClass("is-zoomable").css("background-image", 'url("' + media.small() + '")');
|
|
};
|
|
|
|
return function(column, tweet){
|
|
if (tweet instanceof TD.services.TwitterConversation || tweet instanceof TD.services.TwitterConversationMessageEvent){
|
|
return if checkTweetCache(recentMessages, tweet.id);
|
|
}
|
|
else{
|
|
return if checkTweetCache(recentTweets, tweet.id);
|
|
}
|
|
|
|
startRecentTweetTimer();
|
|
|
|
if (column.model.getHasNotification()){
|
|
const sensitive = isSensitive(tweet);
|
|
const previews = $TDX.notificationMediaPreviews && (!sensitive || TD.settings.getDisplaySensitiveMedia());
|
|
// TODO new cards don't have either previews or links
|
|
|
|
const html = $(tweet.render({
|
|
withFooter: false,
|
|
withTweetActions: false,
|
|
withMediaPreview: true,
|
|
isMediaPreviewOff: !previews,
|
|
isMediaPreviewSmall: previews,
|
|
isMediaPreviewLarge: false,
|
|
isMediaPreviewCompact: false,
|
|
isMediaPreviewInQuoted: previews,
|
|
thumbSizeClass: "media-size-medium",
|
|
mediaPreviewSize: "medium"
|
|
}));
|
|
|
|
html.find("footer").last().remove(); // apparently withTweetActions breaks for certain tweets, nice
|
|
html.find(".js-quote-detail").removeClass("is-actionable margin-b--8"); // prevent quoted tweets from changing the cursor and reduce bottom margin
|
|
|
|
if (previews){
|
|
html.find(".reverse-image-search").remove();
|
|
|
|
const container = html.find(".js-media");
|
|
|
|
for(let media of tweet.getMedia()){
|
|
fixMedia(container, media);
|
|
}
|
|
|
|
if (tweet.quotedTweet){
|
|
for(let media of tweet.quotedTweet.getMedia()){
|
|
fixMedia(container, media).addClass("media-size-medium");
|
|
}
|
|
}
|
|
}
|
|
else if (tweet instanceof TD.services.TwitterActionOnTweet){
|
|
html.find(".js-media").remove();
|
|
}
|
|
|
|
html.find("a[data-full-url]").each(function(){ // bypass t.co on all links and fix tooltips
|
|
this.href = this.getAttribute("data-full-url");
|
|
this.removeAttribute("title");
|
|
});
|
|
|
|
html.find("a[href='#']").each(function(){ // remove <a> tags around links that don't lead anywhere (such as account names the tweet replied to)
|
|
this.outerHTML = this.innerHTML;
|
|
});
|
|
|
|
html.find("p.link-complex-target").filter(function(){
|
|
return $(this).text() === "Show this thread";
|
|
}).first().each(function(){
|
|
this.id = "tduck-show-thread";
|
|
|
|
const moveBefore = html.find(".tweet-body > .js-media, .tweet-body > .js-media-preview-container, .quoted-tweet");
|
|
|
|
if (moveBefore){
|
|
$(this).css("margin-top", "5px").removeClass("margin-b--5").parent("span").detach().insertBefore(moveBefore);
|
|
}
|
|
});
|
|
|
|
if (tweet.quotedTweet){
|
|
html.find("p.txt-mute").filter(function(){
|
|
return $(this).text() === "Show this thread";
|
|
}).first().remove();
|
|
}
|
|
|
|
const type = tweet.getChirpType();
|
|
|
|
if (type === "follow"){
|
|
html.find(".js-user-actions-menu").parent().remove();
|
|
html.find(".account-bio").removeClass("padding-t--5").css("padding-top", "2px");
|
|
}
|
|
else if ((type.startsWith("favorite") || type.startsWith("retweet")) && tweet.isAboutYou()){
|
|
html.children().first().addClass("td-notification-padded");
|
|
}
|
|
else if (type.includes("list_member")){
|
|
html.children().first().addClass("td-notification-padded td-notification-padded-alt");
|
|
html.find(".activity-header").css("margin-top", "2px");
|
|
html.find(".avatar").first().css("margin-bottom", "0");
|
|
}
|
|
|
|
if (sensitive){
|
|
html.find(".media-badge").each(function(){
|
|
$(this)[0].lastChild.textContent += " (possibly sensitive)";
|
|
});
|
|
}
|
|
|
|
const source = tweet.getRelatedTweet();
|
|
const duration = source ? source.text.length + (source.quotedTweet ? source.quotedTweet.text.length : 0) : tweet.text.length;
|
|
|
|
const chirpId = source ? source.id : "";
|
|
const tweetUrl = source ? source.getChirpURL() : "";
|
|
const quoteUrl = source && source.quotedTweet ? source.quotedTweet.getChirpURL() : "";
|
|
|
|
$TD.onTweetPopup(column.model.privateState.apiid, chirpId, window.TDGF_getColumnName(column), html.html(), duration, tweetUrl, quoteUrl);
|
|
}
|
|
|
|
if (column.model.getHasSound()){
|
|
$TD.onTweetSound();
|
|
}
|
|
};
|
|
})();
|
|
|
|
//
|
|
// Block: Enable popup notifications.
|
|
//
|
|
execSafe(function hookDesktopNotifications(){
|
|
ensurePropertyExists(TD, "controller", "notifications");
|
|
|
|
TD.controller.notifications.hasNotifications = function(){
|
|
return true;
|
|
};
|
|
|
|
TD.controller.notifications.isPermissionGranted = function(){
|
|
return true;
|
|
};
|
|
|
|
$.subscribe("/notifications/new", function(obj){
|
|
for(let index = obj.items.length - 1; index >= 0; index--){
|
|
onNewTweet(obj.column, obj.items[index]);
|
|
}
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Fix DM notifications not showing if the conversation is open.
|
|
//
|
|
if (checkPropertyExists(TD, "vo", "Column", "prototype", "mergeMissingChirps")){
|
|
TD.vo.Column.prototype.mergeMissingChirps = prependToFunction(TD.vo.Column.prototype.mergeMissingChirps, function(e){
|
|
const model = this.model;
|
|
|
|
if (model && model.state && model.state.type === "privateMe" && !this.notificationsDisabled && e.poller.feed.managed){
|
|
const unread = [];
|
|
|
|
for(let chirp of e.chirps){
|
|
if (Array.isArray(chirp.messages)){
|
|
Array.prototype.push.apply(unread, chirp.messages.filter(message => message.read === false));
|
|
}
|
|
}
|
|
|
|
if (unread.length > 0){
|
|
if (checkPropertyExists(TD, "util", "chirpReverseColumnSort")){
|
|
unread.sort(TD.util.chirpReverseColumnSort);
|
|
}
|
|
|
|
for(let message of unread){
|
|
onNewTweet(this, message);
|
|
}
|
|
|
|
// TODO sound notifications are borked as well
|
|
// TODO figure out what to do with missed notifications at startup
|
|
}
|
|
}
|
|
});
|
|
}
|
|
})();
|
|
|
|
//
|
|
// Block: Mute sound notifications.
|
|
//
|
|
HTMLAudioElement.prototype.play = prependToFunction(HTMLAudioElement.prototype.play, function(){
|
|
return $TDX.muteNotifications;
|
|
});
|
|
|
|
//
|
|
// Block: Add additional link information to context menu.
|
|
//
|
|
execSafe(function setupLinkContextMenu(){
|
|
$(document.body).delegate("a", "contextmenu", function(){
|
|
const me = $(this)[0];
|
|
|
|
if (me.classList.contains("js-media-image-link")){
|
|
const hovered = getHoveredTweet();
|
|
return if !hovered;
|
|
|
|
const tweet = hovered.obj.hasMedia() ? hovered.obj : hovered.obj.quotedTweet;
|
|
const media = tweet.getMedia().find(media => media.mediaId === me.getAttribute("data-media-entity-id"));
|
|
|
|
if ((media.isVideo && media.service === "twitter") || media.isAnimatedGif){
|
|
$TD.setRightClickedLink("video", media.chooseVideoVariant().url);
|
|
}
|
|
else{
|
|
$TD.setRightClickedLink("image", media.large());
|
|
}
|
|
}
|
|
else if (me.classList.contains("js-gif-play")){
|
|
$TD.setRightClickedLink("video", $(this).closest(".js-media-gif-container").find("video").attr("src"));
|
|
}
|
|
else if (me.hasAttribute("data-full-url")){
|
|
$TD.setRightClickedLink("link", me.getAttribute("data-full-url"));
|
|
}
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Add tweet-related options to context menu.
|
|
//
|
|
execSafe(function setupTweetContextMenu(){
|
|
ensurePropertyExists(TD, "controller", "columnManager", "get");
|
|
ensurePropertyExists(TD, "services", "ChirpBase", "TWEET");
|
|
ensurePropertyExists(TD, "services", "TwitterActionFollow");
|
|
|
|
const processMedia = function(chirp){
|
|
return chirp.getMedia().filter(item => !item.isAnimatedGif).map(item => item.entity.media_url_https + ":small").join(";");
|
|
};
|
|
|
|
app.delegate("section.js-column", "contextmenu", function(){
|
|
const hovered = getHoveredTweet();
|
|
return if !hovered;
|
|
|
|
const tweet = hovered.obj;
|
|
const quote = tweet.quotedTweet;
|
|
|
|
if (tweet.chirpType === TD.services.ChirpBase.TWEET){
|
|
const tweetUrl = tweet.getChirpURL();
|
|
const quoteUrl = quote && quote.getChirpURL();
|
|
|
|
const chirpAuthors = quote ? [ tweet.getMainUser().screenName, quote.getMainUser().screenName ].join(";") : tweet.getMainUser().screenName;
|
|
const chirpImages = tweet.hasImage() ? processMedia(tweet) : quote && quote.hasImage() ? processMedia(quote) : "";
|
|
|
|
$TD.setRightClickedChirp(tweetUrl || "", quoteUrl || "", chirpAuthors, chirpImages);
|
|
}
|
|
else if (tweet instanceof TD.services.TwitterActionFollow){
|
|
$TD.setRightClickedLink("link", tweet.following.getProfileURL());
|
|
}
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Expand shortened links on hover or display tooltip.
|
|
//
|
|
execSafe(function setupLinkExpansionOrTooltip(){
|
|
let prevMouseX = -1, prevMouseY = -1;
|
|
let tooltipTimer, tooltipDisplayed;
|
|
|
|
$(document.body).delegate("a[data-full-url]", {
|
|
mouseenter: function(){
|
|
const me = $(this);
|
|
const text = me.text();
|
|
return if text.charCodeAt(text.length - 1) !== 8230 && text.charCodeAt(0) !== 8230; // horizontal ellipsis
|
|
|
|
if ($TDX.expandLinksOnHover){
|
|
tooltipTimer = window.setTimeout(function(){
|
|
me.attr("td-prev-text", text);
|
|
me.text(me.attr("data-full-url").replace(/^https?:\/\/(www\.)?/, ""));
|
|
}, 200);
|
|
}
|
|
else{
|
|
me.removeAttr("title");
|
|
|
|
tooltipTimer = window.setTimeout(function(){
|
|
$TD.displayTooltip(me.attr("data-full-url"));
|
|
tooltipDisplayed = true;
|
|
}, 400);
|
|
}
|
|
},
|
|
|
|
mouseleave: function(){
|
|
const me = $(this)[0];
|
|
|
|
if (me.hasAttribute("td-prev-text")){
|
|
me.innerText = me.getAttribute("td-prev-text");
|
|
}
|
|
|
|
window.clearTimeout(tooltipTimer);
|
|
|
|
if (tooltipDisplayed){
|
|
tooltipDisplayed = false;
|
|
$TD.displayTooltip(null);
|
|
}
|
|
},
|
|
|
|
mousemove: function(e){
|
|
if (tooltipDisplayed && (prevMouseX !== e.clientX || prevMouseY !== e.clientY)){
|
|
$TD.displayTooltip($(this).attr("data-full-url"));
|
|
prevMouseX = e.clientX;
|
|
prevMouseY = e.clientY;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Support for extra mouse buttons.
|
|
//
|
|
execSafe(function supportExtraMouseButtons(){
|
|
const tryClickSelector = function(selector, parent){
|
|
return $(selector, parent).click().length;
|
|
};
|
|
|
|
const tryCloseModal1 = function(){
|
|
const modal = $("#open-modal");
|
|
return modal.is(":visible") && tryClickSelector("a.mdl-dismiss", modal);
|
|
};
|
|
|
|
const tryCloseModal2 = function(){
|
|
const modal = $(".js-modals-container");
|
|
return modal.length && tryClickSelector("a.mdl-dismiss", modal);
|
|
};
|
|
|
|
const tryCloseHighlightedColumn = function(){
|
|
const column = getHoveredColumn();
|
|
return false if !column;
|
|
|
|
const ele = $(column.ele);
|
|
return ((ele.is(".is-shifted-2") && tryClickSelector(".js-tweet-social-proof-back", ele)) || (ele.is(".is-shifted-1") && tryClickSelector(".js-column-back", ele)));
|
|
};
|
|
|
|
window.TDGF_onMouseClickExtra = function(button){
|
|
if (button === 1){ // back button
|
|
tryClickSelector(".is-shifted-2 .js-tweet-social-proof-back", ".js-modal-panel") ||
|
|
tryClickSelector(".is-shifted-1 .js-column-back", ".js-modal-panel") ||
|
|
tryCloseModal1() ||
|
|
tryCloseModal2() ||
|
|
tryClickSelector(".js-inline-compose-close") ||
|
|
tryCloseHighlightedColumn() ||
|
|
tryClickSelector(".js-app-content.is-open .js-drawer-close:visible") ||
|
|
tryClickSelector(".is-shifted-2 .js-tweet-social-proof-back, .is-shifted-2 .js-dm-participants-back") ||
|
|
$(".is-shifted-1 .js-column-back").click();
|
|
}
|
|
else if (button === 2){ // forward button
|
|
const hovered = getHoveredTweet();
|
|
|
|
if (hovered){
|
|
$(hovered.ele).children().first().click();
|
|
}
|
|
}
|
|
};
|
|
});
|
|
|
|
//
|
|
// Block: Allow drag & drop behavior for dropping links on columns to open their detail view.
|
|
//
|
|
execSafe(function supportDragDropOverColumns(){
|
|
const regexTweet = /^https?:\/\/twitter\.com\/[A-Za-z0-9_]+\/status\/(\d+)\/?\??/;
|
|
const regexAccount = /^https?:\/\/twitter\.com\/(?!signup$|tos$|privacy$|search$|search-)([^/?]+)\/?$/;
|
|
|
|
let dragType = false;
|
|
|
|
const events = {
|
|
dragover: function(e){
|
|
e.originalEvent.dataTransfer.dropEffect = dragType ? "all" : "none";
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
},
|
|
|
|
drop: function(e){
|
|
const url = e.originalEvent.dataTransfer.getData("URL");
|
|
|
|
if (dragType === "tweet"){
|
|
const match = regexTweet.exec(url);
|
|
|
|
if (match.length === 2){
|
|
const column = TD.controller.columnManager.get($(this).attr("data-column"));
|
|
|
|
if (column){
|
|
TD.controller.clients.getPreferredClient().show(match[1], function(chirp){
|
|
TD.ui.updates.showDetailView(column, chirp, column.findChirp(chirp) || chirp);
|
|
$(document).trigger("uiGridClearSelection");
|
|
}, function(){
|
|
alert("error|Could not retrieve the requested tweet.");
|
|
});
|
|
}
|
|
}
|
|
}
|
|
else if (dragType === "account"){
|
|
const match = regexAccount.exec(url);
|
|
|
|
if (match.length === 2){
|
|
$(document).trigger("uiShowProfile", { id: match[1] });
|
|
}
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
};
|
|
|
|
const selectors = {
|
|
tweet: "section.js-column",
|
|
account: app
|
|
};
|
|
|
|
window.TDGF_onGlobalDragStart = function(type, data){
|
|
if (dragType){
|
|
app.undelegate(selectors[dragType], events);
|
|
dragType = null;
|
|
}
|
|
|
|
if (type === "link"){
|
|
dragType = regexTweet.test(data) ? "tweet" : regexAccount.test(data) ? "account": null;
|
|
app.delegate(selectors[dragType], events);
|
|
}
|
|
};
|
|
});
|
|
|
|
//
|
|
// Block: Make middle click on tweet reply icon open the compose drawer, retweet icon trigger a quote, and favorite icon open a 'Like from accounts...' modal.
|
|
//
|
|
execSafe(function supportMiddleClickTweetActions(){
|
|
app.delegate(".tweet-action,.tweet-detail-action", "auxclick", function(e){
|
|
return if e.which !== 2;
|
|
|
|
const column = TD.controller.columnManager.get($(this).closest("section.js-column").attr("data-column"));
|
|
return if !column;
|
|
|
|
const ele = $(this).closest("article");
|
|
const tweet = column.findChirp(ele.attr("data-tweet-id")) || column.findChirp(ele.attr("data-key"));
|
|
return if !tweet;
|
|
|
|
switch($(this).attr("rel")){
|
|
case "reply":
|
|
const main = tweet.getMainTweet();
|
|
|
|
$(document).trigger("uiDockedComposeTweet", {
|
|
type: "reply",
|
|
from: [ tweet.account.getKey() ],
|
|
inReplyTo: {
|
|
id: tweet.id,
|
|
htmlText: main.htmlText,
|
|
user: {
|
|
screenName: main.user.screenName,
|
|
name: main.user.name,
|
|
profileImageURL: main.user.profileImageURL
|
|
}
|
|
},
|
|
mentions: tweet.getReplyUsers(),
|
|
element: ele
|
|
});
|
|
|
|
break;
|
|
|
|
case "favorite":
|
|
$(document).trigger("uiShowFavoriteFromOptions", { tweet });
|
|
break;
|
|
|
|
case "retweet":
|
|
TD.controller.stats.quoteTweet();
|
|
|
|
$(document).trigger("uiComposeTweet", {
|
|
type: "tweet",
|
|
from: [ tweet.account.getKey() ],
|
|
quotedTweet: tweet.getMainTweet(),
|
|
element: ele // triggers reply-account plugin
|
|
});
|
|
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
e.stopImmediatePropagation();
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Add a pin icon to make tweet compose drawer stay open.
|
|
//
|
|
execSafe(function setupStayOpenPin(){
|
|
$(document).on("tduckOldComposerActive", function(e){
|
|
const ele = $(`#import "markup/pin.html"`).appendTo(".js-docked-compose .js-compose-header");
|
|
|
|
ele.click(function(){
|
|
if (TD.settings.getComposeStayOpen()){
|
|
ele.css("transform", "rotate(0deg)");
|
|
TD.settings.setComposeStayOpen(false);
|
|
}
|
|
else{
|
|
ele.css("transform", "rotate(90deg)");
|
|
TD.settings.setComposeStayOpen(true);
|
|
}
|
|
});
|
|
|
|
if (TD.settings.getComposeStayOpen()){
|
|
ele.css("transform", "rotate(90deg)");
|
|
}
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Make submitting search queries while holding Ctrl or middle-clicking the search icon open the search externally.
|
|
//
|
|
onAppReady.push(function setupSearchTriggerHook(){
|
|
const openSearchExternally = function(event, input){
|
|
$TD.openBrowser("https://twitter.com/search/?q=" + encodeURIComponent(input.val() || ""));
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
input.val("").blur();
|
|
app.click(); // unfocus everything
|
|
};
|
|
|
|
$$(".js-app-search-input").keydown(function(e){
|
|
(e.ctrlKey && e.keyCode === 13) && openSearchExternally(e, $(this)); // enter
|
|
});
|
|
|
|
$$(".js-perform-search").on("click auxclick", function(e){
|
|
(e.ctrlKey || e.button === 1) && openSearchExternally(e, $(".js-app-search-input:visible"));
|
|
}).each(function(){
|
|
window.TDGF_prioritizeNewestEvent($(this)[0], "click");
|
|
});
|
|
|
|
$$("[data-action='show-search']").on("click auxclick", function(e){
|
|
(e.ctrlKey || e.button === 1) && openSearchExternally(e, $());
|
|
});
|
|
});
|
|
|
|
//
|
|
// Block: Setup video player hooks.
|
|
//
|
|
execSafe(function setupVideoPlayer(){
|
|
const getGifLink = function(ele){
|
|
return ele.attr("src") || ele.children("source[video-src]").first().attr("video-src");
|
|
};
|
|
|
|
const getVideoTweetLink = function(obj){
|
|
let parent = obj.closest(".js-tweet").first();
|
|
let link = (parent.hasClass("tweet-detail") ? parent.find("a[rel='url']") : parent.find("time").first().children("a")).first();
|
|
return link.attr("href");
|
|
};
|
|
|
|
const getUsername = function(tweet){
|
|
return tweet && (tweet.quotedTweet || tweet).getMainUser().screenName;
|
|
};
|
|
|
|
app.delegate(".js-gif-play", {
|
|
click: function(e){
|
|
let src = !e.ctrlKey && getGifLink($(this).closest(".js-media-gif-container").find("video"));
|
|
let tweet = getVideoTweetLink($(this));
|
|
|
|
if (src){
|
|
let hovered = getHoveredTweet();
|
|
window.TDGF_playVideo(src, tweet, getUsername(hovered && hovered.obj));
|
|
}
|
|
else{
|
|
$TD.openBrowser(tweet);
|
|
}
|
|
|
|
e.stopPropagation();
|
|
},
|
|
|
|
mousedown: function(e){
|
|
if (e.button === 1){
|
|
e.preventDefault();
|
|
}
|
|
},
|
|
|
|
mouseup: function(e){
|
|
if (e.button === 1){
|
|
$TD.openBrowser(getVideoTweetLink($(this)));
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
|
|
window.TDGF_injectMustache("status/media_thumb.mustache", "append", "is-gif", " is-paused");
|
|
|
|
TD.mustaches["media/native_video.mustache"] = '<div class="js-media-gif-container media-item nbfc is-video" style="background-image:url({{imageSrc}})"><video class="js-media-gif media-item-gif full-width block {{#isPossiblySensitive}}is-invisible{{/isPossiblySensitive}}" loop src="{{videoUrl}}"></video><a class="js-gif-play pin-all is-actionable">{{> media/video_overlay}}</a></div>';
|
|
|
|
ensurePropertyExists(TD, "components", "MediaGallery", "prototype", "_loadTweet");
|
|
ensurePropertyExists(TD, "components", "BaseModal", "prototype", "setAndShowContainer");
|
|
ensurePropertyExists(TD, "ui", "Column", "prototype", "playGifIfNotManuallyPaused");
|
|
|
|
let cancelModal = false;
|
|
|
|
TD.components.MediaGallery.prototype._loadTweet = appendToFunction(TD.components.MediaGallery.prototype._loadTweet, function(){
|
|
const media = this.chirp.getMedia().find(media => media.mediaId === this.clickedMediaEntityId);
|
|
|
|
if (media && media.isVideo && media.service === "twitter"){
|
|
window.TDGF_playVideo(media.chooseVideoVariant().url, this.chirp.getChirpURL(), getUsername(this.chirp));
|
|
cancelModal = true;
|
|
}
|
|
});
|
|
|
|
TD.components.BaseModal.prototype.setAndShowContainer = prependToFunction(TD.components.BaseModal.prototype.setAndShowContainer, function(){
|
|
if (cancelModal){
|
|
cancelModal = false;
|
|
return true;
|
|
}
|
|
});
|
|
|
|
TD.ui.Column.prototype.playGifIfNotManuallyPaused = function(){};
|
|
});
|
|
|
|
//
|
|
// Block: Detect and notify about connection issues.
|
|
//
|
|
(function(){
|
|
const onConnectionError = function(){
|
|
return if $("#tweetduck-conn-issues").length;
|
|
|
|
const ele = $(`#import "markup/offline.html"`).appendTo(document.body);
|
|
|
|
ele.find("button").click(function(){
|
|
ele.fadeOut(200);
|
|
});
|
|
};
|
|
|
|
const onConnectionFine = function(){
|
|
const ele = $("#tweetduck-conn-issues");
|
|
|
|
ele.fadeOut(200, function(){
|
|
ele.remove();
|
|
});
|
|
};
|
|
|
|
window.addEventListener("offline", onConnectionError);
|
|
window.addEventListener("online", onConnectionFine);
|
|
})();
|