From 25562e0d541b35272494d5437a929dad44835828 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Steind=C3=B3r?= <steinibragason@gmail.com>
Date: Sat, 27 May 2017 17:08:47 +0000
Subject: [PATCH 1/7] Account theme switcher (Pls merge) (#750)

* added pagination

* cleanup

* indentation fix

* fix

* Loads theme from context

* Basic theme switching working

* working properly

* Fuck golint tbqh

* united language and theme into one settings page

* made the settings page a little nicer

* fixed it so it works properly now

* removed parts of inline js and fixed bug

* removed remains of other theme switching method

* fixed very minor bug

* fix
---
 main.go                                       |  4 +-
 model/user.go                                 |  3 +-
 public/js/main.js                             | 41 +++++++++++++++++++
 ...ge_handler.go => publicSettingsHandler.go} | 25 ++++++-----
 router/router.go                              |  4 +-
 router/template.go                            |  9 ++--
 router/template_functions.go                  | 14 +++----
 router/template_variables.go                  | 18 ++++++--
 router/upload_handler.go                      |  4 +-
 router/user_handler.go                        | 14 +++----
 router/view_torrent_handler.go                |  4 +-
 service/user/verification.go                  |  4 +-
 templates/index.html                          | 41 ++++---------------
 ...nge_language.html => public_settings.html} | 10 +++++
 util/messages/messages.go                     |  6 +--
 .../publicSettings.go}                        | 15 ++++++-
 .../publicSettings_test.go}                   |  2 +-
 17 files changed, 136 insertions(+), 82 deletions(-)
 rename router/{language_handler.go => publicSettingsHandler.go} (65%)
 rename templates/{change_language.html => public_settings.html} (65%)
 rename util/{languages/translation.go => publicSettings/publicSettings.go} (93%)
 rename util/{languages/translation_test.go => publicSettings/publicSettings_test.go} (94%)

