-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathLetterboxd_Link_Badges.user.js
More file actions
119 lines (107 loc) · 4.29 KB
/
Letterboxd_Link_Badges.user.js
File metadata and controls
119 lines (107 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// ==UserScript==
// @name Letterboxd Link Badges
// @namespace https://github.com/sinazadeh/userscripts
// @version 1.1.6
// @description Enhances Letterboxd film pages by replacing IMDb/TMDb text links with icons and adding direct "Watch on Stremio" badges.
// @author TheSina
// @match https://letterboxd.com/film/*
// @match https://letterboxd.com/*/film/*
// @grant GM_addStyle
// @license MIT
// @downloadURL https://raw.githubusercontent.com/sinazadeh/userscripts/refs/heads/main/Letterboxd_Link_Badges.user.js
// @updateURL https://raw.githubusercontent.com/sinazadeh/userscripts/refs/heads/main/Letterboxd_Link_Badges.meta.js
// ==/UserScript==
/* jshint esversion: 6 */
(function () {
'use strict';
// 1) Inject CSS overrides + badge styles
GM_addStyle(`
p.text-link.text-footer {
display: flex !important;
align-items: center !important;
flex-wrap: nowrap !important;
}
p.text-link.text-footer a.micro-button {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
margin: 0 8px !important;
padding: 2px !important;
position: relative !important; /* for badge positioning */
}
p.text-link.text-footer img {
width: 36px !important;
height: 36px !important;
vertical-align: middle !important;
}
.stremio-badge {
position: absolute;
top: -4px;
right: -4px;
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: bold;
color: white;
border-radius: 3px;
background: linear-gradient(to bottom right, #8e44ad, #3498db);
}
`);
function createStremioButton(imdbId, type) {
const isApp = type === 'app';
const href = isApp
? `stremio://detail/movie/${imdbId}`
: `https://web.stremio.com/#/detail/movie/${imdbId}/${imdbId}`;
const link = document.createElement('a');
link.className = 'micro-button track-event';
link.dataset.trackAction = `Stremio ${isApp ? 'App' : 'Web'}`;
link.href = href;
link.title = `Open in Stremio ${isApp ? 'App' : 'Web'}`;
if (!isApp) {
link.target = '_blank';
}
const img = document.createElement('img');
img.src =
'https://www.google.com/s2/favicons?domain=web.stremio.com&sz=64';
link.appendChild(img);
const badge = document.createElement('span');
badge.className = 'stremio-badge';
badge.textContent = isApp ? 'A' : 'W';
link.appendChild(badge);
return link;
}
function injectBadges() {
const footer = document.querySelector('p.text-link.text-footer');
if (!footer || footer.dataset.sbInjected) return;
footer.dataset.sbInjected = 'true';
const imdbLink = footer.querySelector('a[data-track-action="IMDb"]');
const tmdbLink = footer.querySelector('a[data-track-action="TMDB"]');
if (!imdbLink || !tmdbLink) return;
const imdbIdMatch = imdbLink.href.match(/tt\d+/);
if (!imdbIdMatch) return;
const imdbId = imdbIdMatch[0];
// Replace text with favicons
const swapFavicon = (link, domain) => {
link.textContent = '';
const img = document.createElement('img');
img.src = `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;
link.appendChild(img);
};
swapFavicon(imdbLink, 'imdb.com');
swapFavicon(tmdbLink, 'themoviedb.org');
// Create and inject Stremio buttons
const stremioAppButton = createStremioButton(imdbId, 'app');
const stremioWebButton = createStremioButton(imdbId, 'web');
tmdbLink.after(stremioAppButton, stremioWebButton);
}
// Run on initial load, PJAX navigations, and DOM changes
injectBadges();
document.addEventListener('pjax:complete', injectBadges);
new MutationObserver(injectBadges).observe(document.body, {
childList: true,
subtree: true,
});
})();