Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"manifest_version": 3,
"version": "0.2.0",
"version": "0.2.1",
"name": "Django Files",
"description": "Django Files Web Extension",
"homepage_url": "https://github.com/django-files/web-extension",
Expand Down
1 change: 1 addition & 0 deletions src/css/popup.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
body {
width: 360px;
overflow-x: hidden;
}

a {
Expand Down
28 changes: 20 additions & 8 deletions src/html/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<title>Django Files Options</title>
<link rel="icon" href="../images/logo16.png" sizes="any">
<link rel="stylesheet" type="text/css" href="../dist/bootstrap/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../dist/fontawesome/js/all.min.js">
<link rel="stylesheet" type="text/css" href="../css/options.css">
</head>
<body class="h-100">
Expand All @@ -12,13 +13,13 @@
<source src="../images/loop.webm" type="video/webm">
</video>

<div class="container-fluid p-3 h-100">
<div class="container-fluid p-2 h-100">
<div class="d-flex align-items-center h-100">
<div class="col-md-6 col-12 m-auto">
<div class="card p-3" >
<div class="card p-2 mb-3" >
<h1 class="text-center">Django Files Extension</h1>
<img src="../images/logo96.png" class="img-fluid m-auto d-block my-1" alt="Django Files" height="96" width="96">
<div class="card-body">
<h1 class="text-center">Django Files Extension</h1>
<img src="../images/logo96.png" class="img-fluid m-auto d-block my-3" alt="Django Files" height="96" width="96">
<table class="table table-sm table-borderless">
<caption class="visually-hidden">Keyboard Shortcuts</caption>
<thead class="visually-hidden"><tr><th>Description</th><th>Shortcut</th></tr></thead>
Expand All @@ -28,21 +29,27 @@ <h1 class="text-center">Django Files Extension</h1>
</tr></tbody>
</table>
<form id="options-form">
<div class="mb-3">
<div class="mb-2">
<label for="url" class="form-label">Django Files URL</label>
<input type="text" class="form-control" id="url" aria-describedby="urlHelp" autocomplete="off">
<div id="urlHelp" class="form-text">The Full URL to your Django Files server.</div>
</div>
<div class="mb-3">
<div class="mb-2">
<label for="token" class="form-label">Auth Token</label>
<input type="password" class="form-control" id="token" aria-describedby="tokenHelp" autocomplete="off">
<div id="tokenHelp" class="form-text">Token From Django Files Settings.</div>
</div>
<div class="form-check form-switch mb-3">
<div class="mb-2">
<label for="recentFiles" class="form-label">Recent Files</label>
<input type="number" class="form-control" id="recentFiles" aria-describedby="recentFilesHelp" autocomplete="off">
<div id="recentFilesHelp" class="form-text">Number of Recent Files in Popup.</div>
</div>
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" role="switch" id="contextMenu">
<label class="form-check-label" for="contextMenu" aria-describedby="contextMenuHelp">Enable Right Click Menu</label>
</div>
<button id="submit" type="submit" class="btn btn-outline-success w-100">Save Settings</button>
<button id="submit" type="submit" class="btn btn-outline-success w-100">
Save Options <i class="fa-regular fa-floppy-disk ms-2"></i></button>
</form>
</div>
<div class="text-center">
Expand All @@ -57,9 +64,14 @@ <h1 class="text-center">Django Files Extension</h1>
</div>
</div>

<div id="bottom-container" class="position-fixed bottom-0 end-0">
<div id="toast-container" class=""></div>
</div>

<script type="text/javascript" src="../dist/polyfill/browser-polyfill.min.js"></script>
<script type="text/javascript" src="../dist/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../dist/bootstrap/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="../dist/fontawesome/js/all.min.js"></script>
<script type="text/javascript" src="../dist/clipboard/clipboard.min.js"></script>
<script type="module" src="../js/options.js"></script>

Expand Down
13 changes: 6 additions & 7 deletions src/html/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<title>Django Files Popup</title>
<link rel="icon" href="../images/logo16.png" sizes="any">
<link rel="stylesheet" type="text/css" href="../dist/bootstrap/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../dist/fontawesome/js/all.min.js">
<link rel="stylesheet" type="text/css" href="../css/popup.css">
<script type="text/javascript" src="../js/theme.js"></script>
</head>
Expand All @@ -17,15 +18,12 @@ <h2>Django Files Extension</h2>
<div class="d-grid g-2">
<div id="django-files-links" class="btn-group btn-group-sm" role="group" aria-label="Django Files Links" style="display: none;">
<button type="button" class="btn btn-outline-success" data-href="" data-location="/files/">
Files</button>
<i class="fa-regular fa-folder-open me-2"></i> Files</button>
<button type="button" class="btn btn-outline-success" data-href="" data-location="/gallery/">
Gallery</button>
<!-- <button type="button" class="btn btn-outline-primary" data-href="../html/options.html">-->
<!-- Options</button>-->
<i class="fa-regular fa-images me-2"></i> Gallery</button>
</div>

<a class="btn btn-outline-primary btn-sm my-1" role="button" target="_blank" data-href="../html/options.html">Open Options</a>

<a class="btn btn-outline-primary btn-sm my-1" role="button" target="_blank" data-href="../html/options.html">
<i class="fa-solid fa-gear me-2"></i> Open Options</a>
</div>
<p class="mb-0">Recent Uploads:</p>
<table id="recent" class="table table-striped table-sm mb-0 ">
Expand All @@ -39,6 +37,7 @@ <h2>Django Files Extension</h2>
<script type="text/javascript" src="../dist/polyfill/browser-polyfill.min.js"></script>
<script type="text/javascript" src="../dist/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../dist/bootstrap/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="../dist/fontawesome/js/all.min.js"></script>
<script type="text/javascript" src="../dist/clipboard/clipboard.min.js"></script>
<script type="text/javascript" src="../js/popup.js"></script>

Expand Down
8 changes: 4 additions & 4 deletions src/js/exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ export function createContextMenus() {
console.log('createContextMenus')
const contexts = [
[['link'], 'short', 'Create Short URL'],
[['image'], 'upload', 'Upload to Django Files'],
[['video'], 'upload', 'Upload to Django Files'],
[['audio'], 'upload', 'Upload to Django Files'],
[['image'], 'upload-image', 'Upload Image'],
[['video'], 'upload-video', 'Upload Video'],
[['audio'], 'upload-audio', 'Upload Audio'],
[['link', 'image', 'video', 'audio'], 'separator', 'separator-1'],
[['link', 'image', 'video', 'audio'], 'options', 'Open Options'],
]
for (const context of contexts) {
if (context[1].includes('separator')) {
if (context[1].startsWith('separator')) {
chrome.contextMenus.create({
type: context[1],
contexts: context[0],
Expand Down
28 changes: 28 additions & 0 deletions src/js/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ async function initOptions() {
const commands = await chrome.commands.getAll()
document.getElementById('mainKey').textContent =
commands.find((x) => x.name === '_execute_action').shortcut || 'Not Set'
document.getElementById('recentFiles').value = options?.recentFiles || '10'
}

/**
Expand All @@ -42,13 +43,40 @@ async function saveOptions(event) {
}
console.log('auth:', auth)
let options = {}
options.recentFiles = document.getElementById('recentFiles').value
options.contextMenu = document.getElementById('contextMenu').checked
if (options.contextMenu) {
chrome.contextMenus.removeAll()
createContextMenus()
} else {
chrome.contextMenus.removeAll()
}
console.log('options:', options)
await chrome.storage.sync.set({ auth, options })
document.getElementById('url').value = auth.url
showToast('Options Saved')
}

/**
* Show Bootstrap Toast
* Requires: jQuery
* @function showToast
* @param {String} message
* @param {String} bsClass
*/
function showToast(message, bsClass = 'success') {
// TODO: Remove jQuery Dependency
const toastEl = $(
'<div class="toast align-items-center border-0 my-3" role="alert" aria-live="assertive" aria-atomic="true">\n' +
' <div class="d-flex">\n' +
' <div class="toast-body">Options Saved</div>\n' +
' <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>\n' +
' </div>\n' +
'</div>'
)
toastEl.find('.toast-body').text(message)
toastEl.addClass('text-bg-' + bsClass)
$('#toast-container').append(toastEl)
const toast = new bootstrap.Toast(toastEl) // eslint-disable-line
toast.show()
}
109 changes: 68 additions & 41 deletions src/js/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,31 @@ document.querySelectorAll('[data-href]').forEach((el) => {
el.addEventListener('click', popupLink)
})

/**
* Popup Links Callback
* because firefox needs us to call window.close() from the popup
* @function popupLink
* @param {MouseEvent} event
*/
async function popupLink(event) {
console.log('popupLink:', event)
const { auth } = await chrome.storage.sync.get(['auth'])
let url
if (event.target.dataset.location) {
url = auth?.url + event.target.dataset.location
} else if (event.target.dataset.href.startsWith('http')) {
url = event.target.dataset.href
} else {
url = chrome.runtime.getURL(event.target.dataset.href)
}
console.log(`url: ${url}`)
await chrome.tabs.create({ active: true, url })
window.close()
}

/**
* Popup Init Function
* TODO: Overhaul this function
* @function initPopup
*/
async function initPopup() {
console.log('initPopup')
const { auth } = await chrome.storage.sync.get(['auth'])
const { auth, options } = await chrome.storage.sync.get(['auth', 'options'])
console.log('auth:', auth)
if (!auth?.url || !auth?.token) {
return displayError('Missing URL or Token.')
}
document.getElementById('django-files-links').style.display = 'flex'

let headers = { Authorization: auth.token }
let options = { method: 'GET', headers: headers, cache: 'no-cache' }
let opts = {
method: 'GET',
headers: { Authorization: auth.token },
cache: 'no-cache',
}
let response
let data
try {
response = await fetch(auth.url + '/api/recent/', options)
const url = new URL(auth.url + '/api/recent/')
url.searchParams.append('amount', options?.recentFiles || '10')
response = await fetch(url, opts)
data = await response.json()
} catch (error) {
console.warn(error)
Expand All @@ -66,36 +49,80 @@ async function initPopup() {
return displayError('No Files Returned.')
}

updateTable(data)
const clipboard = new ClipboardJS('.clip') // eslint-disable-line
document.querySelectorAll('[data-href]').forEach((el) => {
el.addEventListener('click', popupLink)
})
}

/**
* Popup Links Callback
* because firefox needs us to call window.close() from the popup
* @function popupLink
* @param {MouseEvent} event
*/
async function popupLink(event) {
console.log('popupLink:', event)
const { auth } = await chrome.storage.sync.get(['auth'])
let url
if (event.target.dataset.location) {
url = auth?.url + event.target.dataset.location
} else if (event.target.dataset.href.startsWith('http')) {
url = event.target.dataset.href
} else {
url = chrome.runtime.getURL(event.target.dataset.href)
}
console.log(`url: ${url}`)
await chrome.tabs.create({ active: true, url })
window.close()
}

/**
* Update Popup Table with Data
* @function updateTable
* @param {Object} data
*/
function updateTable(data) {
let tbodyRef = document
.getElementById('recent')
.getElementsByTagName('tbody')[0]

data.forEach(function (value, i) {
let name = String(value.split('/').reverse()[0])
const name = String(value.split('/').reverse()[0])
const row = tbodyRef.insertRow()

let copyLink = document.createTextNode(i + 1)
// let copyLink = document.createElement('a')
// copyLink.text = 1 + i
// copyLink.title = name
// copyLink.href = value
// copyLink.target = '_blank'
const copyLink = document.createTextNode(i + 1)
const cell1 = row.insertCell()
cell1.appendChild(copyLink)

let fileLink = document.createElement('a')
const fileLink = document.createElement('a')
fileLink.text = name
fileLink.title = name
fileLink.href = value
fileLink.dataset.href = value
fileLink.setAttribute('role', 'button')
fileLink.classList.add(
'link-underline',
'link-underline-opacity-0',
'link-underline-opacity-75-hover'
)
fileLink.target = '_blank'

let row = tbodyRef.insertRow()
let cell1 = row.insertCell()
cell1.appendChild(copyLink)
let cell2 = row.insertCell()
const cell2 = row.insertCell()
cell2.appendChild(fileLink)

const copyBtn = document.createElement('a')
copyBtn.title = 'Copy'
copyBtn.setAttribute('role', 'button')
copyBtn.classList.add('clip')
copyBtn.dataset.clipboardText = value
copyBtn.innerHTML = '<i class="fa-regular fa-clipboard text-white"></i>'
const cell3 = row.insertCell()
cell3.appendChild(copyBtn)
})
}

/**
* Popup Action Init
* Display Popup Error Message
* @function displayError
* @param {String} message
*/
Expand Down
8 changes: 4 additions & 4 deletions src/js/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ chrome.notifications.onClicked.addListener((notificationId) => {
export async function onInstalled() {
console.log('onInstalled')
let { options } = await chrome.storage.sync.get(['options'])
options = options || { contextMenu: true }
options = options || { contextMenu: true, recentFiles: '10' }
console.log('options:', options)
await chrome.storage.sync.set({ options })
if (options.contextMenu) {
Expand All @@ -34,7 +34,7 @@ export async function onInstalled() {
async function contextMenuClick(ctx) {
console.log('contextMenuClick:', ctx)
console.log(`ctx.menuItemId: ${ctx.menuItemId}`)
if (ctx.menuItemId === 'upload') {
if (ctx.menuItemId.startsWith('upload')) {
if (ctx.srcUrl) {
let mediaType =
ctx.menuItemId.charAt(0).toUpperCase() + ctx.menuItemId.slice(1)
Expand Down Expand Up @@ -101,8 +101,8 @@ async function processRemote(endpoint, url, message) {
* @function sendNotification
* @param {String} title
* @param {String} text
* @param {String} id
* @param {Number} timeout
* @param {String} id - Optional
* @param {Number} timeout - Optional
*/
async function sendNotification(title, text, id = '', timeout = 10) {
console.log(`sendNotification: ${id || 'randomID'}: ${title} - ${text}`)
Expand Down