feat: implement type effect

This commit is contained in:
jinhojang6 2024-02-14 04:34:21 +09:00
parent 591d5d4df9
commit 15ec60cdd5
5 changed files with 108 additions and 20 deletions

View File

@ -20,19 +20,19 @@
class="h-full p-4 overflow-auto text-xs border-2 rounded-md sm:text-sm md:text-base"
style={`background-color: ${$theme.background}; color: ${$theme.foreground}; border-color: transparent;`}
>
<History />
<div class="lex-col md:flex-row">
<div id="input" class="flex flex-col md:flex-row">
<Ps1 />
<Input />
<div class="buttons-row">{`
</div>
<div class="buttons-row">
{`
----------------------------------------------------------------------------
< Apply > < X >
< X >
-----------------------------------------------------------------------------
`}
</div>
</div>
</main>

View File

@ -20,12 +20,16 @@ body {
background-color: #000099;
}
.banner {
white-space: pre-wrap;
}
main > div > div:first-child {
display: none;
}
main > div:first-child > p {
margin-bottom: 24px;
#input {
margin-top: 24px;
}
.buttons-row {
@ -34,6 +38,16 @@ main > div:first-child > p {
white-space: pre-wrap;
}
.whitespace-pre {
white-space: pre-wrap;
}
.link {
color: #828282;
text-decoration: underline;
cursor: pointer;
}
::-webkit-scrollbar {
width: 5px;
height: 5px;

View File

@ -1,15 +1,21 @@
<script lang="ts">
import { history } from '../stores/history';
import { theme } from '../stores/theme';
import Ps1 from './Ps1.svelte';
import { history } from "../stores/history";
import { theme } from "../stores/theme";
import Ps1 from "./Ps1.svelte";
function parseTemplateString(templateString: string) {
const htmlContent = templateString.replace('<template>', '').replace('</template>', '');
return htmlContent;
}
</script>
<p class="banner"></p>
{#each $history as { command, outputs }}
<div style={`color: ${$theme.foreground}`}>
<div class="flex-col md:flex-row">
<Ps1 />
<div class="flex">
<p class="visible md:hidden"></p>
<p class="px-2">{command}</p>
@ -17,9 +23,11 @@
</div>
{#each outputs as output}
<p class="whitespace-pre">
{output}
</p>
{#if output.startsWith("<template>")}
{@html parseTemplateString(output)}
{:else}
<p class="whitespace-pre">{output}</p>
{/if}
{/each}
</div>
{/each}

View File

@ -16,8 +16,11 @@
if ($history.length === 0) {
const command = commands['banner'] as () => string;
console.log('command',command);
if (command) {
const output = command();
console.log('output',output);
$history = [...$history, { command: 'banner', outputs: [output] }];
}

View File

@ -9,6 +9,11 @@ export const commands: Record<
string,
(args: string[]) => Promise<string> | string
> = {
apply: async () => {
const htmlString = "<template>Please email us at <a class=\"link\" href=\"mailto:contact@free.technology\">contact@free.technology</a></template>";
return htmlString;
},
help: () => "Available commands: " + Object.keys(commands).join(", "),
hostname: () => hostname,
whoami: () => "guest",
@ -111,8 +116,62 @@ export const commands: Record<
return `curl: could not fetch URL ${url}. Details: ${error}`;
}
},
banner: () => `
banner: () => {
function displayTextLetterByLetter(
elementClass: any,
text: any,
minDelay = 1,
maxDelay = 10
) {
const elements = document.getElementsByClassName(elementClass);
const element = elements[elements.length - 1]
if (!element) return;
// Append cursor initially
const cursor = document.createElement("span");
cursor.className = "cursor";
element.appendChild(cursor);
let currentIndex = 0;
function displayNextLetter() {
if (currentIndex < text.length) {
let charToAdd = text[currentIndex];
if (text.substr(currentIndex, 4) === "<br>") {
charToAdd = "<br>";
currentIndex += 4;
} else {
currentIndex++;
}
// Insert the character or <br> before the cursor
if (charToAdd === "<br>") {
const brElement = document.createElement("br");
element?.insertBefore(brElement, cursor);
} else {
const textNode = document.createTextNode(charToAdd);
element?.insertBefore(textNode, cursor);
}
let randomDelay = Math.random() * (maxDelay - minDelay) + minDelay;
setTimeout(displayNextLetter, randomDelay);
} else {
// If all characters are added, remove the cursor
cursor.style.display = "none";
const baner = document.getElementsByClassName("banner")[0];
if (baner) {
// delete the banner
baner.remove();
// add the banner to the history
history.update((h) => [...h, { command: "banner", outputs: [text] }]);
}
}
}
displayNextLetter();
}
const text = `██████╗ ███████╗██████╗ ██╗██████╗ █████╗ ████████╗██╗ ██╗ ██████╗ ███████╗
@ -131,6 +190,10 @@ Peripatetic School — simply referred to as the Peripatos after the ancient
walkway of the Acropolis was an informal institution of ancient Greece
where members conducted philosophical and scientific inquiries.
Type 'help' to see list of available commands.
`,
Type 'help' to see list of available commands.`;
displayTextLetterByLetter("banner", text);
return '';
},
};