From 57d65aa22af1288abbae919377d8571442970741 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 28 Mar 2013 03:10:50 +0100 Subject: [PATCH 1/9] Notify users of available updates. #968 --- package.json | 1 + src/features.coffee | 5 +++-- src/main.coffee | 35 +++++++++++++++++++++++++++++++---- src/metadata.js | 4 ++-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 32095fc07..dc63399f9 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "name": "4chan X Beta", "repo": "https://github.com/MayhemYDG/4chan-x/", "page": "https://4chan-x.just-believe.in/", + "buildsPath": "builds/", "mainBranch": "v3", "matches": [ "*://api.4chan.org/*", diff --git a/src/features.coffee b/src/features.coffee index 4549e58ca..e4ffc5d31 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -210,9 +210,10 @@ Settings = order: 110 open: -> Conf['Enable 4chan\'s Extension'] - unless $.get 'previousversion' + if (prevVersion = $.get 'previousversion', null) isnt g.VERSION + $.set 'lastupdate', Date.now() $.set 'previousversion', g.VERSION - $.on d, '4chanXInitFinished', Settings.open + $.on d, '4chanXInitFinished', Settings.open unless prevVersion Settings.addSection 'Main', Settings.main Settings.addSection 'Filter', Settings.filter diff --git a/src/main.coffee b/src/main.coffee index d6639bce2..317c7e7af 100644 --- a/src/main.coffee +++ b/src/main.coffee @@ -457,6 +457,7 @@ Main = Main.callbackNodes Post, posts $.event '4chanXInitFinished' + Main.checkUpdate() callbackNodes: (klass, nodes) -> # get the nodes' length only once @@ -480,13 +481,39 @@ Main = obj = e.detail unless typeof obj.callback.name is 'string' throw new Error "Invalid callback name: #{obj.callback.name}" - Klass = if obj.type is 'Post' - Post - else - Thread + switch obj.type + when 'Post' + Klass = Post + when 'Thread' + Klass = Thread + else + return obj.callback.isAddon = true Klass::callbacks.push obj.callback + checkUpdate: -> + return unless Main.isThisPageLegit() + # Check for updates after: + # - 6 hours since the last update on Opera because it lacks auto-updating. + # - 7 days since the last update on Chrome/Firefox. + # After that, check for updates every day if we still haven't updated. + now = Date.now() + freq = <% if (type === 'userjs') { %>6 * $.HOUR<% } else { %>7 * $.DAY<% } %> + if $.get('lastupdate', 0) > now - freq and $.get('lastchecked') > now - $.DAY + return + $.ajax '<%= meta.page %><%= meta.buildsPath %>version', onload: -> + return unless @status is 200 + version = @response + return unless /^\d\.\d+\.\d+$/.test version + if g.VERSION is version + # Don't check for updates too frequently if there wasn't one in a 'long' time. + $.set 'lastupdate', now + return + $.set 'lastchecked', now + el = $.el 'span', + innerHTML: "Update: <%= meta.name %> v#{version} is out, get it target=_blank>here." + new Notification 'info', el, 2 * $.MINUTE + handleErrors: (errors) -> unless 'length' of errors error = errors diff --git a/src/metadata.js b/src/metadata.js index 810a371bc..62ffec242 100644 --- a/src/metadata.js +++ b/src/metadata.js @@ -16,7 +16,7 @@ // @grant GM_deleteValue // @grant GM_openInTab // @run-at document-start -// @updateURL <%= meta.page %>builds/<%= name %>.meta.js -// @downloadURL <%= meta.page %>builds/<%= name %>.user.js +// @updateURL <%= meta.page %><%= meta.buildsPath %><%= name %>.meta.js +// @downloadURL <%= meta.page %><%= meta.buildsPath %><%= name %>.user.js // @icon data:image/png;base64,<%= grunt.file.read('img/icon48.png', {encoding: 'base64'}) %> // ==/UserScript== From be92325ee4f2e23b149db74947763fe9dca9992d Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 28 Mar 2013 03:23:10 +0100 Subject: [PATCH 2/9] Fix logic. --- src/main.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.coffee b/src/main.coffee index 317c7e7af..25639e6a6 100644 --- a/src/main.coffee +++ b/src/main.coffee @@ -499,7 +499,7 @@ Main = # After that, check for updates every day if we still haven't updated. now = Date.now() freq = <% if (type === 'userjs') { %>6 * $.HOUR<% } else { %>7 * $.DAY<% } %> - if $.get('lastupdate', 0) > now - freq and $.get('lastchecked') > now - $.DAY + if $.get('lastupdate', 0) > now - freq or $.get('lastchecked', 0) > now - $.DAY return $.ajax '<%= meta.page %><%= meta.buildsPath %>version', onload: -> return unless @status is 200 From e37216e2746cedf789a4956ca8cc5786baf7c3e3 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 28 Mar 2013 16:47:37 +0100 Subject: [PATCH 3/9] Revert 3 unread-related commits. #968 This reverts commits: - c49c201d91de6484e07c07650619d7924b192ffb - f95acfd134a9ed14d4293b1fb0896566d3c4721c - 846efbd013a5e8bb6e4361c842b20da10b17f587 --- src/features.coffee | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/features.coffee b/src/features.coffee index 7c0ca5fbc..86c22b606 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -3554,8 +3554,8 @@ ThreadExcerpt = name: 'Thread Excerpt' cb: @node node: -> - d.title = if (excerpt = Get.threadExcerpt @).length > 80 - "#{excerpt[...77]}..." + d.title = if (excerpt = Get.threadExcerpt @).length > 50 + "#{excerpt[...47]}..." else excerpt @@ -3575,7 +3575,6 @@ Unread = Unread.lastReadPost = $.get("lastReadPosts.#{@board}", threads: {}).threads[@] or 0 Unread.posts = [] Unread.postsQuotingYou = [] - Unread.titleEl = $ 'title', d.head Unread.title = d.title posts = [] for ID, post of @posts @@ -3657,17 +3656,10 @@ Unread = count = Unread.posts.length if Conf['Unread Count'] - prefix = if count - "(#{count})" + d.title = if g.DEAD + "(#{Unread.posts.length}) /#{g.BOARD}/ - 404" else - '' - # XXX Chrome bug where it doesn't always update the tab title. - # crbug.com/16650 - # crbug.com/124381 - Unread.titleEl.textContent = if g.DEAD - "#{prefix} /#{g.BOARD}/ - 404" - else - "#{prefix} #{Unread.title}" + "(#{Unread.posts.length}) #{Unread.title}" return unless Conf['Unread Tab Icon'] From 7dafdfd6e432de8c1bf885bd677fc21b03fe6263 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 28 Mar 2013 16:49:27 +0100 Subject: [PATCH 4/9] Longer excerpts. --- src/features.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features.coffee b/src/features.coffee index 86c22b606..ccd549443 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -3554,8 +3554,8 @@ ThreadExcerpt = name: 'Thread Excerpt' cb: @node node: -> - d.title = if (excerpt = Get.threadExcerpt @).length > 50 - "#{excerpt[...47]}..." + d.title = if (excerpt = Get.threadExcerpt @).length > 80 + "#{excerpt[...77]}..." else excerpt From b69c1934cd3abfdbc44934ead97efa30c79a9ed5 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Thu, 28 Mar 2013 16:52:15 +0100 Subject: [PATCH 5/9] Don't need that workaround on Chrome. --- src/features.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/features.coffee b/src/features.coffee index ccd549443..a47c780a5 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -3679,10 +3679,12 @@ Unread = else Favicon.default + <% if (type !== 'crx') { %> # `favicon.href = href` doesn't work on Firefox. # `favicon.href = href` isn't enough on Opera. # Opera won't always update the favicon if the href didn't change. $.add d.head, Favicon.el + <% } %> Favicon = init: -> From 7107c754afe2c432005e5cd1e81462767e6a9483 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 29 Mar 2013 01:19:18 +0100 Subject: [PATCH 6/9] Fix header autohiding not syncing correctly. --- src/features.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features.coffee b/src/features.coffee index a47c780a5..c5b29702f 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -129,7 +129,7 @@ Header = $.set 'Header catalog links', @checked setBarVisibility: (hide) -> - @headerToggler.firstElementChild.checked = hide + Header.headerToggler.firstElementChild.checked = hide (if hide then $.addClass else $.rmClass) Header.bar, 'autohide' toggleBarVisibility: -> hide = if @nodeName is 'INPUT' From 48457f27122560fa4c545efb26c62ce3f2c4a562 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 29 Mar 2013 02:07:19 +0100 Subject: [PATCH 7/9] name, value -> key, val --- lib/$.coffee | 64 +++++++++++++++++++++++++---------------------- src/manifest.json | 1 - 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/lib/$.coffee b/lib/$.coffee index cb3c56bad..0b4d23ca3 100644 --- a/lib/$.coffee +++ b/lib/$.coffee @@ -202,15 +202,15 @@ $.extend $, "#{size} #{['B', 'KB', 'MB', 'GB'][unit]}" <% if (type === 'crx') { %> - delete: (name) -> - localStorage.removeItem g.NAMESPACE + name - get: (name, defaultValue) -> - if value = localStorage.getItem g.NAMESPACE + name - JSON.parse value + delete: (key) -> + localStorage.removeItem g.NAMESPACE + key + get: (key, defaultVal) -> + if val = localStorage.getItem g.NAMESPACE + key + JSON.parse val else - defaultValue - set: (name, value) -> - localStorage.setItem g.NAMESPACE + name, JSON.stringify value + defaultVal + set: (key, val) -> + localStorage.setItem g.NAMESPACE + key, JSON.stringify val <% } else if (type === 'userjs') { %> do -> # http://www.opera.com/docs/userjs/specs/#scriptstorage @@ -221,31 +221,35 @@ do -> # To access the storage object later, keep a reference # to the object. {scriptStorage} = opera - $.delete = (name) -> - delete scriptStorage[g.NAMESPACE + name] - $.get = (name, defaultValue) -> - if value = scriptStorage[g.NAMESPACE + name] - JSON.parse value + $.delete = (key) -> + key = g.NAMESPACE + key + localStorage.removeItem key + delete scriptStorage[key] + $.get = (key, defaultVal) -> + if val = scriptStorage[g.NAMESPACE + key] + JSON.parse val else - defaultValue - $.set = (name, value) -> - name = g.NAMESPACE + name - value = JSON.stringify value + defaultVal + $.set = (key, val) -> + key = g.NAMESPACE + key + val = JSON.stringify val # for `storage` events - localStorage.setItem name, value - scriptStorage[name] = value + localStorage.setItem key, val + scriptStorage[key] = val <% } else { %> - delete: (name) -> - GM_deleteValue g.NAMESPACE + name - get: (name, defaultValue) -> - if value = GM_getValue g.NAMESPACE + name - JSON.parse value + delete: (key) -> + key = g.NAMESPACE + key + localStorage.removeItem key + GM_deleteValue key + get: (key, defaultVal) -> + if val = GM_getValue g.NAMESPACE + key + JSON.parse val else - defaultValue - set: (name, value) -> - name = g.NAMESPACE + name - value = JSON.stringify value + defaultVal + set: (key, val) -> + key = g.NAMESPACE + key + val = JSON.stringify val # for `storage` events - localStorage.setItem name, value - GM_setValue name, value + localStorage.setItem key, val + GM_setValue key, val <% } %> diff --git a/src/manifest.json b/src/manifest.json index 53e48aeda..599de79a8 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -14,6 +14,5 @@ "run_at": "document_start" }], "homepage_url": "<%= meta.page %>", - "incognito": "spanning", "minimum_chrome_version": "25" } From 1b9c606f113736601d237f42b7b3d40ece08a808 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 29 Mar 2013 02:39:02 +0100 Subject: [PATCH 8/9] Begin working on Chrome's storage API. Let's start easy with $.delete. --- lib/$.coffee | 26 +++++++++++++++++--------- src/features.coffee | 3 +-- src/manifest.json | 5 ++++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/$.coffee b/lib/$.coffee index 0b4d23ca3..4b3b321a1 100644 --- a/lib/$.coffee +++ b/lib/$.coffee @@ -202,8 +202,8 @@ $.extend $, "#{size} #{['B', 'KB', 'MB', 'GB'][unit]}" <% if (type === 'crx') { %> - delete: (key) -> - localStorage.removeItem g.NAMESPACE + key + delete: (keys) -> + chrome.storage.sync.remove keys get: (key, defaultVal) -> if val = localStorage.getItem g.NAMESPACE + key JSON.parse val @@ -221,10 +221,14 @@ do -> # To access the storage object later, keep a reference # to the object. {scriptStorage} = opera - $.delete = (key) -> - key = g.NAMESPACE + key - localStorage.removeItem key - delete scriptStorage[key] + $.delete = (keys) -> + unless keys instanceof Array + keys = [keys] + for key in keys + key = g.NAMESPACE + key + localStorage.removeItem key + delete scriptStorage[key] + return $.get = (key, defaultVal) -> if val = scriptStorage[g.NAMESPACE + key] JSON.parse val @@ -238,9 +242,13 @@ do -> scriptStorage[key] = val <% } else { %> delete: (key) -> - key = g.NAMESPACE + key - localStorage.removeItem key - GM_deleteValue key + unless keys instanceof Array + keys = [keys] + for key in keys + key = g.NAMESPACE + key + localStorage.removeItem key + GM_deleteValue key + return get: (key, defaultVal) -> if val = GM_getValue g.NAMESPACE + key JSON.parse val diff --git a/src/features.coffee b/src/features.coffee index c5b29702f..6df6b8de4 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -331,8 +331,7 @@ Settings = innerHTML: ": Clear manually hidden threads and posts on /#{g.BOARD}/." $.on $('button', div), 'click', -> @textContent = 'Hidden: 0' - $.delete "hiddenThreads.#{g.BOARD}" - $.delete "hiddenPosts.#{g.BOARD}" + $.delete ["hiddenThreads.#{g.BOARD}", "hiddenPosts.#{g.BOARD}"] $.after $('input[name="Stubs"]', section).parentNode.parentNode, div export: -> now = Date.now() diff --git a/src/manifest.json b/src/manifest.json index 599de79a8..b17375947 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -14,5 +14,8 @@ "run_at": "document_start" }], "homepage_url": "<%= meta.page %>", - "minimum_chrome_version": "25" + "minimum_chrome_version": "25", + "permissions": [ + "storage" + ] } From b3b224a8dfdbea62bbc51d745dc7eb14dde572b2 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Fri, 29 Mar 2013 02:59:20 +0100 Subject: [PATCH 9/9] Make $.set use the Chrome storage API. This is about to get really ugly. --- lib/$.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/$.coffee b/lib/$.coffee index 4b3b321a1..9c12aba7a 100644 --- a/lib/$.coffee +++ b/lib/$.coffee @@ -210,7 +210,9 @@ $.extend $, else defaultVal set: (key, val) -> - localStorage.setItem g.NAMESPACE + key, JSON.stringify val + item = {} + item[key] = val + chrome.storage.sync.set item <% } else if (type === 'userjs') { %> do -> # http://www.opera.com/docs/userjs/specs/#scriptstorage