parent
b6680d7cab
commit
00398272bd
@ -0,0 +1,237 @@ |
|||||||
|
<!-- |
||||||
|
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||||
|
// All rights reserved. |
||||||
|
// Licensed under the Apache License, Version 2.0 |
||||||
|
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||||
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||||
|
// at your option. All files in the project carrying such |
||||||
|
// notice may not be copied, modified, or distributed except |
||||||
|
// according to those terms. |
||||||
|
--> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import ng from "../../api"; |
||||||
|
import { |
||||||
|
branch_subscribe, |
||||||
|
active_session, |
||||||
|
online, |
||||||
|
get_blob, |
||||||
|
} from "../../store"; |
||||||
|
import { cur_tab } from "../../tab"; |
||||||
|
import { |
||||||
|
ExclamationTriangle, |
||||||
|
ArrowDownTray, |
||||||
|
ArrowUpTray, |
||||||
|
} from "svelte-heros-v2"; |
||||||
|
|
||||||
|
import { onMount, onDestroy, tick } from "svelte"; |
||||||
|
import { Button, Progressbar, Spinner } from "flowbite-svelte"; |
||||||
|
import { t } from "svelte-i18n"; |
||||||
|
let is_tauri = import.meta.env.TAURI_PLATFORM; |
||||||
|
|
||||||
|
let upload_progress: null | { total: number; current: number; error?: any } = null; |
||||||
|
|
||||||
|
let commits = $active_session && branch_subscribe($cur_tab.branch.nuri, false); |
||||||
|
let fileinput; |
||||||
|
|
||||||
|
let file_urls = {}; |
||||||
|
const prepare_url = (nuri) => { |
||||||
|
if (!file_urls[nuri]) { |
||||||
|
file_urls[nuri] = { |
||||||
|
click: false |
||||||
|
}; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
const download = async (file) => { |
||||||
|
if (is_tauri) { |
||||||
|
await ng.file_save_to_downloads($active_session.session_id, file.reference, file.name, "did:ng:"+$cur_tab.branch.nuri); |
||||||
|
} else { |
||||||
|
file_urls[file.nuri].url = await get_blob(file, false); |
||||||
|
//console.log(file.name); |
||||||
|
//console.log(file_urls[file.nuri].click); |
||||||
|
await tick(); |
||||||
|
file_urls[file.nuri].click.click(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const isImage = async (url) : Promise<boolean> => { |
||||||
|
if ( typeof url === 'string' ) { |
||||||
|
let blob = await fetch(url).then(r => r.blob()); |
||||||
|
return blob.type.startsWith("image/"); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
function uploadFile(upload_id, nuri, file, success) { |
||||||
|
console.log(nuri); |
||||||
|
let chunkSize = 1_048_564; |
||||||
|
let fileSize = file.size; |
||||||
|
let offset = 0; |
||||||
|
let readBlock = null; |
||||||
|
upload_progress = { total: fileSize, current: offset }; |
||||||
|
|
||||||
|
let onLoadHandler = async function (event) { |
||||||
|
let result = event.target.result; |
||||||
|
|
||||||
|
if (event.target.error == null) { |
||||||
|
offset += result.byteLength; |
||||||
|
upload_progress = { total: fileSize, current: offset }; |
||||||
|
|
||||||
|
// console.log("chunk", result); |
||||||
|
|
||||||
|
let res = await ng.upload_chunk( |
||||||
|
$active_session.session_id, |
||||||
|
upload_id, |
||||||
|
result, |
||||||
|
nuri |
||||||
|
); |
||||||
|
//console.log("chunk upload res", res); |
||||||
|
// if (onChunkRead) { |
||||||
|
// onChunkRead(result); |
||||||
|
// } |
||||||
|
} else { |
||||||
|
// if (onChunkError) { |
||||||
|
// onChunkError(event.target.error); |
||||||
|
// } |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// If finished: |
||||||
|
if (offset >= fileSize) { |
||||||
|
//console.log("file uploaded"); |
||||||
|
let res = await ng.upload_chunk( |
||||||
|
$active_session.session_id, |
||||||
|
upload_id, |
||||||
|
[], |
||||||
|
nuri |
||||||
|
); |
||||||
|
//console.log("end upload res", res); |
||||||
|
if (success) { |
||||||
|
upload_progress = { total: fileSize, current: fileSize }; |
||||||
|
success(res); |
||||||
|
} else { |
||||||
|
upload_progress = { total: fileSize, current: fileSize, error: true }; |
||||||
|
} |
||||||
|
|
||||||
|
// Make progress bar disappear |
||||||
|
setTimeout(() => { |
||||||
|
upload_progress = null; |
||||||
|
}, 1_000); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
readBlock(offset, chunkSize, file); |
||||||
|
}; |
||||||
|
|
||||||
|
readBlock = function (offset, length, file) { |
||||||
|
let fileReader = new FileReader(); |
||||||
|
let blob = file.slice(offset, length + offset); |
||||||
|
fileReader.onload = onLoadHandler; |
||||||
|
fileReader.readAsArrayBuffer(blob); |
||||||
|
}; |
||||||
|
|
||||||
|
readBlock(offset, chunkSize, file); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
const onFileSelected = async (e) => { |
||||||
|
let image = e.target.files[0]; |
||||||
|
if (!image) return; |
||||||
|
//console.log(image.type); |
||||||
|
|
||||||
|
let start_request_payload = { |
||||||
|
RandomAccessFilePut: image.type, |
||||||
|
}; |
||||||
|
let nuri = "did:ng:"+$cur_tab.branch.nuri; |
||||||
|
let start_res = await ng.app_request_with_nuri_command(nuri, "FilePut", $active_session.session_id, start_request_payload); |
||||||
|
let upload_id = start_res.V0.FileUploading; |
||||||
|
|
||||||
|
uploadFile(upload_id, nuri, image, async (reference) => { |
||||||
|
if (reference) { |
||||||
|
let file_put_payload = { |
||||||
|
AddFile: { |
||||||
|
filename: image.name, |
||||||
|
object: reference.V0.FileUploaded, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
await ng.app_request_with_nuri_command(nuri, "FilePut", $active_session.session_id, file_put_payload); |
||||||
|
} |
||||||
|
}); |
||||||
|
fileinput.value = ""; |
||||||
|
}; |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
<div class="w-full"> |
||||||
|
<div class="row pt-2 w-full"> |
||||||
|
|
||||||
|
<Button |
||||||
|
disabled={!$online && !is_tauri} |
||||||
|
type="button" |
||||||
|
on:click={() => { |
||||||
|
fileinput.click(); |
||||||
|
}} |
||||||
|
class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mr-2 mb-2" |
||||||
|
> |
||||||
|
<ArrowUpTray class="w-8 h-8 mr-2 -ml-1"/> |
||||||
|
{$t("doc.file.upload")} |
||||||
|
</Button> |
||||||
|
<input |
||||||
|
style="display:none" |
||||||
|
type="file" |
||||||
|
on:change={(e) => onFileSelected(e)} |
||||||
|
bind:this={fileinput} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
{#if upload_progress !== null} |
||||||
|
<div class="mx-6 mt-2"> |
||||||
|
<Progressbar |
||||||
|
progress={( |
||||||
|
(100 * upload_progress.current) / |
||||||
|
upload_progress.total |
||||||
|
).toFixed(0)} |
||||||
|
labelOutside={$t("doc.file.upload_progress")} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
{/if} |
||||||
|
{#if commits} |
||||||
|
{#await commits.load()} |
||||||
|
<p>{$t("connectivity.loading")}...</p> |
||||||
|
{:then} |
||||||
|
{#each $commits.files as file} |
||||||
|
<p class="mb-5"> |
||||||
|
|
||||||
|
{#await get_blob(file, true)} |
||||||
|
<div class="ml-2"> |
||||||
|
<Spinner /> |
||||||
|
</div> |
||||||
|
{:then url} |
||||||
|
{#await isImage(url) then is} |
||||||
|
{#if is} |
||||||
|
<img src={url} title={file.nuri} alt={file.name} /> |
||||||
|
{/if} |
||||||
|
{/await} |
||||||
|
<span class="ml-2 text-gray-600">{file.name}<br/></span> |
||||||
|
{#if url === false} |
||||||
|
<span><ExclamationTriangle tabindex="-1" class="ml-2 w-6 h-8 focus:outline-none" style="display:inline"/>{$t("errors.cannot_load_this_file")}</span> |
||||||
|
{:else if prepare_url(file.nuri)} |
||||||
|
<a bind:this={file_urls[file.nuri].click} |
||||||
|
href={file_urls[file.nuri].url || ""} |
||||||
|
target="_blank" |
||||||
|
download={file.name} |
||||||
|
></a> |
||||||
|
<button class="ml-2 select-none p-1 pb-0 text-gray-600" style="box-shadow:none;" on:click={()=>download(file)}> |
||||||
|
<span><ArrowDownTray tabindex="-1" class="w-6 h-8 mr-3 focus:outline-none" style="display:inline"/>{$t("doc.file.download")}</span> |
||||||
|
</button> |
||||||
|
{/if} |
||||||
|
{/await} |
||||||
|
</p> |
||||||
|
{/each} |
||||||
|
{/await} |
||||||
|
{/if} |
||||||
|
|
||||||
|
</div> |
Loading…
Reference in new issue