@@ -1,38 +1,68 @@
:root {
--windowTitlebarHeight: 5rem;
--windowTitlebarHeight: 8.7rem;
--window-titlebar-height: var(--windowTitlebarHeight);
--windowTitlebarColour: 53, 59, 72;
--window-titlebar-colour: var(--windowTitlebarColour);
--windowTitlebarColourLight: 63, 69, 82;
--window-titlebar-colour-light: var(--windowTitlebarColourLight);
}

#titlebar {
background-color: rgba(53, 59, 72, 1);
color: rgb(200, 200, 200);
background-color: rgba(var(--windowTitlebarColour), 1);
display: flex;
justify-content: space-between;
user-select: none;
-webkit-app-region: drag;
overflow: hidden;
position: relative;
width: 100vw;
height: var(--windowTitlebarHeight);
padding: .75rem;
padding-bottom: 0;
}

#appContainer:not(.fullscreen) #titlebar {
border-radius: var(--windowBorderRadius) var(--windowBorderRadius) 0 0;
background-color: rgba(53, 59, 72, .8);
background-color: rgba(var(--windowTitlebarColour), .8);
}

#titlebar>#titlebarMenu {
-webkit-app-region: no-drag;
background: none;
border: none;
width: 2.25rem;
height: 2.25rem;
padding: .33rem;
margin-right: .25rem;
border-radius: 2px;
}

#titlebar>#titlebarMenu:hover,
#titlebar>#titlebarMenu:focus {
background: rgb(var(--windowTitlebarColourLight));
cursor: pointer;
}

#titlebar>#titlebarMenu>img {
filter: invert(1);
width: 100%;
}

#titlebar>#titlebarIcon {
width: 1.5rem;
height: 1.5rem;
margin: .5rem;
margin: .25rem;
filter: invert(1);
opacity: .5;
}

#titlebar>#title {
font-size: 1rem;
font-weight: 500;
cursor: default;
padding: .5rem 1rem .5rem 0;
width: 100vw;
padding: .25rem 4rem .5rem .5rem;
opacity: .5;
color: white;
line-height: 1.75rem;
}

#titlebar>#titlebarButtons {
@@ -54,17 +84,20 @@
transition: all .1s ease;
}

#titlebar>#titlebarButtons>button:hover {
#titlebar>#titlebarButtons>button:hover,
#titlebar>#titlebarButtons>button:focus {
opacity: 1;
padding: .75rem;
}

#titlebar>#titlebarButtons>#minimise:hover {
#titlebar>#titlebarButtons>#minimise:hover,
#titlebar>#titlebarButtons>#minimise:focus {
background: url("../images/minimise.png") no-repeat center center;
background-size: 60%;
}

#titlebar>#titlebarButtons>#maximise:hover {
#titlebar>#titlebarButtons>#maximise:hover,
#titlebar>#titlebarButtons>#maximise:focus {
background: url("../images/maximise.png") no-repeat center center;
background-size: 60%;
}
@@ -73,7 +106,8 @@
margin-right: .25rem;
}

#titlebar>#titlebarButtons>#close:hover {
#titlebar>#titlebarButtons>#close:hover,
#titlebar>#titlebarButtons>#close:focus {
background: url("../images/close.png") no-repeat center center;
background-size: 60%;
}
@@ -2,7 +2,9 @@
background: #F9F9F9;
width: 100%;
height: calc(100% - var(--windowTitlebarHeight));
overflow-y: auto;
--scrollbarBorderRadius: 0;
--scrollbar-border-radius: var(--scrollbarBorderRadius);
display: flex;
}

#appContainer:not(.fullscreen) #viewport {
BIN +1.25 KB data/images/back.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +1.35 KB data/images/dirUp.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +985 Bytes data/images/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +801 Bytes data/images/menu.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

@@ -0,0 +1,13 @@
const quickfind = document.querySelector("#quickFind");

function rebuildQuickfind () {
const items = quickfind.querySelectorAll(".quickFindItem");
items.forEach((item, i) => {
item.setAttribute("tabindex", 0);
item.addEventListener("click", event => {
searchbar.value = item.dataset.url;
search(searchbar.value);
});
});
}
rebuildQuickfind();
@@ -0,0 +1,14 @@
const itemlist = document.querySelector("#itemList");
const minimalDistance = 200;

itemlist.addEventListener("scroll", event => {
const viewportBottom = itemlist.scrollTop + itemlist.clientHeight;
const windowBottom = itemlist.scrollHeight;
const distanceBetweenBottoms = windowBottom - viewportBottom;
if (distanceBetweenBottoms < minimalDistance) {
const factor = (minimalDistance - distanceBetweenBottoms) / minimalDistance * .425;
itemlist.style.setProperty("--scrollbarBorderRadius", `${factor}rem`);
}

//if search() itemlist.style.setProperty("--scrollbarBorderRadius", 0);
});
@@ -1,34 +1,72 @@
const searchbar = document.querySelector("#search");
const searchbar = document.querySelector("#search>input");
const itemList = document.querySelector("#itemList");
const fs = require("fs");
const { readdir, stat } = require("fs");
const nodePath = require("path");
const { promisify } = require("util");
const readDir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const readDir = promisify(readdir);
const { app } = electron.remote;
const fs = require("fs");

function lookupIcon (path, img) {
return new Promise((resolve, reject) => {
const ext = nodePath.extname(path).replace(".", "");
fs.readFile("./data/json/icons.json", (err, data) => {
if (err) reject(err);
const json = JSON.parse(data);
const src = json[ext];
if (src) {
resolve(src);
} else {
app.getFileIcon(path, (err, icon) => {
if (err) console.error(err);
resolve(icon.toDataURL());
});
}
});
});
}

