file explorer working
but can't open files externally
8
.gitignore
vendored
@ -1 +1,7 @@
|
|||||||
node_modules
|
.DS_Store
|
||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
|
thumbs.db
|
||||||
|
yarn-error.log
|
||||||
|
.yarnclean
|
||||||
|
.vscode
|
||||||
|
14
CHANGELOG.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Changelog
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
### Changed
|
||||||
|
### Deprecated
|
||||||
|
### Removed
|
||||||
|
### Fixed
|
||||||
|
### Security
|
15
README.md
@ -1 +1,14 @@
|
|||||||
Gestionnaire de fichier en construction!
|
# Delta File Manager
|
||||||
|
|
||||||
|
A WIP project By [Avior](https://delta-wings.net) <florian.bouillon@delta-wings.net> (Gitlab account: [Gitlab](https://gitlab.com/aviortheking))
|
||||||
|
|
||||||
|
this project is licensed under the [MIT License](./LICENSE.md)
|
||||||
|
|
||||||
|
|
||||||
|
## Icons
|
||||||
|
|
||||||
|
I used the icons from [Feather icons](https://feathericons.com) (Github link: [Github](https://github.com/feathericons/feather)) licensed under the [MIT License](https://github.com/feathericons/feather/blob/master/LICENSE)
|
||||||
|
|
||||||
|
## issues
|
||||||
|
|
||||||
|
- Actually we need to manually delete three lines from the package nunjuck loader to be able to run the dev server (index.js #21-23)
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
# import Gitlab from 'gitlab'
|
|
||||||
{ ProjectBundle } = require('gitlab')
|
|
||||||
|
|
||||||
options = {
|
|
||||||
url: 'https://gitlab.com'
|
|
||||||
token: ''
|
|
||||||
}
|
|
||||||
|
|
||||||
gitlab = new ProjectBundle(options)
|
|
||||||
# this is actually a test
|
|
||||||
forceRefresh = true
|
|
||||||
|
|
||||||
user = undefined
|
|
||||||
getUser = () ->
|
|
||||||
if user is undefined or forceRefresh
|
|
||||||
user = await gitlab.Users.current()
|
|
||||||
user
|
|
||||||
|
|
||||||
projects = undefined
|
|
||||||
getProjects = () ->
|
|
||||||
console.log "loading Projects!"
|
|
||||||
|
|
||||||
if projects is undefined or forceRefresh
|
|
||||||
console.log "loading Projects!"
|
|
||||||
|
|
||||||
projects = await gitlab.Projects.all { membership: true }
|
|
||||||
console.log projects
|
|
||||||
projects
|
|
||||||
|
|
||||||
project = {}
|
|
||||||
getProject = (projectId) ->
|
|
||||||
if projectId isnt undefined
|
|
||||||
if project[projectId] is undefined or forceRefresh
|
|
||||||
project[projectId] = await (gitlab.Projects).show projectId
|
|
||||||
return project[projectId]
|
|
||||||
return undefined
|
|
||||||
|
|
||||||
projectTree = {}
|
|
||||||
getProjectTree = (projectId) ->
|
|
||||||
if projectId isnt undefined
|
|
||||||
if projectTree[projectId] is undefined or forceRefresh
|
|
||||||
projectTree[projectId] = await gitlab.Repositories.tree(projectId, { recursive: true }).catch (e) ->
|
|
||||||
console.log "pouet"
|
|
||||||
console.log ed
|
|
||||||
|
|
||||||
return projectTree[projectId]
|
|
||||||
return undefined
|
|
||||||
|
|
||||||
loadProjects = (parent) ->
|
|
||||||
for el in await getProjects()
|
|
||||||
tr = document.createElement 'tr'
|
|
||||||
name = el.name_with_namespace.split '/'
|
|
||||||
name.pop()
|
|
||||||
td = "<td>" + el.id + "</td><td>" + el.name + "</td><td>" + name.join(" -> ") + "</td>"
|
|
||||||
tr.innerHTML = td
|
|
||||||
tr.setAttribute 'data-id', el.id
|
|
||||||
tr.addEventListener 'click', (event) ->
|
|
||||||
console.log event
|
|
||||||
loadProjectTree document.querySelector(".tree"), event.target.parentNode.getAttribute("data-id")
|
|
||||||
return
|
|
||||||
parent.appendChild tr
|
|
||||||
return
|
|
||||||
|
|
||||||
loadProjectTree = (parent, projectId) ->
|
|
||||||
parent.innerHTML = ''
|
|
||||||
for el in await getProjectTree projectId
|
|
||||||
path = el.path.split "/"
|
|
||||||
path.pop()
|
|
||||||
tempParent = parent
|
|
||||||
if el.type is "tree" then element = "<ul data-path=\"" + el.name + "\"></ul>"
|
|
||||||
else element = "<li>" + el.name + "</li>"
|
|
||||||
if path.length > 1
|
|
||||||
tempParent = parent.querySelector "[data-path=\"" + path.pop() + "\"]"
|
|
||||||
tempParent.innerHTML += element
|
|
||||||
for el in parent.querySelectorAll("[data-path]")
|
|
||||||
li = document.createElement "li"
|
|
||||||
text = document.createTextNode el.getAttribute("data-path") + "/"
|
|
||||||
li.appendChild text
|
|
||||||
li.classList.add "folder"
|
|
||||||
el.parentNode.insertBefore(li, el)
|
|
||||||
return
|
|
||||||
|
|
||||||
loadProjects(document.querySelector('.projectList'))
|
|
||||||
# console.log projects
|
|
31
index.html
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Hello World!</title>
|
|
||||||
<link rel="stylesheet" href="./styles.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>File Name</th>
|
|
||||||
<th>Modified</th>
|
|
||||||
<th>Size</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</main>
|
|
||||||
<script>
|
|
||||||
// You can also require other files to run in this process
|
|
||||||
require('./renderer.js');
|
|
||||||
// getProjects();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
56
main.js
@ -1,56 +0,0 @@
|
|||||||
// Modules to control application life and create native browser window
|
|
||||||
const {app, BrowserWindow} = require('electron')
|
|
||||||
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
|
||||||
let mainWindow
|
|
||||||
|
|
||||||
function createWindow () {
|
|
||||||
// Create the browser window.
|
|
||||||
mainWindow = new BrowserWindow({
|
|
||||||
width: 800,
|
|
||||||
height: 600,
|
|
||||||
webPreferences: {
|
|
||||||
nodeIntegration: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// and load the index.html of the app.
|
|
||||||
mainWindow.loadFile('index.html')
|
|
||||||
|
|
||||||
// Open the DevTools.
|
|
||||||
// mainWindow.webContents.openDevTools()
|
|
||||||
|
|
||||||
// Emitted when the window is closed.
|
|
||||||
mainWindow.on('closed', function () {
|
|
||||||
// Dereference the window object, usually you would store windows
|
|
||||||
// in an array if your app supports multi windows, this is the time
|
|
||||||
// when you should delete the corresponding element.
|
|
||||||
mainWindow = null
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
|
||||||
// initialization and is ready to create browser windows.
|
|
||||||
// Some APIs can only be used after this event occurs.
|
|
||||||
app.on('ready', createWindow)
|
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
|
||||||
app.on('window-all-closed', function () {
|
|
||||||
// On macOS it is common for applications and their menu bar
|
|
||||||
// to stay active until the user quits explicitly with Cmd + Q
|
|
||||||
if (process.platform !== 'darwin') {
|
|
||||||
app.quit()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.on('activate', function () {
|
|
||||||
// On macOS it's common to re-create a window in the app when the
|
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (mainWindow === null) {
|
|
||||||
createWindow()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// In this file you can include the rest of your app's specific main process
|
|
||||||
// code. You can also put them in separate files and require them here.
|
|
66
package.json
@ -1,18 +1,64 @@
|
|||||||
{
|
{
|
||||||
"name": "delta-file-manager",
|
"name": "delta-file-manager",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "A customizable fiel manager",
|
|
||||||
"main": "main.js",
|
|
||||||
"scripts": {
|
|
||||||
"start": "electron ."
|
|
||||||
},
|
|
||||||
"author": "Avior",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"homepage": "https://delta-wings.net/dfm",
|
||||||
"electron": "^4.0.6"
|
"author": {
|
||||||
|
"name": "Florian bouillon",
|
||||||
|
"email": "florian.bouillon@delta-wings.net",
|
||||||
|
"url": "https://delta-wings.net/"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "electron-webpack dev",
|
||||||
|
"compile": "electron-webpack",
|
||||||
|
"dist": "yarn compile && electron-builder",
|
||||||
|
"dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null"
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"appId": "net.deltawings.deltafilemanager",
|
||||||
|
"productName": "Delta File Manager",
|
||||||
|
"copyright": "Copyright @ 2019 ${author}",
|
||||||
|
"win": {
|
||||||
|
"target": [
|
||||||
|
{
|
||||||
|
"target": "nsis",
|
||||||
|
"arch": [
|
||||||
|
"x64",
|
||||||
|
"ia32"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nsis": {
|
||||||
|
"oneClick": false
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"target": [
|
||||||
|
{
|
||||||
|
"target": "deb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "AppImage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ts-node": "^8.0.2",
|
"@types/nunjucks": "^3.1.1",
|
||||||
"typescript": "^3.3.3333"
|
"@types/sharp": "^0.21.3",
|
||||||
|
"source-map-support": "^0.5.10"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "4.0.1",
|
||||||
|
"electron-builder": "20.38.4",
|
||||||
|
"electron-webpack": "^2.6.2",
|
||||||
|
"electron-webpack-ts": "^3.1.1",
|
||||||
|
"node-sass": "^4.11.0",
|
||||||
|
"nunjucks": "^3.2.0",
|
||||||
|
"nunjucks-loader": "^3.0.0",
|
||||||
|
"sass-loader": "^7.1.0",
|
||||||
|
"typescript": "^3.3.3333",
|
||||||
|
"webpack": "4.28.4",
|
||||||
|
"webpack-build-notifier": "^0.1.30"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
require("ts-node").register();
|
|
||||||
require("./src/renderer");
|
|
30
src/common/Actions.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import DeltaFile from "./DeltaFile";
|
||||||
|
import {
|
||||||
|
sep
|
||||||
|
} from 'path';
|
||||||
|
import {
|
||||||
|
getDataFolder
|
||||||
|
} from "./Functions";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
class Actions { //WIP
|
||||||
|
|
||||||
|
public deleteFile(file: DeltaFile) {
|
||||||
|
let res = getDataFolder() + sep + "trash" + sep + "files" + sep + file.name;
|
||||||
|
if(fs.existsSync(res)) {
|
||||||
|
//rename and add it
|
||||||
|
} else {
|
||||||
|
//move the folder/file in the trash
|
||||||
|
//write to infos.json about the deleted file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public emptyBin() {
|
||||||
|
//delete all files in the trash
|
||||||
|
}
|
||||||
|
|
||||||
|
//file is the file name in the trash
|
||||||
|
public restoreDeletedFile(file: string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
112
src/common/DeltaFile.ts
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import {
|
||||||
|
sep
|
||||||
|
} from 'path';
|
||||||
|
const icons = require("./icons.json");
|
||||||
|
//TODO handle file redirection when no link is given
|
||||||
|
|
||||||
|
|
||||||
|
export default class DeltaFile {
|
||||||
|
|
||||||
|
_name: string = "";
|
||||||
|
_modetime: Date | string = "--";
|
||||||
|
_size: number | string = "--";
|
||||||
|
_path: string = "";
|
||||||
|
_type: number = 0; // 0 = directory, 1 = file;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
public static loadFileFromElements(name: string, path: string, type: boolean = false, modetime?: Date, size?: number): DeltaFile {
|
||||||
|
let file = new DeltaFile();
|
||||||
|
if(type) file.modetime = (modetime != undefined) ? modetime : "--";
|
||||||
|
file.name = name;
|
||||||
|
file.path = path;
|
||||||
|
if(type) file.type = type ? 1 : 0;
|
||||||
|
if(type) file.size = (size != undefined) ? size : "--";
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static loadFileFromPath(path: string): DeltaFile | undefined {
|
||||||
|
let file = new DeltaFile();
|
||||||
|
try {
|
||||||
|
var stat = fs.statSync(path);
|
||||||
|
} catch (error) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
let name = path.split(sep).pop();
|
||||||
|
|
||||||
|
if(name == undefined) return undefined;
|
||||||
|
|
||||||
|
file.type = stat.isDirectory() ? 0 : 1;
|
||||||
|
if(file.type != 0) {
|
||||||
|
file.modetime = stat.mtime;
|
||||||
|
file.size = stat.size;
|
||||||
|
}
|
||||||
|
file.path = path;
|
||||||
|
file.name = name;
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public get name() : string {return this._name}
|
||||||
|
public set name(v : string) {this._name = v}
|
||||||
|
|
||||||
|
public get modetime(): Date | string {return this._modetime}
|
||||||
|
public set modetime(v: Date | string) {this._modetime = v}
|
||||||
|
public formatTime(): string {
|
||||||
|
if(typeof this.modetime === "string") return this.modetime;
|
||||||
|
return this.modetime.toISOString()
|
||||||
|
.replace(/T/, ' ')
|
||||||
|
.replace(/\..+/, '')
|
||||||
|
.replace(":", "/");
|
||||||
|
}
|
||||||
|
// 2019/03/09 04:14:01
|
||||||
|
|
||||||
|
public get size(): number | string {return this._size}
|
||||||
|
public set size(v: number | string) {this._size = v}
|
||||||
|
public formatSize(): string {
|
||||||
|
if(typeof this.size === "string") return this.size;
|
||||||
|
if(this.size === 0) return "0 bytes";
|
||||||
|
let sep = 1024, d = 2;
|
||||||
|
let ent = ["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];
|
||||||
|
let f = Math.floor(Math.log(this.size)/Math.log(sep));
|
||||||
|
return parseFloat((this.size / Math.pow(sep, f)).toFixed(d)) + " " + ent[f];
|
||||||
|
}
|
||||||
|
|
||||||
|
public get path(): string {return this._path}
|
||||||
|
public set path(v: string) {this._path = v}
|
||||||
|
|
||||||
|
public get type(): number {return this._type}
|
||||||
|
public set type(v: number) {this._type = v}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getThumbnail
|
||||||
|
*/
|
||||||
|
public getThumbnail(): string | undefined {
|
||||||
|
//if file load picture
|
||||||
|
//if folder see location(/home/___/pictures, /home) or name (like git, node_modules)
|
||||||
|
if(this.type == 0) {
|
||||||
|
for (const el in icons.folder.name) {
|
||||||
|
if (icons.folder.name.hasOwnProperty(el)) {
|
||||||
|
const element = icons.folder.name[el];
|
||||||
|
if(el == this.name.toLowerCase()) return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(icons.folder.path[this.path] != undefined) return icons.folder.path[this.path];
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
let ext = this.path.split("/").pop();
|
||||||
|
if(ext == undefined) return undefined;
|
||||||
|
ext = ext.split(".").pop();
|
||||||
|
console.log(ext);
|
||||||
|
if(ext == undefined) return undefined;
|
||||||
|
let imgExt = ["jpg", "jpeg", "png"];
|
||||||
|
if(imgExt.includes(ext) ) return "file://" + this.path;
|
||||||
|
if(icons.file.extension[ext] != undefined) return icons.file.extension[ext];
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/common/Functions.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {
|
||||||
|
sep
|
||||||
|
} from 'path';
|
||||||
|
|
||||||
|
const folderName = "delta-file-manager";
|
||||||
|
|
||||||
|
export function getDataFolder() {
|
||||||
|
let platform = process.platform;
|
||||||
|
if(platform == "win32") {
|
||||||
|
return process.env.APP_DATA + sep + folderName;
|
||||||
|
} else if(platform == "darwin") {
|
||||||
|
return process.env.HOME + sep + "Library/Preferences" + sep + folderName;
|
||||||
|
} else if(platform == "linux") {
|
||||||
|
return process.env.HOME + sep + ".config" + sep + folderName;
|
||||||
|
} else return undefined;
|
||||||
|
}
|
31
src/common/icons.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"folder": {
|
||||||
|
"name": {
|
||||||
|
"..": "icons/chevron-left.svg",
|
||||||
|
"git": "icons/github.svg",
|
||||||
|
".git": "icons/github.svg",
|
||||||
|
"pictures": "icons/image.svg",
|
||||||
|
"music": "icons/music.svg",
|
||||||
|
"videos": "icons/video.svg",
|
||||||
|
"public": "icons/users.svg",
|
||||||
|
"downloads": "icons/download.svg",
|
||||||
|
".vscode": "icons/code.svg",
|
||||||
|
"node_modules": "icons/package.svg",
|
||||||
|
".config": "icons/settings.svg",
|
||||||
|
"src": "icons/code.svg"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"/home": "icons/home.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"name": {
|
||||||
|
".gitlab-ci.yaml": "icons/gitlab.svg"
|
||||||
|
},
|
||||||
|
"extension": {
|
||||||
|
"code-workspace": "icons/code.svg",
|
||||||
|
"coffee": "icons/coffee.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
src/main/index.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
import { app, BrowserWindow } from 'electron'
|
||||||
|
import * as path from 'path'
|
||||||
|
import { format as formatUrl } from 'url'
|
||||||
|
|
||||||
|
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
|
// global reference to mainWindow (necessary to prevent window from being garbage collected)
|
||||||
|
let mainWindow
|
||||||
|
|
||||||
|
function createMainWindow() {
|
||||||
|
const window = new BrowserWindow({
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isDevelopment) {
|
||||||
|
window.webContents.openDevTools()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDevelopment) {
|
||||||
|
window.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}`)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.loadURL(formatUrl({
|
||||||
|
pathname: path.join(__dirname, 'index.html'),
|
||||||
|
protocol: 'file',
|
||||||
|
slashes: true
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
window.on('closed', () => {
|
||||||
|
mainWindow = null
|
||||||
|
})
|
||||||
|
|
||||||
|
window.webContents.on('devtools-opened', () => {
|
||||||
|
window.focus()
|
||||||
|
setImmediate(() => {
|
||||||
|
window.focus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
|
||||||
|
// quit application when all windows are closed
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
// on macOS it is common for applications to stay open until the user explicitly quits
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
// on macOS it is common to re-create a window even after all windows have been closed
|
||||||
|
if (mainWindow === null) {
|
||||||
|
mainWindow = createMainWindow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// create main BrowserWindow when electron is ready
|
||||||
|
app.on('ready', () => {
|
||||||
|
mainWindow = createMainWindow()
|
||||||
|
})
|
@ -1,69 +0,0 @@
|
|||||||
import { sep } from 'path';
|
|
||||||
import { Stats } from "fs";
|
|
||||||
const fs = require("fs");
|
|
||||||
import { shell } from 'electron';
|
|
||||||
|
|
||||||
const loader = document.querySelector("tbody");
|
|
||||||
const rootPath = '/';
|
|
||||||
|
|
||||||
|
|
||||||
const loadFolder = (path: string) => {
|
|
||||||
loader.innerHTML = "";
|
|
||||||
|
|
||||||
if(path != rootPath) {
|
|
||||||
let pt = path.split("/");
|
|
||||||
pt.pop();
|
|
||||||
console.log(rootPath);
|
|
||||||
console.log(pt.join("/"));
|
|
||||||
let pouet = "" == pt.join("/") ? sep : pt.join("/");
|
|
||||||
addElement("..", pouet);
|
|
||||||
}
|
|
||||||
fs.readdir(path, (err, items) => {
|
|
||||||
for (const item of items) {
|
|
||||||
console.log(path);
|
|
||||||
let it = path == "/" ? path + item : path + sep + item;
|
|
||||||
fs.stat(it, (err, stat) => {
|
|
||||||
// console.log(err);
|
|
||||||
let pth = path == "/" ? path + item : path + sep + item;
|
|
||||||
addElement(item, pth, stat);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function addElement(filename: string, path: string, stat: Stats = null) {
|
|
||||||
let mtime = stat != null ? stat.mtime : null;
|
|
||||||
let classe = stat != null ? (stat.isDirectory() ? "folder" : "file") : "folder";
|
|
||||||
if(stat != null) var month = (mtime.getUTCMonth() + 1) > 10 ? "0" + (mtime.getUTCMonth() + 1) : "" + (mtime.getUTCMonth() + 1);
|
|
||||||
else var month = "0";
|
|
||||||
let time = stat == null || stat.isDirectory() ? "--" : mtime.getUTCFullYear() + "/" + month + "/" + mtime.getUTCDate();
|
|
||||||
let bytes = stat == null || stat.isDirectory() ? "--" : formatBytes(stat.size);
|
|
||||||
let tr = document.createElement("tr");
|
|
||||||
tr.classList.add(classe);
|
|
||||||
tr.setAttribute("data-file", path);
|
|
||||||
tr.addEventListener("click", function() {
|
|
||||||
if(this.classList.contains("folder")) loadFolder(this.getAttribute("data-file"));
|
|
||||||
else loadFile(this.getAttribute("data-file"));
|
|
||||||
});
|
|
||||||
for (const el of [filename, time, bytes]) {
|
|
||||||
let td = document.createElement("td");
|
|
||||||
td.innerText = el;
|
|
||||||
tr.appendChild(td);
|
|
||||||
}
|
|
||||||
loader.appendChild(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatBytes(integ: number): string {
|
|
||||||
if(integ === 0) return "0 bytes";
|
|
||||||
let sep = 1024, d = 2;
|
|
||||||
let ent = ["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];
|
|
||||||
let f = Math.floor(Math.log(integ)/Math.log(sep));
|
|
||||||
return parseFloat((integ / Math.pow(sep, f)).toFixed(d)) + " " + ent[f];
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadFile(file: string) {
|
|
||||||
shell.openItem(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadFolder("/");
|
|
38
src/renderer/fileRenderers/blocks.njk
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{% extends "../index.njk" %}
|
||||||
|
|
||||||
|
{% block filelist %}
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
{% for file in files %}
|
||||||
|
{% if file.type == "0" %}
|
||||||
|
{% set thumb = file.getThumbnail() %}
|
||||||
|
{% if thumb != undefined %}
|
||||||
|
<div class="grid-item folder" data-file={{ file.path }} style="background-image: url({{ thumb }})">
|
||||||
|
{% else %}
|
||||||
|
<div class="grid-item folder" data-file={{ file.path }}>
|
||||||
|
{% endif %}
|
||||||
|
{{file.name}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
{% for file in files %}
|
||||||
|
{% if file.type == "1" %}
|
||||||
|
<div class="grid-item file" data-file="{{ file.path }}">
|
||||||
|
{% if file.getThumbnail() != undefined %}
|
||||||
|
<div class="item-preview" style='background-image: url("{{ file.getThumbnail() }}")'>
|
||||||
|
{% else %}
|
||||||
|
<div class="item-preview null">
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="item-name">{{ file.name }}</div>
|
||||||
|
<div class="item-size">{{ file.formatSize() }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
23
src/renderer/fileRenderers/list.njk
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{% extends "../index.njk" %}
|
||||||
|
|
||||||
|
{% block filelist %}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Last Time modified</th>
|
||||||
|
<th>Size</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for file in files %}
|
||||||
|
<tr data-file="{{ file.path }}">
|
||||||
|
<td>{{ file.name }}</td>
|
||||||
|
<td>{{ file.formatTime() }}</td>
|
||||||
|
<td>{{ file.formatSize() }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
5
src/renderer/index.njk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<aside>
|
||||||
|
</aside>
|
||||||
|
<main>
|
||||||
|
{% block filelist %}{% endblock %}
|
||||||
|
</main>
|
52
src/renderer/index.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// import { render as nunjuckRender} from 'nunjucks';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { sep } from 'path';
|
||||||
|
import DeltaFile from '../common/DeltaFile';
|
||||||
|
import './style.scss';
|
||||||
|
import { Template } from 'nunjucks';
|
||||||
|
|
||||||
|
const tpl: Template = require("./fileRenderers/blocks.njk");
|
||||||
|
|
||||||
|
const rootPath = "/";
|
||||||
|
|
||||||
|
const loadFolder = (path: string) => {
|
||||||
|
let results = [];
|
||||||
|
if(path != rootPath) {
|
||||||
|
let pt = path.split("/");
|
||||||
|
pt.pop();
|
||||||
|
let pouet = "" == pt.join("/") ? sep : pt.join("/");
|
||||||
|
results.push(DeltaFile.loadFileFromElements("..", pouet, false));
|
||||||
|
}
|
||||||
|
let items = fs.readdirSync(path);
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
let pth = path == "/" ? path + item : path + sep + item;
|
||||||
|
let file = DeltaFile.loadFileFromPath(pth);
|
||||||
|
if(file != undefined)results.push(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const showFolder = (folder: string) => {
|
||||||
|
let app = document.getElementById("app");
|
||||||
|
if(app == undefined) app = document.body;
|
||||||
|
var els = loadFolder(folder);
|
||||||
|
app.innerHTML = tpl.render({files: els});
|
||||||
|
app.querySelectorAll("[data-file]").forEach((el) => {
|
||||||
|
el.addEventListener("click", function(this: HTMLElement) {
|
||||||
|
// console.log(this);
|
||||||
|
let folder = this.getAttribute("data-file");
|
||||||
|
if(folder != null) showFolder(folder);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
showFolder("/");
|
||||||
|
|
||||||
|
// function loadFile(file: string) {
|
||||||
|
// shell.openItem(file);
|
||||||
|
// }
|
||||||
|
// console.log(render("index.njk"));
|
||||||
|
// console.log(loadFolder("/"));
|
110
src/renderer/style.scss
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
grid-gap: 30px;
|
||||||
|
place-items: stretch;
|
||||||
|
// justify-content: center;
|
||||||
|
padding: 30px;
|
||||||
|
@media (max-width: 1190px) {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
}
|
||||||
|
@media (max-width: 960px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
@media (max-width: 721px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
@media (max-width: 502px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .grid-item {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space:nowrap;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
justify-self: stretch;
|
||||||
|
min-width: 150px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.folder {
|
||||||
|
background-image: url(../../static/icons/folder.svg);
|
||||||
|
background-size: 30px;
|
||||||
|
background-position-y: center;
|
||||||
|
background-position-x: 10px;
|
||||||
|
// min-width: 150px;
|
||||||
|
height: 45px;
|
||||||
|
line-height: 45px;
|
||||||
|
border: 1px solid rgba(0,0,0,.1);
|
||||||
|
padding: 10px .5%;
|
||||||
|
padding-left: calc(.5% + 45px);
|
||||||
|
border-radius: 10px;
|
||||||
|
color: rgba(0, 0, 0, .8);
|
||||||
|
|
||||||
|
transition-property: box-shadow, transform, background-color;
|
||||||
|
transition-duration: 200ms;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0px 5px 0px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
box-shadow: 0px -0px 0px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.file {
|
||||||
|
border-radius: 10px;
|
||||||
|
transition-property: box-shadow, transform, background-color;
|
||||||
|
transition-duration: 200ms;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0px 5px 0px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
box-shadow: 0px -0px 0px 0px rgba(0, 0, 0, 0.3);
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
.item-preview {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
|
height: 150px;
|
||||||
|
box-shadow: inset 0 0 20px 0 rgba(0, 0, 0, .1);
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
&.null {
|
||||||
|
background-image: url(../../static/icons/file.svg);
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
margin: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
color: rgba(0, 0, 0, .8)
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-size {
|
||||||
|
color: rgba(0, 0, 0, .5);
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
user-select: none;
|
||||||
|
}
|
1
static/icons/chevron-left.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-left"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
After Width: | Height: | Size: 270 B |
1
static/icons/code.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-code"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>
|
After Width: | Height: | Size: 307 B |
1
static/icons/coffee.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-coffee"><path d="M18 8h1a4 4 0 0 1 0 8h-1"></path><path d="M2 8h16v9a4 4 0 0 1-4 4H6a4 4 0 0 1-4-4V8z"></path><line x1="6" y1="1" x2="6" y2="4"></line><line x1="10" y1="1" x2="10" y2="4"></line><line x1="14" y1="1" x2="14" y2="4"></line></svg>
|
After Width: | Height: | Size: 447 B |
1
static/icons/download.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-download"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
After Width: | Height: | Size: 370 B |
1
static/icons/file.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
|
After Width: | Height: | Size: 337 B |
1
static/icons/folder.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-folder"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>
|
After Width: | Height: | Size: 311 B |
1
static/icons/github.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-github"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
|
After Width: | Height: | Size: 527 B |
1
static/icons/gitlab.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-gitlab"><path d="M22.65 14.39L12 22.13 1.35 14.39a.84.84 0 0 1-.3-.94l1.22-3.78 2.44-7.51A.42.42 0 0 1 4.82 2a.43.43 0 0 1 .58 0 .42.42 0 0 1 .11.18l2.44 7.49h8.1l2.44-7.51A.42.42 0 0 1 18.6 2a.43.43 0 0 1 .58 0 .42.42 0 0 1 .11.18l2.44 7.51L23 13.45a.84.84 0 0 1-.35.94z"></path></svg>
|
After Width: | Height: | Size: 490 B |
1
static/icons/home.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
After Width: | Height: | Size: 332 B |
1
static/icons/icons.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
source : https://feathericons.com/
|
1
static/icons/image.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-image"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
|
After Width: | Height: | Size: 369 B |
1
static/icons/music.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-music"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle></svg>
|
After Width: | Height: | Size: 327 B |
1
static/icons/package.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-package"><path d="M12.89 1.45l8 4A2 2 0 0 1 22 7.24v9.53a2 2 0 0 1-1.11 1.79l-8 4a2 2 0 0 1-1.79 0l-8-4a2 2 0 0 1-1.1-1.8V7.24a2 2 0 0 1 1.11-1.79l8-4a2 2 0 0 1 1.78 0z"></path><polyline points="2.32 6.16 12 11 21.68 6.16"></polyline><line x1="12" y1="22.76" x2="12" y2="11"></line><line x1="7" y1="3.5" x2="17" y2="8.5"></line></svg>
|
After Width: | Height: | Size: 538 B |
1
static/icons/settings.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
After Width: | Height: | Size: 1011 B |
1
static/icons/users.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
|
After Width: | Height: | Size: 400 B |
1
static/icons/video.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-video"><polygon points="23 7 16 12 23 17 23 7"></polygon><rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect></svg>
|
After Width: | Height: | Size: 329 B |
@ -14,13 +14,18 @@ table th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table tr {
|
table tr {
|
||||||
border-bottom: 1px solid #212121;
|
border-bottom: 1px solid #aaa;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table tr td {
|
||||||
|
border-left: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
table tr td:first-child {
|
table tr td:first-child {
|
||||||
padding-left: 60px;
|
padding-left: 60px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
border-left: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
table tr.folder td:first-child {
|
table tr.folder td:first-child {
|
||||||
|
3
tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": "./node_modules/electron-webpack/tsconfig-base.json"
|
||||||
|
}
|