aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2023-07-11 22:54:23 -0400
committerBobby <[email protected]>2023-07-11 22:54:23 -0400
commit1038819ecd3af7056fba5121ff46a2ac748468f9 (patch)
treec215066d2915ebd95b80bfd1a226b26faaf7e5c8
parent0dfce68729c7bf768b035157849366fb40638bca (diff)
downloadthatcomputerscientist-1038819ecd3af7056fba5121ff46a2ac748468f9.tar.xz
thatcomputerscientist-1038819ecd3af7056fba5121ff46a2ac748468f9.zip
Music working. Welcome page added
-rw-r--r--solitude/constants/welcome_playlist.py40
-rw-r--r--solitude/urls.py2
-rw-r--r--solitude/views.py9
-rw-r--r--static/@solitude/css/shared.css0
-rw-r--r--static/@solitude/css/welcome/audio.css142
-rw-r--r--static/@solitude/css/welcome/welcome.css98
-rw-r--r--static/@solitude/music/welcome/cover_art/default.jpegbin0 -> 10508 bytes
-rw-r--r--static/@solitude/music/welcome/cover_art/dripping.webpbin0 -> 8960 bytes
-rw-r--r--static/@solitude/music/welcome/cover_art/sleepy_rain.webpbin0 -> 18214 bytes
-rw-r--r--static/@solitude/music/welcome/cover_art/wish_you_were_here.webpbin0 -> 9750 bytes
-rw-r--r--static/@solitude/music/welcome/dripping.mp3bin0 -> 4451265 bytes
-rw-r--r--static/@solitude/music/welcome/rain_and_nostalgia_v60s.mp3bin0 -> 2255307 bytes
-rw-r--r--static/@solitude/music/welcome/sleepy_rain.mp3bin0 -> 2034625 bytes
-rw-r--r--static/@solitude/music/welcome/wish_you_were_here.mp3bin0 -> 5014674 bytes
-rw-r--r--static/@solitude/videos/solitude_welcome.mp4bin0 -> 14740048 bytes
-rw-r--r--templates/@solitude/welcome.html238
16 files changed, 525 insertions, 4 deletions
diff --git a/solitude/constants/welcome_playlist.py b/solitude/constants/welcome_playlist.py
new file mode 100644
index 00000000..628327ce
--- /dev/null
+++ b/solitude/constants/welcome_playlist.py
@@ -0,0 +1,40 @@
+"""
+ Shifoo's Solitude by Bobby
+ --------------------------
+ Shifoo's Solitude is a Web Dungeon located beyond the Dark Hollows of the Endless Information SuperHighway — a dark yet tranquil place where all questions end, curiosity begins, the mind awakens, and one's journey begins anew in the solitude of a serene mind!
+ --------------------------
+
+ File: welcome_playlist.py
+ Description: Contains Metadata for tracks in the Welcome Page
+ Date: Jul 11, 2023
+ Last Modified: Jul 11, 2023
+"""
+BASE_MUSIC_DIR = "/static/@solitude/music/welcome"
+BASE_COVER_ART_DIR = "/static/@solitude/music/welcome/cover_art"
+
+WELCOME_TRACKS = {
+ "SleepyRain": {
+ "title": "Sleepy Rain",
+ "artist": "lorenzobuczek",
+ "location": f"{BASE_MUSIC_DIR}/sleepy_rain.mp3",
+ "cover_art": f"{BASE_COVER_ART_DIR}/sleepy_rain.webp",
+ },
+ "RainAndNostalgia": {
+ "title": "Rain and Nostalgia v60s",
+ "artist": "lesfm",
+ "location": f"{BASE_MUSIC_DIR}/rain_and_nostalgia_v60s.mp3",
+ "cover_art": f"{BASE_COVER_ART_DIR}/default.jpeg",
+ },
+ "WishYouWereHere": {
+ "title": "Wish You Were Here",
+ "artist": "Lofi_hour",
+ "location": f"{BASE_MUSIC_DIR}/wish_you_were_here.mp3",
+ "cover_art": f"{BASE_COVER_ART_DIR}/wish_you_were_here.webp",
+ },
+ "Dripping": {
+ "title": "Dripping",
+ "artist": "Lofi_hour",
+ "location": f"{BASE_MUSIC_DIR}/dripping.mp3",
+ "cover_art": f"{BASE_COVER_ART_DIR}/dripping.webp",
+ },
+}
diff --git a/solitude/urls.py b/solitude/urls.py
index 68819664..c4458ebe 100644
--- a/solitude/urls.py
+++ b/solitude/urls.py
@@ -5,5 +5,5 @@ from . import views
app_name = 'solitude'
urlpatterns = [
- path('', views.home, name='home'),
+ path('', views.welcome, name='welcome'),
]
diff --git a/solitude/views.py b/solitude/views.py
index 212c84eb..da2e06ca 100644
--- a/solitude/views.py
+++ b/solitude/views.py
@@ -1,7 +1,12 @@
from django.shortcuts import render
+from .constants.welcome_playlist import WELCOME_TRACKS
+
+import json
# Create your views here.
TEMPLATE_BASE_PATH = '@solitude'
-def home(request):
- return render(request, f'{TEMPLATE_BASE_PATH}/welcome.html')
+def welcome(request):
+ return render(request, f'{TEMPLATE_BASE_PATH}/welcome.html', {
+ 'playlist_tracks': str(json.dumps(WELCOME_TRACKS))
+ })
diff --git a/static/@solitude/css/shared.css b/static/@solitude/css/shared.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/static/@solitude/css/shared.css
diff --git a/static/@solitude/css/welcome/audio.css b/static/@solitude/css/welcome/audio.css
new file mode 100644
index 00000000..ca5b144c
--- /dev/null
+++ b/static/@solitude/css/welcome/audio.css
@@ -0,0 +1,142 @@
+.audio-bars {
+ position: relative;
+ display: flex;
+ width: auto;
+ transform: scale3d(2, 2, 1); /* EZ SCALE */
+}
+.bar {
+ background: #fff;
+ height: 20px;
+ width: 2px;
+ margin-right: 2px;
+}
+.bar:last-child {
+ margin-right: 0;
+}
+
+@keyframes sound {
+ 0% {
+ transform: scale3d(1, 0.1, 1);
+ }
+ 100% {
+ transform: scale3d(1, 1, 1);
+ }
+}
+@keyframes sound2 {
+ 0% {
+ transform: scale3d(1, 0.1, 1);
+ }
+ 100% {
+ transform: scale3d(1, 0.5, 1);
+ }
+}
+
+.bar:nth-child(1) {
+ animation: sound2 0ms -800ms linear infinite alternate;
+ animation-duration: 200ms;
+}
+.bar:nth-child(2) {
+ animation: sound 0ms -800ms linear infinite alternate;
+ animation-duration: 300ms;
+}
+.bar:nth-child(3) {
+ animation: sound 0ms -800ms linear infinite alternate;
+ animation-duration: 200ms;
+}
+.bar:nth-child(4) {
+ animation: sound 0ms -800ms linear infinite alternate;
+ animation-duration: 250ms;
+}
+.bar:nth-child(5) {
+ animation: sound2 0ms -800ms linear infinite alternate;
+ animation-duration: 150ms;
+}
+
+#welcome-playlist-player {
+ background: rgba(0, 0, 0, 0.5);
+ border-radius: 16px 0 0 16px;
+ box-shadow: 0 4px 30px rgba(255, 255, 255, 0.1);
+ backdrop-filter: blur(5.5px);
+ -webkit-backdrop-filter: blur(5.5px);
+ border: 1px solid rgba(0, 0, 0, 0.3);
+ padding: 16px;
+ position: absolute;
+ bottom: 2rem;
+ right: 0;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 1.5rem;
+ transition: all 0.5s ease;
+}
+
+.controls {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 1rem;
+ height: 1rem;
+ padding: 0.8rem;
+ border: 0.2rem solid var(--button-color);
+ border-radius: 50%;
+ filter: drop-shadow(0 0 0.5rem rgba(255, 255, 255, 0.8));
+}
+
+.player {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 1.5rem;
+}
+
+.play {
+ height: 0;
+ width: 0;
+ margin-left: calc(2 * 0.25 * var(--button-height));
+ /*margin-left: 17px;*/
+ background: none;
+ border: none;
+ border-top: var(--button-height) solid transparent;
+ border-bottom: var(--button-height) solid transparent;
+ border-left: calc(var(--button-height) * 2 * 0.86) solid var(--button-color);
+}
+
+.pause {
+ position: relative;
+ background: none;
+ border: none;
+ height: calc(var(--button-height) * 2);
+ width: calc(var(--button-height) * 2 * 0.86);
+}
+.pause:before,
+.pause:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ height: 100%;
+ width: 33%;
+ background: var(--button-color);
+}
+.pause:before {
+ left: 0;
+}
+.pause:after {
+ right: 0;
+}
+
+.hidden {
+ display: none;
+}
+
+.title {
+ color: #7679f5;
+}
+
+.artist {
+ color: #e2fdff;
+}
+
+.track {
+ letter-spacing: 0.1rem;
+}
+
diff --git a/static/@solitude/css/welcome/welcome.css b/static/@solitude/css/welcome/welcome.css
new file mode 100644
index 00000000..22a1a747
--- /dev/null
+++ b/static/@solitude/css/welcome/welcome.css
@@ -0,0 +1,98 @@
+/*
+ Shifoo's Solitude by Bobby
+ --------------------------
+ Shifoo's Solitude is a Web Dungeon located beyond the Dark Hollows of the Endless Information SuperHighway — a dark yet tranquil place where all questions end, curiosity begins, the mind awakens, and one's journey begins anew in the solitude of a serene mind!
+ --------------------------
+
+ File: welcome.css
+ Description: CSS for the welcome page (exclusively)
+ Date: Jul 11, 2023
+ Last Modified: Jul 11, 2023
+*/
+@import url("https://fonts.googleapis.com/css2?family=Handlee&family=Poppins:wght@400&family=Share:wght@700&display=swap");
+@import url(audio.css);
+:root {
+ --button-height: 0.5rem;
+ --button-color: #edd;
+ color-schema: dark;
+ font-family: "Handlee", cursive;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ color: white;
+}
+
+#cover-video {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ object-fit: cover;
+ z-index: -100;
+}
+
+#cover-wrapper {
+ position: fixed;
+ top: 0;
+ left: 0;
+ min-width: 100%;
+ min-height: 100%;
+ height: 100%;
+ width: 100%;
+ background-color: rgba(0, 0, 0, 0.15);
+ z-index: -99;
+}
+
+#welcome-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-height: 100vh;
+}
+
+.cwrapper {
+ text-align: center;
+}
+
+p {
+ margin: 0;
+ padding: 0;
+}
+
+.small {
+ font-size: 0.8rem;
+ margin: 0.5rem 0;
+ color: #aaa;
+}
+
+#welcome-button {
+ font-family: "Poppins", sans-serif;
+ font-size: 1.5rem;
+ padding: 0.5rem 1rem;
+ border-radius: 0.5rem;
+ transition: all 0.2s ease-in-out;
+ margin-top: 10rem;
+}
+
+.description {
+ font-family: "Share", sans-serif;
+ font-size: 1rem;
+ margin-top: -4rem;
+ letter-spacing: 0.1rem;
+}
+
+.text-box {
+ font-family: "Share", cursive;
+}
+
+.text-box > h1 {
+ margin: 0;
+ font-size: 10rem;
+ color: rgb(255 255 255 / 60%);
+ padding: .5em;
+}
+
diff --git a/static/@solitude/music/welcome/cover_art/default.jpeg b/static/@solitude/music/welcome/cover_art/default.jpeg
new file mode 100644
index 00000000..39937665
--- /dev/null
+++ b/static/@solitude/music/welcome/cover_art/default.jpeg
Binary files differ
diff --git a/static/@solitude/music/welcome/cover_art/dripping.webp b/static/@solitude/music/welcome/cover_art/dripping.webp
new file mode 100644
index 00000000..3edb2ce3
--- /dev/null
+++ b/static/@solitude/music/welcome/cover_art/dripping.webp
Binary files differ
diff --git a/static/@solitude/music/welcome/cover_art/sleepy_rain.webp b/static/@solitude/music/welcome/cover_art/sleepy_rain.webp
new file mode 100644
index 00000000..a9bd0566
--- /dev/null
+++ b/static/@solitude/music/welcome/cover_art/sleepy_rain.webp
Binary files differ
diff --git a/static/@solitude/music/welcome/cover_art/wish_you_were_here.webp b/static/@solitude/music/welcome/cover_art/wish_you_were_here.webp
new file mode 100644
index 00000000..4ed66ea7
--- /dev/null
+++ b/static/@solitude/music/welcome/cover_art/wish_you_were_here.webp
Binary files differ
diff --git a/static/@solitude/music/welcome/dripping.mp3 b/static/@solitude/music/welcome/dripping.mp3
new file mode 100644
index 00000000..b0e2e1c5
--- /dev/null
+++ b/static/@solitude/music/welcome/dripping.mp3
Binary files differ
diff --git a/static/@solitude/music/welcome/rain_and_nostalgia_v60s.mp3 b/static/@solitude/music/welcome/rain_and_nostalgia_v60s.mp3
new file mode 100644
index 00000000..b5146189
--- /dev/null
+++ b/static/@solitude/music/welcome/rain_and_nostalgia_v60s.mp3
Binary files differ
diff --git a/static/@solitude/music/welcome/sleepy_rain.mp3 b/static/@solitude/music/welcome/sleepy_rain.mp3
new file mode 100644
index 00000000..5b5e4eb8
--- /dev/null
+++ b/static/@solitude/music/welcome/sleepy_rain.mp3
Binary files differ
diff --git a/static/@solitude/music/welcome/wish_you_were_here.mp3 b/static/@solitude/music/welcome/wish_you_were_here.mp3
new file mode 100644
index 00000000..9aece37c
--- /dev/null
+++ b/static/@solitude/music/welcome/wish_you_were_here.mp3
Binary files differ
diff --git a/static/@solitude/videos/solitude_welcome.mp4 b/static/@solitude/videos/solitude_welcome.mp4
new file mode 100644
index 00000000..623c5cd9
--- /dev/null
+++ b/static/@solitude/videos/solitude_welcome.mp4
Binary files differ
diff --git a/templates/@solitude/welcome.html b/templates/@solitude/welcome.html
index a3fd191e..9c07dad2 100644
--- a/templates/@solitude/welcome.html
+++ b/templates/@solitude/welcome.html
@@ -1 +1,237 @@
-<h1>Shifoo's Solitude</h1> \ No newline at end of file
+{% load static %}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>Shifoo's Solitude | Welcome</title>
+ <meta name="description" content="Welcome to Shifoo's Solitude — A Web Dungeon located beyond the Dark Hollows of the Endless Information SuperHighway — a dark yet tranquil place where all questions end, curiosity begins, the mind awakens, and one's journey begins anew in the solitude of a serene mind!" />
+ <link rel="stylesheet"type="text/css" href="{% static '@solitude/css/welcome/welcome.css' %}" />
+ </head>
+ <body>
+ <video id="cover-video" autoplay muted playsinline loop preload="auto" nocontrols>
+ <source src="{% static '@solitude/videos/solitude_welcome.mp4' %}#t=0.1" type="video/mp4" />
+ </video>
+ </div><div id="cover-wrapper">
+ <div id="welcome-content">
+ <div class="cwrapper">
+ <div class="text-box">
+ <h1>THE SOLITUDE</h1>
+ </div>
+ </div>
+ <p class="description"></p>
+ <button id="enter">Enter The Solitude!</button>
+ <div id="welcome-playlist-player">
+ <div class="controls">
+ <button role="play" id="playButton" class="play"></button>
+ <button role="pause" id="pauseButton" class="pause hidden"></button>
+ </div>
+ <img id="album-art" src="" alt="Album Art" width="100" height="100" />
+ <div class="player">
+ <div class="audio-bars">
+ <div class="bar"></div>
+ <div class="bar"></div>
+ <div class="bar"></div>
+ <div class="bar"></div>
+ <div class="bar"></div>
+ </div>
+ <div class="audio-info">
+ <p class="small">Currently Playing</p>
+ <p class="track"><span id="track-title" class="title">Sleepy Rain</span> by <span id="track-artist" class="artist">lorenzzo</span></p>
+ <p class="small"><span id="min-elap">00</span>:<span id="sec-elap">00</span> / <span id="min-dur">00</span>:<span id="sec-dur">00</span></p>
+ <audio id="audio" preload="auto" nocontrols preload="auto">
+ <source src="" type="audio/mp3" />
+ </audio>
+ </div>
+ </div>
+ </div>
+ </div>
+ <script>
+ Object.defineProperty(Array.prototype, 'shuffle', {
+ value: function() {
+ for (let i = this.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [this[i], this[j]] = [this[j], this[i]];
+ }
+ return this;
+ }
+ });
+
+ const playlistTracks = JSON.parse("{{ playlist_tracks }}".replace(/&quot;/g, '"'));
+ const tracks = Object.entries(playlistTracks).map(track => track[1]).shuffle();
+
+ const controls = document.querySelector('.controls');
+ const audio = document.querySelector('#audio');
+ const trackTitle = document.querySelector('#track-title');
+ const trackArtist = document.querySelector('#track-artist');
+ const albumArt = document.querySelector('#album-art');
+ const minElap = document.querySelector('#min-elap');
+ const secElap = document.querySelector('#sec-elap');
+ const minDur = document.querySelector('#min-dur');
+ const secDur = document.querySelector('#sec-dur');
+
+ let currentTrack = 0;
+
+ const loadAudio = new Promise((resolve, reject) => {
+ audio.addEventListener('canplaythrough', () => {
+ resolve(audio);
+ });
+ });
+
+ async function playAudio () {
+ audio.src = tracks[currentTrack].location;
+ const duration = audio.duration;
+ audio.play().catch(e => {
+ window.addEventListener('click', () => {
+ controls.click();
+ audio.play();
+ }, { once: true });
+ });
+ return audio;
+ }
+
+ function pauseAudio () {
+ audio.pause();
+ }
+
+ function nextTrack () {
+ currentTrack = (currentTrack + 1) % tracks.length;
+ audio.currentTime = 0;
+ playTrack();
+ }
+
+ function playTrack() {
+ const track = tracks[currentTrack];
+ trackTitle.textContent = track.title;
+ trackArtist.textContent = track.artist;
+ albumArt.src = track.cover_art;
+ playAudio().then(audio => {
+ audio.addEventListener('ended', nextTrack);
+ });
+ }
+
+ function updateIntervals() {
+ const duration = audio.duration;
+ const currentTime = audio.currentTime;
+ const elapsed = Math.floor(currentTime);
+ const total = Math.floor(duration);
+ const minutesElapsed = Math.floor(elapsed / 60);
+ const secondsElapsed = elapsed % 60;
+ const minutesTotal = Math.floor(total / 60) || 0;
+ const secondsTotal = total % 60 || 0;
+ minElap.textContent = minutesElapsed < 10 ? `0${minutesElapsed}` : minutesElapsed;
+ secElap.textContent = secondsElapsed < 10 ? `0${secondsElapsed}` : secondsElapsed;
+ minDur.textContent = minutesTotal < 10 ? `0${minutesTotal}` : minutesTotal;
+ secDur.textContent = secondsTotal < 10 ? `0${secondsTotal}` : secondsTotal;
+ }
+
+ function togglePlayPause () {
+ const buttons = Array.from(this.children);
+ let triggeredButton;
+ buttons.forEach(button => {
+ if (!button.classList.contains('hidden')) {
+ triggeredButton = button;
+ }
+ button.classList.toggle('hidden')
+ });
+ signalTrigger(triggeredButton);
+ };
+
+ function signalTrigger (button) {
+ const role = button.getAttribute('role');
+ switch (role) {
+ case 'play':
+ playAudio();
+ break;
+ case 'pause':
+ pauseAudio();
+ break;
+ }
+ }
+
+ audio.currentTime = 0;
+ controls.addEventListener('click', togglePlayPause);
+ audio.addEventListener('timeupdate', updateIntervals);
+
+ playTrack();
+
+ class TextScramble {
+ constructor(el) {
+ this.el = el
+ this.chars = '!<>-_\\/[]{}—=+*^?#________'
+ this.update = this.update.bind(this)
+ }
+ setText(newText) {
+ const oldText = this.el.innerText
+ const length = Math.max(oldText.length, newText.length)
+ const promise = new Promise((resolve) => this.resolve = resolve)
+ this.queue = []
+ for (let i = 0; i < length; i++) {
+ const from = oldText[i] || ''
+ const to = newText[i] || ''
+ const start = Math.floor(Math.random() * 40)
+ const end = start + Math.floor(Math.random() * 40)
+ this.queue.push({ from, to, start, end })
+ }
+ cancelAnimationFrame(this.frameRequest)
+ this.frame = 0
+ this.update()
+ return promise
+ }
+ update() {
+ let output = ''
+ let complete = 0
+ for (let i = 0, n = this.queue.length; i < n; i++) {
+ let { from, to, start, end, char } = this.queue[i]
+ if (this.frame >= end) {
+ complete++
+ output += to
+ } else if (this.frame >= start) {
+ if (!char || Math.random() < 0.28) {
+ char = this.randomChar()
+ this.queue[i].char = char
+ }
+ output += `<span class="dud">${char}</span>`
+ } else {
+ output += from
+ }
+ }
+ this.el.innerHTML = output
+ if (complete === this.queue.length) {
+ this.resolve()
+ } else {
+ this.frameRequest = requestAnimationFrame(this.update)
+ this.frame++
+ }
+ }
+ randomChar() {
+ return this.chars[Math.floor(Math.random() * this.chars.length)]
+ }
+ }
+
+ const phrases = [
+ 'Welcome to Shifoo\'s Solitude',
+ 'A Web Dungeon located beyond the Dark Hollows of the Endless Information SuperHighway',
+ 'a dark yet tranquil place where all questions end, curiosity begins, the mind awakens,',
+ 'and one\'s journey begins anew in the solitude of a serene mind!',
+ 'The Solitude awaits your arrival...'
+ ]
+
+ const el = document.querySelector('.description')
+ const fx = new TextScramble(el)
+
+ let counter = 0
+ const next = () => {
+ fx.setText(phrases[counter]).then(() => {
+ setTimeout(next, 3200)
+ })
+ counter = (counter + 1) % phrases.length
+ }
+
+ next()
+
+ </script>
+
+ </body>
+</html>