Clean things up a bit before uploading to the web
This commit is contained in:
parent
222743e60d
commit
721750e91e
@ -8,14 +8,13 @@ import PlaygroundView from '@/components/PlaygroundView.vue'
|
||||
|
||||
const routes: { [index: string]: Component } = {
|
||||
'/': HomeView,
|
||||
play: PlaygroundView,
|
||||
'/play': PlaygroundView,
|
||||
}
|
||||
|
||||
const currentPath = ref<string>(window.location.hash)
|
||||
|
||||
window.addEventListener('hashchange', () => {
|
||||
currentPath.value = window.location.hash
|
||||
console.log(currentPath.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,21 +1,30 @@
|
||||
:root {
|
||||
--bg-color: #141414;
|
||||
--fg-color: #ff00ff;
|
||||
--fg-color-header: #00ffff;
|
||||
--fg-color-link: #ffff40;
|
||||
--fg-color-link-visited: #ff8040;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
font-family: monospace;
|
||||
background: black;
|
||||
color: #ff00ff;
|
||||
font-family: 'Courier New', monospace;
|
||||
background: var(--bg-color);
|
||||
color: var(--fg-color);
|
||||
font-size: 12pt;
|
||||
margin: auto;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
font: inherit;
|
||||
font-family: 'Courier New', monospace;
|
||||
margin: 0.5em 0;
|
||||
padding: 0.5em 0.75em;
|
||||
}
|
||||
|
||||
progress::-webkit-progress-bar,
|
||||
progress::-moz-progress-bar {
|
||||
background: #ff00ff;
|
||||
background: var(--fg-color);
|
||||
}
|
||||
|
||||
h1,
|
||||
@ -24,13 +33,26 @@ h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: #00ffff;
|
||||
margin: 0 0 0.25em;
|
||||
color: var(--fg-color-header);
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4040ff;
|
||||
color: var(--fg-color-link);
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #ff4040;
|
||||
color: var(--fg-color-link-visited);
|
||||
}
|
||||
|
||||
section {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
section h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
border-bottom: 2px solid color(from var(--fg-color-header) srgb r g b / 30%);
|
||||
}
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<span class="blink">
|
||||
<slot />
|
||||
</span>
|
||||
<span class="blink"><slot /></span>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.blink {
|
||||
display: inline-block;
|
||||
animation: blinker 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes blinker {
|
||||
50% {
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.blink {
|
||||
opacity: 0;
|
||||
animation: blinker 2s ease-in-out 10;
|
||||
}
|
||||
|
||||
@keyframes blinker {
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,12 +1,22 @@
|
||||
<script lang="ts" setup>
|
||||
import { useTemplateRef } from 'vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
start: [name: string]
|
||||
progress: [loaded: number, total: number]
|
||||
load: [data: ArrayBuffer]
|
||||
progress: [read: number, total: number]
|
||||
success: [data: ArrayBuffer]
|
||||
error: [message: string]
|
||||
}>()
|
||||
|
||||
async function handleFiles(event: Event) {
|
||||
const MAX_FILE_SIZE = 1440 * 1024
|
||||
|
||||
const fileInput = useTemplateRef('file-input')
|
||||
|
||||
async function onOpenClick() {
|
||||
fileInput.value?.click()
|
||||
}
|
||||
|
||||
async function onFileChange(event: Event) {
|
||||
const files = (event.target as HTMLInputElement).files
|
||||
if (!files?.length) {
|
||||
return
|
||||
@ -14,18 +24,28 @@ async function handleFiles(event: Event) {
|
||||
|
||||
try {
|
||||
const data = await readFile(files[0])
|
||||
emit('load', data)
|
||||
} catch (error) {
|
||||
emit('error', error as string)
|
||||
emit('success', data)
|
||||
} catch (e) {
|
||||
let error
|
||||
if (!(e instanceof Error)) {
|
||||
error = new Error('' + e)
|
||||
} else {
|
||||
error = e
|
||||
}
|
||||
emit('error', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
async function readFile(file: File): Promise<ArrayBuffer> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
function readFile(file: File): Promise<ArrayBuffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
reject(new Error('Maximum file size exceeded'))
|
||||
return
|
||||
}
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onloadstart = () => {
|
||||
emit('start', file.name)
|
||||
reader.onloadstart = (event: ProgressEvent) => {
|
||||
emit('progress', event.loaded, event.total)
|
||||
}
|
||||
|
||||
reader.onprogress = (event: ProgressEvent) => {
|
||||
@ -39,22 +59,28 @@ async function readFile(file: File): Promise<ArrayBuffer> {
|
||||
}
|
||||
|
||||
reader.onerror = () => {
|
||||
reject('load error')
|
||||
reject(`read error`)
|
||||
}
|
||||
|
||||
reader.onabort = () => {
|
||||
reject('load aborted')
|
||||
reject('read aborted')
|
||||
}
|
||||
|
||||
reader.readAsArrayBuffer(file)
|
||||
emit('start', file.name)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form>
|
||||
<input id="disk-file" type="file" @change="handleFiles" />
|
||||
</form>
|
||||
<div>
|
||||
<input id="disk-file" ref="file-input" type="file" @change="onFileChange" />
|
||||
<button type="button" @click="onOpenClick">Open a disk image...</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
input[type='file'] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -10,6 +10,10 @@ const hexDump = computed(() => {
|
||||
let offset = 0
|
||||
const total = buffer.byteLength
|
||||
|
||||
if (total === 0) {
|
||||
return ''.padEnd(80, ' ')
|
||||
}
|
||||
|
||||
while (offset < total) {
|
||||
const values = [offset.toString(16).padStart(8, '0')]
|
||||
const asciiValues: string[] = []
|
||||
@ -77,6 +81,7 @@ pre {
|
||||
height: 20rem;
|
||||
max-height: 20rem;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
color: #c0c0c0;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,15 +3,29 @@
|
||||
<template>
|
||||
<header>
|
||||
<h1>Floppy Drive</h1>
|
||||
<p>Coming soonish...</p>
|
||||
<p>Load floppy disk(images) right from your browser.</p>
|
||||
</header>
|
||||
<section>
|
||||
<h2>The Idea</h2>
|
||||
<h2>What is it?</h2>
|
||||
<p>
|
||||
Allow visitors to upload floppy disk images so that they can browse, view, and download the
|
||||
A website that lets you upload floppy disk images so you can browse, view, and download the
|
||||
files stored on them.
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Is is ready yet?</h2>
|
||||
<p>Everything is still very much a work in progress.</p>
|
||||
<p>
|
||||
Feel free to <a href="/#/play">play around</a> with some of the things I am working on, but
|
||||
understand that it is <strong>NOT</strong> working yet.
|
||||
</p>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
header p {
|
||||
margin: 0;
|
||||
font-style: italic;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<h2>Page Not Found</h2>
|
||||
<h2>Oops... Page Not Found</h2>
|
||||
<p>I couldn't seem to find that.</p>
|
||||
<p>You should probably just head back <a href="/">Home</a>.</p>
|
||||
</section>
|
||||
|
||||
@ -3,66 +3,89 @@ import { ref } from 'vue'
|
||||
import DiskReader from '@/components/DiskReader.vue'
|
||||
import HexDump from '@/components/HexDump.vue'
|
||||
|
||||
const loadName = ref('')
|
||||
const loadTotal = ref(0)
|
||||
const loadLoaded = ref(0)
|
||||
const loadData = ref(new ArrayBuffer(0))
|
||||
type DiskReadyState = 'empty' | 'read-started' | 'read-success' | 'read-failed'
|
||||
|
||||
function handleStart(name: string) {
|
||||
console.log(`Loading file: ${name}`)
|
||||
loadName.value = name
|
||||
loadLoaded.value = 0
|
||||
loadTotal.value = -1
|
||||
const diskReadyState = ref<DiskReadyState>('empty')
|
||||
const diskName = ref('')
|
||||
const diskTotalBytes = ref(0)
|
||||
const diskReadBytes = ref(0)
|
||||
const diskReadError = ref('')
|
||||
const diskData = ref(new ArrayBuffer(0))
|
||||
|
||||
function onReadStart(name: string) {
|
||||
console.log(`Reading disk from ${name}`)
|
||||
diskReadyState.value = 'read-started'
|
||||
diskName.value = name
|
||||
diskReadBytes.value = 0
|
||||
diskTotalBytes.value = -1
|
||||
}
|
||||
|
||||
function handleLoad(data: ArrayBuffer) {
|
||||
console.log('File loaded')
|
||||
loadData.value = data
|
||||
function onReadSuccess(data: ArrayBuffer) {
|
||||
console.log('Disk read succeeded')
|
||||
diskReadyState.value = 'read-success'
|
||||
diskData.value = data
|
||||
}
|
||||
|
||||
function handleError(message: string) {
|
||||
console.log('Error loading file' + message)
|
||||
loadLoaded.value = -1
|
||||
loadTotal.value = -1
|
||||
function onReadError(message: string) {
|
||||
console.log('Disk read failed: ' + message)
|
||||
diskData.value = new ArrayBuffer(0)
|
||||
diskReadError.value = message
|
||||
diskReadyState.value = 'read-failed'
|
||||
diskReadBytes.value = -1
|
||||
diskTotalBytes.value = -1
|
||||
}
|
||||
|
||||
function handleProgress(loaded: number, total: number) {
|
||||
loadLoaded.value = loaded
|
||||
loadTotal.value = total
|
||||
function onReadProgress(read: number, total: number) {
|
||||
diskReadBytes.value = read
|
||||
diskTotalBytes.value = total
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav>
|
||||
<a href="/#/">Home</a>
|
||||
</nav>
|
||||
<section>
|
||||
<h2>Playground</h2>
|
||||
<p>This is my playground for testing out my code.</p>
|
||||
<p>
|
||||
<strong><em>WARNING!!!</em> Use at your own risk!</strong>
|
||||
</p>
|
||||
<section>
|
||||
<h3>Disk Upload</h3>
|
||||
<DiskReader
|
||||
@error="handleError"
|
||||
@load="handleLoad"
|
||||
@progress="handleProgress"
|
||||
@start="handleStart"
|
||||
/>
|
||||
<div v-if="loadName">
|
||||
Loading {{ loadName }}
|
||||
<progress :max="loadTotal" :value="loadLoaded">
|
||||
{{ ((loadLoaded / loadTotal) * 100.0).toFixed(2) }} %
|
||||
</progress>
|
||||
{{ ((loadLoaded / loadTotal) * 100.0).toFixed(2) }} %
|
||||
<h3>Disk Read</h3>
|
||||
<div class="cols">
|
||||
<DiskReader
|
||||
@error="onReadError"
|
||||
@progress="onReadProgress"
|
||||
@start="onReadStart"
|
||||
@success="onReadSuccess"
|
||||
/>
|
||||
<div v-if="diskReadyState === 'read-started'">
|
||||
{{ diskName }} reading
|
||||
<progress :max="diskTotalBytes" :value="diskReadBytes">
|
||||
{{ ((diskReadBytes / diskTotalBytes) * 100.0).toFixed(2) }} %
|
||||
</progress>
|
||||
{{ ((diskReadBytes / diskTotalBytes) * 100.0).toFixed(2) }} %
|
||||
</div>
|
||||
<div v-else-if="diskReadyState === 'read-success'">{{ diskName }} loaded</div>
|
||||
<div v-else-if="diskReadyState === 'read-failed'">
|
||||
error reading disk: {{ diskReadError }}
|
||||
</div>
|
||||
<div v-else>No disk loaded</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Disk Hex Dump</h3>
|
||||
<HexDump :buffer="loadData" />
|
||||
<HexDump :buffer="diskData" />
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
progress {
|
||||
margin-top: 1em;
|
||||
margin-left: 1em;
|
||||
margin-right: 0.25em;
|
||||
.cols {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
gap: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -5,8 +5,9 @@ import BlinkingText from '@/components/BlinkingText.vue'
|
||||
<template>
|
||||
<header>
|
||||
<pre>
|
||||
A:\> DIR
|
||||
Welcome to Floppy Drive!
|
||||
|
||||
A:\> DIR
|
||||
General failure reading drive A
|
||||
Abort, Retry, Fail? <BlinkingText>█</BlinkingText>
|
||||
</pre>
|
||||
@ -17,7 +18,8 @@ Abort, Retry, Fail? <BlinkingText>█</BlinkingText>
|
||||
pre {
|
||||
font-weight: bold;
|
||||
transform: skewX(-3deg);
|
||||
text-shadow: 0 0 5px #0f8;
|
||||
text-shadow: 0 0 5px #80ff80;
|
||||
color: #0f0;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user