diff --git a/main.go b/main.go
index 6dd01182..a77f03b6 100644
--- a/main.go
+++ b/main.go
@@ -16,7 +16,7 @@ import (
 	"github.com/NyaaPantsu/nyaa/service/scraper"
 	"github.com/NyaaPantsu/nyaa/service/torrent/metainfoFetcher"
 	"github.com/NyaaPantsu/nyaa/service/user"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/NyaaPantsu/nyaa/util/log"
 	"github.com/NyaaPantsu/nyaa/util/search"
 	"github.com/NyaaPantsu/nyaa/util/signals"
@@ -129,7 +129,7 @@ func main() {
 		if err != nil {
 			log.Fatal(err.Error())
 		}
-		err = languages.InitI18n(conf.I18n, userService.NewCurrentUserRetriever())
+		err = publicSettings.InitI18n(conf.I18n, userService.NewCurrentUserRetriever())
 		if err != nil {
 			log.Fatal(err.Error())
 		}
diff --git a/model/user.go b/model/user.go
index 42541a04..940aeacc 100644
--- a/model/user.go
+++ b/model/user.go
@@ -31,6 +31,7 @@ type User struct {
 	APIToken       string    `gorm:"column:api_token"`
 	APITokenExpiry time.Time `gorm:"column:api_token_expiry"`
 	Language       string    `gorm:"column:language"`
+	Theme          string    `gorm:"column:theme"`
 	UserSettings   string    `gorm:"column:settings"`
 
 	// TODO: move this to PublicUser
@@ -62,7 +63,7 @@ func (u User) Size() (s int) {
 		4*3 + //time.Time
 		3*2 + // arrays
 		// string arrays
-		len(u.Username) + len(u.Password) + len(u.Email) + len(u.APIToken) + len(u.MD5) + len(u.Language)
+		len(u.Username) + len(u.Password) + len(u.Email) + len(u.APIToken) + len(u.MD5) + len(u.Language) + len(u.Theme)
 	s *= 8
 
 	// Ignoring foreign key users. Fuck them.
diff --git a/public/js/main.js b/public/js/main.js
index 605f4654..9335f37b 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -11,6 +11,47 @@ function toggleNightMode() {
 	localStorage.setItem("night", (night == "true") ? "false" : "true");
 }
 
+// Switches between themes when a new one is selected
+function switchThemes(){
+	themeName = document.getElementById("theme-selector").value
+	var head = document.getElementsByTagName("head")[0];
+	// Remove the theme in place, it fails if one isn't set
+	try{
+		head.removeChild(document.getElementById("theme"));
+	} catch(err){}
+	// Don't add a node if we don't want extra styling
+	if(themeName === ""){
+		return;
+	}
+	// Create the new one and put it back
+        var newTheme = document.createElement("link");
+        newTheme.setAttribute("rel", "stylesheet");
+        newTheme.setAttribute("href", "/css/"+ themeName + ".css");
+        newTheme.setAttribute("id", "theme");
+	head.appendChild(newTheme);
+}
+
+
+function changeTheme(opt) {
+	theme = opt.value;
+	localStorage.setItem("theme", theme);
+	document.getElementById("theme").href = "/css/" + theme;
+	console.log(theme);
+}
+
+function toggleMascot(btn) {
+	var state= btn.value;
+	if (state == "hide") {
+		btn.innerHTML = "Mascot";
+		document.getElementById("mascot").className = "hide";
+		btn.value = "show";
+	} else {
+		btn.innerHTML = "Mascot";
+		document.getElementById("mascot").className = "";
+		btn.value = "hide";
+	}
+}
+
 // Used by spoiler tags
 function toggleLayer(elem) {
 	if (elem.classList.contains("hide"))
diff --git a/router/language_handler.go b/router/publicSettingsHandler.go
similarity index 65%
rename from router/language_handler.go
rename to router/publicSettingsHandler.go
index cf6dfc3e..eb6d8fb1 100644
--- a/router/language_handler.go
+++ b/router/publicSettingsHandler.go
@@ -5,7 +5,7 @@ import (
 	"net/http"
 
 	"github.com/NyaaPantsu/nyaa/service/user"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/NyaaPantsu/nyaa/util/timeHelper"
 )
 
@@ -15,11 +15,10 @@ type LanguagesJSONResponse struct {
 	Languages map[string]string `json:"languages"`
 }
 
-// SeeLanguagesHandler : Controller to view the languages
-func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) {
-	_, Tlang := languages.GetTfuncAndLanguageFromRequest(r)
-	availableLanguages := languages.GetAvailableLanguages()
-
+// SeePublicSettingsHandler : Controller to view the languages and themes
+func SeePublicSettingsHandler(w http.ResponseWriter, r *http.Request) {
+	_, Tlang := publicSettings.GetTfuncAndLanguageFromRequest(r)
+	availableLanguages := publicSettings.GetAvailableLanguages()
 	defer r.Body.Close()
 	contentType := r.Header.Get("Content-Type")
 	if contentType == "application/json" {
@@ -35,7 +34,7 @@ func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) {
 			Language:                Tlang.Tag,
 			Languages:               availableLanguages,
 		}
-		err := changeLanguageTemplate.ExecuteTemplate(w, "index.html", clv)
+		err := changePublicSettingsTemplate.ExecuteTemplate(w, "index.html", clv)
 		if err != nil {
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return
@@ -43,25 +42,29 @@ func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
-// ChangeLanguageHandler : Controller for changing the current language
-func ChangeLanguageHandler(w http.ResponseWriter, r *http.Request) {
+// ChangePublicSettingsHandler : Controller for changing the current language and theme
+func ChangePublicSettingsHandler(w http.ResponseWriter, r *http.Request) {
+	theme := r.FormValue("theme")
 	lang := r.FormValue("language")
 
+	availableLanguages := publicSettings.GetAvailableLanguages()
 	defer r.Body.Close()
-	availableLanguages := languages.GetAvailableLanguages()
 	if _, exists := availableLanguages[lang]; !exists {
 		http.Error(w, "Language not available", http.StatusInternalServerError)
 		return
 	}
 
-	// If logged in, update user language; if not, set cookie.
+	// If logged in, update user language.
 	user, _ := userService.CurrentUser(r)
 	if user.ID > 0 {
 		user.Language = lang
+		user.Theme = theme
 		// I don't know if I should use this...
 		userService.UpdateUserCore(&user)
 	}
+	// Set cookie
 	http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang, Expires: timeHelper.FewDaysLater(365)})
+	http.SetCookie(w, &http.Cookie{Name: "theme", Value: theme, Expires: timeHelper.FewDaysLater(365)})
 
 	url, _ := Router.Get("home").URL()
 	http.Redirect(w, r, url.String(), http.StatusSeeOther)
diff --git a/router/router.go b/router/router.go
index 81caf978..5bd83037 100755
--- a/router/router.go
+++ b/router/router.go
@@ -114,8 +114,8 @@ func init() {
 
 	Router.Handle("/dumps", gzipDatabaseDumpHandler).Name("dump").Methods("GET")
 
-	Router.HandleFunc("/language", SeeLanguagesHandler).Methods("GET").Name("see_languages")
-	Router.HandleFunc("/language", ChangeLanguageHandler).Methods("POST").Name("change_language")
+	Router.HandleFunc("/settings", SeePublicSettingsHandler).Methods("GET").Name("see_languages")
+	Router.HandleFunc("/settings", ChangePublicSettingsHandler).Methods("POST").Name("see_languages")
 
 	Router.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
 }
diff --git a/router/template.go b/router/template.go
index 224e2c8e..f67cc522 100644
--- a/router/template.go
+++ b/router/template.go
@@ -26,7 +26,7 @@ var homeTemplate,
 	viewUserDeleteTemplate,
 	userTorrentEd,
 	notFoundTemplate,
-	changeLanguageTemplate,
+	changePublicSettingsTemplate,
 	databaseDumpTemplate *template.Template
 
 var panelIndex,
@@ -128,10 +128,11 @@ func ReloadTemplates() {
 			file:  "404.html",
 		},
 		{
-			templ: &changeLanguageTemplate,
-			name:  "change_language",
-			file:  "change_language.html",
+			templ: &changePublicSettingsTemplate,
+			name:  "change_settings",
+			file:  "public_settings.html",
 		},
+
 	}
 	for idx := range pubTempls {
 		pubTempls[idx].indexFile = filepath.Join(TemplateDir, "index.html")
diff --git a/router/template_functions.go b/router/template_functions.go
index 5a2e6a65..5bea0549 100644
--- a/router/template_functions.go
+++ b/router/template_functions.go
@@ -12,12 +12,12 @@ import (
 	"github.com/NyaaPantsu/nyaa/util"
 	"github.com/NyaaPantsu/nyaa/util/categories"
 	"github.com/NyaaPantsu/nyaa/util/filelist"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 )
 
 type captchaData struct {
 	CaptchaID string
-	T         languages.TemplateTfunc
+	T         publicSettings.TemplateTfunc
 }
 
 // FuncMap : Functions accessible in templates by {{ $.Function }}
@@ -146,7 +146,7 @@ var FuncMap = template.FuncMap{
 		return template.HTML(ret)
 	},
 	"Sukebei":            config.IsSukebei,
-	"getDefaultLanguage": languages.GetDefaultLanguage,
+	"getDefaultLanguage": publicSettings.GetDefaultLanguage,
 	"getAvatar": func(hash string, size int) string {
 		return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv.Itoa(size)
 	},
@@ -180,23 +180,23 @@ var FuncMap = template.FuncMap{
 		}
 		return ""
 	},
-	"fileSize": func(filesize int64, T languages.TemplateTfunc) template.HTML {
+	"fileSize": func(filesize int64, T publicSettings.TemplateTfunc) template.HTML {
 		if filesize == 0 {
 			return T("unknown")
 		}
 		return template.HTML(util.FormatFilesize(filesize))
 	},
-	"makeCaptchaData": func(captchaID string, T languages.TemplateTfunc) captchaData {
+	"makeCaptchaData": func(captchaID string, T publicSettings.TemplateTfunc) captchaData {
 		return captchaData{captchaID, T}
 	},
 	"DefaultUserSettings": func(s string) bool {
 		return config.DefaultUserSettings[s]
 	},
-	"makeTreeViewData": func(f *filelist.FileListFolder, nestLevel int, T languages.TemplateTfunc, identifierChain string) interface{} {
+	"makeTreeViewData": func(f *filelist.FileListFolder, nestLevel int, T publicSettings.TemplateTfunc, identifierChain string) interface{} {
 		return struct{
 			Folder *filelist.FileListFolder
 			NestLevel int
-			T languages.TemplateTfunc
+			T publicSettings.TemplateTfunc
 			IdentifierChain string
 		}{ f, nestLevel, T, identifierChain }
 	},
diff --git a/router/template_variables.go b/router/template_variables.go
index 1cd03bab..9c0b4922 100644
--- a/router/template_variables.go
+++ b/router/template_variables.go
@@ -9,7 +9,7 @@ import (
 	"github.com/NyaaPantsu/nyaa/service/user"
 	userForms "github.com/NyaaPantsu/nyaa/service/user/form"
 	"github.com/NyaaPantsu/nyaa/util/filelist"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/gorilla/mux"
 )
 
@@ -74,6 +74,16 @@ type changeLanguageVariables struct {
 	Languages map[string]string
 }
 
+type ChangeThemeVariables struct {
+	commonTemplateVariables
+}
+
+type publicSettingsVariables struct {
+	commonTemplateVariables
+	Language  string
+	Languages map[string]string
+}
+
 /* MODERATION Variables */
 
 type panelIndexVbs struct {
@@ -91,7 +101,8 @@ type panelIndexVbs struct {
 type commonTemplateVariables struct {
 	Navigation navigation
 	Search     searchForm
-	T          languages.TemplateTfunc
+	T          publicSettings.TemplateTfunc
+	Theme      string
 	User       *model.User
 	URL        *url.URL   // for parsing URL in templates
 	Route      *mux.Route // for getting current route in templates
@@ -140,7 +151,8 @@ func newCommonVariables(r *http.Request) commonTemplateVariables {
 	return commonTemplateVariables{
 		Navigation: newNavigation(),
 		Search:     newSearchForm(),
-		T:          languages.GetTfuncFromRequest(r),
+		T:          publicSettings.GetTfuncFromRequest(r),
+		Theme:      publicSettings.GetThemeFromRequest(r),
 		User:       getUser(r),
 		URL:        r.URL,
 		Route:      mux.CurrentRoute(r),
diff --git a/router/upload_handler.go b/router/upload_handler.go
index 58faf8b6..327cbe03 100644
--- a/router/upload_handler.go
+++ b/router/upload_handler.go
@@ -16,7 +16,7 @@ import (
 	"github.com/NyaaPantsu/nyaa/service/upload"
 	"github.com/NyaaPantsu/nyaa/service/user"
 	"github.com/NyaaPantsu/nyaa/service/user/permission"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/NyaaPantsu/nyaa/util/log"
 	msg "github.com/NyaaPantsu/nyaa/util/messages"
 )
@@ -109,7 +109,7 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
 				for _, follower := range user.Followers {
 					follower.ParseSettings() // We need to call it before checking settings
 					if follower.Settings.Get("new_torrent") {
-						T, _, _ := languages.TfuncAndLanguageWithFallback(follower.Language, follower.Language) // We need to send the notification to every user in their language
+						T, _, _ := publicSettings.TfuncAndLanguageWithFallback(follower.Language, follower.Language) // We need to send the notification to every user in their language
 
 						notifierService.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url.String(), follower.Settings.Get("new_torrent_email"))
 					}
diff --git a/router/user_handler.go b/router/user_handler.go
index 6d9cb1a5..c725a998 100644
--- a/router/user_handler.go
+++ b/router/user_handler.go
@@ -12,7 +12,7 @@ import (
 	"github.com/NyaaPantsu/nyaa/service/user/form"
 	"github.com/NyaaPantsu/nyaa/service/user/permission"
 	"github.com/NyaaPantsu/nyaa/util/crypto"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	msg "github.com/NyaaPantsu/nyaa/util/messages"
 	"github.com/NyaaPantsu/nyaa/util/modelHelper"
 	"github.com/gorilla/mux"
@@ -72,7 +72,7 @@ func UserProfileHandler(w http.ResponseWriter, r *http.Request) {
 	defer r.Body.Close()
 	vars := mux.Vars(r)
 	id := vars["id"]
-	Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
+	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
 	messages := msg.GetMessages(r)
 
 	userProfile, _, errorUser := userService.RetrieveUserForAdmin(id)
@@ -125,7 +125,7 @@ func UserDetailsHandler(w http.ResponseWriter, r *http.Request) {
 		if userPermission.CurrentOrAdmin(currentUser, userProfile.ID) {
 			b := form.UserForm{}
 			modelHelper.BindValueForm(&b, r)
-			availableLanguages := languages.GetAvailableLanguages()
+			availableLanguages := publicSettings.GetAvailableLanguages()
 			userProfile.ParseSettings()
 			htv := userProfileEditVariables{newCommonVariables(r), &userProfile, b, messages.GetAllErrors(), messages.GetAllInfos(), availableLanguages}
 			err := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", htv)
@@ -154,7 +154,7 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
 	userForm := form.UserForm{}
 	userSettingsForm := form.UserSettingsForm{}
 
-	Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
+	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
 
 	if len(r.PostFormValue("email")) > 0 {
 		form.EmailValidation(r.PostFormValue("email"), messages)
@@ -189,7 +189,7 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 	}
-	availableLanguages := languages.GetAvailableLanguages()
+	availableLanguages := publicSettings.GetAvailableLanguages()
 	upev := userProfileEditVariables{
 		commonTemplateVariables: newCommonVariables(r),
 		UserProfile:             &userProfile,
@@ -325,7 +325,7 @@ func UserNotificationsHandler(w http.ResponseWriter, r *http.Request) {
 	currentUser := getUser(r)
 	if currentUser.ID > 0 {
 		messages := msg.GetMessages(r)
-		Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
+		Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
 		if r.URL.Query()["clear"] != nil {
 			notifierService.DeleteAllNotifications(currentUser.ID)
 			messages.AddInfo("infos", Ts("notifications_cleared"))
@@ -348,7 +348,7 @@ func UserAPIKeyResetHandler(w http.ResponseWriter, r *http.Request) {
 	id := vars["id"]
 	currentUser := getUser(r)
 
-	Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
+	Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
 	messages := msg.GetMessages(r)
 	userProfile, _, errorUser := userService.RetrieveUserForAdmin(id)
 	if errorUser != nil || !userPermission.CurrentOrAdmin(currentUser, userProfile.ID) || userProfile.ID == 0 {
diff --git a/router/view_torrent_handler.go b/router/view_torrent_handler.go
index b0b25bfd..dd933a5f 100644
--- a/router/view_torrent_handler.go
+++ b/router/view_torrent_handler.go
@@ -17,7 +17,7 @@ import (
 	"github.com/NyaaPantsu/nyaa/service/user/permission"
 	"github.com/NyaaPantsu/nyaa/util"
 	"github.com/NyaaPantsu/nyaa/util/filelist"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/NyaaPantsu/nyaa/util/log"
 	msg "github.com/NyaaPantsu/nyaa/util/messages"
 	"github.com/gorilla/mux"
@@ -113,7 +113,7 @@ func PostCommentHandler(w http.ResponseWriter, r *http.Request) {
 		url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10))
 		torrent.Uploader.ParseSettings()
 		if torrent.Uploader.Settings.Get("new_comment") {
-			T, _, _ := languages.TfuncAndLanguageWithFallback(torrent.Uploader.Language, torrent.Uploader.Language) // We need to send the notification to every user in their language
+			T, _, _ := publicSettings.TfuncAndLanguageWithFallback(torrent.Uploader.Language, torrent.Uploader.Language) // We need to send the notification to every user in their language
 			notifierService.NotifyUser(torrent.Uploader, comment.Identifier(), fmt.Sprintf(T("new_comment_on_torrent"), torrent.Name), url.String(), torrent.Uploader.Settings.Get("new_comment_email"))
 		}
 
diff --git a/service/user/verification.go b/service/user/verification.go
index 09f60b69..3b52b3b8 100644
--- a/service/user/verification.go
+++ b/service/user/verification.go
@@ -11,7 +11,7 @@ import (
 	"github.com/NyaaPantsu/nyaa/db"
 	"github.com/NyaaPantsu/nyaa/model"
 	"github.com/NyaaPantsu/nyaa/util/email"
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/NyaaPantsu/nyaa/util/timeHelper"
 	"github.com/gorilla/securecookie"
 )
@@ -20,7 +20,7 @@ var verificationHandler = securecookie.New(config.EmailTokenHashKey, nil)
 
 // SendEmailVerification sends an email verification token via email.
 func SendEmailVerification(to string, token string) error {
-	T, err := languages.GetDefaultTfunc()
+	T, err := publicSettings.GetDefaultTfunc()
 	if err != nil {
 		return err
 	}
diff --git a/templates/index.html b/templates/index.html
index d3a38ff1..271428de 100755
--- a/templates/index.html
+++ b/templates/index.html
@@ -12,24 +12,18 @@
 
     <!-- RSS Feed with Context -->
     <link href="{{ block "rss_link" . }}{{ genRouteWithQuery "feed" .URL }}{{end}}" rel="alternate" type="application/rss+xml" title="Nyaa Pantsu - {{block "rsstitle" .}}Last torrents{{end}} RSS Feed" />
-
+    
     <!-- do NOT move -->
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
-
-    <link rel="stylesheet" id="style" href="{{.URL.Parse "/css/main.css"}}?v=3">
-    <link rel="stylesheet" id="theme" href="">
+    <!-- Base theme -->
+    <link rel="stylesheet" id="style" href="{{.URL.Parse "/css/main.css"}}?v=2">
+    <!-- User selected theme, if any -->
+    {{if $.Theme}}<link rel="stylesheet" id="theme" href="/css/{{$.Theme}}.css">{{end}}
 
     <!-- Search Box for Google -->
    <script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","url":"https://nyaa.pantsu.cat/","potentialAction":{"@type":"SearchAction","target":"https://nyaa.pantsu.cat/search?q={search_term_string}","query-input":"required name=search_term_string"}}</script>
 		<script>
 			// We need this inline javascript for preventing theme flickering
-			function changeTheme(opt) {
-				theme = opt.value;
-				localStorage.setItem("theme", theme);
-				document.getElementById("theme").href = "/css/" + theme;
-				console.log(theme);
-			}
-
 			function toggleMascot(btn) {
 				var state= btn.value;
 				if (state == "hide") {
@@ -42,24 +36,10 @@
 					btn.value = "hide";
 				}
 			}
-			function setTheme() {
-				var themeFromStorage = localStorage.getItem('theme');
-				document.getElementById('theme').href = "/css/" + themeFromStorage;
-				window.addEventListener("load", () => {
-					var selectOptions = document.getElementById("theme_select").children
-					for (var option of selectOptions) {
-						option.selected = option.value == themeFromStorage;
-					}
-				});
-			}
 		</script>
-		<!-- Fix theme switching for google chrome where onload doesn't work -->
-    <script type="text/javascript">
-			setTheme();
-    </script>
 		{{ block "additional_header" .}}{{end}}
     </head>
-  <body onload="setTheme();">
+   <body>
    <nav id="header" class="header">
 		<div class="container">
 			<div class="h-left">
@@ -108,15 +88,8 @@
 			<div class="container footer center">
 
 				<div class="footer-opt">
-					<select onchange="changeTheme(this.options[this.selectedIndex])" name="Theme" id="theme_select" class="form-input">
-						<option value="">Default</option>
-						<option value="g.css">/g/ Anon</option>
-						<option value="tomorrow.css">Tomorrow</option>
-					</select>
-
 					<button class="form-input btn" onclick="toggleMascot(this)" value="hide"><span class="oi" data-glyph="eye"></span> Mascot</button>
-
-					<p><a href="/language">Change Language</a></p>
+					<p><a href="/settings">Change Settings</a></p>
 				</div>
 
 				<span><i>Powered by <a href="#">NyaaPantsu</a></i></span>
diff --git a/templates/change_language.html b/templates/public_settings.html
similarity index 65%
rename from templates/change_language.html
rename to templates/public_settings.html
index f11c9549..f84ab414 100644
--- a/templates/change_language.html
+++ b/templates/public_settings.html
@@ -11,8 +11,18 @@
 				<option value="{{ $tag }}" {{ if eq $currentLanguage $tag }}selected{{end}}>{{ $translatedName }}</option>
 			{{ end }}
 			</select>
+			<h3>{{call $.T "theme"}}</h3>
+			<select id="theme-selector" name="theme" class="form-input" onchange="switchThemes()">
+				<option value="{{$.Theme}}" selected>{{call $.T "select"}}</option>
+				<option value="g">/g/</option>
+				<option value="tomorrow">Tomorrow</option>
+				<option value="">None</option>
+			</select>
+			</br>
+			</br>
 			<button type="submit" class="form-input btn">{{call $.T "save_changes"}}</button>
 		</div>
+
 	</form>
 	<div style="padding-bottom: 1em"></div>
 </div>
diff --git a/util/messages/messages.go b/util/messages/messages.go
index 4eb9eab7..c620888f 100644
--- a/util/messages/messages.go
+++ b/util/messages/messages.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"net/http"
 
-	"github.com/NyaaPantsu/nyaa/util/languages"
+	"github.com/NyaaPantsu/nyaa/util/publicSettings"
 	"github.com/gorilla/context"
 	"github.com/nicksnyder/go-i18n/i18n"
 )
@@ -24,13 +24,13 @@ type Messages struct {
 func GetMessages(r *http.Request) *Messages {
 	if rv := context.Get(r, MessagesKey); rv != nil {
 		mes := rv.(*Messages)
-		T, _ := languages.GetTfuncAndLanguageFromRequest(r)
+		T, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
 		mes.T = T
 		mes.r = r
 		return mes
 	}
 	context.Set(r, MessagesKey, &Messages{})
-	T, _ := languages.GetTfuncAndLanguageFromRequest(r)
+	T, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
 	return &Messages{make(map[string][]string), make(map[string][]string), r, T}
 }
 
diff --git a/util/languages/translation.go b/util/publicSettings/publicSettings.go
similarity index 93%
rename from util/languages/translation.go
rename to util/publicSettings/publicSettings.go
index 975bfdd0..67d598e8 100644
--- a/util/languages/translation.go
+++ b/util/publicSettings/publicSettings.go
@@ -1,4 +1,4 @@
-package languages
+package publicSettings
 
 import (
 	"errors"
@@ -133,6 +133,19 @@ func GetTfuncFromRequest(r *http.Request) TemplateTfunc {
 	}
 }
 
+// GetThemeFromRequest: Gets the user selected theme from the request
+func GetThemeFromRequest(r *http.Request) string {
+	user, _ := getCurrentUser(r)
+	if user.ID > 0 {
+		return user.Theme
+	}
+	cookie, err := r.Cookie("theme")
+	if err == nil {
+		return cookie.Value
+	}
+	return ""
+}
+
 func getCurrentUser(r *http.Request) (model.User, error) {
 	if userRetriever == nil {
 		return model.User{}, errors.New("failed to get current user: no user retriever set")
diff --git a/util/languages/translation_test.go b/util/publicSettings/publicSettings_test.go
similarity index 94%
rename from util/languages/translation_test.go
rename to util/publicSettings/publicSettings_test.go
index e58d46cb..36851f35 100644
--- a/util/languages/translation_test.go
+++ b/util/publicSettings/publicSettings_test.go
@@ -1,4 +1,4 @@
-package languages
+package publicSettings
 
 import (
 	"path"

From 3c10f9c48e7b14a61b379c51a63695559a3be5e7 Mon Sep 17 00:00:00 2001
From: kipukun <kipukun@waifu.club>
Date: Sat, 27 May 2017 16:48:04 -0400
Subject: [PATCH 2/7] Fix pagination borders

---
 public/css/main.css | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/public/css/main.css b/public/css/main.css
index fd06bf91..acc5e608 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -277,8 +277,8 @@ th { border-bottom-width: 2px; }
 	min-width: 35px;
 }
 
-.pagination li:first-child { border-radius: 3px 0 0 3px; }
-.pagination li:nth-last-child(2)  { border-radius: 0 3px 3px 0; border-right-width: 1px !important}
+.pagination a:first-child li { border-radius: 3px 0 0 3px; }
+.pagination a:nth-last-child(2) li { border-radius: 0 3px 3px 0; border-right-width: 1px !important}
 
 
 #footer { width: 100%; bottom: 0; left: 0; margin-top: 40px;}

From 5f37e7dad72762e96a0a6569f4167a063ba2e66c Mon Sep 17 00:00:00 2001
From: kipukun <kipukun@waifu.club>
Date: Sat, 27 May 2017 17:19:43 -0400
Subject: [PATCH 3/7] Fix dates and user torrent table

---
 public/css/main.css                | 5 +++--
 templates/_user_list_torrents.html | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/public/css/main.css b/public/css/main.css
index acc5e608..4da54fcc 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -222,6 +222,7 @@ select.form-input {
 
 table {
 	border-collapse:collapse;
+	width: 100%;
 	table-layout: fixed;
 }
 
@@ -250,7 +251,7 @@ th { border-bottom-width: 2px; }
 .tr-size { width: 90px; }
 .tr-se, .tr-le { font-weight: bold; }
 .tr-se, .tr-le, .tr-dl { width: 50px; }
-.tr-date { width: 90px; }
+.tr-date { width: 100px; }
 
 .sort-arrows { margin-left: 0.2rem; }
 .sort-arrows span {
@@ -467,7 +468,7 @@ td.tr-le { color: #E84C4C; }
 	font-weight: bold;
 }
 .torrent-info-data {
-	width: 60%;
+	width: 50%;
 }
 .torrent-info-row {
 	text-align: left;
diff --git a/templates/_user_list_torrents.html b/templates/_user_list_torrents.html
index 6844e75e..38a13a54 100644
--- a/templates/_user_list_torrents.html
+++ b/templates/_user_list_torrents.html
@@ -44,7 +44,7 @@
               <td class="tr-size hide-xs">
                   {{ fileSize .Filesize $.T }}
               </td>
-              <td class="tr-date home-td date-short hide-xs">{{.Date}}</td>
+              <td class="tr-date date-short hide-xs">{{.Date}}</td>
           </tr>
           {{end}}
           {{end}}

From ea335c106abe7d3d566a31670fbebe72a0296829 Mon Sep 17 00:00:00 2001
From: kipukun <kipukun@waifu.club>
Date: Sat, 27 May 2017 17:33:52 -0400
Subject: [PATCH 4/7] Fix mascot using wrong mp3 source

---
 public/js/main.js    | 15 +++------------
 templates/index.html | 12 +++++++-----
 2 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/public/js/main.js b/public/js/main.js
index 9335f37b..4da174c4 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -32,13 +32,6 @@ function switchThemes(){
 }
 
 
-function changeTheme(opt) {
-	theme = opt.value;
-	localStorage.setItem("theme", theme);
-	document.getElementById("theme").href = "/css/" + theme;
-	console.log(theme);
-}
-
 function toggleMascot(btn) {
 	var state= btn.value;
 	if (state == "hide") {
@@ -86,13 +79,11 @@ window.onload = function() {
 };
 
 function playVoice() {
-	switch (theme) {
-	case "tomorrow.css":
+	if (explosion) {
 		explosion.play();
-		break;
-	default:
+	}
+	else {
 		nyanpassu.volume = 0.5;
 		nyanpassu.play();
-		break;
 	}
 }
diff --git a/templates/index.html b/templates/index.html
index 271428de..5ff594cc 100755
--- a/templates/index.html
+++ b/templates/index.html
@@ -73,14 +73,16 @@
         {{block "content" .}}{{call $.T "nothing_here"}}{{end}}
       </div>
 <div id="mascot" class="hide-xs" onclick="playVoice();"></div>
+	{{ if eq .Theme "tomorrow" }}
+	<audio id="explosion" hidden preload="none">
+        <source src="https://megumin.love/sounds/explosion.mp3" type="audio/mpeg">
+     </audio>
+	{{ else }}
      <audio id="nyanpassu" hidden preload="none">
         <source src="https://a.doko.moe/sewang.mp3" type="audio/mpeg">
      </audio>
-     <audio id="explosion" hidden preload="none">
-        <source src="https://megumin.love/sounds/explosion.mp3" type="audio/mpeg">
-     </audio>
-
-<div class="pagination">
+	 {{end}}
+     <div class="pagination">
               {{ genNav .Navigation .URL 15 }}
 </div>
 

From 8cf1ce61197a90a0cc2dd884564af2c9ef714cc0 Mon Sep 17 00:00:00 2001
From: kipukun <kipukun@waifu.club>
Date: Sat, 27 May 2017 17:47:52 -0400
Subject: [PATCH 5/7] Make account settings not look like dogshit

---
 public/css/main.css          |  1 +
 templates/_profile_edit.html | 40 ++++++++++++++++++------------------
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/public/css/main.css b/public/css/main.css
index 4da54fcc..999fcbcc 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -518,6 +518,7 @@ td.tr-le { color: #E84C4C; }
 }
 .profile-content {
 	width: 70%;
+	text-align: left;
 }
 .magnet-icon {
 	display: inline-block;
diff --git a/templates/_profile_edit.html b/templates/_profile_edit.html
index bded9849..5c4536e0 100644
--- a/templates/_profile_edit.html
+++ b/templates/_profile_edit.html
@@ -11,14 +11,14 @@
         <form role="form" method="POST">
             <label class="input-label">{{call $.T "api_token" }}:</label>
               <p style="font-family: monospace;">{{.APIToken}}</p>
-              <a class="form-input" href="{{ genRoute "user_profile_apireset" "id" (print .ID) "username" .Username }}">Reset Api key</a> <br> <br>
+              <a class="form-input up-input" href="{{ genRoute "user_profile_apireset" "id" (print .ID) "username" .Username }}">Reset Api key</a> <br> <br>
             <label class="input-label">{{ call $.T "email_address" }}:</label> <br>
-              <input class="form-input" type="text" name="email" id="email" value="{{.Email}}"> <br>
+              <input class="form-input up-input" type="text" name="email" id="email" value="{{.Email}}"> <br>
 	 			{{ range (index $.FormErrors "email")}}
 					<p class="text-error">{{ . }}</p>
 				{{end}}
             <label class="input-label">{{ call $.T "language"}}:</label> <br>
-                <select id="language" name="language" class="form-input">
+                <select id="language" name="language" class="form-input up-input">
 					{{ $userLanguage := .Language }}
 					{{ range $tag, $translatedName := $.Languages }}
 						<option value="{{ $tag }}" {{ if or (eq $userLanguage $tag) (and (eq $userLanguage "") (eq $tag getDefaultLanguage)) }}selected{{end}}>{{ $translatedName }} {{if eq $tag getDefaultLanguage}}({{ call $.T "default" }}){{end}}</option>
@@ -29,18 +29,18 @@
 				{{end}}
           {{ if not (HasAdmin $.User)}}
             <label class="input-label">{{ call $.T "current_password"}}:</label> <br>
-              <input class="form-input" name="current_password" id="current_password" type="password"> <br>
+              <input class="form-input up-input up-input" name="current_password" id="current_password" type="password"> <br>
 	 			{{ range (index $.FormErrors "current_password")}}
 					<p class="text-error">{{ . }}</p>
 				{{end}}
           {{end}}
             <label class="input-label">{{ call $.T "password"}}:</label> <br>
-              <input class="form-input" name="password" id="password" type="password"> <br>
+              <input class="form-input up-input up-input" name="password" id="password" type="password"> <br>
 	 			{{ range (index $.FormErrors "password")}}
 					<p class="text-error">{{ . }}</p>
 				{{end}}
             <label class="input-label">{{ call $.T "confirm_password"}}:</label> <br>
-              <input class="form-input" name="password_confirmation" id="password_confirmation" type="password"> <br>
+              <input class="form-input up-input up-input" name="password_confirmation" id="password_confirmation" type="password"> <br>
 	 			{{ range (index $.FormErrors "password_confirmation")}}
 					<p class="text-error">{{ . }}</p>
 				{{end}}
@@ -48,7 +48,7 @@
           {{ with .Settings }}
           {{ if DefaultUserSettings "new_torrent"}}
             <label class="input-label">{{ call $.T "new_torrent_settings" }}:</label> <br>
-                <select id="new_torrent" name="new_torrent" class="form-control">
+                <select id="new_torrent" name="new_torrent" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_torrent") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_torrent" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -58,7 +58,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_torrent_email"}}
             <label class="input-label">{{ call $.T "new_torrent_email_settings" }}:</label> <br>
-                <select id="new_torrent_email" name="new_torrent_email" class="form-control">
+                <select id="new_torrent_email" name="new_torrent_email" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_torrent_email") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_torrent_email"}}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -68,7 +68,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_comment"}}
             <label class="input-label">{{ call $.T "new_comment_settings" }}:</label> <br>
-                <select id="new_comment" name="new_comment" class="form-control">
+                <select id="new_comment" name="new_comment" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_comment") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_comment" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -78,7 +78,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_comment_email"}}
             <label class="input-label">{{ call $.T "new_comment_email_settings" }}:</label> <br>
-                <select id="new_comment_email" name="new_comment_email" class="form-control">
+                <select id="new_comment_email" name="new_comment_email" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_comment_email") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_comment_email" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -88,7 +88,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_responses"}}
             <label class="input-label">{{ call $.T "new_responses_settings" }}:</label> <br>
-                <select id="new_responses" name="new_responses" class="form-control">
+                <select id="new_responses" name="new_responses" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_responses") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_responses" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -98,7 +98,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_responses_email"}}
             <label class="input-label">{{ call $.T "new_responses_email_settings" }}:</label> <br>
-                <select id="new_responses_email" name="new_responses_email" class="form-control">
+                <select id="new_responses_email" name="new_responses_email" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_responses_email") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_responses_email" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -108,7 +108,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_follower"}}
             <label class="input-label">{{ call $.T "new_follower_settings" }}:</label> <br>
-                <select id="new_follower" name="new_follower" class="form-control">
+                <select id="new_follower" name="new_follower" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_follower") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_follower" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -118,7 +118,7 @@
           {{end}}
           {{ if DefaultUserSettings "new_follower_email"}}
             <label class="input-label">{{ call $.T "new_follower_email_settings" }}:</label> <br>
-                <select id="new_follower_email" name="new_follower_email" class="form-control">
+                <select id="new_follower_email" name="new_follower_email" class="form-input up-input">
                   <option value="0" {{ if not (.Get "new_follower_email") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "new_follower_email"}}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -128,7 +128,7 @@
           {{end}}
           {{ if DefaultUserSettings "followed"}}
             <label class="input-label">{{ call $.T "followed_settings" }}:</label> <br>
-                <select id="followed" name="followed" class="form-control">
+                <select id="followed" name="followed" class="form-input up-input">
                   <option value="0" {{ if not (.Get "followed") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "followed" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select><br>
@@ -138,7 +138,7 @@
           {{end}}
           {{ if DefaultUserSettings "followed_email"}}
             <label class="input-label">{{ call $.T "followed_email_settings" }}:</label> <br>
-                <select id="followed_email" name="followed_email" class="form-control">
+                <select id="followed_email" name="followed_email" class="form-input up-input">
                   <option value="0" {{ if not (.Get "followed_email") }}selected{{end}}>{{ call $.T "no"}}</option>
                   <option value="1" {{ if .Get "followed_email" }}selected{{end}}>{{ call $.T "yes"}}</option>
                 </select> <br>
@@ -150,12 +150,12 @@
           {{ if HasAdmin $.User}}
           <h3>{{ call $.T "moderation"}}</h3>
             <label class="input-label">{{ call $.T "username"}}:</label> <br>
-              <input class="form-control" name="username" id="username" type="text" value="{{.Username}}">
+              <input class="form-input up-input" name="username" id="username" type="text" value="{{.Username}}">
 	 			{{ range (index $.FormErrors "username")}}
 					<p class="text-error">{{ . }}</p>
 				{{end}}
             <label class="input-label">{{ call $.T "role" }}:</label>
-                <select id="status" name="status" class="form-control">
+                <select id="status" name="status" class="form-input up-input">
                 	<option value="-1" {{ if eq .Status -1 }}selected{{end}}>{{ call $.T "banned"}}</option>
                 	<option value="0" {{ if eq .Status 0 }}selected{{end}}>{{ call $.T "member"}} ({{ call $.T "default" }})</option>
                 	<option value="1" {{ if eq .Status 1 }}selected{{end}}>{{ call $.T "trusted_member"}}</option>
@@ -168,9 +168,9 @@
 				{{end}}
 		  {{end}}
             <label class="input-label"></label>
-              <input type="submit" class="btn btn-primary" name="save" value="{{ call $.T "save_changes"}}">
+              <input type="submit" class="form-input" name="save" value="{{ call $.T "save_changes"}}">
               <span></span>
-              <input type="reset" class="btn btn-default" value="{{ call $.T "cancel"}}">
+              <input type="reset" class="form-input" value="{{ call $.T "cancel"}}">
         </form>
        </div>
         {{ if CurrentOrAdmin $.User .ID }}

From 90fbf50fb7d6a1dc8199dc5e8af826845a5fd23e Mon Sep 17 00:00:00 2001
From: kipukun <kipukun@waifu.club>
Date: Sat, 27 May 2017 17:50:59 -0400
Subject: [PATCH 6/7] Small fix to see more torrents button's right width

---
 public/css/main.css | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/public/css/main.css b/public/css/main.css
index 999fcbcc..38134d7f 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -520,6 +520,9 @@ td.tr-le { color: #E84C4C; }
 	width: 70%;
 	text-align: left;
 }
+div.profile-content.box > nav > ul > li {
+	border-right-width: 1px;
+}
 .magnet-icon {
 	display: inline-block;
 	background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAbFBMVEUAAAA2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWs2iWsVx+37AAAAI3RSTlMAAQIDBQgKDhItLklOT1JdY2Z4e3x/kZiwx8jX5unt7/f7/b5l+wAAAABrSURBVBhXhY7JEgFBFARTa4ydwbONNf//H116Ilo4qFNWHiqKTn0ngEKqZqCn/+KsdgOgou9sImIPwDYidvxu3FQnQFI1cVI9jsit6h1W1jlAftaiAaZVXwIwe5T6mpcreXFRr+tx/W/YwwejJxM5Y6lK9QAAAABJRU5ErkJggg==');

From 9e9c1a7aea7bac722fefeac7df7ff0b3ddb2e1fa Mon Sep 17 00:00:00 2001
From: kipukun <kipukun@waifu.club>
Date: Sat, 27 May 2017 18:16:14 -0400
Subject: [PATCH 7/7] Move footer in front of mascot

---
 public/css/main.css | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/public/css/main.css b/public/css/main.css
index 38134d7f..a28ff2ff 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -287,6 +287,8 @@ th { border-bottom-width: 2px; }
 .footer {
 	text-align: center;
 	padding: 1rem 0 1.2rem 0;
+	position: relative;
+	z-index: 2;
  }
 
 .footer-opt {