mirror of
https://github.com/Dvorinka/Trackeep.git
synced 2026-06-03 12:03:00 +00:00
285 lines
8.0 KiB
JavaScript
285 lines
8.0 KiB
JavaScript
/* global chrome */
|
|
|
|
const statusEl = document.getElementById('status');
|
|
const configHintEl = document.getElementById('configHint');
|
|
const openOptionsBtn = document.getElementById('openOptions');
|
|
|
|
const bookmarkTitleInput = document.getElementById('bookmarkTitle');
|
|
const bookmarkUrlInput = document.getElementById('bookmarkUrl');
|
|
const bookmarkDescriptionInput = document.getElementById('bookmarkDescription');
|
|
const bookmarkTagsInput = document.getElementById('bookmarkTags');
|
|
const bookmarkPublicInput = document.getElementById('bookmarkPublic');
|
|
const saveBookmarkBtn = document.getElementById('saveBookmarkBtn');
|
|
|
|
const fileInput = document.getElementById('fileInput');
|
|
const fileDescriptionInput = document.getElementById('fileDescription');
|
|
const uploadFileBtn = document.getElementById('uploadFileBtn');
|
|
|
|
let trackeepConfig = {
|
|
apiBaseUrl: '',
|
|
authToken: ''
|
|
};
|
|
|
|
function setStatus(message, type) {
|
|
statusEl.textContent = message || '';
|
|
statusEl.classList.remove('error', 'success');
|
|
if (type) {
|
|
statusEl.classList.add(type);
|
|
}
|
|
}
|
|
|
|
function disableForms(disabled) {
|
|
[bookmarkTitleInput, bookmarkUrlInput, bookmarkDescriptionInput, bookmarkTagsInput, bookmarkPublicInput, saveBookmarkBtn,
|
|
fileInput, fileDescriptionInput, uploadFileBtn].forEach((el) => {
|
|
if (!el) return;
|
|
el.disabled = disabled;
|
|
});
|
|
}
|
|
|
|
function loadConfig(callback) {
|
|
chrome.storage.sync.get(['trackeepApiBaseUrl', 'trackeepAuthToken'], (items) => {
|
|
const apiBaseUrl = (items.trackeepApiBaseUrl || '').trim();
|
|
const authToken = (items.trackeepAuthToken || '').trim();
|
|
|
|
trackeepConfig = { apiBaseUrl, authToken };
|
|
|
|
if (!apiBaseUrl || !authToken) {
|
|
configHintEl.textContent = 'Configure API URL and token in Options to enable saving.';
|
|
disableForms(true);
|
|
} else {
|
|
configHintEl.textContent = `Using API: ${apiBaseUrl}`;
|
|
disableForms(false);
|
|
}
|
|
|
|
if (typeof callback === 'function') {
|
|
callback();
|
|
}
|
|
});
|
|
}
|
|
|
|
function detectTrackeepDomain(callback) {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
const tab = tabs && tabs[0];
|
|
if (!tab || !tab.url) {
|
|
if (callback) callback();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const url = new URL(tab.url);
|
|
// Common Trackeep domains: localhost, trackeep.*, etc.
|
|
const isTrackeepDomain = url.hostname.includes('trackeep') || url.hostname === 'localhost';
|
|
if (isTrackeepDomain && url.protocol === 'https:') {
|
|
const candidate = `${url.origin}/api/v1`;
|
|
// Only pre-fill if not already set
|
|
chrome.storage.sync.get(['trackeepApiBaseUrl'], (items) => {
|
|
if (!items.trackeepApiBaseUrl) {
|
|
chrome.storage.sync.set({ trackeepApiBaseUrl: candidate }, () => {
|
|
console.log('Auto-detected Trackeep API URL:', candidate);
|
|
if (callback) callback();
|
|
});
|
|
} else {
|
|
if (callback) callback();
|
|
}
|
|
});
|
|
} else {
|
|
if (callback) callback();
|
|
}
|
|
} catch (e) {
|
|
if (callback) callback();
|
|
}
|
|
});
|
|
}
|
|
|
|
function initActiveTab() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
const tab = tabs && tabs[0];
|
|
if (!tab) return;
|
|
|
|
// Check for context menu data first
|
|
chrome.storage.local.get(['contextMenuData'], (items) => {
|
|
const ctx = items.contextMenuData;
|
|
if (ctx && ctx.timestamp && Date.now() - ctx.timestamp < 5000) {
|
|
// Use context menu data if recent
|
|
if (ctx.url && !bookmarkUrlInput.value) {
|
|
bookmarkUrlInput.value = ctx.url;
|
|
}
|
|
if (ctx.title && !bookmarkTitleInput.value) {
|
|
bookmarkTitleInput.value = ctx.title;
|
|
}
|
|
if (ctx.selection && !bookmarkDescriptionInput.value) {
|
|
bookmarkDescriptionInput.value = ctx.selection;
|
|
}
|
|
// Clear after using
|
|
chrome.storage.local.remove(['contextMenuData']);
|
|
} else {
|
|
// Fallback to active tab
|
|
if (tab.title && !bookmarkTitleInput.value) {
|
|
bookmarkTitleInput.value = tab.title;
|
|
}
|
|
if (tab.url && !bookmarkUrlInput.value) {
|
|
bookmarkUrlInput.value = tab.url;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async function saveBookmark(event) {
|
|
event.preventDefault();
|
|
setStatus('', null);
|
|
|
|
const { apiBaseUrl, authToken } = trackeepConfig;
|
|
if (!apiBaseUrl || !authToken) {
|
|
setStatus('Missing API URL or auth token. Open options first.', 'error');
|
|
return;
|
|
}
|
|
|
|
const url = bookmarkUrlInput.value.trim();
|
|
if (!url) {
|
|
setStatus('URL is required.', 'error');
|
|
return;
|
|
}
|
|
|
|
const title = bookmarkTitleInput.value.trim() || url;
|
|
const description = bookmarkDescriptionInput.value.trim();
|
|
const tagsRaw = bookmarkTagsInput.value.trim();
|
|
const isPublic = !!bookmarkPublicInput.checked;
|
|
|
|
const tags = tagsRaw
|
|
? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean)
|
|
: [];
|
|
|
|
const payload = {
|
|
title,
|
|
url,
|
|
description,
|
|
tags,
|
|
is_public: isPublic
|
|
};
|
|
|
|
saveBookmarkBtn.disabled = true;
|
|
setStatus('Saving bookmark…', null);
|
|
|
|
try {
|
|
const base = apiBaseUrl.replace(/\/$/, '');
|
|
const response = await fetch(`${base}/bookmarks`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${authToken}`
|
|
},
|
|
body: JSON.stringify(payload)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
let errorMessage = `Failed to save bookmark (status ${response.status})`;
|
|
try {
|
|
const data = await response.json();
|
|
if (data && data.error) {
|
|
errorMessage = data.error;
|
|
}
|
|
} catch (_) {
|
|
// ignore JSON parse errors
|
|
}
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
setStatus('Bookmark saved to Trackeep.', 'success');
|
|
} catch (err) {
|
|
console.error('Error saving bookmark', err);
|
|
setStatus(err && err.message ? err.message : 'Failed to save bookmark.', 'error');
|
|
} finally {
|
|
saveBookmarkBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
async function uploadFile(event) {
|
|
event.preventDefault();
|
|
setStatus('', null);
|
|
|
|
const { apiBaseUrl, authToken } = trackeepConfig;
|
|
if (!apiBaseUrl || !authToken) {
|
|
setStatus('Missing API URL or auth token. Open options first.', 'error');
|
|
return;
|
|
}
|
|
|
|
const file = fileInput.files && fileInput.files[0];
|
|
if (!file) {
|
|
setStatus('Please choose a file to upload.', 'error');
|
|
return;
|
|
}
|
|
|
|
const description = fileDescriptionInput.value.trim();
|
|
|
|
const formData = new FormData();
|
|
formData.append('file', file, file.name);
|
|
if (description) {
|
|
formData.append('description', description);
|
|
}
|
|
|
|
uploadFileBtn.disabled = true;
|
|
setStatus('Uploading file…', null);
|
|
|
|
try {
|
|
const base = apiBaseUrl.replace(/\/$/, '');
|
|
const response = await fetch(`${base}/files/upload`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${authToken}`
|
|
},
|
|
body: formData
|
|
});
|
|
|
|
if (!response.ok) {
|
|
let errorMessage = `Failed to upload file (status ${response.status})`;
|
|
try {
|
|
const data = await response.json();
|
|
if (data && data.error) {
|
|
errorMessage = data.error;
|
|
}
|
|
} catch (_) {
|
|
// ignore JSON parse errors
|
|
}
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
setStatus('File uploaded to Trackeep.', 'success');
|
|
fileInput.value = '';
|
|
fileDescriptionInput.value = '';
|
|
} catch (err) {
|
|
console.error('Error uploading file', err);
|
|
setStatus(err && err.message ? err.message : 'Failed to upload file.', 'error');
|
|
} finally {
|
|
uploadFileBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
function openOptions() {
|
|
if (chrome.runtime.openOptionsPage) {
|
|
chrome.runtime.openOptionsPage();
|
|
} else {
|
|
window.open(chrome.runtime.getURL('options.html'));
|
|
}
|
|
}
|
|
|
|
// Init
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
openOptionsBtn.addEventListener('click', openOptions);
|
|
saveBookmarkBtn.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
saveBookmark(e);
|
|
});
|
|
uploadFileBtn.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
uploadFile(e);
|
|
});
|
|
|
|
detectTrackeepDomain(() => {
|
|
loadConfig(() => {
|
|
initActiveTab();
|
|
});
|
|
});
|
|
});
|