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
4 changes: 4 additions & 0 deletions css/public.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* Prevent user interaction on content */
#imgframe {
pointer-events: none;
}
5 changes: 4 additions & 1 deletion lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,11 @@ public function setDownloadLimit(string $token, int $limit): Response {
$insert = true;
}

// Update DB
// Set new limit
$shareLimit->setLimit($limit);
// Reset existing counter
$shareLimit->setDownloads(0);
// Update DB
if ($insert) {
$this->mapper->insert($shareLimit);
} else {
Expand Down
9 changes: 6 additions & 3 deletions src/models/DownloadLimitAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,21 @@ export default class DownloadLimitAction {

data() {
return {
icon: 'icon-download',
icon: this._store.loading ? 'icon-loading-small' : 'icon-download',
is: this._store.enabled ? ActionInput : null,
text: t('files_downloadlimit', 'Download limit'),
title: t('files_downloadlimit', 'Download count: {count}', this._store),
value: this._store.limit,
disabled: this._store.loading,
}
}

get handlers() {
return {
'update:value': debounce((limit) => {
setDownloadLimit(this._store.token, limit)
'update:value': debounce(async (limit) => {
this._store.loading = true
await setDownloadLimit(this._store.token, limit)
this._store.loading = false
}, 300),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/models/LimitEnableAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default class LimitEnableAction {
is: ActionCheckbox,
text: t('files_downloadlimit', 'Limit downloads'),
checked: this._store.enabled,
disabled: this._store.loading,
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/models/Store.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class Store {
limit: null,
count: null,
token: null,
loading: false,
}

get enabled() {
Expand Down Expand Up @@ -62,4 +63,12 @@ export default class Store {
this._data.token = token
}

get loading() {
return this._data.loading
}

set loading(loading) {
this._data.loading = loading
}

}
50 changes: 47 additions & 3 deletions src/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,64 @@
*
*/
import { loadState } from '@nextcloud/initial-state'
import { translatePlural as n } from '@nextcloud/l10n'
import { translate as t, translatePlural as n } from '@nextcloud/l10n'

import '../css/public.css'

const { limit, downloads } = loadState(appName, 'download_limit', { limit: -1, downloads: 0 })
console.debug('[DEBUG]', appName, { limit, downloads })

let count = limit - downloads
let clicks = 0

const updateCounter = function(span) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing count parameter no?

if (count === 0) {
span.innerText = t(appName, 'You have reached the maximum amount of downloads allowed')
} else {
span.innerText = n(appName, '1 remaining download allowed', '{count} remaining downloads allowed', count, { count })
}
}

window.addEventListener('DOMContentLoaded', function() {
if (limit > 0) {
const count = limit - downloads
const container = document.getElementById('header-primary-action')
const span = document.createElement('span')

span.style = 'color: var(--color-primary-text); padding: 0 10px;'
span.innerText = n('files_downloadlimit', '1 remaining download allowed', '{count} remaining downloads allowed', count, { count })
updateCounter(span, count)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or extra count parameter here, not clear, it seems count is actually global

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's cleaner, you're right, let me fix in a pr :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#83


container.prepend(span)

// Preventing mouse interaction
document.querySelector('#files-public-content').oncontextmenu = function(event) {
event.preventDefault()
event.stopPropagation()
return false
}

// Adding double-download warning
const downloadButtons = document.querySelectorAll('a[href*="/download/"]') || []
new Set(downloadButtons).forEach(button => {
button.addEventListener('click', (event) => {
// Warn about download limits
if (clicks > 0) {
if (!confirm(t(appName, 'This share has a limited number of downloads. Are you sure you want to trigger a new download?'))) {
event.preventDefault()
event.stopPropagation()
return
}
}

// Handle counts changes
count--
clicks++
updateCounter(span, count)

// Remove the buttons if share is now expired
if (count === 0) {
[...downloadButtons].forEach(button => button.remove())
}
})
})
}
})