feat: startup splash for user configuration
This commit is contained in:
		
							parent
							
								
									4dd15d52bb
								
							
						
					
					
						commit
						56c315c301
					
				| @ -10,6 +10,13 @@ | |||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| 
 | 
 | ||||||
|  | <div id="start-splash"> | ||||||
|  |     <img class="center" src="oct.jpg"></img> | ||||||
|  |     <input class="center" type="text" id="username" placeholder="Choose a username!" onkeyup="usernameInputUpdated(event)"></input> | ||||||
|  |     <!--<ul class="center" id="interest-selection"></ul>--> | ||||||
|  |     <a id="advance-button" class="center" href="#" onclick="advanceSplash()">Choose some interests!</a> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
| <!-- blocks are added by JavaScript so container starts empty --> | <!-- blocks are added by JavaScript so container starts empty --> | ||||||
| <div id="block-container"></div> | <div id="block-container"></div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										207
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								main.js
									
									
									
									
									
								
							| @ -8,7 +8,34 @@ const adjectives = [ | |||||||
|     "analytical", "motivated", "solution-focused", "committed", "agile" |     "analytical", "motivated", "solution-focused", "committed", "agile" | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
|  | const interests = [ | ||||||
|  |     "music", "comedy", "travel", "technology", "hiking", "nature", "food", "movies", | ||||||
|  |     "culture", "art", "activism", "community", "books", "baking", "creativity", "fitness", | ||||||
|  |     "fashion", "wellness", "history", "adventure", "gaming", "gardening", "sustainability", | ||||||
|  |     "coding", "coffee", "DIY", "crafts", "pets", "animals", "humor", "languages", "sports", | ||||||
|  |     "competition", "meditation", "mindfulness", "design", "concerts", "innovation", "museums", | ||||||
|  |     "future", "writing", "relaxation", "photography", "compassion", "nutrition", "style", | ||||||
|  |     "restaurants", "gadgets", "inspiration", "literature", "outdoors", "wildlife", "conservation", | ||||||
|  |     "motivation", "beauty", "culinary arts", "festivals", "exploration", "knowledge", "camping", | ||||||
|  |     "archeology", "triathlon", "endurance", "luxury", "wine", "fine dining", "audio equipment", | ||||||
|  |     "sound quality", "startups", "entrepreneurship", "extreme sports", "philosophy", "survival", | ||||||
|  |     "environment", "politics", "running", "gastronomy", "genres", "software", "current events", | ||||||
|  |     "recipes", "listening", "discovery", "expression", "reading", "recommendations", "news", | ||||||
|  |     "analysis", "trends", "dining", "reviews", "rescue", "welfare", "health", "artists", "cooking" | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | var localUser = { | ||||||
|  |     user: null, | ||||||
|  |     interests: [], | ||||||
|  |     postingStyle: null | ||||||
|  | }; | ||||||
|  | var splashStep = 0; | ||||||
|  | const maxInterests = 3; | ||||||
|  | 
 | ||||||
|  | // configuration
 | ||||||
| const localMode = false; | const localMode = false; | ||||||
|  | const showSplash = false; | ||||||
|  | 
 | ||||||
| const blockContainer = document.getElementById("block-container"); | const blockContainer = document.getElementById("block-container"); | ||||||
| const postCountElem = document.getElementById("post-count"); | const postCountElem = document.getElementById("post-count"); | ||||||
| const postTotalElem = document.getElementById("post-total"); | const postTotalElem = document.getElementById("post-total"); | ||||||
| @ -215,13 +242,18 @@ function makePostFromJson(json) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getCurrentUser() { | function getCurrentUser() { | ||||||
|  |     // return some default values if we didn't do the initial configuration 
 | ||||||
|  |     if (!showSplash) { | ||||||
|  |         return { | ||||||
|  |             "user": "ktyl", | ||||||
|  |             "interests": ["trains", "trains", "trains"], | ||||||
|  |             "posting_style": "borderline maniacal train content" | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return { |     return { | ||||||
|         "user": "theChief", |         "user": localUser.user, | ||||||
|         "interests": [ |         "interests": localUser.interests, | ||||||
|             "gen-ai", |  | ||||||
|             "blockchain", |  | ||||||
|             "nfts" |  | ||||||
|         ], |  | ||||||
|         "posting_style": "just the most truly inane takes" |         "posting_style": "just the most truly inane takes" | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @ -243,12 +275,10 @@ function writePost(postCallback) { | |||||||
|             body: "local mode post (local mode post)" |             body: "local mode post (local mode post)" | ||||||
|         }); |         }); | ||||||
|         postCallback(post); |         postCallback(post); | ||||||
|         //blockContainer.insertBefore(post.getElement(), getTopPost());
 |  | ||||||
|     } else { |     } else { | ||||||
|         fetch("https://api.wayfarer.games/singularity/generate-posts.php", request) |         fetch("https://api.wayfarer.games/singularity/generate-posts.php", request) | ||||||
|             .then(response => response.json()) |             .then(response => response.json()) | ||||||
|             .then(makePostFromJson) |             .then(makePostFromJson) | ||||||
|             //.then(post => blockContainer.insertBefore(post.getElement(), getTopPost()));
 |  | ||||||
|             .then(postCallback); |             .then(postCallback); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -302,6 +332,162 @@ function init() { | |||||||
|     window.addEventListener("scroll", handleInfiniteScroll); |     window.addEventListener("scroll", handleInfiniteScroll); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | function chooseInterest(interest) { | ||||||
|  |     if (localUser.interests.length == maxInterests) { | ||||||
|  |         console.error(`can't choose more than ${maxInterests} interests`); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     localUser.interests.push(interest); | ||||||
|  | 
 | ||||||
|  |     const interestsTextElem = document.getElementById("interests-text"); | ||||||
|  | 
 | ||||||
|  |     if (localUser.interests.length != maxInterests) { | ||||||
|  |         interestsTextElem.innerHTML = getInterestsTextValue(localUser.interests.length); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const advanceButtonElem = document.getElementById("advance-button"); | ||||||
|  |     advanceButtonElem.innerHTML = "Begin!"; | ||||||
|  |     advanceButtonElem.style.visibility = "visible"; | ||||||
|  | 
 | ||||||
|  |     interestsTextElem.remove(); | ||||||
|  |     const interestsListElem = document.getElementById("interest-selection"); | ||||||
|  |     interestsListElem.remove(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getInterestsSubset() { | ||||||
|  |     const count = 20; | ||||||
|  |     let subset = []; | ||||||
|  | 
 | ||||||
|  |     while (subset.length < count) { | ||||||
|  |         const interest = interests[Math.floor(Math.random() * interests.length)]; | ||||||
|  | 
 | ||||||
|  |         // skip if it's already included
 | ||||||
|  |         if (subset.includes(interest)) | ||||||
|  |             continue; | ||||||
|  | 
 | ||||||
|  |         // skip if the user has already chosen it
 | ||||||
|  |         if (localUser.interests.includes(interest)) | ||||||
|  |             continue; | ||||||
|  | 
 | ||||||
|  |         subset.push(interest); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return subset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function populateSplashInterests() { | ||||||
|  | 
 | ||||||
|  |     const rootElem = document.getElementById("interest-selection"); | ||||||
|  |     if (rootElem == null) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     // clear existing interests
 | ||||||
|  |     rootElem.innerHTML = ""; | ||||||
|  | 
 | ||||||
|  |     const interestsSubset = getInterestsSubset(); | ||||||
|  | 
 | ||||||
|  |     for (let i = 0; i < interestsSubset.length; i++) { | ||||||
|  |         const interest = interestsSubset[i]; | ||||||
|  |         const listItemElem = document.createElement("li"); | ||||||
|  |         rootElem.appendChild(listItemElem); | ||||||
|  | 
 | ||||||
|  |         const buttonElem = document.createElement("a"); | ||||||
|  |         buttonElem.innerHTML = `#${interest}`; | ||||||
|  |         buttonElem.addEventListener("click", () => { | ||||||
|  |             chooseInterest(interest); | ||||||
|  |             populateSplashInterests(); | ||||||
|  |         }); | ||||||
|  |         listItemElem.appendChild(buttonElem); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getInterestsTextValue(numChosenInterests) { | ||||||
|  |     return `Choose some interests! (${numChosenInterests}/${maxInterests})`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function usernameInputUpdated(event) { | ||||||
|  |     const inputElem = document.getElementById("username"); | ||||||
|  |     const buttonElem = document.getElementById("advance-button"); | ||||||
|  |     const isNameEmpty = inputElem.value.length == ""; | ||||||
|  |     buttonElem.style.visibility = isNameEmpty ? "hidden" : "visible"; | ||||||
|  | 
 | ||||||
|  |     if (isNameEmpty) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     if (event.key == "Enter") { | ||||||
|  |         advanceSplash(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function chooseName() { | ||||||
|  |     // check that a name has been chosen
 | ||||||
|  |     const inputElem = document.getElementById("username"); | ||||||
|  |     if (!inputElem.value) { | ||||||
|  |         console.error("a name needs to be entered!"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     splashStep = 1; | ||||||
|  |     localUser.user = inputElem.value; | ||||||
|  | 
 | ||||||
|  |     // TODO: disable button until name has been chosen
 | ||||||
|  | 
 | ||||||
|  |     // TODO: insert interest selection elements before name input
 | ||||||
|  |     //writePost(post => blockContainer.insertBefore(post.getElement(), getTopPost()));
 | ||||||
|  |     const splashElem = document.getElementById("start-splash"); | ||||||
|  | 
 | ||||||
|  |     const interestsTextElem = document.createElement("p"); | ||||||
|  |     interestsTextElem.innerHTML = getInterestsTextValue(0); | ||||||
|  |     interestsTextElem.id = "interests-text"; | ||||||
|  |     interestsTextElem.className = "center"; | ||||||
|  |     splashElem.insertBefore(interestsTextElem, inputElem); | ||||||
|  | 
 | ||||||
|  |     const interestsListElem = document.createElement("ul"); | ||||||
|  |     interestsListElem.className = "center"; | ||||||
|  |     interestsListElem.id = "interest-selection"; | ||||||
|  |     splashElem.insertBefore(interestsListElem, inputElem); | ||||||
|  | 
 | ||||||
|  |     populateSplashInterests(); | ||||||
|  | 
 | ||||||
|  |     // remove name input
 | ||||||
|  |     inputElem.remove(); | ||||||
|  | 
 | ||||||
|  |     const advanceButtonElem = document.getElementById("advance-button"); | ||||||
|  |     advanceButtonElem.style.visibility = "hidden"; | ||||||
|  | 
 | ||||||
|  |     splashStep = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function chooseInterests() { | ||||||
|  |     if (localUser.interests.length < maxInterests) { | ||||||
|  |         console.error(`need to choose ${maxInterests} interests`); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     console.log("TODO: generate user posting style"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function removeSplash() { | ||||||
|  |     document.getElementById("start-splash").remove(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function advanceSplash() { | ||||||
|  |     switch(splashStep) { | ||||||
|  |         case 0: | ||||||
|  |             chooseName(); | ||||||
|  |             break; | ||||||
|  |         case 1: | ||||||
|  |             chooseInterests(); | ||||||
|  |             removeSplash(); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             console.error(`nothing defined for splash step ${splashStep}`); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| function loadDataFromEndpoint(endpoint, callback) { | function loadDataFromEndpoint(endpoint, callback) { | ||||||
|     fetch(endpoint) |     fetch(endpoint) | ||||||
|         .then(response => response.json()) |         .then(response => response.json()) | ||||||
| @ -311,6 +497,7 @@ function loadDataFromEndpoint(endpoint, callback) { | |||||||
|         }); |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| const usersUrl = localMode ? "users.json" : "https://api.wayfarer.games/singularity/users.json"; | const usersUrl = localMode ? "users.json" : "https://api.wayfarer.games/singularity/users.json"; | ||||||
| const postsUrl = localMode ? "posts.json" : "https://api.wayfarer.games/singularity/posts.json"; | const postsUrl = localMode ? "posts.json" : "https://api.wayfarer.games/singularity/posts.json"; | ||||||
| loadDataFromEndpoint(usersUrl, json => { users = json.users; }); | loadDataFromEndpoint(usersUrl, json => { users = json.users; }); | ||||||
| @ -333,3 +520,7 @@ loadDataFromEndpoint(postsUrl, json => { | |||||||
| 
 | 
 | ||||||
|     postTotalElem.innerHTML = Object.keys(posts).length; |     postTotalElem.innerHTML = Object.keys(posts).length; | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | if (!showSplash) { | ||||||
|  |     removeSplash(); | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										96
									
								
								styles.css
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								styles.css
									
									
									
									
									
								
							| @ -1,15 +1,17 @@ | |||||||
| :root { | :root { | ||||||
|     --header-height: 64px; |     --header-height: 64px; | ||||||
|     --background-color: #374955; |     --blue-gray: #374955; | ||||||
|     --accent-color: #86b1cc; |     --sky-blue: #86b1cc; | ||||||
|     --comment-column-width: 3px; |     --comment-column-width: 3px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| body { | body { | ||||||
|  |     margin: 0; | ||||||
|  |     padding: 0; | ||||||
|     font-family: "Poppins", sans-serif; |     font-family: "Poppins", sans-serif; | ||||||
|     font-weight: 400; |     font-weight: 400; | ||||||
|     font-style: normal; |     font-style: normal; | ||||||
|     background-color: var(--background-color); |     background-color: var(--sky-blue); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @media only screen and (min-width: 800px) { | @media only screen and (min-width: 800px) { | ||||||
| @ -23,6 +25,77 @@ body { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #start-splash { | ||||||
|  |     position: fixed; | ||||||
|  |     width: 100%; | ||||||
|  |     height: 100%; | ||||||
|  |     padding: 0; | ||||||
|  |     margin: 0; | ||||||
|  |     background-color: white; | ||||||
|  |     z-index: 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .center { | ||||||
|  |     display: block; | ||||||
|  |     margin: auto; | ||||||
|  |     padding: auto; | ||||||
|  |     text-align: center; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #start-splash img { | ||||||
|  |     max-width: 40vw; | ||||||
|  |     margin-top: 10vh; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #start-splash input { | ||||||
|  |     margin: 2em auto; | ||||||
|  |     border: none; | ||||||
|  |     background-color: var(--sky-blue); | ||||||
|  |     color: white; | ||||||
|  |     border-radius: 16px; | ||||||
|  |     font-size: 1.5em; | ||||||
|  |     padding: 4px 8px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #advance-button { | ||||||
|  |     width: 20%; | ||||||
|  |     margin: 2em auto; | ||||||
|  |     color: white; | ||||||
|  |     background-color: var(--sky-blue); | ||||||
|  |     text-align: center; | ||||||
|  |     visibility: hidden; | ||||||
|  |     padding: 4px 8px; | ||||||
|  |     border-radius: 16px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #interests-text { | ||||||
|  |     color: var(--blue-gray); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #interest-selection { | ||||||
|  |     width: 80%; | ||||||
|  |     padding: 8px; | ||||||
|  |     display: flex; | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |     justify-content: center; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #interest-selection li { | ||||||
|  |     display: inline; | ||||||
|  |     margin: .5em; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #interest-selection li a { | ||||||
|  |     padding: 4px 8px; | ||||||
|  |     border-radius: 16px; | ||||||
|  |     color: white; | ||||||
|  |     background-color: var(--sky-blue); | ||||||
|  |     transition: all 200ms ease-in-out; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #interest-selection li a:hover { | ||||||
|  |     background-color: var(--blue-gray); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| #block-container { | #block-container { | ||||||
|     display: flex; |     display: flex; | ||||||
| @ -51,19 +124,20 @@ body { | |||||||
|     border-radius: calc(var(--header-height) / 2); |     border-radius: calc(var(--header-height) / 2); | ||||||
|     margin-top: calc(var(--header-height) / 8); |     margin-top: calc(var(--header-height) / 8); | ||||||
|     padding: calc(var(--header-height) / 8) calc(var(--header-height) / 4); |     padding: calc(var(--header-height) / 8) calc(var(--header-height) / 4); | ||||||
|     background-color: var(--accent-color); |     background-color: var(--sky-blue); | ||||||
|     color: var(--backround-color); |     color: white; | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|     transition: all 200ms ease-in-out; |     transition: all 200ms ease-in-out; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .reply-button:hover { | .reply-button:hover { | ||||||
|     background-color: var(--background-color); |     background-color: var(--blue-gray); | ||||||
|     color: white; |     color: white; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .reply-button:active { | .reply-button:active { | ||||||
|     background-color: white; |     background-color: white; | ||||||
|  |     color: var(--blue-gray); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .post-header { | .post-header { | ||||||
| @ -82,16 +156,16 @@ body { | |||||||
| 
 | 
 | ||||||
| .write-post { | .write-post { | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|     color: var(--background-color); |     color: var(--blue-gray); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .write-post:hover { | .write-post:hover { | ||||||
|     background-color: var(--accent-color); |     background-color: var(--sky-blue); | ||||||
|     color: white; |     color: white; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .write-post:active { | .write-post:active { | ||||||
|     background-color: var(---background-color); |     background-color: var(---blue-gray); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .write-post h2 { | .write-post h2 { | ||||||
| @ -102,7 +176,7 @@ body { | |||||||
| 
 | 
 | ||||||
| a { | a { | ||||||
|     text-decoration: none; |     text-decoration: none; | ||||||
|     color: var(--background-color); |     color: var(--blue-gray); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .pfp { | .pfp { | ||||||
| @ -118,7 +192,7 @@ a { | |||||||
| 
 | 
 | ||||||
| .post:not(.block) { | .post:not(.block) { | ||||||
|     margin-top: calc(var(--header-height) / 4); |     margin-top: calc(var(--header-height) / 4); | ||||||
|     border-left: var(--comment-column-width) solid var(--accent-color); |     border-left: var(--comment-column-width) solid var(--sky-blue); | ||||||
|     padding-left: calc(var(--header-height) / 2 - var(--comment-column-width)); |     padding-left: calc(var(--header-height) / 2 - var(--comment-column-width)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user