your desktop cpu simply c

This commit is contained in:
MeowcaTheoRange 2024-04-14 15:37:15 -05:00
parent 3823cc14d9
commit d8eaaba9c9
15 changed files with 465 additions and 15 deletions

19
package-lock.json generated
View file

@ -13,7 +13,8 @@
"react-dom": "^18",
"react-markdown": "^9.0.1",
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.0"
"remark-gfm": "^4.0.0",
"use-sound": "^4.0.1"
},
"devDependencies": {
"@types/node": "^20",
@ -573,6 +574,11 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/howler": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz",
"integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w=="
},
"node_modules/html-url-attributes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz",
@ -1950,6 +1956,17 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/use-sound": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/use-sound/-/use-sound-4.0.1.tgz",
"integrity": "sha512-hykJ86kNcu6y/FzlSHcQxhjSGMslZx2WlfLpZNoPbvueakv4OF3xPxEtGV2YmculrIaH0tPp9LtG4jgy17xMWg==",
"dependencies": {
"howler": "^2.1.3"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/vfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz",

View file

@ -14,7 +14,8 @@
"react-dom": "^18",
"react-markdown": "^9.0.1",
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.0"
"remark-gfm": "^4.0.0",
"use-sound": "^4.0.1"
},
"devDependencies": {
"@types/node": "^20",

4
qna.txt Normal file
View file

@ -0,0 +1,4 @@
fetch("https://retrospring.net/ajax/ask", {
"body": "{\"rcpt\":\"111212083514464878\",\"question\":\"hi sneex it is me abtmtr. i am not in your house right now but hypothetically if i was. where do you keep your hams\",\"anonymousQuestion\":\"true\"}",
"method": "POST"
});

View file

@ -1,6 +1,7 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "@/styles/style.css";
import { Sounds } from "@/components/Sounds";
const lexendDeca = localFont({ src: "../../public/fonts/Lexend Deca/Variable.ttf"});
const materialSymbols = localFont({ src: "../../public/fonts/Material Symbols/Variable.ttf"});

View file

@ -1,6 +1,7 @@
import { MainLayout } from "@/layout/MainLayout/MainLayout";
import Link from "next/link";
import buttons from "@/buttons.json";
import Searchbar from "@/components/Searchbar/Searchbar";
export default async function Home() {
const data = await fetch("https://pronouns.cc/api/v1/users/mtr").then(x=>x.json());
@ -12,6 +13,7 @@ export default async function Home() {
return (
<MainLayout currentPage="/" title="Root">
<img className="headerImage" src="/welcome.png" alt="WELCOME! Enjoy your stay at abtmtr.link!"></img>
<Searchbar />
<p>abtmtr.link is a domain for a suite of services, ranging from micro-blogging to web search.</p>
<p>I'm {goodNames[0].value}, otherwise known as {goodNames.slice(1).map((name:{value:string}, idx:number) => (
idx == goodNames.length - 2 ? (<>or <b>{name.value}</b></>) : (<><b>{name.value}</b>{goodNames.length <= 2 ? ", " : " "}</>)

10
src/app/search/page.tsx Normal file
View file

@ -0,0 +1,10 @@
import Searchbar from "@/components/Searchbar/Searchbar";
import { MainLayout } from "@/layout/MainLayout/MainLayout";
export default function Page() {
return (
<MainLayout currentPage="/search/" title="Search" subtitle="Powered by s.abtmtr.link">
<Searchbar />
</MainLayout>
)
}

View file

@ -0,0 +1,144 @@
import { MainLayout } from "@/layout/MainLayout/MainLayout";
import styles from "./styles.module.css";
import Link from "next/link";
import { ConditionalNull, ConditionalParent } from "@/components/utility/Conditional";
import Searchbar from "@/components/Searchbar/Searchbar";
//
export default async function Home({
searchParams
}:{
searchParams: {
q: string,
page: string
}
}) {
const curPage = parseInt(searchParams?.page) || 1;
const searchResults = await fetch(`https://s.abtmtr.link/search?q=${searchParams.q}&pageno=${curPage}&format=json`, {
headers: [
["Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"]
]
}).then(x => x.json());
return (
<MainLayout currentPage="/search/search/" title="Search" subtitle={`Results for "${searchParams.q}"`} backButton>
<Searchbar value={searchParams.q} />
<div className={styles.SearchInfoboxes}>
{searchResults.infoboxes?.map((box:{
infobox: string,
attributes?: {
label: string,
value?: string,
image?: {
src: string,
alt: string,
title: string,
width: number,
height: number,
type: string,
themes: string,
colorinvertable: boolean,
contenttype: string
}
}[],
id?: string,
content?: string,
img_src?: string,
urls: {
title: string,
url: string
}[],
engine: string,
engines: string[]
}) => {
return (
<div className={styles.SearchInfobox}>
<h2>{box.infobox}</h2>
<ConditionalParent
condition={box.img_src != null && box.img_src.length > 0}
parent={(x => (
<div className={styles.SideBySideImage}>
<img src={box.img_src} />
{x}
</div>
))}
>
<ConditionalNull condition={box.content != null}>
<div>
<small><a href={box.id}>{box.id}</a></small><br />
<p>{box.content}</p>
</div>
</ConditionalNull>
</ConditionalParent>
{box.attributes?.map(attribute => (<div>
<p><b>{attribute.label}</b></p>
<ConditionalNull condition={attribute.value != null}>
<p>{attribute.value}</p>
</ConditionalNull>
<ConditionalNull condition={attribute.image != null}>
<img
src={attribute.image?.src}
alt={attribute.image?.alt}
title={attribute.image?.title}
height={attribute.image?.height}
width={attribute.image?.width}
></img>
</ConditionalNull>
</div>))}
{box.urls.map(url => (<p>
<a href={url.url}>{url.title}</a>
</p>))}
<small>{box.engines?.join(" ") ?? box.engine}</small>
</div>
);
})}
</div>
{searchResults.results?.map((result:{
url: string,
title: string,
content?: string,
img_src?: string,
engine: string,
parsed_url: string[],
engines: string[],
positions: number[],
score: number,
category: string
}) => {
const content = result.content?.match(/^.+?(?:\.|$)/m);
return (
<div className={styles.SearchResult}>
<p>
<Link href={result.url}>{result.title}</Link>
<br />
<small>{result.url}</small>
</p>
<ConditionalParent
condition={result.img_src != null && result.img_src.length > 0}
parent={(x => (
<div className={styles.SideBySideImage}>
<img src={result.img_src} />
{x}
</div>
))}
>
<div>
<ConditionalNull condition={content != null}>
<i>"{content?.[0].replace(/"/g, "")}"</i><br />
</ConditionalNull>
<small>{result.engines?.join(" ") ?? result.engine}</small>
</div>
</ConditionalParent>
</div>
)
})}
<div className="navigation">
<ConditionalNull condition={curPage > 1}>
<Link href={`?q=${searchParams.q}&page=${curPage - 1}`}>Previous</Link>
</ConditionalNull>
<ConditionalNull condition={searchResults.results?.length > 0}>
<Link href={`?q=${searchParams.q}&page=${curPage + 1}`}>Next</Link>
</ConditionalNull>
</div>
</MainLayout>
)
}

View file

@ -0,0 +1,31 @@
.SearchResult {
margin: 16px 0;
}
.SearchInfobox {
/* border: 1px solid var(--fg-2); */
background-color: var(--bg-3);
color: var(--fg-3);
border-radius: 4px;
padding: 8px;
margin: 16px 0;
}
.SearchInfobox h2 {
/* margin-left: 8px; */
margin-top: 0;
margin-bottom: 8px;
}
.SideBySideImage {
display: grid;
grid-template-columns: auto 1fr;
gap: 8px;
}
.SideBySideImage img {
max-height: 100%;
max-width: 150px !important;
border: 1px solid var(--fg-3);
border-radius: 4px;
}

View file

@ -0,0 +1,69 @@
"use client";
import Link from "next/link";
import styles from "./styles.module.css";
import { FormEvent, KeyboardEvent, useRef, useState } from "react";
import { stringify } from "querystring";
import { ConditionalNull } from "@/components/utility/Conditional";
import { useRouter } from "next/navigation";
export default function Searchbar({value}:{value?:string}) {
const [href, setHref] = useState<string>("");
const [arr, setArr] = useState<string[]>([]);
const searchRouter = useRouter();
let currentTimeout: number | NodeJS.Timeout;
function suggestTimeout(e:FormEvent<HTMLInputElement>) {
const target = e.target as HTMLInputElement;
if (target.value.length < 1)
setHref("");
else
setHref(`/search/search/?${stringify({q:target.value})}`);
clearTimeout(currentTimeout);
currentTimeout = setTimeout(executeAC, 500, e);
}
async function executeAC(e:FormEvent<HTMLInputElement>) {
const target = e.target as HTMLInputElement;
console.log(target.value);
const rows = await fetch(`https://s.abtmtr.link/autocompleter?${stringify({
q: target.value
})}`).then(x => x.json());
if (rows == null) return;
setArr(rows[1]);
}
function onKeypress(e:KeyboardEvent<HTMLInputElement>) {
if (e.key === "Enter") {
// Cancel the default action, if needed
e.preventDefault();
searchRouter.push(href);
}
}
return (<>
<div className={styles.SearchBox}>
<input
type="text" name="q" className={styles.SearchBoxForm}
autoCorrect="off"
autoComplete="off"
onInput={suggestTimeout}
onKeyDown={onKeypress}
placeholder="Search s.abtmtr.link"
defaultValue={value}
></input>
<Link className={styles.SearchBoxButton} href={href}>search</Link>
</div>
<ConditionalNull condition={arr.length > 0}>
<div className={styles.SuggestionBox}>
{arr.map(result => (
<div className={styles.SuggestionBoxIndex}>
<Link href={`/search/search/?${stringify({q:result})}`}>
{result}
</Link>
</div>
))}
</div>
</ConditionalNull></>
)
}

View file

@ -0,0 +1,48 @@
.SearchBox {
margin: 16px 0;
width: 100%;
border-radius: 4px;
height: 2em;
background-color: var(--bg-3);
color: var(--fg-3);
display: grid;
grid-template-columns: 1fr auto;
/* overflow: hidden; */
}
.SearchBoxForm {
border-radius: 4px 0 0 4px;
padding: 2px 8px !important;
font-family: var(--font-LexendDeca);
vertical-align: middle;
border: none;
background-color: transparent;
color: currentColor;
}
.SearchBoxForm::placeholder {
color: var(--fg-1);
}
.SearchBoxButton {
display: inline-block;
border-radius: 0 4px 4px 0;
font-family: var(--font-MaterialSymbols);
font-size: 24px;
padding: 0 8px;
vertical-align: middle;
line-height: 1.25em;
cursor: pointer;
text-decoration: none;
}
.SuggestionBox {
margin-top: 8px;
width: 100%;
border-radius: 4px;
background-color: var(--bg-3);
color: var(--fg-2);
padding: 8px;
}
.SuggestionBoxIndex {}

View file

@ -0,0 +1,24 @@
'use client';
export const Sounds = {
alternative: new Audio("/sfx/s_alternative.mp3"),
busy: new Audio("/sfx/s_busy.mp3"),
happy: new Audio("/sfx/s_happy.mp3"),
hover: new Audio("/sfx/s_hover.mp3"),
impossible: new Audio("/sfx/s_impossible.mp3"),
notice: new Audio("/sfx/s_notice.mp3"),
open: new Audio("/sfx/s_open.mp3"),
possible_alt: new Audio("/sfx/s_possible_alt.mp3"),
sad: new Audio("/sfx/s_sad.mp3"),
};
export function preload() {
Object.values(Sounds).forEach((sound) => {
sound.preload = "auto";
})
}
export function playSound(audio:HTMLAudioElement) {
audio.currentTime = 0;
audio.play();
}

View file

@ -54,6 +54,7 @@
background-color: var(--bg-1);
color: var(--fg-1);
border-right: 1px solid var(--neutral);
overflow-y: scroll;
}
.MainLayout_Aside.Modifier_Open {}
@ -72,6 +73,7 @@
background-color: var(--bg-2);
color: var(--fg-2);
border-bottom: 1px solid var(--neutral);
overflow: hidden;
display: grid;
grid-template-columns: auto;
@ -86,7 +88,7 @@
.MainLayout_Inner_Header.Modifier_Back {
padding: 6px 8px;
grid-template-columns: 32px auto;
grid-template-columns: 32px 1fr;
}
.MainLayout_Inner_Header_Back_Button {
@ -106,18 +108,30 @@
justify-content: center;
align-items: flex-start;
align-content: center;
width: 100%;
overflow: hidden;
}
.MainLayout_Inner_Header_Title h1 {
display: inline-block;
margin: 0;
vertical-align: middle;
font-size: 1em;
text-wrap: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.MainLayout_Inner_Header_Title span {
display: inline-block;
margin: 0;
vertical-align: middle;
font-size: 0.75em;
text-wrap: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.MainLayout_Inner_Main {

View file

@ -16,5 +16,5 @@ export function MainLayout({
sidebar?: React.ReactNode,
currentPage: string
}) {
return <Desktop title={title} subtitle={subtitle} backButton={backButton} sidebar={sidebar ?? SidebarMain({currentPage})}>{children}</Desktop>
return <Desktop title={title} subtitle={subtitle} backButton={backButton} sidebar={sidebar ?? <SidebarMain currentPage={currentPage} />}>{children}</Desktop>
}

View file

@ -21,10 +21,24 @@
background-color: var(--bg-2);
}
.Main_List_Button {
/* .Main_List_Button {
transition: scale 0.0625s;
}
.Main_List_Button:active {
scale: 0.95;
}
}
*/ .Main_List_Button_Slim {
padding: 2px 8px !important;
background-color: var(--bg-3);
color: var(--fg-2);
}
.Main_List_Button_Slim:hover {
background-color: var(--bg-2);
color: var(--fg-1);
}
/* .Main_List_Button_Slim:active {
scale: 1;
} */

View file

@ -1,62 +1,133 @@
'use client';
import Link from "next/link";
import styles from "./Main.module.css";
// import useSound from 'use-sound';
export function SidebarMain({currentPage}:{currentPage:string}) {
// const [openPlay] = useSound("/sfx/s_open.mp3");
// const [impossiblePlay] = useSound("/sfx/s_impossible.mp3");
// const [hoverPlay] = useSound("/sfx/s_hover.mp3");
return <>
<h1>abtmtr.link</h1>
{/* <div className={styles.Main_Image}>
<img src="/favicon.ico" width="128" height="128" />
</div> */}
<div className={styles.Main_List}>
<Link href="/" className={currentPage === "/" ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/"
className={currentPage === "/" ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage === "/" ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">home</span>
<span>Root</span>
</div>
</Link>
<Link href="/projects/" className={currentPage.includes("/projects/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/search/"
className={currentPage.includes("/search/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage === "/" ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">search</span>
<span>Search</span>
</div>
</Link>
<Link
href="/projects/"
className={currentPage.includes("/projects/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/projects/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">folder</span>
<span>Projects</span>
</div>
</Link>
<Link href="/characters/" className={currentPage.includes("/characters/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/characters/"
className={currentPage.includes("/characters/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/characters/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">group</span>
<span>Characters</span>
</div>
</Link>
<Link href="/blog/" className={currentPage.includes("/blog/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/blog/"
className={currentPage.includes("/blog/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/blog/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">description</span>
<span>Blog</span>
</div>
</Link>
<Link href="/gallery/" className={currentPage.includes("/gallery/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/gallery/"
className={currentPage.includes("/gallery/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/gallery/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">image</span>
<span>Gallery</span>
</div>
</Link>
<Link href="/stories/" className={currentPage.includes("/stories/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/stories/"
className={currentPage.includes("/stories/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/stories/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">book</span>
<span>Stories</span>
</div>
</Link>
<Link href="/links/" className={currentPage.includes("/links/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/links/"
className={currentPage.includes("/links/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/links/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">link</span>
<span>Links</span>
</div>
</Link>
<Link href="/oao/" className={currentPage.includes("/oao/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/oao/"
className={currentPage.includes("/oao/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/oao/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">campaign</span>
<span>Opinions & Objections</span>
</div>
</Link>
<Link href="/about/" className={currentPage.includes("/about/") ? styles.Main_List_CurrentLink : ""} tabIndex={-1}>
<Link
href="/about/"
className={currentPage.includes("/about/") ? styles.Main_List_CurrentLink : ""}
tabIndex={-1}
// onClick={() => currentPage.includes("/about/") ? impossiblePlay() : openPlay()}
// onMouseEnter={hoverPlay}
>
<div className={`fw ${styles.Main_List_Button}`}>
<span className="icon">info</span>
<span>About</span>