From fe31d4197b66cced9ca84779fac4fe69242d844b Mon Sep 17 00:00:00 2001 From: r Date: Tue, 18 Feb 2020 22:15:37 +0000 Subject: Add frame based navigation --- .gitignore | 1 + BUGS | 3 + model/settings.go | 26 +++--- renderer/model.go | 46 +++++------ renderer/renderer.go | 12 +++ service/auth.go | 29 +++++++ service/logging.go | 25 ++++++ service/service.go | 189 ++++++++++++++++---------------------------- service/transport.go | 65 +++++++++++---- static/style.css | 13 +++ templates/about.tmpl | 3 +- templates/emoji.tmpl | 3 +- templates/error.tmpl | 4 +- templates/header.tmpl | 5 +- templates/likedby.tmpl | 3 +- templates/nav.tmpl | 34 ++++++++ templates/navigation.tmpl | 30 ------- templates/notification.tmpl | 23 ++++-- templates/postform.tmpl | 2 +- templates/retweetedby.tmpl | 3 +- templates/root.tmpl | 17 ++++ templates/search.tmpl | 3 +- templates/settings.tmpl | 11 ++- templates/signin.tmpl | 2 +- templates/status.tmpl | 38 ++++----- templates/thread.tmpl | 3 +- templates/timeline.tmpl | 5 +- templates/user.tmpl | 3 +- templates/usersearch.tmpl | 3 +- 29 files changed, 347 insertions(+), 257 deletions(-) create mode 100644 BUGS create mode 100644 templates/nav.tmpl delete mode 100644 templates/navigation.tmpl create mode 100644 templates/root.tmpl diff --git a/.gitignore b/.gitignore index 516f77b..037bea6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bloat database +bloat.def.conf diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..4972d14 --- /dev/null +++ b/BUGS @@ -0,0 +1,3 @@ +Here's a list of known bugs in bloat: + +- and tags are not supported in HTML5 diff --git a/model/settings.go b/model/settings.go index 7d22747..b1463c7 100644 --- a/model/settings.go +++ b/model/settings.go @@ -1,21 +1,23 @@ package model type Settings struct { - DefaultVisibility string `json:"default_visibility"` - CopyScope bool `json:"copy_scope"` - ThreadInNewTab bool `json:"thread_in_new_tab"` - MaskNSFW bool `json:"mask_nfsw"` - FluorideMode bool `json:"fluoride_mode"` - DarkMode bool `json:"dark_mode"` + DefaultVisibility string `json:"default_visibility"` + CopyScope bool `json:"copy_scope"` + ThreadInNewTab bool `json:"thread_in_new_tab"` + MaskNSFW bool `json:"mask_nfsw"` + AutoRefreshNotifications bool `json:"auto_refresh_notifications"` + FluorideMode bool `json:"fluoride_mode"` + DarkMode bool `json:"dark_mode"` } func NewSettings() *Settings { return &Settings{ - DefaultVisibility: "public", - CopyScope: true, - ThreadInNewTab: false, - MaskNSFW: true, - FluorideMode: false, - DarkMode: false, + DefaultVisibility: "public", + CopyScope: true, + ThreadInNewTab: false, + MaskNSFW: true, + AutoRefreshNotifications: false, + FluorideMode: false, + DarkMode: false, } } diff --git a/renderer/model.go b/renderer/model.go index 842dd71..45d3117 100644 --- a/renderer/model.go +++ b/renderer/model.go @@ -14,30 +14,17 @@ type Context struct { UserID string } -type HeaderData struct { - Title string - NotificationCount int - CustomCSS string - CSRFToken string -} - -type NavbarData struct { - User *mastodon.Account - NotificationCount int +type NavData struct { + CommonData *CommonData + User *mastodon.Account + PostContext model.PostContext } type CommonData struct { - HeaderData *HeaderData - NavbarData *NavbarData -} - -func (c CommonData) IsCurrentUser(id string) bool { - if c.NavbarData != nil && - c.NavbarData.User != nil && - c.NavbarData.User.ID == id { - return true - } - return false + Title string + CustomCSS string + CSRFToken string + AutoRefresh bool } type ErrorData struct { @@ -53,13 +40,16 @@ type SigninData struct { *CommonData } +type RootData struct { + Title string +} + type TimelineData struct { *CommonData - Title string - Statuses []*mastodon.Status - NextLink string - PrevLink string - PostContext model.PostContext + Title string + Statuses []*mastodon.Status + NextLink string + PrevLink string } type ThreadData struct { @@ -72,8 +62,9 @@ type ThreadData struct { type NotificationData struct { *CommonData Notifications []*mastodon.Notification + UnreadCount int + ReadID string NextLink string - DarkMode bool } type UserData struct { @@ -84,7 +75,6 @@ type UserData struct { Users []*mastodon.Account Statuses []*mastodon.Status NextLink string - DarkMode bool } type UserSearchData struct { diff --git a/renderer/renderer.go b/renderer/renderer.go index bd9ccd8..293a6c6 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -19,6 +19,8 @@ type TemplateData struct { type Renderer interface { RenderSigninPage(ctx *Context, writer io.Writer, data *SigninData) (err error) RenderErrorPage(ctx *Context, writer io.Writer, data *ErrorData) + RenderRootPage(ctx *Context, writer io.Writer, data *RootData) (err error) + RenderNavPage(ctx *Context, writer io.Writer, data *NavData) (err error) RenderTimelinePage(ctx *Context, writer io.Writer, data *TimelineData) (err error) RenderThreadPage(ctx *Context, writer io.Writer, data *ThreadData) (err error) RenderNotificationPage(ctx *Context, writer io.Writer, data *NotificationData) (err error) @@ -67,6 +69,16 @@ func (r *renderer) RenderErrorPage(ctx *Context, writer io.Writer, return } +func (r *renderer) RenderNavPage(ctx *Context, writer io.Writer, + data *NavData) (err error) { + return r.template.ExecuteTemplate(writer, "nav.tmpl", WithContext(data, ctx)) +} + +func (r *renderer) RenderRootPage(ctx *Context, writer io.Writer, + data *RootData) (err error) { + return r.template.ExecuteTemplate(writer, "root.tmpl", WithContext(data, ctx)) +} + func (r *renderer) RenderTimelinePage(ctx *Context, writer io.Writer, data *TimelineData) (err error) { return r.template.ExecuteTemplate(writer, "timeline.tmpl", WithContext(data, ctx)) diff --git a/service/auth.go b/service/auth.go index 4c5b38b..9e6f709 100644 --- a/service/auth.go +++ b/service/auth.go @@ -68,6 +68,22 @@ func (s *as) ServeSigninPage(ctx context.Context, c *model.Client) (err error) { return s.Service.ServeSigninPage(ctx, c) } +func (s *as) ServeRootPage(ctx context.Context, c *model.Client) (err error) { + err = s.authenticateClient(ctx, c) + if err != nil { + return + } + return s.Service.ServeRootPage(ctx, c) +} + +func (s *as) ServeNavPage(ctx context.Context, c *model.Client) (err error) { + err = s.authenticateClient(ctx, c) + if err != nil { + return + } + return s.Service.ServeNavPage(ctx, c) +} + func (s *as) ServeTimelinePage(ctx context.Context, c *model.Client, tType string, maxID string, minID string) (err error) { err = s.authenticateClient(ctx, c) @@ -382,3 +398,16 @@ func (s *as) Delete(ctx context.Context, c *model.Client, id string) (err error) } return s.Service.Delete(ctx, c, id) } + +func (s *as) ReadNotifications(ctx context.Context, c *model.Client, + maxID string) (err error) { + err = s.authenticateClient(ctx, c) + if err != nil { + return + } + err = checkCSRF(ctx, c) + if err != nil { + return + } + return s.Service.ReadNotifications(ctx, c, maxID) +} diff --git a/service/logging.go b/service/logging.go index 055dadd..795f329 100644 --- a/service/logging.go +++ b/service/logging.go @@ -34,6 +34,22 @@ func (s *ls) ServeSigninPage(ctx context.Context, c *model.Client) (err error) { return s.Service.ServeSigninPage(ctx, c) } +func (s *ls) ServeRootPage(ctx context.Context, c *model.Client) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, took=%v, err=%v\n", + "ServeRootPage", time.Since(begin), err) + }(time.Now()) + return s.Service.ServeRootPage(ctx, c) +} + +func (s *ls) ServeNavPage(ctx context.Context, c *model.Client) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, took=%v, err=%v\n", + "ServeNavPage", time.Since(begin), err) + }(time.Now()) + return s.Service.ServeNavPage(ctx, c) +} + func (s *ls) ServeTimelinePage(ctx context.Context, c *model.Client, tType string, maxID string, minID string) (err error) { defer func(begin time.Time) { @@ -276,3 +292,12 @@ func (s *ls) Delete(ctx context.Context, c *model.Client, id string) (err error) }(time.Now()) return s.Service.Delete(ctx, c, id) } + +func (s *ls) ReadNotifications(ctx context.Context, c *model.Client, + maxID string) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, max_id=%v, took=%v, err=%v\n", + "ReadNotifications", maxID, time.Since(begin), err) + }(time.Now()) + return s.Service.ReadNotifications(ctx, c, maxID) +} diff --git a/service/service.go b/service/service.go index ecd0d3f..9e01509 100644 --- a/service/service.go +++ b/service/service.go @@ -21,6 +21,8 @@ var ( type Service interface { ServeErrorPage(ctx context.Context, c *model.Client, err error) ServeSigninPage(ctx context.Context, c *model.Client) (err error) + ServeRootPage(ctx context.Context, c *model.Client) (err error) + ServeNavPage(ctx context.Context, c *model.Client) (err error) ServeTimelinePage(ctx context.Context, c *model.Client, tType string, maxID string, minID string) (err error) ServeThreadPage(ctx context.Context, c *model.Client, id string, reply bool) (err error) ServeLikedByPage(ctx context.Context, c *model.Client, id string) (err error) @@ -53,6 +55,7 @@ type Service interface { MuteConversation(ctx context.Context, c *model.Client, id string) (err error) UnMuteConversation(ctx context.Context, c *model.Client, id string) (err error) Delete(ctx context.Context, c *model.Client, id string) (err error) + ReadNotifications(ctx context.Context, c *model.Client, maxID string) (err error) } type service struct { @@ -126,45 +129,14 @@ func addToReplyMap(m map[string][]mastodon.ReplyInfo, key interface{}, } func (svc *service) getCommonData(ctx context.Context, c *model.Client, - title string) (data *renderer.CommonData, err error) { - - data = new(renderer.CommonData) - data.HeaderData = &renderer.HeaderData{ - Title: title + " - " + svc.clientName, - NotificationCount: 0, - CustomCSS: svc.customCSS, - } - - if c == nil || !c.Session.IsLoggedIn() { - return - } - - notifications, err := c.GetNotifications(ctx, nil) - if err != nil { - return nil, err - } - - var notificationCount int - for i := range notifications { - if notifications[i].Pleroma != nil && - !notifications[i].Pleroma.IsSeen { - notificationCount++ - } - } - - u, err := c.GetAccountCurrentUser(ctx) - if err != nil { - return nil, err + title string) (data *renderer.CommonData) { + data = &renderer.CommonData{ + Title: title + " - " + svc.clientName, + CustomCSS: svc.customCSS, } - - data.NavbarData = &renderer.NavbarData{ - User: u, - NotificationCount: notificationCount, + if c != nil && c.Session.IsLoggedIn() { + data.CSRFToken = c.Session.CSRFToken } - - data.HeaderData.NotificationCount = notificationCount - data.HeaderData.CSRFToken = c.Session.CSRFToken - return } @@ -174,11 +146,7 @@ func (svc *service) ServeErrorPage(ctx context.Context, c *model.Client, err err errStr = err.Error() } - commonData, err := svc.getCommonData(ctx, nil, "error") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, nil, "error") data := &renderer.ErrorData{ CommonData: commonData, Error: errStr, @@ -191,11 +159,7 @@ func (svc *service) ServeErrorPage(ctx context.Context, c *model.Client, err err func (svc *service) ServeSigninPage(ctx context.Context, c *model.Client) ( err error) { - commonData, err := svc.getCommonData(ctx, nil, "signin") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, nil, "signin") data := &renderer.SigninData{ CommonData: commonData, } @@ -204,6 +168,37 @@ func (svc *service) ServeSigninPage(ctx context.Context, c *model.Client) ( return svc.renderer.RenderSigninPage(rCtx, c.Writer, data) } +func (svc *service) ServeRootPage(ctx context.Context, c *model.Client) (err error) { + data := &renderer.RootData{ + Title: svc.clientName, + } + + rCtx := getRendererContext(c) + return svc.renderer.RenderRootPage(rCtx, c.Writer, data) +} + +func (svc *service) ServeNavPage(ctx context.Context, c *model.Client) (err error) { + u, err := c.GetAccountCurrentUser(ctx) + if err != nil { + return + } + + postContext := model.PostContext{ + DefaultVisibility: c.Session.Settings.DefaultVisibility, + Formats: svc.postFormats, + } + + commonData := svc.getCommonData(ctx, c, "Nav") + data := &renderer.NavData{ + User: u, + CommonData: commonData, + PostContext: postContext, + } + + rCtx := getRendererContext(c) + return svc.renderer.RenderNavPage(rCtx, c.Writer, data) +} + func (svc *service) ServeTimelinePage(ctx context.Context, c *model.Client, tType string, maxID string, minID string) (err error) { @@ -269,23 +264,13 @@ func (svc *service) ServeTimelinePage(ctx context.Context, c *model.Client, nextLink = fmt.Sprintf("/timeline/%s?max_id=%s", tType, pg.MaxID) } - postContext := model.PostContext{ - DefaultVisibility: c.Session.Settings.DefaultVisibility, - Formats: svc.postFormats, - } - - commonData, err := svc.getCommonData(ctx, c, tType+" timeline ") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, tType+" timeline ") data := &renderer.TimelineData{ - Title: title, - Statuses: statuses, - NextLink: nextLink, - PrevLink: prevLink, - PostContext: postContext, - CommonData: commonData, + Title: title, + Statuses: statuses, + NextLink: nextLink, + PrevLink: prevLink, + CommonData: commonData, } rCtx := getRendererContext(c) @@ -356,11 +341,7 @@ func (svc *service) ServeThreadPage(ctx context.Context, c *model.Client, addToReplyMap(replies, statuses[i].InReplyToID, statuses[i].ID, i+1) } - commonData, err := svc.getCommonData(ctx, c, "post by "+status.Account.DisplayName) - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, "post by "+status.Account.DisplayName) data := &renderer.ThreadData{ Statuses: statuses, PostContext: postContext, @@ -380,11 +361,7 @@ func (svc *service) ServeLikedByPage(ctx context.Context, c *model.Client, return } - commonData, err := svc.getCommonData(ctx, c, "likes") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, "likes") data := &renderer.LikedByData{ CommonData: commonData, Users: likers, @@ -402,11 +379,7 @@ func (svc *service) ServeRetweetedByPage(ctx context.Context, c *model.Client, return } - commonData, err := svc.getCommonData(ctx, c, "retweets") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, "retweets") data := &renderer.RetweetedByData{ CommonData: commonData, Users: retweeters, @@ -421,6 +394,7 @@ func (svc *service) ServeNotificationPage(ctx context.Context, c *model.Client, var nextLink string var unreadCount int + var readID string var pg = mastodon.Pagination{ MaxID: maxID, MinID: minID, @@ -439,23 +413,19 @@ func (svc *service) ServeNotificationPage(ctx context.Context, c *model.Client, } if unreadCount > 0 { - err := c.ReadNotifications(ctx, notifications[0].ID) - if err != nil { - return err - } + readID = notifications[0].ID } - if len(pg.MaxID) > 0 { + if len(notifications) == 20 && len(pg.MaxID) > 0 { nextLink = "/notifications?max_id=" + pg.MaxID } - commonData, err := svc.getCommonData(ctx, c, "notifications") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, "notifications") + commonData.AutoRefresh = c.Session.Settings.AutoRefreshNotifications data := &renderer.NotificationData{ Notifications: notifications, + UnreadCount: unreadCount, + ReadID: readID, NextLink: nextLink, CommonData: commonData, } @@ -521,14 +491,10 @@ func (svc *service) ServeUserPage(ctx context.Context, c *model.Client, return errInvalidArgument } - commonData, err := svc.getCommonData(ctx, c, user.DisplayName) - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, user.DisplayName) data := &renderer.UserData{ User: user, - IsCurrent: commonData.IsCurrentUser(user.ID), + IsCurrent: c.Session.UserID == user.ID, Type: pageType, Users: users, Statuses: statuses, @@ -564,11 +530,7 @@ func (svc *service) ServeUserSearchPage(ctx context.Context, c *model.Client, title += " \"" + q + "\"" } - commonData, err := svc.getCommonData(ctx, c, title) - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, title) data := &renderer.UserSearchData{ CommonData: commonData, User: user, @@ -582,11 +544,7 @@ func (svc *service) ServeUserSearchPage(ctx context.Context, c *model.Client, } func (svc *service) ServeAboutPage(ctx context.Context, c *model.Client) (err error) { - commonData, err := svc.getCommonData(ctx, c, "about") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, "about") data := &renderer.AboutData{ CommonData: commonData, } @@ -596,16 +554,12 @@ func (svc *service) ServeAboutPage(ctx context.Context, c *model.Client) (err er } func (svc *service) ServeEmojiPage(ctx context.Context, c *model.Client) (err error) { - commonData, err := svc.getCommonData(ctx, c, "emojis") - if err != nil { - return - } - emojis, err := c.GetInstanceEmojis(ctx) if err != nil { return } + commonData := svc.getCommonData(ctx, c, "emojis") data := &renderer.EmojiData{ Emojis: emojis, CommonData: commonData, @@ -636,11 +590,7 @@ func (svc *service) ServeSearchPage(ctx context.Context, c *model.Client, title += " \"" + q + "\"" } - commonData, err := svc.getCommonData(ctx, c, title) - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, title) data := &renderer.SearchData{ CommonData: commonData, Q: q, @@ -655,11 +605,7 @@ func (svc *service) ServeSearchPage(ctx context.Context, c *model.Client, } func (svc *service) ServeSettingsPage(ctx context.Context, c *model.Client) (err error) { - commonData, err := svc.getCommonData(ctx, c, "settings") - if err != nil { - return - } - + commonData := svc.getCommonData(ctx, c, "settings") data := &renderer.SettingsData{ CommonData: commonData, Settings: &c.Session.Settings, @@ -911,3 +857,8 @@ func (svc *service) Delete(ctx context.Context, c *model.Client, id string) (err error) { return c.DeleteStatus(ctx, id) } + +func (svc *service) ReadNotifications(ctx context.Context, c *model.Client, + maxID string) (err error) { + return c.ReadNotifications(ctx, maxID) +} diff --git a/service/transport.go b/service/transport.go index 5ce0e56..48e2ee2 100644 --- a/service/transport.go +++ b/service/transport.go @@ -64,14 +64,30 @@ func NewHandler(s Service, staticDir string) http.Handler { rootPage := func(w http.ResponseWriter, req *http.Request) { sessionID, _ := req.Cookie("session_id") - - location := "/signin" if sessionID != nil && len(sessionID.Value) > 0 { - location = "/timeline/home" + c := newClient(w) + ctx := newCtxWithSesion(req) + err := s.ServeRootPage(ctx, c) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + s.ServeErrorPage(ctx, c, err) + return + } + } else { + w.Header().Add("Location", "/signin") + w.WriteHeader(http.StatusFound) } + } - w.Header().Add("Location", location) - w.WriteHeader(http.StatusFound) + navPage := func(w http.ResponseWriter, req *http.Request) { + c := newClient(w) + ctx := newCtxWithSesion(req) + err := s.ServeNavPage(ctx, c) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + s.ServeErrorPage(ctx, c, err) + return + } } signinPage := func(w http.ResponseWriter, req *http.Request) { @@ -297,7 +313,7 @@ func NewHandler(s Service, staticDir string) http.Handler { return } - w.Header().Add("Location", "/timeline/home") + w.Header().Add("Location", "/") w.WriteHeader(http.StatusFound) } @@ -326,7 +342,7 @@ func NewHandler(s Service, staticDir string) http.Handler { return } - location := "/timeline/home" + "#status-" + id + location := req.Header.Get("Referer") if len(replyToID) > 0 { location = "/thread/" + replyToID + "#status-" + id } @@ -540,16 +556,18 @@ func NewHandler(s Service, staticDir string) http.Handler { copyScope := req.FormValue("copy_scope") == "true" threadInNewTab := req.FormValue("thread_in_new_tab") == "true" maskNSFW := req.FormValue("mask_nsfw") == "true" + arn := req.FormValue("auto_refresh_notifications") == "true" fluorideMode := req.FormValue("fluoride_mode") == "true" darkMode := req.FormValue("dark_mode") == "true" settings := &model.Settings{ - DefaultVisibility: visibility, - CopyScope: copyScope, - ThreadInNewTab: threadInNewTab, - MaskNSFW: maskNSFW, - FluorideMode: fluorideMode, - DarkMode: darkMode, + DefaultVisibility: visibility, + CopyScope: copyScope, + ThreadInNewTab: threadInNewTab, + MaskNSFW: maskNSFW, + AutoRefreshNotifications: arn, + FluorideMode: fluorideMode, + DarkMode: darkMode, } err := s.SaveSettings(ctx, c, settings) @@ -559,7 +577,7 @@ func NewHandler(s Service, staticDir string) http.Handler { return } - w.Header().Add("Location", req.Header.Get("Referer")) + w.Header().Add("Location", "/") w.WriteHeader(http.StatusFound) } @@ -611,6 +629,22 @@ func NewHandler(s Service, staticDir string) http.Handler { w.WriteHeader(http.StatusFound) } + readNotifications := func(w http.ResponseWriter, req *http.Request) { + c := newClient(w) + ctx := newCtxWithSesionCSRF(req, req.FormValue("csrf_token")) + maxID := req.URL.Query().Get("max_id") + + err := s.ReadNotifications(ctx, c, maxID) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + s.ServeErrorPage(ctx, c, err) + return + } + + w.Header().Add("Location", req.Header.Get("Referer")) + w.WriteHeader(http.StatusFound) + } + signout := func(w http.ResponseWriter, req *http.Request) { // TODO remove session from database http.SetCookie(w, &http.Cookie{ @@ -694,7 +728,9 @@ func NewHandler(s Service, staticDir string) http.Handler { } r.HandleFunc("/", rootPage).Methods(http.MethodGet) + r.HandleFunc("/nav", navPage).Methods(http.MethodGet) r.HandleFunc("/signin", signinPage).Methods(http.MethodGet) + r.HandleFunc("//{type}", timelinePage).Methods(http.MethodGet) r.HandleFunc("/timeline/{type}", timelinePage).Methods(http.MethodGet) r.HandleFunc("/timeline", timelineOldPage).Methods(http.MethodGet) r.HandleFunc("/thread/{id}", threadPage).Methods(http.MethodGet) @@ -726,6 +762,7 @@ func NewHandler(s Service, staticDir string) http.Handler { r.HandleFunc("/muteconv/{id}", muteConversation).Methods(http.MethodPost) r.HandleFunc("/unmuteconv/{id}", unMuteConversation).Methods(http.MethodPost) r.HandleFunc("/delete/{id}", delete).Methods(http.MethodPost) + r.HandleFunc("/notifications/read", readNotifications).Methods(http.MethodPost) r.HandleFunc("/signout", signout).Methods(http.MethodGet) r.HandleFunc("/fluoride/like/{id}", fLike).Methods(http.MethodPost) r.HandleFunc("/fluoride/unlike/{id}", fUnlike).Methods(http.MethodPost) diff --git a/static/style.css b/static/style.css index 2f80af9..a647d4f 100644 --- a/static/style.css +++ b/static/style.css @@ -460,6 +460,19 @@ a:hover, margin-top: 6px; } +.notification-title-container>* { + display: inline; +} + +.notification-title { + font-size: 18pt; + margin-right: 8px; +} + +.notification-refresh { + margin-right: 8px; +} + .dark { background-color: #222222; background-image: none; diff --git a/templates/about.tmpl b/templates/about.tmpl index b3c9a49..d4761de 100644 --- a/templates/about.tmpl +++ b/templates/about.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
About
diff --git a/templates/emoji.tmpl b/templates/emoji.tmpl index 2066afa..3e9f0f0 100644 --- a/templates/emoji.tmpl +++ b/templates/emoji.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Emojis
diff --git a/templates/error.tmpl b/templates/error.tmpl index 0d6115a..fc925ca 100644 --- a/templates/error.tmpl +++ b/templates/error.tmpl @@ -1,11 +1,11 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Error
{{.Error}}
Home - Sign In + Sign In
{{template "footer.tmpl"}} diff --git a/templates/header.tmpl b/templates/header.tmpl index 2889ead..76831f2 100644 --- a/templates/header.tmpl +++ b/templates/header.tmpl @@ -7,7 +7,10 @@ {{if .CSRFToken}} {{end}} - {{if gt .NotificationCount 0}}({{.NotificationCount}}) {{end}}{{.Title}} + {{if .AutoRefresh}} + + {{end}} + {{.Title}} {{if .CustomCSS}} diff --git a/templates/likedby.tmpl b/templates/likedby.tmpl index 00857c1..222254c 100644 --- a/templates/likedby.tmpl +++ b/templates/likedby.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Liked By
{{template "userlist.tmpl" (WithContext .Users $.Ctx)}} diff --git a/templates/nav.tmpl b/templates/nav.tmpl new file mode 100644 index 0000000..620643e --- /dev/null +++ b/templates/nav.tmpl @@ -0,0 +1,34 @@ +{{with .Data}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}} + + +{{template "postform.tmpl" (WithContext .PostContext $.Ctx)}} + +{{template "footer.tmpl"}} +{{end}} diff --git a/templates/navigation.tmpl b/templates/navigation.tmpl deleted file mode 100644 index a85f9fd..0000000 --- a/templates/navigation.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -{{with .Data}} - -{{end}} diff --git a/templates/notification.tmpl b/templates/notification.tmpl index 51cc6e3..9e1854c 100644 --- a/templates/notification.tmpl +++ b/templates/notification.tmpl @@ -1,14 +1,25 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} -
Notifications
+{{template "header.tmpl" (WithContext .CommonData $.Ctx)}} +
+
+ Notifications + {{if gt .UnreadCount 0}}({{.UnreadCount }}){{end}} +
+ refresh + {{if .ReadID}} +
+ + +
+ {{end}} +
{{range .Notifications}}
{{if eq .Type "follow"}}
@@ -31,7 +42,7 @@ {{else if eq .Type "reblog"}}
- + avatar {{EmojiFilter .Account.DisplayName .Account.Emojis}} @@ -44,7 +55,7 @@ {{else if eq .Type "favourite"}}
- + avatar {{EmojiFilter .Account.DisplayName .Account.Emojis}} diff --git a/templates/postform.tmpl b/templates/postform.tmpl index 51ac5e6..d5c1fb9 100644 --- a/templates/postform.tmpl +++ b/templates/postform.tmpl @@ -11,7 +11,7 @@ emoji list
- +
{{if gt (len .Formats) 0}} diff --git a/templates/retweetedby.tmpl b/templates/retweetedby.tmpl index ce0d337..9492ee6 100644 --- a/templates/retweetedby.tmpl +++ b/templates/retweetedby.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Retweeted By
{{template "userlist.tmpl" (WithContext .Users $.Ctx)}} diff --git a/templates/root.tmpl b/templates/root.tmpl new file mode 100644 index 0000000..cd33139 --- /dev/null +++ b/templates/root.tmpl @@ -0,0 +1,17 @@ +{{with .Data}} + + + + + + {{.Title}} + + + + + + + + + +{{end}} diff --git a/templates/search.tmpl b/templates/search.tmpl index 96548b5..ede147e 100644 --- a/templates/search.tmpl +++ b/templates/search.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Search
diff --git a/templates/settings.tmpl b/templates/settings.tmpl index e7d49e9..d8ede87 100644 --- a/templates/settings.tmpl +++ b/templates/settings.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Settings
@@ -24,11 +23,15 @@
- + +
+
+ +
- +
diff --git a/templates/signin.tmpl b/templates/signin.tmpl index a199948..069572b 100644 --- a/templates/signin.tmpl +++ b/templates/signin.tmpl @@ -1,5 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Signin
diff --git a/templates/status.tmpl b/templates/status.tmpl index 95dee20..c4f2e5f 100644 --- a/templates/status.tmpl +++ b/templates/status.tmpl @@ -2,7 +2,7 @@
{{if .Reblog}}
- + avatar {{EmojiFilter .Account.DisplayName .Account.Emojis}} @@ -14,39 +14,39 @@ {{with $s := .Data}}
{{EmojiFilter .Account.DisplayName .Account.Emojis}} - + {{.Account.Acct}} -
+
- + source {{if .Muted}} - + {{else}}
- +
{{end}} {{if eq $.Ctx.UserID .Account.ID}}
- +
{{end}}
@@ -55,7 +55,7 @@
{{if .InReplyToID}} @@ -139,16 +139,16 @@ {{end}}
{{if or (eq .Visibility "private") (eq .Visibility "direct")}} - + retweet {{else}} @@ -156,17 +156,17 @@
- +
{{else}}
- +
{{end}} {{end}} - + {{if .ReblogsCount}} ({{DisplayInteractionCount .ReblogsCount}}) {{end}}
@@ -175,22 +175,22 @@
- +
{{else}}
- +
{{end}} - + {{if .FavouritesCount}} ({{DisplayInteractionCount .FavouritesCount}}) {{end}}
+ target="{{if $.Ctx.ThreadInNewTab}}_blank{{else}}main{{end}}"> diff --git a/templates/thread.tmpl b/templates/thread.tmpl index 2927ee4..8cf9ead 100644 --- a/templates/thread.tmpl +++ b/templates/thread.tmpl @@ -1,6 +1,5 @@ {{with $s := .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
Thread
{{range .Statuses}} diff --git a/templates/timeline.tmpl b/templates/timeline.tmpl index 0321c7f..82b624d 100644 --- a/templates/timeline.tmpl +++ b/templates/timeline.tmpl @@ -1,10 +1,7 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
{{.Title}}
-{{template "postform.tmpl" (WithContext .PostContext $.Ctx)}} - {{range .Statuses}} {{template "status.tmpl" (WithContext . $.Ctx)}} {{end}} diff --git a/templates/user.tmpl b/templates/user.tmpl index de2b5c4..6ea79f7 100644 --- a/templates/user.tmpl +++ b/templates/user.tmpl @@ -1,6 +1,5 @@ {{with .Data}} -{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}} -{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}}
User