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