From 2ce0ccb1106c8b21b2e9d99ecf8e0772cbf6344a Mon Sep 17 00:00:00 2001 From: Bobby Date: Wed, 12 Jul 2023 19:14:06 -0400 Subject: Solitude: Welcome Page Done! Reponds based on `visited` Cookie --- solitude/urls.py | 2 +- solitude/views.py | 14 +- static/@solitude/css/welcome/audio.css | 1 - static/@solitude/css/welcome/button.css | 68 ++++ static/@solitude/css/welcome/glitch.css | 574 +++++++++++++++++++++++++++++++ static/@solitude/css/welcome/welcome.css | 32 +- static/@solitude/js/welcome.js | 113 ++++++ templates/@solitude/home.html | 1 + templates/@solitude/welcome.html | 209 ++--------- 9 files changed, 801 insertions(+), 213 deletions(-) create mode 100644 static/@solitude/css/welcome/button.css create mode 100644 static/@solitude/css/welcome/glitch.css create mode 100644 static/@solitude/js/welcome.js create mode 100644 templates/@solitude/home.html diff --git a/solitude/urls.py b/solitude/urls.py index c4458ebe..68819664 100644 --- a/solitude/urls.py +++ b/solitude/urls.py @@ -5,5 +5,5 @@ from . import views app_name = 'solitude' urlpatterns = [ - path('', views.welcome, name='welcome'), + path('', views.home, name='home'), ] diff --git a/solitude/views.py b/solitude/views.py index da2e06ca..81bc1075 100644 --- a/solitude/views.py +++ b/solitude/views.py @@ -1,3 +1,4 @@ +from django.http import HttpResponse from django.shortcuts import render from .constants.welcome_playlist import WELCOME_TRACKS @@ -6,7 +7,12 @@ import json # Create your views here. TEMPLATE_BASE_PATH = '@solitude' -def welcome(request): - return render(request, f'{TEMPLATE_BASE_PATH}/welcome.html', { - 'playlist_tracks': str(json.dumps(WELCOME_TRACKS)) - }) +def home(request): + is_first_time = request.COOKIES.get('visited', False) + if not is_first_time: + response = render(request, f'{TEMPLATE_BASE_PATH}/welcome.html', { + 'playlist_tracks': str(json.dumps(WELCOME_TRACKS)) + }) + response.set_cookie('visited', True) + return response + return render(request, f'{TEMPLATE_BASE_PATH}/home.html') diff --git a/static/@solitude/css/welcome/audio.css b/static/@solitude/css/welcome/audio.css index ca5b144c..5e0d0c58 100644 --- a/static/@solitude/css/welcome/audio.css +++ b/static/@solitude/css/welcome/audio.css @@ -139,4 +139,3 @@ .track { letter-spacing: 0.1rem; } - diff --git a/static/@solitude/css/welcome/button.css b/static/@solitude/css/welcome/button.css new file mode 100644 index 00000000..48dc5b2e --- /dev/null +++ b/static/@solitude/css/welcome/button.css @@ -0,0 +1,68 @@ +.button { + --offset: 10px; + --border-size: 2px; + display: block; + position: relative; + padding: 1.5em 3em; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border: 0; + background: transparent; + color: #7679f5; + text-transform: uppercase; + letter-spacing: 0.25em; + outline: none; + cursor: pointer; + font-weight: bold; + border-radius: 0; + box-shadow: inset 0 0 0 var(--border-size) currentcolor; + transition: background 0.8s ease; +} +.button:hover { + background: rgba(100, 0, 0, 0.03); +} +.button__horizontal, +.button__vertical { + position: absolute; + top: var(--horizontal-offset, 0); + right: var(--vertical-offset, 0); + bottom: var(--horizontal-offset, 0); + left: var(--vertical-offset, 0); + transition: transform 0.8s ease; + will-change: transform; +} +.button__horizontal::before, +.button__vertical::before { + content: ""; + position: absolute; + border: inherit; +} +.button__horizontal { + --vertical-offset: calc(var(--offset) * -1); + border-top: var(--border-size) solid currentcolor; + border-bottom: var(--border-size) solid currentcolor; +} +.button__horizontal::before { + top: calc(var(--vertical-offset) - var(--border-size)); + bottom: calc(var(--vertical-offset) - var(--border-size)); + left: calc(var(--vertical-offset) * -1); + right: calc(var(--vertical-offset) * -1); +} +.button:hover .button__horizontal { + transform: scaleX(0); +} +.button__vertical { + --horizontal-offset: calc(var(--offset) * -1); + border-left: var(--border-size) solid currentcolor; + border-right: var(--border-size) solid currentcolor; +} +.button__vertical::before { + top: calc(var(--horizontal-offset) * -1); + bottom: calc(var(--horizontal-offset) * -1); + left: calc(var(--horizontal-offset) - var(--border-size)); + right: calc(var(--horizontal-offset) - var(--border-size)); +} +.button:hover .button__vertical { + transform: scaleY(0); +} diff --git a/static/@solitude/css/welcome/glitch.css b/static/@solitude/css/welcome/glitch.css new file mode 100644 index 00000000..6b8c8987 --- /dev/null +++ b/static/@solitude/css/welcome/glitch.css @@ -0,0 +1,574 @@ +.glitch { + position: relative; + color: #fff; + font-size: 10rem; + font-family: "Share", cursive; +} + +.line:not(:first-child) { + position: absolute; + top: 0; + left: 0; +} +.line:nth-child(1) { + -webkit-animation: clip 3000ms -300ms linear infinite, + glitch1 500ms -80ms linear infinite; + animation: clip 3000ms -300ms linear infinite, + glitch1 500ms -80ms linear infinite; +} +@-webkit-keyframes glitch1 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(0px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch1 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(0px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(2) { + -webkit-animation: clip 3000ms -600ms linear infinite, + glitch2 500ms -433ms linear infinite; + animation: clip 3000ms -600ms linear infinite, + glitch2 500ms -433ms linear infinite; +} +@-webkit-keyframes glitch2 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(3px); + color: #4e9a26; + } + 90% { + transform: translateX(-3px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch2 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(3px); + color: #4e9a26; + } + 90% { + transform: translateX(-3px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(3) { + -webkit-animation: clip 3000ms -900ms linear infinite, + glitch3 500ms -664ms linear infinite; + animation: clip 3000ms -900ms linear infinite, + glitch3 500ms -664ms linear infinite; +} +@-webkit-keyframes glitch3 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch3 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(4px); + color: #4e9a26; + } + 90% { + transform: translateX(5px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(4) { + -webkit-animation: clip 3000ms -1200ms linear infinite, + glitch4 500ms -276ms linear infinite; + animation: clip 3000ms -1200ms linear infinite, + glitch4 500ms -276ms linear infinite; +} +@-webkit-keyframes glitch4 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(2px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch4 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(2px); + color: #ac1212; + } + 95% { + transform: translateX(-2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(5) { + -webkit-animation: clip 3000ms -1500ms linear infinite, + glitch5 500ms -180ms linear infinite; + animation: clip 3000ms -1500ms linear infinite, + glitch5 500ms -180ms linear infinite; +} +@-webkit-keyframes glitch5 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-2px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch5 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-2px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(6) { + -webkit-animation: clip 3000ms -1800ms linear infinite, + glitch6 500ms -954ms linear infinite; + animation: clip 3000ms -1800ms linear infinite, + glitch6 500ms -954ms linear infinite; +} +@-webkit-keyframes glitch6 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch6 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-3px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(7) { + -webkit-animation: clip 3000ms -2100ms linear infinite, + glitch7 500ms -377ms linear infinite; + animation: clip 3000ms -2100ms linear infinite, + glitch7 500ms -377ms linear infinite; +} +@-webkit-keyframes glitch7 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(2px); + color: #4e9a26; + } + 90% { + transform: translateX(-1px); + color: #ac1212; + } + 95% { + transform: translateX(-1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch7 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(2px); + color: #4e9a26; + } + 90% { + transform: translateX(-1px); + color: #ac1212; + } + 95% { + transform: translateX(-1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(8) { + -webkit-animation: clip 3000ms -2400ms linear infinite, + glitch8 500ms -104ms linear infinite; + animation: clip 3000ms -2400ms linear infinite, + glitch8 500ms -104ms linear infinite; +} +@-webkit-keyframes glitch8 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-2px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch8 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-2px); + color: #ac1212; + } + 95% { + transform: translateX(4px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(9) { + -webkit-animation: clip 3000ms -2700ms linear infinite, + glitch9 500ms -606ms linear infinite; + animation: clip 3000ms -2700ms linear infinite, + glitch9 500ms -606ms linear infinite; +} +@-webkit-keyframes glitch9 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch9 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(1px); + color: #4e9a26; + } + 90% { + transform: translateX(-4px); + color: #ac1212; + } + 95% { + transform: translateX(2px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +.line:nth-child(10) { + -webkit-animation: clip 3000ms -3000ms linear infinite, + glitch10 500ms -560ms linear infinite; + animation: clip 3000ms -3000ms linear infinite, + glitch10 500ms -560ms linear infinite; +} +@-webkit-keyframes glitch10 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-1px); + color: #4e9a26; + } + 90% { + transform: translateX(1px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} +@keyframes glitch10 { + 0% { + transform: translateX(0); + } + 80% { + transform: translateX(0); + color: #fff; + } + 85% { + transform: translateX(-1px); + color: #4e9a26; + } + 90% { + transform: translateX(1px); + color: #ac1212; + } + 95% { + transform: translateX(1px); + color: #fff; + } + 100% { + transform: translateX(0); + } +} + +@-webkit-keyframes clip { + 0% { + -webkit-clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + } + 100% { + -webkit-clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + } +} + +@keyframes clip { + 0% { + -webkit-clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + clip-path: polygon(0 100%, 100% 100%, 100% 120%, 0 120%); + } + 100% { + -webkit-clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + clip-path: polygon(0 -20%, 100% -20%, 100% 0%, 0 0); + } +} diff --git a/static/@solitude/css/welcome/welcome.css b/static/@solitude/css/welcome/welcome.css index 22a1a747..b4fcde6c 100644 --- a/static/@solitude/css/welcome/welcome.css +++ b/static/@solitude/css/welcome/welcome.css @@ -11,6 +11,8 @@ */ @import url("https://fonts.googleapis.com/css2?family=Handlee&family=Poppins:wght@400&family=Share:wght@700&display=swap"); @import url(audio.css); +@import url(button.css); +@import url(glitch.css); :root { --button-height: 0.5rem; --button-color: #edd; @@ -42,7 +44,6 @@ min-height: 100%; height: 100%; width: 100%; - background-color: rgba(0, 0, 0, 0.15); z-index: -99; } @@ -52,6 +53,14 @@ align-items: center; justify-content: center; min-height: 100vh; + background: repeating-linear-gradient( + 0deg, + #0e0d0e77 25%, + #0e0d0e77 50%, + #17181977 50%, + #17181977 75% + ); + background-size: 10px 10px; } .cwrapper { @@ -78,21 +87,8 @@ p { margin-top: 10rem; } -.description { - font-family: "Share", sans-serif; - font-size: 1rem; - margin-top: -4rem; - letter-spacing: 0.1rem; +@media only screen and (max-width: 600px) { + .glitch { + font-size: 5rem; + } } - -.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/js/welcome.js b/static/@solitude/js/welcome.js new file mode 100644 index 00000000..d8921075 --- /dev/null +++ b/static/@solitude/js/welcome.js @@ -0,0 +1,113 @@ +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 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(); diff --git a/templates/@solitude/home.html b/templates/@solitude/home.html new file mode 100644 index 00000000..de6f7fe1 --- /dev/null +++ b/templates/@solitude/home.html @@ -0,0 +1 @@ +

Welcome to Solitude

\ No newline at end of file diff --git a/templates/@solitude/welcome.html b/templates/@solitude/welcome.html index 9c07dad2..ba4e47d5 100644 --- a/templates/@solitude/welcome.html +++ b/templates/@solitude/welcome.html @@ -16,12 +16,23 @@
-
-

THE SOLITUDE

+
+
the solitude
+
the solitude
+
the solitude
+
the solitude
+
the solitude
+
the solitude
+
the solitude
+
the solitude
+
the solitude
-
-

- +
+
@@ -48,190 +59,10 @@
- + -- cgit v1.2.3