feat(ui): permit drag&drop to the operating system
a drop outside of the browser will: - upload the file if only 1 file selected - upload a .zip of the directory or multiple selection (browsers do not permit multiple upload yet) note: I had to create a new handler because a post request to /api/batch/download is possible via JS but it will create a memory blob in the browser, during the drag action. This may exhaust the browser's memory if heavy files This will initiate zip creation from the server even if drop is canceled The best approach is to add a handler supporting GET calls, this call will be triggered by the browser on drop action outside of it's window
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
// deserialize comma separated string into into Vec<String>
|
||||
pub fn deserialize_csv<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer).unwrap_or_default();
|
||||
Ok(s.split(',')
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(String::from)
|
||||
.collect())
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod cookie_auth;
|
||||
pub mod deserializer;
|
||||
pub mod handlers;
|
||||
pub mod routes;
|
||||
|
||||
|
||||
@@ -203,7 +203,9 @@ pub fn create_api_routes(app_state: &Arc<AppState>) -> Router<Arc<AppState>> {
|
||||
// Trash operations (soft delete)
|
||||
.route("/trash", post(batch_handler::trash_batch))
|
||||
// Download as ZIP
|
||||
.route("/download", post(batch_handler::download_batch))
|
||||
.route("/download", post(batch_handler::download_batch_post))
|
||||
// work arround for drag & drop (does not support POST requests)
|
||||
.route("/download", get(batch_handler::download_batch_querystring))
|
||||
.with_state(batch_handler_state);
|
||||
|
||||
// Create search routes if the service is available
|
||||
|
||||
@@ -1081,6 +1081,41 @@ const ui = {
|
||||
lastItemDiv = div;
|
||||
}
|
||||
|
||||
let downloadUrl;
|
||||
let nameEncoded;
|
||||
|
||||
// tells Browser URL to call to drop selection on operating system (desktop, file manager etc)
|
||||
// will generate a zipfile if multiple
|
||||
if (selectedCardFromList.length === 1) {
|
||||
// only 1 file
|
||||
if (info.type === 'file') {
|
||||
nameEncoded = info.name.replaceAll(/:/g, '-'); // issue is that DownloadURL is using : as separator;
|
||||
downloadUrl = `${window.location.origin}/api/files/${info.id}`;
|
||||
} else {
|
||||
// directory into ZIP
|
||||
nameEncoded = info.name.replaceAll(/:/g, '-').concat('.zip');
|
||||
downloadUrl = `${window.location.origin}/api/folders/${info.id}/download?format=zip`;
|
||||
}
|
||||
} else {
|
||||
// must use ZIP container
|
||||
// TODO better naming like ("selection in ${parent.name}") modulo i18n ? ...
|
||||
const now = new Date().toISOString().replace(/T/, ' ').replace(/\.*/, '').replaceAll(/:/g, '-');
|
||||
nameEncoded = `oxicloud ${now}.zip`;
|
||||
const folders = [];
|
||||
const files = [];
|
||||
filesList.querySelectorAll(`div.selected`).forEach((e) => {
|
||||
const item = itemInfo(e);
|
||||
if (item.type === 'file') {
|
||||
files.push(item.id);
|
||||
} else {
|
||||
folders.push(item.id);
|
||||
}
|
||||
});
|
||||
downloadUrl = `${window.location.origin}/api/batch/download?file_ids=${files.join(',')}&folder_ids=${folders.join(',')}`;
|
||||
}
|
||||
|
||||
e.dataTransfer?.setData('DownloadURL', `application/octet-stream:${nameEncoded}:${downloadUrl}`);
|
||||
|
||||
// if more than 1 item, display the badge
|
||||
if (selectedCardFromList.length > 1) {
|
||||
const badge = document.createElement('span');
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// OxiCloud Service Worker
|
||||
// FIXME: generate cache name according build ?
|
||||
const CACHE_NAME = 'oxicloud-cache-v20';
|
||||
const CACHE_NAME = 'oxicloud-cache-v21';
|
||||
|
||||
// Only cache static assets — NOT HTML files.
|
||||
// HTML files are served network-first so browsers always get the latest
|
||||
|
||||
Reference in New Issue
Block a user