diff --git a/cista-front/.gitignore b/cista-front/.gitignore
index 36cf632..ed637e9 100644
--- a/cista-front/.gitignore
+++ b/cista-front/.gitignore
@@ -9,6 +9,7 @@ lerna-debug.log*
# No locking
package-lock.json
+yarn.lock
node_modules
.DS_Store
diff --git a/cista-front/src/App.vue b/cista-front/src/App.vue
index 79250be..3b3e323 100644
--- a/cista-front/src/App.vue
+++ b/cista-front/src/App.vue
@@ -52,7 +52,11 @@ const globalShortcutHandler = (event: KeyboardEvent) => {
const c = documentStore.fileExplorer.isCursor()
const keyup = event.type === 'keyup'
if (event.repeat) {
- if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || (c && event.code === 'Space')) {
+ if (
+ event.key === 'ArrowUp' ||
+ event.key === 'ArrowDown' ||
+ (c && event.code === 'Space')
+ ) {
event.preventDefault()
}
return
@@ -70,7 +74,11 @@ const globalShortcutHandler = (event: KeyboardEvent) => {
documentStore.fileExplorer.toggleSelectAll()
}
// Keys 1-3 to sort columns
- else if (c && keyup && (event.key === '1' || event.key === '2' || event.key === '3')) {
+ else if (
+ c &&
+ keyup &&
+ (event.key === '1' || event.key === '2' || event.key === '3')
+ ) {
documentStore.fileExplorer.toggleSortColumn(+event.key)
}
// Rename
@@ -85,7 +93,7 @@ const globalShortcutHandler = (event: KeyboardEvent) => {
event.preventDefault()
if (!vert) {
if (timer) {
- clearTimeout(timer) // Good for either timeout or interval
+ clearTimeout(timer) // Good for either timeout or interval
timer = null
}
return
@@ -94,11 +102,13 @@ const globalShortcutHandler = (event: KeyboardEvent) => {
// Initial move, then t0 delay until repeats at tr intervals
const select = event.shiftKey
documentStore.fileExplorer.cursorMove(vert, select)
- const t0 = 200, tr = 30
+ const t0 = 200,
+ tr = 30
timer = setTimeout(
- () => timer = setInterval(() => {
- documentStore.fileExplorer.cursorMove(vert, select)
- }, tr),
+ () =>
+ (timer = setInterval(() => {
+ documentStore.fileExplorer.cursorMove(vert, select)
+ }, tr)),
t0 - tr
)
}
diff --git a/cista-front/src/assets/main.css b/cista-front/src/assets/main.css
index 6c8d264..1918b7b 100644
--- a/cista-front/src/assets/main.css
+++ b/cista-front/src/assets/main.css
@@ -46,7 +46,9 @@
--header-background: none;
--header-color: black;
}
- nav, .menu, .rename-button {
+ nav,
+ .menu,
+ .rename-button {
display: none;
}
.breadcrumb > a {
@@ -57,8 +59,12 @@
clip-path: none !important;
max-width: none !important;
}
- .breadcrumb > a::after { content: '/'; }
- .breadcrumb svg { fill: black !important; }
+ .breadcrumb > a::after {
+ content: '/';
+ }
+ .breadcrumb svg {
+ fill: black !important;
+ }
main {
height: auto !important;
padding-bottom: 0 !important;
@@ -72,22 +78,27 @@
min-width: 0 !important;
padding: 0 !important;
}
- .selection input { display: none }
- .selection input:checked { display: inherit; }
+ .selection input {
+ display: none;
+ }
+ .selection input:checked {
+ display: inherit;
+ }
tbody .selection input:checked {
opacity: 1 !important;
transform: scale(0.5);
top: 0.1rem !important;
left: -0.3rem !important;
}
-
}
/* Hide scrollbar for all browsers */
-main::-webkit-scrollbar { display: none; }
+main::-webkit-scrollbar {
+ display: none;
+}
main {
- -ms-overflow-style: none; /* IE and Edge */
- scrollbar-width: none; /* Firefox */
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
}
body {
background-color: var(--primary-background);
@@ -96,7 +107,8 @@ body {
color: var(--primary-color);
margin: 0;
}
-tbody .size, tbody .modified {
+tbody .size,
+tbody .modified {
font-family: 'Roboto Mono';
}
header {
@@ -146,7 +158,7 @@ table {
flex-direction: column;
}
main {
- height: calc(100svh - 9rem); /* fill almost the rest of the screen after header */
- padding-bottom: 3rem; /* convenience space on the bottom */
+ height: calc(100svh - 9rem); /* fill almost the rest of the screen after header */
+ padding-bottom: 3rem; /* convenience space on the bottom */
overflow-y: scroll;
}
diff --git a/cista-front/src/components/FileExplorer.vue b/cista-front/src/components/FileExplorer.vue
index 17694cc..9c35244 100644
--- a/cista-front/src/components/FileExplorer.vue
+++ b/cista-front/src/components/FileExplorer.vue
@@ -48,7 +48,11 @@
"
/>
-
{{ editing.modified }} |
+
+
+ |
{{ editing.sizedisp }} |
@@ -95,13 +99,27 @@
@focus.stop="cursor = doc"
>{{ doc.name }}
-
+
- {{ doc.modified }} |
+
+
+ |
{{ doc.sizedisp }} |
@@ -208,7 +226,8 @@ defineExpose({
const N = documents.length
const mod = (a: number, b: number) => ((a % b) + b) % b
const increment = (i: number, d: number) => mod(i + d, N + 1)
- const index = cursor.value !== null ? documents.indexOf(cursor.value) : documents.length
+ const index =
+ cursor.value !== null ? documents.indexOf(cursor.value) : documents.length
const moveto = increment(index, d)
cursor.value = documents[moveto] ?? null
const tr = cursor.value ? document.getElementById(`file-${cursor.value.key}`) : null
@@ -316,6 +335,7 @@ watchEffect(() => {
if (editing.value) cursor.value = editing.value
})
const contextMenu = (ev: Event, doc: Document) => {
+ cursor.value = doc
console.log('Context menu', ev, doc)
}
@@ -345,6 +365,9 @@ table tbody input[type='checkbox'] {
}
table .selection {
width: 2rem;
+ height: 2rem;
+ text-align: center;
+ text-overflow: clip;
}
table .modified {
width: 8rem;
@@ -372,12 +395,21 @@ table td {
position: relative;
}
.name .rename-button {
- padding-left: 1rem;
position: absolute;
right: 0;
animation: appear calc(5 * var(--transition-time)) linear;
}
-@keyframes appear { from { opacity: 0 } 80% { opacity: 0 } to { opacity: 1 } }
+@keyframes appear {
+ from {
+ opacity: 0;
+ }
+ 80% {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
thead tr {
background: linear-gradient(to bottom, #eee, #fff 30%, #ddd);
color: #000;
@@ -423,7 +455,7 @@ tbody .selection input {
height: 2em;
}
.selection input:checked {
- opacity: .7;
+ opacity: 0.7;
}
.file .selection::before {
content: '📄 ';
diff --git a/cista-front/src/components/FileRenameInput.vue b/cista-front/src/components/FileRenameInput.vue
index 82a74ca..6f9be20 100644
--- a/cista-front/src/components/FileRenameInput.vue
+++ b/cista-front/src/components/FileRenameInput.vue
@@ -35,7 +35,11 @@ const props = defineProps<{
const apply = () => {
props.exit()
- if (props.doc.key !== 'new' && (name.value === props.doc.name || name.value.length === 0)) return
+ if (
+ props.doc.key !== 'new' &&
+ (name.value === props.doc.name || name.value.length === 0)
+ )
+ return
props.rename(props.doc, name.value)
}
@@ -45,9 +49,9 @@ input#FileRenameInput {
color: var(--primary-color);
background: var(--primary-background);
border: 0;
- border-radius: .3rem;
- padding: .4rem;
- margin: -.4rem;
+ border-radius: 0.3rem;
+ padding: 0.4rem;
+ margin: -0.4rem;
width: 100%;
outline: none;
font: inherit;
diff --git a/cista-front/src/components/HeaderMain.vue b/cista-front/src/components/HeaderMain.vue
index cd7db19..bc780e9 100644
--- a/cista-front/src/components/HeaderMain.vue
+++ b/cista-front/src/components/HeaderMain.vue
@@ -46,7 +46,7 @@ defineExpose({
/>
-
+
diff --git a/cista-front/src/main.ts b/cista-front/src/main.ts
index 745fc01..fe6ed7d 100644
--- a/cista-front/src/main.ts
+++ b/cista-front/src/main.ts
@@ -8,12 +8,12 @@ import router from './router'
import piniaPluginPersistedState from 'pinia-plugin-persistedstate'
-
const app = createApp(App)
app.config.errorHandler = err => {
/* handle error */
console.log(err)
}
+
const pinia = createPinia()
pinia.use(piniaPluginPersistedState)
app.use(pinia)
diff --git a/cista-front/src/repositories/Document.ts b/cista-front/src/repositories/Document.ts
index 9bf177a..461ca4b 100644
--- a/cista-front/src/repositories/Document.ts
+++ b/cista-front/src/repositories/Document.ts
@@ -99,7 +99,7 @@ export class DocumentHandler {
this.handleUpdateMessage(msg)
break
case !!msg.space:
- console.log("Watch space", msg.space)
+ console.log('Watch space', msg.space)
break
case !!msg.error:
this.handleError(msg)
@@ -109,14 +109,14 @@ export class DocumentHandler {
}
private handleRootMessage({ root }: { root: DirEntry }) {
- console.log("Watch root", root)
+ console.log('Watch root', root)
if (this.store && this.store.root) {
this.store.user.isLoggedIn = true
this.store.root = root
}
}
private handleUpdateMessage(updateData: { update: UpdateEntry[] }) {
- console.log("Watch update", updateData.update)
+ console.log('Watch update', updateData.update)
let node: DirEntry = this.store.root
for (const elem of updateData.update) {
if (elem.deleted) {
diff --git a/cista-front/src/utils/index.ts b/cista-front/src/utils/index.ts
index 384eb27..6771273 100644
--- a/cista-front/src/utils/index.ts
+++ b/cista-front/src/utils/index.ts
@@ -27,19 +27,19 @@ export function formatUnixDate(t: number) {
return 'now'
}
if (Math.abs(diff) <= 60000) {
- return formatter.format(Math.round(diff / 1000), 'second')
+ return formatter.format(Math.round(diff / 1000), 'second').replace(' ago', '').replaceAll(' ', '\u202F')
}
if (Math.abs(diff) <= 3600000) {
- return formatter.format(Math.round(diff / 60000), 'minute')
+ return formatter.format(Math.round(diff / 60000), 'minute').replace('utes', '').replace('ute', '').replaceAll(' ', '\u202F')
}
if (Math.abs(diff) <= 86400000) {
- return formatter.format(Math.round(diff / 3600000), 'hour')
+ return formatter.format(Math.round(diff / 3600000), 'hour').replaceAll(' ', '\u202F')
}
if (Math.abs(diff) <= 604800000) {
- return formatter.format(Math.round(diff / 86400000), 'day')
+ return formatter.format(Math.round(diff / 86400000), 'day').replaceAll(' ', '\u202F')
}
let d = date.toLocaleDateString('en-ie', {
@@ -48,7 +48,7 @@ export function formatUnixDate(t: number) {
month: 'short',
day: 'numeric'
}).replace("Sept", "Sep")
- if (d.length === 14) d = d.replace(' ', '\u202F\u2007') // dom < 10 alignment (thin and figure spaces)
+ if (d.length === 14) d = d.replace(' ', ' \u2007') // dom < 10 alignment (add figure space)
d = d.replaceAll(' ', '\u202F').replace('\u202F', '\u00A0') // nobr spaces, thin w/ date but not weekday
d = d.slice(0, -4) + d.slice(-2) // Two digit year is enough
return d