Scrollable code

This commit is contained in:
Adrien Bouvais 2024-05-09 19:20:14 +02:00
parent bd514dd1e9
commit 56f09d6d49
9 changed files with 162 additions and 170 deletions

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"time"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -15,6 +16,7 @@ import (
const EDGEDB_AUTH_BASE_URL = "http://127.0.0.1:10700/db/main/ext/auth" const EDGEDB_AUTH_BASE_URL = "http://127.0.0.1:10700/db/main/ext/auth"
func generatePKCE() (string, string) { func generatePKCE() (string, string) {
fmt.Println("Generating PKCE")
verifier := make([]byte, 32) verifier := make([]byte, 32)
_, err := rand.Read(verifier) _, err := rand.Read(verifier)
if err != nil { if err != nil {
@ -22,7 +24,16 @@ func generatePKCE() (string, string) {
} }
challenge := sha256.Sum256(verifier) challenge := sha256.Sum256(verifier)
return base64.RawURLEncoding.EncodeToString(verifier), base64.RawURLEncoding.EncodeToString(challenge[:])
var URLEncoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_")
var RawURLEncoding = URLEncoding.WithPadding(base64.NoPadding)
encodedVerifier := RawURLEncoding.EncodeToString(verifier)
encodedChallenge := RawURLEncoding.EncodeToString(challenge[:])
fmt.Println("verifier: " + encodedVerifier)
fmt.Println("challenge: " + encodedChallenge)
return encodedVerifier, encodedChallenge
} }
func handleUiSignIn(c *fiber.Ctx) error { func handleUiSignIn(c *fiber.Ctx) error {
@ -31,18 +42,13 @@ func handleUiSignIn(c *fiber.Ctx) error {
fmt.Println("handleUiSignIn verifier: " + verifier) fmt.Println("handleUiSignIn verifier: " + verifier)
fmt.Println("handleUiSignIn challenge: " + challenge) fmt.Println("handleUiSignIn challenge: " + challenge)
redirectURL := fmt.Sprintf("%s/ui/signin?challenge=%s", EDGEDB_AUTH_BASE_URL, challenge) cookie := new(fiber.Cookie)
cookie.Name = "jade-edgedb-pkce-verifier"
cookie.Value = verifier
cookie.Expires = time.Now().Add(10 * time.Minute)
c.Cookie(cookie)
c.Cookie(&fiber.Cookie{ return c.Redirect(fmt.Sprintf("%s/ui/signup?challenge=%s", EDGEDB_AUTH_BASE_URL, challenge), fiber.StatusTemporaryRedirect)
Name: "jade-edgedb-pkce-verifier",
Value: verifier,
HTTPOnly: true,
Path: "/",
Secure: true,
SameSite: "Strict",
})
return c.Redirect(redirectURL, fiber.StatusMovedPermanently)
} }
func handleUiSignUp(c *fiber.Ctx) error { func handleUiSignUp(c *fiber.Ctx) error {
@ -51,30 +57,13 @@ func handleUiSignUp(c *fiber.Ctx) error {
fmt.Println("handleUiSignUp verifier: " + verifier) fmt.Println("handleUiSignUp verifier: " + verifier)
fmt.Println("handleUiSignUp challenge: " + challenge) fmt.Println("handleUiSignUp challenge: " + challenge)
redirectURL := fmt.Sprintf("%s/ui/signup?challenge=%s", EDGEDB_AUTH_BASE_URL, challenge) cookie := new(fiber.Cookie)
cookie.Name = "jade-edgedb-pkce-verifier"
cookie.Value = verifier
cookie.Expires = time.Now().Add(10 * time.Minute)
c.Cookie(cookie)
c.Cookie(&fiber.Cookie{ return c.Redirect(fmt.Sprintf("%s/ui/signup?challenge=%s", EDGEDB_AUTH_BASE_URL, challenge), fiber.StatusTemporaryRedirect)
Name: "jade-edgedb-pkce-verifier",
Value: verifier,
HTTPOnly: true,
Path: "/",
Secure: true,
SameSite: "Strict",
})
return c.Redirect(redirectURL, fiber.StatusMovedPermanently)
}
func handleCallbackSignup(c *fiber.Ctx) error {
code := c.Query("code")
fmt.Println("Callback signup code: " + code)
verifier := c.Cookies("jade-edgedb-pkce-verifier")
if verifier == "" {
return c.Status(fiber.StatusBadRequest).SendString("Could not find 'verifier' in the cookie store. Is this the same user agent/browser that started the authorization flow?")
}
return c.SendString("OK")
} }
func handleCallback(c *fiber.Ctx) error { func handleCallback(c *fiber.Ctx) error {
@ -93,6 +82,7 @@ func handleCallback(c *fiber.Ctx) error {
fmt.Println("handleCallback verifier: " + verifier) fmt.Println("handleCallback verifier: " + verifier)
codeExchangeURL := fmt.Sprintf("%s/token?code=%s&verifier=%s", EDGEDB_AUTH_BASE_URL, code, verifier) codeExchangeURL := fmt.Sprintf("%s/token?code=%s&verifier=%s", EDGEDB_AUTH_BASE_URL, code, verifier)
fmt.Println("codeExchangeURL: " + codeExchangeURL)
resp, err := http.Get(codeExchangeURL) resp, err := http.Get(codeExchangeURL)
if err != nil { if err != nil {
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error from the auth server: %s", err.Error())) return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error from the auth server: %s", err.Error()))

View File

@ -42,10 +42,9 @@ func main() {
app.Get("/generateMultipleMessages", GenerateMultipleMessages) // Generate multiple messages app.Get("/generateMultipleMessages", GenerateMultipleMessages) // Generate multiple messages
app.Get("/messageContent", GetMessageContentHandler) app.Get("/messageContent", GetMessageContentHandler)
app.Get("/auth/ui/signin", handleUiSignIn) app.Get("/signin", handleUiSignIn)
app.Get("/auth/ui/signup", handleUiSignUp) app.Get("/signup", handleUiSignUp)
app.Get("/auth/callback", handleCallback) app.Get("/callback", handleCallback)
app.Get("/auth/callbackSignup", handleCallbackSignup)
app.Get("test", func(c *fiber.Ctx) error { app.Get("test", func(c *fiber.Ctx) error {
fmt.Println("test") fmt.Println("test")

17
static/animations.css Normal file
View File

@ -0,0 +1,17 @@
.message-bot.htmx-added {
opacity: 0;
}
.message-bot {
opacity: 1;
transition: opacity 1s ease-out;
}
.message-user.htmx-added {
opacity: 0;
}
.message-user {
opacity: 1;
transition: opacity 1s ease-out;
}

109
static/style.css Normal file
View File

@ -0,0 +1,109 @@
.my-indicator {
display: none;
}
.htmx-request .my-indicator {
display: inline;
}
.htmx-request.my-indicator {
display: inline;
}
svg text {
font-family: 'Russo One', sans-serif;
text-transform: uppercase;
fill: #000;
stroke: #000;
font-size: 240px;
}
.message-content {
background-color: #303030;
border-radius: 5px;
padding: 10px;
}
#chat-messages .message-content pre {
overflow-x: auto;
white-space: pre;
max-width: 662px;
}
#chat-messages .message-content pre code {
display: inline-block;
min-width: 100%;
white-space: inherit;
}
.content {
font-size: 14px;
line-height: 1.5;
color: #ffffff;
}
.content pre {
font-family: monospace;
background-color: #363636 !important;
border-radius: 3px;
}
#chat-messages {
max-width: 780px;
margin: auto;
width: 95%;
margin-bottom: 180px;
}
#chat-input-form {
max-width: 900px;
margin: auto;
width: 98%;
}
:root {
--bulma-body-background-color: #202020;
--bulma-primary: #126d0f;
}
body,
html {
height: 100%;
margin: 0;
}
.chat-input-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
bottom: 10px;
left: 0;
right: 0;
padding: 10px;
max-width: 800px;
margin: 0 auto;
z-index: 1;
}
.textarea-wrapper {
position: relative;
width: 100%;
}
.textarea {
width: 100%;
padding-right: 140px;
/* Adjust this value based on the button and dropdown width */
box-sizing: border-box;
}
.button-group {
position: absolute;
bottom: 10px;
right: 10px;
display: flex;
align-items: center;
gap: 10px;
}

View File

@ -18,6 +18,7 @@ func markdownToHTML(markdownText string) string {
if err := md.Convert([]byte(markdownText), &buf); err != nil { if err := md.Convert([]byte(markdownText), &buf); err != nil {
panic(err) // Handle the error appropriately panic(err) // Handle the error appropriately
} }
return buf.String() return buf.String()
} }

View File

@ -2,7 +2,6 @@
<hx hx-get="/loadChat" hx-trigger="load" hx-swap="outerHTML"></hx> <hx hx-get="/loadChat" hx-trigger="load" hx-swap="outerHTML"></hx>
<div class="chat-input-container mb-5"> <div class="chat-input-container mb-5">
<div class="textarea-wrapper"> <div class="textarea-wrapper">
<textarea class="textarea" placeholder="Type your message here..." name="message"></textarea> <textarea class="textarea" placeholder="Type your message here..." name="message"></textarea>

View File

@ -9,50 +9,8 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<style> <link rel="stylesheet" href="/animations.css">
body, <link rel="stylesheet" href="/style.css">
html {
height: 100%;
margin: 0;
}
.chat-input-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
bottom: 10px;
left: 0;
right: 0;
padding: 10px;
max-width: 800px;
/* Adjust this value to your desired maximum width */
margin: 0 auto;
/* Center the container horizontally */
}
.textarea-wrapper {
position: relative;
width: 100%;
}
.textarea {
width: 100%;
padding-right: 140px;
/* Adjust this value based on the button and dropdown width */
box-sizing: border-box;
}
.button-group {
position: absolute;
bottom: 10px;
right: 10px;
display: flex;
align-items: center;
gap: 10px;
}
</style>
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com"> <meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
</head> </head>
@ -64,88 +22,6 @@
{{embed}} {{embed}}
<style>
.my-indicator {
display: none;
}
.htmx-request .my-indicator {
display: inline;
}
.htmx-request.my-indicator {
display: inline;
}
</style>
<!-- Style stuff -->
<style>
svg text {
font-family: 'Russo One', sans-serif;
text-transform: uppercase;
fill: #000;
stroke: #000;
font-size: 240px;
}
.message-content {
background-color: #303030;
border-radius: 5px;
padding: 10px;
}
.content {
font-size: 14px;
line-height: 1.5;
color: #ffffff;
}
.content pre {
font-family: monospace;
background-color: #363636 !important;
border-radius: 3px;
}
#chat-messages {
max-width: 800px;
margin: auto;
width: 95%;
}
#chat-input-form {
max-width: 900px;
margin: auto;
width: 98%;
}
:root {
--bulma-body-background-color: #202020;
--bulma-primary: #126d0f;
}
</style>
<!-- Animations stuff -->
<style>
.message-bot.htmx-added {
opacity: 0;
}
.message-bot {
opacity: 1;
transition: opacity 1s ease-out;
}
.message-user.htmx-added {
opacity: 0;
}
.message-user {
opacity: 1;
transition: opacity 1s ease-out;
}
</style>
</body> </body>
</html> </html>

View File

@ -14,8 +14,9 @@
{{ Content|safe }} {{ Content|safe }}
</div> </div>
</div> </div>
<button hx-post="/deleteMessage?id={{ ID }}" style="position: absolute; top: 3; right: 3;" <button id="delete-button-{{ ID }}" hx-post="/deleteMessage?id={{ ID }}"
hx-swap="outerHTML" hx-target="#chat-container" class="delete" aria-label="delete"></button> style="position: absolute; top: 3; right: 3;" hx-swap="outerHTML" hx-target="#chat-container"
class="delete" aria-label="delete"></button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -12,10 +12,10 @@
<div class="navbar-end"> <div class="navbar-end">
<div class="navbar-item"> <div class="navbar-item">
<div class="buttons"> <div class="buttons">
<a class="button is-light is-small" href="/auth/ui/signin"> <a class="button is-light is-small" href="/signin">
Log in Log in
</a> </a>
<a class="button is-primary" href="/auth/ui/signup"> <a class="button is-primary" href="/signup">
<strong>Sign up</strong> <strong>Sign up</strong>
</a> </a>
</div> </div>