adding browser extension and some QoL

This commit is contained in:
2026-08-12 00:14:47 +02:00
parent 0ca65ea473
commit d5f092883a
14 changed files with 1708 additions and 29 deletions

View File

@@ -0,0 +1,197 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
body {
background-color: #0f1015;
color: #dce0ed;
font-size: 14px;
line-height: 1.5;
padding: 40px 20px;
display: flex;
justify-content: center;
}
.container {
width: 100%;
max-width: 640px;
background: #161822;
border: 1px solid #242738;
border-radius: 12px;
padding: 28px 32px;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4);
}
.header {
display: flex;
align-items: center;
gap: 16px;
padding-bottom: 20px;
border-bottom: 1px solid #242738;
margin-bottom: 24px;
}
.logo {
width: 48px;
height: 48px;
}
h1 {
font-size: 20px;
font-weight: 700;
color: #ffffff;
}
.subtitle {
font-size: 13px;
color: #7a829a;
}
.section {
margin-bottom: 24px;
}
h2 {
font-size: 14px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #4da6ff;
margin-bottom: 12px;
}
.field-group {
display: flex;
flex-direction: column;
gap: 10px;
}
.radio-label {
display: flex;
align-items: flex-start;
gap: 12px;
background: #1c1e2d;
border: 1px solid #2a2e44;
padding: 12px 14px;
border-radius: 8px;
cursor: pointer;
transition: border-color 0.2s ease;
}
.radio-label:hover {
border-color: #3d4464;
}
.radio-label input[type="radio"] {
margin-top: 3px;
accent-color: #0066ff;
}
.radio-content strong {
display: block;
font-size: 13px;
color: #ffffff;
}
.radio-content p {
font-size: 12px;
color: #8c93aa;
margin-top: 2px;
}
.field {
margin-bottom: 14px;
display: flex;
flex-direction: column;
gap: 6px;
}
.field label {
font-size: 12px;
font-weight: 600;
color: #b0b6cc;
}
input[type="text"],
input[type="url"],
input[type="password"],
select {
background: #12131b;
border: 1px solid #292d42;
color: #ffffff;
padding: 9px 12px;
border-radius: 7px;
font-size: 13px;
outline: none;
width: 100%;
transition: border-color 0.2s ease;
}
input:focus, select:focus {
border-color: #0066ff;
}
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.field-row {
margin-bottom: 14px;
}
.checkbox-label {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
font-size: 13px;
color: #dce0ed;
}
.checkbox-label input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: #0066ff;
cursor: pointer;
}
.actions {
display: flex;
align-items: center;
gap: 14px;
margin-top: 28px;
padding-top: 20px;
border-top: 1px solid #242738;
}
.btn-save {
background: linear-gradient(135deg, #0066ff, #0044cc);
color: #ffffff;
border: none;
padding: 10px 20px;
font-size: 13px;
font-weight: 700;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-save:hover {
background: linear-gradient(135deg, #1a75ff, #0052e6);
box-shadow: 0 4px 12px rgba(0, 102, 255, 0.3);
}
.toast {
font-size: 13px;
font-weight: 600;
color: #2ed573;
}
.toast.hidden {
display: none;
}

View File

@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>f0ckm Extension Options</title>
<link rel="stylesheet" href="options.css">
</head>
<body>
<div class="container">
<div class="header">
<img src="../icons/icon48.png" alt="f0ckm Icon" class="logo">
<div>
<h1>f0ckm Browser Integration Settings</h1>
<p class="subtitle">Configure browser extension upload modes and API settings</p>
</div>
</div>
<form id="settings-form">
<div class="section">
<h2>Integration Mode</h2>
<div class="field-group">
<label class="radio-label">
<input type="radio" name="uploadMode" value="desktop" id="mode-desktop">
<div class="radio-content">
<strong>Desktop Application Integration (f0ckm://)</strong>
<p>Delegates downloads & uploads directly to the KDE system tray app. Provides live tray digit icons, Spectacle notifications, sound effects, and local gallery history.</p>
</div>
</label>
<label class="radio-label">
<input type="radio" name="uploadMode" value="direct" id="mode-direct">
<div class="radio-content">
<strong>Direct Browser Extension API Upload</strong>
<p>Uploads files directly from the browser background page using API URL and API Key set below.</p>
</div>
</label>
</div>
</div>
<div class="section">
<h2>API & Server Configuration</h2>
<div class="field">
<label for="apiUrl">API Endpoint URL</label>
<input type="url" id="apiUrl" placeholder="https://your-f0ckm-instance.com/api/v2/upload">
</div>
<div class="field">
<label for="apiKey">API Key</label>
<input type="password" id="apiKey" placeholder="Enter your secret API key">
</div>
</div>
<div class="section">
<h2>Default Upload Preferences</h2>
<div class="grid-2">
<div class="field">
<label for="rating">Default Rating</label>
<select id="rating">
<option value="">Default (Untagged)</option>
<option value="sfw">Safe (sfw)</option>
<option value="nsfw">Questionable (nsfw)</option>
<option value="nsfl">Explicit (nsfl)</option>
</select>
</div>
<div class="field">
<label for="visibility">Default Visibility</label>
<select id="visibility">
<option value="0">Public (0)</option>
<option value="1">Unlisted (1)</option>
<option value="2">Private (2)</option>
</select>
</div>
</div>
<div class="field">
<label for="tags">Default Tags</label>
<input type="text" id="tags" placeholder="e.g. browser, web, media">
</div>
<div class="field-row">
<label class="checkbox-label">
<input type="checkbox" id="isOc">
<span>Mark uploads as Original Content (OC)</span>
</label>
</div>
<div class="field">
<label for="urlType">Copied Link Format</label>
<select id="urlType">
<option value="post">f0ckm Post URL (Viewer page)</option>
<option value="direct">Direct File Link (Raw image/media file)</option>
</select>
</div>
</div>
<div class="actions">
<button type="submit" id="btn-save" class="btn-save">Save Settings</button>
<span id="save-toast" class="toast hidden">✓ Settings saved successfully!</span>
</div>
</form>
</div>
<script src="options.js"></script>
</body>
</html>

View File

@@ -0,0 +1,63 @@
const DEFAULT_SETTINGS = {
uploadMode: "desktop",
apiUrl: "https://f0ckm.com/api/v2/upload",
apiKey: "",
rating: "s",
tags: "",
visibility: "0",
isOc: false,
urlType: "post"
};
document.addEventListener("DOMContentLoaded", () => {
const form = document.getElementById("settings-form");
const modeDesktop = document.getElementById("mode-desktop");
const modeDirect = document.getElementById("mode-direct");
const apiUrl = document.getElementById("apiUrl");
const apiKey = document.getElementById("apiKey");
const rating = document.getElementById("rating");
const visibility = document.getElementById("visibility");
const tags = document.getElementById("tags");
const isOc = document.getElementById("isOc");
const urlType = document.getElementById("urlType");
const saveToast = document.getElementById("save-toast");
// Load existing settings
chrome.storage.sync.get(DEFAULT_SETTINGS, (items) => {
if (items.uploadMode === "direct") {
modeDirect.checked = true;
} else {
modeDesktop.checked = true;
}
apiUrl.value = items.apiUrl || "";
apiKey.value = items.apiKey || "";
rating.value = items.rating || "s";
visibility.value = items.visibility !== undefined ? String(items.visibility) : "0";
tags.value = items.tags || "";
isOc.checked = !!items.isOc;
urlType.value = items.urlType || "post";
});
// Save settings on form submit
form.addEventListener("submit", (e) => {
e.preventDefault();
const newSettings = {
uploadMode: modeDirect.checked ? "direct" : "desktop",
apiUrl: apiUrl.value.trim(),
apiKey: apiKey.value.trim(),
rating: rating.value,
visibility: visibility.value,
tags: tags.value.trim(),
isOc: isOc.checked,
urlType: urlType.value
};
chrome.storage.sync.set(newSettings, () => {
saveToast.classList.remove("hidden");
setTimeout(() => {
saveToast.classList.add("hidden");
}, 2500);
});
});
});