Files
f0ckm-uploader/browser-extension/popup/popup.js

305 lines
10 KiB
JavaScript

function normalizeApiUrl(url) {
if (!url) return "";
url = url.trim().replace(/^['"]|['"]$/g, "");
if (!url) return "";
if (!/^https?:\/\//i.test(url)) {
url = "http://" + url;
}
try {
const parsed = new URL(url);
let path = parsed.pathname.replace(/\/+$/, "");
if (!path || path === "") {
return `${parsed.origin}/api/v2/upload`;
} else if (path.endsWith("/api/v2")) {
return `${parsed.origin}/upload`;
} else if (!path.endsWith("/upload")) {
return `${parsed.origin}/api/v2/upload`;
}
return url;
} catch (e) {
return url;
}
}
function initPopup() {
const modeDesktop = document.getElementById("mode-desktop");
const modeDirect = document.getElementById("mode-direct");
const btnOpenOptions = document.getElementById("btn-open-options");
const apiConfigCard = document.getElementById("api-config-card");
const popupApiUrl = document.getElementById("popup-api-url");
const popupApiKey = document.getElementById("popup-api-key");
const btnSaveApiConfig = document.getElementById("btn-save-api-config");
const btnPopupTest = document.getElementById("btn-popup-test");
const popupApiToast = document.getElementById("popup-api-toast");
const btnUploadTab = document.getElementById("btn-upload-tab");
const btnUploadText = document.getElementById("btn-upload-text");
const btnUploadUrl = document.getElementById("btn-upload-url");
const urlInput = document.getElementById("url-input");
const statusCard = document.getElementById("status-card");
const statusSpinner = document.getElementById("status-spinner");
const statusText = document.getElementById("status-text");
const resultContainer = document.getElementById("result-container");
const resultLink = document.getElementById("result-link");
const btnCopyResult = document.getElementById("btn-copy-result");
const siteBadge = document.getElementById("site-badge");
const tabTitle = document.getElementById("tab-title");
const tabUrlPreview = document.getElementById("tab-url-preview");
let activeTabUrl = "";
if (btnOpenOptions) {
btnOpenOptions.addEventListener("click", () => {
if (chrome.runtime.openOptionsPage) {
chrome.runtime.openOptionsPage();
} else {
window.open(chrome.runtime.getURL("options/options.html"));
}
});
}
function updateModeUI(mode) {
if (mode === "direct") {
if (modeDirect) modeDirect.checked = true;
if (apiConfigCard) apiConfigCard.classList.remove("hidden");
} else {
if (modeDesktop) modeDesktop.checked = true;
if (apiConfigCard) apiConfigCard.classList.add("hidden");
}
}
// 1. Load settings & drafts asynchronously without blocking UI initialization
try {
chrome.storage.sync.get({ uploadMode: "desktop", apiUrl: "", apiKey: "", draftUrl: "" }, (settings) => {
if (chrome.runtime.lastError || !settings) return;
if (popupApiUrl) popupApiUrl.value = settings.apiUrl || "";
if (popupApiKey) popupApiKey.value = settings.apiKey || "";
if (urlInput && settings.draftUrl) urlInput.value = settings.draftUrl;
updateModeUI(settings.uploadMode);
});
} catch (e) {}
// Auto-save on input so values are never lost if popup closes when copying/switching tabs
if (popupApiUrl) {
popupApiUrl.addEventListener("input", () => {
chrome.storage.sync.set({ apiUrl: popupApiUrl.value });
});
}
if (popupApiKey) {
popupApiKey.addEventListener("input", () => {
chrome.storage.sync.set({ apiKey: popupApiKey.value });
});
}
if (urlInput) {
urlInput.addEventListener("input", () => {
chrome.storage.sync.set({ draftUrl: urlInput.value });
});
}
if (modeDesktop) {
modeDesktop.addEventListener("change", () => {
chrome.storage.sync.set({ uploadMode: "desktop" }, () => {
updateModeUI("desktop");
});
});
}
if (modeDirect) {
modeDirect.addEventListener("change", () => {
chrome.storage.sync.set({ uploadMode: "direct" }, () => {
updateModeUI("direct");
});
});
}
if (btnSaveApiConfig) {
btnSaveApiConfig.addEventListener("click", () => {
const rawUrl = popupApiUrl ? popupApiUrl.value.trim() : "";
const key = popupApiKey ? popupApiKey.value.trim() : "";
const normUrl = normalizeApiUrl(rawUrl);
if (popupApiUrl && normUrl) popupApiUrl.value = normUrl;
chrome.storage.sync.set({ apiUrl: normUrl || rawUrl, apiKey: key }, () => {
if (popupApiToast) {
popupApiToast.textContent = "Saved!";
popupApiToast.style.color = "#00e676";
setTimeout(() => { popupApiToast.textContent = ""; }, 2000);
}
});
});
}
if (btnPopupTest) {
btnPopupTest.addEventListener("click", () => {
const url = popupApiUrl ? popupApiUrl.value.trim() : "";
const key = popupApiKey ? popupApiKey.value.trim() : "";
if (!url || !key) {
if (popupApiToast) {
popupApiToast.textContent = "Enter URL & Key!";
popupApiToast.style.color = "#ff4444";
}
return;
}
btnPopupTest.disabled = true;
if (popupApiToast) {
popupApiToast.textContent = "Testing...";
popupApiToast.style.color = "#4da6ff";
}
chrome.runtime.sendMessage({ action: "test_connection", apiUrl: url, apiKey: key }, (res) => {
btnPopupTest.disabled = false;
if (popupApiToast) {
if (res && res.success) {
popupApiToast.textContent = "✓ OK!";
popupApiToast.style.color = "#00e676";
} else {
popupApiToast.textContent = "❌ " + (res ? res.msg : "Failed");
popupApiToast.style.color = "#ff4444";
}
}
});
});
}
// 2. Query Tab Info immediately
try {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs && tabs[0]) {
populateTabInfo(tabs[0]);
} else {
chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs2) => {
if (tabs2 && tabs2[0]) {
populateTabInfo(tabs2[0]);
}
});
}
});
} catch (e) {}
function populateTabInfo(tab) {
if (!tab) return;
activeTabUrl = tab.url || tab.pendingUrl || "";
if (tabTitle) tabTitle.textContent = tab.title || "Active Page";
if (tabUrlPreview) tabUrlPreview.textContent = activeTabUrl || "No URL available";
const isYouTube = activeTabUrl.includes("youtube.com") || activeTabUrl.includes("youtu.be");
if (isYouTube) {
if (siteBadge) {
siteBadge.textContent = "▶ YouTube";
siteBadge.classList.add("youtube");
}
if (btnUploadText) btnUploadText.textContent = "Upload YouTube Video to f0ckm";
if (btnUploadTab) btnUploadTab.classList.add("youtube-style");
} else {
if (siteBadge) {
siteBadge.textContent = "🌐 Web Page";
siteBadge.classList.remove("youtube");
}
if (btnUploadText) btnUploadText.textContent = "Upload Page URL to f0ckm";
if (btnUploadTab) btnUploadTab.classList.remove("youtube-style");
}
}
// 3. Upload Active Tab Button Click Handler
if (btnUploadTab) {
btnUploadTab.addEventListener("click", () => {
if (activeTabUrl && (activeTabUrl.startsWith("http://") || activeTabUrl.startsWith("https://"))) {
triggerUpload(activeTabUrl);
} else {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const tab = tabs ? tabs[0] : null;
const url = tab ? (tab.url || tab.pendingUrl) : "";
if (url && (url.startsWith("http://") || url.startsWith("https://"))) {
activeTabUrl = url;
triggerUpload(url);
} else {
showStatus("Could not get active tab URL.", false);
}
});
}
});
}
// 4. Custom pasted URL Upload Button Click Handler
if (btnUploadUrl) {
btnUploadUrl.addEventListener("click", () => {
const url = urlInput ? urlInput.value.trim() : "";
if (url) {
triggerUpload(url);
} else {
showStatus("Please enter a valid URL.", false);
}
});
}
if (urlInput) {
urlInput.addEventListener("keydown", (e) => {
if (e.key === "Enter" && btnUploadUrl) {
btnUploadUrl.click();
}
});
}
if (btnCopyResult) {
btnCopyResult.addEventListener("click", () => {
const linkUrl = resultLink ? resultLink.href : "";
if (linkUrl && linkUrl !== "#" && !linkUrl.endsWith("#")) {
navigator.clipboard.writeText(linkUrl);
btnCopyResult.textContent = "Copied!";
setTimeout(() => {
btnCopyResult.textContent = "Copy Link";
}, 1500);
}
});
}
function showStatus(text, loading = false) {
if (!statusCard) return;
statusCard.classList.remove("hidden");
if (statusText) statusText.textContent = text;
if (loading) {
if (statusSpinner) statusSpinner.classList.remove("hidden");
if (resultContainer) resultContainer.classList.add("hidden");
} else {
if (statusSpinner) statusSpinner.classList.add("hidden");
}
}
function showSuccessResult(finalUrl) {
if (!statusCard) return;
statusCard.classList.remove("hidden");
if (statusSpinner) statusSpinner.classList.add("hidden");
if (statusText) statusText.textContent = "Upload Successful! Click link to open:";
if (resultLink) {
resultLink.href = finalUrl;
resultLink.textContent = finalUrl;
}
if (resultContainer) resultContainer.classList.remove("hidden");
}
function triggerUpload(url) {
const currentMode = (modeDirect && modeDirect.checked) ? "direct" : "desktop";
if (currentMode === "desktop") {
showStatus("Sending URL to f0ckm desktop app...", true);
chrome.runtime.sendMessage({ action: "upload_url", url: url }, () => {
showStatus("URL sent to f0ckm app! Check system tray / notifications.", false);
});
} else {
showStatus("Sending URL to f0ckm API...", true);
chrome.runtime.sendMessage({ action: "upload_url", url: url }, (response) => {
if (response && response.resultUrl) {
showSuccessResult(response.resultUrl);
} else {
showStatus("Upload failed or queued. Check notification / settings.", false);
}
});
}
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initPopup);
} else {
initPopup();
}