Skip to content

Commit 91999d1

Browse files
authored
Add files via upload
1 parent 6dd4ebb commit 91999d1

5 files changed

Lines changed: 342 additions & 104 deletions

File tree

plugin/background.js

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function createIcon(color, size) {
2121

2222
/**
2323
* Updates the browser action icon's state (enabled/disabled) based on whether the URL
24-
* in the given tab matches any of the user-configured sites.
24+
* in the given tab matches any of the user-configured and enabled sites.
2525
* @param {number} tabId - The ID of the tab to update.
2626
* @param {string} url - The URL of the tab.
2727
*/
@@ -32,6 +32,9 @@ function updateActionIconState(tabId, url) {
3232
const sites = result.sites;
3333
let matchFound = false;
3434
for (const site of sites) {
35+
// Skip disabled sites
36+
if (site.enabled === false) continue;
37+
3538
if (site.host && url.includes(site.host)) {
3639
if (site.urlRegex) {
3740
try {
@@ -67,20 +70,28 @@ function updateActionIconState(tabId, url) {
6770
async function getActiveAddress(settings) {
6871
const addressesToTry = [settings.internalAddress, settings.externalAddress].filter(Boolean);
6972
for (const address of addressesToTry) {
73+
let addressWithProtocol = address;
74+
// If no protocol is specified, default to http. User can override by adding https:// in settings.
75+
if (!address.startsWith('http://') && !address.startsWith('https://')) {
76+
addressWithProtocol = `http://${address}`;
77+
}
78+
7079
let cleanBaseUrl;
80+
// Log which address is being tried.
81+
console.log(`SickChill Plugin: Attempting to connect to ${addressWithProtocol}`);
7182
try {
72-
// Ensure the address has a protocol for the URL constructor.
73-
let addressWithProtocol = address;
74-
if (!address.startsWith('http://') && !address.startsWith('https://')) {
75-
addressWithProtocol = `https://${address}`;
76-
}
7783
const urlObject = new URL(addressWithProtocol);
78-
cleanBaseUrl = `${urlObject.protocol}//${urlObject.host}`;
79-
// Ping the SickChill API to verify connectivity.
84+
// Remove any trailing slash from the path to create a clean base URL.
85+
const cleanPath = urlObject.pathname.replace(/\/+$/, '');
86+
cleanBaseUrl = `${urlObject.protocol}//${urlObject.host}${cleanPath}`;
87+
8088
await fetch(`${cleanBaseUrl}/api/${settings.apiKey}/?cmd=ping`, { signal: AbortSignal.timeout(3000) });
89+
90+
// Log success.
91+
console.log(`SickChill Plugin: Successfully connected to ${cleanBaseUrl}`);
8192
return cleanBaseUrl;
8293
} catch (e) {
83-
console.warn(`Address ${cleanBaseUrl || address} failed the connection test.`);
94+
console.warn(`SickChill Plugin: Connection to ${cleanBaseUrl || addressWithProtocol} failed.`);
8495
}
8596
}
8697
return null;
@@ -146,6 +157,9 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
146157
if (request.action === "directToAddShowPage") {
147158
handleDirectToAddShow(request.name);
148159
}
160+
// Return true to indicate that we will send a response asynchronously.
161+
// This is good practice but not strictly necessary for this specific action.
162+
return true;
149163
});
150164

151165
// --- Event Listeners for Browser Action Icon ---
@@ -163,6 +177,7 @@ function checkActiveTab() {
163177

164178
// Update the icon whenever a tab is updated.
165179
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
180+
// Use 'complete' to ensure the final URL is evaluated
166181
if (changeInfo.status === 'complete') {
167182
updateActionIconState(tabId, tab.url);
168183
}
@@ -171,7 +186,9 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
171186
// Update the icon when the user switches to a different tab.
172187
chrome.tabs.onActivated.addListener((activeInfo) => {
173188
chrome.tabs.get(activeInfo.tabId, (tab) => {
174-
updateActionIconState(tab.id, tab.url);
189+
if (tab) {
190+
updateActionIconState(tab.id, tab.url);
191+
}
175192
});
176193
});
177194

plugin/content.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,13 @@ function performInjection(targetElement, title) {
6464
function initialize() {
6565
chrome.storage.local.get({ sites: [] }, (result) => {
6666
if (chrome.runtime.lastError) return;
67+
6768
const matchingSite = result.sites.find(site => {
69+
// Check if site is enabled (undefined is treated as enabled for backward compatibility)
70+
if (site.enabled === false) {
71+
return false;
72+
}
73+
6874
if (site.host && window.location.href.includes(site.host)) {
6975
// If a URL regex is provided, it must also match.
7076
if (site.urlRegex) {
@@ -79,6 +85,7 @@ function initialize() {
7985
}
8086
return false;
8187
});
88+
8289
if (matchingSite) {
8390
waitForElementsAndInject(matchingSite);
8491
}

plugin/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "SickChill Plugin",
4-
"version": "1.1",
4+
"version": "1.2",
55
"description": "A plugin to interact with SickChill.",
66
"permissions": [
77
"storage",

plugin/options.html

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,35 +89,52 @@
8989
#status { margin-top: 15px; font-weight: bold; }
9090

9191
/* Site List */
92-
#siteList {
92+
#siteList, #shareSiteList, #importSiteList {
9393
list-style: none;
9494
padding: 0;
95+
max-height: 40vh;
96+
overflow-y: auto;
9597
}
9698
.site-item {
9799
display: flex;
98100
align-items: center;
99-
justify-content: space-between;
101+
gap: 15px;
100102
padding: 10px;
101103
border-bottom: 1px solid #eee;
102104
}
103105
.site-item:last-child {
104106
border-bottom: none;
105107
}
108+
.site-details {
109+
flex-grow: 1;
110+
}
106111
.site-item-name {
107112
font-weight: bold;
108113
}
109114
.site-item-host {
110115
color: #555;
111-
margin-left: 15px;
116+
margin-left: 2px;
117+
}
118+
.site-item-actions {
119+
margin-left: auto;
112120
}
113121
.site-item-actions button { margin-left: 10px; }
114122

115123
/* Data Management Section */
116124
.data-actions {
117125
display: flex;
126+
flex-wrap: wrap;
118127
gap: 10px;
119128
margin-top: 10px;
120129
}
130+
131+
/* Toggle Switch CSS */
132+
.switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; }
133+
.switch input { opacity: 0; width: 0; height: 0; }
134+
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 24px; }
135+
.slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; }
136+
input:checked + .slider { background-color: #007bff; }
137+
input:checked + .slider:before { transform: translateX(20px); }
121138

122139
/* Modal */
123140
.modal-backdrop {
@@ -128,6 +145,7 @@
128145
display: none;
129146
align-items: center;
130147
justify-content: center;
148+
z-index: 100;
131149
}
132150
.modal-content {
133151
background-color: white;
@@ -145,6 +163,14 @@
145163
.modal-actions button {
146164
margin-left: 10px;
147165
}
166+
#shareSiteList li, #importSiteList li {
167+
display: flex;
168+
align-items: center;
169+
padding: 8px;
170+
}
171+
#shareSiteList input[type="checkbox"], #importSiteList input[type="checkbox"] {
172+
margin-right: 10px;
173+
}
148174
</style>
149175
</head>
150176
<body>
@@ -153,23 +179,25 @@
153179
<h1>
154180
SickChill Plugin Settings
155181
</h1>
156-
<br>
157-
<span class="header-links">
158-
(<a href="https://tiwas.github.io/sc-plugin/" target="_blank">homepage</a> |
159-
<a href="https://github.com/Tiwas/sc-plugin" target="_blank">github</a>)
160-
</span>
182+
<br>
183+
<span class="header-links">
184+
(<a href="https://tiwas.github.io/sc-plugin/" target="_blank">homepage</a> |
185+
<a href="https://github.com/Tiwas/sc-plugin" target="_blank">github</a>)
186+
</span>
161187
<div id="version-display"></div>
162188
</header>
163189

164190
<div class="settings-card">
165191
<h2>General</h2>
166192
<div class="form-group">
167-
<label for="externalAddress">External Address (IP/Host)</label>
168-
<input type="text" id="externalAddress">
193+
<label for="externalAddress">External Address</label>
194+
<input type="text" id="externalAddress" placeholder="e.g., my-sickchill.com">
195+
<small>Include http:// or https:// if needed. Defaults to http:// if no protocol is specified.</small>
169196
</div>
170197
<div class="form-group">
171-
<label for="internalAddress">Internal Address (IP)</label>
172-
<input type="text" id="internalAddress">
198+
<label for="internalAddress">Internal Address</label>
199+
<input type="text" id="internalAddress" placeholder="e.g., 192.168.1.100:8081">
200+
<small>Include http:// or https:// if needed. Defaults to http:// if no protocol is specified.</small>
173201
</div>
174202
<div class="form-group">
175203
<label for="apiKey">API Key</label>
@@ -195,22 +223,22 @@ <h2>General</h2>
195223
<div class="sites-card">
196224
<h2>Configured Sites</h2>
197225
<ul id="siteList">
198-
<!-- Site items will be injected here by JavaScript -->
199-
</ul>
226+
</ul>
200227
<button id="addSiteBtn" class="btn-primary">Add New Site</button>
201228
</div>
202229

203230
<div class="settings-card">
204231
<h2>Data Management</h2>
205-
<p>Save all your settings to a file, or restore them from a backup.</p>
232+
<p>Save all your settings to a file, restore them from a backup, or load community examples.</p>
206233
<div class="data-actions">
207234
<button id="backupBtn" class="btn-secondary">Backup Settings</button>
208-
<button id="restoreBtn" class="btn-secondary">Restore Settings</button>
235+
<button id="restoreBtn" class="btn-secondary">Load Settings</button>
236+
<button id="loadExamplesBtn" class="btn-secondary">Load Examples</button>
237+
<button id="shareRulesBtn" class="btn-secondary">Share Your Rules</button>
209238
<input type="file" id="restoreInput" accept=".json" style="display: none;">
210239
</div>
211240
</div>
212241

213-
<!-- Modal for adding/editing sites -->
214242
<div id="siteModal" class="modal-backdrop">
215243
<div class="modal-content">
216244
<h2 id="modalTitle">Add Site</h2>
@@ -234,7 +262,6 @@ <h2 id="modalTitle">Add Site</h2>
234262
<input type="text" id="siteContentRegex" placeholder="e.g., TV Series">
235263
<small>Case-insensitive regex to match against the page text content.</small>
236264
</div>
237-
238265
<div class="form-group-box">
239266
<h3>Name Extraction (Required)</h3>
240267
<small>Provide exactly ONE of the following two methods.</small>
@@ -249,7 +276,6 @@ <h3>Name Extraction (Required)</h3>
249276
<small>Extracts name using an XPath query.</small>
250277
</div>
251278
</div>
252-
253279
<div class="form-group-box" style="margin-top: 20px;">
254280
<h3>Logo Injection (Required)</h3>
255281
<div class="form-group" style="margin-top: 15px;">
@@ -258,14 +284,37 @@ <h3>Logo Injection (Required)</h3>
258284
<small>XPath to find the element where the 'Add' link should be injected.</small>
259285
</div>
260286
</div>
261-
262287
<div class="modal-actions">
263288
<button id="cancelModalBtn" class="btn-secondary">Cancel</button>
264289
<button id="saveModalBtn" class="btn-primary">Save Site</button>
265290
</div>
266291
</div>
267292
</div>
268293

294+
<div id="shareModal" class="modal-backdrop">
295+
<div class="modal-content">
296+
<h2>Share Your Rules</h2>
297+
<p>Select the site rules you want to share with the community. This will generate a pre-filled GitHub issue for you to submit.</p>
298+
<ul id="shareSiteList"></ul>
299+
<div class="modal-actions">
300+
<button id="cancelShareModalBtn" class="btn-secondary">Cancel</button>
301+
<button id="generateShareLinkBtn" class="btn-primary">Generate Share Link</button>
302+
</div>
303+
</div>
304+
</div>
305+
306+
<div id="importModal" class="modal-backdrop">
307+
<div class="modal-content">
308+
<h2>Import Rules</h2>
309+
<p>Select the rules you want to import from the file.</p>
310+
<ul id="importSiteList"></ul>
311+
<div class="modal-actions">
312+
<button id="cancelImportModalBtn" class="btn-secondary">Cancel</button>
313+
<button id="importSelectedBtn" class="btn-primary">Import Selected</button>
314+
</div>
315+
</div>
316+
</div>
317+
269318
<script src="options.js"></script>
270319
</body>
271-
</html>
320+
</html>

0 commit comments

Comments
 (0)