Add callback to $.set and use it.

We can now:

- Update status of 404'd threads in watcher before redirecting.
- Wait until imported settings are saved before prompting to reload.

Also $.clear now passes errors to the callback rather than simply failing.
This commit is contained in:
ccd0 2015-02-14 16:05:16 -08:00
parent 5ad84a700e
commit 6dd2a4103c
5 changed files with 56 additions and 31 deletions

View File

@ -129,12 +129,14 @@ Main =
initReady: -> initReady: ->
if d.title in ['4chan - Temporarily Offline', '4chan - 404 Not Found'] if d.title in ['4chan - Temporarily Offline', '4chan - 404 Not Found']
if Conf['404 Redirect'] and g.VIEW is 'thread' if g.VIEW is 'thread'
href = Redirect.to 'thread', ThreadWatcher.set404 g.BOARD.ID, g.THREADID, ->
boardID: g.BOARD.ID if Conf['404 Redirect']
threadID: g.THREADID href = Redirect.to 'thread',
postID: +location.hash.match /\d+/ # post number or 0 boardID: g.BOARD.ID
Redirect.navigate href, "/#{g.BOARD}/" threadID: g.THREADID
postID: +location.hash.match /\d+/ # post number or 0
Redirect.navigate href, "/#{g.BOARD}/"
return return
# 4chan Pass Link # 4chan Pass Link

View File

@ -175,15 +175,17 @@ Settings =
reader = new FileReader() reader = new FileReader()
reader.onload = (e) -> reader.onload = (e) ->
try try
Settings.loadSettings JSON.parse e.target.result Settings.loadSettings JSON.parse(e.target.result), (err) ->
if confirm 'Import successful. Reload now?' if err
window.location.reload() output.textContent = 'Import failed due to an error.'
else if confirm 'Import successful. Reload now?'
window.location.reload()
catch err catch err
output.textContent = 'Import failed due to an error.' output.textContent = 'Import failed due to an error.'
c.error err.stack c.error err.stack
reader.readAsText file reader.readAsText file
loadSettings: (data) -> loadSettings: (data, cb) ->
version = data.version.split '.' version = data.version.split '.'
if version[0] is '2' if version[0] is '2'
convertSettings = (data, map) -> convertSettings = (data, map) ->
@ -265,11 +267,17 @@ Settings =
if data.Conf['WatchedThreads'] if data.Conf['WatchedThreads']
data.Conf['watchedThreads'] = boards: ThreadWatcher.convert data.Conf['WatchedThreads'] data.Conf['watchedThreads'] = boards: ThreadWatcher.convert data.Conf['WatchedThreads']
delete data.Conf['WatchedThreads'] delete data.Conf['WatchedThreads']
$.clear -> $.set data.Conf $.clear (err) ->
return cb err if err
$.set data.Conf, cb
reset: -> reset: ->
if confirm 'Your current settings will be entirely wiped, are you sure?' if confirm 'Your current settings will be entirely wiped, are you sure?'
$.clear -> window.location.reload() if confirm 'Reset successful. Reload now?' $.clear (err) ->
if err
$('.imp-exp-result').textContent = 'Import failed due to an error.'
else if confirm 'Reset successful. Reload now?'
window.location.reload()
filter: (section) -> filter: (section) ->
$.extend section, <%= importHTML('Settings/Filter-select') %> $.extend section, <%= importHTML('Settings/Filter-select') %>

View File

