index.astro 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. ---
  2. import Layout from "../layouts/Layout.astro";
  3. import Taskbar from "../components/taskbar.astro";
  4. import App from "../components/app.astro";
  5. import Aboutme from "../components/aboutme.astro";
  6. import Redirect from "../components/redirect.astro";
  7. import Contact from "../components/contact.astro";
  8. import Pgp from "../components/pgp.astro";
  9. import Projects from "../components/projects.astro";
  10. import PastWork from "../components/pastwork.astro";
  11. import Duolingo from "../components/duolingo.astro";
  12. import GitHubGraph from "../components/githubgraph.astro";
  13. import NowPlaying from "../components/nowplaying.astro";
  14. import Ram from "../components/ram.astro";
  15. // Projects
  16. import Summize from "../components/projects/summize.astro";
  17. import Notion from "../components/projects/notion.astro";
  18. // import Imdb from "../components/projects/imdb.astro";
  19. import "../styles/global.css";
  20. import me from "../assets/apps/me.png";
  21. import github from "../assets/apps/github.png";
  22. import pastwork from "../assets/apps/pastWork.png";
  23. import projects from "../assets/apps/projects.png";
  24. import blog from "../assets/apps/blog.png";
  25. import contact from "../assets/apps/contact.png";
  26. import pgp from "../assets/apps/pgp.png";
  27. import Glance from "../components/projects/glance.astro";
  28. import ramIcon from "../assets/apps/blog.png";
  29. function dragElement(elmnt) {
  30. var pos1 = 0,
  31. pos2 = 0,
  32. pos3 = 0,
  33. pos4 = 0;
  34. if (document.getElementById(elmnt.id + "header")) {
  35. document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  36. document.getElementById(elmnt.id + "header").ontouchstart = dragMouseDown;
  37. } else {
  38. elmnt.onmousedown = dragMouseDown;
  39. elmnt.ontouchstart = dragMouseDown;
  40. }
  41. function dragMouseDown(e) {
  42. // e.preventDefault();
  43. raiseUpSpec(elmnt.id);
  44. if (e.type == "touchstart") {
  45. pos3 = e.touches[0].clientX;
  46. pos4 = e.touches[0].clientY;
  47. } else {
  48. pos3 = e.clientX;
  49. pos4 = e.clientY;
  50. }
  51. document.onmouseup = closeDragElement;
  52. document.ontouchend = closeDragElement;
  53. document.onmousemove = elementDrag;
  54. document.ontouchmove = elementDrag;
  55. }
  56. function elementDrag(e) {
  57. // e.preventDefault();
  58. if (e.type == "touchmove") {
  59. pos1 = pos3 - e.touches[0].clientX;
  60. pos2 = pos4 - e.touches[0].clientY;
  61. pos3 = e.touches[0].clientX;
  62. pos4 = e.touches[0].clientY;
  63. } else {
  64. pos1 = pos3 - e.clientX;
  65. pos2 = pos4 - e.clientY;
  66. pos3 = e.clientX;
  67. pos4 = e.clientY;
  68. }
  69. elmnt.style.top = elmnt.offsetTop - pos2 + "px";
  70. elmnt.style.left = elmnt.offsetLeft - pos1 + "px";
  71. }
  72. function closeDragElement() {
  73. document.onmouseup = null;
  74. document.ontouchend = null;
  75. document.onmousemove = null;
  76. document.ontouchmove = null;
  77. }
  78. }
  79. /** Raise up window with given ID */
  80. function raiseUpSpec(id: string) {
  81. console.log("raising ", id);
  82. let els = document.getElementsByClassName("window");
  83. let elArray = Array.from(els as HTMLCollectionOf<HTMLElement>);
  84. // find the highest z-index
  85. let highestIndex = 0;
  86. for (let element in elArray) {
  87. let zindex = parseInt(elArray[element].style.zIndex);
  88. if (zindex > highestIndex) {
  89. highestIndex = zindex;
  90. }
  91. }
  92. // set the highest z-index plus one
  93. document.getElementById(id).style.zIndex = (highestIndex + 1).toString();
  94. }
  95. function updateRedirectMessage() {
  96. const redirectElement = document.getElementById("Redirect");
  97. const redirectUrl = redirectElement.dataset.redirecturl; // Access the data attribute
  98. const messageElement = redirectElement.querySelector("h2");
  99. messageElement.innerHTML = `You are about to be redirected to <a class="redirUrl" style=" cursor: pointer;
  100. color: blue;
  101. text-decoration: underline; " href="${redirectUrl}"">${redirectUrl.replace("https://", "")}</a>`;
  102. const buttonElement = redirectElement.querySelector("#okButton");
  103. // open redirect url
  104. buttonElement.setAttribute(
  105. "onclick",
  106. `window.location.href = "${redirectUrl}"`
  107. );
  108. }
  109. let apps: app[] = [
  110. {
  111. name: "About Me",
  112. logo: me.src,
  113. onclick: () => {
  114. raiseUpSpec("About Me");
  115. document.getElementById("About Me").style.display = "block";
  116. },
  117. row: 1,
  118. },
  119. // {
  120. // name: "Blog",
  121. // logo: blog.src,
  122. // onclick: () => {
  123. // raiseUpSpec("Redirect");
  124. // document.getElementById("Redirect").style.display = "block";
  125. // document.getElementById("Redirect").dataset.redirecturl =
  126. // "https://blog.simo.ng/";
  127. // updateRedirectMessage();
  128. // },
  129. // row: 1,
  130. // },
  131. {
  132. name: "Projects",
  133. logo: projects.src,
  134. onclick: () => {
  135. raiseUpSpec("Projects ");
  136. document.getElementById("Projects ").style.display = "block";
  137. },
  138. row: 1,
  139. },
  140. // {
  141. // name: "Past Work",
  142. // logo: pastwork.src,
  143. // row: 1,
  144. // },
  145. {
  146. name: "Past Work",
  147. logo: pastwork.src,
  148. onclick: () => {
  149. raiseUpSpec("Past Work");
  150. document.getElementById("Past Work").style.display = "block";
  151. },
  152. row: 1,
  153. },
  154. {
  155. name: "Git",
  156. logo: github.src,
  157. onclick: () => {
  158. // ignore
  159. raiseUpSpec("Redirect");
  160. document.getElementById("Redirect").style.display = "block";
  161. document.getElementById("Redirect").dataset.redirecturl =
  162. "https://git.simo.ng/simo";
  163. updateRedirectMessage();
  164. },
  165. row: 2,
  166. },
  167. {
  168. name: "RAM",
  169. logo: ramIcon.src,
  170. onclick: () => {
  171. raiseUpSpec("ram");
  172. document.getElementById("ram").style.display = "block";
  173. },
  174. row: 2,
  175. },
  176. {
  177. name: "Contact",
  178. logo: contact.src,
  179. row: 2,
  180. onclick: () => {
  181. raiseUpSpec("contact");
  182. document.getElementById("contact").style.display = "block";
  183. },
  184. },
  185. {
  186. name: "PGP Key",
  187. logo: pgp.src,
  188. row: 1,
  189. onclick: () => {
  190. raiseUpSpec("pgp");
  191. document.getElementById("pgp").classList.add("fullscreen");
  192. document.getElementById("pgp").style.display = "block";
  193. },
  194. },
  195. ];
  196. let projectsArr: project[] = [
  197. {
  198. title: "Glance",
  199. id: "glance",
  200. },
  201. {
  202. title: "Summize",
  203. id: "summize",
  204. },
  205. {
  206. title: "Notion2Canvas",
  207. id: "notion",
  208. },
  209. ];
  210. const row1Items = apps.filter((item) => item.row === 1);
  211. const row2Items = apps.filter((item) => item.row === 2);
  212. let clientFunctions: Function[] | String[] = [
  213. raiseUpSpec,
  214. updateRedirectMessage,
  215. dragElement,
  216. updateRedirectMessage,
  217. ];
  218. clientFunctions = clientFunctions.map((item) => String(item));
  219. apps = apps.map((item) => {
  220. item.onclick = String(item.onclick);
  221. return item;
  222. });
  223. ---
  224. <Layout title="Simo">
  225. <div style="width: 100%; height: calc(100vh - 3.5rem); ">
  226. <Pgp />
  227. <div style="display: flex;">
  228. <div
  229. style="height: 20rem; display: flex; flex-direction: column; align-items: flex-start;"
  230. >
  231. {row1Items.map((item) => <App {item} />)}
  232. </div>
  233. <div
  234. style="height: 20rem; display: flex; flex-direction: column; align-items: flex-start;"
  235. >
  236. {row2Items.map((item) => <App {item} />)}
  237. </div>
  238. </div>
  239. <Aboutme />
  240. <Redirect />
  241. <Contact />
  242. <iframe
  243. id="SimoSearch"
  244. title="SimoSearch"
  245. src="https://search.simo.ng/#embed"
  246. loading="lazy"
  247. referrerpolicy="no-referrer"
  248. allowfullscreen
  249. style="
  250. display: none;
  251. position: absolute;
  252. left: 62%;
  253. top: 10%;
  254. border: 0;
  255. outline: 0;
  256. background: transparent;
  257. "
  258. ></iframe>
  259. <Ram />
  260. <NowPlaying />
  261. <PastWork />
  262. <Projects projects={projectsArr} />
  263. <Summize />
  264. <Notion />
  265. <Glance />
  266. <Duolingo />
  267. <GitHubGraph />
  268. </div>
  269. <Taskbar />
  270. </Layout>
  271. <script define:vars={{ apps, projectsArr, clientFunctions }}>
  272. let dino = `
  273. ██████████████
  274. ████░░████████████
  275. ██████████████████
  276. ██████████████████
  277. ██████████████████
  278. ████████
  279. ██████████████░░
  280. ██████
  281. ██ ██████████
  282. ██▒▒ ▒▒▒▒██████████▒▒▒▒
  283. ████▓▓ ██████████████ ▒▒
  284. ██████▒▒▒▒████████████████
  285. ██████████████████████████
  286. ██████████████████████
  287. ██████████████████
  288. ▒▒██████████████
  289. ▒▒██████▒▒██▓▓
  290. ████ ▓▓
  291. ██▒▒ ▓▓
  292. ██ ██
  293. `;
  294. console.log(dino);
  295. for (func in clientFunctions) {
  296. eval(clientFunctions[func]);
  297. }
  298. Array.from(document.getElementsByClassName("project")).forEach((project) => {
  299. // console.log(projectsArr[0].id + "item");
  300. let id = projectsArr.find((i) => i.id + "item" == project.id).id;
  301. // console.log(id);
  302. if (id == "pgpcord") {
  303. project.onclick = () => {
  304. setTimeout(() => {
  305. raiseUpSpec("redirect");
  306. document.getElementById("redirect").style.display = "block";
  307. document.getElementById("redirect").dataset.redirecturl =
  308. "https://blog.simo.ng/articles/WIP/pgpcord";
  309. updateRedirectMessage();
  310. }, 1);
  311. };
  312. return;
  313. }
  314. project.onclick = () => {
  315. setTimeout(() => {
  316. console.log(id)
  317. document.getElementsByClassName(id)[0].style.display = "block";
  318. raiseUpSpec(document.getElementsByClassName(id)[0].id);
  319. }, 1);
  320. };
  321. });
  322. Array.from(document.getElementsByClassName("window")).forEach((window) => {
  323. dragElement(window);
  324. window.querySelectorAll('.title-bar-controls button').forEach((btn) => {
  325. btn.addEventListener('mousedown', (e) => e.stopPropagation());
  326. btn.addEventListener('touchstart', (e) => e.stopPropagation());
  327. });
  328. window.addEventListener("click", () => {
  329. raiseUpSpec(window.id);
  330. });
  331. Array.from(document.querySelectorAll(".projectwindow a")).forEach(
  332. (link) => {
  333. link.addEventListener("click", (e) => {
  334. document.getElementById("redirect").style.display = "block";
  335. document.getElementById("redirect").dataset.redirecturl = link.href;
  336. updateRedirectMessage();
  337. e.preventDefault();
  338. setTimeout(() => {
  339. raiseUpSpec("redirect");
  340. }, 1);
  341. return false;
  342. });
  343. }
  344. );
  345. const titleButtons = Array.from(
  346. window.querySelectorAll('.title-bar-controls button')
  347. )
  348. const minimizeBtn = titleButtons.find(
  349. (btn) => (btn.getAttribute('aria-label') || '').toLowerCase() === 'minimize'
  350. );
  351. const closeBtn = titleButtons.find(
  352. (btn) => (btn.getAttribute('aria-label') || '').toLowerCase() === 'close'
  353. );
  354. if (minimizeBtn) {
  355. minimizeBtn.addEventListener('click', () => {
  356. minimizeWindow(window.id);
  357. });
  358. }
  359. if (closeBtn) {
  360. closeBtn.addEventListener('click', () => {
  361. window.classList.add('closed');
  362. removeFromTaskbar(window.id);
  363. const onEnd = () => {
  364. window.classList.remove('closed');
  365. window.style.display = 'none';
  366. };
  367. window.addEventListener('animationend', onEnd, { once: true });
  368. setTimeout(() => {
  369. if (window.style.display !== 'none') {
  370. window.classList.remove('closed');
  371. window.style.display = 'none';
  372. }
  373. }, 250);
  374. });
  375. }
  376. });
  377. apps.forEach((app) => {
  378. let itemName = app.name.replace(" ", "");
  379. // console.log(itemName)
  380. if (app.onclick == "undefined") {
  381. return;
  382. }
  383. document.getElementById(itemName).addEventListener("click", () => {
  384. const appFunc = eval(app.onclick);
  385. appFunc();
  386. });
  387. });
  388. function minimizeWindow(windowId) {
  389. const window = document.getElementById(windowId);
  390. addToTaskbar(windowId);
  391. const windowRect = window.getBoundingClientRect();
  392. const taskbarButton = document.getElementById(`taskbar-${windowId}`);
  393. const buttonRect = taskbarButton.getBoundingClientRect();
  394. const translateX = buttonRect.left - windowRect.left;
  395. const translateY = buttonRect.top - windowRect.top;
  396. window.style.transition = "all 0.3s ease-out";
  397. window.style.transform = `translate(${translateX}px, ${translateY}px) scale(0.1)`;
  398. window.style.opacity = "0";
  399. setTimeout(() => {
  400. window.style.display = "none";
  401. window.style.transition = "";
  402. window.style.transform = "";
  403. window.style.opacity = "";
  404. }, 300);
  405. }
  406. function restoreWindow(windowId) {
  407. const window = document.getElementById(windowId);
  408. const taskbarButton = document.getElementById(`taskbar-${windowId}`);
  409. const buttonRect = taskbarButton.getBoundingClientRect();
  410. const windowRect = window.getBoundingClientRect();
  411. const translateX = buttonRect.left - windowRect.left;
  412. const translateY = buttonRect.top - windowRect.top;
  413. window.style.transform = `translate(${translateX}px, ${translateY}px) scale(0.1)`;
  414. window.style.opacity = "0";
  415. window.style.display = "block";
  416. removeFromTaskbar(windowId);
  417. raiseUpSpec(windowId);
  418. requestAnimationFrame(() => {
  419. window.style.transition = "all 0.3s ease-out";
  420. window.style.transform = "translate(0, 0) scale(1)";
  421. window.style.opacity = "1";
  422. setTimeout(() => {
  423. window.style.transition = "";
  424. window.style.transform = "";
  425. window.style.opacity = "";
  426. }, 300);
  427. });
  428. }
  429. function addToTaskbar(windowId) {
  430. const taskbarWindows = document.getElementById("taskbar-windows");
  431. if (document.getElementById(`taskbar-${windowId}`)) {
  432. return;
  433. }
  434. const window = document.getElementById(windowId);
  435. const titleBar = window.querySelector(".title-bar-text");
  436. const title = titleBar ? titleBar.textContent : windowId;
  437. const icon = "";
  438. const button = document.createElement("button");
  439. button.id = `taskbar-${windowId}`;
  440. button.style.cssText = `
  441. min-width: 140px;
  442. max-width: 180px;
  443. height: 2.25rem;
  444. padding: 0 0.5rem;
  445. overflow: hidden;
  446. cursor: pointer;
  447. background-color: #c0c0c0;
  448. box-shadow: -2px -2px #e0dede, -2px 0 #e0dede, 0 -2px #e0dede, -4px -4px white, -4px 0 white, 0 -4px white, 2px 2px #818181, 0 2px #818181, 2px 0 #818181, 2px -2px #e0dede, -2px 2px #818181, -4px 2px white, -4px 4px black, 4px 4px black, 4px 0 black, 0 4px black, 2px -4px white, 4px -4px black;
  449. display: flex;
  450. align-items: center;
  451. gap: 0.35rem;
  452. border: none;
  453. `;
  454. const iconSpan = document.createElement("span");
  455. iconSpan.textContent = icon;
  456. iconSpan.style.cssText = `
  457. font-size: 18px;
  458. flex-shrink: 0;
  459. line-height: 1;
  460. `;
  461. const textSpan = document.createElement("span");
  462. textSpan.textContent = title;
  463. textSpan.style.cssText = `
  464. overflow: hidden;
  465. text-overflow: ellipsis;
  466. white-space: nowrap;
  467. font-weight: bold;
  468. font-size: 11px;
  469. letter-spacing: 0.3px;
  470. `;
  471. button.appendChild(iconSpan);
  472. button.appendChild(textSpan);
  473. button.addEventListener("mousedown", () => {
  474. button.style.boxShadow = "-2px -2px #818181, -2px 0 #818181, 0 -2px #818181, -4px -4px black, -4px 0 black, 0 -4px black, 2px 2px #e0dede, 0 2px #e0dede, 2px 0 #e0dede, 2px -2px #818181, -2px 2px #e0dede, -4px 2px black, -4px 4px white, 4px 4px white, 4px 0 white, 0 4px white, 2px -4px black, 4px -4px white";
  475. });
  476. button.addEventListener("mouseup", () => {
  477. button.style.boxShadow = "-2px -2px #e0dede, -2px 0 #e0dede, 0 -2px #e0dede, -4px -4px white, -4px 0 white, 0 -4px white, 2px 2px #818181, 0 2px #818181, 2px 0 #818181, 2px -2px #e0dede, -2px 2px #818181, -4px 2px white, -4px 4px black, 4px 4px black, 4px 0 black, 0 4px black, 2px -4px white, 4px -4px black";
  478. });
  479. button.addEventListener("click", () => {
  480. restoreWindow(windowId);
  481. });
  482. taskbarWindows.appendChild(button);
  483. }
  484. function removeFromTaskbar(windowId) {
  485. const button = document.getElementById(`taskbar-${windowId}`);
  486. if (button) {
  487. button.remove();
  488. }
  489. }
  490. const startButton = document.querySelector('button[aria-label="startButton"]');
  491. if (startButton) {
  492. startButton.addEventListener('click', () => {
  493. const w = document.getElementById('SimoSearch');
  494. if (!w) return;
  495. w.style.display = 'block';
  496. w.style.zIndex = '9999';
  497. });
  498. }
  499. </script>