diff options
| author | r <r@freesoftwareextremist.com> | 2020-11-09 12:10:29 +0000 | 
|---|---|---|
| committer | r <r@freesoftwareextremist.com> | 2020-11-09 12:10:29 +0000 | 
| commit | c3f39210d8451d65f3ecaa88046380f42dc536a1 (patch) | |
| tree | d43280e9c56ecebd8270722bcf043a19b1cd757d | |
| parent | 3a3a8672ba3c9c6fd6905e2273c72b4ab36db552 (diff) | |
| download | bloat-c3f39210d8451d65f3ecaa88046380f42dc536a1.tar.gz bloat-c3f39210d8451d65f3ecaa88046380f42dc536a1.zip | |
Add fluoridated reply to popup
| -rw-r--r-- | renderer/model.go | 5 | ||||
| -rw-r--r-- | renderer/renderer.go | 1 | ||||
| -rw-r--r-- | service/auth.go | 8 | ||||
| -rw-r--r-- | service/logging.go | 8 | ||||
| -rw-r--r-- | service/service.go | 10 | ||||
| -rw-r--r-- | service/transport.go | 13 | ||||
| -rw-r--r-- | static/fluoride.js | 76 | ||||
| -rw-r--r-- | templates/statuspopup.tmpl | 15 | 
8 files changed, 128 insertions, 8 deletions
| diff --git a/renderer/model.go b/renderer/model.go index 0e5204a..0505c0b 100644 --- a/renderer/model.go +++ b/renderer/model.go @@ -63,6 +63,11 @@ type ThreadData struct {  	ReplyMap    map[string][]mastodon.ReplyInfo  } +type StatusData struct { +	*CommonData +	Status    *mastodon.Status +} +  type NotificationData struct {  	*CommonData  	Notifications []*mastodon.Notification diff --git a/renderer/renderer.go b/renderer/renderer.go index 3d4685f..724178e 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -20,6 +20,7 @@ const (  	RootPage         = "root.tmpl"  	TimelinePage     = "timeline.tmpl"  	ThreadPage       = "thread.tmpl" +	StatusPopup      = "status.tmpl"  	NotificationPage = "notification.tmpl"  	UserPage         = "user.tmpl"  	UserSearchPage   = "usersearch.tmpl" diff --git a/service/auth.go b/service/auth.go index 7845675..c670130 100644 --- a/service/auth.go +++ b/service/auth.go @@ -107,6 +107,14 @@ func (s *as) ServeThreadPage(c *model.Client, id string, reply bool) (err error)  	return s.Service.ServeThreadPage(c, id, reply)  } +func (s *as) ServeStatusPopup(c *model.Client, id string) (err error) { +	err = s.authenticateClient(c) +	if err != nil { +		return +	} +	return s.Service.ServeStatusPopup(c, id) +} +  func (s *as) ServeLikedByPage(c *model.Client, id string) (err error) {  	err = s.authenticateClient(c)  	if err != nil { diff --git a/service/logging.go b/service/logging.go index 3cb99bf..d283a55 100644 --- a/service/logging.go +++ b/service/logging.go @@ -67,6 +67,14 @@ func (s *ls) ServeThreadPage(c *model.Client, id string,  	return s.Service.ServeThreadPage(c, id, reply)  } +func (s *ls) ServeStatusPopup(c *model.Client, id string) (err error) { +	defer func(begin time.Time) { +		s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n", +			"ServeStatusPopup", id, time.Since(begin), err) +	}(time.Now()) +	return s.Service.ServeStatusPopup(c, id) +} +  func (s *ls) ServeLikedByPage(c *model.Client, id string) (err error) {  	defer func(begin time.Time) {  		s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n", diff --git a/service/service.go b/service/service.go index 48aafda..82ff972 100644 --- a/service/service.go +++ b/service/service.go @@ -28,6 +28,7 @@ type Service interface {  	ServeTimelinePage(c *model.Client, tType string, maxID string,  		minID string) (err error)  	ServeThreadPage(c *model.Client, id string, reply bool) (err error) +	ServeStatusPopup(c *model.Client, id string) (err error)  	ServeLikedByPage(c *model.Client, id string) (err error)  	ServeRetweetedByPage(c *model.Client, id string) (err error)  	ServeNotificationPage(c *model.Client, maxID string, minID string) (err error) @@ -365,6 +366,15 @@ func (svc *service) ServeThreadPage(c *model.Client, id string, reply bool) (err  	return svc.renderer.Render(rCtx, c.Writer, renderer.ThreadPage, data)  } +func (svc *service) ServeStatusPopup(c *model.Client, id string) (err error) { +	status, err := c.GetStatus(ctx, id) +	if err != nil { +		return +	} +	rCtx := getRendererContext(c) +	return svc.renderer.Render(rCtx, c.Writer, renderer.StatusPopup, status) +} +  func (svc *service) ServeLikedByPage(c *model.Client, id string) (err error) {  	likers, err := c.GetFavouritedBy(ctx, id, nil)  	if err != nil { diff --git a/service/transport.go b/service/transport.go index 6c0975d..bacb19d 100644 --- a/service/transport.go +++ b/service/transport.go @@ -62,6 +62,7 @@ func serveJson(w io.Writer, data interface{}) (err error) {  func serveJsonError(w http.ResponseWriter, err error) {  	var d = make(map[string]interface{})  	d["error"] = err.Error() +	w.Header().Set("Content-Type", "application/json")  	w.WriteHeader(http.StatusInternalServerError)  	json.NewEncoder(w).Encode(d)  	return @@ -796,6 +797,17 @@ func NewHandler(s Service, staticDir string) http.Handler {  		}  	} +	statusPopup := func(w http.ResponseWriter, req *http.Request) { +		c := newClient(w, req, "") +		id, _ := mux.Vars(req)["id"] + +		err := s.ServeStatusPopup(c, id) +		if err != nil { +			serveJsonError(w, err) +			return +		} +	} +  	r.HandleFunc("/", rootPage).Methods(http.MethodGet)  	r.HandleFunc("/nav", navPage).Methods(http.MethodGet)  	r.HandleFunc("/signin", signinPage).Methods(http.MethodGet) @@ -840,6 +852,7 @@ func NewHandler(s Service, staticDir string) http.Handler {  	r.HandleFunc("/fluoride/unlike/{id}", fUnlike).Methods(http.MethodPost)  	r.HandleFunc("/fluoride/retweet/{id}", fRetweet).Methods(http.MethodPost)  	r.HandleFunc("/fluoride/unretweet/{id}", fUnretweet).Methods(http.MethodPost) +	r.HandleFunc("/fluoride/status/{id}", statusPopup).Methods(http.MethodGet)  	r.PathPrefix("/static").Handler(http.StripPrefix("/static",  		http.FileServer(http.Dir(staticDir)))) diff --git a/static/fluoride.js b/static/fluoride.js index c1eb06f..9cf318b 100644 --- a/static/fluoride.js +++ b/static/fluoride.js @@ -7,6 +7,8 @@ var reverseActions = {  	"unretweet": "retweet"  }; +var statusCache = {}; +  var csrfToken = "";  var antiDopamineMode = false; @@ -33,11 +35,12 @@ function http(method, url, body, type, success, error) {  	};  	req.onerror = function() {  		if (typeof error === "function") { -			error(this.responseText); +			error(this);  		}  	};  	req.open(method, url); -	req.setRequestHeader("Content-Type", type); +	if (type) +		req.setRequestHeader("Content-Type", type);  	req.send(body);  } @@ -132,12 +135,7 @@ function isInView(el) {  	return false;  } -function handleReplyToLink(a) { -	if (!a) -		return; -	var id = a.getAttribute("href"); -	if (!id || id[0] != "#") -		return; +function replyToLinkLocal(a) {  	a.onmouseenter = function(event) {  		var id = event.target.getAttribute("href");  		var status = document.querySelector(id); @@ -168,6 +166,68 @@ function handleReplyToLink(a) {  	}  } +var inMouseEnter = false; +function replyToLinkRemote(a) { +	a.onmouseenter = function(event) { +		inMouseEnter = true; +		var id = event.target.getAttribute("href"); +		var arr = id.replace("/thread", "").split("#"); +		if (arr.length < 2) +			return +		id = arr[1].replace("status-", ""); +		if (statusCache[id]) { +			var copy = document.createElement("div"); +			copy.innerHTML = statusCache[id]; +			copy = copy.firstElementChild; +			copy.id = "reply-to-popup"; +			var ract = event.target.getBoundingClientRect(); +			if (ract.top > window.innerHeight / 2) { +				copy.style.bottom = (window.innerHeight -  +					window.scrollY - ract.top) + "px"; +			} +			event.target.parentElement.appendChild(copy); +		} else { +			http("GET", "/fluoride/status/"+id, null, null, function(res, type) { +				statusCache[id] = res; +				if (!inMouseEnter) +					return; +				var copy = document.createElement("div"); +				copy.innerHTML = res; +				copy = copy.firstElementChild; +				copy.id = "reply-to-popup"; +				var ract = event.target.getBoundingClientRect(); +				if (ract.top > window.innerHeight / 2) { +					copy.style.bottom = (window.innerHeight -  +						window.scrollY - ract.top) + "px"; +				} +				event.target.parentElement.appendChild(copy); +			}, function(err) { +				console.log("error:", err); +			}) +		} +	} +	a.onmouseleave = function(event) { +		inMouseEnter = false; +		var popup = document.getElementById("reply-to-popup"); +		if (popup) { +			popup.parentElement.removeChild(popup);     +		}  +	} +} + +function handleReplyToLink(a) { +	if (!a) +		return; +	var id = a.getAttribute("href"); +	if (!id) +		return; +	if (id[0] === "#") { +		replyToLinkLocal(a); +	} else if (id.indexOf("/thread/") === 0) { +		replyToLinkRemote(a); +	} +} +  function handleReplyLink(a) {  	a.onmouseenter = function(event) {  		var id = event.target.getAttribute("href"); diff --git a/templates/statuspopup.tmpl b/templates/statuspopup.tmpl new file mode 100644 index 0000000..8cf9ead --- /dev/null +++ b/templates/statuspopup.tmpl @@ -0,0 +1,15 @@ +{{with $s := .Data}} +{{template "header.tmpl" (WithContext .CommonData $.Ctx)}} +<div class="page-title"> Thread </div> + +{{range .Statuses}} + +{{template "status.tmpl" (WithContext . $.Ctx)}} +{{if $s.PostContext.ReplyContext}}{{if eq .ID $s.PostContext.ReplyContext.InReplyToID}} +{{template "postform.tmpl" (WithContext $s.PostContext $.Ctx)}} +{{end}}{{end}} + +{{end}} + +{{template "footer.tmpl"}} +{{end}} | 
