##// END OF EJS Templates
Showing unread posts count when new posts appear in the background tab
neko259 -
r468:1829c2a6 default
parent child Browse files
Show More
@@ -1,192 +1,197 b''
1 /*
1 /*
2 @licstart The following is the entire license notice for the
2 @licstart The following is the entire license notice for the
3 JavaScript code in this page.
3 JavaScript code in this page.
4
4
5
5
6 Copyright (C) 2013 neko259
6 Copyright (C) 2013 neko259
7
7
8 The JavaScript code in this page is free software: you can
8 The JavaScript code in this page is free software: you can
9 redistribute it and/or modify it under the terms of the GNU
9 redistribute it and/or modify it under the terms of the GNU
10 General Public License (GNU GPL) as published by the Free Software
10 General Public License (GNU GPL) as published by the Free Software
11 Foundation, either version 3 of the License, or (at your option)
11 Foundation, either version 3 of the License, or (at your option)
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 without even the implied warranty of MERCHANTABILITY or FITNESS
13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15
15
16 As additional permission under GNU GPL version 3 section 7, you
16 As additional permission under GNU GPL version 3 section 7, you
17 may distribute non-source (e.g., minimized or compacted) forms of
17 may distribute non-source (e.g., minimized or compacted) forms of
18 that code without the copy of the GNU GPL normally required by
18 that code without the copy of the GNU GPL normally required by
19 section 4, provided you include this license notice and a URL
19 section 4, provided you include this license notice and a URL
20 through which recipients can access the Corresponding Source.
20 through which recipients can access the Corresponding Source.
21
21
22 @licend The above is the entire license notice
22 @licend The above is the entire license notice
23 for the JavaScript code in this page.
23 for the JavaScript code in this page.
24 */
24 */
25
25
26 var THREAD_UPDATE_DELAY = 10000;
26 var THREAD_UPDATE_DELAY = 10000;
27
27
28 var loading = false;
28 var loading = false;
29 var lastUpdateTime = null;
29 var lastUpdateTime = null;
30 var unreadPosts = 0
30
31
31 function blink(node) {
32 function blink(node) {
32 var blinkCount = 2;
33 var blinkCount = 2;
33 var blinkDelay = 250;
34 var blinkDelay = 250;
34
35
35 var nodeToAnimate = node;
36 var nodeToAnimate = node;
36 for (var i = 0; i < blinkCount; i++) {
37 for (var i = 0; i < blinkCount; i++) {
37 nodeToAnimate = nodeToAnimate.fadeOut(blinkDelay).fadeIn(blinkDelay);
38 nodeToAnimate = nodeToAnimate.fadeOut(blinkDelay).fadeIn(blinkDelay);
38 }
39 }
39 }
40 }
40
41
41 function updateThread() {
42 function updateThread() {
42 if (loading) {
43 if (loading) {
43 return;
44 return;
44 }
45 }
45
46
46 loading = true;
47 loading = true;
47
48
48 var threadPosts = $('div.thread').children('.post');
49 var threadPosts = $('div.thread').children('.post');
49
50
50 var lastPost = threadPosts.last();
51 var lastPost = threadPosts.last();
51 var threadId = threadPosts.first().attr('id');
52 var threadId = threadPosts.first().attr('id');
52
53
53 var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/';
54 var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/';
54 $.getJSON(diffUrl)
55 $.getJSON(diffUrl)
55 .success(function(data) {
56 .success(function(data) {
56 var bottom = isPageBottom();
57 var bottom = isPageBottom();
57
58
58 var addedPosts = data.added;
59 var addedPosts = data.added;
59 for (var i = 0; i < addedPosts.length; i++) {
60 for (var i = 0; i < addedPosts.length; i++) {
60 var postText = addedPosts[i];
61 var postText = addedPosts[i];
61
62
62 var post = $(postText);
63 var post = $(postText);
63 post.appendTo(lastPost.parent());
64 post.appendTo(lastPost.parent());
64 addRefLinkPreview(post[0]);
65 addRefLinkPreview(post[0]);
65
66
66 lastPost = post;
67 lastPost = post;
67 blink(post);
68 blink(post);
68 }
69 }
69
70
70 var updatedPosts = data.updated;
71 var updatedPosts = data.updated;
71 for (var i = 0; i < updatedPosts.length; i++) {
72 for (var i = 0; i < updatedPosts.length; i++) {
72 var postText = updatedPosts[i];
73 var postText = updatedPosts[i];
73
74
74 var post = $(postText);
75 var post = $(postText);
75 var postId = post.attr('id');
76 var postId = post.attr('id');
76
77
77 var oldPost = $('div.thread').children('.post[id=' + postId + ']');
78 var oldPost = $('div.thread').children('.post[id=' + postId + ']');
78
79
79 oldPost.replaceWith(post);
80 oldPost.replaceWith(post);
80 addRefLinkPreview(post[0]);
81 addRefLinkPreview(post[0]);
81
82
82 blink(post);
83 blink(post);
83 }
84 }
84
85
85 // TODO Process deleted posts
86 // TODO Process deleted posts
86
87
87 lastUpdateTime = data.last_update;
88 lastUpdateTime = data.last_update;
88 loading = false;
89 loading = false;
89
90
90 if (bottom) {
91 if (bottom) {
91 var $target = $('html,body');
92 var $target = $('html,body');
92 $target.animate({scrollTop: $target.height()}, 1000);
93 $target.animate({scrollTop: $target.height()}, 1000);
93 }
94 }
94
95
95 $('#reply-count').text(getReplyCount());
96 $('#reply-count').text(getReplyCount());
96 $('#image-count').text(getImageCount());
97 $('#image-count').text(getImageCount());
97
98
98 updateBumplimitProgress(data.added.length);
99 updateBumplimitProgress(data.added.length);
99 updatePostBumpableStatus();
100 updatePostBumpableStatus();
100
101
101 if (data.added.length + data.updated.length > 0) {
102 if (data.added.length + data.updated.length > 0) {
102 showNewPostsTitle();
103 showNewPostsTitle(data.added.length);
103 }
104 }
104 })
105 })
105 .error(function(data) {
106 .error(function(data) {
106 // TODO Show error message that server is unavailable?
107 // TODO Show error message that server is unavailable?
107
108
108 loading = false;
109 loading = false;
109 });
110 });
110 }
111 }
111
112
112 function isPageBottom() {
113 function isPageBottom() {
113 var scroll = $(window).scrollTop() / ($(document).height()
114 var scroll = $(window).scrollTop() / ($(document).height()
114 - $(window).height())
115 - $(window).height())
115
116
116 return scroll == 1
117 return scroll == 1
117 }
118 }
118
119
119 function initAutoupdate() {
120 function initAutoupdate() {
120 loading = false;
121 loading = false;
121
122
122 lastUpdateTime = $('.metapanel').attr('data-last-update');
123 lastUpdateTime = $('.metapanel').attr('data-last-update');
123
124
124 setInterval(updateThread, THREAD_UPDATE_DELAY);
125 setInterval(updateThread, THREAD_UPDATE_DELAY);
125 }
126 }
126
127
127 function getReplyCount() {
128 function getReplyCount() {
128 return $('.thread').children('.post').length
129 return $('.thread').children('.post').length
129 }
130 }
130
131
131 function getImageCount() {
132 function getImageCount() {
132 return $('.thread').find('img').length
133 return $('.thread').find('img').length
133 }
134 }
134
135
135 /**
136 /**
136 * Update bumplimit progress bar
137 * Update bumplimit progress bar
137 */
138 */
138 function updateBumplimitProgress(postDelta) {
139 function updateBumplimitProgress(postDelta) {
139 var progressBar = $('#bumplimit_progress');
140 var progressBar = $('#bumplimit_progress');
140 if (progressBar) {
141 if (progressBar) {
141 var postsToLimitElement = $('#left_to_limit');
142 var postsToLimitElement = $('#left_to_limit');
142
143
143 var oldPostsToLimit = parseInt(postsToLimitElement.text());
144 var oldPostsToLimit = parseInt(postsToLimitElement.text());
144 var postCount = getReplyCount();
145 var postCount = getReplyCount();
145 var bumplimit = postCount - postDelta + oldPostsToLimit;
146 var bumplimit = postCount - postDelta + oldPostsToLimit;
146
147
147 var newPostsToLimit = bumplimit - postCount;
148 var newPostsToLimit = bumplimit - postCount;
148 if (newPostsToLimit <= 0) {
149 if (newPostsToLimit <= 0) {
149 $('.bar-bg').remove();
150 $('.bar-bg').remove();
150 } else {
151 } else {
151 postsToLimitElement.text(newPostsToLimit);
152 postsToLimitElement.text(newPostsToLimit);
152 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
153 progressBar.width((100 - postCount / bumplimit * 100.0) + '%');
153 }
154 }
154 }
155 }
155 }
156 }
156
157
157 /**
158 /**
158 * If the bumplimit is reached, add dead_post class to all posts
159 * If the bumplimit is reached, add dead_post class to all posts
159 */
160 */
160 function updatePostBumpableStatus() {
161 function updatePostBumpableStatus() {
161 var postCount = getReplyCount();
162 var postCount = getReplyCount();
162 var postsToLimitElement = $('#left_to_limit');
163 var postsToLimitElement = $('#left_to_limit');
163 var postsToLimit = parseInt(postsToLimitElement.text());
164 var postsToLimit = parseInt(postsToLimitElement.text());
164
165
165 if (postsToLimit <= 0) {
166 if (postsToLimit <= 0) {
166 $('.thread').find('.post').addClass('dead_post');
167 $('.thread').find('.post').addClass('dead_post');
167 }
168 }
168 }
169 }
169
170
170 var documentOriginalTitle = '';
171 var documentOriginalTitle = '';
171 /**
172 /**
172 * Show 'new posts' text in the title if the document is not visible to a user
173 * Show 'new posts' text in the title if the document is not visible to a user
173 */
174 */
174 function showNewPostsTitle() {
175 function showNewPostsTitle(newPostCount) {
175 if (document.hidden) {
176 if (document.hidden) {
176 documentOriginalTitle = document.title;
177 if (documentOriginalTitle === '') {
177 document.title = gettext('[new posts]') + ' ' + document.title;
178 documentOriginalTitle = document.title;
179 }
180 unreadPosts = unreadPosts + newPostCount;
181 document.title = '[' + unreadPosts + '] ' + documentOriginalTitle;
178
182
179 document.addEventListener('visibilitychange', function() {
183 document.addEventListener('visibilitychange', function() {
180 if (documentOriginalTitle !== '') {
184 if (documentOriginalTitle !== '') {
181 document.title = documentOriginalTitle;
185 document.title = documentOriginalTitle;
182 documentOriginalTitle = '';
186 documentOriginalTitle = '';
187 unreadPosts = 0;
183 }
188 }
184
189
185 document.removeEventListener('visibilitychange', null);
190 document.removeEventListener('visibilitychange', null);
186 });
191 });
187 }
192 }
188 }
193 }
189
194
190 $(document).ready(function(){
195 $(document).ready(function(){
191 initAutoupdate();
196 initAutoupdate();
192 });
197 });
General Comments 0
You need to be logged in to leave comments. Login now