diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..81855e91 --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ +# Gosora doesn't use Apache, this file is just here to stop Apache from blindly serving our config files, etc. when this program isn't intended to be served in such a manner at all + +deny from all \ No newline at end of file diff --git a/README.md b/README.md index 79c5bd2f..7d56374e 100644 --- a/README.md +++ b/README.md @@ -104,10 +104,14 @@ We're looking for ways to clean-up the plugin system so that all of them (except ![Tempra Simple Mobile](https://github.com/Azareal/Gosora/blob/master/images/tempra-simple-mobile-375px.png) +![Tempra Cursive Theme](https://github.com/Azareal/Gosora/blob/master/images/tempra-cursive.png) + ![Tempra Conflux Theme](https://github.com/Azareal/Gosora/blob/master/images/tempra-conflux.png) ![Tempra Conflux Mobile](https://github.com/Azareal/Gosora/blob/master/images/tempra-conflux-mobile-320px.png) +![Tempra Conflux Mobile](https://github.com/Azareal/Gosora/blob/master/images/tempra-conflux-control-panel.png) + ![Cosmo Conflux Theme](https://github.com/Azareal/Gosora/blob/master/images/cosmo-conflux.png) ![Cosmo Theme](https://github.com/Azareal/Gosora/blob/master/images/cosmo.png) diff --git a/forum.go b/forum.go index 7b2fad0b..988aac15 100644 --- a/forum.go +++ b/forum.go @@ -13,9 +13,7 @@ type ForumAdmin struct Active bool Preset string TopicCount int - PresetLang string - PresetEmoji string } type Forum struct diff --git a/gen_router.go b/gen_router.go index b4a3c09d..9c58a4ec 100644 --- a/gen_router.go +++ b/gen_router.go @@ -1,5 +1,6 @@ // Code generated by. DO NOT EDIT. /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ +// The router generator might be discontinued in favour of syncmaps in Go 1.9, it will be temporarily used for a couple of months as a lockless alternative to maps package main //import "fmt" diff --git a/group.go b/group.go index 63754b0a..5c386281 100644 --- a/group.go +++ b/group.go @@ -12,7 +12,7 @@ type GroupAdmin struct ID int Name string Rank string - RankEmoji string + RankClass string CanEdit bool CanDelete bool } diff --git a/images/alerts.png b/images/cosmo-alerts.png similarity index 100% rename from images/alerts.png rename to images/cosmo-alerts.png diff --git a/images/create-topic.png b/images/create-topic.png new file mode 100644 index 00000000..c90d9c31 Binary files /dev/null and b/images/create-topic.png differ diff --git a/images/edit_setting.PNG b/images/edit_setting.PNG index b9ffa77d..e1b8b7d8 100644 Binary files a/images/edit_setting.PNG and b/images/edit_setting.PNG differ diff --git a/images/forum-list.PNG b/images/forum-list.PNG index a2d703d5..4b6fe612 100644 Binary files a/images/forum-list.PNG and b/images/forum-list.PNG differ diff --git a/images/group_editor.png b/images/group_editor.png new file mode 100644 index 00000000..73c11969 Binary files /dev/null and b/images/group_editor.png differ diff --git a/images/group_editor_wip.png b/images/group_editor_wip.png deleted file mode 100644 index b0d4c781..00000000 Binary files a/images/group_editor_wip.png and /dev/null differ diff --git a/images/group_list.png b/images/group_list.png new file mode 100644 index 00000000..98958a3f Binary files /dev/null and b/images/group_list.png differ diff --git a/images/group_list_wip.png b/images/group_list_wip.png deleted file mode 100644 index 18651a73..00000000 Binary files a/images/group_list_wip.png and /dev/null differ diff --git a/images/panel-dashboard.png b/images/panel-dashboard.png index 8dd11c87..9d01c097 100644 Binary files a/images/panel-dashboard.png and b/images/panel-dashboard.png differ diff --git a/images/tempra-cursive.png b/images/tempra-cursive.png index fed58034..4d731aae 100644 Binary files a/images/tempra-cursive.png and b/images/tempra-cursive.png differ diff --git a/images/tempra-simple-alerts.png b/images/tempra-simple-alerts.png new file mode 100644 index 00000000..d470c5bf Binary files /dev/null and b/images/tempra-simple-alerts.png differ diff --git a/panel_routes.go b/panel_routes.go index 8dd7ad41..f2e5503d 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -28,7 +28,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var cpustr, cpuColour string perc2, err := cpu.Percent(time.Duration(time.Second),true) if err != nil { @@ -44,7 +44,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ cpuColour = "stat_red" } } - + var ramstr, ramColour string memres, err := mem.VirtualMemory() if err != nil { @@ -52,7 +52,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } else { total_count, total_unit := convert_byte_unit(float64(memres.Total)) used_count := convert_byte_in_unit(float64(memres.Total - memres.Available),total_unit) - + // Round totals with .9s up, it's how most people see it anyway. Floats are notoriously imprecise, so do it off 0.85 //fmt.Println(used_count) var totstr string @@ -63,12 +63,12 @@ func route_panel(w http.ResponseWriter, r *http.Request){ totstr = fmt.Sprintf("%.1f",total_count) } //fmt.Println(used_count) - + if used_count > total_count { used_count = total_count } ramstr = fmt.Sprintf("%.1f",used_count) + " / " + totstr + total_unit - + ramperc := ((memres.Total - memres.Available) * 100) / memres.Total //fmt.Println(ramperc) if ramperc < 50 { @@ -79,7 +79,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ ramColour = "stat_red" } } - + var postCount int err = db.QueryRow("select count(*) from replies where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&postCount) if err != nil && err != sql.ErrNoRows { @@ -87,7 +87,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ return } var postInterval string = "day" - + var postColour string if postCount > 25 { postColour = "stat_green" @@ -96,7 +96,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } else { postColour = "stat_red" } - + var topicCount int err = db.QueryRow("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&topicCount) if err != nil && err != sql.ErrNoRows { @@ -104,7 +104,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ return } var topicInterval string = "day" - + var topicColour string if topicCount > 8 { topicColour = "stat_green" @@ -113,7 +113,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } else { topicColour = "stat_red" } - + var reportCount int err = db.QueryRow("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now() and parentID = 1").Scan(&reportCount) if err != nil && err != sql.ErrNoRows { @@ -121,7 +121,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ return } var reportInterval string = "week" - + var newUserCount int err = db.QueryRow("select count(*) from users where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&newUserCount) if err != nil && err != sql.ErrNoRows { @@ -129,18 +129,18 @@ func route_panel(w http.ResponseWriter, r *http.Request){ return } var newUserInterval string = "week" - + var gridElements []GridElement = []GridElement{ GridElement{"dash-version","v" + version.String(),0,"grid_istat stat_green","","","Gosora is up-to-date :)"}, GridElement{"dash-cpu","CPU: " + cpustr + "%",1,"grid_istat " + cpuColour,"","","The global CPU usage of this server"}, GridElement{"dash-ram","RAM: " + ramstr,2,"grid_istat " + ramColour,"","","The global RAM usage of this server"}, } - + if enable_websockets { uonline := ws_hub.UserCount() gonline := ws_hub.GuestCount() totonline := uonline + gonline - + var onlineColour string if totonline > 10 { onlineColour = "stat_green" @@ -149,7 +149,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } else { onlineColour = "stat_red" } - + var onlineGuestsColour string if gonline > 10 { onlineGuestsColour = "stat_green" @@ -158,7 +158,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } else { onlineGuestsColour = "stat_red" } - + var onlineUsersColour string if uonline > 5 { onlineUsersColour = "stat_green" @@ -167,28 +167,28 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } else { onlineUsersColour = "stat_red" } - + totonline, totunit := convert_friendly_unit(totonline) uonline, uunit := convert_friendly_unit(uonline) gonline, gunit := convert_friendly_unit(gonline) - + gridElements = append(gridElements, GridElement{"dash-totonline",strconv.Itoa(totonline) + totunit + " online",3,"grid_stat " + onlineColour,"","","The number of people who are currently online"}) gridElements = append(gridElements, GridElement{"dash-gonline",strconv.Itoa(gonline) + gunit + " guests online",4,"grid_stat " + onlineGuestsColour,"","","The number of guests who are currently online"}) gridElements = append(gridElements, GridElement{"dash-uonline",strconv.Itoa(uonline) + uunit + " users online",5,"grid_stat " + onlineUsersColour,"","","The number of logged-in users who are currently online"}) } - + gridElements = append(gridElements, GridElement{"dash-postsperday",strconv.Itoa(postCount) + " posts / " + postInterval,6,"grid_stat " + postColour,"","","The number of new posts over the last 24 hours"}) gridElements = append(gridElements, GridElement{"dash-topicsperday",strconv.Itoa(topicCount) + " topics / " + topicInterval,7,"grid_stat " + topicColour,"","","The number of new topics over the last 24 hours"}) gridElements = append(gridElements, GridElement{"dash-totonlineperday","20 online / day",8,"grid_stat stat_disabled","","","Coming Soon!"/*"The people online over the last 24 hours"*/}) - + gridElements = append(gridElements, GridElement{"dash-searches","8 searches / week",9,"grid_stat stat_disabled","","","Coming Soon!"/*"The number of searches over the last 7 days"*/}) gridElements = append(gridElements, GridElement{"dash-newusers",strconv.Itoa(newUserCount) + " new users / " + newUserInterval,10,"grid_stat","","","The number of new users over the last 7 days"}) gridElements = append(gridElements, GridElement{"dash-reports",strconv.Itoa(reportCount) + " reports / " + reportInterval,11,"grid_stat","","","The number of reports over the last 7 days"}) - + gridElements = append(gridElements, GridElement{"dash-minperuser","2 minutes / user / week",12,"grid_stat stat_disabled","","","Coming Soon!"/*"The average number of number of minutes spent by each active user over the last 7 days"*/}) gridElements = append(gridElements, GridElement{"dash-visitorsperweek","2 visitors / week",13,"grid_stat stat_disabled","","","Coming Soon!"/*"The number of unique visitors we've had over the last 7 days"*/}) gridElements = append(gridElements, GridElement{"dash-postsperuser","5 posts / user / week",14,"grid_stat stat_disabled","","","Coming Soon!"/*"The average number of posts made by each active user over the past week"*/}) - + pi := PanelDashboardPage{"Control Panel Dashboard",user,noticeList,gridElements,nil} templates.ExecuteTemplate(w,"panel-dashboard.html",pi) } @@ -202,16 +202,22 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var forumList []interface{} for _, forum := range forums { if forum.Name != "" { - fadmin := ForumAdmin{forum.ID,forum.Name,forum.Active,forum.Preset,forum.TopicCount,preset_to_lang(forum.Preset),preset_to_emoji(forum.Preset)} + fadmin := ForumAdmin{forum.ID,forum.Name,forum.Active,forum.Preset,forum.TopicCount,preset_to_lang(forum.Preset)} + if fadmin.Preset == "" { + fadmin.Preset = "custom" + } forumList = append(forumList,fadmin) } } pi := Page{"Forum Manager",user,noticeList,forumList,nil} - templates.ExecuteTemplate(w,"panel-forums.html",pi) + err := templates.ExecuteTemplate(w,"panel-forums.html",pi) + if err != nil { + InternalError(err,w,r) + } } func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){ @@ -223,17 +229,17 @@ func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } if r.FormValue("session") != user.Session { SecurityError(w,r,user) return } - + var active bool fname := r.PostFormValue("forum-name") fpreset := strip_invalid_preset(r.PostFormValue("forum-preset")) @@ -243,13 +249,13 @@ func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){ } else { active = false } - + fid, err := create_forum(fname,active,fpreset) if err != nil { InternalError(err,w,r) return } - + permmap_to_query(preset_to_permmap(fpreset),fid) http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther) } @@ -267,21 +273,21 @@ func route_panel_forums_delete(w http.ResponseWriter, r *http.Request, sfid stri SecurityError(w,r,user) return } - + fid, err := strconv.Atoi(sfid) if err != nil { LocalError("The provided Forum ID is not a valid number.",w,r,user) return } - + if !forum_exists(fid) { LocalError("The forum you're trying to delete doesn't exist.",w,r,user) return } - + confirm_msg := "Are you sure you want to delete the '" + forums[fid].Name + "' forum?" yousure := AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid),confirm_msg} - + pi := Page{"Delete Forum",user,noticeList,tList,yousure} templates.ExecuteTemplate(w,"areyousure.html",pi) } @@ -299,7 +305,7 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request, sf SecurityError(w,r,user) return } - + fid, err := strconv.Atoi(sfid) if err != nil { LocalError("The provided Forum ID is not a valid number.",w,r,user) @@ -309,7 +315,7 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request, sf LocalError("The forum you're trying to delete doesn't exist.",w,r,user) return } - + err = delete_forum(fid) if err != nil { InternalError(err,w,r) @@ -327,7 +333,7 @@ func route_panel_forums_edit(w http.ResponseWriter, r *http.Request, sfid string NoPermissions(w,r,user) return } - + fid, err := strconv.Atoi(sfid) if err != nil { LocalError("The provided Forum ID is not a valid number.",w,r,user) @@ -337,7 +343,7 @@ func route_panel_forums_edit(w http.ResponseWriter, r *http.Request, sfid string LocalError("The forum you're trying to edit doesn't exist.",w,r,user) return } - + pi := Page{"Forum Editor",user,noticeList,tList,nil} templates.ExecuteTemplate(w,"panel-forum-edit.html",pi) } @@ -351,11 +357,11 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, sfid NoPermissions(w,r,user) return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } if r.FormValue("session") != user.Session { SecurityError(w,r,user) @@ -365,30 +371,30 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, sfid if is_js == "" { is_js = "0" } - + fid, err := strconv.Atoi(sfid) if err != nil { LocalErrorJSQ("The provided Forum ID is not a valid number.",w,r,user,is_js) return } - - forum_name := r.PostFormValue("forum-name") - forum_preset := strip_invalid_preset(r.PostFormValue("forum-preset")) - forum_active := r.PostFormValue("forum-active") + + forum_name := r.PostFormValue("forum_name") + forum_preset := strip_invalid_preset(r.PostFormValue("forum_preset")) + forum_active := r.PostFormValue("forum_active") if !forum_exists(fid) { LocalErrorJSQ("The forum you're trying to edit doesn't exist.",w,r,user,is_js) return } - + /*if forum_name == "" && forum_active == "" { LocalErrorJSQ("You haven't changed anything!",w,r,user,is_js) return }*/ - + if forum_name == "" { forum_name = forums[fid].Name } - + var active bool if forum_active == "" { active = forums[fid].Active @@ -397,13 +403,13 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, sfid } else { active = false } - + _, err = update_forum_stmt.Exec(forum_name,active,forum_preset,fid) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - + if forums[fid].Name != forum_name { forums[fid].Name = forum_name } @@ -413,9 +419,9 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, sfid if forums[fid].Preset != forum_preset { forums[fid].Preset = forum_preset } - + permmap_to_query(preset_to_permmap(forum_preset),fid) - + if is_js == "0" { http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther) } else { @@ -432,7 +438,7 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var settingList map[string]interface{} = make(map[string]interface{}) rows, err := db.Query("select name, content, type from settings") if err != nil { @@ -440,7 +446,7 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){ return } defer rows.Close() - + var sname, scontent, stype string for rows.Next() { err := rows.Scan(&sname,&scontent,&stype) @@ -448,7 +454,7 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + if stype == "list" { llist := settingLabels[sname] labels := strings.Split(llist,",") @@ -472,7 +478,7 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + pi := Page{"Setting Manager",user,noticeList,tList,settingList} templates.ExecuteTemplate(w,"panel-settings.html",pi) } @@ -487,7 +493,7 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request, sname string){ return } setting := Setting{sname,"","",""} - + err := db.QueryRow("select content, type from settings where name = ?", setting.Name).Scan(&setting.Content,&setting.Type) if err == sql.ErrNoRows { LocalError("The setting you want to edit doesn't exist.",w,r,user) @@ -496,7 +502,7 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request, sname string){ InternalError(err,w,r) return } - + var itemList []interface{} if setting.Type == "list" { llist, ok := settingLabels[setting.Name] @@ -504,13 +510,13 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request, sname string){ LocalError("The labels for this setting don't exist",w,r,user) return } - + conv, err := strconv.Atoi(setting.Content) if err != nil { LocalError("The value of this setting couldn't be converted to an integer",w,r,user) return } - + labels := strings.Split(llist,",") for index, label := range labels { itemList = append(itemList, OptionLabel{ @@ -520,7 +526,7 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request, sname string){ }) } } - + pi := Page{"Edit Setting",user,noticeList,itemList,setting} templates.ExecuteTemplate(w,"panel-setting.html",pi) } @@ -534,21 +540,21 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, sname stri NoPermissions(w,r,user) return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } if r.FormValue("session") != user.Session { SecurityError(w,r,user) return } - + var stype string var sconstraints string scontent := r.PostFormValue("setting-value") - + err = db.QueryRow("select name, type, constraints from settings where name = ?", sname).Scan(&sname, &stype, &sconstraints) if err == sql.ErrNoRows { LocalError("The setting you want to edit doesn't exist.",w,r,user) @@ -557,7 +563,7 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, sname stri InternalError(err,w,r) return } - + if stype == "bool" { if scontent == "on" || scontent == "1" { scontent = "1" @@ -565,13 +571,13 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, sname stri scontent = "0" } } - + _, err = update_setting_stmt.Exec(scontent,sname) if err != nil { InternalError(err,w,r) return } - + errmsg := parseSetting(sname, scontent, stype, sconstraints) if errmsg != "" { LocalError(errmsg,w,r,user) @@ -589,12 +595,12 @@ func route_panel_plugins(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var pluginList []interface{} for _, plugin := range plugins { pluginList = append(pluginList,plugin) } - + pi := Page{"Plugin Manager",user,noticeList,pluginList,nil} templates.ExecuteTemplate(w,"panel-plugins.html",pi) } @@ -612,20 +618,20 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, uname SecurityError(w,r,user) return } - + plugin, ok := plugins[uname] if !ok { LocalError("The plugin isn't registered in the system",w,r,user) return } - + var active bool err := db.QueryRow("select active from plugins where uname = ?", uname).Scan(&active) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return } - + if plugins[uname].Activate != nil { err = plugins[uname].Activate() if err != nil { @@ -633,7 +639,7 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, uname return } } - + has_plugin := err != sql.ErrNoRows if has_plugin { if active { @@ -652,7 +658,7 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, uname return } } - + log.Print("Activating plugin '" + plugin.Name + "'") plugin.Active = true plugins[uname] = plugin @@ -669,18 +675,18 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, unam NoPermissions(w,r,user) return } - + if r.FormValue("session") != user.Session { SecurityError(w,r,user) return } - + plugin, ok := plugins[uname] if !ok { LocalError("The plugin isn't registered in the system",w,r,user) return } - + var active bool err := db.QueryRow("select active from plugins where uname = ?", uname).Scan(&active) if err == sql.ErrNoRows { @@ -690,7 +696,7 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, unam InternalError(err,w,r) return } - + if !active { LocalError("The plugin you're trying to deactivate isn't active",w,r,user) return @@ -700,11 +706,11 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, unam InternalError(err,w,r) return } - + plugin.Active = false plugins[uname] = plugin plugins[uname].Deactivate() - + http.Redirect(w,r,"/panel/plugins/",http.StatusSeeOther) } @@ -717,7 +723,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var userList []interface{} rows, err := db.Query("select `uid`,`name`,`group`,`active`,`is_super_admin`,`avatar` from users") if err != nil { @@ -725,7 +731,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ return } defer rows.Close() - + for rows.Next() { puser := User{ID: 0,} err := rows.Scan(&puser.ID, &puser.Name, &puser.Group, &puser.Active, &puser.Is_Super_Admin, &puser.Avatar) @@ -733,7 +739,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + init_user_perms(&puser) if puser.Avatar != "" { if puser.Avatar[0] == '.' { @@ -742,7 +748,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ } else { puser.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(puser.ID),1) } - + if groups[puser.Group].Tag != "" { puser.Tag = groups[puser.Group].Tag } else { @@ -755,7 +761,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + pi := Page{"User Manager",user,noticeList,userList,nil} err = templates.ExecuteTemplate(w,"panel-users.html",pi) if err != nil { @@ -768,19 +774,19 @@ func route_panel_users_edit(w http.ResponseWriter, r *http.Request,suid string){ if !ok { return } - + // Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with if !user.Is_Super_Mod || !user.Perms.EditUser { NoPermissions(w,r,user) return } - + uid, err := strconv.Atoi(suid) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) return } - + targetUser, err := users.CascadeGet(uid) if err == sql.ErrNoRows { LocalError("The user you're trying to edit doesn't exist.",w,r,user) @@ -789,12 +795,12 @@ func route_panel_users_edit(w http.ResponseWriter, r *http.Request,suid string){ InternalError(err,w,r) return } - + if targetUser.Is_Admin && !user.Is_Admin { LocalError("Only administrators can edit the account of an administrator.",w,r,user) return } - + var groupList []interface{} for _, group := range groups[1:] { if !user.Perms.EditUserGroupAdmin && group.Is_Admin { @@ -805,7 +811,7 @@ func route_panel_users_edit(w http.ResponseWriter, r *http.Request,suid string){ } groupList = append(groupList,group) } - + pi := Page{"User Editor",user,noticeList,groupList,targetUser} err = templates.ExecuteTemplate(w,"panel-user-edit.html",pi) if err != nil { @@ -826,13 +832,13 @@ func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request, suid SecurityError(w,r,user) return } - + uid, err := strconv.Atoi(suid) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) return } - + targetUser, err := users.CascadeGet(uid) if err == sql.ErrNoRows { LocalError("The user you're trying to edit doesn't exist.",w,r,user) @@ -841,18 +847,18 @@ func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request, suid InternalError(err,w,r) return } - + if targetUser.Is_Admin && !user.Is_Admin { LocalError("Only administrators can edit the account of an administrator.",w,r,user) return } - + newname := html.EscapeString(r.PostFormValue("user-name")) if newname == "" { LocalError("You didn't put in a username.",w,r,user) return } - + newemail := html.EscapeString(r.PostFormValue("user-email")) if newemail == "" { LocalError("You didn't put in an email address.",w,r,user) @@ -862,24 +868,24 @@ func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request, suid LocalError("You need the EditUserEmail permission to edit the email address of a user.",w,r,user) return } - + newpassword := r.PostFormValue("user-password") if newpassword != "" && !user.Perms.EditUserPassword { LocalError("You need the EditUserPassword permission to edit the password of a user.",w,r,user) return } - + newgroup, err := strconv.Atoi(r.PostFormValue("user-group")) if err != nil { LocalError("The provided GroupID is not a valid number.",w,r,user) return } - + if (newgroup > groupCapCount) || (newgroup < 0) || groups[newgroup].Name=="" { LocalError("The group you're trying to place this user in doesn't exist.",w,r,user) return } - + if !user.Perms.EditUserGroupAdmin && groups[newgroup].Is_Admin { LocalError("You need the EditUserGroupAdmin permission to assign someone to an administrator group.",w,r,user) return @@ -888,23 +894,23 @@ func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request, suid LocalError("You need the EditUserGroupAdmin permission to assign someone to a super mod group.",w,r,user) return } - + _, err = update_user_stmt.Exec(newname,newemail,newgroup,targetUser.ID) if err != nil { InternalError(err,w,r) return } - + if newpassword != "" { SetPassword(targetUser.ID,newpassword) } - + err = users.Load(targetUser.ID) if err != nil { LocalError("This user no longer exists!",w,r,user) return } - + http.Redirect(w,r,"/panel/users/edit/" + strconv.Itoa(targetUser.ID),http.StatusSeeOther) } @@ -917,37 +923,37 @@ func route_panel_groups(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var groupList []interface{} for _, group := range groups[1:] { var rank string - var rank_emoji string + var rank_class string var can_edit bool var can_delete bool = false - + if group.Is_Admin { rank = "Admin" - rank_emoji = "👑" + rank_class = "admin" } else if group.Is_Mod { rank = "Mod" - rank_emoji = "👮" + rank_class = "mod" } else if group.Is_Banned { rank = "Banned" - rank_emoji = "⛓️" + rank_class = "banned" } else if group.ID == 6 { rank = "Guest" - rank_emoji = "👽" + rank_class = "guest" } else { rank = "Member" - rank_emoji = "👪" + rank_class = "member" } - + can_edit = user.Perms.EditGroup && (!group.Is_Admin || user.Perms.EditGroupAdmin) && (!group.Is_Mod || user.Perms.EditGroupSuperMod) - - groupList = append(groupList, GroupAdmin{group.ID,group.Name,rank,rank_emoji,can_edit,can_delete}) + + groupList = append(groupList, GroupAdmin{group.ID,group.Name,rank,rank_class,can_edit,can_delete}) } //fmt.Printf("%+v\n", groupList) - + pi := Page{"Group Manager",user,noticeList,groupList,nil} templates.ExecuteTemplate(w,"panel-groups.html",pi) } @@ -961,19 +967,19 @@ func route_panel_groups_edit(w http.ResponseWriter, r *http.Request, sgid string NoPermissions(w,r,user) return } - + gid, err := strconv.Atoi(sgid) if err != nil { LocalError("The Group ID is not a valid integer.",w,r,user) return } - + if !group_exists(gid) { //fmt.Println("aaaaa monsters") NotFound(w,r) return } - + group := groups[gid] if group.Is_Admin && !user.Perms.EditGroupAdmin { LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) @@ -983,7 +989,7 @@ func route_panel_groups_edit(w http.ResponseWriter, r *http.Request, sgid string LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) return } - + var rank string if group.Is_Admin { rank = "Admin" @@ -996,9 +1002,9 @@ func route_panel_groups_edit(w http.ResponseWriter, r *http.Request, sgid string } else { rank = "Member" } - + disable_rank := !user.Perms.EditGroupGlobalPerms || (group.ID == 6) - + pi := EditGroupPage{"Group Editor",user,noticeList,group.ID,group.Name,group.Tag,rank,disable_rank,nil} err = templates.ExecuteTemplate(w,"panel-group-edit.html",pi) if err != nil { @@ -1015,19 +1021,19 @@ func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request, sgid NoPermissions(w,r,user) return } - + gid, err := strconv.Atoi(sgid) if err != nil { LocalError("The Group ID is not a valid integer.",w,r,user) return } - + if !group_exists(gid) { //fmt.Println("aaaaa monsters") NotFound(w,r) return } - + group := groups[gid] if group.Is_Admin && !user.Perms.EditGroupAdmin { LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) @@ -1037,7 +1043,7 @@ func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request, sgid LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) return } - + var localPerms []NameLangToggle localPerms = append(localPerms, NameLangToggle{"ViewTopic",GetLocalPermPhrase("ViewTopic"),group.Perms.ViewTopic}) localPerms = append(localPerms, NameLangToggle{"LikeItem",GetLocalPermPhrase("LikeItem"),group.Perms.LikeItem}) @@ -1050,7 +1056,7 @@ func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request, sgid localPerms = append(localPerms, NameLangToggle{"DeleteReply",GetLocalPermPhrase("DeleteReply"),group.Perms.DeleteReply}) localPerms = append(localPerms, NameLangToggle{"PinTopic",GetLocalPermPhrase("PinTopic"),group.Perms.PinTopic}) localPerms = append(localPerms, NameLangToggle{"CloseTopic",GetLocalPermPhrase("CloseTopic"),group.Perms.CloseTopic}) - + var globalPerms []NameLangToggle globalPerms = append(globalPerms, NameLangToggle{"BanUsers",GetGlobalPermPhrase("BanUsers"),group.Perms.BanUsers}) globalPerms = append(globalPerms, NameLangToggle{"ActivateUsers",GetGlobalPermPhrase("ActivateUsers"),group.Perms.ActivateUsers}) @@ -1071,7 +1077,7 @@ func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request, sgid globalPerms = append(globalPerms, NameLangToggle{"ManagePlugins",GetGlobalPermPhrase("ManagePlugins"),group.Perms.ManagePlugins}) globalPerms = append(globalPerms, NameLangToggle{"ViewAdminLogs",GetGlobalPermPhrase("ViewAdminLogs"),group.Perms.ViewAdminLogs}) globalPerms = append(globalPerms, NameLangToggle{"ViewIPs",GetGlobalPermPhrase("ViewIPs"),group.Perms.ViewIPs}) - + pi := EditGroupPermsPage{"Group Editor",user,noticeList,group.ID,group.Name,localPerms,globalPerms,nil} err = templates.ExecuteTemplate(w,"panel-group-edit-perms.html",pi) if err != nil { @@ -1092,19 +1098,19 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid SecurityError(w,r,user) return } - + gid, err := strconv.Atoi(sgid) if err != nil { LocalError("The Group ID is not a valid integer.",w,r,user) return } - + if !group_exists(gid) { //fmt.Println("aaaaa monsters") NotFound(w,r) return } - + group := groups[gid] if group.Is_Admin && !user.Perms.EditGroupAdmin { LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) @@ -1114,7 +1120,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) return } - + gname := r.FormValue("group-name") if gname == "" { LocalError("The group name can't be left blank.",w,r,user) @@ -1122,7 +1128,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid } gtag := r.FormValue("group-tag") rank := r.FormValue("group-type") - + var original_rank string if group.Is_Admin { original_rank = "Admin" @@ -1135,7 +1141,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid } else { original_rank = "Member" } - + group_update_mutex.Lock() defer group_update_mutex.Unlock() if rank != original_rank { @@ -1143,14 +1149,14 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid LocalError("You need the EditGroupGlobalPerms permission to change the group type.",w,r,user) return } - + switch(rank) { case "Admin": if !user.Perms.EditGroupAdmin { LocalError("You need the EditGroupAdmin permission to designate this group as an admin group.",w,r,user) return } - + _, err = update_group_rank_stmt.Exec(1,1,0,gid) if err != nil { InternalError(err,w,r) @@ -1164,7 +1170,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid LocalError("You need the EditGroupSuperMod permission to designate this group as a super-mod group.",w,r,user) return } - + _, err = update_group_rank_stmt.Exec(0,1,0,gid) if err != nil { InternalError(err,w,r) @@ -1199,7 +1205,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid return } } - + _, err = update_group_stmt.Exec(gname,gtag,gid) if err != nil { InternalError(err,w,r) @@ -1207,7 +1213,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, sgid } groups[gid].Name = gname groups[gid].Tag = gtag - + http.Redirect(w,r,"/panel/groups/edit/" + strconv.Itoa(gid),http.StatusSeeOther) } @@ -1224,19 +1230,19 @@ func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request SecurityError(w,r,user) return } - + gid, err := strconv.Atoi(sgid) if err != nil { LocalError("The Group ID is not a valid integer.",w,r,user) return } - + if !group_exists(gid) { //fmt.Println("aaaaa monsters") NotFound(w,r) return } - + group := groups[gid] if group.Is_Admin && !user.Perms.EditGroupAdmin { LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) @@ -1246,7 +1252,7 @@ func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) return } - + //var lpmap map[string]bool = make(map[string]bool) var pmap map[string]bool = make(map[string]bool) if user.Perms.EditGroupLocalPerms { @@ -1256,7 +1262,7 @@ func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request pmap[perm] = (pvalue == "1") } } - + //var gpmap map[string]bool = make(map[string]bool) if user.Perms.EditGroupGlobalPerms { gplist := GlobalPermList @@ -1265,25 +1271,25 @@ func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request pmap[perm] = (pvalue == "1") } } - + pjson, err := json.Marshal(pmap) if err != nil { LocalError("Unable to marshal the data",w,r,user) return } - + _, err = update_group_perms_stmt.Exec(pjson,gid) if err != nil { InternalError(err,w,r) return } - + err = rebuild_group_permissions(gid) if err != nil { InternalError(err,w,r) return } - + http.Redirect(w,r,"/panel/groups/edit/perms/" + strconv.Itoa(gid),http.StatusSeeOther) } @@ -1300,14 +1306,14 @@ func route_panel_groups_create_submit(w http.ResponseWriter, r *http.Request){ SecurityError(w,r,user) return } - + group_name := r.PostFormValue("group-name") if group_name == "" { LocalError("You need a name for this group!",w,r,user) return } group_tag := r.PostFormValue("group-tag") - + var is_admin, is_mod, is_banned bool if user.Perms.EditGroupGlobalPerms { group_type := r.PostFormValue("group-type") @@ -1328,7 +1334,7 @@ func route_panel_groups_create_submit(w http.ResponseWriter, r *http.Request){ is_banned = true } } - + gid, err := create_group(group_name, group_tag, is_admin, is_mod, is_banned) if err != nil { InternalError(err,w,r) @@ -1347,7 +1353,7 @@ func route_panel_themes(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + var pThemeList, vThemeList []Theme for _, theme := range themes { if theme.HideFromThemes { @@ -1358,9 +1364,9 @@ func route_panel_themes(w http.ResponseWriter, r *http.Request){ } else { vThemeList = append(vThemeList,theme) } - + } - + pi := ThemesPage{"Theme Manager",user,noticeList,pThemeList,vThemeList,nil} err := templates.ExecuteTemplate(w,"panel-themes.html",pi) if err != nil { @@ -1381,7 +1387,7 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, uname st SecurityError(w,r,user) return } - + theme, ok := themes[uname] if !ok { LocalError("The theme isn't registered in the system",w,r,user) @@ -1391,14 +1397,14 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, uname st LocalError("You must not enable this theme",w,r,user) return } - + var isDefault bool err := db.QueryRow("select `default` from `themes` where `uname` = ?", uname).Scan(&isDefault) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return } - + has_theme := err != sql.ErrNoRows if has_theme { if isDefault { @@ -1417,17 +1423,17 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, uname st return } } - + _, err = update_theme_stmt.Exec(0,defaultTheme) if err != nil { InternalError(err,w,r) return } - + log.Print("Setting theme '" + theme.Name + "' as the default theme") theme.Active = true themes[uname] = theme - + dTheme, ok := themes[defaultTheme] if !ok { InternalError(errors.New("The default theme is missing"),w,r) @@ -1435,12 +1441,12 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, uname st } dTheme.Active = false themes[defaultTheme] = dTheme - + defaultTheme = uname reset_template_overrides() add_theme_static_files(uname) map_theme_templates(theme) - + http.Redirect(w,r,"/panel/themes/",http.StatusSeeOther) } @@ -1453,14 +1459,14 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + rows, err := db.Query("select action, elementID, elementType, ipaddress, actorID, doneAt from moderation_logs") if err != nil { InternalError(err,w,r) return } defer rows.Close() - + var logs []Log var action, elementType, ipaddress, doneAt string var elementID, actorID int @@ -1470,12 +1476,12 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + actor, err := users.CascadeGet(actorID) if err != nil { actor = &User{Name:"Unknown"} } - + switch(action) { case "lock": topic, err := topics.CascadeGet(elementID) @@ -1539,7 +1545,7 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + pi := LogsPage{"Moderation Logs",user,noticeList,logs,nil} err = templates.ExecuteTemplate(w,"panel-modlogs.html",pi) if err != nil { diff --git a/permissions.go b/permissions.go index 5b6c53d0..15922558 100644 --- a/permissions.go +++ b/permissions.go @@ -1,4 +1,5 @@ package main + import "log" import "fmt" import "sync" @@ -78,7 +79,7 @@ type Perms struct ManagePlugins bool ViewAdminLogs bool ViewIPs bool - + // Forum permissions ViewTopic bool LikeItem bool @@ -93,7 +94,7 @@ type Perms struct PinTopic bool CloseTopic bool //CloseOwnTopic bool - + ExtData interface{} } @@ -113,7 +114,7 @@ type ForumPerms struct PinTopic bool CloseTopic bool //CloseOwnTopic bool - + Overrides bool ExtData map[string]bool } @@ -122,16 +123,16 @@ func init() { BlankPerms = Perms{ ExtData: make(map[string]bool), } - + BlankForumPerms = ForumPerms{ ExtData: make(map[string]bool), } - + GuestPerms = Perms{ ViewTopic: true, ExtData: make(map[string]bool), } - + AllPerms = Perms{ BanUsers: true, ActivateUsers: true, @@ -152,7 +153,7 @@ func init() { ManagePlugins: true, ViewAdminLogs: true, ViewIPs: true, - + ViewTopic: true, LikeItem: true, CreateTopic: true, @@ -163,10 +164,10 @@ func init() { DeleteReply: true, PinTopic: true, CloseTopic: true, - + ExtData: make(map[string]bool), } - + AllForumPerms = ForumPerms{ ViewTopic: true, LikeItem: true, @@ -178,11 +179,11 @@ func init() { DeleteReply: true, PinTopic: true, CloseTopic: true, - + Overrides: true, ExtData: make(map[string]bool), } - + ReadWriteForumPerms = ForumPerms{ ViewTopic: true, LikeItem: true, @@ -191,7 +192,7 @@ func init() { Overrides: true, ExtData: make(map[string]bool), } - + ReadReplyForumPerms = ForumPerms{ ViewTopic: true, LikeItem: true, @@ -199,15 +200,15 @@ func init() { Overrides: true, ExtData: make(map[string]bool), } - + ReadForumPerms = ForumPerms{ ViewTopic: true, Overrides: true, ExtData: make(map[string]bool), } - + guest_user.Perms = GuestPerms - + if debug { fmt.Printf("Guest Perms: ") fmt.Printf("%+v\n", GuestPerms) @@ -262,12 +263,12 @@ var permupdate_mutex sync.Mutex func permmap_to_query(permmap map[string]ForumPerms, fid int) error { permupdate_mutex.Lock() defer permupdate_mutex.Unlock() - + _, err := delete_forum_perms_by_forum_stmt.Exec(fid) if err != nil { return err } - + perms, err := json.Marshal(permmap["admins"]) if err != nil { return err @@ -276,7 +277,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - + perms, err = json.Marshal(permmap["staff"]) if err != nil { return err @@ -285,7 +286,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - + perms, err = json.Marshal(permmap["members"]) if err != nil { return err @@ -294,7 +295,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - + perms, err = json.Marshal(permmap["guests"]) if err != nil { return err @@ -303,7 +304,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - + return rebuild_forum_permissions(fid) } @@ -314,7 +315,7 @@ func rebuild_forum_permissions(fid int) error { return err } defer rows.Close() - + log.Print("Updating the forum permissions") for rows.Next() { var gid int @@ -342,7 +343,7 @@ func rebuild_forum_permissions(fid int) error { var blank_int_list []int groups[gid].Forums = blank_list groups[gid].CanSee = blank_int_list - + for ffid, _ := range forums { forum_perm, ok := forum_perms[gid][ffid] if ok { @@ -353,7 +354,7 @@ func rebuild_forum_permissions(fid int) error { forum_perm = BlankForumPerms groups[gid].Forums = append(groups[gid].Forums,forum_perm) } - + if forum_perm.Overrides { if forum_perm.ViewTopic { groups[gid].CanSee = append(groups[gid].CanSee, ffid) @@ -375,7 +376,7 @@ func build_forum_permissions() error { func strip_invalid_preset(preset string) string { switch(preset) { - case "all","announce","members","staff","admins","archive": + case "all","announce","members","staff","admins","archive","custom": break default: return "" } @@ -384,17 +385,18 @@ func strip_invalid_preset(preset string) string { func preset_to_lang(preset string) string { switch(preset) { - case "all": return ""//return "Everyone" + case "all": return "Public" case "announce": return "Announcements" case "members": return "Member Only" case "staff": return "Staff Only" case "admins": return "Admin Only" case "archive": return "Archive" + case "custom": return "Custom" } return "" } -func preset_to_emoji(preset string) string { +/*func preset_to_emoji(preset string) string { switch(preset) { case "all": return ""//return "Everyone" case "announce": return "📣" @@ -404,7 +406,7 @@ func preset_to_emoji(preset string) string { case "archive": return "☠️" } return "" -} +}*/ func rebuild_group_permissions(gid int) error { var permstr []byte @@ -413,13 +415,13 @@ func rebuild_group_permissions(gid int) error { if err != nil { return err } - + tmp_perms := Perms{ExtData: make(map[string]bool)} err = json.Unmarshal(permstr, &tmp_perms) if err != nil { return err } - + groups[gid].Perms = tmp_perms return nil } diff --git a/plugin_bbcode.go b/plugin_bbcode.go index 3de421d2..5d5fe58b 100644 --- a/plugin_bbcode.go +++ b/plugin_bbcode.go @@ -172,6 +172,7 @@ func bbcode_parse_without_code(data interface{}) interface{} { msg = bbcode_url_label.ReplaceAllString(msg,"$4") msg = bbcode_quotes.ReplaceAllString(msg,"$1") } + return string(msgbytes) } @@ -181,6 +182,7 @@ func bbcode_full_parse(data interface{}) interface{} { //fmt.Println("BBCode PrePre String:") //fmt.Println("`"+msg+"`") //fmt.Println("----") + msgbytes := []byte(msg) has_u := false has_b := false @@ -189,6 +191,7 @@ func bbcode_full_parse(data interface{}) interface{} { has_c := false complex_bbc := false msgbytes = append(msgbytes,space_gap...) + //fmt.Println("BBCode Simple Pre:") //fmt.Println("`"+string(msgbytes)+"`") //fmt.Println("----") @@ -272,8 +275,7 @@ func bbcode_full_parse(data interface{}) interface{} { if complex_bbc { i := 0 - var start int - var lastTag int + var start, lastTag int var outbytes []byte //fmt.Println("BBCode Pre:") //fmt.Println("`"+string(msgbytes)+"`") @@ -366,5 +368,6 @@ func bbcode_full_parse(data interface{}) interface{} { } else { msg = string(msgbytes[0:len(msgbytes) - 10]) } + return msg } diff --git a/plugin_markdown.go b/plugin_markdown.go index ff5d7bdd..9474e4c7 100644 --- a/plugin_markdown.go +++ b/plugin_markdown.go @@ -1,29 +1,373 @@ package main + +//import "fmt" import "regexp" +//import "strings" + +var markdown_max_depth int = 25 // How deep the parser will go when parsing Markdown strings +var markdown_unclosed_element []byte + +var markdown_bold_tag_open []byte +var markdown_bold_tag_close []byte +var markdown_italic_tag_open []byte +var markdown_italic_tag_close []byte +var markdown_underline_tag_open []byte +var markdown_underline_tag_close []byte +var markdown_strike_tag_open []byte +var markdown_strike_tag_close []byte var markdown_bold_italic *regexp.Regexp var markdown_bold *regexp.Regexp var markdown_italic *regexp.Regexp +var markdown_strike *regexp.Regexp +var markdown_underline *regexp.Regexp func init() { plugins["markdown"] = NewPlugin("markdown","Markdown","Azareal","http://github.com/Azareal","","","",init_markdown,nil,deactivate_markdown) } func init_markdown() { + //plugins["markdown"].AddHook("parse_assign", markdown_regex_parse) plugins["markdown"].AddHook("parse_assign", markdown_parse) + + markdown_unclosed_element = []byte("[Unclosed Element]") + + markdown_bold_tag_open = []byte("") + markdown_bold_tag_close = []byte("") + markdown_italic_tag_open = []byte("") + markdown_italic_tag_close = []byte("") + markdown_underline_tag_open = []byte("") + markdown_underline_tag_close = []byte("") + markdown_strike_tag_open = []byte("") + markdown_strike_tag_close = []byte("") + markdown_bold_italic = regexp.MustCompile(`\*\*\*(.*)\*\*\*`) markdown_bold = regexp.MustCompile(`\*\*(.*)\*\*`) markdown_italic = regexp.MustCompile(`\*(.*)\*`) + //markdown_strike = regexp.MustCompile(`\~\~(.*)\~\~`) + markdown_strike = regexp.MustCompile(`\~(.*)\~`) + //markdown_underline = regexp.MustCompile(`\_\_(.*)\_\_`) + markdown_underline = regexp.MustCompile(`\_(.*)\_`) } func deactivate_markdown() { + //plugins["markdown"].RemoveHook("parse_assign", markdown_regex_parse) plugins["markdown"].RemoveHook("parse_assign", markdown_parse) } -func markdown_parse(data interface{}) interface{} { +func markdown_regex_parse(data interface{}) interface{} { msg := data.(string) msg = markdown_bold_italic.ReplaceAllString(msg,"$1") msg = markdown_bold.ReplaceAllString(msg,"$1") msg = markdown_italic.ReplaceAllString(msg,"$1") + msg = markdown_strike.ReplaceAllString(msg,"$1") + msg = markdown_underline.ReplaceAllString(msg,"$1") return msg -} \ No newline at end of file +} + + +// An adapter for the parser, so that the parser can call itself recursively. +// This is less for the simple Markdown elements like bold and italics and more for the really complicated ones I plan on adding at some point. +func markdown_parse(data interface{}) interface{} { + return _markdown_parse(data.(string) + " ",0) +} + +// Under Construction! +func _markdown_parse(msg string, n int) string { + if n > markdown_max_depth { + return "[Markdown Error: Overflowed the max depth of 20]" + } + + var outbytes []byte + var lastElement int + //fmt.Println("enter message loop") + //fmt.Printf("Message: %v\n",strings.Replace(msg,"\r","\\r",-1)) + + for index := 0; index < len(msg); index++ { + /*//fmt.Println("--OUTER MARKDOWN LOOP START--") + //fmt.Println("index",index) + //fmt.Println("msg[index]",msg[index]) + //fmt.Println("string(msg[index])",string(msg[index])) + //fmt.Println("--OUTER MARKDOWN LOOP END--") + //fmt.Println(" ")*/ + + switch(msg[index]) { + case '_': + var startIndex int = index + if (index + 1) >= len(msg) { + break + } + + index++ + index = markdown_skip_until_char(msg, index, '_') + if (index - (startIndex + 1)) < 2 || index >= len(msg) { + break + } + + sIndex := startIndex + 1 + lIndex := index + index++ + + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_underline_tag_open...) + outbytes = append(outbytes, msg[sIndex:lIndex]...) + outbytes = append(outbytes, markdown_underline_tag_close...) + + lastElement = index + index-- + case '~': + var startIndex int = index + if (index + 1) >= len(msg) { + break + } + + index++ + index = markdown_skip_until_char(msg, index, '~') + if (index - (startIndex + 1)) < 2 || index >= len(msg) { + break + } + + sIndex := startIndex + 1 + lIndex := index + index++ + + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_strike_tag_open...) + outbytes = append(outbytes, msg[sIndex:lIndex]...) + outbytes = append(outbytes, markdown_strike_tag_close...) + + lastElement = index + index-- + case '*': + //fmt.Println("------") + //fmt.Println("[]byte(msg):",[]byte(msg)) + //fmt.Println("len(msg)",len(msg)) + //fmt.Println("start index",index) + //fmt.Println("start msg[index]",msg[index]) + //fmt.Println("start string(msg[index])",string(msg[index])) + //fmt.Println("start []byte(msg[:index])",[]byte(msg[:index])) + + var startIndex int = index + var italic bool = true + var bold bool + if (index + 2) < len(msg) { + //fmt.Println("start index + 1",index + 1) + //fmt.Println("start msg[index]",msg[index + 1]) + //fmt.Println("start string(msg[index])",string(msg[index + 1])) + + if msg[index + 1] == '*' { + //fmt.Println("two asterisks") + bold = true + index++ + if msg[index + 1] != '*' { + italic = false + } else { + //fmt.Println("three asterisks") + index++ + } + } + } + + //fmt.Println("lastElement",lastElement) + //fmt.Println("startIndex:",startIndex) + //fmt.Println("msg[startIndex]",msg[startIndex]) + //fmt.Println("string(msg[startIndex])",string(msg[startIndex])) + + //fmt.Println("preabrupt index",index) + //fmt.Println("preabrupt msg[index]",msg[index]) + //fmt.Println("preabrupt string(msg[index])",string(msg[index])) + //fmt.Println("preabrupt []byte(msg[:index])",[]byte(msg[:index])) + //fmt.Println("preabrupt msg[:index]",msg[:index]) + + // Does the string terminate abruptly? + if (index + 1) >= len(msg) { + break + } + + index++ + + //fmt.Println("preskip index",index) + //fmt.Println("preskip msg[index]",msg[index]) + //fmt.Println("preskip string(msg[index])",string(msg[index])) + + index = markdown_skip_until_asterisk(msg,index) + + if index >= len(msg) { + break + } + + //fmt.Println("index",index) + //fmt.Println("[]byte(msg[:index])",[]byte(msg[:index])) + //fmt.Println("msg[index]",msg[index]) + + sIndex := startIndex + lIndex := index + if bold && italic { + //fmt.Println("bold & italic final code") + if (index + 3) >= len(msg) { + //fmt.Println("unclosed markdown element @ exit element") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_unclosed_element...) + lastElement = startIndex + break + } + index += 3 + sIndex += 3 + } else if bold { + //fmt.Println("bold final code") + if (index + 2) >= len(msg) { + //fmt.Println("true unclosed markdown element @ exit element") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_unclosed_element...) + lastElement = startIndex + break + } + index += 2 + sIndex += 2 + } else { + //fmt.Println("italic final code") + if (index + 1) >= len(msg) { + //fmt.Println("true unclosed markdown element @ exit element") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_unclosed_element...) + lastElement = startIndex + break + } + index++ + sIndex++ + } + + //fmt.Println("sIndex",sIndex) + //fmt.Println("lIndex",lIndex) + + if lIndex <= sIndex { + //fmt.Println("unclosed markdown element @ lIndex <= sIndex") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_unclosed_element...) + lastElement = startIndex + break + } + + if sIndex < 0 || lIndex < 0 { + //fmt.Println("unclosed markdown element @ sIndex < 0 || lIndex < 0") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdown_unclosed_element...) + lastElement = startIndex + break + } + + //fmt.Println("final sIndex",sIndex) + //fmt.Println("final lIndex",lIndex) + //fmt.Println("final index",index) + //fmt.Println("final msg[index]",msg[index]) + //fmt.Println("final string(msg[index])",string(msg[index])) + + //fmt.Println("final msg[sIndex]",msg[sIndex]) + //fmt.Println("final string(msg[sIndex])",string(msg[sIndex])) + //fmt.Println("final msg[lIndex]",msg[lIndex]) + //fmt.Println("final string(msg[lIndex])",string(msg[lIndex])) + + //fmt.Println("[]byte(msg[:sIndex])",[]byte(msg[:sIndex])) + //fmt.Println("[]byte(msg[:lIndex])",[]byte(msg[:lIndex])) + + outbytes = append(outbytes, msg[lastElement:startIndex]...) + + if bold { + outbytes = append(outbytes, markdown_bold_tag_open...) + } + if italic { + outbytes = append(outbytes, markdown_italic_tag_open...) + } + + outbytes = append(outbytes, msg[sIndex:lIndex]...) + + if bold { + outbytes = append(outbytes, markdown_bold_tag_close...) + } + if italic { + outbytes = append(outbytes, markdown_italic_tag_close...) + } + + lastElement = index + index-- + //case '`': + //case '_': + //case '~': + //case 10: // newline + } + } + + //fmt.Println("exit message loop") + //fmt.Println(" ") + + if len(outbytes) == 0 { + return msg + } else if lastElement < (len(msg) - 1) { + return string(outbytes) + msg[lastElement:] + } + return string(outbytes) +} + +func markdown_find_char(data string ,index int ,char byte) bool { + for ; index < len(data); index++ { + item := data[index] + if item > 32 { + return (item == char) + } + } + return false +} + +func markdown_skip_until_char(data string, index int, char byte) int { + for ; index < len(data); index++ { + if data[index] == char { + break + } + } + return index +} + +func markdown_skip_until_asterisk(data string, index int) int { +SwitchLoop: + for ; index < len(data); index++ { + switch(data[index]) { + case 10: + if ((index+1) < len(data)) && markdown_find_char(data,index,'*') { + index = markdown_skip_list(data,index) + } + case '*': break SwitchLoop + } + } + return index +} + +// plugin_markdown doesn't support lists yet, but I want it to be easy to have nested lists when we do have them +func markdown_skip_list(data string, index int) int { + var lastNewline int + var datalen int = len(data) + + for ; index < datalen; index++ { + SkipListInnerLoop: + if data[index] == 10 { + lastNewline = index + for ; index < datalen; index++ { + if data[index] > 32 { + break + } else if data[index] == 10 { + goto SkipListInnerLoop + } + } + + if index >= datalen { + if data[index] != '*' && data[index] != '-' { + if (lastNewline + 1) < datalen { + return lastNewline + 1 + } + return lastNewline + } + } + } + } + + return index +} diff --git a/public/global.js b/public/global.js index 2e60e0a2..def40bb7 100644 --- a/public/global.js +++ b/public/global.js @@ -21,12 +21,12 @@ function load_alerts(menu_alerts) menu_alerts.find(".alertList").html("
"+data.errmsg+"
"); return; } - + var alist = ""; for(var i in data.msgs) { var msg = data.msgs[i]; var mmsg = msg.msg; - + if("sub" in msg) { for(var i = 0; i < msg.sub.length; i++) { mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]); @@ -34,11 +34,11 @@ function load_alerts(menu_alerts) console.log(msg.sub[i]); } } - + if(mmsg.length > 46) mmsg = mmsg.substring(0,43) + "..."; else if(mmsg.length > 35) size_dial = " smaller"; //9px else size_dial = ""; // 10px - + if("avatar" in msg) { alist += "
"+mmsg+"
"; console.log(msg.avatar); @@ -48,10 +48,8 @@ function load_alerts(menu_alerts) console.log(msg); //console.log(mmsg); } - - if(alist == "") { - alist = "
You don't have any alerts
" - } + + if(alist == "") alist = "
You don't have any alerts
"; menu_alerts.find(".alertList").html(alist); if(data.msgs.length != 0) { menu_alerts.find(".alert_counter").text(data.msgs.length); @@ -65,7 +63,7 @@ function load_alerts(menu_alerts) console.log(data.errmsg); errtxt = data.errmsg; } - else errtxt = "Unable to get the alerts" + else errtxt = "Unable to get the alerts"; } catch(e) { errtxt = "Unable to get the alerts"; } menu_alerts.find(".alertList").html("
"+errtxt+"
"); } @@ -74,81 +72,77 @@ function load_alerts(menu_alerts) $(document).ready(function(){ function SplitN(data,ch,n) { - var out = [] - if(data.length == 0) { - return out - } - - var lastIndex = 0 - var j = 0 - var lastN = 1 + var out = []; + if(data.length == 0) return out; + + var lastIndex = 0; + var j = 0; + var lastN = 1; for(var i = 0; i < data.length; i++) { if(data[i] == ch) { - out[j++] = data.substring(lastIndex,i) - lastIndex = i - if(lastN == n) { - break - } - lastN++ + out[j++] = data.substring(lastIndex,i); + lastIndex = i; + if(lastN == n) break; + lastN++; } } if(data.length > lastIndex) { - out[out.length - 1] += data.substring(lastIndex) + out[out.length - 1] += data.substring(lastIndex); } - return out + return out; } - + if(window["WebSocket"]) { - conn = new WebSocket("ws://" + document.location.host + "/ws/") + conn = new WebSocket("ws://" + document.location.host + "/ws/"); conn.onopen = function() { - conn.send("page " + document.location.pathname + '\r') + conn.send("page " + document.location.pathname + '\r'); } conn.onclose = function() { - conn = false + conn = false; } conn.onmessage = function(event) { - //console.log("WS_Message:") - //console.log(event.data) - var messages = event.data.split('\r') + //console.log("WS_Message:"); + //console.log(event.data); + var messages = event.data.split('\r'); for(var i = 0; i < messages.length; i++) { - //console.log("Message:") - //console.log(messages[i]) + //console.log("Message:"); + //console.log(messages[i]); if(messages[i].startsWith("set ")) { - //msgblocks = messages[i].split(' ',3) - msgblocks = SplitN(messages[i]," ",3) + //msgblocks = messages[i].split(' ',3); + msgblocks = SplitN(messages[i]," ",3); if(msgblocks.length < 3) { - continue + continue; } - document.querySelector(msgblocks[1]).innerHTML = msgblocks[2] + document.querySelector(msgblocks[1]).innerHTML = msgblocks[2]; } else if(messages[i].startsWith("set-class ")) { - msgblocks = SplitN(messages[i]," ",3) + msgblocks = SplitN(messages[i]," ",3); if(msgblocks.length < 3) { - continue + continue; } - document.querySelector(msgblocks[1]).className = msgblocks[2] + document.querySelector(msgblocks[1]).className = msgblocks[2]; } } } } else { conn = false } - + $(".open_edit").click(function(event){ //console.log("Clicked on edit"); event.preventDefault(); $(".hide_on_edit").hide(); $(".show_on_edit").show(); }); - + $(".topic_item .submit_edit").click(function(event){ event.preventDefault(); $(".topic_name").html($(".topic_name_input").val()); $(".topic_content").html($(".topic_content_input").val()); $(".topic_status_e:not(.open_edit)").html($(".topic_status_input").val()); - + $(".hide_on_edit").show(); $(".show_on_edit").hide(); - + var topic_name_input = $('.topic_name_input').val(); var topic_status_input = $('.topic_status_input').val(); var topic_content_input = $('.topic_content_input').val(); @@ -158,31 +152,31 @@ $(document).ready(function(){ //console.log("Form Action: " + form_action); $.ajax({ url: form_action, + type: "POST", + dataType: "json", data: { topic_name: topic_name_input, topic_status: topic_status_input, topic_content: topic_content_input, topic_js: 1 - }, - type: "POST", - dataType: "json" + } }); }); - + $(".delete_item").click(function(event) { post_link(event); var block = $(this).closest('.deletable_block'); block.remove(); }); - + $(".edit_item").click(function(event) { event.preventDefault(); var block_parent = $(this).closest('.editable_parent'); var block = block_parent.find('.editable_block').eq(0); block.html("
"); - + $(".submit_edit").click(function(event) { event.preventDefault(); @@ -190,21 +184,21 @@ $(document).ready(function(){ var block = block_parent.find('.editable_block').eq(0); var newContent = block.find('textarea').eq(0).val(); block.html(newContent); - + var form_action = $(this).closest('a').attr("href"); //console.log("Form Action: " + form_action); $.ajax({ url: form_action, type: "POST", dataType: "json", data: { is_js: "1", edit_item: newContent } }); }); }); - + $(".edit_field").click(function(event) { event.preventDefault(); var block_parent = $(this).closest('.editable_parent'); var block = block_parent.find('.editable_block').eq(0); block.html(""); - + $(".submit_edit").click(function(event) { event.preventDefault(); @@ -212,7 +206,7 @@ $(document).ready(function(){ var block = block_parent.find('.editable_block').eq(0); var newContent = block.find('input').eq(0).val(); block.html(newContent); - + var form_action = $(this).closest('a').attr("href"); //console.log("Form Action: " + form_action); $.ajax({ @@ -223,25 +217,38 @@ $(document).ready(function(){ }); }); }); - + $(".edit_fields").click(function(event) { event.preventDefault(); + //console.log("clicked .edit_fields"); var block_parent = $(this).closest('.editable_parent'); + //console.log(block_parent); block_parent.find('.hide_on_edit').hide(); block_parent.find('.editable_block').show(); block_parent.find('.editable_block').each(function(){ var field_name = this.getAttribute("data-field"); var field_type = this.getAttribute("data-type"); - if(field_type=="list") { + if(field_type=="list") + { var field_value = this.getAttribute("data-value"); if(field_name in form_vars) var it = form_vars[field_name]; else var it = ['No','Yes']; var itLen = it.length; var out = ""; + //console.log("Field Name '" + field_name + "'") + //console.log("Field Type",field_type) + //console.log("Field Value '" + field_value + "'") for (var i = 0; i < itLen; i++){ - if(field_value==i) sel = "selected "; - else sel = ""; + //console.log("Field Possibility '" + it[i] + "'"); + if(field_value == i || field_value == it[i]) { + sel = "selected "; + //console.log("Class List: ",this.classList) + this.classList.remove(field_name + '_' + it[i]); + //console.log("Removing " + field_name + '_' + it[i]); + //console.log(this.classList) + this.innerHTML = ""; + } else sel = ""; out += ""; } this.innerHTML = ""; @@ -249,22 +256,35 @@ $(document).ready(function(){ else this.innerHTML = ""; }); block_parent.find('.show_on_edit').eq(0).show(); - + + // Remove any handlers already attached to the submitter + $(".submit_edit").unbind("click"); + $(".submit_edit").click(function(event) { event.preventDefault(); + //console.log("running .submit_edit event"); var out_data = {is_js: "1"} var block_parent = $(this).closest('.editable_parent'); var block = block_parent.find('.editable_block').each(function(){ var field_name = this.getAttribute("data-field"); var field_type = this.getAttribute("data-type"); - if(field_type == "list") var newContent = $(this).find('select :selected').text(); - else var newContent = $(this).find('input').eq(0).val(); - - this.innerHTML = newContent; - out_data[field_name] = newContent + if(field_type == "list") { + var newContent = $(this).find('select :selected').text(); + this.classList.add(field_name + '_' + newContent); + this.innerHTML = ""; + } else { + var newContent = $(this).find('input').eq(0).val(); + this.innerHTML = newContent; + } + //console.log(".submit_edit"); + //console.log("field_name",field_name); + //console.log("field_type",field_type); + //console.log("newContent",newContent); + this.setAttribute("data-value",newContent); + out_data[field_name] = newContent; }); - + var form_action = $(this).closest('a').attr("href"); //console.log("Form Action: " + form_action); //console.log(out_data); @@ -273,7 +293,7 @@ $(document).ready(function(){ block_parent.find('.show_on_edit').hide(); }); }); - + $(".ip_item").each(function(){ var ip = this.textContent; //console.log("IP: " + ip); @@ -285,24 +305,24 @@ $(document).ready(function(){ }; } }); - + $(this).click(function() { $(".selectedAlert").removeClass("selectedAlert"); }); - + $(".menu_alerts").ready(function(){ load_alerts($(this)); }); - + $(".menu_alerts").click(function(event) { event.stopPropagation(); if($(this).hasClass("selectedAlert")) return; this.className += " selectedAlert"; load_alerts($(this)); }); - + this.onkeyup = function(event){ if(event.which == 37) this.querySelectorAll("#prevFloat a")[0].click(); if(event.which == 39) this.querySelectorAll("#nextFloat a")[0].click(); }; -}); \ No newline at end of file +}); diff --git a/router_gen/main.go b/router_gen/main.go index 22228610..2633e283 100644 --- a/router_gen/main.go +++ b/router_gen/main.go @@ -1,4 +1,5 @@ /* WIP Under Construction */ +// The router generator might be discontinued in favour of syncmaps in Go 1.9, it will be temporarily used for a couple of months as a lockless alternative to maps package main import "log" @@ -16,7 +17,7 @@ func main() { routes() var out string - var fdata string = "// Code generated by. DO NOT EDIT.\n/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */\n" + var fdata string = "// Code generated by. DO NOT EDIT.\n/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */\n// The router generator might be discontinued in favour of syncmaps in Go 1.9, it will be temporarily used for a couple of months as a lockless alternative to maps\n" for _, route := range route_list { var end int diff --git a/routes.go b/routes.go index 8ab4b1de..46638483 100644 --- a/routes.go +++ b/routes.go @@ -34,7 +34,7 @@ func route_static(w http.ResponseWriter, r *http.Request){ w.WriteHeader(http.StatusNotFound) return } - + // Surely, there's a more efficient way of doing this? if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && file.Info.ModTime().Before(t.Add(1 * time.Second)) { w.WriteHeader(http.StatusNotModified) @@ -72,9 +72,9 @@ func route_overview(w http.ResponseWriter, r *http.Request){ } pi := Page{"Overview",user,noticeList,tList,nil} err := templates.ExecuteTemplate(w,"overview.html",pi) - if err != nil { - InternalError(err,w,r) - } + if err != nil { + InternalError(err,w,r) + } } func route_custom_page(w http.ResponseWriter, r *http.Request){ @@ -87,19 +87,19 @@ func route_custom_page(w http.ResponseWriter, r *http.Request){ NotFound(w,r) return } - + err := templates.ExecuteTemplate(w,"page_" + name,Page{"Page",user,noticeList,tList,nil}) if err != nil { InternalError(err,w,r) } } - + func route_topics(w http.ResponseWriter, r *http.Request){ user, noticeList, ok := SessionCheck(w,r) if !ok { return } - + var fidList []string group := groups[user.Group] for _, fid := range group.CanSee { @@ -107,7 +107,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ fidList = append(fidList,strconv.Itoa(fid)) } } - + var topicList []TopicsRow rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.likeCount, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid where parentID in("+strings.Join(fidList,",")+") order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC") //rows, err := get_topic_list_stmt.Query() @@ -115,7 +115,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + topicItem := TopicsRow{ID: 0} for rows.Next() { err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.ParentID, &topicItem.LikeCount, &topicItem.CreatedByName, &topicItem.Avatar) @@ -123,7 +123,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + if topicItem.Avatar != "" { if topicItem.Avatar[0] == '.' { topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar @@ -131,13 +131,13 @@ func route_topics(w http.ResponseWriter, r *http.Request){ } else { topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1) } - + if topicItem.ParentID >= 0 { topicItem.ForumName = forums[topicItem.ParentID].Name } else { topicItem.ForumName = "" } - + /*topicItem.CreatedAt, err = relative_time(topicItem.CreatedAt) if err != nil { InternalError(err,w,r) @@ -146,7 +146,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ if err != nil { InternalError(err,w,r) } - + if hooks["trow_assign"] != nil { topicItem = run_hook("trow_assign", topicItem).(TopicsRow) } @@ -158,7 +158,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ return } rows.Close() - + pi := TopicsPage{"Topic List",user,noticeList,topicList,nil} if template_topics_handle != nil { template_topics_handle(pi,w) @@ -177,7 +177,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, sfid string){ PreError("The provided ForumID is not a valid number.",w,r) return } - + user, noticeList, ok := ForumSessionCheck(w,r,fid) if !ok { return @@ -187,7 +187,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, sfid string){ NoPermissions(w,r,user) return } - + // Calculate the offset var offset int last_page := int(forums[fid].TopicCount / items_per_page) + 1 @@ -204,7 +204,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, sfid string){ InternalError(err,w,r) return } - + var topicList []TopicUser topicItem := TopicUser{ID: 0} for rows.Next() { @@ -213,7 +213,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, sfid string){ InternalError(err,w,r) return } - + if topicItem.Avatar != "" { if topicItem.Avatar[0] == '.' { topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar @@ -221,12 +221,12 @@ func route_forum(w http.ResponseWriter, r *http.Request, sfid string){ } else { topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1) } - + topicItem.LastReplyAt, err = relative_time(topicItem.LastReplyAt) if err != nil { InternalError(err,w,r) } - + if hooks["trow_assign"] != nil { topicItem = run_hook("trow_assign", topicItem).(TopicUser) } @@ -238,7 +238,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, sfid string){ return } rows.Close() - + pi := ForumPage{forums[fid].Name,user,noticeList,topicList,forums[fid],page,last_page,nil} if template_forum_handle != nil { template_forum_handle(pi,w) @@ -255,7 +255,7 @@ func route_forums(w http.ResponseWriter, r *http.Request){ if !ok { return } - + var forumList []Forum var err error group := groups[user.Group] @@ -276,7 +276,7 @@ func route_forums(w http.ResponseWriter, r *http.Request){ forumList = append(forumList, forum) } } - + pi := ForumsPage{"Forum List",user,noticeList,forumList,nil} if template_forums_handle != nil { template_forums_handle(pi,w) @@ -287,19 +287,19 @@ func route_forums(w http.ResponseWriter, r *http.Request){ } } } - + func route_topic_id(w http.ResponseWriter, r *http.Request){ var err error var page, offset int var replyList []Reply - + page, _ = strconv.Atoi(r.FormValue("page")) tid, err := strconv.Atoi(r.URL.Path[len("/topic/"):]) if err != nil { PreError("The provided TopicID is not a valid number.",w,r) return } - + // Get the topic... topic, err := get_topicuser(tid) if err == sql.ErrNoRows { @@ -310,7 +310,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ return } topic.Css = no_css_tmpl - + user, noticeList, ok := ForumSessionCheck(w,r,topic.ParentID) if !ok { return @@ -320,20 +320,20 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - + topic.Content = parse_message(topic.Content) topic.ContentLines = strings.Count(topic.Content,"\n") - + // We don't want users posting in locked topics... if topic.Is_Closed && !user.Is_Mod { user.Perms.CreateReply = false } - + topic.Tag = groups[topic.Group].Tag if groups[topic.Group].Is_Mod || groups[topic.Group].Is_Admin { topic.Css = staff_css_tmpl } - + /*if settings["url_tags"] == false { topic.URLName = "" } else { @@ -344,7 +344,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ topic.URL = topic.URL + topic.URLName } }*/ - + // Calculate the offset last_page := int(topic.PostCount / items_per_page) + 1 if page > 1 { @@ -355,7 +355,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } else { page = 1 } - + // Get the replies.. rows, err := get_topic_replies_offset_stmt.Query(topic.ID, offset) if err == sql.ErrNoRows { @@ -365,7 +365,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + replyItem := Reply{Css: no_css_tmpl} for rows.Next() { err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &replyItem.Group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress, &replyItem.LikeCount, &replyItem.ActionType) @@ -373,17 +373,17 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + replyItem.ParentID = topic.ID replyItem.ContentHtml = parse_message(replyItem.Content) replyItem.ContentLines = strings.Count(replyItem.Content,"\n") - + if groups[replyItem.Group].Is_Mod || groups[replyItem.Group].Is_Admin { replyItem.Css = staff_css_tmpl } else { replyItem.Css = no_css_tmpl } - + if replyItem.Avatar != "" { if replyItem.Avatar[0] == '.' { replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar @@ -391,9 +391,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } else { replyItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyItem.CreatedBy),1) } - + replyItem.Tag = groups[replyItem.Group].Tag - + /*if settings["url_tags"] == false { replyItem.URLName = "" } else { @@ -404,7 +404,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ replyItem.URL = replyItem.URL + replyItem.URLName } }*/ - + // We really shouldn't have inline HTML, we should do something about this... if replyItem.ActionType != "" { switch(replyItem.ActionType) { @@ -426,7 +426,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } } replyItem.Liked = false - + if hooks["rrow_assign"] != nil { replyItem = run_hook("rrow_assign", replyItem).(Reply) } @@ -438,7 +438,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ return } rows.Close() - + tpage := TopicPage{topic.Title,user,noticeList,replyList,topic,page,last_page,nil} if template_topic_handle != nil { template_topic_handle(tpage,w) @@ -455,19 +455,19 @@ func route_profile(w http.ResponseWriter, r *http.Request){ if !ok { return } - + var err error var replyContent, replyCreatedByName, replyCreatedAt, replyAvatar, replyTag string var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyLines, replyGroup int var replyCss template.CSS var replyList []Reply - + pid, err := strconv.Atoi(r.URL.Path[len("/user/"):]) if err != nil { LocalError("The provided User ID is not a valid number.",w,r,user) return } - + var puser *User if pid == user.ID { user.Is_Mod = true @@ -483,7 +483,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ return } } - + // Get the replies.. rows, err := db.Query("select users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group from users_replies left join users ON users_replies.createdBy = users.uid where users_replies.uid = ?", puser.ID) if err != nil { @@ -491,14 +491,14 @@ func route_profile(w http.ResponseWriter, r *http.Request){ return } defer rows.Close() - + for rows.Next() { err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &replyGroup) if err != nil { InternalError(err,w,r) return } - + replyLines = strings.Count(replyContent,"\n") if groups[replyGroup].Is_Mod || groups[replyGroup].Is_Admin { replyCss = staff_css_tmpl @@ -512,7 +512,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } else { replyAvatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyCreatedBy),1) } - + if groups[replyGroup].Tag != "" { replyTag = groups[replyGroup].Tag } else if puser.ID == replyCreatedBy { @@ -520,10 +520,10 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } else { replyTag = "" } - + replyLiked := false replyLikeCount := 0 - + replyList = append(replyList, Reply{rid,puser.ID,replyContent,parse_message(replyContent),replyCreatedBy,replyCreatedByName,replyGroup,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","","",0,"",replyLiked,replyLikeCount,"",""}) } err = rows.Err() @@ -531,7 +531,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ InternalError(err,w,r) return } - + ppage := ProfilePage{puser.Name + "'s Profile",user,noticeList,replyList,*puser,false} if template_profile_handle != nil { template_profile_handle(ppage,w) @@ -553,7 +553,7 @@ func route_topic_create(w http.ResponseWriter, r *http.Request, sfid string){ return } } - + user, noticeList, ok := ForumSessionCheck(w,r,fid) if !ok { return @@ -562,7 +562,7 @@ func route_topic_create(w http.ResponseWriter, r *http.Request, sfid string){ NoPermissions(w,r,user) return } - + var forumList []Forum group := groups[user.Group] for _, fid := range group.CanSee { @@ -570,7 +570,7 @@ func route_topic_create(w http.ResponseWriter, r *http.Request, sfid string){ forumList = append(forumList, forums[fid]) } } - + ctpage := CreateTopicPage{"Create Topic",user,noticeList,forumList,fid,nil} if template_create_topic_handle != nil { template_create_topic_handle(ctpage,w) @@ -581,21 +581,21 @@ func route_topic_create(w http.ResponseWriter, r *http.Request, sfid string){ } } } - + // POST functions. Authorised users only. func route_create_topic(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } - + fid, err := strconv.Atoi(r.PostFormValue("topic-board")) if err != nil { PreError("The provided ForumID is not a valid number.",w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -604,7 +604,7 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + topic_name := html.EscapeString(r.PostFormValue("topic-name")) content := html.EscapeString(preparse_message(r.PostFormValue("topic-content"))) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) @@ -612,7 +612,7 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { LocalError("Bad IP",w,r,user) return } - + wcount := word_count(content) res, err := create_topic_stmt.Exec(fid,topic_name,content,parse_message(content),ipaddress,wcount,user.ID) if err != nil { @@ -624,14 +624,14 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = add_topics_to_forum_stmt.Exec(1,fid) if err != nil { InternalError(err,w,r) return } forums[fid].TopicCount -= 1 - + _, err = update_forum_cache_stmt.Exec(topic_name,lastId,user.Name,user.ID,fid) if err != nil { InternalError(err,w,r) @@ -642,13 +642,13 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { forums[fid].LastReplyer = user.Name forums[fid].LastReplyerID = user.ID forums[fid].LastTopicTime = "" - + _, err = add_subscription_stmt.Exec(user.ID,lastId,"topic") if err != nil { InternalError(err,w,r) return } - + http.Redirect(w,r,"/topic/" + strconv.FormatInt(lastId,10), http.StatusSeeOther) err = increase_post_user_stats(wcount,user.ID,true,user) if err != nil { @@ -661,14 +661,14 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } tid, err := strconv.Atoi(r.PostFormValue("tid")) if err != nil { PreError("Failed to convert the Topic ID",w,r) return } - + var topic_name string var fid int var createdBy int @@ -680,7 +680,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -689,21 +689,21 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + content := preparse_message(html.EscapeString(r.PostFormValue("reply-content"))) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { LocalError("Bad IP",w,r,user) return } - + wcount := word_count(content) _, err = create_reply_stmt.Exec(tid,content,parse_message(content),ipaddress,wcount, user.ID) if err != nil { InternalError(err,w,r) return } - + _, err = add_replies_to_topic_stmt.Exec(1, tid) if err != nil { InternalError(err,w,r) @@ -714,7 +714,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + res, err := add_activity_stmt.Exec(user.ID,createdBy,"reply","topic",tid) if err != nil { InternalError(err,w,r) @@ -725,13 +725,13 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = notify_watchers_stmt.Exec(lastId) if err != nil { InternalError(err,w,r) return } - + // Reload the topic... err = topics.Load(tid) if err != nil && err != sql.ErrNoRows { @@ -741,7 +741,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + http.Redirect(w,r,"/topic/" + strconv.Itoa(tid), http.StatusSeeOther) err = increase_post_user_stats(wcount, user.ID, false, user) if err != nil { @@ -754,15 +754,15 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } - + tid, err := strconv.Atoi(r.URL.Path[len("/topic/like/submit/"):]) if err != nil { PreError("Topic IDs can only ever be numbers.",w,r) return } - + var words int var fid int var createdBy int @@ -774,7 +774,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -783,7 +783,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + err = db.QueryRow("select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'topics'", user.ID, tid).Scan(&tid) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) @@ -792,7 +792,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { LocalError("You already liked this!",w,r,user) return } - + _, err = users.CascadeGet(createdBy) if err != nil && err == sql.ErrNoRows { LocalError("The target user doesn't exist",w,r,user) @@ -801,7 +801,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + //score := words_to_score(words,true) score := 1 _, err = create_like_stmt.Exec(score,tid,"topics",user.ID) @@ -809,13 +809,13 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = add_likes_to_topic_stmt.Exec(1,tid) if err != nil { InternalError(err,w,r) return } - + res, err := add_activity_stmt.Exec(user.ID,createdBy,"like","topic",tid) if err != nil { InternalError(err,w,r) @@ -826,7 +826,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + /*_, err = notify_watchers_stmt.Exec(lastId) if err != nil { InternalError(err,w,r) @@ -837,7 +837,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + // Reload the topic... err = topics.Load(tid) if err != nil && err != sql.ErrNoRows { @@ -847,7 +847,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) } @@ -855,15 +855,15 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { PreError("Bad Form",w,r) - return + return } - + rid, err := strconv.Atoi(r.URL.Path[len("/reply/like/submit/"):]) if err != nil { PreError("The provided Reply ID is not a valid number.",w,r) return } - + var tid int var words int var createdBy int @@ -875,7 +875,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + var fid int err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) if err == sql.ErrNoRows { @@ -885,7 +885,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + user, ok := SimpleForumSessionCheck(w,r,fid) if !ok { return @@ -894,7 +894,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + err = db.QueryRow("select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'replies'", user.ID, rid).Scan(&rid) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) @@ -903,7 +903,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { LocalError("You already liked this!",w,r,user) return } - + _, err = users.CascadeGet(createdBy) if err != nil && err != sql.ErrNoRows { LocalError("The target user doesn't exist",w,r,user) @@ -912,7 +912,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + //score := words_to_score(words,false) score := 1 _, err = create_like_stmt.Exec(score,rid,"replies",user.ID) @@ -920,13 +920,13 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = add_likes_to_reply_stmt.Exec(1,rid) if err != nil { InternalError(err,w,r) return } - + res, err := add_activity_stmt.Exec(user.ID,createdBy,"like","post",rid) if err != nil { InternalError(err,w,r) @@ -937,13 +937,13 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + _, err = notify_one_stmt.Exec(createdBy,lastId) if err != nil { InternalError(err,w,r) return } - + http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) } @@ -956,24 +956,24 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { NoPermissions(w,r,user) return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } uid, err := strconv.Atoi(r.PostFormValue("uid")) if err != nil { LocalError("Invalid UID",w,r,user) return } - + _, err = create_profile_reply_stmt.Exec(uid,html.EscapeString(preparse_message(r.PostFormValue("reply-content"))),parse_message(html.EscapeString(preparse_message(r.PostFormValue("reply-content")))),user.ID) if err != nil { InternalError(err,w,r) return } - + var user_name string err = db.QueryRow("select name from users where uid = ?", uid).Scan(&user_name) if err == sql.ErrNoRows { @@ -983,7 +983,7 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + http.Redirect(w, r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) } @@ -1000,7 +1000,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string Banned(w,r,user) return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) @@ -1010,15 +1010,15 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string SecurityError(w,r,user) return } - + item_id, err := strconv.Atoi(sitem_id) if err != nil { LocalError("Bad ID",w,r,user) return } - + item_type := r.FormValue("type") - + var fid int = 1 var tid int var title, content, data string @@ -1031,7 +1031,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string InternalError(err,w,r) return } - + err = db.QueryRow("select title, data from topics where tid = ?",tid).Scan(&title,&data) if err == sql.ErrNoRows { LocalError("We were unable to find the topic which the reported post is supposed to be in",w,r,user) @@ -1050,7 +1050,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string InternalError(err,w,r) return } - + err = db.QueryRow("select name from users where uid = ?", tid).Scan(&title) if err == sql.ErrNoRows { LocalError("We were unable to find the profile which the reported post is supposed to be on",w,r,user) @@ -1077,16 +1077,16 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string } // Don't try to guess the type LocalError("Unknown type",w,r,user) - return + return } - + var count int rows, err := db.Query("select count(*) as count from topics where data = ? and data != '' and parentID = 1", item_type + "_" + strconv.Itoa(item_id)) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) return } - + for rows.Next() { err = rows.Scan(&count) if err != nil { @@ -1098,20 +1098,20 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string LocalError("Someone has already reported this!",w,r,user) return } - + title = "Report: " + title res, err := create_report_stmt.Exec(title,content,parse_message(content),user.ID,item_type + "_" + strconv.Itoa(item_id)) if err != nil { InternalError(err,w,r) return } - + lastId, err := res.LastInsertId() if err != nil { InternalError(err,w,r) return } - + _, err = add_topics_to_forum_stmt.Exec(1, fid) if err != nil { InternalError(err,w,r) @@ -1122,7 +1122,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string InternalError(err,w,r) return } - + http.Redirect(w,r,"/topic/" + strconv.FormatInt(lastId, 10), http.StatusSeeOther) } @@ -1148,19 +1148,19 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque LocalError("You need to login to edit your account.",w,r,user) return } - + err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } - + var real_password string var salt string current_password := r.PostFormValue("account-current-password") new_password := r.PostFormValue("account-new-password") confirm_password := r.PostFormValue("account-confirm-password") - + err = get_password_stmt.QueryRow(user.ID).Scan(&real_password, &salt) if err == sql.ErrNoRows { LocalError("Your account no longer exists.",w,r,user) @@ -1169,7 +1169,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque InternalError(err,w,r) return } - + current_password = current_password + salt err = bcrypt.CompareHashAndPassword([]byte(real_password), []byte(current_password)) if err == bcrypt.ErrMismatchedHashAndPassword { @@ -1184,14 +1184,14 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque return } SetPassword(user.ID, new_password) - + // Log the user out as a safety precaution _, err = logout_stmt.Exec(user.ID) if err != nil { InternalError(err,w,r) return } - + noticeList = append(noticeList,"Your password was successfully updated") pi := Page{"Edit Password",user,noticeList,tList,nil} templates.ExecuteTemplate(w,"account-own-edit.html", pi) @@ -1216,7 +1216,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request return } r.Body = http.MaxBytesReader(w, r.Body, int64(max_request_size)) - + user, noticeList, ok := SessionCheck(w,r) if !ok { return @@ -1225,13 +1225,13 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request LocalError("You need to login to edit your account.",w,r,user) return } - + err := r.ParseMultipartForm(int64(max_request_size)) if err != nil { LocalError("Upload failed",w,r,user) return } - + var filename string var ext string for _, fheaders := range r.MultipartForm.File { @@ -1242,7 +1242,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request return } defer infile.Close() - + // We don't want multiple files if filename != "" { if filename != hdr.Filename { @@ -1253,7 +1253,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request } else { filename = hdr.Filename } - + if ext == "" { extarr := strings.Split(hdr.Filename,".") if len(extarr) < 2 { @@ -1261,7 +1261,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request return } ext = extarr[len(extarr) - 1] - + reg, err := regexp.Compile("[^A-Za-z0-9]+") if err != nil { LocalError("Bad file extension", w, r, user) @@ -1270,14 +1270,14 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request ext = reg.ReplaceAllString(ext,"") ext = strings.ToLower(ext) } - + outfile, err := os.Create("./uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext); if err != nil { LocalError("Upload failed [File Creation Failed]",w,r,user) return } defer outfile.Close() - + _, err = io.Copy(outfile, infile); if err != nil { LocalError("Upload failed [Copy Failed]",w,r,user) @@ -1285,7 +1285,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request } } } - + _, err = set_avatar_stmt.Exec("." + ext, strconv.Itoa(user.ID)) if err != nil { InternalError(err,w,r) @@ -1298,7 +1298,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request return } noticeList = append(noticeList, "Your avatar was successfully updated") - + pi := Page{"Edit Avatar",user,noticeList,tList,nil} templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi) } @@ -1328,23 +1328,23 @@ func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Reque err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } - + new_username := html.EscapeString(r.PostFormValue("account-new-username")) _, err = set_username_stmt.Exec(new_username, strconv.Itoa(user.ID)) if err != nil { LocalError("Unable to change the username. Does someone else already have this name?",w,r,user) return } - + user.Name = new_username err = users.Load(user.ID) if err != nil { LocalError("Your account doesn't exist!",w,r,user) return } - + noticeList = append(noticeList,"Your username was successfully updated") pi := Page{"Edit Username",user,noticeList,tList,nil} templates.ExecuteTemplate(w,"account-own-edit-username.html", pi) @@ -1359,7 +1359,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { LocalError("You need to login to edit your account.",w,r,user) return } - + email := Email{UserID: user.ID} var emailList []interface{} rows, err := db.Query("select email, validated from emails where uid = ?", user.ID) @@ -1367,13 +1367,13 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { log.Fatal(err) } defer rows.Close() - + for rows.Next() { err := rows.Scan(&email.Email, &email.Validated) if err != nil { log.Fatal(err) } - + if email.Email == user.Email { email.Primary = true } @@ -1383,7 +1383,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { if err != nil { log.Fatal(err) } - + // Was this site migrated from another forum software? Most of them don't have multiple emails for a single user. This also applies when the admin switches enable_emails on after having it off for a while if len(emailList) == 0 { email.Email = user.Email @@ -1391,7 +1391,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { email.Primary = true emailList = append(emailList, email) } - + if !enable_emails { noticeList = append(noticeList, "The email system has been turned off. All features involving sending emails have been disabled.") } @@ -1409,7 +1409,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re return } token := r.URL.Path[len("/user/edit/token/"):] - + email := Email{UserID: user.ID} targetEmail := Email{UserID: user.ID} var emailList []interface{} @@ -1419,14 +1419,14 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re return } defer rows.Close() - + for rows.Next() { err := rows.Scan(&email.Email, &email.Validated, &email.Token) if err != nil { InternalError(err,w,r) return } - + if email.Email == user.Email { email.Primary = true } @@ -1440,7 +1440,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re InternalError(err,w,r) return } - + if len(emailList) == 0 { LocalError("A verification email was never sent for you!",w,r,user) return @@ -1449,13 +1449,13 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re LocalError("That's not a valid token!",w,r,user) return } - + _, err = verify_email_stmt.Exec(user.Email) if err != nil { InternalError(err,w,r) return } - + // If Email Activation is on, then activate the account while we're here if settings["activation_type"] == 2 { _, err = activate_user_stmt.Exec(user.ID) @@ -1464,7 +1464,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re return } } - + if !enable_emails { noticeList = append(noticeList,"The email system has been turned off. All features involving sending emails have been disabled.") } @@ -1482,13 +1482,13 @@ func route_logout(w http.ResponseWriter, r *http.Request) { LocalError("You can't logout without logging in first.",w,r,user) return } - + _, err := logout_stmt.Exec(user.ID) if err != nil { InternalError(err,w,r) return } - + err = users.Load(user.ID) if err != nil { LocalError("Your account doesn't exist!",w,r,user) @@ -1496,7 +1496,7 @@ func route_logout(w http.ResponseWriter, r *http.Request) { } http.Redirect(w,r, "/", http.StatusSeeOther) } - + func route_login(w http.ResponseWriter, r *http.Request) { user, noticeList, ok := SessionCheck(w,r) if !ok { @@ -1522,16 +1522,16 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } - + var uid int var real_password string var salt string var session string username := html.EscapeString(r.PostFormValue("username")) password := r.PostFormValue("password") - + err = login_stmt.QueryRow(username).Scan(&uid, &username, &real_password, &salt) if err == sql.ErrNoRows { LocalError("That username doesn't exist.",w,r,user) @@ -1540,14 +1540,14 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + // Emergency password reset mechanism.. if salt == "" { if password != real_password { LocalError("That's not the correct password.",w,r,user) return } - + // Re-encrypt the password SetPassword(uid, password) } else { // Normal login.. @@ -1556,7 +1556,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + err := bcrypt.CompareHashAndPassword([]byte(real_password), []byte(password)) if err == bcrypt.ErrMismatchedHashAndPassword { LocalError("That's not the correct password.",w,r,user) @@ -1566,19 +1566,19 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { return } } - + session, err = GenerateSafeString(sessionLength) if err != nil { InternalError(err,w,r) return } - + _, err = update_session_stmt.Exec(session, uid) if err != nil { InternalError(err,w,r) return } - + cookie := http.Cookie{Name: "uid",Value: strconv.Itoa(uid),Path: "/",MaxAge: year} http.SetCookie(w,&cookie) cookie = http.Cookie{Name: "session",Value: session,Path: "/",MaxAge: year} @@ -1606,39 +1606,39 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { LocalError("Bad Form",w,r,user) - return + return } - + username := html.EscapeString(r.PostFormValue("username")) if username == "" { LocalError("You didn't put in a username.",w,r,user) - return + return } email := html.EscapeString(r.PostFormValue("email")) if email == "" { LocalError("You didn't put in an email.",w,r,user) - return + return } - + password := r.PostFormValue("password") if password == "" { LocalError("You didn't put in a password.",w,r,user) - return + return } if password == "test" || password == "123456" || password == "123" || password == "password" { LocalError("Your password is too weak.",w,r,user) - return + return } - + confirm_password := r.PostFormValue("confirm_password") log.Print("Registration Attempt! Username: " + username) - + // Do the two inputted passwords match..? if password != confirm_password { LocalError("The two passwords don't match.",w,r,user) return } - + // Is this username already taken..? err = username_exists_stmt.QueryRow(username).Scan(&username) if err != nil && err != sql.ErrNoRows { @@ -1648,7 +1648,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { LocalError("This username isn't available. Try another.",w,r,user) return } - + salt, err := GenerateSafeString(saltLength) if err != nil { InternalError(err,w,r) @@ -1659,14 +1659,14 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + password = password + salt hashed_password, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { InternalError(err,w,r) return } - + var active int var group int switch settings["activation_type"] { @@ -1676,7 +1676,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { default: // Anything else. E.g. Admin Activation or Email Activation. group = activation_group } - + res, err := register_stmt.Exec(username,email,string(hashed_password),salt,group,session,active) if err != nil { InternalError(err,w,r) @@ -1687,7 +1687,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + // Check if this user actually owns this email, if email activation is on, automatically flip their account to active when the email is validated. Validation is also useful for determining whether this user should receive any alerts, etc. via email if enable_emails { token, err := GenerateSafeString(80) @@ -1700,13 +1700,13 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r) return } - + if !SendValidationEmail(username, email, token) { LocalError("We were unable to send the email for you to confirm that this email address belongs to you. You may not have access to some functionality until you do so. Please ask an administrator for assistance.",w,r,user) return } } - + cookie := http.Cookie{Name: "uid",Value: strconv.FormatInt(lastId, 10),Path: "/",MaxAge: year} http.SetCookie(w,&cookie) cookie = http.Cookie{Name: "session",Value: session,Path: "/",MaxAge: year} @@ -1728,18 +1728,18 @@ func route_api(w http.ResponseWriter, r *http.Request) { PreErrorJSQ("Bad Form",w,r,is_js) return } - + user, ok := SimpleSessionCheck(w,r) if !ok { return } - + action := r.FormValue("action") if action != "get" && action != "set" { PreErrorJSQ("Invalid Action",w,r,is_js) return } - + module := r.FormValue("module") switch(module) { case "alerts": // A feed of events tailored for a specific user @@ -1747,13 +1747,13 @@ func route_api(w http.ResponseWriter, r *http.Request) { PreError("You can only fetch alerts in the JSON format!",w,r) return } - + w.Header().Set("Content-Type","application/json") if !user.Loggedin { w.Write(phrase_login_alerts) return } - + var msglist string var asid int var actor_id int @@ -1763,26 +1763,26 @@ func route_api(w http.ResponseWriter, r *http.Request) { var elementID int //--- var targetUser *User - + rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID) if err != nil { InternalErrorJS(err,w,r) return } - + for rows.Next() { err = rows.Scan(&asid,&actor_id,&targetUser_id,&event,&elementType,&elementID) if err != nil { InternalErrorJS(err,w,r) return } - + actor, err := users.CascadeGet(actor_id) if err != nil { LocalErrorJS("Unable to find the actor",w,r) return } - + /*if elementType != "forum" { targetUser, err = users.CascadeGet(targetUser_id) if err != nil { @@ -1790,12 +1790,12 @@ func route_api(w http.ResponseWriter, r *http.Request) { return } }*/ - + if event == "friend_invite" { msglist += `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"\/user\/`+strconv.Itoa(actor.ID)+`","avatar":"`+strings.Replace(actor.Avatar,"/","\\/",-1)+`"},` continue } - + /* "You received a friend invite from {user}" "{x}{mentioned you on}{user}{'s profile}" @@ -1809,7 +1809,7 @@ func route_api(w http.ResponseWriter, r *http.Request) { "{x}{replied to}{your topic}{topic}" "{x}{created a new topic}{topic}" */ - + var act string var post_act string var url string @@ -1840,7 +1840,7 @@ func route_api(w http.ResponseWriter, r *http.Request) { } url = build_topic_url(elementID) area = topic.Title - + if targetUser_id == user.ID { post_act = " your topic" } @@ -1867,7 +1867,7 @@ func route_api(w http.ResponseWriter, r *http.Request) { default: LocalErrorJS("Invalid elementType",w,r) } - + switch(event) { case "like": if elementType == "user" { @@ -1888,17 +1888,17 @@ func route_api(w http.ResponseWriter, r *http.Request) { } case "reply": act = "replied to" } - + msglist += `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `"},` } - + err = rows.Err() if err != nil { InternalErrorJS(err,w,r) return } rows.Close() - + if len(msglist) != 0 { msglist = msglist[0:len(msglist)-1] } diff --git a/template_list.go b/template_list.go index 5311b224..38e7be0e 100644 --- a/template_list.go +++ b/template_list.go @@ -60,10 +60,13 @@ var topic_2 []byte = []byte(`"><`) var topic_3 []byte = []byte(` -
+ >
`) +var topic_7 []byte = []byte(`">> +`) var topic_8 []byte = []byte(` +
@@ -101,34 +104,43 @@ var topic_24 []byte = []byte(`"> var topic_25 []byte = []byte(`

+ + + `) -var topic_28 []byte = []byte(`  +var topic_28 []byte = []byte(`   + `) var topic_29 []byte = []byte(` `) +var topic_32 []byte = []byte(`">`) var topic_33 []byte = []byte(` `) +var topic_34 []byte = []byte(`' class="mod_button open_edit" style="font-weight:normal;" title="Edit Topic">`) var topic_35 []byte = []byte(` `) +var topic_36 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Delete Topic">`) var topic_37 []byte = []byte(``) +var topic_38 []byte = []byte(`' style="font-weight:normal;" title="Unpin Topic">`) var topic_39 []byte = []byte(` `) +var topic_40 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Pin Topic">`) var topic_41 []byte = []byte(` -   +var topic_43 []byte = []byte(`&type=topic" class="mod_button report_item" style="font-weight:normal;" title="Flag Topic"> + `) -var topic_44 []byte = []byte(``) -var topic_45 []byte = []byte(`😀`) +var topic_44 []byte = []byte(``) var topic_46 []byte = []byte(``) var topic_47 []byte = []byte(``) var topic_48 []byte = []byte(``) -var topic_49 []byte = []byte(`👑`) +var topic_49 []byte = []byte(``) var topic_50 []byte = []byte(` + +
`) @@ -149,30 +161,38 @@ var topic_58 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;backgrou var topic_59 []byte = []byte(`">

`) var topic_60 []byte = []byte(`

+ + + `) -var topic_62 []byte = []byte(`  +var topic_62 []byte = []byte(`   + `) var topic_63 []byte = []byte(` `) +var topic_66 []byte = []byte(`">`) var topic_67 []byte = []byte(` `) +var topic_68 []byte = []byte(`" class="mod_button" title="Edit Reply">`) var topic_69 []byte = []byte(` `) +var topic_70 []byte = []byte(`" class="mod_button" title="Delete Reply">`) var topic_71 []byte = []byte(` -   +var topic_73 []byte = []byte(`&type=reply" class="mod_button report_item" title="Flag Reply"> + `) -var topic_74 []byte = []byte(``) -var topic_75 []byte = []byte(`😀`) +var topic_74 []byte = []byte(``) var topic_76 []byte = []byte(``) var topic_77 []byte = []byte(``) var topic_78 []byte = []byte(``) -var topic_79 []byte = []byte(`👑`) +var topic_79 []byte = []byte(``) var topic_80 []byte = []byte(` + +
`) var topic_81 []byte = []byte(` @@ -192,10 +212,10 @@ var topic_83 []byte = []byte(`' type="hidden" /> `) -var footer_0 []byte = []byte(` -
+var footer_0 []byte = []byte(`
-`) + +`) var topic_alt_0 []byte = []byte(`
<
`) @@ -353,10 +373,13 @@ var topic_alt_83 []byte = []byte(`' type="hidden" /> `) var profile_0 []byte = []byte(` -
-
-
+ +
+
+ +
+
`) var profile_2 []byte = []byte(``) var profile_3 []byte = []byte(``) @@ -364,7 +387,9 @@ var profile_4 []byte = []byte(``) var profile_5 []byte = []byte(`
+
Ban`) var profile_12 []byte = []byte(` Report +var profile_14 []byte = []byte(`&type=user" class="profile_menu_item report_item">Report
-
+ + -
`) +
`) var profile_15 []byte = []byte(`
`) -var profile_21 []byte = []byte(` -

+var profile_21 []byte = []byte(`

`) -var profile_23 []byte = []byte(`  +var profile_22 []byte = []byte(`" class="real_username username">`) +var profile_23 []byte = []byte(`   + `) var profile_24 []byte = []byte(`  +var profile_25 []byte = []byte(`" class="mod_button" title="Edit Item"> +  `) +var profile_26 []byte = []byte(`" class="mod_button" title="Delete Item">`) var profile_27 []byte = []byte(` - +var profile_29 []byte = []byte(`&type=user-reply"> + `) var profile_30 []byte = []byte(``) var profile_31 []byte = []byte(``) @@ -411,7 +440,8 @@ var profile_32 []byte = []byte(`
`) var profile_33 []byte = []byte(`
-
+ +
`) var profile_34 []byte = []byte(`
@@ -427,6 +457,7 @@ var profile_35 []byte = []byte(`' type="hidden" /> `) var profile_36 []byte = []byte(`
+ `) var forums_0 []byte = []byte(`
@@ -436,10 +467,10 @@ var forums_0 []byte = []byte(` `) var forums_1 []byte = []byte(` @@ -488,13 +519,14 @@ var forum_5 []byte = []byte(`" /> var forum_6 []byte = []byte(`?page=`) var forum_7 []byte = []byte(`">>
`) var forum_8 []byte = []byte(` +
`) var forum_9 []byte = []byte(` `) -var forum_10 []byte = []byte(`🔒︎`) +var forum_10 []byte = []byte(`🔒︎`) var forum_11 []byte = []byte(`New Topic`) +var forum_12 []byte = []byte(`" class='username head_tag_upshift'>New Topic`) var forum_13 []byte = []byte(`
diff --git a/templates/account-own-edit-avatar.html b/templates/account-own-edit-avatar.html index b7c8539f..f98b28cf 100644 --- a/templates/account-own-edit-avatar.html +++ b/templates/account-own-edit-avatar.html @@ -12,7 +12,7 @@
@@ -21,4 +21,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/account-own-edit-username.html b/templates/account-own-edit-username.html index a98d3b8b..9e2045db 100644 --- a/templates/account-own-edit-username.html +++ b/templates/account-own-edit-username.html @@ -7,11 +7,11 @@
- -
{{.CurrentUser.Name}}
+ +
{{.CurrentUser.Name}}
@@ -20,4 +20,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/account-own-edit.html b/templates/account-own-edit.html index 7f84170b..49fa9c03 100644 --- a/templates/account-own-edit.html +++ b/templates/account-own-edit.html @@ -7,15 +7,15 @@ -{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/create-topic.html b/templates/create-topic.html index ac408ed5..854b2379 100644 --- a/templates/create-topic.html +++ b/templates/create-topic.html @@ -5,13 +5,13 @@
- +
@@ -22,4 +22,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/footer.html b/templates/footer.html index a5b3e7f7..46c8b96a 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -1,4 +1,3 @@ -
- \ No newline at end of file + diff --git a/templates/forum.html b/templates/forum.html index b8a21b9a..f44e5e75 100644 --- a/templates/forum.html +++ b/templates/forum.html @@ -1,10 +1,12 @@ {{template "header.html" . }} + {{if gt .Page 1}}{{end}} {{if ne .LastPage .Page}} {{end}} +
{{.Title}} - {{if ne .CurrentUser.ID 0}}{{if not .CurrentUser.Perms.CreateTopic}}🔒︎{{else}}New Topic{{end}}{{end}}
+ {{if ne .CurrentUser.ID 0}}{{if not .CurrentUser.Perms.CreateTopic}}🔒︎{{else}}New Topic{{end}}{{end}}
{{range .ItemList}}
diff --git a/templates/forums.html b/templates/forums.html index 261cfee7..7bf3827d 100644 --- a/templates/forums.html +++ b/templates/forums.html @@ -4,8 +4,8 @@
{{range .ItemList}} {{else}}
You don't have access to any forums.
{{end}}
diff --git a/templates/login.html b/templates/login.html index a413013c..9fc6f867 100644 --- a/templates/login.html +++ b/templates/login.html @@ -5,11 +5,11 @@
@@ -18,4 +18,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-adminlogs.html b/templates/panel-adminlogs.html index 944d86c3..37181535 100644 --- a/templates/panel-adminlogs.html +++ b/templates/panel-adminlogs.html @@ -14,7 +14,7 @@ -
+
{{range .Logs}}
{{.Action}}
@@ -26,4 +26,4 @@ {{end}}
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-dashboard.html b/templates/panel-dashboard.html index 557598d8..6d581b5c 100644 --- a/templates/panel-dashboard.html +++ b/templates/panel-dashboard.html @@ -1,11 +1,11 @@ {{template "header.html" . }} {{template "panel-menu.html" . }}
-
+
{{range .GridItems}}
{{.Body}}
{{end}}
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-forums.html b/templates/panel-forums.html index e22e56e8..9b7a564c 100644 --- a/templates/panel-forums.html +++ b/templates/panel-forums.html @@ -1,48 +1,50 @@ {{template "header.html" . }} {{template "panel-menu.html" . }} +
-
+
{{range .ItemList}} -
- {{.Name}} - - 🕵️ - - {{if .PresetEmoji}}{{.PresetEmoji}} - {{else if .PresetLang}}{{.PresetLang}}{{else}}{{end}} - - {{if gt .ID 0}}Edit - {{end}} - {{if gt .ID 1}}Delete{{end}} +
+ {{.Name}} + + + + + + {{if gt .ID 0}}Edit + {{end}} + {{if gt .ID 1}}Delete{{end}} +
{{end}}
+
- +
- +
{{if .CurrentUser.Perms.EditGroup}}
- +
@@ -43,4 +43,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-groups.html b/templates/panel-groups.html index f22bfffb..5e0fae3d 100644 --- a/templates/panel-groups.html +++ b/templates/panel-groups.html @@ -1,18 +1,19 @@ {{template "header.html" . }} {{template "panel-menu.html" . }} +
-
+
{{range .ItemList}} -
- {{.Name}} - - {{if .RankEmoji}}{{.RankEmoji}} - {{else}}{{.Rank}}{{end}} - - {{if .CanEdit}}Edit{{end}} +
+ {{.Name}} + + {{if .RankClass}} + {{else}}{{.Rank}}{{end}} + + {{if .CanEdit}}Edit{{end}}
{{end}} @@ -23,11 +24,11 @@
- +
- +
@@ -47,4 +48,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-modlogs.html b/templates/panel-modlogs.html index fa7ba114..78869d7e 100644 --- a/templates/panel-modlogs.html +++ b/templates/panel-modlogs.html @@ -14,7 +14,7 @@ -
+
{{range .Logs}}
{{.Action}}
@@ -26,4 +26,4 @@ {{end}}
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-plugins.html b/templates/panel-plugins.html index 7cfa3a72..146d345f 100644 --- a/templates/panel-plugins.html +++ b/templates/panel-plugins.html @@ -4,18 +4,18 @@ -
+
{{range .ItemList}} -
- {{.Name}}
+
+ {{.Name}}
Author: {{.Author}} - {{if .Settings}}Settings{{end}} - {{if .Active}}Deactivate - {{else}}Activate{{end}} + {{if .Settings}}Settings{{end}} + {{if .Active}}Deactivate + {{else}}Activate{{end}}
{{end}}
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-setting.html b/templates/panel-setting.html index e0581cc3..4b8e9c07 100644 --- a/templates/panel-setting.html +++ b/templates/panel-setting.html @@ -4,15 +4,15 @@ -
+
- -
{{.Something.Name}}
+ +
{{.Something.Name}}
{{if eq .Something.Type "list"}}
- +
{{else}}{{end}}
@@ -34,4 +34,4 @@
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-settings.html b/templates/panel-settings.html index 19d9373a..7b88e764 100644 --- a/templates/panel-settings.html +++ b/templates/panel-settings.html @@ -4,13 +4,13 @@ -
+
{{range $key, $value := .Something}} -
- {{$key}} + {{end}}
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-themes.html b/templates/panel-themes.html index 1ec079a7..3054dd85 100644 --- a/templates/panel-themes.html +++ b/templates/panel-themes.html @@ -1,21 +1,28 @@ {{template "header.html" . }} {{template "panel-menu.html" . }} - + +
-
+
{{range .PrimaryThemes}} -
+
- {{.FriendlyName}}
- Author: {{.Creator}} + {{.FriendlyName}}
+ Author: {{.Creator}}
- - {{if .MobileFriendly}}📱{{end}} - {{if .Tag}}{{.Tag}}{{end}} - {{if .Active}}Default{{else}}Make Default{{end}} + + {{if .MobileFriendly}}📱{{end}} + {{if .Tag}}{{.Tag}}{{end}} + {{if .Active}}Default{{else}}Make Default{{end}}
{{end}} @@ -23,20 +30,20 @@ -
+
{{range .VariantThemes}} -
+
- {{.FriendlyName}}
- Author: {{.Creator}} + {{.FriendlyName}}
+ Author: {{.Creator}}
- - {{if .MobileFriendly}}📱{{end}} - {{if .Tag}}{{.Tag}}{{end}} - {{if .Active}}Default{{else}}Make Default{{end}} + + {{if .MobileFriendly}}📱{{end}} + {{if .Tag}}{{.Tag}}{{end}} + {{if .Active}}Default{{else}}Make Default{{end}}
{{end}}
-{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/panel-user-edit.html b/templates/panel-user-edit.html index 88c27b5c..a652c006 100644 --- a/templates/panel-user-edit.html +++ b/templates/panel-user-edit.html @@ -4,23 +4,23 @@ -
+
- +
{{if .CurrentUser.Perms.EditUserPassword}}{{end}} {{if .CurrentUser.Perms.EditUserEmail}}
- +
{{end}} {{if .CurrentUser.Perms.EditUserGroup}}
- +
@@ -39,4 +49,5 @@ {{end}}
-{{template "footer.html" . }} \ No newline at end of file + +{{template "footer.html" . }} diff --git a/templates/register.html b/templates/register.html index 8a67aa33..c03f992f 100644 --- a/templates/register.html +++ b/templates/register.html @@ -5,19 +5,19 @@ -{{template "footer.html" . }} \ No newline at end of file +{{template "footer.html" . }} diff --git a/templates/topic.html b/templates/topic.html index ef432aac..8d47e47e 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -1,7 +1,12 @@ {{template "header.html" . }} + {{if gt .Page 1}}{{end}} + {{if ne .LastPage .Page}} -{{end}} +
+ > +
{{end}} +
@@ -22,14 +27,27 @@

{{.Topic.Content}}

- {{.Topic.CreatedByName}}  - {{if .CurrentUser.Perms.LikeItem}} {{end}} - {{if .CurrentUser.Perms.EditTopic}} {{end}} - {{if .CurrentUser.Perms.DeleteTopic}} {{end}} - {{if .CurrentUser.Perms.PinTopic}}{{if .Topic.Sticky}}{{else}} {{end}}{{end}} -   - {{if .Topic.LikeCount}}{{.Topic.LikeCount}}😀{{end}} - {{if .Topic.Tag}}{{.Topic.Tag}}{{else}}{{.Topic.Level}}👑{{end}} + + + + {{.Topic.CreatedByName}}   + + {{if .CurrentUser.Perms.LikeItem}} + {{end}} + + {{if .CurrentUser.Perms.EditTopic}}{{end}} + + {{if .CurrentUser.Perms.DeleteTopic}}{{end}} + + {{if .CurrentUser.Perms.PinTopic}}{{if .Topic.Sticky}}{{else}}{{end}}{{end}} + + + + {{if .Topic.LikeCount}}{{end}} + + {{if .Topic.Tag}}{{.Topic.Tag}}{{else}}{{.Topic.Level}}{{end}} + +
{{range .ItemList}}{{if .ActionType}} @@ -40,13 +58,24 @@ {{else}}

{{.ContentHtml}}

- {{.CreatedByName}}  - {{if $.CurrentUser.Perms.LikeItem}} {{end}} - {{if $.CurrentUser.Perms.EditReply}} {{end}} - {{if $.CurrentUser.Perms.DeleteReply}} {{end}} -   - {{if .LikeCount}}{{.LikeCount}}😀{{end}} - {{if .Tag}}{{.Tag}}{{else}}{{.Level}}👑{{end}} + + + + {{.CreatedByName}}   + + {{if $.CurrentUser.Perms.LikeItem}}{{end}} + + {{if $.CurrentUser.Perms.EditReply}}{{end}} + + {{if $.CurrentUser.Perms.DeleteReply}}{{end}} + + + + {{if .LikeCount}}{{end}} + + {{if .Tag}}{{.Tag}}{{else}}{{.Level}}{{end}} + +
{{end}}{{end}}
diff --git a/themes.go b/themes.go index 669fd1d1..e0651a74 100644 --- a/themes.go +++ b/themes.go @@ -1,16 +1,18 @@ -/* Copyright Azareal 2016 - 2017 */ +/* Copyright Azareal 2016 - 2018 */ package main -//import "fmt" -import "log" -import "io" -import "os" -import "strings" -import "mime" -import "io/ioutil" -import "path/filepath" -import "encoding/json" -import "net/http" +import ( + //"fmt" + "log" + "io" + "os" + "strings" + "mime" + "io/ioutil" + "path/filepath" + "encoding/json" + "net/http" +) var defaultTheme string var themes map[string]Theme = make(map[string]Theme) @@ -29,9 +31,10 @@ type Theme struct HideFromThemes bool ForkOf string Tag string + URL string Settings map[string]ThemeSetting Templates []TemplateMapping - + // This variable should only be set and unset by the system, not the theme meta file Active bool } @@ -54,28 +57,28 @@ func init_themes() { if err != nil { log.Fatal(err) } - + for _, themeFile := range themeFiles { if !themeFile.IsDir() { continue } - + themeName := themeFile.Name() log.Print("Adding theme '" + themeName + "'") themeFile, err := ioutil.ReadFile("./themes/" + themeName + "/theme.json") if err != nil { log.Fatal(err) } - + var theme Theme err = json.Unmarshal(themeFile, &theme) if err != nil { log.Fatal(err) } - - + + theme.Active = false // Set this to false, just in case someone explicitly overrode this value in the JSON file - + if theme.FullImage != "" { if debug { log.Print("Adding theme image") @@ -85,7 +88,7 @@ func init_themes() { log.Fatal(err) } } - + themes[theme.Name] = theme } } @@ -99,22 +102,22 @@ func add_theme_static_files(themeName string) { return nil } path = strings.Replace(path,"\\","/",-1) - + if debug { log.Print("Attempting to add static file '" + path + "' for default theme '" + themeName + "'") } - + data, err := ioutil.ReadFile(path) if err != nil { return err } - + path = strings.TrimPrefix(path,"themes/" + themeName + "/public") if debug { log.Print("Added the '" + path + "' static file for default theme " + themeName + ".") } gzip_data := compress_bytes_gzip(data) - + static_files["/static" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(filepath.Ext("/themes/" + themeName + "/public" + path)),f,f.ModTime().UTC().Format(http.TimeFormat)} return nil }) @@ -132,9 +135,9 @@ func map_theme_templates(theme Theme) { if themeTmpl.Source == "" { log.Fatal("Invalid source template name") } - + // `go generate` is one possibility for letting plugins inject custom page structs, but it would simply add another step of compilation. It might be simpler than the current build process from the perspective of the administrator? - + dest_tmpl_ptr, ok := tmpl_ptr_map[themeTmpl.Name] if !ok { log.Fatal("The destination template doesn't exist!") @@ -143,7 +146,7 @@ func map_theme_templates(theme Theme) { if !ok { log.Fatal("The source template doesn't exist!") } - + switch d_tmpl_ptr := dest_tmpl_ptr.(type) { case *func(TopicPage,io.Writer): switch s_tmpl_ptr := source_tmpl_ptr.(type) { @@ -208,24 +211,24 @@ func map_theme_templates(theme Theme) { func reset_template_overrides() { log.Print("Resetting the template overrides") - + for name, _ := range overriden_templates { log.Print("Resetting '" + name + "' template override") - + origin_pointer, ok := tmpl_ptr_map["o_" + name] if !ok { //log.Fatal("The origin template doesn't exist!") log.Print("The origin template doesn't exist!") return } - + dest_tmpl_ptr, ok := tmpl_ptr_map[name] if !ok { //log.Fatal("The destination template doesn't exist!") log.Print("The destination template doesn't exist!") return } - + // Not really a pointer, more of a function handle, an artifact from one of the earlier versions of themes.go switch o_ptr := origin_pointer.(type) { case func(TopicPage,io.Writer): diff --git a/themes/cosmo-classic/theme.json b/themes/cosmo-classic/theme.json index 6401d3bf..5b1e7e7a 100644 --- a/themes/cosmo-classic/theme.json +++ b/themes/cosmo-classic/theme.json @@ -6,10 +6,11 @@ "Disabled": true, "HideFromThemes": true, "Tag": "🏗️", + "URL": "github.com/Azareal/Gosora", "Templates": [ { "Name": "topic", "Source": "topic_alt" } ] -} \ No newline at end of file +} diff --git a/themes/cosmo-conflux/public/main.css b/themes/cosmo-conflux/public/main.css index 6c6ca908..cd3e5b3f 100644 --- a/themes/cosmo-conflux/public/main.css +++ b/themes/cosmo-conflux/public/main.css @@ -7,22 +7,19 @@ -webkit-box-sizing: border-box; } -h1 -{ +h1 { text-shadow: 0 1px 0 black; color: darkgray; height: 60px; } -a -{ +a { text-decoration: none; color: black; } a img { border: 0; /* IE fix..*/ } -body -{ +body { background: url('/static/atombb-small.png') no-repeat left, url('/static/stars-mk1.png'); color: black; background-color: #141414; @@ -31,15 +28,13 @@ body font-family: Arial; } -ul -{ +ul { background: darkgray; padding-top: 0px; padding-bottom: 0px; list-style-type: none; } -li -{ +li { display: block; float: left; text-align: center; @@ -48,7 +43,7 @@ li margin-right: 2px; padding-left: 1px; padding-right: 1px; - + border: 1px solid #7a7a7a; border-top: none; border-bottom: none; @@ -58,27 +53,23 @@ li } li:first-child { border-left: 1px solid #7a7a7a; } -li a -{ +li a { color: white; text-decoration: none; } -li:hover a, li a:hover, li a:link, li a:visited -{ +li:hover a, li a:hover, li a:link, li a:visited { color: white; text-decoration: none; } -li:hover - { +li:hover { background: rgba(10,10,10,0.5); font-weight: normal; color: white; } -.menu_right -{ +.menu_right { float: right; color: white; font-size: 25px; @@ -144,7 +135,6 @@ li:hover text-overflow: ellipsis; } .alertItem.withAvatar { - /*background-image: url('/uploads/avatar_1.jpg');*/ background-size: 36px; background-repeat: no-repeat; text-align: center; @@ -166,8 +156,7 @@ li:hover font-size: 9px; } -#footer -{ +#footer { clear: left; margin: 0px auto; width: 300px; @@ -176,14 +165,12 @@ li:hover hr { color: silver; border: 1px solid silver; } -.rowhead -{ +.rowhead { border-top: none; font-weight: bold; color: white; } -.rowhead:hover -{ +.rowhead:hover { color: rgba(200,200,200,1); transition: color 1s; -moz-transition: color 1s; @@ -240,44 +227,37 @@ hr { color: silver; border: 1px solid silver; } .rowhead .topic_status_e { display: none !important; } .topic_button { float: right; position: relative; top: -22px; margin-right: 2px; border-style: solid !important; } -.colblock_left -{ +.colblock_left { padding: 0px; padding-top: 0px; width: 30%; float: left; margin-right: 8px; } -.colblock_right -{ +.colblock_right { padding: 0px; padding-top: 0px; width: 65%; overflow: hidden; word-wrap: break-word; } -.colblock_left:empty { display: none; } -.colblock_right:empty { display: none; } -.colblock_left:first-of-type { margin-top: 8px; } -.colblock_right:first-of-type { margin-top: 8px; } +.colblock_left:empty, .colblock_right:empty { display: none; } +.colblock_left:first-of-type, .colblock_right:first-of-type { margin-top: 8px; } /* The new method of doing columns layouts, colblock is now deprecated :( */ -.colstack_left -{ +.colstack_left { float: left; width: 30%; margin-right: 8px; margin-top: 12px; } -.colstack_right -{ +.colstack_right { float: left; width: 65%; width: calc(70% - 15px); margin-top: 12px; } -.colstack_item -{ +.colstack_item { padding: 0px; padding-top: 0px; margin-bottom: 16px; @@ -311,92 +291,61 @@ hr { color: silver; border: 1px solid silver; } padding-bottom: 12px; font-size: 16px; } -.grid_istat { - /*margin-bottom: 10px;*/ - margin-bottom: 5px; -} +.grid_istat { margin-bottom: 5px; } .stat_green { background-color: lightgreen; border-color: green; } .stat_orange { background-color: #ffe4b3; border-color: orange; } .stat_red { background-color: #ffb2b2; border-color: red; } .stat_disabled { background-color: lightgray; border-color: gray; } -.colitem -{ - padding-left: 8px; - padding-right: 8px; - padding-top: 17px; - padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; -} -.colitem.passive -{ - font-weight: normal; - text-transform: none; -} -.colitem a -{ - text-decoration: none; - color: black; -} -.colitem a:hover { color: silver; } -.col_left -{ - width: 30%; - float: left; -} -.col_right -{ - width: 69%; - overflow: hidden; -} - -.formrow -{ - /*height: 40px;*/ - width: 100%; -} -/*Clearfix*/ -.formrow:before, -.formrow:after { +.formrow { width: 100%; } +/* Clearfix */ +.formrow:before, .formrow:after { content: " "; display: table; } .formrow:after { clear: both; } .formrow:not(:last-child) { border-bottom: 1px dotted #ccc; } -.formitem -{ +.formitem { float: left; - padding-left: 8px; - padding-right: 8px; - padding-top: 13px; - padding-bottom: 8px; - font-weight: bold; + padding: 10px; + min-width: 20%; + /*font-size: 17px;*/ + font-weight: normal; } -.formitem:first-child { font-weight: bold; } .formitem:not(:last-child) { border-right: 1px dotted #ccc; } .formitem.invisible_border { border: none; } /* Mostly for textareas */ .formitem:only-child { width: 100%; } -.formitem textarea -{ +.formitem textarea { width: 100%; height: 100px; outline-color: #8e8e8e; } +.formitem:not(:only-child) input, .formitem:not(:only-child) select { padding: 3px;/*5px;*/ } +.formitem:not(:only-child).formlabel { + padding-top: 15px;/*18px;*/ + padding-bottom: 12px;/*16px;*/ + /*padding-left: 15px;*/ +} +.formbutton { + padding: 7px; + display: block; + margin-left: auto; + margin-right: auto; + font-size: 14px; + border-color: #ccc; +} -.tbody -{ +.tbody { border-top: 1px solid silver; margin: 8px; padding: 8px; } -.error -{ +.error { padding: 5px; margin: 5px; width: 90%; @@ -406,8 +355,7 @@ hr { color: silver; border: 1px solid silver; } border-radius: 5px; } -.success -{ +.success { padding: 5px; padding-left: 24px; margin: 5px; @@ -421,8 +369,7 @@ hr { color: silver; border: 1px solid silver; } border-radius: 5px; } -.notice -{ +.notice { padding: 5px; padding-left: 24px; margin: 5px; @@ -436,8 +383,7 @@ hr { color: silver; border: 1px solid silver; } box-sizing: border-box; } -/*button -{ +/*button { background: #ce2424; background: linear-gradient(#f97779, #ce2424); border: 1px solid #be2424; @@ -451,8 +397,7 @@ hr { color: silver; border: 1px solid silver; } } button .big { padding: 6px; }*/ -.formbutton -{ +.formbutton { background: white; border: 1px solid #8e8e8e; color: #505050; @@ -462,8 +407,7 @@ button .big { padding: 6px; }*/ border-radius: 0px; } -.username -{ +.username { text-transform: none; text-shadow: none; margin-left: 0px; @@ -488,22 +432,17 @@ button .big { padding: 6px; }*/ background: rgb(250,250,250); } -.mention { - font-weight: bold; -} - +.mention { font-weight: bold; } .threadHidden { background: orange; } .threadDeleted { background: rgba(255,0,0,0.5); } -.pagination -{ +.pagination { margin-top: 8px; margin-left: 5px; } .pagination a { color: #717171; } -.page -{ +.page { display: inline-block; margin-right: 5px; text-decoration: none; @@ -516,8 +455,7 @@ button .big { padding: 6px; }*/ border-radius: 5px; } -blockquote -{ +blockquote { border: solid 1px darkgray; background-color: #f8fafd; color: #758fa3; @@ -527,8 +465,7 @@ blockquote margin: 5px; } -blockquote .head -{ +blockquote .head { display: block; font-weight: bold; font-size: 13px; @@ -539,23 +476,20 @@ blockquote .head border-bottom: solid 1px #dde5ed; } -blockquote p -{ +blockquote p { line-height: 20px; margin-bottom: 10px; padding-left: 15px; } .rep-upvote { font-size: 13.5px !important; } -.rep-upvote span -{ +.rep-upvote span { position: relative; top: -4px; letter-spacing: 0.02em; } -.action -{ +.action { background-color: #A0CFEC; font-style: italic; padding: 15px; @@ -564,8 +498,7 @@ blockquote p } .post-content { word-wrap: break-word; } -.sidebar -{ +.sidebar { position: -moz-sticky; position: -ms-sticky; position: -o-sticky; @@ -576,8 +509,7 @@ blockquote p .gadget { padding-bottom: 20px; } /* Topic */ -.post_avatar -{ +.post_avatar { border-radius: 5px; margin-left: auto; margin-right: auto; @@ -612,22 +544,6 @@ blockquote p height: 20px; } -.tag-mini -{ - text-transform: none; - margin-left: 0px; - padding-left: 3px; - padding-right: 3px; - padding-top: 1.5px; - padding-bottom: 0px; - color: #505050; /* 80,80,80 */ - background-color: #FFFFFF; - border-style: dotted; - border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ - border-width: 1px; - font-size: 10px; -} - .action_button { display: block; float: left; @@ -643,6 +559,24 @@ blockquote p float: right; border-left: solid 1px #eaeaea; } + +.like_label:before { + content: "😀"; +} +.edit_label:before { + content: "🖊️"; +} +.trash_label:before { + content: "🗑️"; +} +.flag_label:before { + content: "🚩"; +} + +.mod_button { + margin-right: 4px; +} + .post_item:not(.simple) { background-color: #eaeaea; } @@ -718,8 +652,8 @@ blockquote p border-style: dotted; border-color: #505050; padding: 0px; - padding-left: 5px; - padding-right: 5px; + padding-left: 5px; + padding-right: 5px; z-index: 100; } @@ -733,13 +667,101 @@ blockquote p } .prev_button { left: 14px; } .next_button { right: 14px; } +.head_tag_upshift { display: none; } + +/* Control Panel */ +.tag-mini { + margin-left: 0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 2px; + padding-bottom: 2px; + + color: black; + font-size: 12px; +} + +.panel_tag { + padding-left: 0px; + padding-right: 0px; + border: none; + background: none; + color: #202020; + font-size: 14px; +} + +.panel_floater { + float: right; +} +#panel_groups > .rowitem > .panel_floater { + float: none; +} +#panel_groups > .rowitem > .panel_floater > .panel_right_button { + float: right; +} +#panel_forums > .rowitem > .panel_floater { + float: none; +} +#panel_forums > .rowitem > .panel_floater > .panel_buttons { + float: right; +} + +.panel_rank_tag, .forum_preset, .forum_active { + float: none; + color: #202020 !important; + font-size: 11px; +} +.panel_rank_tag_admin:before { + content: "Admins"; +} +.panel_rank_tag_mod:before { + content: "Mods"; +} +.panel_rank_tag_banned:before { + content: "Banned"; +} +.panel_rank_tag_guest:before { + content: "Guests"; +} +.panel_rank_tag_member:before { + content: "Members"; +} + +.forum_preset_announce:after { + content: "Announcements"; +} +.forum_preset_members:after { + content: "Member Only"; +} +.forum_preset_staff:after { + content: "Staff Only"; +} +.forum_preset_admins:after { + content: "Admin Only"; +} +.forum_preset_archive:after { + content: "Archive"; +} +.forum_preset_all:after { + content: "Public"; +} +.forum_preset_custom, .forum_preset_ { + display: none !important; +} +.forum_active_Hide:before { + content: "Hidden"; +} +.forum_active_Hide + .forum_preset:before { + content: " | "; +} +.forum_active_Show { + display: none !important; +} /* Responsive Layout */ /* Anything that isn't a small mobile */ -@media(min-width: 501px) -{ - .options - { +@media(min-width: 501px) { + .options { float: right; position: relative; top: -50px; @@ -750,17 +772,16 @@ blockquote p height: 30px; width: 30px; overflow: none; - + transition-property: background; transition-duration: 0.5s; transition-timing-function: linear; } - + .options:last-child { border-left: 1px solid rgba(100,100,110,0.75); } .right_most { margin-right: 10%; border-right: 1px solid rgba(100,100,110,0.75); } - - /*.options > .counter - { + + /*.options > .counter { background: red; border-radius: 5px; color: #FFFFFF; @@ -770,17 +791,15 @@ blockquote p line-height: 16px; font-size: 10px; width: 16px; - + position: absolute; right: 0px; }*/ } -@media (max-width: 800px) -{ +@media (max-width: 800px) { body { background: #505050; margin-bottom: 10px;} - #main - { + #main { width: 100%; min-width: 300px; margin-top: 0px; @@ -788,125 +807,112 @@ blockquote p padding: 10px; box-sizing: border-box; } - - ul - { + + ul { margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; - + line-height: 30px; min-height: 30px; padding-left: 8px; padding-right: 8px; - + background-image: linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -moz-linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -o-linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -ms-linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -webkit-linear-gradient(bottom, #2e2e2e, #4c4c4c); } - li - { + li { font-size: 14px; padding-left: 12px; padding-right: 12px; height: 30px; } - li:hover - { + li:hover { background-image: linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -moz-linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -o-linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -ms-linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -webkit-linear-gradient(bottom, #4c4c4c, #2e2e2e); } - - .rowblock { border-left: none;border-right: none;border-bottom: none; } - .rowitem { border-left: none;border-right: none; } - .rowhead { border-left: none;border-right: none; } - .tbody { border-left: none;border-right: none; } + + .rowblock { border-left: none; border-right: none; border-bottom: none; } + .rowitem { border-left: none; border-right: none; } + .rowhead { border-left: none; border-right: none; } + .tbody { border-left: none; border-right: none; } } -@media(max-width: 620px) -{ - .menu_create_topic { display: none;} - .menu_overview { display: none; } - .hide_on_mobile { display: none; } +@media(max-width: 620px) { + .menu_create_topic, .menu_overview, .hide_on_mobile { display: none; } } /* This one is specifically for small mobiles.. */ -@media(max-width: 500px) -{ +@media(max-width: 500px) { #main { margin-top: 20px; } .rowblock { box-sizing: border-box; } .rowblock:first-of-type { margin-top: 2px; } body { overflow-x: hidden; } - + .topic_name { text-align: left; margin-left: 8px; width: 50%; text-overflow: ellipsis; overflow: hidden; } .menu_profile { display: none; } .options { display: none !important; } - ul - { + ul { line-height: 30px; min-height: 30px; padding-left: 4px; padding-right: 4px; - + margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; - + clear: left; width: 100%; } - li - { + li { font-size: 15px; padding-left: 6px; padding-right: 6px; height: 28px; } - - #back - { + + #back { position: relative; top: -25px; } - #main - { + #main { padding-left: 4px; padding-right: 6px; } - - .notice - { + + .notice { width: 100%; margin-left: 0px; margin-right: 0px; margin-bottom: 8px; margin-top: 0px; - + padding: 5px; background: #96CDCD; background-image: none; box-sizing: border-box; } - + .post-content { word-wrap: normal; } .post-meta { white-space: normal; } - .post_avatar - { + .post_avatar { max-height: 80px; max-width: 80px; } .tag_block { word-wrap: break-word; } - + .notice:first-child { display: inline-block; } .getTopics { display: none; } - + .userinfo { width: 70px; } .userinfo .avatar_item { background-size: 64px; @@ -919,54 +925,48 @@ blockquote p } .user_content { min-height: 80px !important; } .user_content.nobuttons { min-height: 103px !important; } - + .colstack_grid { grid-template-columns: none; grid-gap: 8px; } .grid_istat { margin-bottom: 0px; } } -@media (min-width: 800px) -{ - @-webkit-keyframes slidein - { +@media (min-width: 800px) { + @-webkit-keyframes slidein { from { transform: translate(0,-50px) scale(0.75); } to {} } - @-moz-keyframes slidein - { + @-moz-keyframes slidein { from { transform: translate(0,-50px) scale(0.75); } to {} } - @keyframes slidein - { + @keyframes slidein { from { transform: translate(0,-50px) scale(0.75); } to {} } .right_most { margin-right: 15%; } - - #back - { + + #back { width: 800px; margin-top: 15px; margin-left: auto; margin-right: auto; margin-bottom: 15px; - + background: none; border-top: none; padding: 0px; padding-top: 0px; padding-bottom: 10px; - + background-color: rgba(30,30,30,0.75); border: 1px solid rgba(100,100,110,0.75); box-shadow: -1px -1px 1px rgba(0, 0, 0, 1), 1px 1px 1px rgba(0,0,0,0.5); - + transition-property: height; transition-duration: 0.5s; transition-timing-function: linear; } - - #main - { + + #main { float: left; clear: left; width: 765px; @@ -976,9 +976,8 @@ blockquote p margin-right: 12px; margin-bottom: 15px; } - - .nav - { + + .nav { position: sticky; top: 0px; width: 800px; @@ -987,14 +986,13 @@ blockquote p perspective: 1000px; z-index: 20; } - - ul - { + + ul { line-height: 40px; min-height: 40px; padding-left: 20px; padding-right: 20px; - + margin-top: 0px; margin-bottom: 0px; background: none; @@ -1002,42 +1000,37 @@ blockquote p border: 1px solid rgba(90,90,90,0.75); transition: transform 0.7s; } - ul:hover - { + ul:hover { transform: rotateX(-15deg); } - - li - { + + li { font-size: 15px; padding-left: 15px; padding-right: 15px; height: 38px; } } -@media (max-width: 1023px) { .left_sidebar { display: none; } .right_sidebar { display: none; } } -@media (min-width: 1024px) -{ - #back - { +@media (max-width: 1023px) { .right_sidebar { display: none; } } +@media (min-width: 1024px) { + #back { width: 1000px; margin-top: 15px; margin-left: auto; margin-right: auto; margin-bottom: 15px; - + background: none; border-top: none; padding: 0px; padding-top: 0px; padding-bottom: 10px; - + background-color: rgba(30,30,30,0.75); border: 1px solid rgba(100,100,110,0.75); box-shadow: -1px -1px 1px rgba(0, 0, 0, 1), 1px 1px 1px rgba(0,0,0,0.5); } - #main - { + #main { float: left; clear: left; width: 700px; @@ -1047,8 +1040,8 @@ blockquote p margin-right: 12px; margin-bottom: 15px; } - - .left_sidebar { display: none; } /* This theme only supports right sidebars, at the moment.. */ + #main:not(.shrink_main) { width: calc(100% - 30px); } + .right_sidebar { float: left; width: 250px; @@ -1061,30 +1054,27 @@ blockquote p .nav { width: 1000px; } } -@media (min-width: 1603px) -{ - #back - { +@media (min-width: 1603px) { + #back { width: 1548px; margin-left: auto; margin-right: auto; } - + #main { width: 1250px; } + #main:not(.shrink_main) { width: calc(100% - 30px); } } -@media (min-width: 2400px) -{ - #back - { +@media (min-width: 2400px) { + #back { width: 2000px; margin-left: auto; margin-right: auto; } - + #main { width: 1690px; } - .index_category - { + #main:not(.shrink_main) { width: calc(100% - 30px); } + .index_category { float: left; width: 835px; } @@ -1093,12 +1083,12 @@ blockquote p .index_category:only-child { width: 100%; } } -@media (min-width: 3000px) -{ +@media (min-width: 3000px) { #back { width: 2900px; } #main { width: 2490px; } + #main:not(.shrink_main) { width: calc(100% - 30px); } .index_category { width: 1230px; } .index_category:only-child { width: 100%; } - + .right_sidebar { width: 350px; } -} \ No newline at end of file +} diff --git a/themes/cosmo-conflux/theme.json b/themes/cosmo-conflux/theme.json index a1cd21f3..5aaf9af4 100644 --- a/themes/cosmo-conflux/theme.json +++ b/themes/cosmo-conflux/theme.json @@ -6,10 +6,12 @@ "FullImage": "cosmo-conflux.png", "ForkOf": "cosmo", "MobileFriendly": true, + "Tag": "🏗️", + "URL": "github.com/Azareal/Gosora", "Templates": [ { "Name": "topic", "Source": "topic_alt" } ] -} \ No newline at end of file +} diff --git a/themes/cosmo/public/main.css b/themes/cosmo/public/main.css index 79be211b..0ec5e722 100644 --- a/themes/cosmo/public/main.css +++ b/themes/cosmo/public/main.css @@ -7,22 +7,19 @@ -webkit-box-sizing: border-box; } -h1 -{ +h1 { text-shadow: 0 1px 0 black; color: darkgray; height: 60px; } -a -{ +a { text-decoration: none; color: black; } a img { border: 0; /* IE fix..*/ } -body -{ +body { background: url('/static/atombb-small.png') no-repeat left, url('/static/stars-mk1.png'); color: black; background-color: #141414; @@ -31,16 +28,14 @@ body font-family: Arial; } -ul -{ +ul { background: darkgray; padding-top: 0px; padding-bottom: 0px; list-style-type: none; } -li -{ +li { display: block; float: left; text-align: center; @@ -49,25 +44,22 @@ li margin-right: 2px; padding-left: 1px; padding-right: 1px; - + border-right: 1px solid #7a7a7a; font-weight: normal; color: white; } li:first-child { border-left: 1px solid #7a7a7a; } -li a -{ +li a { color: white; text-decoration: none; } -li:hover - { +li:hover { background: rgba(10,10,10,0.5); font-weight: normal; } -.menu_right -{ +.menu_right { float: right; color: white; font-size: 25px; @@ -133,7 +125,6 @@ li:hover text-overflow: ellipsis; } .alertItem.withAvatar { - /*background-image: url('/uploads/avatar_1.jpg');*/ background-size: 36px; background-repeat: no-repeat; text-align: center; @@ -155,24 +146,14 @@ li:hover font-size: 9px; } -#footer -{ - clear: left; - margin: 0px auto; - width: 300px; - text-align: center; -} - hr { color: silver; border: 1px solid silver; } -.rowhead -{ +.rowhead { border-top: none; font-weight: bold; color: white; } -.rowhead:hover -{ +.rowhead:hover { color: rgba(200,200,200,1); transition: color 1s; -moz-transition: color 1s; @@ -228,45 +209,37 @@ hr { color: silver; border: 1px solid silver; } .rowhead .topic_status_e { display: none !important; } .topic_button { float: right; position: relative; top: -22px; margin-right: 2px; border-style: solid !important; } -.colblock_left -{ +.colblock_left { padding: 0px; padding-top: 0px; width: 30%; float: left; margin-right: 8px; } -.colblock_right -{ +.colblock_right { padding: 0px; padding-top: 0px; width: 65%; overflow: hidden; word-wrap: break-word; } -.colblock_left:empty { display: none; } -.colblock_right:empty -{ display: none; } -.colblock_left:first-of-type { margin-top: 8px; } -.colblock_right:first-of-type { margin-top: 8px; } +.colblock_left:empty, .colblock_right:empty { display: none; } +.colblock_left:first-of-type, .colblock_right:first-of-type { margin-top: 8px; } -/* The new method of doing columns layouts, colblock is now deprecated */ -.colstack_left -{ +/* The new method of doing columns layouts, colblock is now deprecated :( */ +.colstack_left { float: left; width: 30%; margin-right: 8px; margin-top: 12px; } -.colstack_right -{ +.colstack_right { float: left; width: 65%; width: calc(70% - 15px); margin-top: 12px; } -.colstack_item -{ +.colstack_item { padding: 0px; padding-top: 0px; margin-bottom: 16px; @@ -300,107 +273,63 @@ hr { color: silver; border: 1px solid silver; } padding-bottom: 12px; font-size: 16px; } -.grid_istat { - /*margin-bottom: 10px;*/ - margin-bottom: 5px; -} +.grid_istat { margin-bottom: 5px; } .stat_green { background-color: lightgreen; border-color: green; } .stat_orange { background-color: #ffe4b3; border-color: orange; } .stat_red { background-color: #ffb2b2; border-color: red; } .stat_disabled { background-color: lightgray; border-color: gray; } -.colitem -{ - padding-left: 8px; - padding-right: 8px; - padding-top: 17px; - padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; -} -.colitem.passive -{ - font-weight: normal; - text-transform: none; -} -.colitem a -{ - text-decoration: none; - color: black; -} -.colitem a:hover { color: silver; } - -.col_left -{ - width: 30%; - float: left; -} -.col_right -{ - width: 69%; - overflow: hidden; -} - -.formrow -{ - /*height: 40px;*/ +.formrow { width: 100%; } -/*Clearfix*/ -.formrow:before, -.formrow:after { +/* Clearfix */ +.formrow:before, .formrow:after { content: " "; display: table; } -.formrow:after { - clear: both; -} -.formrow:not(:last-child) -{ - border-bottom: 1px dotted #ccc; -} +.formrow:after { clear: both; } +.formrow:not(:last-child) { border-bottom: 1px dotted #ccc; } -.formitem -{ +.formitem { float: left; - padding-left: 8px; - padding-right: 8px; - padding-top: 13px; - padding-bottom: 8px; - font-weight: bold; -} -.formitem:first-child -{ - font-weight: bold; -} -.formitem:not(:last-child) -{ - border-right: 1px dotted #ccc; -} -.formitem.invisible_border -{ - border: none; + padding: 10px; + min-width: 20%; + /*font-size: 17px;*/ + font-weight: normal; } +.formitem:not(:last-child) { border-right: 1px dotted #ccc; } +.formitem.invisible_border { border: none; } /* Mostly for textareas */ .formitem:only-child { width: 100%; } -.formitem textarea -{ +.formitem textarea { width: 100%; height: 100px; outline-color: #8e8e8e; } +.formitem:not(:only-child) input, .formitem:not(:only-child) select { padding: 3px;/*5px;*/ } +.formitem:not(:only-child).formlabel { + padding-top: 15px;/*18px;*/ + padding-bottom: 12px;/*16px;*/ + /*padding-left: 15px;*/ +} +.formbutton { + padding: 7px; + display: block; + margin-left: auto; + margin-right: auto; + font-size: 14px; + border-color: #ccc; +} -.tbody -{ +.tbody { border-top: 1px solid silver; margin: 8px; padding: 8px; } -.error -{ +.error { padding: 5px; margin: 5px; width: 90%; @@ -410,8 +339,7 @@ hr { color: silver; border: 1px solid silver; } border-radius: 5px; } -.success -{ +.success { padding: 5px; padding-left: 24px; margin: 5px; @@ -425,8 +353,7 @@ hr { color: silver; border: 1px solid silver; } border-radius: 5px; } -.notice -{ +.notice { padding: 5px; padding-left: 24px; margin: 5px; @@ -440,8 +367,7 @@ hr { color: silver; border: 1px solid silver; } box-sizing: border-box; } -/*button -{ +/*button { background: #ce2424; background: linear-gradient(#f97779, #ce2424); border: 1px solid #be2424; @@ -455,8 +381,7 @@ hr { color: silver; border: 1px solid silver; } } button .big { padding: 6px; }*/ -.formbutton -{ +.formbutton { background: white; border: 1px solid #8e8e8e; color: #505050; @@ -466,8 +391,7 @@ button .big { padding: 6px; }*/ border-radius: 0px; } -.username -{ +.username { text-transform: none; text-shadow: none; margin-left: 0px; @@ -493,22 +417,17 @@ button .big { padding: 6px; }*/ background: rgb(250,250,250); } -.mention { - font-weight: bold; -} - +.mention { font-weight: bold; } .threadHidden { background: orange; } .threadDeleted { background: rgba(255,0,0,0.5); } -.pagination -{ +.pagination { margin-top: 8px; margin-left: 5px; } .pagination a { color: #717171; } -.page -{ +.page { display: inline-block; margin-right: 5px; text-decoration: none; @@ -521,8 +440,7 @@ button .big { padding: 6px; }*/ border-radius: 5px; } -blockquote -{ +blockquote { border: solid 1px darkgray; background-color: #f8fafd; color: #758fa3; @@ -532,8 +450,7 @@ blockquote margin: 5px; } -blockquote .head -{ +blockquote .head { display: block; font-weight: bold; font-size: 13px; @@ -544,23 +461,20 @@ blockquote .head border-bottom: solid 1px #dde5ed; } -blockquote p -{ +blockquote p { line-height: 20px; margin-bottom: 10px; padding-left: 15px; } .rep-upvote { font-size: 13.5px !important; } -.rep-upvote span -{ +.rep-upvote span { position: relative; top: -4px; letter-spacing: 0.02em; } -.action -{ +.action { background-color: #A0CFEC; font-style: italic; padding: 15px; @@ -569,8 +483,7 @@ blockquote p } .post-content { word-wrap: break-word; } -.sidebar -{ +.sidebar { position: -moz-sticky; position: -ms-sticky; position: -o-sticky; @@ -584,8 +497,7 @@ blockquote p .cell_last img { margin-right: 8px; } /* User Postbit */ -.tag_block -{ +.tag_block { background: url('/static/fabric-base-simple-alpha.png'), linear-gradient(#DF5B5A,#D93636); background-color: red; border-bottom-left-radius: 4px; @@ -607,8 +519,7 @@ blockquote p } .tag_block:last-child { margin-bottom: 10px; } -.tag_block .tag_pre, .tag_block .tag_post -{ +.tag_block .tag_pre, .tag_block .tag_post { background-color: #EA9090; height: 4px; position: absolute; @@ -616,27 +527,23 @@ blockquote p top: -4px; } -.tag_block .tag_pre -{ +.tag_block .tag_pre { border-top-left-radius: 3px; left: -1px; } -.post_tag -{ +.post_tag { color: white; font-size: 13px; font-style: normal; text-overflow: ellipsis; font-weight: bold; } -.tag_block .tag_post -{ +.tag_block .tag_post { border-top-right-radius: 3px; right: -1px; } -.tag_block.groupRibbon -{ +.tag_block.groupRibbon { display: none; } @@ -681,6 +588,24 @@ blockquote p float: right; border-left: solid 1px #eaeaea; } + +.like_label:before { + content: "😀"; +} +.edit_label:before { + content: "🖊️"; +} +.trash_label:before { + content: "🗑️"; +} +.flag_label:before { + content: "🚩"; +} + +.mod_button { + margin-right: 4px; +} + .post_item:not(.simple) { background-color: #eaeaea; } @@ -705,7 +630,7 @@ blockquote p .userinfo { border-radius: 5px; - + background: white; width: 132px; padding: 2px; @@ -769,13 +694,101 @@ blockquote p } .prev_button { left: 14px; } .next_button { right: 14px; } +.head_tag_upshift { display: none !important; } + +/* Control Panel */ +.tag-mini { + margin-left: 0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 2px; + padding-bottom: 2px; + + color: black; + font-size: 12px; +} + +.panel_tag { + padding-left: 0px; + padding-right: 0px; + border: none; + background: none; + color: #202020; + font-size: 14px; +} + +.panel_floater { + float: right; +} +#panel_groups > .rowitem > .panel_floater { + float: none; +} +#panel_groups > .rowitem > .panel_floater > .panel_right_button { + float: right; +} +#panel_forums > .rowitem > .panel_floater { + float: none; +} +#panel_forums > .rowitem > .panel_floater > .panel_buttons { + float: right; +} + +.panel_rank_tag, .forum_preset, .forum_active { + float: none; + color: #202020 !important; + font-size: 11px; +} +.panel_rank_tag_admin:before { + content: "Admins"; +} +.panel_rank_tag_mod:before { + content: "Mods"; +} +.panel_rank_tag_banned:before { + content: "Banned"; +} +.panel_rank_tag_guest:before { + content: "Guests"; +} +.panel_rank_tag_member:before { + content: "Members"; +} + +.forum_preset_announce:after { + content: "Announcements"; +} +.forum_preset_members:after { + content: "Member Only"; +} +.forum_preset_staff:after { + content: "Staff Only"; +} +.forum_preset_admins:after { + content: "Admin Only"; +} +.forum_preset_archive:after { + content: "Archive"; +} +.forum_preset_all:after { + content: "Public"; +} +.forum_preset_custom, .forum_preset_ { + display: none !important; +} +.forum_active_Hide:before { + content: "Hidden"; +} +.forum_active_Hide + .forum_preset:before { + content: " | "; +} +.forum_active_Show { + display: none !important; +} /* Responsive Layout */ /* Anything that isn't a small mobile */ -@media(min-width: 501px) -{ - .options - { +@media(min-width: 501px) { + .options { float: right; position: relative; top: -50px; @@ -786,37 +799,19 @@ blockquote p height: 30px; width: 30px; overflow: none; - + transition-property: background; transition-duration: 0.5s; transition-timing-function: linear; } - + .options:last-child { border-left: 1px solid rgba(100,100,110,0.75); } .right_most { margin-right: 10%; border-right: 1px solid rgba(100,100,110,0.75); } - - /*.options > .counter - { - background: red; - border-radius: 5px; - color: #FFFFFF; - display: inline-block; - font-weight: bold; - text-align: center; - line-height: 16px; - font-size: 10px; - width: 16px; - - position: absolute; - right: 0px; - }*/ } -@media (max-width: 800px) -{ - body { background: #505050; margin-bottom: 10px;} - #main - { +@media (max-width: 800px) { + body { background: #505050; margin-bottom: 10px; } + #main { width: 100%; min-width: 300px; margin-top: 0px; @@ -824,130 +819,117 @@ blockquote p padding: 10px; box-sizing: border-box; } - - ul - { + + ul { margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; - + line-height: 30px; min-height: 30px; padding-left: 8px; padding-right: 8px; - + background-image: linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -moz-linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -o-linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -ms-linear-gradient(bottom, #2e2e2e, #4c4c4c); background-image: -webkit-linear-gradient(bottom, #2e2e2e, #4c4c4c); } - li - { + li { font-size: 14px; padding-left: 12px; padding-right: 12px; height: 30px; } - li:hover - { + li:hover { background-image: linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -moz-linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -o-linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -ms-linear-gradient(bottom, #4c4c4c, #2e2e2e); background-image: -webkit-linear-gradient(bottom, #4c4c4c, #2e2e2e); } - - .rowblock { border-left: none;border-right: none;border-bottom: none; } - .rowitem { border-left: none;border-right: none; } - .rowhead { border-left: none;border-right: none; } - .tbody { border-left: none;border-right: none; } + + .rowblock { border-left: none; border-right: none; border-bottom: none; } + .rowitem { border-left: none; border-right: none; } + .rowhead { border-left: none; border-right: none; } + .tbody { border-left: none; border-right: none; } .forumLastposter { width: 35%; } .forumLastposter .title { width: 90px; } .cell_author img { display: none; } .cell_last img { display: none; } } -@media(max-width: 620px) -{ - .menu_create_topic { display: none;} - .menu_overview { display: none; } - .hide_on_mobile { display: none; } +@media(max-width: 620px) { + .menu_create_topic, .menu_overview, .hide_on_mobile { display: none; } } /* This one is specifically for small mobiles.. */ -@media(max-width: 500px) -{ +@media(max-width: 500px) { #main { margin-top: 20px; } .rowblock { box-sizing: border-box; } .rowblock:first-of-type { margin-top: 2px; } body { overflow-x: hidden; } - + .topic_name { text-align: left; margin-left: 8px; width: 50%; text-overflow: ellipsis; overflow: hidden; } .menu_profile { display: none; } .options { display: none !important; } - ul - { + ul { line-height: 30px; min-height: 30px; padding-left: 4px; padding-right: 4px; - + margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; - + clear: left; width: 100%; } - li - { + li { font-size: 15px; padding-left: 6px; padding-right: 6px; height: 28px; } - - #back - { + + #back { position: relative; top: -25px; } - #main - { + #main { padding-left: 4px; padding-right: 6px; } - .notice - { + .notice { width: 100%; margin-left: 0px; margin-right: 0px; margin-bottom: 8px; margin-top: 0px; - + padding: 5px; background: #96CDCD; background-image: none; box-sizing: border-box; } - + .post-content { word-wrap: normal; } .post-meta { white-space: normal; } - .post_avatar - { + .post_avatar { max-height: 80px; max-width: 80px; } .tag_block { word-wrap: break-word; } .tag_block:last-child { margin-bottom: 5px; } - + .notice:first-child { display: inline-block; } .forumLastposter img { display: none; } .getTopics { display: none; } - + .userinfo { width: 70px; } .userinfo .avatar_item { background-size: 64px; @@ -960,54 +942,48 @@ blockquote p } .user_content { min-height: 97.5px !important; } .user_content.nobuttons { min-height: 121px !important; } - + .colstack_grid { grid-template-columns: none; grid-gap: 8px; } .grid_istat { margin-bottom: 0px; } } -@media (min-width: 800px) -{ - @-webkit-keyframes slidein - { +@media (min-width: 800px) { + @-webkit-keyframes slidein { from { transform: translate(0,-50px) scale(0.75); } to {} } - @-moz-keyframes slidein - { + @-moz-keyframes slidein { from { transform: translate(0,-50px) scale(0.75); } to {} } - @keyframes slidein - { + @keyframes slidein { from { transform: translate(0,-50px) scale(0.75); } to {} } .right_most { margin-right: 15%; } - - #back - { + + #back { width: 800px; margin-top: 15px; margin-left: auto; margin-right: auto; margin-bottom: 15px; - + background: none; border-top: none; padding: 0px; padding-top: 0px; padding-bottom: 10px; - + background-color: rgba(30,30,30,0.75); border: 1px solid rgba(100,100,110,0.75); box-shadow: -1px -1px 1px rgba(0, 0, 0, 1), 1px 1px 1px rgba(0,0,0,0.5); - + transition-property: height; transition-duration: 0.5s; transition-timing-function: linear; } - - #main - { + + #main { float: left; clear: left; width: 765px; @@ -1017,9 +993,8 @@ blockquote p margin-right: 12px; margin-bottom: 15px; } - - .nav - { + + .nav { position: sticky; top: 0px; width: 800px; @@ -1028,14 +1003,13 @@ blockquote p perspective: 1000px; z-index: 20; } - - ul - { + + ul { line-height: 40px; min-height: 40px; padding-left: 20px; padding-right: 20px; - + margin-top: 0px; margin-bottom: 0px; background: none; @@ -1044,39 +1018,35 @@ blockquote p transition: transform 0.7s; } ul:hover { transform: rotateX(-15deg); } - - li - { + + li { font-size: 15px; padding-left: 15px; padding-right: 15px; height: 38px; } } -@media (max-width: 1023px) { .left_sidebar { display: none; } .right_sidebar { display: none; } } -@media (min-width: 1024px) -{ - #back - { +@media (max-width: 1023px) { .right_sidebar { display: none; } } +@media (min-width: 1024px) { + #back { width: 1000px; margin-top: 15px; margin-left: auto; margin-right: auto; margin-bottom: 15px; - + background: none; border-top: none; padding: 0px; padding-top: 0px; padding-bottom: 10px; - + background-color: rgba(30,30,30,0.75); border: 1px solid rgba(100,100,110,0.75); box-shadow: -1px -1px 1px rgba(0, 0, 0, 1), 1px 1px 1px rgba(0,0,0,0.5); } - - #main - { + + #main { float: left; clear: left; width: 700px; @@ -1086,8 +1056,9 @@ blockquote p margin-right: 12px; margin-bottom: 15px; } - - .left_sidebar { display: none; } /* This theme only supports right sidebars, at the moment.. */ + + #main:not(.shrink_main) { width: calc(100% - 30px); } + .right_sidebar { float: left; width: 250px; @@ -1100,28 +1071,26 @@ blockquote p .nav { width: 1000px; } } -@media (min-width: 1603px) -{ - #back - { +@media (min-width: 1603px) { + #back { width: 1548px; margin-left: auto; margin-right: auto; } #main { width: 1250px; } + #main:not(.shrink_main) { width: calc(100% - 30px); } .forumLastposter .title { width: 280px; } } -@media (min-width: 2400px) -{ - #back - { +@media (min-width: 2400px) { + #back { width: 2000px; margin-left: auto; margin-right: auto; } - + #main { width: 1690px; } + #main:not(.shrink_main) { width: calc(100% - 30px); } .index_category { float: left; width: 835px; } .index_category:nth-child(even) { margin-left: 10px; } .index_category:nth-child(odd) { overflow: hidden; } @@ -1130,14 +1099,14 @@ blockquote p .forumLastposter .title { width: 200px; } } -@media (min-width: 3000px) -{ +@media (min-width: 3000px) { #back { width: 2900px; } #main { width: 2490px; } + #main:not(.shrink_main) { width: calc(100% - 30px); } .index_category { width: 1230px; } .index_category:only-child { width: 100%; } .forumLastposter .title { width: 300px; } - + .right_sidebar { width: 350px; } - .myinfo_avatar { max-height: 120px;max-width: 120px; } -} \ No newline at end of file + .myinfo_avatar { max-height: 120px; max-width: 120px; } +} diff --git a/themes/cosmo/theme.json b/themes/cosmo/theme.json index 526ba268..570b63bf 100644 --- a/themes/cosmo/theme.json +++ b/themes/cosmo/theme.json @@ -5,10 +5,12 @@ "Creator": "Azareal", "FullImage": "cosmo.png", "MobileFriendly": true, + "Tag": "🏗️", + "URL": "github.com/Azareal/Gosora", "Templates": [ { "Name": "topic", "Source": "topic_alt" } ] -} \ No newline at end of file +} diff --git a/themes/shadow/theme.json b/themes/shadow/theme.json index fa861f80..689270ed 100644 --- a/themes/shadow/theme.json +++ b/themes/shadow/theme.json @@ -4,5 +4,6 @@ "Version": "0.0.1", "Creator": "Azareal", "Disabled": true, - "HideFromThemes": true -} \ No newline at end of file + "HideFromThemes": true, + "URL": "github.com/Azareal/Gosora" +} diff --git a/themes/tempra-conflux/public/main.css b/themes/tempra-conflux/public/main.css index c60ef478..d776167e 100644 --- a/themes/tempra-conflux/public/main.css +++ b/themes/tempra-conflux/public/main.css @@ -4,8 +4,7 @@ -webkit-box-sizing: border-box; } -body -{ +body { font-family: arial; padding-bottom: 8px; background-image: url('/static/test_bg2.svg'); @@ -17,10 +16,7 @@ body .user_content { font-family: Segoe UI Emoji, arial; } } -/*.move_left{float: left;position: relative;left: 50%;} -.move_right{float: left;position: relative;left: -50%;}*/ -ul -{ +ul { padding-left: 0px; padding-right: 0px; height: 36px; @@ -29,29 +25,25 @@ ul background-color: white; margin-bottom: 12px; } -li -{ +li { height: 35px; padding-left: 10px; padding-top: 8px; padding-bottom: 8px; } li:hover { background: rgb(250,250,250); } -li a -{ +li a { text-decoration: none; /*color: #515151;*/ color: black; font-size: 17px; } -.menu_left -{ +.menu_left { float: left; border-right: 1px solid #ccc; padding-right: 10px; } -.menu_right -{ +.menu_right { float: right; border-left: 1px solid #ccc; padding-right: 10px; @@ -90,13 +82,8 @@ li a color: black; font-weight: bold; } -.selectedAlert .alert_counter { - display: none; -} -.menu_alerts .alertList { - display: none; - text-transform: none; -} +.selectedAlert .alert_counter { display: none; } +.menu_alerts .alertList { display: none; } .selectedAlert .alertList { position: absolute; top: 51px; @@ -104,26 +91,27 @@ li a background: white; font-size: 10px; line-height: 16px; - width: 156px; + width: 300px; right: calc(5% + 7px); border-top: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; + margin-bottom: 10px; } .alertItem { padding: 8px; overflow: hidden; text-overflow: ellipsis; + padding-top: 15px; + padding-bottom: 16px; } .alertItem.withAvatar { - /*background-image: url('/uploads/avatar_1.jpg');*/ - background-size: 36px; + background-size: 60px; background-repeat: no-repeat; - text-align: center; padding-right: 12px; - padding-left: 42px; - height: 46px; + padding-left: 68px; + height: 50px; } .alertItem.withAvatar:not(:last-child) { border-bottom: 1px solid rgb(230,230,230); @@ -131,26 +119,25 @@ li a .alertItem .text { overflow: hidden; text-overflow: ellipsis; - height: 30px; + height: 40px; width: 100%; color: black; - font-size: 10px; - font-weight: bold; + font-size: 13px; + white-space: nowrap; + font-weight: normal; } -.alertItem .text.smaller { - font-size: 9px; +.alertItem:not(.withAvatar) { + margin-left: 5px; } -.container -{ +.container { width: 90%; padding: 0px; margin-left: auto; margin-right: auto; } -.rowblock -{ +.rowblock { border: 1px solid #ccc; width: 100%; padding: 0px; @@ -158,8 +145,7 @@ li a } .rowblock:empty { display: none; } -.colblock_left -{ +.colblock_left { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -167,8 +153,7 @@ li a float: left; margin-right: 8px; } -.colblock_right -{ +.colblock_right { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -176,24 +161,20 @@ li a overflow: hidden; word-wrap: break-word; } -.colblock_left:empty { display: none; } -.colblock_right:empty { display: none; } +.colblock_left:empty, .colblock_right:empty { display: none; } /* The new method of doing columns layouts, colblock is now deprecated :( */ -.colstack_left -{ +.colstack_left { float: left; width: 30%; margin-right: 8px; } -.colstack_right -{ +.colstack_right { float: left; width: 65%; width: calc(70% - 15px); } -.colstack_item -{ +.colstack_item { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -211,6 +192,7 @@ li a grid-template-columns: repeat(3, 1fr); grid-gap: 12px; margin-left: 5px; + margin-top: 2px; } .grid_item { border: 1px solid #ccc; @@ -225,76 +207,42 @@ li a padding-bottom: 12px; font-size: 16px; } -.grid_istat { - margin-bottom: 5px; -} +.grid_istat { margin-bottom: 5px; } .stat_green { background-color: lightgreen; border-color: green; } .stat_orange { background-color: #ffe4b3; border-color: orange; } .stat_red { background-color: #ffb2b2; border-color: red; } .stat_disabled { background-color: lightgray; border-color: gray; } -.rowitem -{ +.rowitem { width: 100%; - padding-left: 8px; + /*padding-left: 8px; padding-right: 8px; padding-top: 17px; padding-bottom: 12px; font-weight: bold; - text-transform: uppercase; + text-transform: uppercase;*/ + padding-left: 10px; + padding-top: 14px; + padding-bottom: 12px; + padding-right: 10px; background-color: white; } -.rowitem.passive -{ +.rowitem.passive { font-weight: normal; text-transform: none; } -.rowitem:not(:last-child) -{ +.rowitem:not(:last-child) { border-bottom: 1px dotted #ccc; } -.rowitem a -{ +.rowitem a { text-decoration: none; color: black; } .rowitem a:hover { color: silver; } .opthead { display: none; } -.col_left -{ - width: 30%; - float: left; -} -.col_right -{ - width: 69%; - overflow: hidden; -} -.colitem -{ - padding-left: 8px; - padding-right: 8px; - padding-top: 17px; - padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; -} -.colitem.passive -{ - font-weight: normal; - text-transform: none; -} -.colitem a -{ - text-decoration: none; - color: black; -} -.colitem a:hover { color: silver; } - -.formrow -{ +.formrow { width: 100%; background-color: white; } @@ -307,42 +255,49 @@ li a .formrow:after { clear: both; } .formrow:not(:last-child) { border-bottom: 1px dotted #ccc; } -.formitem -{ +.formitem { float: left; - padding-left: 8px; - padding-right: 8px; - padding-top: 13px; - padding-bottom: 8px; - font-weight: bold; + padding: 10px; + min-width: 20%; + /*font-size: 17px;*/ + font-weight: normal; } -.formitem:first-child { font-weight: bold; } .formitem:not(:last-child) { border-right: 1px dotted #ccc; } .formitem.invisible_border { border: none; } /* Mostly for textareas */ .formitem:only-child { width: 100%; } -.formitem textarea -{ +.formitem textarea { width: 100%; height: 100px; outline-color: #8e8e8e; } -.formitem:has-child() -{ +.formitem:has-child() { margin: 0 auto; float: none; } +.formitem:not(:only-child) input, .formitem:not(:only-child) select { padding: 3px;/*5px;*/ } +.formitem:not(:only-child).formlabel { + padding-top: 15px;/*18px;*/ + padding-bottom: 12px;/*16px;*/ + /*padding-left: 15px;*/ +} +.formbutton { + padding: 7px; + display: block; + margin-left: auto; + margin-right: auto; + font-size: 15px; + border-color: #ccc; +} -button -{ +button { background: white; border: 1px solid #8e8e8e; } /* Topics */ -.topic_status -{ +.topic_status { text-transform: none; margin-left: 8px; padding-left: 2px; @@ -367,8 +322,7 @@ button background: linear-gradient(to bottom, #eaeaea, hsl(0,0%,79%)); } -.username -{ +.username, .panel_tag { text-transform: none; margin-left: 0px; padding-left: 4px; @@ -382,12 +336,19 @@ button border-width: 1px; font-size: 15px; } -button.username -{ +button.username { position: relative; top: -0.25px; } +/* We'll be rewriting the profiles soon too! */ +/*.username.real_username { + color: #404040; + font-size: 16px; + padding-right: 4px; +} +.username.real_username:hover { color: black; }*/ + .postQuote { border: rgb(200,200,210); background: rgb(245,245,255); @@ -400,42 +361,23 @@ button.username border-width: 1px; } -.tag-mini -{ - text-transform: none; - margin-left: 0px; - padding-left: 3px; - padding-right: 3px; - padding-top: 1.5px; - padding-bottom: 0px; - color: #505050; /* 80,80,80 */ - background-color: #FFFFFF; - border-style: dotted; - border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ - border-width: 1px; - font-size: 10px; -} - .mention { font-weight: bold; } .show_on_edit { display: none; } -.alert -{ +.alert { display: block; padding: 5px; margin-bottom: 10px; border: 1px solid #ccc; } -.alert_success -{ +.alert_success { display: block; padding: 5px; - border: 1px solid A2FC00; + border: 1px solid #A2FC00; margin-bottom: 10px; - background-color: DAF7A6; + background-color: #DAF7A6; } -.alert_error -{ +.alert_error { display: block; padding: 5px; border: 1px solid #FF004B; @@ -484,6 +426,25 @@ button.username border-left: solid 1px #eaeaea; } +.like_label:before { + content: "😀"; +} +.edit_label:before { + content: "🖊️"; +} +.trash_label:before { + content: "🗑️"; +} +.flag_label:before { + content: "🚩"; +} + +.mod_button { + margin-right: 4px; +} +.simple > .real_username { color: #404040; font-size: 17px; } +.simple > .user_content { background: none; } + .simple { background-color: white; } .post_item:not(.simple) { background-color: #eaeaea; @@ -576,7 +537,116 @@ button.username .prev_button { left: 14px; } .next_button { right: 14px; } -/* Media Queries from Simple. Probably useless in Conflux */ +.head_tag_upshift { + float: right; + position: relative; + top: -2px; +} + +/* Control Panel */ +.panel_upshift:visited { + color: black; +} + +.tag-mini { + margin-left: 0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 2px; + padding-bottom: 2px; + + color: black; + font-size: 12px; +} + +.panel_tag { + padding-left: 0px; + padding-right: 0px; + border: none; + background: none; + color: #202020; + font-size: 14px; +} + +.panel_floater { + float: right; +} +#panel_groups > .rowitem > .panel_floater { + float: none; +} +#panel_groups > .rowitem > .panel_floater > .panel_right_button { + float: right; +} +#panel_forums > .rowitem > .panel_floater { + float: none; +} +#panel_forums > .rowitem > .panel_floater > .panel_buttons { + float: right; +} + +.panel_rank_tag, .forum_preset, .forum_active { + float: none; + color: #202020 !important; + font-size: 11px; +} +.panel_rank_tag_admin:before { + content: "Admins"; +} +.panel_rank_tag_mod:before { + content: "Mods"; +} +.panel_rank_tag_banned:before { + content: "Banned"; +} +.panel_rank_tag_guest:before { + content: "Guests"; +} +.panel_rank_tag_member:before { + content: "Members"; +} + +.forum_preset_announce:after { + content: "Announcements"; +} +.forum_preset_members:after { + content: "Member Only"; +} +.forum_preset_staff:after { + content: "Staff Only"; +} +.forum_preset_admins:after { + content: "Admin Only"; +} +.forum_preset_archive:after { + content: "Archive"; +} +.forum_preset_all:after { + content: "Public"; +} +.forum_preset_custom, .forum_preset_ { + display: none !important; +} +.forum_active_Hide:before { + content: "Hidden"; +} +.forum_active_Hide + .forum_preset:before { + content: " | "; +} +.forum_active_Show { + display: none !important; +} + +.theme_row > .panel_floater > .panel_right_button { + margin-left: 5px; +} + +@media(max-width: 1300px) { + .theme_row { + background-image: none !important; + } +} + +/* The Media Queries */ @media (max-width: 880px) { li { height: 29px; @@ -589,23 +659,25 @@ button.username height: 30px; margin-top: 8px; } - .menu_left { padding-right: 9px; } - .menu_right { padding-right: 9px; } + .menu_left, .menu_right { padding-right: 9px; } .menu_alerts { padding-left: 7px; padding-right: 7px; font-size: 18px; } - - body { padding-left: 4px; padding-right: 4px; margin: 0px !important; width: 100% !important; height: 100% !important; overflow-x: hidden; } + + body { + padding-left: 4px; + padding-right: 4px; + margin: 0px !important; + width: 100% !important; + height: 100% !important; + overflow-x: hidden; + } .container { width: auto; } .selectedAlert .alertList { top: 37px; right: 4px; } } -@media (max-width: 810px) { - .rowitem { text-transform: none; } -} - @media (max-width: 680px) { li { padding-left: 5px; @@ -615,10 +687,9 @@ button.username } li a { font-size: 14px; } ul { height: 26px; } - .menu_left { padding-right: 7px; } - .menu_right { padding-right: 7px; } + .menu_left, .menu_right { padding-right: 7px; } .menu_create_topic { display: none; } - + .menu_alerts { padding-left: 4px; padding-right: 4px; @@ -626,7 +697,7 @@ button.username padding-top: 1px; } .selectedAlert .alertList { top: 33px; } - + .hide_on_mobile { display: none; } .prev_button, .next_button { top: auto;bottom: 5px; } .colstack_grid { grid-template-columns: none; grid-gap: 8px; } @@ -636,8 +707,30 @@ button.username @media (max-width: 470px) { ul { margin-bottom: 10px; } .menu_overview, .menu_profile, .hide_on_micro { display: none; } + .selectedAlert .alertList { + width: 156px; + margin-bottom: 5px; + } + .alertItem.withAvatar { + background-size: 36px; + text-align: center; + padding-left: 42px; + height: 46px; + } + .alertItem { + padding: 8px; + } + .alertItem .text { + height: 30px; + font-size: 10px; + font-weight: bold; + white-space: normal; + } + .alertItem .text.smaller { + font-size: 9px; + } .post_container { overflow: visible !important; } - + .post_item { background-position: 0px 2px !important; background-size: 64px 64px !important; @@ -679,7 +772,7 @@ button.username .user_content.nobuttons { min-height: 100.5px !important; } .the_name { font-size: 15px; } .post_tag { font-size: 12px; } - + .container { width: 100% !important; } } diff --git a/themes/tempra-conflux/theme.json b/themes/tempra-conflux/theme.json index 45017c71..c98e1c4e 100644 --- a/themes/tempra-conflux/theme.json +++ b/themes/tempra-conflux/theme.json @@ -1,14 +1,15 @@ { "Name": "tempra-conflux", "FriendlyName": "Tempra Conflux", - "Version": "0.0.1", + "Version": "0.1.0-dev", "Creator": "Azareal", "FullImage": "tempra-conflux.png", "MobileFriendly": true, + "URL": "github.com/Azareal/Gosora", "Templates": [ { "Name": "topic", "Source": "topic_alt" } ] -} \ No newline at end of file +} diff --git a/themes/tempra-cursive/public/main.css b/themes/tempra-cursive/public/main.css index 5ed37002..825b42c9 100644 --- a/themes/tempra-cursive/public/main.css +++ b/themes/tempra-cursive/public/main.css @@ -4,8 +4,7 @@ -webkit-box-sizing: border-box; } -body -{ +body { font-family: cursive; padding-bottom: 8px; } @@ -15,8 +14,7 @@ body .user_content { font-family: Segoe UI Emoji, arial; } } -ul -{ +ul { padding-left: 0px; padding-right: 0px; height: 36px; @@ -25,31 +23,27 @@ ul background-color: white; margin-bottom: 12px; } -li -{ +li { height: 35px; padding-left: 10px; padding-top: 8px; padding-bottom: 8px; } li:hover { background: rgb(250,250,250); } -li a -{ +li a { text-decoration: none; /*color: #515151;*/ color: black; font-size: 17px; } -.menu_left -{ +.menu_left { float: left; border-right: 1px solid #ccc; padding-right: 10px; font-family: cursive; padding-top: 4px; } -.menu_right -{ +.menu_right { float: right; border-left: 1px solid #ccc; padding-right: 10px; @@ -74,25 +68,16 @@ li a padding-top: 2.5px; height: 14px; text-align: center; - border: white solid 1px; } -.menu_alerts .alert_counter:empty { - display: none; -} +.menu_alerts .alert_counter:empty { display: none; } -.selectedAlert { +.selectedAlert, .selectedAlert:hover { background: white; color: black; } -.selectedAlert:hover { - background: white; - color: black; -} -.menu_alerts .alertList { - display: none; - text-transform: none; -} +.menu_alerts .alertList { display: none; } + .selectedAlert .alertList { position: absolute; top: 51px; @@ -100,24 +85,27 @@ li a background: white; font-size: 10px; line-height: 16px; - width: 135px; + width: 300px; right: calc(5% + 7px); border-top: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; + margin-bottom: 10px; } .alertItem { padding: 8px; overflow: hidden; text-overflow: ellipsis; + padding-top: 15px; + padding-bottom: 16px; } .alertItem.withAvatar { - background-size: auto 56px; + background-size: 60px; background-repeat: no-repeat; - text-align: right; padding-right: 12px; - height: 46px; + padding-left: 68px; + height: 50px; } .alertItem.withAvatar:not(:last-child) { border-bottom: 1px solid rgb(230,230,230); @@ -126,24 +114,24 @@ li a overflow: hidden; text-overflow: ellipsis; float: right; - width: calc(100% - 20px); - height: 30px; + height: 40px; + width: 100%; + white-space: nowrap; } .alertItem .text { - font-size: 10px; - font-weight: bold; + font-size: 13px; + font-weight: normal; + margin-left: 5px; } -.container -{ +.container { width: 90%; padding: 0px; margin-left: auto; margin-right: auto; } -.rowblock -{ +.rowblock { border: 1px solid #ccc; width: 100%; padding: 0px; @@ -151,8 +139,7 @@ li a } .rowblock:empty { display: none; } -.colblock_left -{ +.colblock_left { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -160,8 +147,7 @@ li a float: left; margin-right: 8px; } -.colblock_right -{ +.colblock_right { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -169,24 +155,20 @@ li a overflow: hidden; word-wrap: break-word; } -.colblock_left:empty { display: none; } -.colblock_right:empty { display: none; } +.colblock_left:empty, .colblock_right:empty { display: none; } /* The new method of doing columns layouts, colblock is now deprecated :( */ -.colstack_left -{ +.colstack_left { float: left; width: 30%; margin-right: 8px; } -.colstack_right -{ +.colstack_right { float: left; width: 65%; width: calc(70% - 15px); } -.colstack_item -{ +.colstack_item { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -205,6 +187,7 @@ li a /*grid-gap: 15px;*/ grid-gap: 12px; margin-left: 5px; + margin-top: 2px; } .grid_item { border: 1px solid #ccc; @@ -224,7 +207,7 @@ li a } .grid_istat { /*margin-bottom: 10px;*/ - margin-bottom: 5px; + margin-bottom: 3px; } .stat_green { background-color: lightgreen; border-color: lightgreen; } @@ -232,29 +215,19 @@ li a .stat_red { background-color: #ffb2b2; border-color: #ffb2b2; } .stat_disabled { background-color: lightgray; border-color: lightgray; } -.rowhead { font-family: cursive; } -.rowitem -{ +.rowitem { width: 100%; padding-left: 8px; padding-right: 8px; padding-top: 12px; padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; background-color: white; + font-family: cursive; } -.rowitem.passive -{ - font-weight: normal; - text-transform: none; -} -.rowitem:not(:last-child) -{ +.rowitem:not(:last-child) { border-bottom: 1px dotted #ccc; } -.rowitem a -{ +.rowitem a { text-decoration: none; color: black; } @@ -262,39 +235,7 @@ li a .top_post { margin-bottom: 16px; } .opthead { display: none; } -.col_left -{ - width: 30%; - float: left; -} -.col_right -{ - width: 69%; - overflow: hidden; -} -.colitem -{ - padding-left: 8px; - padding-right: 8px; - padding-top: 17px; - padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; -} -.colitem.passive -{ - font-weight: normal; - text-transform: none; -} -.colitem a -{ - text-decoration: none; - color: black; -} -.colitem a:hover { color: silver; } - -.formrow -{ +.formrow { width: 100%; background-color: white; } @@ -305,49 +246,51 @@ li a display: table; } .formrow:after { clear: both; } +.formrow:not(:last-child) { border-bottom: 1px dotted #ccc; } -.formrow:not(:last-child) -{ - border-bottom: 1px dotted #ccc; -} - -.formitem -{ +.formitem { float: left; - padding-left: 8px; - padding-right: 8px; - padding-top: 13px; - padding-bottom: 8px; - font-weight: bold; + padding: 10px; + min-width: 20%; + /*font-size: 17px;*/ + font-weight: normal; } - -.formitem:first-child { font-weight: bold; } .formitem:not(:last-child) { border-right: 1px dotted #ccc; } .formitem.invisible_border { border: none; } /* Mostly for textareas */ .formitem:only-child { width: 100%; } -.formitem textarea -{ +.formitem textarea { width: 100%; height: 100px; outline-color: #8e8e8e; } -.formitem:has-child() -{ +.formitem:has-child() { margin: 0 auto; float: none; } +.formitem:not(:only-child) input, .formitem:not(:only-child) select { padding: 3px;/*5px;*/ } +.formitem:not(:only-child).formlabel { + padding-top: 15px;/*18px;*/ + padding-bottom: 12px;/*16px;*/ + /*padding-left: 15px;*/ +} +.formbutton { + padding: 7px; + display: block; + margin-left: auto; + margin-right: auto; + font-size: 15px; + border-color: #ccc; +} -button -{ +button { background: white; border: 1px solid #8e8e8e; } /* Topics */ -.topic_status -{ +.topic_status { text-transform: none; margin-left: 8px; padding-left: 2px; @@ -360,8 +303,7 @@ button } .topic_status:empty { display: none; } -.username -{ +.username, .panel_tag { text-transform: none; margin-left: 0px; padding-left: 0px; @@ -372,13 +314,16 @@ button font-size: 15px; background: none; } -button.username -{ +button.username { position: relative; top: -0.25px; } .username.level { color: #303030; } -.username.real_username { color: #404040; font-size: 17px; padding-right: 4px; } +.username.real_username { + color: #404040; + font-size: 16px; + padding-right: 4px; +} .username.real_username:hover { color: black; } .tag-text { @@ -386,29 +331,18 @@ button.username display: inline-block; } -.post_item > .username { - padding-top: 23px; +.controls > .username { display: inline-block; -} - -.tag-mini -{ - text-transform: none; - margin-left: 0px; - padding-left: 3px; - padding-right: 3px; - padding-top: 1.5px; padding-bottom: 0px; - color: #505050; /* 80,80,80 */ - background-color: #FFFFFF; - border-style: dotted; - border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ - border-width: 1px; - font-size: 10px; } -.post_item > .mod_button > button { - font-size: 15px; +.real_username { + margin-right: -8px; +} + +.mod_button > button { + font-family: cursive; + font-size: 12px; color: #202020; opacity: 0.7; border: none; @@ -417,6 +351,60 @@ button.username opacity: 0.9; } +.mod_button:not(:last-child) { + margin-right: 4px; +} + +.like_label:before { + content: "+1"; +} +.like_count_label:before { + content: "likes"; +} +.like_count_label { + color: #202020; + opacity: 0.7; + font-size: 12px; +} +.like_count { + color: #202020; + opacity: 0.7; + padding-left: 1px; + padding-right: 2px; + font-size: 12px; +} +.like_count:before { + content: "|"; + margin-right: 5px; +} +.edit_label:before { + content: "Edit"; +} +.trash_label:before { + content: "Delete"; +} +.pin_label:before { + content: "Pin"; +} +.unpin_label:before { + content: "Unpin"; +} +.flag_label:before { + content: "Flag"; +} +.level_label { + margin-right: 1px; +} +.level_label:before { + content: "Level"; +} + +.controls { + margin-top: 23px; + display: inline-block; + width: 100%; +} + .action_item { padding: 14px; text-align: center; @@ -433,37 +421,34 @@ button.username margin-bottom: 8px; } -.mention { - font-weight: bold; -} - .level { float: right; - color: #505050; border-left: none; padding-left: 3px; padding-right: 5px; - font-size: 16px; + font-family: cursive; + font-size: 15px; + color: #202020; + opacity: 0.7; + border: none; } +.mention { font-weight: bold; } .show_on_edit { display: none; } -.alert -{ +.alert { display: block; padding: 5px; margin-bottom: 10px; border: 1px solid #ccc; } -.alert_success -{ +.alert_success { display: block; padding: 5px; border: 1px solid A2FC00; margin-bottom: 10px; background-color: DAF7A6; } -.alert_error -{ +.alert_error { display: block; padding: 5px; border: 1px solid #FF004B; @@ -495,6 +480,104 @@ button.username .prev_button { left: 14px; } .next_button { right: 14px; } +.head_tag_upshift { + color: #202020; + opacity: 0.7; + font-size: 12px; +} + +/* Control Panel */ + +.tag-mini { + margin-left: 0px; + padding-left: 0px; + padding-right: 0px; + padding-top: 2px; + padding-bottom: 2px; + + font-family: cursive; + font-size: 12px; + color: #202020; + opacity: 0.7; +} + +.panel_floater { + float: right; +} +#panel_groups > .rowitem > .panel_floater { + float: none; +} +#panel_groups > .rowitem > .panel_floater > .panel_right_button { + float: right; +} +#panel_forums > .rowitem > .panel_floater { + float: none; +} +#panel_forums > .rowitem > .panel_floater > .panel_buttons { + float: right; +} +#panel_forums > .rowitem > .panel_floater > .panel_buttons > .panel_right_button { + color: #505050; + font-size: 14px; +} +.panel_rank_tag, .forum_preset, .forum_active { + float: none; + color: #202020; + opacity: 0.7; + font-size: 10px; +} +.panel_rank_tag_admin:before { + content: "Admin Group"; +} +.panel_rank_tag_mod:before { + content: "Mod Group"; +} +.panel_rank_tag_banned:before { + content: "Banned Group"; +} +.panel_rank_tag_guest:before { + content: "Guest Group"; +} +.panel_rank_tag_member:before { + content: "Member Group"; +} + +.forum_preset_announce:after { + content: "Announcements"; +} +.forum_preset_members:after { + content: "Member Only"; +} +.forum_preset_staff:after { + content: "Staff Only"; +} +.forum_preset_admins:after { + content: "Admin Only"; +} +.forum_preset_archive:after { + content: "Archive"; +} +.forum_preset_all:after { + content: "Public"; +} +.forum_preset_custom, .forum_preset_ { + display: none !important; +} +.forum_active_Hide:before { + content: "Hidden"; +} +.forum_active_Hide + .forum_preset:before { + content: " | "; +} +.forum_active_Show { + display: none !important; +} +@media(max-width: 1300px) { + .theme_row { + background-image: none !important; + } +} + @media (max-width: 880px) { li { height: 29px; @@ -514,18 +597,21 @@ button.username padding-right: 7px; font-size: 18px; } - - body { padding-left: 4px; padding-right: 4px; margin: 0px !important; width: 100% !important; height: 100% !important; overflow-x: hidden; } + + body { + padding-left: 4px; + padding-right: 4px; + margin: 0px !important; + width: 100% !important; + height: 100% !important; + overflow-x: hidden; + } .container { width: auto; } .selectedAlert .alertList { top: 37px; right: 4px; } } @media (max-width: 810px) { - .rowitem { text-transform: none; } - /*.rowhead { font-family: arial; } - .menu_left { font-family: arial; }*/ body { font-family: arial; } - .level { font-size: 17px; } } @media (max-width: 700px) { @@ -540,35 +626,56 @@ button.username .menu_left { padding-right: 5px; padding-top: 1px; } .menu_right { padding-right: 5px; } .menu_create_topic { display: none;} - + .menu_alerts { padding-left: 4px; padding-right: 4px; font-size: 16px; padding-top: 1px; } - .menu_alerts .alert_counter { - top: -23px; - left: 8px; - } + .menu_alerts .alert_counter { top: -23px; left: 8px; } .selectedAlert .alertList { top: 33px; } - + .hide_on_mobile { display: none; } .prev_button, .next_button { top: auto; bottom: 5px; } .colstack_grid { grid-template-columns: none; grid-gap: 8px; } .grid_istat { margin-bottom: 0px; } } +@media (max-width: 350px) { + .hide_on_micro { display: none !important; } +} + @media (max-width: 470px) { - .menu_overview { display: none; } - .menu_profile { display: none; } - .hide_on_micro { display: none; } - .post_container { - overflow: visible !important; + .menu_overview, .menu_profile, .hide_on_micro { display: none; } + .selectedAlert .alertList { + width: 135px; + margin-bottom: 5px; } + .alertItem.withAvatar { + background-size: 36px; + text-align: right; + padding-left: 10px; + height: 46px; + } + .alertItem { + padding: 8px; + } + .alertItem.withAvatar .text { + width: calc(100% - 20px); + height: 30px; + white-space: normal; + } + .alertItem .text { + font-size: 10px; + font-weight: bold; + margin-left: 0px; + } + + .post_container { overflow: visible !important; } .post_item { background-position: 0px 2px !important; - background-size: 64px 64px !important; + background-size: 64px auto !important; padding-left: 2px !important; min-height: 96px; position: relative !important; @@ -576,6 +683,7 @@ button.username .post_item > .user_content { margin-left: 75px !important; width: 100% !important; + min-height: 45px; } .post_item > .mod_button { float: right !important; @@ -583,9 +691,7 @@ button.username position: relative; top: -14px; } - .post_item > .mod_button > button { - opacity: 1; - } + .post_item > .mod_button > button { opacity: 1; } .post_item > .real_username { position: absolute; top: 70px; @@ -597,6 +703,11 @@ button.username font-size: 15px; text-align: center; } + .post_item > .controls { + margin-top: 0px; + margin-left: 74px; + width: calc(100% - 74px); + } .container { width: 100% !important; } } diff --git a/themes/tempra-cursive/tempra-cursive.png b/themes/tempra-cursive/tempra-cursive.png index fed58034..4d731aae 100644 Binary files a/themes/tempra-cursive/tempra-cursive.png and b/themes/tempra-cursive/tempra-cursive.png differ diff --git a/themes/tempra-cursive/theme.json b/themes/tempra-cursive/theme.json index a6c91fe1..c9fee6cd 100644 --- a/themes/tempra-cursive/theme.json +++ b/themes/tempra-cursive/theme.json @@ -1,10 +1,10 @@ { "Name": "tempra-cursive", "FriendlyName": "Tempra Cursive", - "Version": "0.0.1", + "Version": "0.1.0-dev", "Creator": "Azareal", "FullImage": "tempra-cursive.png", "ForkOf": "tempra-simple", - "Tag": "🏗️", - "MobileFriendly": true -} \ No newline at end of file + "MobileFriendly": true, + "URL": "github.com/Azareal/Gosora" +} diff --git a/themes/tempra-simple/public/main.css b/themes/tempra-simple/public/main.css index ec37cd8b..889c4b54 100644 --- a/themes/tempra-simple/public/main.css +++ b/themes/tempra-simple/public/main.css @@ -4,8 +4,7 @@ -webkit-box-sizing: border-box; } -body -{ +body { font-family: arial; padding-bottom: 8px; } @@ -15,10 +14,7 @@ body .user_content { font-family: Segoe UI Emoji, arial; } } -/*.move_left{float: left;position: relative;left: 50%;} -.move_right{float: left;position: relative;left: -50%;}*/ -ul -{ +ul { padding-left: 0px; padding-right: 0px; height: 36px; @@ -27,29 +23,25 @@ ul background-color: white; margin-bottom: 12px; } -li -{ +li { height: 35px; padding-left: 10px; padding-top: 8px; padding-bottom: 8px; } li:hover { background: rgb(250,250,250); } -li a -{ +li a { text-decoration: none; /*color: #515151;*/ color: black; font-size: 17px; } -.menu_left -{ +.menu_left { float: left; border-right: 1px solid #ccc; padding-right: 10px; } -.menu_right -{ +.menu_right { float: right; border-left: 1px solid #ccc; padding-right: 10px; @@ -89,7 +81,6 @@ li a } .menu_alerts .alertList { display: none; - text-transform: none; } .selectedAlert .alertList { position: absolute; @@ -98,24 +89,27 @@ li a background: white; font-size: 10px; line-height: 16px; - width: 135px; + width: 300px; right: calc(5% + 7px); border-top: 1px solid #ccc; border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; + margin-bottom: 10px; } .alertItem { padding: 8px; overflow: hidden; text-overflow: ellipsis; + padding-top: 15px; + padding-bottom: 16px; } .alertItem.withAvatar { - background-size: auto 56px; + background-size: 60px; background-repeat: no-repeat; - text-align: right; padding-right: 12px; - height: 46px; + padding-left: 68px; + height: 50px; } .alertItem.withAvatar:not(:last-child) { border-bottom: 1px solid rgb(230,230,230); @@ -124,24 +118,24 @@ li a overflow: hidden; text-overflow: ellipsis; float: right; - width: calc(100% - 20px); - height: 30px; + height: 40px; + width: 100%; + white-space: nowrap; } .alertItem .text { - font-size: 10px; - font-weight: bold; + font-size: 13px; + font-weight: normal; + margin-left: 5px; } -.container -{ +.container { width: 90%; padding: 0px; margin-left: auto; margin-right: auto; } -.rowblock -{ +.rowblock { border: 1px solid #ccc; width: 100%; padding: 0px; @@ -149,8 +143,7 @@ li a } .rowblock:empty { display: none; } -.colblock_left -{ +.colblock_left { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -158,8 +151,7 @@ li a float: left; margin-right: 8px; } -.colblock_right -{ +.colblock_right { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -167,24 +159,20 @@ li a overflow: hidden; word-wrap: break-word; } -.colblock_left:empty { display: none; } -.colblock_right:empty { display: none; } +.colblock_left:empty, .colblock_right:empty { display: none; } /* The new method of doing columns layouts, colblock is now deprecated :( */ -.colstack_left -{ +.colstack_left { float: left; width: 30%; margin-right: 8px; } -.colstack_right -{ +.colstack_right { float: left; width: 65%; width: calc(70% - 15px); } -.colstack_item -{ +.colstack_item { border: 1px solid #ccc; padding: 0px; padding-top: 0px; @@ -203,6 +191,7 @@ li a /*grid-gap: 15px;*/ grid-gap: 12px; margin-left: 5px; + margin-top: 2px; } .grid_item { border: 1px solid #ccc; @@ -230,28 +219,26 @@ li a .stat_red { background-color: #ffb2b2; border-color: #ffb2b2; } .stat_disabled { background-color: lightgray; border-color: lightgray; } -.rowitem -{ +.rowitem { width: 100%; - padding-left: 8px; + /*padding-left: 8px; padding-right: 8px; padding-top: 17px; + padding-bottom: 12px;*/ + padding-left: 10px; + padding-top: 14px; padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; + padding-right: 10px; + /*font-weight: bold;*/ background-color: white; } -.rowitem.passive -{ - font-weight: normal; - text-transform: none; -} -.rowitem:not(:last-child) -{ +/*.rowitem:not(.passive) { + font-size: 17px; +}*/ +.rowitem:not(:last-child) { border-bottom: 1px dotted #ccc; } -.rowitem a -{ +.rowitem a { text-decoration: none; color: black; } @@ -259,31 +246,7 @@ li a .top_post { margin-bottom: 12px; } .opthead { display: none; } -.col_left -{ - width: 30%; - float: left; -} -.col_right -{ - width: 69%; - overflow: hidden; -} -.colitem -{ - padding-left: 8px; - padding-right: 8px; - padding-top: 17px; - padding-bottom: 12px; - font-weight: bold; - text-transform: uppercase; -} -.colitem.passive { font-weight: normal; text-transform: none; } -.colitem a { text-decoration: none; color: black; } -.colitem a:hover { color: silver; } - -.formrow -{ +.formrow { width: 100%; background-color: white; } @@ -296,43 +259,49 @@ li a .formrow:after { clear: both; } .formrow:not(:last-child) { border-bottom: 1px dotted #ccc; } -.formitem -{ +.formitem { float: left; - padding-left: 8px; - padding-right: 8px; - padding-top: 13px; - padding-bottom: 8px; - font-weight: bold; + padding: 10px; + min-width: 20%; + /*font-size: 17px;*/ + font-weight: normal; } - -.formitem:first-child { font-weight: bold; } .formitem:not(:last-child) { border-right: 1px dotted #ccc; } .formitem.invisible_border { border: none; } /* Mostly for textareas */ .formitem:only-child { width: 100%; } -.formitem textarea -{ +.formitem textarea { width: 100%; height: 100px; outline-color: #8e8e8e; } -.formitem:has-child() -{ +.formitem:has-child() { margin: 0 auto; float: none; } +.formitem:not(:only-child) input, .formitem:not(:only-child) select { padding: 3px;/*5px;*/ } +.formitem:not(:only-child).formlabel { + padding-top: 15px;/*18px;*/ + padding-bottom: 12px;/*16px;*/ + /*padding-left: 15px;*/ +} +.formbutton { + padding: 7px; + display: block; + margin-left: auto; + margin-right: auto; + font-size: 15px; + border-color: #ccc; +} -button -{ +button { background: white; border: 1px solid #8e8e8e; } /* Topics */ -.topic_status -{ +.topic_status { text-transform: none; margin-left: 8px; padding-left: 2px; @@ -345,8 +314,7 @@ button } .topic_status:empty { display: none; } -.username -{ +.username, .panel_tag { text-transform: none; margin-left: 0px; padding-left: 4px; @@ -370,8 +338,7 @@ button.username { position: relative; top: -0.25px; } display: inline-block; } -.tag-mini -{ +.tag-mini { text-transform: none; margin-left: 0px; padding-left: 3px; @@ -395,6 +362,55 @@ button.username { position: relative; top: -0.25px; } opacity: 0.9; } +.mod_button { + margin-right: 4px; +} + +.like_label:before, .like_count_label:before { + content: "😀"; +} +.like_count_label { + color: #505050; + float: right; + opacity: 0.85; + margin-left: 5px; +} +.like_count { + float: right; + color: #505050; + border-left: none; + padding-left: 5px; + padding-right: 5px; + font-size: 17px; +} +.edit_label:before { + content: "🖊️"; +} +.trash_label:before { + content: "🗑️"; +} +.pin_label:before { + content: "📌"; +} +.unpin_label:before { + content: "📌"; +} +.unpin_label { + background-color: #D6FFD6; +} +.flag_label:before { + content: "🚩"; +} +.level_label:before { + content: "👑"; +} + +.controls { + margin-top: 23px; + display: inline-block; + width: 100%; +} + .action_item { padding: 14px; text-align: center; @@ -411,10 +427,6 @@ button.username { position: relative; top: -0.25px; } margin-bottom: 8px; } -.mention { - font-weight: bold; -} - .level { float: right; color: #505050; @@ -424,24 +436,23 @@ button.username { position: relative; top: -0.25px; } font-size: 17px; } +.mention { font-weight: bold; } .show_on_edit { display: none; } -.alert -{ + +.alert { display: block; padding: 5px; margin-bottom: 10px; border: 1px solid #ccc; } -.alert_success -{ +.alert_success { display: block; padding: 5px; border: 1px solid A2FC00; margin-bottom: 10px; background-color: DAF7A6; } -.alert_error -{ +.alert_error { display: block; padding: 5px; border: 1px solid #FF004B; @@ -472,6 +483,72 @@ button.username { position: relative; top: -0.25px; } } .prev_button { left: 14px; } .next_button { right: 14px; } +.head_tag_upshift { + float: right; + position: relative; + top: -2px; +} + +/* Control Panel */ + +.panel_upshift { + font-size: 18px; + position: relative; + top: -2px; +} +.panel_upshift:visited { + color: black; +} +/*.panel_tag_upshift { + margin-left: 2px; + position: relative; + top:-3px; + color: #505050; +}*/ + +.panel_floater { + float: right; +} +.panel_rank_tag_admin:before { + content: "👑"; +} +.panel_rank_tag_mod:before { + content: "👮"; +} +.panel_rank_tag_banned:before { + content: "⛓️"; +} +.panel_rank_tag_guest:before { + content: "👽"; +} +.panel_rank_tag_member:before { + content: "👪"; +} + +.forum_preset_announce:before { + content: "📣"; +} +.forum_preset_members:before { + content: "👪"; +} +.forum_preset_staff:before { + content: "👮"; +} +.forum_preset_admins:before { + content: "👑"; +} +.forum_preset_archive:before { + content: "☠️"; +} +.forum_preset_all, .forum_preset_custom, .forum_preset_ { + display: none !important; +} +.forum_active_Hide:before { + content: "🕵️"; +} +.forum_active_Show { + display: none !important; +} @media (max-width: 880px) { li { @@ -492,7 +569,7 @@ button.username { position: relative; top: -0.25px; } padding-right: 7px; font-size: 18px; } - + body { padding-left: 4px; padding-right: 4px; @@ -505,10 +582,6 @@ button.username { position: relative; top: -0.25px; } .selectedAlert .alertList { top: 37px; right: 4px; } } -@media (max-width: 810px) { - .rowitem { text-transform: none; } -} - @media (max-width: 680px) { li { padding-left: 5px; @@ -521,7 +594,7 @@ button.username { position: relative; top: -0.25px; } .menu_left { padding-right: 7px; } .menu_right { padding-right: 7px; } .menu_create_topic { display: none;} - + .menu_alerts { padding-left: 4px; padding-right: 4px; @@ -529,7 +602,7 @@ button.username { position: relative; top: -0.25px; } padding-top: 1px; } .selectedAlert .alertList { top: 33px; } - + .hide_on_mobile { display: none !important; } .prev_button, .next_button { top: auto; bottom: 5px; } .colstack_grid { grid-template-columns: none; grid-gap: 8px; } @@ -538,6 +611,30 @@ button.username { position: relative; top: -0.25px; } @media (max-width: 470px) { .menu_overview, .menu_profile { display: none; } + .selectedAlert .alertList { + width: 135px; + margin-bottom: 5px; + } + .alertItem.withAvatar { + background-size: 36px; + text-align: right; + padding-left: 10px; + height: 46px; + } + .alertItem { + padding: 8px; + } + .alertItem.withAvatar .text { + width: calc(100% - 20px); + height: 30px; + white-space: normal; + } + .alertItem .text { + font-size: 10px; + font-weight: bold; + margin-left: 0px; + } + .hide_on_micro { display: none !important; } .post_container { overflow: visible !important; } .post_item:not(.action_item) { @@ -552,33 +649,49 @@ button.username { position: relative; top: -0.25px; } width: 100% !important; min-height: 45px; } - .post_item > .mod_button { + .post_item > .controls > .mod_button { float: right !important; margin-left: 2px !important; + margin-right: 3px; } - .post_item > .mod_button > button { opacity: 1; } - .post_item > .real_username { - /*position: absolute; - top: 70px; - float: left; - margin-top: -2px;*/ + .post_item > .controls > .mod_button > button { + opacity: 1; + padding-left: 3px; + padding-right: 3px; + } + .post_item > .controls > .real_username { margin-top: 0px; - /*padding-top: 3px !important; - margin-right: 2px; - width: 60px;*/ - margin-left: 74px; margin-right: 0px; font-size: 15px; - /*text-align: center;*/ color: black; max-width: 61px; - /*overflow: hidden;*/ text-overflow: ellipsis; } + .post_item > .controls { + margin-top: 0px; + margin-left: 74px; + width: calc(100% - 74px); + } .container { width: 100% !important; } } @media (max-width: 330px) { li { padding-left: 6px; } .menu_left { padding-right: 6px; } + .post_item > .controls > .real_username { + display: inline-block; + overflow: hidden; + margin-right: -3px; + text-overflow: clip; + max-width: 84px; + } + .post_item > .controls { + margin-left: 72px; + } + .top_post > .post_item > .controls > .real_username { + max-width: 57px; + } + .top_post > .post_item { + padding-right: 4px; + } } diff --git a/themes/tempra-simple/theme.json b/themes/tempra-simple/theme.json index 8458126d..d15ad0e8 100644 --- a/themes/tempra-simple/theme.json +++ b/themes/tempra-simple/theme.json @@ -1,8 +1,9 @@ { "Name": "tempra-simple", "FriendlyName": "Tempra Simple", - "Version": "0.0.1", + "Version": "0.1.0-dev", "Creator": "Azareal", "FullImage": "tempra-simple.png", - "MobileFriendly": true -} \ No newline at end of file + "MobileFriendly": true, + "URL": "github.com/Azareal/Gosora" +}