media query theme (#139)
* feat: use css media query to derive theme * fix: rename alt for toggle images * feat: remove no-cache middleware
This commit is contained in:
parent
b0ae8a50b5
commit
e409176642
1
main.go
1
main.go
@ -35,7 +35,6 @@ func main() {
|
|||||||
|
|
||||||
r.Use(gin.Recovery())
|
r.Use(gin.Recovery())
|
||||||
r.Use(middleware.XssPreventionHeaders())
|
r.Use(middleware.XssPreventionHeaders())
|
||||||
r.Use(middleware.NoCacheMiddleware())
|
|
||||||
r.Use(middleware.OptionsMiddleware())
|
r.Use(middleware.OptionsMiddleware())
|
||||||
r.Use(middleware.Ratelimit())
|
r.Use(middleware.Ratelimit())
|
||||||
|
|
||||||
|
@ -11,17 +11,19 @@
|
|||||||
--link-color: #92adff;
|
--link-color: #92adff;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme='light'] {
|
@media (prefers-color-scheme: light) {
|
||||||
--main-bg: #dbdbdb;
|
:root {
|
||||||
--text-color: #000;
|
--main-bg: #dbdbdb;
|
||||||
--muted-text-color: #636363;
|
--text-color: #000;
|
||||||
--code-bg: #36383d;
|
--muted-text-color: #636363;
|
||||||
--code-fg: #ffffff;
|
--code-bg: #36383d;
|
||||||
--input-bg: #bcbcbc;
|
--code-fg: #ffffff;
|
||||||
--input-bg-hover: #a8a8a8;
|
--input-bg: #bcbcbc;
|
||||||
--meta-bg: #aaa8a8;
|
--input-bg-hover: #a8a8a8;
|
||||||
--divider-color: #b5b5b5;
|
--meta-bg: #aaa8a8;
|
||||||
--link-color: #335ad0;
|
--divider-color: #b5b5b5;
|
||||||
|
--link-color: #335ad0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
package middleware
|
|
||||||
|
|
||||||
import "github.com/gin-gonic/gin"
|
|
||||||
|
|
||||||
func NoCacheMiddleware() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
c.Header("Cache-Control", "no-cache, no-store, must-revalidate")
|
|
||||||
c.Header("Pragma", "no-cache")
|
|
||||||
c.Header("Expires", "0")
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,6 @@ import (
|
|||||||
func OptionsMiddleware() gin.HandlerFunc {
|
func OptionsMiddleware() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
c.Set("disable_images", false)
|
c.Set("disable_images", false)
|
||||||
c.Set("theme", "dark")
|
|
||||||
|
|
||||||
imagesCookie, err := c.Cookie("disable_images")
|
imagesCookie, err := c.Cookie("disable_images")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -16,13 +15,6 @@ func OptionsMiddleware() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
themeCookie, err := c.Cookie("theme")
|
|
||||||
if err == nil {
|
|
||||||
if themeCookie == "light" {
|
|
||||||
c.Set("theme", "light")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,6 @@ func Ratelimit() gin.HandlerFunc {
|
|||||||
if val.(int) > 30 {
|
if val.(int) > 30 {
|
||||||
c.HTML(429, "home.html", gin.H{
|
c.HTML(429, "home.html", gin.H{
|
||||||
"errorMessage": "You have exceeded the request limit. Please try again in a minute.",
|
"errorMessage": "You have exceeded the request limit. Please try again in a minute.",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
func GetHome(c *gin.Context) {
|
func GetHome(c *gin.Context) {
|
||||||
c.HTML(200, "home.html", gin.H{
|
c.HTML(200, "home.html", gin.H{
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +61,6 @@ func PostHome(c *gin.Context) {
|
|||||||
if err := c.ShouldBind(&body); err != nil {
|
if err := c.ShouldBind(&body); err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
c.HTML(400, "home.html", gin.H{
|
||||||
"errorMessage": "Invalid request body",
|
"errorMessage": "Invalid request body",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -72,7 +70,6 @@ func PostHome(c *gin.Context) {
|
|||||||
if translated == "" {
|
if translated == "" {
|
||||||
c.HTML(400, "home.html", gin.H{
|
c.HTML(400, "home.html", gin.H{
|
||||||
"errorMessage": "Invalid stack overflow/exchange URL",
|
"errorMessage": "Invalid stack overflow/exchange URL",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,6 @@ package routes
|
|||||||
import (
|
import (
|
||||||
"anonymousoverflow/config"
|
"anonymousoverflow/config"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@ -21,26 +19,8 @@ func ChangeOptions(c *gin.Context) {
|
|||||||
c.SetCookie("disable_images", fmt.Sprintf("%t", !c.MustGet("disable_images").(bool)), 60*60*24*365*10, "/", "", false, true)
|
c.SetCookie("disable_images", fmt.Sprintf("%t", !c.MustGet("disable_images").(bool)), 60*60*24*365*10, "/", "", false, true)
|
||||||
c.HTML(200, "home.html", gin.H{
|
c.HTML(200, "home.html", gin.H{
|
||||||
"successMessage": "Images are now " + text,
|
"successMessage": "Images are now " + text,
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
|
|
||||||
case "theme":
|
|
||||||
text := "dark"
|
|
||||||
if c.MustGet("theme").(string) == "dark" {
|
|
||||||
text = "light"
|
|
||||||
}
|
|
||||||
|
|
||||||
c.SetCookie("theme", text, 60*60*24*365*10, "/", "", false, true)
|
|
||||||
// get redirect url from query
|
|
||||||
redirectUrl := c.Query("redirect_url")
|
|
||||||
|
|
||||||
if !strings.HasPrefix(redirectUrl, os.Getenv("APP_URL")) {
|
|
||||||
redirectUrl = os.Getenv("APP_URL")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Redirect(302, redirectUrl)
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
c.String(400, "400 Bad Request")
|
c.String(400, "400 Bad Request")
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
if _, err := strconv.Atoi(questionId); err != nil {
|
if _, err := strconv.Atoi(questionId); err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
c.HTML(400, "home.html", gin.H{
|
||||||
"errorMessage": "Invalid question ID",
|
"errorMessage": "Invalid question ID",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -60,7 +59,6 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
if resp.StatusCode() != 200 {
|
if resp.StatusCode() != 200 {
|
||||||
c.HTML(500, "home.html", gin.H{
|
c.HTML(500, "home.html", gin.H{
|
||||||
"errorMessage": fmt.Sprintf("Received a non-OK status code %d", resp.StatusCode()),
|
"errorMessage": fmt.Sprintf("Received a non-OK status code %d", resp.StatusCode()),
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -74,7 +72,6 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(500, "home.html", gin.H{
|
c.HTML(500, "home.html", gin.H{
|
||||||
"errorMessage": "Unable to parse question data",
|
"errorMessage": "Unable to parse question data",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -84,7 +81,6 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(500, "home.html", gin.H{
|
c.HTML(500, "home.html", gin.H{
|
||||||
"errorMessage": "Failed to extract question data",
|
"errorMessage": "Failed to extract question data",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -94,7 +90,6 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(500, "home.html", gin.H{
|
c.HTML(500, "home.html", gin.H{
|
||||||
"errorMessage": "Failed to extract answer data",
|
"errorMessage": "Failed to extract answer data",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -110,7 +105,6 @@ func ViewQuestion(c *gin.Context) {
|
|||||||
"question": newFilteredQuestion,
|
"question": newFilteredQuestion,
|
||||||
"answers": answers,
|
"answers": answers,
|
||||||
"imagePolicy": imagePolicy,
|
"imagePolicy": imagePolicy,
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"currentUrl": fmt.Sprintf("%s%s", os.Getenv("APP_URL"), c.Request.URL.Path),
|
"currentUrl": fmt.Sprintf("%s%s", os.Getenv("APP_URL"), c.Request.URL.Path),
|
||||||
"sortValue": params.SoSortValue,
|
"sortValue": params.SoSortValue,
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
@ -132,7 +126,6 @@ func parseAndValidateParameters(c *gin.Context) (inputs viewQuestionInputs, err
|
|||||||
if _, err = strconv.Atoi(questionId); err != nil {
|
if _, err = strconv.Atoi(questionId); err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
c.HTML(400, "home.html", gin.H{
|
||||||
"errorMessage": "Invalid question ID",
|
"errorMessage": "Invalid question ID",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
"version": config.Version,
|
"version": config.Version,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
@ -33,7 +33,6 @@ func RedirectShortenedOverflowURL(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.HTML(400, "home.html", gin.H{
|
c.HTML(400, "home.html", gin.H{
|
||||||
"errorMessage": "Unable to fetch stack overflow URL",
|
"errorMessage": "Unable to fetch stack overflow URL",
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -41,7 +40,6 @@ func RedirectShortenedOverflowURL(c *gin.Context) {
|
|||||||
if resp.StatusCode() != 302 {
|
if resp.StatusCode() != 302 {
|
||||||
c.HTML(400, "home.html", gin.H{
|
c.HTML(400, "home.html", gin.H{
|
||||||
"errorMessage": fmt.Sprintf("Unexpected HTTP status from origin: %d", resp.StatusCode()),
|
"errorMessage": fmt.Sprintf("Unexpected HTTP status from origin: %d", resp.StatusCode()),
|
||||||
"theme": c.MustGet("theme").(string),
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html data-theme="{{ .theme }}">
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>AnonymousOverflow - Private frontend for StackOverflow</title>
|
<title>AnonymousOverflow - Private frontend for StackOverflow</title>
|
||||||
@ -43,10 +43,9 @@
|
|||||||
<div class="options">
|
<div class="options">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<a href="/options/images">
|
<a href="/options/images">
|
||||||
<img src="/static/icons/image.svg" alt="Toggle theme" />
|
<img src="/static/icons/image.svg" alt="Toggle images" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{ template "themeSwitcher.html" .}}
|
|
||||||
</div>
|
</div>
|
||||||
<p class="footer">
|
<p class="footer">
|
||||||
Brought to you by
|
Brought to you by
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html data-theme="{{ .theme }}">
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>{{ .question.Title }} | AnonymousOverflow</title>
|
<title>{{ .question.Title }} | AnonymousOverflow</title>
|
||||||
@ -25,7 +25,6 @@
|
|||||||
<a href="/" class="logo-link">
|
<a href="/" class="logo-link">
|
||||||
<img class="logo" src="/static/codecircles.webp" alt="AnonymousOverflow home" />
|
<img class="logo" src="/static/codecircles.webp" alt="AnonymousOverflow home" />
|
||||||
</a>
|
</a>
|
||||||
{{ template "themeSwitcher.html" . }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
<div class="icon">
|
|
||||||
<a href="/options/theme?redirect_url={{ .currentUrl }}">
|
|
||||||
<img src="/static/icons/{{ if eq .theme "dark" }}sun{{
|
|
||||||
else }}moon{{ end }}.svg" alt="Toggle theme" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
Loading…
x
Reference in New Issue
Block a user