@ -361,16 +361,16 @@ do ->
chrome.storage.sync.remove keys chrome.storage.sync.remove keys
timeout = {} timeout = {}
setArea = (area) -> setArea = (area, cb) ->
data = {} data = {}
$.extend data, items[area] $.extend data, items[area]
return if !Object.keys(data).length or timeout[area] > Date.now() return if !Object.keys(data).length or timeout[area] > Date.now()
chrome.storage[area].set data, -> chrome.storage[area].set data, ->
if chrome.runtime.lastError if err = chrome.runtime.lastError
c.error chrome.runtime.lastError.message c.error err.message
setTimeout setArea, $.MINUTE, area setTimeout setArea, $.MINUTE, area
timeout[area] = Date.now() + $.MINUTE timeout[area] = Date.now() + $.MINUTE
return return cb? err
delete timeout[area] delete timeout[area]
delete items[area][key] for key of data when items[area][key] is data[key] delete items[area][key] for key of data when items[area][key] is data[key]
@ -382,29 +382,32 @@ do ->
delete $.localKeys[key] delete $.localKeys[key]
key key
chrome.storage.local.remove oldLocal chrome.storage.local.remove oldLocal
cb?()
setSync = $.debounce $.SECOND, -> setSync = $.debounce $.SECOND, ->
setArea 'sync' setArea 'sync'
$.set = (key, val) -> $.set = (key, val, cb) ->
data = if typeof key is 'string' if typeof key is 'string'
$.item key, val data = $.item key, val
else else
key data = key
cb = val
$.extend items.local, data $.extend items.local, data
$.localKeys[key] = true for key of data $.localKeys[key] = true for key of data
setArea 'local' setArea 'local', cb
$.clear = (cb) -> $.clear = (cb) ->
items.local = {} items.local = {}
items.sync = {} items.sync = {}
$.localKeys = {} $.localKeys = {}
count = 2 count = 2
err = null
done = -> done = ->
if chrome.runtime.lastError if chrome.runtime.lastError
c.error chrome.runtime.lastError.message c.error chrome.runtime.lastError.message
return err ?= chrome.runtime.lastError
cb?() unless --count cb? err unless --count
chrome.storage.local.clear done chrome.storage.local.clear done
chrome.storage.sync.clear done chrome.storage.sync.clear done
<% } else { %> <% } else { %>
@ -470,13 +473,14 @@ $.set = do ->
# for `storage` events # for `storage` events
localStorage.setItem key, val localStorage.setItem key, val
(keys, val) -> (keys, val, cb) ->
if typeof keys is 'string' if typeof keys is 'string'
set keys, val set keys, val
return else
for key, val of keys set key, value for key, value of keys
set key, val cb = val
return cb?()
$.clear = (cb) -> $.clear = (cb) ->
try try
$.delete GM_listValues().map (key) -> key.replace g.NAMESPACE, '' $.delete GM_listValues().map (key) -> key.replace g.NAMESPACE, ''

View File

@ -13,7 +13,7 @@ class DataBoard
@sync = sync @sync = sync
$.on d, '4chanXInitFinished', init $.on d, '4chanXInitFinished', init
save: -> $.set @key, @data save: (cb) -> $.set @key, @data, cb
delete: ({boardID, threadID, postID}) -> delete: ({boardID, threadID, postID}) ->
$.forceSync @key $.forceSync @key
@ -38,7 +38,7 @@ class DataBoard
else unless Object.keys(@data.boards[boardID]).length else unless Object.keys(@data.boards[boardID]).length
delete @data.boards[boardID] delete @data.boards[boardID]
set: ({boardID, threadID, postID, val}) -> set: ({boardID, threadID, postID, val}, cb) ->
$.forceSync @key $.forceSync @key
if postID isnt undefined if postID isnt undefined
((@data.boards[boardID] or= {})[threadID] or= {})[postID] = val ((@data.boards[boardID] or= {})[threadID] or= {})[postID] = val
@ -46,7 +46,7 @@ class DataBoard
(@data.boards[boardID] or= {})[threadID] = val (@data.boards[boardID] or= {})[threadID] = val
else else
@data.boards[boardID] = val @data.boards[boardID] = val
@save() @save cb
get: ({boardID, threadID, postID, defaultValue}) -> get: ({boardID, threadID, postID, defaultValue}) ->
if board = @data.boards[boardID] if board = @data.boards[boardID]

View File

@ -335,6 +335,17 @@ ThreadWatcher =
else else
ThreadWatcher.refresh() ThreadWatcher.refresh()
set404: (boardID, threadID, cb) ->
return cb() unless data = ThreadWatcher.db?.get {boardID, threadID}
if Conf['Auto Prune']
ThreadWatcher.db.delete {boardID, threadID}
return cb()
return cb() if data.isDead and not (data.unread? or data.quotingYou?)
data.isDead = true
delete data.unread
delete data.quotingYou
ThreadWatcher.db.set {boardID, threadID, val: data}, cb
toggle: (thread) -> toggle: (thread) ->
boardID = thread.board.ID boardID = thread.board.ID
threadID = thread.ID threadID = thread.ID