aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFChannel0 <77419041+FChannel0@users.noreply.github.com>2021-08-20 01:35:26 -0700
committerGitHub <noreply@github.com>2021-08-20 01:35:26 -0700
commit502558e0bdaf67ca4c012fc1983f42430b8854cd (patch)
treed66b015274b962fedb28c52c0efaaa068368f2b1
parent21917eb2ea72fe40d70c2c991e821aace5430c23 (diff)
parenta497499817cbf72b295253e1a2bb1011d121ba28 (diff)
Merge pull request #52 from KushBlazingJudah/development
Themes
-rw-r--r--activityPubStruct.go20
-rw-r--r--cacheDatabase.go8
-rw-r--r--client.go126
-rw-r--r--database.go8
-rw-r--r--follow.go2
-rw-r--r--main.go62
-rw-r--r--static/archive.html2
-rw-r--r--static/bottom.html23
-rw-r--r--static/css/themes/default.css162
-rw-r--r--static/css/themes/gruvbox.css140
-rw-r--r--static/index.html40
-rw-r--r--static/js/posts.js26
-rw-r--r--static/js/themes.js40
-rw-r--r--static/main.html92
-rw-r--r--static/manage.html6
-rw-r--r--static/nadmin.html8
-rw-r--r--static/ncatalog.html63
-rw-r--r--static/nposts.html30
-rw-r--r--static/posts.html12
-rw-r--r--static/top.html130
20 files changed, 706 insertions, 294 deletions
diff --git a/activityPubStruct.go b/activityPubStruct.go
index 459259a..8676b12 100644
--- a/activityPubStruct.go
+++ b/activityPubStruct.go
@@ -1,6 +1,8 @@
package main
import (
+ "time"
+
"encoding/json"
"html/template"
)
@@ -19,7 +21,7 @@ type ActivityRaw struct {
ToRaw json.RawMessage `json:"to,omitempty"`
BtoRaw json.RawMessage `json:"bto,omitempty"`
CcRaw json.RawMessage `json:"cc,omitempty"`
- Published string `json:"published,omitempty"`
+ Published time.Time `json:"published,omitempty"`
ActorRaw json.RawMessage `json:"actor,omitempty"`
ObjectRaw json.RawMessage `json:"object,omitempty"`
}
@@ -97,11 +99,11 @@ type Activity struct {
Name string `json:"name,omitempty"`
Summary string `json:"summary,omitempty"`
Auth string `json:"auth,omitempty"`
- To []string `json:"to, omitempty"`
+ To []string `json:"to,omitempty"`
Bto []string `json:"bto,omitempty"`
- Cc []string `json:"cc, omitempty"`
- Published string `json:"published,omitempty"`
- Object *ObjectBase `json:"object, omitempty"`
+ Cc []string `json:"cc,omitempty"`
+ Published time.Time `json:"published,omitempty"`
+ Object *ObjectBase `json:"object,omitempty"`
}
type ObjectBase struct {
@@ -123,8 +125,8 @@ type ObjectBase struct {
InReplyTo []ObjectBase `json:"inReplyTo,omitempty"`
Location string `json:"location,omitempty"`
Preview *NestedObjectBase `json:"preview,omitempty"`
- Published string `json:"published,omitempty"`
- Updated string `json:"updated,omitempty"`
+ Published time.Time `json:"published,omitempty"`
+ Updated time.Time `json:"updated,omitempty"`
Object *NestedObjectBase `json:"object,omitempty"`
Attachment []ObjectBase `json:"attachment,omitempty"`
Replies *CollectionBase `json:"replies,omitempty"`
@@ -169,13 +171,13 @@ type NestedObjectBase struct {
InReplyTo []ObjectBase `json:"inReplyTo,omitempty"`
Location string `json:"location,omitempty"`
Preview ObjectBase `json:"preview,omitempty"`
- Published string `json:"published,omitempty"`
+ Published time.Time `json:"published,omitempty"`
Attachment []ObjectBase `json:"attachment,omitempty"`
Replies *CollectionBase `json:"replies,omitempty"`
StartTime string `json:"startTime,omitempty"`
Summary string `json:"summary,omitempty"`
Tag []ObjectBase `json:"tag,omitempty"`
- Updated string `json:"updated,omitempty"`
+ Updated time.Time `json:"updated,omitempty"`
Deleted string `json:"deleted,omitempty"`
Url []ObjectBase `json:"url,omitempty"`
Href string `json:"href,omitempty"`
diff --git a/cacheDatabase.go b/cacheDatabase.go
index ffe5dad..d735cfe 100644
--- a/cacheDatabase.go
+++ b/cacheDatabase.go
@@ -92,7 +92,7 @@ func WriteActivitytoCache(db *sql.DB, obj ObjectBase) {
return
}
- if obj.Updated == "" {
+ if obj.Updated.IsZero() {
obj.Updated = obj.Published
}
@@ -127,7 +127,7 @@ func WriteActivitytoCacheWithAttachment(db *sql.DB, obj ObjectBase, attachment O
return
}
- if obj.Updated == "" {
+ if obj.Updated.IsZero() {
obj.Updated = obj.Published
}
@@ -158,7 +158,7 @@ func WriteAttachmentToCache(db *sql.DB, obj ObjectBase) {
return
}
- if obj.Updated == "" {
+ if obj.Updated.IsZero() {
obj.Updated = obj.Published
}
@@ -189,7 +189,7 @@ func WritePreviewToCache(db *sql.DB, obj NestedObjectBase) {
return
}
- if obj.Updated == "" {
+ if obj.Updated.IsZero() {
obj.Updated = obj.Published
}
diff --git a/client.go b/client.go
index 85a327e..09db0bf 100644
--- a/client.go
+++ b/client.go
@@ -5,6 +5,7 @@ import (
"fmt"
_ "github.com/lib/pq"
"html/template"
+ "log"
"net/http"
"regexp"
"sort"
@@ -53,6 +54,7 @@ type PageData struct {
ReturnTo string
NewsItems []NewsItem
BoardRemainer []int
+ Themes *[]string
}
type AdminPage struct {
@@ -68,6 +70,7 @@ type AdminPage struct {
IsLocal bool
PostBlacklist []PostBlacklist
AutoSubscribe bool
+ Themes *[]string
}
type Report struct {
@@ -93,11 +96,31 @@ type PostBlacklist struct {
Regex string
}
+func mod(i, j int) bool {
+ return i%j == 0
+}
+
+func sub(i, j int) int {
+ return i - j
+}
+
+func unixToReadable(u int) string {
+ return time.Unix(int64(u), 0).Format("Jan 02, 2006")
+}
+
+func timeToReadableLong(t time.Time) string {
+ return t.Format("01/02/06(Mon)15:04:05")
+}
+
+func timeToUnix(t time.Time) string {
+ return fmt.Sprint(t.Unix())
+}
+
func IndexGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
t := template.Must(template.New("").Funcs(template.FuncMap{
- "mod": func(i, j int) bool { return i%j == 0 },
- "sub": func(i, j int) int { return i - j },
- "unixtoreadable": func(u int) string { return time.Unix(int64(u), 0).Format("Jan 02, 2006") }}).ParseFiles("./static/main.html", "./static/index.html"))
+ "mod": mod,
+ "sub": sub,
+ "unixtoreadable": unixToReadable}).ParseFiles("./static/main.html", "./static/index.html"))
actor := GetActorFromDB(db, Domain)
@@ -122,13 +145,19 @@ func IndexGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
data.InstanceIndex = GetCollectionFromReq("https://fchan.xyz/followers").Items
data.NewsItems = getNewsFromDB(db, 3)
- t.ExecuteTemplate(w, "layout", data)
+ data.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", data)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("IndexGet: %s\n", err)
+ }
}
func NewsGet(w http.ResponseWriter, r *http.Request, db *sql.DB, timestamp int) {
t := template.Must(template.New("").Funcs(template.FuncMap{
- "sub": func(i, j int) int { return i - j },
- "unixtoreadable": func(u int) string { return time.Unix(int64(u), 0).Format("Jan 02, 2006") }}).ParseFiles("./static/main.html", "./static/news.html"))
+ "sub": mod,
+ "unixtoreadable": unixToReadable}).ParseFiles("./static/main.html", "./static/news.html"))
actor := GetActorFromDB(db, Domain)
@@ -155,14 +184,20 @@ func NewsGet(w http.ResponseWriter, r *http.Request, db *sql.DB, timestamp int)
data.Title = actor.PreferredUsername + ": " + data.NewsItems[0].Title
- t.ExecuteTemplate(w, "layout", data)
+ data.Themes = &Themes
+
+ err = t.ExecuteTemplate(w, "layout", data)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("NewsGet: %s\n", err)
+ }
}
func AllNewsGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
t := template.Must(template.New("").Funcs(template.FuncMap{
- "mod": func(i, j int) bool { return i%j == 0 },
- "sub": func(i, j int) int { return i - j },
- "unixtoreadable": func(u int) string { return time.Unix(int64(u), 0).Format("Jan 02, 2006") }}).ParseFiles("./static/main.html", "./static/anews.html"))
+ "mod": mod,
+ "sub": sub,
+ "unixtoreadable": unixToReadable}).ParseFiles("./static/main.html", "./static/anews.html"))
actor := GetActorFromDB(db, Domain)
@@ -179,7 +214,13 @@ func AllNewsGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
data.Board.Restricted = actor.Restricted
data.NewsItems = getNewsFromDB(db, 0)
- t.ExecuteTemplate(w, "layout", data)
+ data.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", data)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("AllNewsGet: %s\n", err)
+ }
}
func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Collection) {
@@ -216,13 +257,15 @@ func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Co
"parseReplyLink": func(actorId string, op string, id string, content string) template.HTML {
actor := FingerActor(actorId)
title := strings.ReplaceAll(ParseLinkTitle(actor.Id, op, content), `/\&lt;`, ">")
- link := "<a href=\"" + actor.Name + "/" + shortURL(actor.Outbox, op) + "#" + shortURL(actor.Outbox, id) + "\" title=\"" + title + "\">&gt;&gt;" + shortURL(actor.Outbox, id) + "</a>"
+ link := "<a href=\"" + actor.Name + "/" + shortURL(actor.Outbox, op) + "#" + shortURL(actor.Outbox, id) + "\" title=\"" + title + "\" class=\"replyLink\">&gt;&gt;" + shortURL(actor.Outbox, id) + "</a>"
return template.HTML(link)
},
"add": func(i, j int) int {
return i + j
},
- "sub": func(i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/nposts.html", "./static/top.html", "./static/bottom.html", "./static/posts.html"))
+ "timeToReadableLong": timeToReadableLong,
+ "timeToUnix": timeToUnix,
+ "sub": sub}).ParseFiles("./static/main.html", "./static/nposts.html", "./static/top.html", "./static/bottom.html", "./static/posts.html"))
actor := collection.Actor
@@ -271,7 +314,13 @@ func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Co
returnData.Pages = pages
returnData.TotalPage = len(returnData.Pages) - 1
- t.ExecuteTemplate(w, "layout", returnData)
+ returnData.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", returnData)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("OutboxGet: %s\n", err)
+ }
}
func CatalogGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Collection) {
@@ -296,7 +345,7 @@ func CatalogGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection C
}
return false
},
- "sub": func(i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/ncatalog.html", "./static/top.html"))
+ "sub": sub}).ParseFiles("./static/main.html", "./static/ncatalog.html", "./static/top.html"))
actor := collection.Actor
@@ -326,7 +375,13 @@ func CatalogGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection C
returnData.Posts = collection.OrderedItems
- t.ExecuteTemplate(w, "layout", returnData)
+ returnData.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", returnData)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("CatalogGet: %s\n", err)
+ }
}
func ArchiveGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Collection) {
@@ -343,8 +398,8 @@ func ArchiveGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection C
"parseAttachment": func(obj ObjectBase, catalog bool) template.HTML {
return ParseAttachment(obj, catalog)
},
- "mod": func(i, j int) bool { return i%j == 0 },
- "sub": func(i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/archive.html", "./static/bottom.html"))
+ "mod": mod,
+ "sub": sub}).ParseFiles("./static/main.html", "./static/archive.html", "./static/bottom.html"))
actor := collection.Actor
@@ -374,7 +429,13 @@ func ArchiveGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection C
returnData.Posts = collection.OrderedItems
- t.ExecuteTemplate(w, "layout", returnData)
+ returnData.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", returnData)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("ArchiveGet: %s\n", err)
+ }
}
func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
@@ -403,10 +464,12 @@ func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
"parseReplyLink": func(actorId string, op string, id string, content string) template.HTML {
actor := FingerActor(actorId)
title := strings.ReplaceAll(ParseLinkTitle(actor.Id, op, content), `/\&lt;`, ">")
- link := "<a href=\"" + actor.Name + "/" + shortURL(actor.Outbox, op) + "#" + shortURL(actor.Outbox, id) + "\" title=\"" + title + "\">&gt;&gt;" + shortURL(actor.Outbox, id) + "</a>"
+ link := "<a href=\"" + actor.Name + "/" + shortURL(actor.Outbox, op) + "#" + shortURL(actor.Outbox, id) + "\" title=\"" + title + "\" class=\"replyLink\">&gt;&gt;" + shortURL(actor.Outbox, id) + "</a>"
return template.HTML(link)
},
- "sub": func(i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/npost.html", "./static/top.html", "./static/bottom.html", "./static/posts.html"))
+ "timeToReadableLong": timeToReadableLong,
+ "timeToUnix": timeToUnix,
+ "sub": sub}).ParseFiles("./static/main.html", "./static/npost.html", "./static/top.html", "./static/bottom.html", "./static/posts.html"))
path := r.URL.Path
actor := GetActorFromPath(db, path, "/")
@@ -467,7 +530,13 @@ func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
returnData.PostId = shortURL(returnData.Board.To, returnData.Posts[0].Id)
}
- t.ExecuteTemplate(w, "layout", returnData)
+ returnData.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", returnData)
+ if err != nil {
+ // TODO: actual error handler
+ log.Printf("PostGet: %s\n", err)
+ }
}
func GetBoardCollection(db *sql.DB) []Board {
@@ -724,13 +793,13 @@ func GetActorsFollowPostFromId(db *sql.DB, actors []string, id string) Collectio
type ObjectBaseSortDesc []ObjectBase
func (a ObjectBaseSortDesc) Len() int { return len(a) }
-func (a ObjectBaseSortDesc) Less(i, j int) bool { return a[i].Updated > a[j].Updated }
+func (a ObjectBaseSortDesc) Less(i, j int) bool { return a[i].Updated.After(a[j].Updated) }
func (a ObjectBaseSortDesc) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type ObjectBaseSortAsc []ObjectBase
func (a ObjectBaseSortAsc) Len() int { return len(a) }
-func (a ObjectBaseSortAsc) Less(i, j int) bool { return a[i].Published < a[j].Published }
+func (a ObjectBaseSortAsc) Less(i, j int) bool { return a[i].Published.Before(a[j].Published) }
func (a ObjectBaseSortAsc) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type BoardSortAsc []Board
@@ -886,17 +955,12 @@ func ParseLinkComments(db *sql.DB, board Actor, op string, content string, threa
}
}
- var style string
- if board.Restricted {
- style = "color: #af0a0f;"
- }
-
//replace link with quote format
replyID, isReply := IsReplyToOP(db, op, parsedLink)
if isReply {
id := shortURL(board.Outbox, replyID)
- content = strings.Replace(content, match[i][0], "<a class=\"reply\" style=\""+style+"\" title=\""+quoteTitle+"\" href=\"/"+board.Name+"/"+shortURL(board.Outbox, op)+"#"+id+"\">&gt;&gt;"+id+""+isOP+"</a>", -1)
+ content = strings.Replace(content, match[i][0], "<a class=\"reply\" title=\""+quoteTitle+"\" href=\"/"+board.Name+"/"+shortURL(board.Outbox, op)+"#"+id+"\">&gt;&gt;"+id+""+isOP+"</a>", -1)
} else {
@@ -909,7 +973,7 @@ func ParseLinkComments(db *sql.DB, board Actor, op string, content string, threa
}
if actor.Id != "" {
- content = strings.Replace(content, match[i][0], "<a class=\"reply\" style=\""+style+"\" title=\""+quoteTitle+"\" href=\""+link+"\">&gt;&gt;"+shortURL(board.Outbox, parsedLink)+isOP+" →</a>", -1)
+ content = strings.Replace(content, match[i][0], "<a class=\"reply\" title=\""+quoteTitle+"\" href=\""+link+"\">&gt;&gt;"+shortURL(board.Outbox, parsedLink)+isOP+" →</a>", -1)
}
}
}
diff --git a/database.go b/database.go
index 0a99086..b0a5736 100644
--- a/database.go
+++ b/database.go
@@ -175,16 +175,16 @@ func WriteObjectToDB(db *sql.DB, obj ObjectBase) ObjectBase {
if len(obj.Attachment) > 0 {
if obj.Preview.Href != "" {
obj.Preview.Id = fmt.Sprintf("%s/%s", obj.Actor, CreateUniqueID(db, obj.Actor))
- obj.Preview.Published = time.Now().UTC().Format(time.RFC3339)
- obj.Preview.Updated = time.Now().UTC().Format(time.RFC3339)
+ obj.Preview.Published = time.Now().UTC()
+ obj.Preview.Updated = time.Now().UTC()
obj.Preview.AttributedTo = obj.Id
WritePreviewToDB(db, *obj.Preview)
}
for i, _ := range obj.Attachment {
obj.Attachment[i].Id = fmt.Sprintf("%s/%s", obj.Actor, CreateUniqueID(db, obj.Actor))
- obj.Attachment[i].Published = time.Now().UTC().Format(time.RFC3339)
- obj.Attachment[i].Updated = time.Now().UTC().Format(time.RFC3339)
+ obj.Attachment[i].Published = time.Now().UTC()
+ obj.Attachment[i].Updated = time.Now().UTC()
obj.Attachment[i].AttributedTo = obj.Id
WriteAttachmentToDB(db, obj.Attachment[i])
WriteActivitytoDBWithAttachment(db, obj, obj.Attachment[i], *obj.Preview)
diff --git a/follow.go b/follow.go
index 8dcd312..49558cd 100644
--- a/follow.go
+++ b/follow.go
@@ -214,8 +214,6 @@ func SetActorFollowerDB(db *sql.DB, activity Activity) Activity {
activity.Type = "Accept"
return activity
}
-
- return activity
}
func SetActorFollowingDB(db *sql.DB, activity Activity) Activity {
diff --git a/main.go b/main.go
index 6502cda..abce30d 100644
--- a/main.go
+++ b/main.go
@@ -13,12 +13,14 @@ import (
"html/template"
"io"
"io/ioutil"
+ "log"
"math/rand"
"mime/multipart"
"net/http"
"net/url"
"os"
"os/exec"
+ "path"
"regexp"
"strconv"
"strings"
@@ -29,6 +31,7 @@ var Port = ":" + GetConfigValue("instanceport", "3000")
var TP = GetConfigValue("instancetp", "")
var Instance = GetConfigValue("instance", "")
var Domain = TP + "" + Instance
+var TorInstance = IsOnion(Instance)
var authReq = []string{"captcha", "email", "passphrase"}
@@ -51,6 +54,8 @@ var MediaHashs = make(map[string]string)
var ActorCache = make(map[string]Actor)
+var Themes []string
+
func main() {
CreatedNeededDirectories()
@@ -84,6 +89,22 @@ func main() {
}
}
+ // get list of themes
+ themes, err := ioutil.ReadDir("./static/css/themes")
+ if err != nil {
+ panic(err)
+ }
+
+ for _, f := range themes {
+ if f.Name() == "default" {
+ continue
+ }
+
+ if e := path.Ext(f.Name()); e == ".css" {
+ Themes = append(Themes, strings.TrimSuffix(f.Name(), e))
+ }
+ }
+
// Allow access to public media folder
fileServer := http.FileServer(http.Dir("./public"))
http.Handle("/public/", http.StripPrefix("/public", neuter(fileServer)))
@@ -610,7 +631,13 @@ func main() {
adminData.AutoSubscribe = GetActorAutoSubscribeDB(db, actor.Id)
- t.ExecuteTemplate(w, "layout", adminData)
+ adminData.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", adminData)
+ if err != nil {
+ // TODO: actual error handling
+ log.Printf("mod page: %s\n", err)
+ }
} else if admin || actor.Id == Domain {
t := template.Must(template.New("").Funcs(template.FuncMap{
@@ -645,7 +672,13 @@ func main() {
adminData.PostBlacklist = GetRegexBlacklistDB(db)
- t.ExecuteTemplate(w, "layout", adminData)
+ adminData.Themes = &Themes
+
+ err := t.ExecuteTemplate(w, "layout", adminData)
+ if err != nil {
+ // TODO: actual error handling
+ log.Printf("mod page: %s\n", err)
+ }
}
})
@@ -960,9 +993,6 @@ func main() {
http.Redirect(w, r, "/"+board, http.StatusSeeOther)
return
}
-
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte(""))
})
http.HandleFunc("/deleteattach", func(w http.ResponseWriter, r *http.Request) {
@@ -1034,9 +1064,6 @@ func main() {
http.Redirect(w, r, OP, http.StatusSeeOther)
return
}
-
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte(""))
})
http.HandleFunc("/marksensitive", func(w http.ResponseWriter, r *http.Request) {
@@ -1091,9 +1118,6 @@ func main() {
http.Redirect(w, r, OP, http.StatusSeeOther)
return
}
-
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte(""))
})
http.HandleFunc("/remove", func(w http.ResponseWriter, r *http.Request) {
@@ -1148,9 +1172,6 @@ func main() {
http.Redirect(w, r, "/"+board, http.StatusSeeOther)
return
}
-
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte(""))
})
http.HandleFunc("/removeattach", func(w http.ResponseWriter, r *http.Request) {
@@ -1195,9 +1216,6 @@ func main() {
http.Redirect(w, r, OP, http.StatusSeeOther)
return
}
-
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte(""))
})
http.HandleFunc("/report", func(w http.ResponseWriter, r *http.Request) {
@@ -1621,8 +1639,8 @@ func CreateObject(objType string) ObjectBase {
var nObj ObjectBase
nObj.Type = objType
- nObj.Published = time.Now().UTC().Format(time.RFC3339)
- nObj.Updated = time.Now().UTC().Format(time.RFC3339)
+ nObj.Published = time.Now().UTC()
+ nObj.Updated = time.Now().UTC()
return nObj
}
@@ -1761,7 +1779,7 @@ func CreateAttachmentObject(file multipart.File, header *multipart.FileHeader) (
image.Href = Domain + "/" + tempFile.Name()
image.MediaType = contentType
image.Size = size
- image.Published = time.Now().UTC().Format(time.RFC3339)
+ image.Published = time.Now().UTC()
nAttachment = append(nAttachment, image)
@@ -1793,7 +1811,7 @@ func ParseCommentForReplies(db *sql.DB, comment string, op string) []ObjectBase
if isValid {
var reply = new(ObjectBase)
reply.Id = links[i]
- reply.Published = time.Now().UTC().Format(time.RFC3339)
+ reply.Published = time.Now().UTC()
validLinks = append(validLinks, *reply)
}
}
@@ -2378,7 +2396,7 @@ func ResizeAttachmentToPreview(db *sql.DB) {
var mediatype string
var name string
var size int
- var published string
+ var published time.Time
rows.Scan(&id, &href, &mediatype, &name, &size, &published)
diff --git a/static/archive.html b/static/archive.html
index b08693a..3e040bc 100644
--- a/static/archive.html
+++ b/static/archive.html
@@ -20,7 +20,7 @@
{{ end }}
{{ define "top" }}
-<h1 style="text-align: center; color: #af0a0f;">/{{ .Board.Name }}/ - {{ .Board.PrefName }}</h1>
+<h1>/{{ .Board.Name }}/ - {{ .Board.PrefName }}</h1>
<p style="text-align: center;">{{ .Board.Summary }}</p>
<h1 style="text-align: center;">Archived Posts</h1>
{{ end }}
diff --git a/static/bottom.html b/static/bottom.html
index 9d920c0..023deeb 100644
--- a/static/bottom.html
+++ b/static/bottom.html
@@ -1,20 +1,20 @@
{{ define "bottom" }}
<div id="reply-box" class="popup-box" style="display: none;">
- <div id="reply-header" style="display: inline-block; width: 370px; z-index: 0; cursor: move;"></div><div id="reply-close" style="display: inline-block; float: right;"><a href="javascript:closeReply()">[X]</a></div>
+ <div id="reply-header" style="display: inline-block; z-index: 0; cursor: move;"></div><div id="reply-close" style="display: inline-block; float: right;"><a href="javascript:closeReply()">[X]</a></div>
<form onsubmit="sessionStorage.setItem('element-closed-reply', true)" id="reply-post" action="/post" method="post" enctype="multipart/form-data">
<input id="reply-name" name="name" size="43" type="text" placeholder="Name" maxlength="100">
<input id="reply-options" name="options" size="43" type="text" placeholder="Options" maxlength="100">
- <textarea id="reply-comment" name="comment" rows="12" cols="54" style="width: 396px;" maxlength="2000" oninput="sessionStorage.setItem('element-reply-comment', document.getElementById('reply-comment').value)"></textarea>
+ <textarea id="reply-comment" name="comment" rows="12" cols="54" maxlength="2000" oninput="sessionStorage.setItem('element-reply-comment', document.getElementById('reply-comment').value)"></textarea>
<input id="reply-file" name="file" type="file">
- <input id="reply-submit" type="submit" value="Reply" style="float: right;"><br><br>
+ <input id="reply-submit" type="submit" value="Reply" style="float: right;">
<input type="hidden" id="inReplyTo-box" name="inReplyTo" value="{{ .Board.InReplyTo }}">
<input type="hidden" id="sendTo" name="sendTo" value="{{ .Board.To }}">
<input type="hidden" id="boardName" name="boardName" value="{{ .Board.Name }}">
<input type="hidden" id="captchaCode" name="captchaCode" value="{{ .Board.CaptchaCode }}">
- <input type="hidden" id="returnTo" name="returnTo" value="{{ .ReturnTo }}">
- <input type="checkbox" name="sensitive"><span>Mark attachment as sensitive</span><br><br>
+ <input type="hidden" id="returnTo" name="returnTo" value="{{ .ReturnTo }}"><br>
+ <input type="checkbox" name="sensitive"><span>Mark attachment as sensitive</span><br>
<div style="width: 202px; margin: 0 auto; padding-top: 12px;">
- <label for="captcha">Captcha:</label><br>
+ <label for="captcha">Captcha:</label><br>
<input style="display: inline-block;" type="text" id="captcha" name="captcha" autocomplete="off"><br>
</div>
<div style="width: 230px; margin: 0 auto;">
@@ -23,19 +23,20 @@
</form>
</div>
-<div id="report-box" class="popup-box" style="display: none; ">
- <div id="report-header" style="text-align: center; display: inline-block; width: 370px; z-index: 0; cursor: move;"></div><div id="report-close" style="display: inline-block; float: right;"><a href="javascript:closeReport()">[X]</a></div>
+<div id="report-box" class="popup-box" style="display: none;">
+ <div id="report-header" style="text-align: center; display: inline-block; z-index: 0; cursor: move;"></div><div id="report-close" style="display: inline-block; float: right;"><a href="javascript:closeReport()">[X]</a></div>
<form onsubmit="sessionStorage.setItem('element-closed-report', true)" id="report-post" action="/report" method="post">
- <label for="comment">Reason:</label>
+ <label for="comment">Reason:</label><br>
<textarea id="report-comment" name="comment" rows="12" cols="54" style="width: 396px;" maxlength="100" oninput="sessionStorage.setItem('element-report-comment', document.getElementById('report-comment').value)"></textarea>
+ <br>
<input id="report-submit" type="submit" value="Report" style="float: right;">
<input type="hidden" id="report-inReplyTo-box" name="id" value="{{ .Board.InReplyTo }}">
<input type="hidden" id="sendTo" name="sendTo" value="{{ .Board.To }}">
<input type="hidden" id="boardName" name="board" value="{{ .Board.Name }}">
- <input type="hidden" name="close" value="0">
+ <input type="hidden" name="close" value="0">
<input type="hidden" id="captchaCode" name="captchaCode" value="{{ .Board.CaptchaCode }}">
<div style="width: 202px; margin: 0 auto; padding-top: 12px;">
- <label for="captcha">Captcha:</label><br>
+ <label for="captcha">Captcha:</label><br>
<input style="display: inline-block;" type="text" id="captcha" name="captcha" autocomplete="off"><br>
</div>
<div style="width: 230px; margin: 0 auto;">
diff --git a/static/css/themes/default.css b/static/css/themes/default.css
new file mode 100644
index 0000000..24e85e6
--- /dev/null
+++ b/static/css/themes/default.css
@@ -0,0 +1,162 @@
+a, a:link, a:visited, a:hover, a:active {
+ text-decoration: none
+}
+
+a:link, a:visited, a:active {
+ color: black;
+}
+
+a:hover {
+ color: #de0808;
+}
+
+body {
+ background-color: #eef2fe;
+ color: black;
+}
+
+body.nsfw {
+ background-color: #ffffee;
+ color: #820404
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #af0a0f;
+}
+
+.popup-box {
+ border: 4px solid #d3caf0;
+ background-color: #eff5ff;
+}
+
+.nsfw .popup-box {
+ border: 4px solid #f0e2d9;
+ background-color: #f9f9e0;
+}
+
+.box {
+ background-color: #eff5ff;
+}
+
+.nsfw .box {
+ background-color: #f9f9e0;
+}
+
+.box-alt {
+ background-color: #d3caf0;
+}
+
+.nsfw .box-alt {
+ background-color: #f0e2d9;
+}
+
+
+.quote {
+ color: #789922;
+}
+
+.post {
+ background-color: #d5daf0;
+}
+
+.nsfw .post {
+ background-color: #f0e0d6;
+}
+
+:target > div > .post {
+ background-color: #d6bad0;
+}
+
+.nsfw :target > div > .post {
+ background-color: #f0c0b0;
+}
+
+.title {
+ color: #0f0c5d;
+}
+
+.name, .tripcode {
+ color: #117743;
+}
+
+a.reply {
+ color: #af0a0f;
+}
+
+.replyLink {
+ color: #000080;
+ font-size: 0.8em;
+}
+
+#newpostbtn {
+ text-align: center;
+ margin-top: 80px;
+}
+
+#postForm {
+ margin: auto;
+}
+
+#postForm tr > td:first-child {
+ background-color: #98e;
+ border: 1px black;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+
+.nsfw #postForm tr > td:first-child {
+ background-color: #ea8;
+}
+
+#postForm input[type="text"],
+#postForm textarea,
+#reply-name, #reply-options, #reply-comment {
+ box-sizing: border-box;
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing: border-box;
+}
+
+#reply-name, #reply-options, #reply-comment {
+ width: 100%;
+}
+
+#postForm #captcha {
+ display: block;
+ width: 100%;
+}
+
+.popup-box {
+ position: absolute;
+ width: min-content;
+ z-index: 9;
+ display: block;
+}
+
+/* TODO: rename */
+.box2 {
+ border: 4px solid #f0e2d9;
+ background-color: #f9f9e0;
+}
+
+.newsbox {
+ padding: 25px;
+ border: 4px solid #f0e2d9;
+ background-color: #f9f9e0;
+}
+
+.newsbox h2 {
+ margin: 0;
+ padding: 0;
+}
+
+.newsbox-news {
+ text-align: left;
+ margin-left: 25px;
+ margin-top: 25px;
+ padding: 25px;
+}
+
+.newsbox-news p,
+.newsbox-news h3 {
+ margin: 0;
+}
diff --git a/static/css/themes/gruvbox.css b/static/css/themes/gruvbox.css
new file mode 100644
index 0000000..fb40267
--- /dev/null
+++ b/static/css/themes/gruvbox.css
@@ -0,0 +1,140 @@
+a, a:link, a:visited, a:active {
+ color: #b16286;
+ text-decoration: none
+}
+
+a.reply {
+ color: #cc241d;
+}
+
+a:hover.reply {
+ color: #fb4934;
+}
+
+body {
+ background: #282828;
+ color: #ebdbb2;
+
+ font-family: monospace, sans-serif;
+ font-size: 0.9em;
+}
+
+.popup-box {
+ border: 4px solid #928374;
+ background-color: #3c3836;
+}
+
+.box, .box-alt {
+ background-color: #3c3836;
+}
+
+.quote {
+ color: #98971a;
+}
+
+.post {
+ background-color: #1d2021;
+}
+
+:target > div > .post {
+ background-color: #504945;
+}
+
+.subject {
+ color: #458588;
+}
+
+.name {
+ color: #b8bb26;
+}
+
+.tripcode {
+ color: #689d6a;
+}
+
+h1,h2,h3,h4,h5,h6 {
+ color: #fb4934;
+ margin-bottom: 0.1em;
+}
+
+.replyLink {
+ color: #83a598;
+ font-size: 0.8em;
+}
+
+#newpostbtn {
+ text-align: center;
+ margin-top: 80px;
+}
+
+input[type="text"] {
+ -webkit-appearance: none;
+ -webkit-border-radius: 0;
+}
+
+#postForm {
+ border: 4px solid #928374;
+ background-color: #3c3836;
+ margin: auto;
+
+}
+
+#postForm tr > td:first-child {
+ background-color: #504945;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+
+#postForm input[type="text"],
+#postForm textarea,
+#reply-name, #reply-options, #reply-comment {
+ box-sizing: border-box;
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing: border-box;
+}
+
+#reply-name, #reply-options, #reply-comment {
+ width: 100%;
+}
+
+#postForm #captcha {
+ display: block;
+ width: 100%;
+}
+
+.popup-box {
+ position: absolute;
+ width: min-content;
+ z-index: 9;
+ display: block;
+}
+
+/* TODO: rename */
+.box2 {
+ border: 4px solid #928374;
+ background-color: #3c3836;
+}
+
+.newsbox {
+ padding: 25px;
+ border: 4px solid #928374;
+ background-color: #3c3836;
+}
+
+.newsbox h2 {
+ margin: 0;
+ padding: 0;
+}
+
+.newsbox-news {
+ text-align: left;
+ background-color: #504945;
+ margin-left: 25px;
+ margin-top: 25px;
+ padding: 25px;
+}
+
+.newsbox-news p,
+.newsbox-news h3 {
+ margin: 0;
+}
diff --git a/static/index.html b/static/index.html
index b706e6b..8f1d53b 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,6 +1,6 @@
{{ define "header" }}
<title>{{ .Title }}</title>
-<meta name="description" content="{{ .PreferredUsername }} is a federated image board based on ActivityPub. The current version of the code running on the server is still a work-in-progress product, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
+<meta name="description" content="{{ .PreferredUsername }} is a federated image board based on ActivityPub. The current version of the code running on the server is still a work-in-progress product, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
@@ -23,47 +23,45 @@
<p style="text-align: justify">{{ .PreferredUsername }} is a federated image board based on <a href="https://activitypub.rocks/">ActivityPub</a>. The current version of the code running on the server is still a work-in-progress product, expect a bumpy ride for the time being. Get the server code here: <a href="https://github.com/FChannel0">https://github.com/FChannel0</a>.</p>
{{ if .Boards }}
- {{ $l := len .Boards }}
+ {{ $l := len .Boards }}
<div style="margin-top:50px;">
- <div style="display: grid;border-right: 2px solid #820404">
+ <div style="display: grid;border-right: 2px solid #820404;">
{{ if lt $l 2 }}
<div style="display: inline-grid; border-bottom: 2px solid #820404;border-left: 2px solid #820404;border-top: 2px solid #820404;"><span style="font-size: 1.5em;font-weight: bold;">Local boards</span></div>
{{ else if eq $l 2 }}
<div style="display: inline-grid; grid-column: 1 / 3; border-bottom: 2px solid #820404;border-left: 2px solid #820404;border-top: 2px solid #820404;"><span style="font-size: 1.5em;font-weight: bold;">Local boards</span></div>
{{ else }}
<div style="display: inline-grid;grid-column: 1 / 4;border-bottom: 2px solid #820404;border-left: 2px solid #820404;border-top: 2px solid #820404;"><span style="font-size: 1.5em;font-weight: bold;">Local boards</span></div>
- {{ end }}
+ {{ end }}
{{ range .Boards }}
<div style="whitespace: nowrap;display: inline-grid;text-align: left;padding: 5px;border-bottom: 2px solid #820404;border-left: 2px solid #820404;"><a href="{{.Location}}"><b>/{{.Name}}/</b> - {{.PrefName}} {{ if not .Restricted }} [NSFW] {{ end }}</a></div>
{{ end }}
- {{ if gt $l 2 }}
+ {{ if gt $l 2 }}
{{ range .BoardRemainer }}
<div style="whitespace: nowrap;display: inline-grid;text-align: left;padding: 5px;border-bottom: 2px solid #820404;border-left: 2px solid #820404;"></div>
{{ end }}
{{ end }}
- </div>
+ </div>
</div>
{{ end }}
-
- {{ if .NewsItems }}
- <div class="popup-box" style="margin-top:50px;">
- <table style="text-align: left; margin: 25px;">
- <th>
- <tr><h4><a href="/news">{{ .PreferredUsername }} News</a></h4></tr>
- </th>
+
+ {{ if .NewsItems }}
+ <div class="newsbox" style="margin-top:50px;">
+ <h2><a href="/news">{{ .PreferredUsername }} News</a></h2>
{{ range $i, $e := .NewsItems }}
- <tr>
- <td>{{ if $.Board.ModCred }}<a href="/{{ $.Key }}/newsdelete/{{ $e.Time }}">[Delete] </a>{{end}}
- <a href="/news/{{.Time}}">{{unixtoreadable $e.Time}} - {{$e.Title}}</a>
- <br><p style="margin-left: 25px;">{{$e.Content}}</p>
+ <div class="newsbox-news">
+ <h3><a href="/news/{{.Time}}">{{unixtoreadable $e.Time}} - {{$e.Title}}</a>{{ if $.Board.ModCred }} <a href="/{{ $.Key }}/newsdelete/{{ $e.Time }}">[Delete] </a>{{end}}</h3>
+ <br>
+
+ <p>{{$e.Content}}</p>
</td>
- </tr>
+ </div>
{{ end }}
</table>
</div>
- {{ end }}
-
- <div class="popup-box" style="margin-top:50px;">
+ {{ end }}
+
+ <div class="box2" style="margin-top:50px;">
<h4 style="margin-bottom:5px;">Current known instances</h4>
<span>(always use a proxy)</span>
<table style="text-align: left; margin: 25px;">
diff --git a/static/js/posts.js b/static/js/posts.js
index 455e7ea..30f4893 100644
--- a/static/js/posts.js
+++ b/static/js/posts.js
@@ -2,29 +2,16 @@ function startNewPost(){
var el = document.getElementById("newpostbtn");
el.style="display:none;";
el.setAttribute("state", "1");
- document.getElementById("newpost").style = "display: block;";
+ document.getElementById("newpost").style = "";
+ sessionStorage.setItem("newpostState", true);
}
function stopNewPost(){
var el = document.getElementById("newpostbtn");
el.style="display:block;";
el.setAttribute("state", "0");
- document.getElementById("newpost").style = "display: hidden;";
-}
-
-function newpost()
-{
- var state = document.getElementById("newpostbtn").getAttribute("state");
- if(state === "0")
- {
- startNewPost();
- sessionStorage.setItem("newpostState", true);
- }
- else
- {
- stopNewPost();
- sessionStorage.setItem("newpostState", false);
- }
+ document.getElementById("newpost").style = "display: none;";
+ sessionStorage.setItem("newpostState", false);
}
function shortURL(actorName, url)
@@ -182,7 +169,7 @@ function quote(actorName, opid, id)
var h = document.getElementById(id + "-content").offsetTop - 348;
}
- const boxStyle = "display: block; position: absolute; width: 400px; height: 600px; z-index: 9; top: " + h + "px; left: " + w + "px; padding: 5px;";
+ const boxStyle = "top: " + h + "px; left: " + w + "px;";
box.setAttribute("style", boxStyle);
sessionStorage.setItem("element-reply-style", boxStyle);
sessionStorage.setItem("reply-top", h);
@@ -202,7 +189,6 @@ function quote(actorName, opid, id)
sessionStorage.setItem("element-reply-comment", comment.value);
dragElement(header);
-
}
function report(actorName, id)
@@ -216,7 +202,7 @@ function report(actorName, id)
var w = window.innerWidth / 2 - 200;
var h = document.getElementById(id + "-content").offsetTop - 348;
- const boxStyle = "display: block; position: absolute; width: 400px; height: 480px; z-index: 9; top: " + h + "px; left: " + w + "px; padding: 5px;";
+ const boxStyle = "top: " + h + "px; left: " + w + "px;";
box.setAttribute("style", boxStyle);
sessionStorage.setItem("element-report-style", boxStyle);
sessionStorage.setItem("report-top", h);
diff --git a/static/js/themes.js b/static/js/themes.js
new file mode 100644
index 0000000..3f1b906
--- /dev/null
+++ b/static/js/themes.js
@@ -0,0 +1,40 @@
+function setCookie(key, value, age) {
+ document.cookie = key + "=" + encodeURIComponent(value) + ";sameSite=strict;max-age=" + 60 * 60 * 24 * age + ";path=/";
+}
+
+function getCookie(key) {
+ if (document.cookie.length != 0) {
+ return document.cookie.split('; ').find(row => row.startsWith(key)).split('=')[1];
+ }
+ return "";
+}
+
+function setTheme(name) {
+ for (let i = 0, tags = document.getElementsByTagName("link"); i < tags.length; i++) {
+ if (tags[i].type === "text/css" && tags[i].title) {
+ tags[i].disabled = !(tags[i].title === name);
+ }
+ }
+
+ setCookie("theme", name, 3650);
+}
+
+function applyTheme() {
+ // HACK: disable all of the themes first. this for some reason makes things work.
+ for (let i = 0, tags = document.getElementsByTagName("link"); i < tags.length; i++) {
+ if (tags[i].type === "text/css" && tags[i].title) {
+ tags[i].disabled = true;
+ }
+ }
+ let theme = getCookie("theme") || "default";
+ setTheme(theme);
+
+ // reflect this in the switcher
+ let switcher = document.getElementById("themeSwitcher");
+ for(var i = 0; i < switcher.options.length; i++) {
+ if (switcher.options[i].value === theme) {
+ switcher.selectedIndex = i;
+ break;
+ }
+ }
+}
diff --git a/static/main.html b/static/main.html
index 362b7b3..794a602 100644
--- a/static/main.html
+++ b/static/main.html
@@ -8,81 +8,13 @@
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
<link rel="icon" type="image/png" href="/static/favicon.png">
- <style>
- a, a:link, a:visited, a:hover, a:active {
- text-decoration: none
- }
-
- a:link, a:visited, a:active {
- color: black;
- }
-
- a:hover {
- color: #de0808;
- }
-
- body {
- {{ if .Board.Restricted }}
- background-color: #eef2fe;
- color: black;
- {{ else }}
- background-color: #ffffee;
- color: #820404
- {{ end }}
- }
-
- .popup-box {
- {{ if .Board.Restricted }}
- border: 4px solid #d3caf0;
- background-color: #eff5ff;
- {{ else }}
- border: 4px solid #f0e2d9;
- background-color: #f9f9e0;
- {{ end }}
- }
-
- .box {
- {{ if .Board.Restricted }}
- background-color: #eff5ff;
- {{ else }}
- background-color: #f9f9e0;
- {{ end }}
- }
-
- .box-alt {
- {{ if .Board.Restricted }}
- background-color: #d3caf0;
- {{ else }}
- background-color: #f0e2d9;
- {{ end }}
- }
-
- .quote {
- color: #789922;
- }
-
- .post {
- {{ if .Board.Restricted }}
- background-color: #d5daf0;
- {{ else }}
- background-color: #f0e0d6;
- {{ end }}
- }
-
- :target > div > .post {
- {{ if .Board.Restricted }}
- background-color: #d6bad0;
- {{ else }}
- background-color: #f0c0b0;
- {{ end }}
- }
- .tripcode {
- color: #117743;
- }
- </style>
+ <link rel="stylesheet" type="text/css" href="/static/css/themes/default.css" title="default">
+ {{ range .Themes }}
+ <link rel="alternate stylesheet" type="text/css" href="/static/css/themes/{{.}}.css" title="{{.}}">
+ {{ end }}
{{ template "header" . }}
</head>
- <body>
+ <body {{ if not .Board.Restricted }}class="nsfw"{{ end }} onload="applyTheme()">
<ul style="display: inline; padding:0;">
{{ $l := len .Boards }}
<li style="display: inline;">[<a href="/">Home</a>]</li>
@@ -108,12 +40,24 @@
{{ template "content" . }}
{{ template "bottom" . }}
+
+ <div style="float: right;">
+ Theme:
+ <select id="themeSwitcher" onchange="setTheme(this.options[this.selectedIndex].value)">
+ {{ range .Themes }}
+ <option value="{{.}}">{{.}}</option>
+ {{ end }}
+ </select>
+ </div>
+
<div align="center" style="width: 500px; margin:0 auto; margin-top: 50px;">
<a href="/">[Home]</a><a href="/static/rules.html">[Rules]</a><a href="/static/faq.html">[FAQ]</a>
<p>All trademarks and copyrights on this page are owned by their respective parties.</p>
</div>
+
+ <script src="/static/js/themes.js"></script>
+{{ template "script" . }}
</body>
</html>
-{{ template "script" . }}
{{ end }}
diff --git a/static/manage.html b/static/manage.html
index 3bd621b..dc25468 100644
--- a/static/manage.html
+++ b/static/manage.html
@@ -20,7 +20,7 @@
{{ $board := .Board }}
{{ $key := .Key }}
{{ if .IsLocal }}
-<div id="following" class="popup-box" style="margin-bottom: 25px; margin-top: 5px; padding: 12px;">
+<div id="following" class="box2" style="margin-bottom: 25px; margin-top: 5px; padding: 12px;">
<h4 style="margin: 0; margin-bottom: 5px;">Following</h4>
{{ if .AutoSubscribe }}<a title="Auto Follow is On" href="/autosubscribe?board={{ .Board.Name }}">[Toggle Auto Follow Off]{{ else }}<a title="Auto Follow is Off" href="/autosubscribe?board={{ .Board.Name }}">[Toggle Auto Follow On]{{ end }}</a>
<form id="follow-form" action="/{{ .Key }}/{{ .Board.Name }}/follow" method="post" enctype="application/x-www-form-urlencoded" style="margin-top: 5px;">
@@ -36,7 +36,7 @@
</ul>
</div>
-<div id="followers" class="popup-box" style="margin-bottom: 25px; padding: 12px;">
+<div id="followers" class="box2" style="margin-bottom: 25px; padding: 12px;">
<h4 style="margin: 0; margin-bottom: 5px;">Followers</h4>
<ul style="display: inline-block; padding: 0; margin: 0; list-style-type: none;">
{{ range .Followers }}
@@ -46,7 +46,7 @@
</div>
{{ end }}
-<div id="reported" class="popup-box" style="margin-bottom: 25px; padding: 12px;">
+<div id="reported" class="box2" style="margin-bottom: 25px; padding: 12px;">
<h4 style="margin: 0; margin-bottom: 5px;">Reported</h4>
<ul style="display: inline-block; padding: 0; margin: 0; list-style-type: none;">
{{ $domain := .Domain }}
diff --git a/static/nadmin.html b/static/nadmin.html
index 5e38151..e8fbc36 100644
--- a/static/nadmin.html
+++ b/static/nadmin.html
@@ -26,7 +26,7 @@
</div>
-<div id="following" class="popup-box" style="margin-bottom: 25px; padding: 12px;">
+<div id="following" class="box2" style="margin-bottom: 25px; padding: 12px;">
<h4 style="margin: 0; margin-bottom: 5px;">Subscribed</h4>
<form id="follow-form" action="/{{ .Key }}/follow" method="post" enctype="application/x-www-form-urlencoded">
<input id="follow" name="follow" style="margin-bottom: 12px;" placeholder="http://localhost:3000/g"></input><input type="submit" value="Subscribe"><br>
@@ -41,7 +41,7 @@
</ul>
</div>
-<div id="followers" class="popup-box" style="margin-bottom: 25px; padding: 12px; display:none;">
+<div id="followers" class="box2" style="margin-bottom: 25px; padding: 12px; display:none;">
<h4 style="margin: 0; margin-bottom: 5px;">Followers</h4>
<ul style="display: inline-block; padding: 0; margin: 0; list-style-type: none;">
{{ range .Followers }}
@@ -50,7 +50,7 @@
</ul>
</div>
-<div class="popup-box" style="margin-bottom: 25px; padding: 12px;">
+<div class="box2" style="margin-bottom: 25px; padding: 12px;">
<h3>Create News</h3>
<form id="news" action="/{{ .Key }}/postnews" method="post" enctype="application/x-www-form-urlencoded">
<label>Title:</label><br>
@@ -60,7 +60,7 @@
</form>
</div>
-<div id="regex" class="popup-box" style="margin-bottom: 25px; padding: 12px;">
+<div id="regex" class="box2" style="margin-bottom: 25px; padding: 12px;">
<h3>Regex Post Blacklist</h3>
<form id="blacklist" action="/blacklist" method="post" enctype="application/x-www-form-urlencoded">
<label>Regex:</label><br>
diff --git a/static/ncatalog.html b/static/ncatalog.html
index e35edd0..ec8afd5 100644
--- a/static/ncatalog.html
+++ b/static/ncatalog.html
@@ -17,14 +17,16 @@
{{ define "content" }}
{{ $board := .Board }}
<hr>
-<ul style="margin: 0; padding: 0; display: inline">
- <li style="display: inline"><a href="/{{ $board.Name }}">[Return]</a></li>
+
+<div class="navlinks">
+ [<a href="/{{ $board.Name }}/">Return</a>]
{{ if showArchive }}
- <li style="display: inline"><a href="/{{ $board.Name }}/archive">[Archive]</a></li>
+ [<a href="/{{ $board.Name }}/archive">Archive</a>]
{{ end }}
- <li style="display: inline"><a href="#bottom">[Bottom]</a></li>
- <li style="display: inline"><a href="javascript:location.reload()">[Refresh]</a></li>
-</ul>
+ [<a href="#bottom">Bottom</a>]
+ [<a href="javascript:location.reload()">Refresh</a>]
+</div>
+
<hr>
<div style="padding: 10px; text-align: center;">
@@ -39,7 +41,12 @@
<a href="/marksensitive?id={{ .Id }}&board={{ $board.Actor.Name }}">[Mark Sensitive]</a>
{{ end }}
<div id="hide-{{ .Id }}" style="display: none;">[Hide]</div>
- <div id="sensitive-{{ .Id }}" style="display: none;"><div style="position: relative; text-align: center;"><img id="sensitive-img-{{ .Id }}" style="float: left; margin-right: 10px; margin-bottom: 10px; max-width: 180px; max-height: 180px;" src="/static/sensitive.png"><div id="sensitive-text-{{ .Id }}" style="width: 170px; position: absolute; margin-top: 75px; padding: 5px; background-color: black; color: white; cursor: default; ">NSFW Content</div></div></div>
+ <div id="sensitive-{{ .Id }}" style="display: none;">
+ <div style="position: relative; text-align: center;">
+ <img id="sensitive-img-{{ .Id }}" style="float: left; margin-right: 10px; margin-bottom: 10px; max-width: 180px; max-height: 180px;" src="/static/sensitive.png">
+ <div id="sensitive-text-{{ .Id }}" style="width: 170px; position: absolute; margin-top: 75px; padding: 5px; background-color: black; color: white; cursor: default; ">NSFW Content</div>
+ </div>
+ </div>
<a id="{{ .Id }}-anchor" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox .Id}}">
<div id="media-{{ .Id }}" style="width:180px;"> {{ parseAttachment . true }}</div>
</a>
@@ -67,33 +74,37 @@
}
</script>
{{ end }}
- <a id="{{ .Id }}-link" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox .Id }}">
- <div>
- {{ $replies := .Replies }}
- {{ if $replies }}
- <span style="display: block;">R: {{ $replies.TotalItems }}{{ if $replies.TotalImgs }}/ A: {{ $replies.TotalImgs }}{{ end }}</span>
- {{ end }}
- {{ if .Name }}
- <span style="display: block; color: #0f0c5d;"><b>{{ .Name }}</b></span>
- {{ end }}
+ <a style="color: unset;" id="{{ .Id }}-link" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox .Id }}">
+ <div style="display: block;">
+ {{ $replies := .Replies }}
+ {{ if $replies }}
+ <span>R: {{ $replies.TotalItems }}{{ if $replies.TotalImgs }}/ A: {{ $replies.TotalImgs }}{{ end }}</span>
+ {{ end }}
+ {{ if .Name }}
+ <br>
+ <span class="subject"><b>{{ .Name }}</b></span>
+ {{ end }}
- {{ if .Content }}
- <span style="display: block">{{.Content}}</span>
- {{ end }}
- </div>
+ {{ if .Content }}
+ <br>
+ <span>{{.Content}}</span>
+ {{ end }}
+ </div>
</a>
</div>
{{ end }}
</div>
<hr>
-<ul style="margin: 0; padding: 0; display: inline">
- <li style="display: inline"><a href="/{{ $board.Name }}">[Return]</a></li>
+
+<div class="navlinks">
+ [<a href="/{{ $board.Name }}/">Return</a>]
{{ if showArchive }}
- <li style="display: inline"><a href="/{{ $board.Name }}/archive">[Archive]</a></li>
+ [<a href="/{{ $board.Name }}/archive">Archive</a>]
{{ end }}
- <li style="display: inline"><a id="bottom" href="#top">[Top]</a></li>
- <li style="display: inline"><a href="javascript:location.reload()">[Refresh]</a></li>
-</ul>
+ [<a href="#top">Top</a>]
+ [<a href="javascript:location.reload()">Refresh</a>]
+</div>
+
<hr>
{{ end }}
{{ define "bottom" }}
diff --git a/static/nposts.html b/static/nposts.html
index 6def8b2..46d8bb1 100644
--- a/static/nposts.html
+++ b/static/nposts.html
@@ -15,33 +15,35 @@
{{ define "content" }}
{{ $board := .Board }}
<hr>
-<ul style="margin: 0; padding: 0; display: inline">
- <li style="display: inline"><a href="/{{ $board.Name }}/catalog">[Catalog]</a></li>
+<div class="navlinks">
+ [<a href="/{{ $board.Name }}/catalog">Catalog</a>]
{{ if showArchive }}
- <li style="display: inline"><a href="/{{ $board.Name }}/archive">[Archive]</a></li>
+ [<a href="/{{ $board.Name }}/archive">Archive</a>]
{{ end }}
- <li style="display: inline"><a href="#bottom">[Bottom]</a></li>
- <li style="display: inline"><a href="javascript:location.reload()">[Refresh]</a></li>
-</ul>
+ [<a href="#bottom">Bottom</a>]
+ [<a href="javascript:location.reload()">Refresh</a>]
+</div>
{{ template "posts" . }}
<hr>
-<ul style="margin: 0; padding: 0; display: inline">
- <li style="display: inline"><a href="/{{ $board.Name }}/catalog">[Catalog]</a></li>
+
+<div class="navlinks">
+ [<a href="/{{ $board.Name }}/catalog">Catalog</a>]
{{ if showArchive }}
- <li style="display: inline"><a href="/{{ $board.Name }}/archive">[Archive]</a></li>
+ [<a href="/{{ $board.Name }}/archive">Archive</a>]
{{ end }}
- <li style="display: inline"><a id="bottom" href="#top">[Top]</a></li>
- <li style="display: inline"><a href="javascript:location.reload()">[Refresh]</a></li>
-</ul>
+ [<a href="#top" id="bottom">Top</a>]
+ [<a href="javascript:location.reload()">Refresh</a>]
+</div>
+
<hr>
{{ if gt .TotalPage 0 }}
{{ $totalPage := .TotalPage }}
<ul style="float: right; margin: 0; padding: 0; display: inline">
{{ $page := .CurrentPage }}
{{ if gt $page 0 }}
- <li style="display: inline"><a href="/{{ $board.Name }}?page={{ sub $page 1 }}">[ < ]</a></li>
+ <li style="display: inline"><a href="/{{ $board.Name }}?page={{ sub $page 1 }}">[ &lt; ]</a></li>
{{ end }}
{{ range $i, $e := .Pages }}
{{ if eq $i $page}}
@@ -51,7 +53,7 @@
{{ end }}
{{ end }}
{{ if lt .CurrentPage .TotalPage }}
- <li style="display: inline"><a href="/{{ $board.Name }}?page={{ add $page 1 }}">[ > ]</a></li>
+ <li style="display: inline"><a href="/{{ $board.Name }}?page={{ add $page 1 }}">[ &gt; ]</a></li>
{{ end }}
</ul>
{{ end }}
diff --git a/static/posts.html b/static/posts.html
index 50d8b43..7110dd9 100644
--- a/static/posts.html
+++ b/static/posts.html
@@ -45,7 +45,10 @@
}
</script>
{{ end }}
- <span style="color: #0f0c5d;"><b>{{ .Name }}</b></span><span style="color: #117743;"><b>{{ if .AttributedTo }} {{.AttributedTo }} {{ else }} Anonymous {{ end }}</b></span><span class="tripcode"> {{ .TripCode }} </span><span>{{ .Published }} <a id="{{ .Id }}-anchor" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox $opId }}#{{ short $board.Actor.Outbox .Id }}">No.</a> <a id="{{ .Id }}-link" title="{{ .Id }}" {{ if eq .Type "Note" }} href="javascript:quote('{{ $board.Actor.Id }}', '{{ $opId }}', '{{ .Id }}')" {{ end }}>{{ short $board.Actor.Outbox .Id }}</a> {{ if ne .Type "Tombstone" }}<a href="javascript:report('{{ $board.Actor.Id }}', '{{ .Id }}')">[Report]</a>{{ end }}</span>
+ <span class="subject"><b>{{ .Name }}</b></span>
+ <span class="name"><b>{{ if .AttributedTo }} {{.AttributedTo }} {{ else }} Anonymous {{ end }}</b></span>
+ <span class="tripcode"> {{ .TripCode }} </span>
+ <span class="timestamp" data-utc="{{.Published | timeToUnix}}">{{ .Published | timeToReadableLong }} <a id="{{ .Id }}-anchor" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox $opId }}#{{ short $board.Actor.Outbox .Id }}">No.</a> <a id="{{ .Id }}-link" title="{{ .Id }}" {{ if eq .Type "Note" }} href="javascript:quote('{{ $board.Actor.Id }}', '{{ $opId }}', '{{ .Id }}')" {{ end }}>{{ short $board.Actor.Outbox .Id }}</a> {{ if ne .Type "Tombstone" }}<a href="javascript:report('{{ $board.Actor.Id }}', '{{ .Id }}')">[Report]</a>{{ end }}</span>
<p id="{{ .Id }}-content" style="white-space: pre-wrap; margin: 10px 30px 10px 30px;">{{ parseContent $board.Actor $opId .Content $thread }}</p>
{{ if .Replies }}
{{ $replies := .Replies }}
@@ -57,7 +60,7 @@
{{ range $replies.OrderedItems }}
<div id="{{ short $board.Actor.Outbox .Id }}">
<div style="display: inline-block; overflow: auto;">
- <div style="float: left; display: block; margin-right: 5px;">>></div>
+ <div style="float: left; display: block; margin-right: 5px;">&gt;&gt;</div>
<div class="post" style="overflow: auto; padding: 5px; margin-bottom: 2px;">
{{ if eq $board.ModCred $board.Domain $board.Actor.Id }}
<a href="/delete?id={{ .Id }}&board={{ $board.Actor.Name }}">[Delete Post]</a>
@@ -97,7 +100,10 @@
}
</script>
{{ end }}
- <span style="color: #0f0c5d;"><b>{{ .Name }}</b></span><span style="color: #117743;"><b>{{ if .AttributedTo }} {{.AttributedTo }} {{ else }} Anonymous {{ end }}</b></span><span class="tripcode"> {{ .TripCode }} </span><span>{{ .Published }} <a id="{{ .Id }}-anchor" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox $opId }}#{{ short $board.Actor.Outbox .Id }}">No. </a><a id="{{ .Id }}-link" title="{{ .Id }}" {{ if eq .Type "Note" }} href="javascript:quote('{{ $board.Actor.Id }}', '{{ $opId }}', '{{ .Id }}')" {{ end }}>{{ short $board.Actor.Outbox .Id }}</a> {{ if ne .Type "Tombstone" }}<a href="javascript:report('{{ $board.Actor.Id }}', '{{ .Id }}')">[Report]</a>{{ end }}</span>
+ <span class="subject"><b>{{ .Name }}</b></span>
+ <span class="name"><b>{{ if .AttributedTo }} {{.AttributedTo }} {{ else }} Anonymous {{ end }}</b></span>
+ <span class="tripcode"> {{ .TripCode }} </span>
+ <span class="timestamp" data-utc="{{ .Published | timeToUnix }}">{{ .Published | timeToReadableLong }} <a id="{{ .Id }}-anchor" href="/{{ $board.Name }}/{{ short $board.Actor.Outbox $opId }}#{{ short $board.Actor.Outbox .Id }}">No. </a><a id="{{ .Id }}-link" title="{{ .Id }}" {{ if eq .Type "Note" }} href="javascript:quote('{{ $board.Actor.Id }}', '{{ $opId }}', '{{ .Id }}')" {{ end }}>{{ short $board.Actor.Outbox .Id }}</a> {{ if ne .Type "Tombstone" }}<a href="javascript:report('{{ $board.Actor.Id }}', '{{ .Id }}')">[Report]</a>{{ end }}</span>
{{ $parentId := .Id }}
{{ if .Replies.OrderedItems }}
{{ range .Replies.OrderedItems }}
diff --git a/static/top.html b/static/top.html
index 0081fc7..94abad7 100644
--- a/static/top.html
+++ b/static/top.html
@@ -1,39 +1,59 @@
{{ define "top" }}
<div style="margin: 0 auto; width: 700px; margin-bottom: 100px;">
- <h1 style="text-align: center; color: #af0a0f;">/{{ .Board.Name }}/ - {{ .Board.PrefName }}</h1>
+ <h1 style="text-align: center;">/{{ .Board.Name }}/ - {{ .Board.PrefName }}</h1>
<p style="text-align: center;">{{ .Board.Summary }}</p>
{{ $len := len .Posts }}
{{ if eq $len 0 }}
{{ if .Board.InReplyTo }}
- <h3 id="newpostbtn" state="0" style="text-align: center; margin-top: 80px; display: none;"><a href="javascript:newpost()">[Post a Reply]</a></h3>
+ <h3 id="newpostbtn" state="0" style="display: none;"><a href="javascript:startNewPost()">[Post a Reply]</a></h3>
{{ else }}
- <h3 id="newpostbtn" state="0" style="text-align: center; margin-top: 80px; display: none;"><a href="javascript:newpost()">[Start a New Thread]</a></h3>
+ <h3 id="newpostbtn" state="0" style="display: none;"><a href="javascript:startNewPost()">[Start a New Thread]</a></h3>
{{ end }} <!-- end if inreplyto-->
<div id="newpost">
- <form onsubmit="sessionStorage.setItem('element-closed-reply', true)" id="new-post" action="/post" method="post" enctype="multipart/form-data" style="margin-left: 180px;">
- <label for="name">Name:</label><br>
- <input type="text" id="name" name="name" placeholder="Anonymous" maxlength="100"><br>
- <label for="options">Options:</label><br>
- <input type="text" id="options" name="options" maxlength="100" style="margin-right:10px">{{ if .Board.InReplyTo }}<input type="submit" value="Post">{{ end }}<br>
- {{ if eq .Board.InReplyTo "" }}
- <label for="subject">Subject:</label><br>
- <input type="text" id="subject" name="subject" maxlength="100" style="margin-right:10px"><input type="submit" value="Post"><br>
- {{ end }}
- <label for="comment">Comment:</label><br>
- <textarea rows="10" cols="50" id="comment" name="comment" maxlength="2000"></textarea><br>
+ <form onsubmit="sessionStorage.setItem('element-closed-reply', true)" id="new-post" action="/post" method="post" enctype="multipart/form-data">
+ <table id="postForm">
+ <tr>
+ <tr>
+ <td><label for="name">Name:</label></td>
+ <td><input type="text" id="name" name="name" placeholder="Anonymous" maxlength="100">
+ <a onclick="stopNewPost()" style="float: right;">[X]</a>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="options">Options:</label></td>
+ <td><input type="text" id="options" name="options" maxlength="100" style="margin-right:10px">{{ if .Board.InReplyTo }}<input type="submit" value="Post">{{ end }}</td>
+ </tr>
+ {{ if eq .Board.InReplyTo "" }}
+ <tr>
+ <td><label for="subject">Subject:</label></td>
+ <td><input type="text" id="subject" name="subject" maxlength="100" style="margin-right:10px"><input type="submit" value="Post"></td>
+ </tr>
+ {{ end }}
+ <tr>
+ <td><label for="comment">Comment:</label></td>
+ <td><textarea rows="10" cols="50" id="comment" name="comment" maxlength="2000"></textarea></td>
+ </tr>
+ <tr>
+ <td><label for="file">Image</label></td>
+ <td><input type="file" id="file" name="file" {{ if gt $len 1 }} required {{ else }} {{ if eq $len 0 }} required {{ end }} {{ end }} >
+ <br><input type="checkbox" name="sensitive">Mark sensitive</input></td>
+ </tr>
+ <tr>
+ <td><label for="captcha">Captcha:</label></td>
+ <td>
+ <div style="height: 65px; display: inline;">
+ <img src="{{ .Board.Captcha }}">
+ </div>
+ <input type="text" id="captcha" name="captcha" autocomplete="off">
+ </td>
+ </tr>
+ </table>
+
<input type="hidden" id="inReplyTo" name="inReplyTo" value="{{ .Board.InReplyTo }}">
<input type="hidden" id="sendTo" name="sendTo" value="{{ .Board.To }}">
<input type="hidden" id="boardName" name="boardName" value="{{ .Board.Name }}">
<input type="hidden" id="captchaCode" name="captchaCode" value="{{ .Board.CaptchaCode }}">
<input type="hidden" id="returnTo" name="returnTo" value="{{ .ReturnTo }}">
- <input type="file" id="file" name="file" {{ if gt $len 1 }} required {{ else }} {{ if eq $len 0 }} required {{ end }} {{ end }} ><br><br>
- <input type="checkbox" name="sensitive"><span>Mark attachment as sensitive</span><br><br>
- <label stye="display: inline-block;" for="captcha">Captcha:</label>
- <br>
- <input style="display: inline-block;" type="text" id="captcha" name="captcha" autocomplete="off"><br>
- <div style="height: 65px;">
- <img src="{{ .Board.Captcha }}">
- </div>
</form>
</div>
@@ -41,37 +61,57 @@
{{ if eq (index .Posts 0).Type "Note" }}
{{ if .Board.InReplyTo }}
- <h3 id="newpostbtn" state="0" style="text-align: center; margin-top: 80px; display: none;"><a href="javascript:newpost()">[Post a Reply]</a></h3>
+ <h3 id="newpostbtn" state="0" style="text-align: center; margin-top: 80px; display: none;"><a href="javascript:startNewPost()">[Post a Reply]</a></h3>
{{ else }}
- <h3 id="newpostbtn" state="0" style="text-align: center; margin-top: 80px; display: none;"><a href="javascript:newpost()">[Start a New Thread]</a></h3>
+ <h3 id="newpostbtn" state="0" style="text-align: center; margin-top: 80px; display: none;"><a href="javascript:startNewPost()">[Start a New Thread]</a></h3>
{{ end }} <!-- end if inreplyto-->
{{ $len := len .Posts }}
<div id="newpost">
- <form onsubmit="sessionStorage.setItem('element-closed-reply', true)" id="new-post" action="/post" method="post" enctype="multipart/form-data" style="margin-left: 180px;">
- <label for="name">Name:</label><br>
- <input type="text" id="name" name="name" placeholder="Anonymous" maxlength="100"><br>
- <label for="options">Options:</label><br>
- <input type="text" id="options" name="options" maxlength="100" style="margin-right:10px">{{ if .Board.InReplyTo }}<input type="submit" value="Post">{{ end }}<br>
- {{ if eq .Board.InReplyTo "" }}
- <label for="subject">Subject:</label><br>
- <input type="text" id="subject" name="subject" maxlength="100" style="margin-right:10px"><input type="submit" value="Post"><br>
- {{ end }}
- <label for="comment">Comment:</label><br>
- <textarea rows="10" cols="50" id="comment" name="comment" maxlength="2000"></textarea><br>
+ <form onsubmit="sessionStorage.setItem('element-closed-reply', true)" id="new-post" action="/post" method="post" enctype="multipart/form-data">
+ <table id="postForm">
+ <tr>
+ <tr>
+ <td><label for="name">Name:</label></td>
+ <td><input type="text" id="name" name="name" placeholder="Anonymous" maxlength="100">
+ <a onclick="stopNewPost()" style="float: right;">[X]</a>
+ </tr>
+ <tr>
+ <td><label for="options">Options:</label></td>
+ <td><input type="text" id="options" name="options" maxlength="100" style="margin-right:10px">{{ if .Board.InReplyTo }}<input type="submit" value="Post">{{ end }}</td>
+ </tr>
+ {{ if eq .Board.InReplyTo "" }}
+ <tr>
+ <td><label for="subject">Subject:</label></td>
+ <td><input type="text" id="subject" name="subject" maxlength="100" style="margin-right:10px"><input type="submit" value="Post"></td>
+ </tr>
+ {{ end }}
+ <tr>
+ <td><label for="comment">Comment:</label></td>
+ <td><textarea rows="10" cols="50" id="comment" name="comment" maxlength="2000"></textarea></td>
+ </tr>
+ <tr>
+ <td><label for="file">Image</label></td>
+ <td><input type="file" id="file" name="file" {{ if gt $len 1 }} required {{ else }} {{ if eq $len 0 }} required {{ end }} {{ end }} >
+ <br><input type="checkbox" name="sensitive">Mark sensitive</input></td>
+ </tr>
+ <tr>
+ <td><label for="captcha">Captcha:</label></td>
+ <td>
+ <div style="height: 65px; display: inline;">
+ <img src="{{ .Board.Captcha }}">
+ </div>
+ <input type="text" id="captcha" name="captcha" autocomplete="off">
+ </td>
+ </tr>
+ </table>
+
<input type="hidden" id="inReplyTo" name="inReplyTo" value="{{ .Board.InReplyTo }}">
<input type="hidden" id="sendTo" name="sendTo" value="{{ .Board.To }}">
<input type="hidden" id="boardName" name="boardName" value="{{ .Board.Name }}">
<input type="hidden" id="captchaCode" name="captchaCode" value="{{ .Board.CaptchaCode }}">
- <input type="hidden" id="returnTo" name="returnTo" value="{{ .ReturnTo }}">
- <input type="file" id="file" name="file" {{ if gt $len 1 }} required {{ else }} {{ if eq $len 0 }} required {{ end }} {{ end }} ><br><br>
- <input type="checkbox" name="sensitive"><span>Mark attachment as sensitive</span><br><br>
- <label stye="display: inline-block;" for="captcha">Captcha:</label>
- <br>
- <input style="display: inline-block;" type="text" id="captcha" name="captcha" autocomplete="off"><br>
- <div style="height: 65px;">
- <img src="{{ .Board.Captcha }}">
- </div>
- </form>
+ <input type="hidden" id="returnTo" name="returnTo" value="{{ .ReturnTo }}"> </form>
+ </div>
+
</div>
{{ else }}
<h1 style="text-align: center;">Archived Post</h1>