Fix issues related to AntiDopamine mode
[bloat] / static / fluoride.js
1 // @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0
2
3 var reverseActions = {
4         "like": "unlike",
5         "unlike": "like",
6         "retweet": "unretweet",
7         "unretweet": "retweet"
8 };
9
10 var csrfToken = "";
11 var antiDopamineMode = false;
12
13 function checkCSRFToken() {
14         var tag = document.querySelector("meta[name='csrf_token']");
15         if (tag)
16                 csrfToken = tag.getAttribute("content");
17 }
18
19 function checkAntiDopamineMode() {
20         var tag = document.querySelector("meta[name='antidopamine_mode']");
21         if (tag)
22                 antiDopamineMode = tag.getAttribute("content") === "true";
23 }
24
25 function http(method, url, body, type, success, error) {
26         var req = new XMLHttpRequest();
27         req.onload = function() {
28                 if (this.status === 200 && typeof success === "function") {
29                         success(this.responseText, this.responseType);
30                 } else if (typeof error === "function") {
31                         error(this.responseText);
32                 }
33         };
34         req.onerror = function() {
35                 if (typeof error === "function") {
36                         error(this.responseText);
37                 }
38         };
39         req.open(method, url);
40         req.setRequestHeader("Content-Type", type);
41         req.send(body);
42 }
43
44 function updateActionForm(id, f, action) {
45         f.querySelector("[type='submit']").value = action;
46         f.action = "/" + action + "/" + id;
47         f.dataset.action = action;
48 }
49
50 function handleLikeForm(id, f) {
51         f.onsubmit = function(event) {
52                 event.preventDefault();
53
54                 var action = f.dataset.action;
55                 var forms = document.
56                         querySelectorAll(".status-"+id+" .status-like");
57                 for (var i = 0; i < forms.length; i++) {
58                         updateActionForm(id, forms[i], reverseActions[action]);
59                 }
60
61                 var body = "csrf_token=" + encodeURIComponent(csrfToken);
62                 var contentType = "application/x-www-form-urlencoded";
63                 http("POST", "/fluoride/" + action + "/" + id, 
64                         body, contentType, function(res, type) {
65
66                         if (antiDopamineMode)
67                                 return;
68                         var data = JSON.parse(res);
69                         var count = data.data;
70                         if (count === 0)
71                                 count = "";
72                         var counts = document.
73                                 querySelectorAll(".status-"+id+" .status-like-count");
74                         for (var i = 0; i < counts.length; i++) {
75                                 if (count > 0) {
76                                         counts[i].innerHTML = "(" + count + ")";
77                                 } else {
78                                         counts[i].innerHTML = "";
79                                 }
80                         }
81                 }, function(err) {
82                         for (var i = 0; i < forms.length; i++) {
83                                 updateActionForm(id, forms[i], action);
84                         }
85                 });
86         }
87 }
88
89 function handleRetweetForm(id, f) {
90         f.onsubmit = function(event) {
91                 event.preventDefault();
92
93                 var action = f.dataset.action;
94                 var forms = document.
95                         querySelectorAll(".status-"+id+" .status-retweet");
96                 for (var i = 0; i < forms.length; i++) {
97                         updateActionForm(id, forms[i], reverseActions[action]);
98                 }
99
100                 var body = "csrf_token=" + encodeURIComponent(csrfToken);
101                 var contentType = "application/x-www-form-urlencoded";
102                 http("POST", "/fluoride/" + action + "/" + id, 
103                         body, contentType, function(res, type) {
104
105                         if (antiDopamineMode)
106                                 return;
107                         var data = JSON.parse(res);
108                         var count = data.data;
109                         if (count === 0)
110                                 count = "";
111                         var counts = document.
112                                 querySelectorAll(".status-"+id+" .status-retweet-count");
113                         for (var i = 0; i < counts.length; i++) {
114                                 if (count > 0) {
115                                         counts[i].innerHTML = "(" + count + ")";
116                                 } else {
117                                         counts[i].innerHTML = "";
118                                 }
119                         }
120                 }, function(err) {
121                         for (var i = 0; i < forms.length; i++) {
122                                 updateActionForm(id, forms[i], action);
123                         }
124                 });
125         }
126 }
127
128 function isInView(el) {
129         var ract = el.getBoundingClientRect();
130         if (ract.top > 0 && ract.bottom < window.innerHeight)
131                 return true;
132         return false;
133 }
134
135 function handleReplyToLink(div) {
136         if (!div)
137                 return;
138         var id = div.firstElementChild.getAttribute("href");
139         if (!id || id[0] != "#")
140                 return;
141         div.firstElementChild.onmouseenter = function(event) {
142                 var id = event.target.getAttribute("href");
143                 var status = document.querySelector(id);
144                 if (!status)
145                         return;
146                 if (isInView(status)) {
147                         status.classList.add("highlight");
148                 } else {
149                         var copy = status.cloneNode(true);
150                         copy.id = "reply-to-popup";
151                         var ract = event.target.getBoundingClientRect();
152                         if (ract.top > window.innerHeight / 2) {
153                                 copy.style.bottom = (window.innerHeight - 
154                                         window.scrollY - ract.top) + "px";
155                         }
156                         event.target.parentElement.appendChild(copy);
157                 }
158         }
159         div.firstElementChild.onmouseleave = function(event) {
160                 var popup = document.getElementById("reply-to-popup");
161                 if (popup) {
162                         event.target.parentElement.removeChild(popup);    
163                 } else {
164                         var id = event.target.getAttribute("href");
165                         document.querySelector(id)
166                                 .classList.remove("highlight");
167                 }
168         }
169 }
170
171 function handleReplyLink(div) {
172         div.firstElementChild.onmouseenter = function(event) {
173                 var id = event.target.getAttribute("href");
174                 var status = document.querySelector(id);
175                 if (!status)
176                         return;
177                 if (isInView(status)) {
178                         status.classList.add("highlight");
179                 } else {
180                         var copy = status.cloneNode(true);
181                         copy.id = "reply-popup";
182                         var ract = event.target.getBoundingClientRect();
183                         if (ract.left > window.innerWidth / 2) {
184                                 copy.style.right = (window.innerWidth -
185                                         ract.right - 12) + "px";
186                         }
187                         event.target.parentElement.appendChild(copy);
188                 }
189         }
190         div.firstElementChild.onmouseleave = function(event) {
191                 var popup = document.getElementById("reply-popup");
192                 if (popup) {
193                         event.target.parentElement.removeChild(popup);
194                 } else {
195                         var id = event.target.getAttribute("href");
196                         document.querySelector(id).classList.remove("highlight");
197                 }
198         }
199 }
200
201 function handleStatusLink(a) {
202         if (a.classList.contains("mention"))
203                 return;
204         a.target = "_blank";
205 }
206
207 document.addEventListener("DOMContentLoaded", function() { 
208         checkCSRFToken();
209         checkAntiDopamineMode();
210
211         var statuses = document.querySelectorAll(".status-container");
212         for (var i = 0; i < statuses.length; i++) {
213                 var s = statuses[i];
214                 var id = s.dataset.id;
215
216                 var likeForm = s.querySelector(".status-like");
217                 handleLikeForm(id, likeForm);
218
219                 var retweetForm = s.querySelector(".status-retweet");
220                 handleRetweetForm(id, retweetForm);
221
222                 var replyToLink = s.querySelector(".status-reply-to");
223                 handleReplyToLink(replyToLink);
224
225                 var replyLinks = s.querySelectorAll(".status-reply");
226                 for (var j = 0; j < replyLinks.length; j++) {
227                         handleReplyLink(replyLinks[j]);
228                 }
229
230                 var links = s.querySelectorAll(".status-content a");
231                 for (var j = 0; j < links.length; j++) {
232                         handleStatusLink(links[j]);
233                 }
234         }
235 });
236
237 // @license-end