From 5fbe1ce99fc1c80f6c47caf4c0b50e48c8de24f4 Mon Sep 17 00:00:00 2001 From: TheSaminator Date: Thu, 10 Feb 2022 17:25:18 -0500 Subject: [PATCH] Add profile bios --- .../kotlin/starshipfights/auth/providers.kt | 9 ++- .../starshipfights/data/auth/user_sessions.kt | 1 + .../kotlin/starshipfights/info/view_nav.kt | 1 - .../kotlin/starshipfights/info/views_ships.kt | 5 +- .../kotlin/starshipfights/info/views_user.kt | 56 +++++++++++++++---- src/jvmMain/resources/static/init.js | 32 +++++++++++ src/jvmMain/resources/static/style.css | 9 ++- 7 files changed, 93 insertions(+), 20 deletions(-) diff --git a/src/jvmMain/kotlin/starshipfights/auth/providers.kt b/src/jvmMain/kotlin/starshipfights/auth/providers.kt index 5e49567..afc5046 100644 --- a/src/jvmMain/kotlin/starshipfights/auth/providers.kt +++ b/src/jvmMain/kotlin/starshipfights/auth/providers.kt @@ -88,7 +88,8 @@ interface AuthProvider { val form = call.receiveParameters() val newUser = currentUser.copy( - profileName = form["name"]?.takeIf { it.isNotBlank() } ?: currentUser.profileName + profileName = form["name"]?.takeIf { it.isNotBlank() && it.length <= 32 } ?: redirect("/me/manage?" + parametersOf("error", "Invalid name - must not be blank, must be at most 32 characters").formUrlEncode()), + profileBio = form["bio"]?.takeIf { it.isNotBlank() && it.length <= 240 } ?: redirect("/me/manage?" + parametersOf("error", "Invalid bio - must not be blank, must be at most 240 characters").formUrlEncode()) ) User.put(newUser) redirect("/user/${newUser.id}") @@ -232,7 +233,8 @@ object TestAuthProvider : AuthProvider { discordName = "", discordDiscriminator = "", discordAvatar = null, - profileName = credentials.name + profileName = credentials.name, + profileBio = "BEEP BOOP I EXIST ONLY FOR TESTING BLOP BLARP." ).also { User.put(it) } @@ -395,7 +397,8 @@ class ProductionAuthProvider(val discordLogin: DiscordLogin) : AuthProvider { discordName = discordUsername, discordDiscriminator = discordDiscriminator, discordAvatar = discordAvatar, - profileName = discordUsername + profileName = discordUsername, + profileBio = "Hi, I'm new here!" ) val userSession = UserSession( diff --git a/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt b/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt index b561009..cfab053 100644 --- a/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt +++ b/src/jvmMain/kotlin/starshipfights/data/auth/user_sessions.kt @@ -19,6 +19,7 @@ data class User( val discordDiscriminator: String, val discordAvatar: String?, val profileName: String, + val profileBio: String, val status: UserStatus = UserStatus.AVAILABLE, ) : DataDocument { val discordAvatarUrl: String diff --git a/src/jvmMain/kotlin/starshipfights/info/view_nav.kt b/src/jvmMain/kotlin/starshipfights/info/view_nav.kt index 77b9717..c72fc19 100644 --- a/src/jvmMain/kotlin/starshipfights/info/view_nav.kt +++ b/src/jvmMain/kotlin/starshipfights/info/view_nav.kt @@ -40,7 +40,6 @@ suspend fun ApplicationCall.standardNavBar(): List = listOf( ) else -> listOf( NavLink("/me", user.profileName), - NavLink("/me/manage", "User Preferences"), NavLink("/lobby", "Enter Game Lobby"), NavLink("/logout", "Log Out"), ) diff --git a/src/jvmMain/kotlin/starshipfights/info/views_ships.kt b/src/jvmMain/kotlin/starshipfights/info/views_ships.kt index b776589..3fe6d0f 100644 --- a/src/jvmMain/kotlin/starshipfights/info/views_ships.kt +++ b/src/jvmMain/kotlin/starshipfights/info/views_ships.kt @@ -3,7 +3,6 @@ package starshipfights.info import io.ktor.application.* import kotlinx.html.* import starshipfights.game.* -import java.util.Comparator import kotlin.math.PI import kotlin.math.roundToInt @@ -168,5 +167,9 @@ suspend fun ApplicationCall.shipPage(shipType: ShipType): HTML.() -> Unit = page style = "width:100%;height:25em" attributes["data-model"] = shipType.meshName } + + script { + unsafe { +"window.sfShipMeshViewer = true;" } + } } } diff --git a/src/jvmMain/kotlin/starshipfights/info/views_user.kt b/src/jvmMain/kotlin/starshipfights/info/views_user.kt index 251b82e..e9d868b 100644 --- a/src/jvmMain/kotlin/starshipfights/info/views_user.kt +++ b/src/jvmMain/kotlin/starshipfights/info/views_user.kt @@ -44,14 +44,7 @@ suspend fun ApplicationCall.userPage(): HTML.() -> Unit { +user.discordName +"#" +user.discordDiscriminator - } - if (user.discordId == CurrentConfiguration.discordClient?.ownerId) - p { - style = "text-align:center;border:2px solid #a82;padding:3px;background-color:#fc3;color:#a82;font-variant:small-caps;font-family:'Orbitron',sans-serif" - +"Site Owner" - } - p { - style = "text-align:center" + br when (user.status) { UserStatus.IN_BATTLE -> +"In Battle" UserStatus.READY_FOR_BATTLE -> +"In Battle" @@ -59,11 +52,20 @@ suspend fun ApplicationCall.userPage(): HTML.() -> Unit { UserStatus.AVAILABLE -> if (hasOpenSessions) +"Online" else +"Offline" } } + if (user.discordId == CurrentConfiguration.discordClient?.ownerId) + p { + style = "text-align:center;border:2px solid #a82;padding:3px;background-color:#fc3;color:#a82;font-variant:small-caps;font-family:'Orbitron',sans-serif" + +"Site Owner" + } if (isCurrentUser) { hr { style = "border-color:#036" } - p { - style = "text-align:center" - a(href = "/admiral/new") { +"Create New Admiral" } + div(classes = "list") { + div(classes = "item") { + a(href = "/admiral/new") { +"Create New Admiral" } + } + div(classes = "item") { + a(href = "/me/manage") { +"Edit Profile" } + } } } } @@ -71,6 +73,11 @@ suspend fun ApplicationCall.userPage(): HTML.() -> Unit { section { h1 { +user.profileName } + +user.profileBio + } + section { + h2 { +"Admirals" } + if (admirals.isNotEmpty()) { p { +"This user has the following admirals:" @@ -105,18 +112,40 @@ suspend fun ApplicationCall.manageUserPage(): HTML.() -> Unit { section { h1 { +"User Preferences" } form(method = FormMethod.post, action = "/me/manage") { + h2 { + +"Profile" + } h3 { label { htmlFor = "name" - +"Profile Name" + +"Display Name" } } textInput(name = "name") { required = true + maxLength = "32" + value = currentUser.profileName autoComplete = false + } + p { + style = "font-style:italic;font-size:0.8em;color:#555" + +"Max length 32 characters" + } + h3 { + label { + htmlFor = "bio" + +"Public Bio" + } + } + textArea { + name = "bio" + style = "width: 100%;height:5em" required = true + maxLength = "240" + + +currentUser.profileBio } request.queryParameters["error"]?.let { errorMsg -> p { @@ -272,6 +301,9 @@ suspend fun ApplicationCall.createAdmiralPage(): HTML.() -> Unit { value = "Create Admiral" } } + script { + unsafe { +"window.sfAdmiralNameGen = true;" } + } } } } diff --git a/src/jvmMain/resources/static/init.js b/src/jvmMain/resources/static/init.js index ba0fa8f..2630a19 100644 --- a/src/jvmMain/resources/static/init.js +++ b/src/jvmMain/resources/static/init.js @@ -1,4 +1,6 @@ window.addEventListener("load", function () { + if (!window.sfShipMeshViewer) return; + const canvases = document.getElementsByTagName("canvas"); for (let canvas of canvases) { const modelName = canvas.getAttribute("data-model"); @@ -74,6 +76,8 @@ window.addEventListener("load", function () { }); window.addEventListener("load", function () { + if (!window.sfAdmiralNameGen) return; + const nameBox = document.getElementById("name"); const isFemaleButton = document.getElementById("sex-female"); const generators = document.getElementsByClassName("generate-admiral-name"); @@ -87,3 +91,31 @@ window.addEventListener("load", function () { }; } }); + +window.addEventListener("load", function () { + const textareas = document.getElementsByTagName("textarea"); + for (let textarea of textareas) { + if (!textarea.hasAttribute("maxLength")) continue; + + const maxLengthIndicator = document.createElement("p"); + maxLengthIndicator.style.fontSize = "0.8em"; + maxLengthIndicator.style.fontStyle = "italic"; + maxLengthIndicator.style.color = "#555"; + + textarea.after(maxLengthIndicator); + + function updateIndicator() { + const maxLengthAttr = textarea.getAttribute("maxLength"); + if (!maxLengthAttr) return; + const maxLength = Number(maxLengthAttr); + + maxLengthIndicator.innerText = "" + textarea.value.length + "/" + maxLength; + } + + textarea.addEventListener("input", () => { + updateIndicator(); + }); + + updateIndicator(); + } +}); diff --git a/src/jvmMain/resources/static/style.css b/src/jvmMain/resources/static/style.css index 711f90d..3599128 100644 --- a/src/jvmMain/resources/static/style.css +++ b/src/jvmMain/resources/static/style.css @@ -226,7 +226,8 @@ th { input[type=text], input[type=password], -input[type=email] { +input[type=email], +textarea { box-sizing: border-box; background-color: #aaa; border: none; @@ -240,14 +241,16 @@ input[type=email] { input[type=text]:focus, input[type=password]:focus, -input[type=email]:focus { +input[type=email]:focus, +textarea:focus { outline: none; background-color: #888; } input[type=text]:invalid, input[type=password]:invalid, -input[type=email]:invalid { +input[type=email]:invalid, +textarea:invalid { color: #422; background-color: #e77; border-bottom-color: #211; -- 2.25.1