UNPKG

globular-mvc

Version:

Generic template to create web-application that made use of globular as backend and materialize as css (wrap in web-component's)

1,199 lines (1,000 loc) 305 kB
import '@polymer/iron-icons/iron-icons.js'; import '@polymer/paper-icon-button/paper-icon-button.js'; import '@polymer/paper-input/paper-input.js'; import '@polymer/paper-card/paper-card.js'; import '@polymer/paper-button/paper-button.js'; import '@polymer/paper-checkbox/paper-checkbox.js'; import '@polymer/iron-icons/editor-icons.js' import "@polymer/iron-icons/social-icons"; import "@polymer/iron-icons/av-icons"; import "@polymer/iron-icons/maps-icons"; import "@polymer/paper-progress/paper-progress.js" import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js' import '@polymer/paper-listbox/paper-listbox.js' import '@polymer/paper-item/paper-item.js' import "./DiskSpace.js" import "./Share.js" import * as getUuid from 'uuid-by-string' import { generatePeerToken, getUrl, Model } from '../Model'; import { File as File__ } from "../File"; // File object already exist in js and I need to use it... import { Menu } from './Menu'; import { PermissionsManager } from './Permissions'; import { FileMetaDataInfo, InformationsManager } from './Informations' import { playVideo, playVideos } from './Video' import { playAudio, playAudios } from './Audio' import { GlobularFileReader } from './Reader' import { v4 as uuidv4 } from "uuid"; // Menu to set action on files. import { DropdownMenu } from './dropdownMenu.js'; import { AddPublicDirRequest, ConvertVideoToHlsRequest, ConvertVideoToMpeg4H264Request, CopyRequest, CreateDirRequest, CreateLnkRequest, CreateVideoPreviewRequest, CreateVideoTimeLineRequest, DeleteDirRequest, DeleteFileRequest, GetFileInfoRequest, GetPublicDirsRequest, MoveRequest, ReadFileRequest, RemovePublicDirRequest, SaveFileRequest, StartProcessAudioRequest, StartProcessVideoRequest, UploadFileRequest, UploadVideoRequest } from 'globular-web-client/file/file_pb'; import { createArchive, deleteDir, deleteFile, downloadFileHttp, renameFile, uploadFiles } from 'globular-web-client/api'; import { ApplicationView } from '../ApplicationView'; import { Application } from '../Application'; import { GetSharedResourceRqst, SubjectType } from 'globular-web-client/rbac/rbac_pb'; import { fireResize, getCoords, randomUUID } from './utility'; import * as getUuidByString from 'uuid-by-string'; import { ImageViewer } from './Image'; import { AssociateFileWithTitleRequest, CreateTitleRequest, CreateVideoRequest, GetFileAudiosRequest, GetFileTitlesRequest, GetFileVideosRequest, Person, Poster, Title, Video, Publisher, CreatePersonRequest, GetTitleByIdRequest } from 'globular-web-client/title/title_pb'; import { DownloadTorrentRequest, DropTorrentRequest, GetTorrentInfosRequest, GetTorrentLnksRequest } from 'globular-web-client/torrent/torrent_pb'; import { getImdbInfo } from './Search'; import { setMoveable } from './moveable' import { setResizeable } from './rezieable' import { SplitView } from './Splitter' import { Account } from '../Account'; import { mergeTypedArrays, uint8arrayToStringMethod } from "../Utility"; import { ShareResourceMenu } from './Share.js'; import "../style.css" // keep track of shared directory var shared = {} var public_ = {} /** * Format file size from bytes to Gb, Mb or Kb... * @param {*} f_size * @returns */ export function getFileSizeString(f_size) { // In case of already converted values... if (typeof f_size === 'string' || f_size instanceof String) { return f_size } let size = "" if (f_size > 1024) { if (f_size > 1024 * 1024) { if (f_size > 1024 * 1024 * 1024) { let fileSize = f_size / (1024 * 1024 * 1024); size = fileSize.toFixed(2) + " GB"; } else { let fileSize = f_size / (1024 * 1024); size = fileSize.toFixed(2) + " MB"; } } else { let fileSize = f_size / 1024; size = fileSize.toFixed(2) + " KB"; } } else { size = f_size + " bytes"; } return size } // Return the size of a file at url. function getFileSize(url_, callback, errorcallback) { let url = window.location.protocol + "//" + window.location.host + "/file_size" var xmlhttp = new XMLHttpRequest(); xmlhttp.timeout = 10 * 1000 xmlhttp.onreadystatechange = function () { if (this.readyState == 4 && (this.status == 201 || this.status == 200)) { let obj = JSON.parse(this.responseText) callback(obj.size); } else if (this.readyState == 4) { errorcallback("fail to get the configuration file at url " + url + " status " + this.status) } }; url += "?url=" + url_ xmlhttp.open("GET", url, true); xmlhttp.setRequestHeader("domain", Model.domain); xmlhttp.send(); } function copyToClipboard(text) { var dummy = document.createElement("textarea"); // to avoid breaking orgain page when copying more words // cant copy when adding below this code // dummy.style.display = 'none' document.body.appendChild(dummy); //Be careful if you use texarea. setAttribute('value', value), which works with "input" does not work with "textarea". – Eduard dummy.value = text; dummy.select(); document.execCommand("copy"); document.body.removeChild(dummy); } // Now I will test if imdb info are allready asscociated. export function getTitleInfo(file, callback) { let globules = Model.getGlobules() globules = globules.filter(function (e) { return e.domain !== file.globule.domain }) globules.unshift(file.globule) if (file.titles) { if (file.titles.length > 0) { callback(file.titles) return } } // Now I will get titles info. let ___getTitleInfo___ = (index) => { let g = globules[index] index++ __getTitleInfo__(g, file, (_titles_) => { if (_titles_.length > 0) { _titles_.forEach(t => t.globule = g) if (!file.titles) { file.titles = [] } file.titles = file.titles.concat(_titles_) callback(file.titles) return } if (index < globules.length) { ___getTitleInfo___(index) } else { if (file.titles) { callback(file.titles) } else { callback([]) } } }) } let index = 0 ___getTitleInfo___(index) } function __getTitleInfo__(globule, file, callback) { let rqst = new GetFileTitlesRequest rqst.setIndexpath(globule.config.DataPath + "/search/titles") rqst.setFilepath(file.path) generatePeerToken(globule, token => { globule.titleService.getFileTitles(rqst, { application: Application.application, domain: globule.domain, token: token }) .then(rsp => { callback(rsp.getTitles().getTitlesList()) }) .catch(err => { // so here no title was found... callback([]) }) }) } export function getVideoInfo(file, callback) { if (file.videos) { if (file.videos.length > 0) { callback(file.videos) return } } let globules = Model.getGlobules() globules = globules.filter(function (e) { return e.domain !== file.globule.domain }) globules.unshift(file.globule) // Now I will get titles info. let ___getVideoInfo___ = (index) => { let g = globules[index] index++ __getVideoInfo__(g, file, (_videos_) => { if (_videos_.length > 0) { _videos_.forEach(v => v.globule = g) if (!file.videos) { file.videos = [] } file.videos = file.videos.concat(_videos_) callback(file.videos) return } if (index < globules.length) { ___getVideoInfo___(index) } else { if (file.videos) { callback(file.videos) } else { callback([]) } } }) } let index = 0 ___getVideoInfo___(index) } function __getVideoInfo__(globule, file, callback) { let rqst = new GetFileVideosRequest rqst.setIndexpath(globule.config.DataPath + "/search/videos") rqst.setFilepath(file.path) generatePeerToken(globule, token => { globule.titleService.getFileVideos(rqst, { application: Application.application, domain: globule.domain, token: token }) .then(rsp => { let videos = rsp.getVideos().getVideosList() callback(videos) }) .catch(err => { callback([]) }) }) } export function getAudioInfo(file, callback) { let globules = Model.getGlobules() globules = globules.filter(function (e) { return e.domain !== file.globule.domain }) globules.unshift(file.globule) if (file.audios) { if (file.audios.length > 0) { callback(file.audios) return } } // Now I will get titles info. let ___getAudioInfo___ = (index) => { let g = globules[index] index++ __getAudioInfo__(g, file, (_audios_) => { if (_audios_.length > 0) { _audios_.forEach(a => a.globule = g) if (!file.audios) { file.audios = [] } file.audios = file.audios.concat(_audios_) callback(file.audios) return } if (index < globules.length) { ___getAudioInfo___(index) } else { if (file.audios) { callback(file.audios) } else { callback([]) } } }) } let index = 0 ___getAudioInfo___(index) } function __getAudioInfo__(globule, file, callback) { let rqst = new GetFileAudiosRequest rqst.setIndexpath(globule.config.DataPath + "/search/audios") rqst.setFilepath(file.path) generatePeerToken(globule, token => { globule.titleService.getFileAudios(rqst, { application: Application.application, domain: globule.domain, token: token }) .then(rsp => { let audios = rsp.getAudios().getAudiosList() // set the globule. audios.forEach(a => a.globule = globule) callback(audios) }) .catch(err => { callback([]) }) }) } function formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } function markAsShare(dir) { shared[dir.path] = {}; dir._files.forEach(f => { if (f._isDir) { markAsShare(f) } }) } function markAsPublic(dir, parent) { public_[dir.path] = {}; dir.__parent__ = parent // keep track of the original directory on the disck dir._files.forEach(f => { if (f._isDir) { markAsPublic(f, parent) } }) } function getElementIndex(element) { return Array.from(element.parentNode.children).indexOf(element); } // so here I will initialyse lnk's in that directory function initLnks(dir, callback) { // callback(dir) let initLink_ = (index) => { if (index == dir.files.length) { callback(dir) return } let f = dir.files[index] index += 1 if (!f.isDir) { if (f.name.endsWith(".lnk")) { File__.readText(f, txt => { f.lnk = File__.fromString(txt) initLink_(index) }, () => { initLink_(index) }) } else { initLink_(index) } } else { initLink_(index) } } let index = 0; initLink_(index) } export function getImage(callback, images, files, index, globule) { let f = files[index]; index++ // set the url for the image. let url = "" if (!globule) { // Here I will use the default globule... url = window.location.protocol + "//" + window.location.hostname + ":" if (Application.globular.config.Protocol == "https") { url += Application.globular.config.PortHttps } else { url += Application.globular.config.PortHttp } } else { // Get image from the globule. url = globule.config.Protocol + "://" + globule.domain if (globule.config.Protocol == "https") { if (globule.config.PortHttps != 443) url += ":" + globule.config.PortHttps } else { if (globule.config.PortHttps != 80) url += ":" + globule.config.PortHttp } } if (f == undefined) { callback([]) return } if (!f.path) { callback([]) return } let path = f.path.split("/") path.forEach(item => { item = item.trim() if (item.length > 0) url += "/" + encodeURIComponent(item) }) generatePeerToken(globule, token => { // Set url query parameter. url += "?domain=" + globule.domain url += "&application=" + Model.application url += "&token=" + token var xhr = new XMLHttpRequest(); xhr.timeout = 10 * 1000 xhr.open('GET', url, true); xhr.setRequestHeader("token", token); xhr.setRequestHeader("application", Model.application); xhr.setRequestHeader("domain", globule.domain); // Set responseType to 'arraybuffer', we want raw binary data buffer xhr.responseType = 'blob'; xhr.onload = (rsp) => { if (rsp.currentTarget.status == 200) { var reader = new FileReader(); reader.readAsDataURL(rsp.currentTarget.response); reader.onload = function (e) { let img = document.createElement("img") img.src = e.target.result images.push(img) if (index < files.length) { getImage(callback, images, files, index, globule) } else if (callback != undefined) { callback(images) } }; } }; xhr.send(); }) } // Keep dir info in map to save time... let dirs = {} // Usefull to get dir like /shared or /public that dosent exist on the server. export function getLocalDir(globule, path) { // replace separator... path = path.split("\\").join("/") let key = getUuidByString(globule.domain + "@" + path) let dir = dirs[key] if (dir != null) { return dir } return null } /** * Read dir from local map if available. Read from the server * if not in the map of force (in case of refresh) * @param {*} path The path of the dir on the server * @param {*} callback The success callback * @param {*} errorCallback The error callback * @param {*} force If set the dir will be read from the server. */ function _readDir(path, callback, errorCallback, globule, force = false) { // replace separator... path = path.split("\\").join("/") let key = getUuidByString(globule.domain + "@" + path) if (!force || path == "/public" || path == "/shared") { let dir = dirs[key] if (dir != null) { if (dir.files.length > 0) { callback(dirs[key]) return } } } // Here I will keep the dir info in the cache... File__.readDir(path, false, (dir) => { initLnks(dir, dir => { callback(dir) }) // replace separator... dir.path = dir.path.split("\\").join("/") let parent = dir.path.substring(0, dir.path.lastIndexOf("/")) if (public_[parent]) { markAsPublic(dir, parent) } dirs[key] = dir }, errorCallback, globule) } function getHiddenFiles(path, callback, globule) { let thumbnailPath = path.replace("/playlist.m3u8", "") if (thumbnailPath.lastIndexOf(".mp3") != -1 || thumbnailPath.lastIndexOf(".mp4") != -1 || thumbnailPath.lastIndexOf(".mkv") != -1 || thumbnailPath.lastIndexOf(".avi") != -1 || thumbnailPath.lastIndexOf(".MP4") != -1 || thumbnailPath.lastIndexOf(".MKV") != -1 || thumbnailPath.lastIndexOf(".AVI") != -1) { thumbnailPath = thumbnailPath.substring(0, thumbnailPath.lastIndexOf(".")) } thumbnailPath = thumbnailPath.substring(0, thumbnailPath.lastIndexOf("/") + 1) + ".hidden" + thumbnailPath.substring(thumbnailPath.lastIndexOf("/")) + "/__preview__" _readDir(thumbnailPath, callback, err => { console.log(err); callback(null); }, globule) } function _publishSetDirEvent(path, file_explorer_) { file_explorer_.displayWaitMessage("load " + path) _readDir(path, (dir) => { Model.eventHub.publish("__set_dir_event__", { dir: dir, file_explorer_id: file_explorer_.id }, true) file_explorer_.resume() }, err => { ApplicationView.displayMessage(err, 3000); file_explorer_.resume(); }, file_explorer_.globule) } // the paper tray var paperTray = []; var editMode = ""; /** * That class is the base class of FilesListView and FilesIconView */ export class FilesView extends HTMLElement { constructor() { super() // must icon or list view one is active at time. this._active_ = false // The parent file explorer this._file_explorer_ = null; // Set the shadow dom. this.attachShadow({ mode: 'open' }); // The active explorer path. this.path = undefined // The current directory. this.__dir__ = null; // The list of files to delete this.selected = {}; // The function will be call in case of error. this.onerror = err => ApplicationView.displayMessage(err, 3000); // Innitialisation of the layout. let id = "_" + uuidv4().split("-").join("_").split("@").join("_"); // Create the share resource menu. this.shareResource = new ShareResourceMenu let menuItemsHTML = ` <globular-dropdown-menu-item id="file-infos-menu-item" icon="icons:info" text="File Infos" action=""> </globular-dropdown-menu-item> <globular-dropdown-menu-item id="title-infos-menu-item" icon="icons:info" text="Title Infos" action="" style="display: none;"> </globular-dropdown-menu-item> <globular-dropdown-menu-item id="manage-acess-menu-item" icon="folder-shared" text="Manage access" action=""></globular-dropdown-menu-item> <globular-dropdown-menu-item id="refresh-infos-menu-item" icon="icons:refresh" text="Refresh infos" action="" style="display: none;"></globular-dropdown-menu-item> <globular-dropdown-menu-item separator="true" id="video-menu-item" icon="maps:local-movies" text="Movies" action="" style="display: none;"> <globular-dropdown-menu> <globular-dropdown-menu-item id="generate-timeline-menu-item" icon="maps:local-movies" text="generate timeline" action=""> </globular-dropdown-menu-item> <globular-dropdown-menu-item id="generate-preview-menu-item" icon="maps:local-movies" text="generate preview" action=""> </globular-dropdown-menu-item> <globular-dropdown-menu-item separator="true" id="to-mp4-menu-item" icon="maps:local-movies" text="convert to mp4" action="" style="display: none;"> </globular-dropdown-menu-item> <globular-dropdown-menu-item separator="true" id="to-hls-menu-item" icon="maps:local-movies" text="convert to hls" action="" style="display: none;"> </globular-dropdown-menu-item> </globular-dropdown-menu> </globular-dropdown-menu-item> <globular-dropdown-menu-item separator="true" id="cut-menu-item" icon="icons:content-cut" text="Cut" action=""></globular-dropdown-menu-item> <globular-dropdown-menu-item id="copy-menu-item" icon="content-copy" text="Copy" action=""></globular-dropdown-menu-item> <globular-dropdown-menu-item id="paste-menu-item" icon="icons:content-paste" action="" text="Paste"></globular-dropdown-menu-item> <globular-dropdown-menu-item separator="true" id="rename-menu-item" text="Rename" icon="icons:create" action=""> </globular-dropdown-menu-item> <globular-dropdown-menu-item id="delete-menu-item" icon="icons:delete" action="" text="Delete"> </globular-dropdown-menu-item> <globular-dropdown-menu-item separator="true" id="download-menu-item" icon="icons:cloud-download" text="Download" action=""> </globular-dropdown-menu-item> <globular-dropdown-menu-item id="open-in-new-tab-menu-item" icon="icons:open-in-new" text="Open in new tab" action="" style="display: none;"> </globular-dropdown-menu-item> <globular-dropdown-menu-item id="copy-url-menu-item" icon="icons:link" text="Copy url" action=""> </globular-dropdown-menu-item> ` this.menu = new DropdownMenu("icons:more-vert") this.menu.className = "file-dropdown-menu" this.menu.innerHTML = menuItemsHTML this.videMenuItem = this.menu.querySelector("#video-menu-item") this.fileInfosMenuItem = this.menu.querySelector("#file-infos-menu-item") this.titleInfosMenuItem = this.menu.querySelector("#title-infos-menu-item") this.refreshInfoMenuItem = this.menu.querySelector("#refresh-infos-menu-item") this.mananageAccessMenuItem = this.menu.querySelector("#manage-acess-menu-item") this.renameMenuItem = this.menu.querySelector("#rename-menu-item") this.deleteMenuItem = this.menu.querySelector("#delete-menu-item") this.downloadMenuItem = this.menu.querySelector("#download-menu-item") this.openInNewTabItem = this.menu.querySelector("#open-in-new-tab-menu-item") this.copyUrlItem = this.menu.querySelector("#copy-url-menu-item") // video conversion menu this.generateTimeLineItem = this.menu.querySelector("#generate-timeline-menu-item") this.generatePreviewItem = this.menu.querySelector("#generate-preview-menu-item") this.toMp4MenuItem = this.menu.querySelector("#to-mp4-menu-item") this.toHlsMenuItem = this.menu.querySelector("#to-hls-menu-item") // Now the cut copy and paste menu... this.cutMenuItem = this.menu.querySelector("#cut-menu-item") this.copyMenuItem = this.menu.querySelector("#copy-menu-item") this.pasteMenuItem = this.menu.querySelector("#paste-menu-item") // Action to do when file is set this.menu.setFile = (f) => { this.menu.file = f; if (this.menu.file.mime.startsWith("video") || this.menu.file.videos != undefined || this.menu.file.titles != undefined || this.menu.file.isDir) { this.titleInfosMenuItem.style.display = "block" if (this.menu.file.mime.startsWith("video")) { this.videMenuItem.style.display = "block" this.openInNewTabItem.style.display = "block" this.generateTimeLineItem.style.display = "block" this.generatePreviewItem.style.display = "block" if (this.menu.file.name.endsWith(".mp4") || this.menu.file.name.endsWith(".MP4")) { this.toHlsMenuItem.style.display = "block" this.toMp4MenuItem.style.display = "none" } else if (this.menu.file.mime == "video/hls-stream") { this.toHlsMenuItem.style.display = "none" this.toMp4MenuItem.style.display = "none" } else { this.toHlsMenuItem.style.display = "none" this.toMp4MenuItem.style.display = "block" } } } else { this.videMenuItem.style.display = "none" if (this.menu.file.mime.startsWith("audio")) { this.titleInfosMenuItem.style.display = "block" } else { this.titleInfosMenuItem.style.display = "none" } if (this.menu.file.isDir) { this.refreshInfoMenuItem.style.display = "block" this.videMenuItem.style.display = "block" this.toHlsMenuItem.style.display = "block" this.toMp4MenuItem.style.display = "block" this.generateTimeLineItem.style.display = "none" this.generatePreviewItem.style.display = "none" } this.openInNewTabItem.style.display = "none" } } this.refreshInfoMenuItem.action = () => { let rqst = new StartProcessVideoRequest rqst.setPath(this.menu.file.path) let globule = this._file_explorer_.globule generatePeerToken(globule, token => { globule.fileService.startProcessVideo(rqst, { application: Application.application, domain: globule.domain, token: token }).then(() => { ApplicationView.displayMessage("informations are now updated", 3000) }) .catch(err => ApplicationView.displayMessage(err, 3000)) }) // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.cutMenuItem.action = () => { editMode = "cut" paperTray = []; for (var key in this.selected) { paperTray.push(this.selected[key].path) } // Append file to file menu if (paperTray.length == 0) { paperTray.push(this.menu.file.path) } // empty the selection. this.selected = {} // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.copyMenuItem.action = () => { // So here I will display choice to the user and set the edit mode penpending it response. paperTray = []; for (var key in this.selected) { paperTray.push(this.selected[key].path) } // Append file to file menu if (paperTray.length == 0) { paperTray.push(this.menu.file.path) } // empty the selection. this.selected = {} // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.pasteMenuItem.action = () => { paperTray = []; if (editMode == "copy") { // Here I will call move on the file manager this.copy(this.menu.file.path) } else if (editMode == "cut") { // Here I will call copy this.move(this.menu.file.path) } // empty the selection. this.selected = {} // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.openInNewTabItem.action = () => { let globule = this._file_explorer_.globule generatePeerToken(globule, token => { let url = getUrl(globule) this.menu.file.path.split("/").forEach(item => { let component = encodeURIComponent(item.trim()) if (component.length > 0) { url += "/" + component } }) if (this.menu.file.mime == "video/hls-stream") { url += "/playlist.m3u8" } url += "?application=" + Model.application; url += "&token=" + token window.open(url, '_blank', "fullscreen=yes"); // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) }) } this.copyUrlItem.action = () => { let globule = this._file_explorer_.globule generatePeerToken(globule, token => { let url = getUrl(globule) this.menu.file.path.split("/").forEach(item => { let component = encodeURIComponent(item.trim()) if (component.length > 0) { url += "/" + component } }) if (this.menu.file.mime == "video/hls-stream") { url += "/playlist.m3u8" } url += "?application=" + Model.application; url += "&token=" + token copyToClipboard(url) ApplicationView.displayMessage("url was copy to clipboard...", 3000) // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) }) } this.downloadMenuItem.action = () => { // Here I will create an archive from the selected files and dowload it... let files = []; let globule = null; for (var key in this.selected) { files.push(this.selected[key].path) globule = this.selected[key].globule } if (files.length > 0) { generatePeerToken(globule, token => { // Create a tempory name... let uuid = "_" + uuidv4().split("-").join("_").split("@").join("_"); this._file_explorer_.displayWaitMessage("create archive before for selected files...") createArchive(globule, files, uuid, path => { let url = getUrl(globule) path.split("/").forEach(item => { item = item.trim() if (item.length > 0) { url += "/" + encodeURIComponent(item) } }) url += "?application=" + Model.application if (token) { url += "&token=" + token } // Download the file... this._file_explorer_.displayWaitMessage("start download archive " + path) console.log(url) downloadFileHttp(url, uuid + ".tar.gz", () => { // Now I will remove the file from the server.... this._file_explorer_.displayWaitMessage("remove archive " + path) deleteFile(globule, path, () => { this._file_explorer_.resume() }, err => { ApplicationView.displayMessage(err, 3000); this._file_explorer_.resume() }, token) }, token) }, err => { ApplicationView.displayMessage(err, 3000); this._file_explorer_.resume() }, token) }) } else { let path = this.menu.file.path let name = path.substring(path.lastIndexOf("/") + 1) let globule = this.menu.file.globule // if the file is a directory I will create archive and download it. if (this.menu.file.isDir) { generatePeerToken(globule, token => { this._file_explorer_.displayWaitMessage("create archive before for " + this.menu.file.path) createArchive(globule, [path], name, path_ => { let url = getUrl(globule) path_.split("/").forEach(item => { item = item.trim() if (item.length > 0) { url += "/" + encodeURIComponent(item) } }) url += "?application=" + Model.application if (token) { url += "&token=" + token } // Download the file... this._file_explorer_.displayWaitMessage("start download " + name + ".tar.gz") downloadFileHttp(url, name + ".tar.gz", () => { // Now I will remove the file from the server.... deleteFile(globule, path_, () => { this._file_explorer_.resume() this.selected = {} // clear up selected files. }, err => { ApplicationView.displayMessage(err, 3000); this._file_explorer_.resume(); this.selected = {} }, token) }, token) }, err => { ApplicationView.displayMessage(err, 3000); this._file_explorer_.resume(); this.selected = {} }, token) }) } else { // simply download the file. generatePeerToken(globule, token => { let url = getUrl(globule) path.split("/").forEach(item => { item = item.trim() if (item.length > 0) { url += "/" + encodeURIComponent(item) } }) url += "?application=" + Model.application if (token) { url += "&token=" + token } downloadFileHttp(url, name, () => { // Now I will remove the file from the server.... this.selected = {} }, token), err => { ApplicationView.displayMessage(err, 3000); this.selected = {} } }) } } // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.deleteMenuItem.action = () => { let files = [] let fileList = "" for (var fileName in this.selected) { let file = this.selected[fileName] if (file.lnk) { if (!file.name.endsWith(".lnk")) { file = file.lnk // here I will delete the lnk and not the original file. } } fileList += `<div>${file.path}</div>` files.push(file) } // if not checked but selected with menu... if (fileList.length == 0) { let file = this.menu.file if (file.lnk) { if (!file.name.endsWith(".lnk")) { file = file.lnk // here I will delete the lnk and not the original file. } } fileList += `<div>${file.path}</div>` files.push(file) } let toast = ApplicationView.displayMessage( ` <style> #yes-no-files-delete-box{ display: flex; flex-direction: column; } #yes-no-files-delete-box globular-files-card{ padding-bottom: 10px; } #yes-no-files-delete-box div{ display: flex; padding-bottom: 10px; } </style> <div id="yes-no-files-delete-box"> <div>Your about to delete files</div> <div style="display: flex; flex-direction: column;"> ${fileList} </div> <div>Is it what you want to do? </div> <div style="justify-content: flex-end;"> <paper-button raised id="yes-delete-files">Yes</paper-button> <paper-button raised id="no-delete-files">No</paper-button> </div> </div> `, 15 * 1000 // 15 sec... ); let yesBtn = document.querySelector("#yes-delete-files") let noBtn = document.querySelector("#no-delete-files") // On yes yesBtn.onclick = () => { toast.dismiss(); let success = () => { ApplicationView.displayMessage( `<iron-icon icon='delete' style='margin-right: 10px;'></iron-icon><div> Files are now deleted! </div>`, 3000 ); this.selected = {} } let index = 0; let deleteFile_ = () => { let f = files[index] f.path = f.path.split("\\").join("/") let path = f.path.substring(0, f.path.lastIndexOf("/")) index++ let globule = this._file_explorer_.globule if (f.isDir) { generatePeerToken(globule, token => { this._file_explorer_.globule.fileService.getPublicDirs(new GetPublicDirsRequest, { application: Application.application, domain: this._file_explorer_.globule.domain, token: token }) .then(rsp => { // if the dir is public I will remove it entry from the list and keep the directory... let dirs = rsp.getDirsList() if (dirs.includes(f.path)) { const rqst = new RemovePublicDirRequest rqst.setPath(f.path) generatePeerToken(globule, token => { globule.fileService.removePublicDir(rqst, { application: Application.application, domain: globule.domain, token: token }) .then(rsp => { delete dirs[getUuidByString(this._file_explorer_.globule.domain + "@/public")] Model.publish("reload_dir_event", "/public", false); }) .catch(err => { ApplicationView.displayMessage(err, 3000) }) }) } else { generatePeerToken(globule, token => { deleteDir(globule, f.path, () => { delete dirs[getUuidByString(this._file_explorer_.globule.domain + "@" + path)] this._file_explorer_.globule.eventHub.publish("reload_dir_event", path, false); if (index < Object.keys(this.selected).length) { deleteFile_() } else { success() } }, err => { ApplicationView.displayMessage(err, 3000) }, token) }) } }) }) } else { deleteFile(globule, f.path, () => { delete dirs[getUuidByString(this._file_explorer_.globule.domain + "@" + path)] Model.publish("reload_dir_event", path, false); if (index < Object.keys(this.selected).length) { deleteFile_() } else { success() } }, err => { ApplicationView.displayMessage(err, 3000) }) } } // start file deletion... deleteFile_() } noBtn.onclick = () => { toast.dismiss(); } // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.renameMenuItem.action = () => { // Display the rename input... this.menu.rename() // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.fileInfosMenuItem.action = () => { Model.eventHub.publish(`display_file_infos_${this._file_explorer_.id}_event`, this.menu.file, true) // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } this.titleInfosMenuItem.action = () => { // So here I will create a new permission manager object and display it for the given file. let file = this.menu.file if (file.videos || file.titles || file.audios) { Model.eventHub.publish(`display_media_infos_${this._file_explorer_.id}_event`, file, true) } else { if (file.mime.startsWith("video") || file.isDir) { getVideoInfo(file, (videos) => { if (videos.length > 0) { Model.eventHub.publish(`display_media_infos_${this._file_explorer_.id}_event`, file, true) // Remove it from it parent... if (this.menu.parentNode) { // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } } else { // get the title infos... getTitleInfo(file, (titles) => { if (titles.length > 0) { Model.eventHub.publish(`display_media_infos_${this._file_explorer_.id}_event`, file, true) if (this.menu.parentNode) { // Remove it from it parent... this.menu.close() this.menu.parentNode.removeChild(this.menu) } } else { // So here no video or title info exist for that file I will propose to the user // to create a new video infos... // Here I will ask the user for confirmation before actually delete the contact informations. let toast = ApplicationView.displayMessage( ` <style> #yes-no-create-video-info-box{ display: flex; flex-direction: column; } #yes-no-create-video-info-box globular-picture-card{ padding-bottom: 10px; } #yes-no-create-video-info-box div{ display: flex; padding-bottom: 10px; } </style> <div id="yes-no-create-video-info-box"> <div style="margin-bottom: 10px;">No informations was associated with that video file</div> <img style="max-height: 100px; object-fit: contain; width: 100%;" src="${file.thumbnail}"></img> <span style="font-size: .95rem; text-align: center;">${file.path.substring(file.path.lastIndexOf("/") + 1)}</span> <div style="margin-top: 10px;">Do you want to create video/movie information? </div> <div style="justify-content: flex-end;"> <paper-button raised id="yes-create-video-info">Yes</paper-button> <paper-button raised id="no-create-video-info">No</paper-button> </div> </div> `, 60 * 1000 // 60 sec... ); let yesBtn = document.querySelector("#yes-create-video-info") let noBtn = document.querySelector("#no-create-video-info") // On yes yesBtn.onclick = () => { // So here I will ask witch type of information the user want's to generate, title, video or audio... toast.dismiss(); let toast_ = ApplicationView.displayMessage( ` <style> </style> <div style="display: flex; flex-direction: column;"> <div> Please select the kind of information to create... </div> <img style="max-height: 100px; object-fit: contain; width: 100%; margin-top: 15px;" src="${file.thumbnail}"></img> <paper-radio-group selected="video-option" style="margin-top: 15px;"> <paper-radio-button id="video-option" name="video-option"><span title="simple video ex. youtube">Video</span></paper-radio-button> <paper-radio-button id="title-option" name="title-option"><span title="Movie">Movie or TV Episode/Serie</span></paper-radio-button> </paper-radio-group> <div st