diff --git a/mastodon/status.go b/mastodon/status.go index 06fdd20..e6e247f 100644 --- a/mastodon/status.go +++ b/mastodon/status.go @@ -57,6 +57,7 @@ type Status struct { ThreadInNewTab bool `json:"thread_in_new_tab"` MaskNSFW bool `json:"mask_nsfw"` RetweetedByID string `json:"retweeted_by_id"` + DarkMode bool `json:"dark_mode"` } // Context hold information for mastodon context. diff --git a/model/postContext.go b/model/postContext.go index 3098437..58997f7 100644 --- a/model/postContext.go +++ b/model/postContext.go @@ -9,6 +9,7 @@ type PostContext struct { DefaultVisibility string ReplyContext *ReplyContext Formats []PostFormat + DarkMode bool } type ReplyContext struct { diff --git a/model/settings.go b/model/settings.go index b8eeffc..7d22747 100644 --- a/model/settings.go +++ b/model/settings.go @@ -6,6 +6,7 @@ type Settings struct { ThreadInNewTab bool `json:"thread_in_new_tab"` MaskNSFW bool `json:"mask_nfsw"` FluorideMode bool `json:"fluoride_mode"` + DarkMode bool `json:"dark_mode"` } func NewSettings() *Settings { @@ -15,5 +16,6 @@ func NewSettings() *Settings { ThreadInNewTab: false, MaskNSFW: true, FluorideMode: false, + DarkMode: false, } } diff --git a/renderer/model.go b/renderer/model.go index 102ce55..64b9946 100644 --- a/renderer/model.go +++ b/renderer/model.go @@ -10,6 +10,7 @@ type HeaderData struct { NotificationCount int CustomCSS string FluorideMode bool + DarkMode bool } type NavbarData struct { @@ -58,6 +59,7 @@ type NotificationData struct { Notifications []*mastodon.Notification HasNext bool NextLink string + DarkMode bool } type UserData struct { @@ -66,6 +68,7 @@ type UserData struct { Statuses []*mastodon.Status HasNext bool NextLink string + DarkMode bool } type AboutData struct { diff --git a/renderer/renderer.go b/renderer/renderer.go index 4065312..42bffad 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -11,6 +11,39 @@ import ( "mastodon" ) +var ( + icons = map[string]string{ + "envelope": "/static/icons/envelope.png", + "dark-envelope": "/static/icons/dark-envelope.png", + "globe": "/static/icons/globe.png", + "dark-globe": "/static/icons/dark-globe.png", + "liked": "/static/icons/liked.png", + "dark-liked": "/static/icons/liked.png", + "link": "/static/icons/link.png", + "dark-link": "/static/icons/dark-link.png", + "lock": "/static/icons/lock.png", + "dark-lock": "/static/icons/dark-lock.png", + "mail-forward": "/static/icons/mail-forward.png", + "dark-mail-forward": "/static/icons/dark-mail-forward.png", + "reply": "/static/icons/reply.png", + "dark-reply": "/static/icons/dark-reply.png", + "retweet": "/static/icons/retweet.png", + "dark-retweet": "/static/icons/dark-retweet.png", + "retweeted": "/static/icons/retweeted.png", + "dark-retweeted": "/static/icons/retweeted.png", + "smile-o": "/static/icons/smile-o.png", + "dark-smile-o": "/static/icons/dark-smile-o.png", + "star-o": "/static/icons/star-o.png", + "dark-star-o": "/static/icons/dark-star-o.png", + "star": "/static/icons/star.png", + "dark-star": "/static/icons/dark-star.png", + "unlock-alt": "/static/icons/unlock-alt.png", + "dark-unlock-alt": "/static/icons/dark-unlock-alt.png", + "user-plus": "/static/icons/user-plus.png", + "dark-user-plus": "/static/icons/dark-user-plus.png", + } +) + type Renderer interface { RenderErrorPage(ctx context.Context, writer io.Writer, data *ErrorData) RenderHomePage(ctx context.Context, writer io.Writer, data *HomePageData) (err error) @@ -42,6 +75,7 @@ func NewRenderer(templateGlobPattern string) (r *renderer, err error) { "TimeSince": TimeSince, "FormatTimeRFC3339": FormatTimeRFC3339, "FormatTimeRFC822": FormatTimeRFC822, + "GetIcon": GetIcon, }).ParseGlob(templateGlobPattern) if err != nil { return @@ -180,3 +214,11 @@ func FormatTimeRFC3339(t time.Time) string { func FormatTimeRFC822(t time.Time) string { return t.Format(time.RFC822) } + +func GetIcon(name string, darkMode bool) (icon string) { + if darkMode { + name = "dark-" + name + } + icon, _ = icons[name] + return +} diff --git a/service/service.go b/service/service.go index f43c463..b3c2103 100644 --- a/service/service.go +++ b/service/service.go @@ -281,10 +281,12 @@ func (svc *service) ServeTimelinePage(ctx context.Context, client io.Writer, for i := range statuses { statuses[i].ThreadInNewTab = c.Session.Settings.ThreadInNewTab statuses[i].MaskNSFW = c.Session.Settings.MaskNSFW + statuses[i].DarkMode = c.Session.Settings.DarkMode if statuses[i].Reblog != nil { statuses[i].Reblog.RetweetedByID = statuses[i].ID statuses[i].Reblog.ThreadInNewTab = c.Session.Settings.ThreadInNewTab statuses[i].Reblog.MaskNSFW = c.Session.Settings.MaskNSFW + statuses[i].Reblog.DarkMode = c.Session.Settings.DarkMode } } @@ -317,6 +319,7 @@ func (svc *service) ServeTimelinePage(ctx context.Context, client io.Writer, postContext := model.PostContext{ DefaultVisibility: c.Session.Settings.DefaultVisibility, Formats: svc.postFormats, + DarkMode: c.Session.Settings.DarkMode, } commonData, err := svc.getCommonData(ctx, client, c, timelineType+" timeline ") @@ -385,6 +388,7 @@ func (svc *service) ServeThreadPage(ctx context.Context, client io.Writer, c *mo InReplyToName: status.Account.Acct, ReplyContent: content, }, + DarkMode: c.Session.Settings.DarkMode, } } @@ -401,6 +405,7 @@ func (svc *service) ServeThreadPage(ctx context.Context, client io.Writer, c *mo statuses[i].ShowReplies = true statuses[i].ReplyMap = replyMap statuses[i].MaskNSFW = c.Session.Settings.MaskNSFW + statuses[i].DarkMode = c.Session.Settings.DarkMode addToReplyMap(replyMap, statuses[i].InReplyToID, statuses[i].ID, i+1) } @@ -444,6 +449,7 @@ func (svc *service) ServeNotificationPage(ctx context.Context, client io.Writer, if notifications[i].Status != nil { notifications[i].Status.CreatedAt = notifications[i].CreatedAt notifications[i].Status.MaskNSFW = c.Session.Settings.MaskNSFW + notifications[i].Status.DarkMode = c.Session.Settings.DarkMode switch notifications[i].Type { case "reblog", "favourite": notifications[i].Status.HideAccountInfo = true @@ -476,6 +482,7 @@ func (svc *service) ServeNotificationPage(ctx context.Context, client io.Writer, HasNext: hasNext, NextLink: nextLink, CommonData: commonData, + DarkMode: c.Session.Settings.DarkMode, } err = svc.renderer.RenderNotificationPage(ctx, client, data) if err != nil { @@ -507,8 +514,10 @@ func (svc *service) ServeUserPage(ctx context.Context, client io.Writer, c *mode for i := range statuses { statuses[i].MaskNSFW = c.Session.Settings.MaskNSFW + statuses[i].DarkMode = c.Session.Settings.DarkMode if statuses[i].Reblog != nil { statuses[i].Reblog.MaskNSFW = c.Session.Settings.MaskNSFW + statuses[i].Reblog.DarkMode = c.Session.Settings.DarkMode } } @@ -528,6 +537,7 @@ func (svc *service) ServeUserPage(ctx context.Context, client io.Writer, c *mode HasNext: hasNext, NextLink: nextLink, CommonData: commonData, + DarkMode: c.Session.Settings.DarkMode, } err = svc.renderer.RenderUserPage(ctx, client, data) @@ -723,6 +733,7 @@ func (svc *service) ServeSearchPage(ctx context.Context, client io.Writer, c *mo hasNext = len(results.Statuses) == 20 for i := range results.Statuses { results.Statuses[i].MaskNSFW = c.Session.Settings.MaskNSFW + results.Statuses[i].DarkMode = c.Session.Settings.DarkMode } } @@ -827,6 +838,7 @@ func (svc *service) getCommonData(ctx context.Context, client io.Writer, c *mode data.HeaderData.NotificationCount = notificationCount data.HeaderData.FluorideMode = c.Session.Settings.FluorideMode + data.HeaderData.DarkMode = c.Session.Settings.DarkMode } return diff --git a/service/transport.go b/service/transport.go index d89b854..0072f95 100644 --- a/service/transport.go +++ b/service/transport.go @@ -448,12 +448,14 @@ func NewHandler(s Service, staticDir string) http.Handler { threadInNewTab := req.FormValue("thread_in_new_tab") == "true" maskNSFW := req.FormValue("mask_nsfw") == "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, } err := s.SaveSettings(ctx, w, nil, settings) diff --git a/static/fluoride.js b/static/fluoride.js index 25ab4a3..6a1b5fb 100644 --- a/static/fluoride.js +++ b/static/fluoride.js @@ -1,8 +1,12 @@ var actionIcons = { "like": "/static/icons/star-o.png", + "dark-like": "/static/icons/dark-star-o.png", "unlike": "/static/icons/liked.png", + "dark-unlike": "/static/icons/liked.png", "retweet": "/static/icons/retweet.png", - "unretweet": "/static/icons/retweeted.png" + "dark-retweet": "/static/icons/dark-retweet.png", + "unretweet": "/static/icons/retweeted.png", + "dark-unretweet": "/static/icons/retweeted.png" }; var reverseActions = { @@ -31,7 +35,11 @@ function http(method, url, success, error) { } function updateActionForm(id, f, action) { - f.children[1].src = actionIcons[action]; + if (Array.from(document.body.classList).indexOf("dark") > -1) { + f.children[1].src = actionIcons["dark-" + action]; + } else { + f.children[1].src = actionIcons[action]; + } f.action = "/" + action + "/" + id; f.dataset.action = action; } diff --git a/static/main.css b/static/main.css index 553c9a2..acbca05 100644 --- a/static/main.css +++ b/static/main.css @@ -99,8 +99,8 @@ } .status-action a:hover, -.status-action a:hover i { - opacity: 0.8; +.status-action input:hover { + opacity: 0.6; } .status-action a.status-time { @@ -442,3 +442,29 @@ z-index: 3; margin: 0 8px 0 8px; } + +.dark { + background-color: #222222; + background-image: none; + color: #eaeaea; +} + +.dark a { + color: #81a2be; +} + +.dark .status-action a { + color: #999999; +} + +.dark #post-content { + background-color: #333333; + border: 1px solid #444444; + color: #eaeaea; +} + +.dark #reply-popup, +.dark #reply-to-popup { + background-color: #222222; + border-color: #444444; +} diff --git a/templates/header.tmpl b/templates/header.tmpl index d511590..10afe8a 100644 --- a/templates/header.tmpl +++ b/templates/header.tmpl @@ -12,4 +12,4 @@ {{end}} -
+ diff --git a/templates/notification.tmpl b/templates/notification.tmpl index d68382f..79d6d90 100644 --- a/templates/notification.tmpl +++ b/templates/notification.tmpl @@ -14,7 +14,7 @@