async function search (path) {
const button = document.querySelector("#search>#searchButtons>#refresh");
button.classList.add("loading");
button.title = "Loading";
setTimeout(() => {
button.classList.remove("loading");
button.title = "Refresh";
}, 3000);

while (itemList.lastChild) {
itemList.removeChild(itemList.firstChild);
itemList.removeChild(itemList.lastChild);
}
if (path.toLowerCase().includes("start")) return;
const files = await readDir(searchbar.value);
files.forEach(async (file, i) => {
files.forEach((file, i) => {
const fullpath = nodePath.join(path, file);
const item = document.createElement("LI");
const img = document.createElement("IMG");
img.src = "./data/images/maximise.png";
const figure = document.createElement("FIGURE");
const title = document.createElement("H2");
title.textContent = file;
const description = document.createElement("P");
const stats = await stat(nodePath.join(path, file));
const isDirectory = stats.isDirectory();
description.textContent = (isDirectory) ? "Directory" : "File";
[img, title, description].forEach(element => item.appendChild(element));
const stats = stat(fullpath, (err, stats) => {
const isDirectory = stats.isDirectory();
description.textContent = (isDirectory) ? "Directory" : "File";
if (isDirectory) {
item.addEventListener("click", () => {
searchbar.value = fullpath;
search(searchbar.value);
});
fs.readFile("./data/images/icons/directory.svg", (err, data) => {
if (err) throw err;
figure.innerHTML = data;
});
} else {
const img = document.createElement("IMG");
figure.appendChild(img);
lookupIcon(fullpath).then(src => img.src = src);
}
});
[figure, title, description].forEach(element => item.appendChild(element));
itemList.appendChild(item);
if (isDirectory) {
item.addEventListener("click", () => {
searchbar.value = nodePath.join(path, file);
search(searchbar.value);
});
}
});
}

@@ -0,0 +1,21 @@
function rebuildTabs () {
const tabs = document.querySelectorAll("#tabbar>.tab:not([tabindex])");
tabs.forEach((tab, i) => {
const temp = tab.textContent;
tab.firstChild.remove();
const firstLetter = document.createElement("DIV");
firstLetter.classList.add("tabFirstLetter");
firstLetter.textContent = temp[0].toUpperCase();
const rest = document.createElement("DIV");
rest.textContent = temp.slice(1).toLowerCase();
rest.classList.add("tabRest");
[firstLetter, rest].forEach(div => tab.appendChild(div));
tab.setAttribute("tabindex", 0);
tab.addEventListener("click", event => {
searchbar.value = tab.dataset.url;
search(searchbar.value);
});
});
}

rebuildTabs();
@@ -0,0 +1,3 @@
{
"directory": "./data/images/icons/directory.svg"
}
@@ -7,36 +7,49 @@
<link rel="stylesheet" href="./data/css/common.css">
<link rel="stylesheet" href="./data/css/appContainer.css">
<link rel="stylesheet" href="./data/css/titlebar.css">
<link rel="stylesheet" href="./data/css/menu.css">
<link rel="stylesheet" href="./data/css/tabbar.css">
<link rel="stylesheet" href="./data/css/viewport.css">
<link rel="stylesheet" href="./data/css/search.css">
<link rel="stylesheet" href="./data/css/quickfind.css">
<link rel="stylesheet" href="./data/css/itemList.css">
<title>File Browser</title>
</head>
<body>
<div id="appContainer">
<header id="titlebar" class="fullWidthUItem">
<img id="titlebarIcon" src="./data/images/unmaximise.png" alt="Icon">
<h1 id="title">File Browser</h1>
<header id="titlebar">
<button id="titlebarMenu"><img src="./data/images/menu.png" alt="Menu"></button>
<img id="titlebarIcon" src="./data/images/icon.png" alt="Icon">
<h1 id="title">Pilgrim</h1>
<ul id="tabbar">
<li data-url="Start" class="tab">Start</li>
<li data-url="C:\Users\Wouter\Desktop\Projects\Git" class="tab">Git</li>
</ul>
<div id="titlebarButtons">
<button id="minimise" title="Minimise window"></button>
<button id="maximise" title="Maximise window"></button>
<button id="close" title="Close window"></button>
</div>
<ul id="menu" class="fullWidthUItem">
<li class="menuItem">File</li>
<li class="menuItem">Edit</li>
<li class="menuItem">Other Item</li>
<li class="menuItem">Weird shit</li>
</ul>
<div id="search">
<div id="searchButtons">
<button id="back" title="Go back"></button>
<button id="forward" title="Go forward"></button>
<button id="refresh" title="Refresh"></button>
<button id="dirUp" title="Go up one directory"></button>
</div>
<input type="text" placeholder="Search...">
</div>
</header>
<main id="viewport">
<input id="search" type="text" placeholder="Search...">
<ul id="quickFind">
<li data-url="Start" class="quickFindItem">Start</li>
</ul>
<ul id="itemList"></ul>
</main>
</div>
<script src="./data/js/titlebar.js"></script>
<script src="./data/js/menu.js"></script>
<script src="./data/js/search.js"></script>
<script src="./data/js/tabbar.js"></script>
<script src="./data/js/scrollbar.js"></script>
<script src="./data/js/quickfind.js"></script>
</body>
</html>
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.