Skip to content

Commit 48c676a

Browse files
authored
Fixes and Updates (#8)
* Fixes and Updates * Bump Version * Cleanup
1 parent ecc4423 commit 48c676a

File tree

8 files changed

+132
-65
lines changed

8 files changed

+132
-65
lines changed

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"manifest_version": 3,
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"name": "Django Files",
55
"description": "Django Files Web Extension",
66
"homepage_url": "https://github.com/django-files/web-extension",

src/css/popup.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
body {
22
width: 360px;
3+
overflow-x: hidden;
34
}
45

56
a {

src/html/options.html

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<title>Django Files Options</title>
55
<link rel="icon" href="../images/logo16.png" sizes="any">
66
<link rel="stylesheet" type="text/css" href="../dist/bootstrap/bootstrap.min.css">
7+
<link rel="stylesheet" type="text/css" href="../dist/fontawesome/js/all.min.js">
78
<link rel="stylesheet" type="text/css" href="../css/options.css">
89
</head>
910
<body class="h-100">
@@ -12,13 +13,13 @@
1213
<source src="../images/loop.webm" type="video/webm">
1314
</video>
1415

15-
<div class="container-fluid p-3 h-100">
16+
<div class="container-fluid p-2 h-100">
1617
<div class="d-flex align-items-center h-100">
1718
<div class="col-md-6 col-12 m-auto">
18-
<div class="card p-3" >
19+
<div class="card p-2 mb-3" >
20+
<h1 class="text-center">Django Files Extension</h1>
21+
<img src="../images/logo96.png" class="img-fluid m-auto d-block my-1" alt="Django Files" height="96" width="96">
1922
<div class="card-body">
20-
<h1 class="text-center">Django Files Extension</h1>
21-
<img src="../images/logo96.png" class="img-fluid m-auto d-block my-3" alt="Django Files" height="96" width="96">
2223
<table class="table table-sm table-borderless">
2324
<caption class="visually-hidden">Keyboard Shortcuts</caption>
2425
<thead class="visually-hidden"><tr><th>Description</th><th>Shortcut</th></tr></thead>
@@ -28,21 +29,27 @@ <h1 class="text-center">Django Files Extension</h1>
2829
</tr></tbody>
2930
</table>
3031
<form id="options-form">
31-
<div class="mb-3">
32+
<div class="mb-2">
3233
<label for="url" class="form-label">Django Files URL</label>
3334
<input type="text" class="form-control" id="url" aria-describedby="urlHelp" autocomplete="off">
3435
<div id="urlHelp" class="form-text">The Full URL to your Django Files server.</div>
3536
</div>
36-
<div class="mb-3">
37+
<div class="mb-2">
3738
<label for="token" class="form-label">Auth Token</label>
3839
<input type="password" class="form-control" id="token" aria-describedby="tokenHelp" autocomplete="off">
3940
<div id="tokenHelp" class="form-text">Token From Django Files Settings.</div>
4041
</div>
41-
<div class="form-check form-switch mb-3">
42+
<div class="mb-2">
43+
<label for="recentFiles" class="form-label">Recent Files</label>
44+
<input type="number" class="form-control" id="recentFiles" aria-describedby="recentFilesHelp" autocomplete="off">
45+
<div id="recentFilesHelp" class="form-text">Number of Recent Files in Popup.</div>
46+
</div>
47+
<div class="form-check form-switch mb-2">
4248
<input class="form-check-input" type="checkbox" role="switch" id="contextMenu">
4349
<label class="form-check-label" for="contextMenu" aria-describedby="contextMenuHelp">Enable Right Click Menu</label>
4450
</div>
45-
<button id="submit" type="submit" class="btn btn-outline-success w-100">Save Settings</button>
51+
<button id="submit" type="submit" class="btn btn-outline-success w-100">
52+
Save Options <i class="fa-regular fa-floppy-disk ms-2"></i></button>
4653
</form>
4754
</div>
4855
<div class="text-center">
@@ -57,9 +64,14 @@ <h1 class="text-center">Django Files Extension</h1>
5764
</div>
5865
</div>
5966

67+
<div id="bottom-container" class="position-fixed bottom-0 end-0">
68+
<div id="toast-container" class=""></div>
69+
</div>
70+
6071
<script type="text/javascript" src="../dist/polyfill/browser-polyfill.min.js"></script>
6172
<script type="text/javascript" src="../dist/jquery/jquery.min.js"></script>
6273
<script type="text/javascript" src="../dist/bootstrap/bootstrap.bundle.min.js"></script>
74+
<script type="text/javascript" src="../dist/fontawesome/js/all.min.js"></script>
6375
<script type="text/javascript" src="../dist/clipboard/clipboard.min.js"></script>
6476
<script type="module" src="../js/options.js"></script>
6577

src/html/popup.html

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<title>Django Files Popup</title>
55
<link rel="icon" href="../images/logo16.png" sizes="any">
66
<link rel="stylesheet" type="text/css" href="../dist/bootstrap/bootstrap.min.css">
7+
<link rel="stylesheet" type="text/css" href="../dist/fontawesome/js/all.min.js">
78
<link rel="stylesheet" type="text/css" href="../css/popup.css">
89
<script type="text/javascript" src="../js/theme.js"></script>
910
</head>
@@ -17,15 +18,12 @@ <h2>Django Files Extension</h2>
1718
<div class="d-grid g-2">
1819
<div id="django-files-links" class="btn-group btn-group-sm" role="group" aria-label="Django Files Links" style="display: none;">
1920
<button type="button" class="btn btn-outline-success" data-href="" data-location="/files/">
20-
Files</button>
21+
<i class="fa-regular fa-folder-open me-2"></i> Files</button>
2122
<button type="button" class="btn btn-outline-success" data-href="" data-location="/gallery/">
22-
Gallery</button>
23-
<!-- <button type="button" class="btn btn-outline-primary" data-href="../html/options.html">-->
24-
<!-- Options</button>-->
23+
<i class="fa-regular fa-images me-2"></i> Gallery</button>
2524
</div>
26-
27-
<a class="btn btn-outline-primary btn-sm my-1" role="button" target="_blank" data-href="../html/options.html">Open Options</a>
28-
25+
<a class="btn btn-outline-primary btn-sm my-1" role="button" target="_blank" data-href="../html/options.html">
26+
<i class="fa-solid fa-gear me-2"></i> Open Options</a>
2927
</div>
3028
<p class="mb-0">Recent Uploads:</p>
3129
<table id="recent" class="table table-striped table-sm mb-0 ">
@@ -39,6 +37,7 @@ <h2>Django Files Extension</h2>
3937
<script type="text/javascript" src="../dist/polyfill/browser-polyfill.min.js"></script>
4038
<script type="text/javascript" src="../dist/jquery/jquery.min.js"></script>
4139
<script type="text/javascript" src="../dist/bootstrap/bootstrap.bundle.min.js"></script>
40+
<script type="text/javascript" src="../dist/fontawesome/js/all.min.js"></script>
4241
<script type="text/javascript" src="../dist/clipboard/clipboard.min.js"></script>
4342
<script type="text/javascript" src="../js/popup.js"></script>
4443

src/js/exports.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ export function createContextMenus() {
88
console.log('createContextMenus')
99
const contexts = [
1010
[['link'], 'short', 'Create Short URL'],
11-
[['image'], 'upload', 'Upload to Django Files'],
12-
[['video'], 'upload', 'Upload to Django Files'],
13-
[['audio'], 'upload', 'Upload to Django Files'],
11+
[['image'], 'upload-image', 'Upload Image'],
12+
[['video'], 'upload-video', 'Upload Video'],
13+
[['audio'], 'upload-audio', 'Upload Audio'],
1414
[['link', 'image', 'video', 'audio'], 'separator', 'separator-1'],
1515
[['link', 'image', 'video', 'audio'], 'options', 'Open Options'],
1616
]
1717
for (const context of contexts) {
18-
if (context[1].includes('separator')) {
18+
if (context[1].startsWith('separator')) {
1919
chrome.contextMenus.create({
2020
type: context[1],
2121
contexts: context[0],

src/js/options.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ async function initOptions() {
2626
const commands = await chrome.commands.getAll()
2727
document.getElementById('mainKey').textContent =
2828
commands.find((x) => x.name === '_execute_action').shortcut || 'Not Set'
29+
document.getElementById('recentFiles').value = options?.recentFiles || '10'
2930
}
3031

3132
/**
@@ -42,13 +43,40 @@ async function saveOptions(event) {
4243
}
4344
console.log('auth:', auth)
4445
let options = {}
46+
options.recentFiles = document.getElementById('recentFiles').value
4547
options.contextMenu = document.getElementById('contextMenu').checked
4648
if (options.contextMenu) {
49+
chrome.contextMenus.removeAll()
4750
createContextMenus()
4851
} else {
4952
chrome.contextMenus.removeAll()
5053
}
5154
console.log('options:', options)
5255
await chrome.storage.sync.set({ auth, options })
5356
document.getElementById('url').value = auth.url
57+
showToast('Options Saved')
58+
}
59+
60+
/**
61+
* Show Bootstrap Toast
62+
* Requires: jQuery
63+
* @function showToast
64+
* @param {String} message
65+
* @param {String} bsClass
66+
*/
67+
function showToast(message, bsClass = 'success') {
68+
// TODO: Remove jQuery Dependency
69+
const toastEl = $(
70+
'<div class="toast align-items-center border-0 my-3" role="alert" aria-live="assertive" aria-atomic="true">\n' +
71+
' <div class="d-flex">\n' +
72+
' <div class="toast-body">Options Saved</div>\n' +
73+
' <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>\n' +
74+
' </div>\n' +
75+
'</div>'
76+
)
77+
toastEl.find('.toast-body').text(message)
78+
toastEl.addClass('text-bg-' + bsClass)
79+
$('#toast-container').append(toastEl)
80+
const toast = new bootstrap.Toast(toastEl) // eslint-disable-line
81+
toast.show()
5482
}

src/js/popup.js

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,31 @@ document.querySelectorAll('[data-href]').forEach((el) => {
66
el.addEventListener('click', popupLink)
77
})
88

9-
/**
10-
* Popup Links Callback
11-
* because firefox needs us to call window.close() from the popup
12-
* @function popupLink
13-
* @param {MouseEvent} event
14-
*/
15-
async function popupLink(event) {
16-
console.log('popupLink:', event)
17-
const { auth } = await chrome.storage.sync.get(['auth'])
18-
let url
19-
if (event.target.dataset.location) {
20-
url = auth?.url + event.target.dataset.location
21-
} else if (event.target.dataset.href.startsWith('http')) {
22-
url = event.target.dataset.href
23-
} else {
24-
url = chrome.runtime.getURL(event.target.dataset.href)
25-
}
26-
console.log(`url: ${url}`)
27-
await chrome.tabs.create({ active: true, url })
28-
window.close()
29-
}
30-
319
/**
3210
* Popup Init Function
3311
* TODO: Overhaul this function
3412
* @function initPopup
3513
*/
3614
async function initPopup() {
3715
console.log('initPopup')
38-
const { auth } = await chrome.storage.sync.get(['auth'])
16+
const { auth, options } = await chrome.storage.sync.get(['auth', 'options'])
3917
console.log('auth:', auth)
4018
if (!auth?.url || !auth?.token) {
4119
return displayError('Missing URL or Token.')
4220
}
4321
document.getElementById('django-files-links').style.display = 'flex'
4422

45-
let headers = { Authorization: auth.token }
46-
let options = { method: 'GET', headers: headers, cache: 'no-cache' }
23+
let opts = {
24+
method: 'GET',
25+
headers: { Authorization: auth.token },
26+
cache: 'no-cache',
27+
}
4728
let response
4829
let data
4930
try {
50-
response = await fetch(auth.url + '/api/recent/', options)
31+
const url = new URL(auth.url + '/api/recent/')
32+
url.searchParams.append('amount', options?.recentFiles || '10')
33+
response = await fetch(url, opts)
5134
data = await response.json()
5235
} catch (error) {
5336
console.warn(error)
@@ -66,36 +49,80 @@ async function initPopup() {
6649
return displayError('No Files Returned.')
6750
}
6851

52+
updateTable(data)
53+
const clipboard = new ClipboardJS('.clip') // eslint-disable-line
54+
document.querySelectorAll('[data-href]').forEach((el) => {
55+
el.addEventListener('click', popupLink)
56+
})
57+
}
58+
59+
/**
60+
* Popup Links Callback
61+
* because firefox needs us to call window.close() from the popup
62+
* @function popupLink
63+
* @param {MouseEvent} event
64+
*/
65+
async function popupLink(event) {
66+
console.log('popupLink:', event)
67+
const { auth } = await chrome.storage.sync.get(['auth'])
68+
let url
69+
if (event.target.dataset.location) {
70+
url = auth?.url + event.target.dataset.location
71+
} else if (event.target.dataset.href.startsWith('http')) {
72+
url = event.target.dataset.href
73+
} else {
74+
url = chrome.runtime.getURL(event.target.dataset.href)
75+
}
76+
console.log(`url: ${url}`)
77+
await chrome.tabs.create({ active: true, url })
78+
window.close()
79+
}
80+
81+
/**
82+
* Update Popup Table with Data
83+
* @function updateTable
84+
* @param {Object} data
85+
*/
86+
function updateTable(data) {
6987
let tbodyRef = document
7088
.getElementById('recent')
7189
.getElementsByTagName('tbody')[0]
7290

7391
data.forEach(function (value, i) {
74-
let name = String(value.split('/').reverse()[0])
92+
const name = String(value.split('/').reverse()[0])
93+
const row = tbodyRef.insertRow()
7594

76-
let copyLink = document.createTextNode(i + 1)
77-
// let copyLink = document.createElement('a')
78-
// copyLink.text = 1 + i
79-
// copyLink.title = name
80-
// copyLink.href = value
81-
// copyLink.target = '_blank'
95+
const copyLink = document.createTextNode(i + 1)
96+
const cell1 = row.insertCell()
97+
cell1.appendChild(copyLink)
8298

83-
let fileLink = document.createElement('a')
99+
const fileLink = document.createElement('a')
84100
fileLink.text = name
85101
fileLink.title = name
86-
fileLink.href = value
102+
fileLink.dataset.href = value
103+
fileLink.setAttribute('role', 'button')
104+
fileLink.classList.add(
105+
'link-underline',
106+
'link-underline-opacity-0',
107+
'link-underline-opacity-75-hover'
108+
)
87109
fileLink.target = '_blank'
88-
89-
let row = tbodyRef.insertRow()
90-
let cell1 = row.insertCell()
91-
cell1.appendChild(copyLink)
92-
let cell2 = row.insertCell()
110+
const cell2 = row.insertCell()
93111
cell2.appendChild(fileLink)
112+
113+
const copyBtn = document.createElement('a')
114+
copyBtn.title = 'Copy'
115+
copyBtn.setAttribute('role', 'button')
116+
copyBtn.classList.add('clip')
117+
copyBtn.dataset.clipboardText = value
118+
copyBtn.innerHTML = '<i class="fa-regular fa-clipboard text-white"></i>'
119+
const cell3 = row.insertCell()
120+
cell3.appendChild(copyBtn)
94121
})
95122
}
96123

97124
/**
98-
* Popup Action Init
125+
* Display Popup Error Message
99126
* @function displayError
100127
* @param {String} message
101128
*/

src/js/service-worker.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ chrome.notifications.onClicked.addListener((notificationId) => {
1818
export async function onInstalled() {
1919
console.log('onInstalled')
2020
let { options } = await chrome.storage.sync.get(['options'])
21-
options = options || { contextMenu: true }
21+
options = options || { contextMenu: true, recentFiles: '10' }
2222
console.log('options:', options)
2323
await chrome.storage.sync.set({ options })
2424
if (options.contextMenu) {
@@ -34,7 +34,7 @@ export async function onInstalled() {
3434
async function contextMenuClick(ctx) {
3535
console.log('contextMenuClick:', ctx)
3636
console.log(`ctx.menuItemId: ${ctx.menuItemId}`)
37-
if (ctx.menuItemId === 'upload') {
37+
if (ctx.menuItemId.startsWith('upload')) {
3838
if (ctx.srcUrl) {
3939
let mediaType =
4040
ctx.menuItemId.charAt(0).toUpperCase() + ctx.menuItemId.slice(1)
@@ -101,8 +101,8 @@ async function processRemote(endpoint, url, message) {
101101
* @function sendNotification
102102
* @param {String} title
103103
* @param {String} text
104-
* @param {String} id
105-
* @param {Number} timeout
104+
* @param {String} id - Optional
105+
* @param {Number} timeout - Optional
106106
*/
107107
async function sendNotification(title, text, id = '', timeout = 10) {
108108
console.log(`sendNotification: ${id || 'randomID'}: ${title} - ${text}`)

0 commit comments

Comments
 (0)