Make $.get use the Chrome storage API. Close #503

Still need to fix $.sync, which I'll do tomorrow. Good night.
This commit is contained in:
Nicolas Stepien 2013-03-29 05:59:23 +01:00
parent b3b224a8df
commit 0a33b5a6d5
4 changed files with 250 additions and 156 deletions

View File

@ -200,15 +200,21 @@ $.extend $,
# Round to an integer otherwise. # Round to an integer otherwise.
Math.round size Math.round size
"#{size} #{['B', 'KB', 'MB', 'GB'][unit]}" "#{size} #{['B', 'KB', 'MB', 'GB'][unit]}"
item: (key, val) ->
item = {}
item[key] = val
item
<% if (type === 'crx') { %> <% if (type === 'crx') { %>
# https://developer.chrome.com/extensions/storage.html
delete: (keys) -> delete: (keys) ->
chrome.storage.sync.remove keys chrome.storage.sync.remove keys
get: (key, defaultVal) -> get: (key, val, cb) ->
if val = localStorage.getItem g.NAMESPACE + key if arguments.length is 2
JSON.parse val items = key
cb = val
else else
defaultVal items = $.item key, val
chrome.storage.sync.get items, cb
set: (key, val) -> set: (key, val) ->
item = {} item = {}
item[key] = val item[key] = val
@ -231,11 +237,17 @@ do ->
localStorage.removeItem key localStorage.removeItem key
delete scriptStorage[key] delete scriptStorage[key]
return return
$.get = (key, defaultVal) -> $.get = (key, val, cb) ->
if val = scriptStorage[g.NAMESPACE + key] if arguments.length is 2
JSON.parse val items = key
cb = val
else else
defaultVal items = $.item key, val
$.queueTask ->
for key of items
if val = scriptStorage[g.NAMESPACE + key]
items[key] = JSON.parse val
cb items
$.set = (key, val) -> $.set = (key, val) ->
key = g.NAMESPACE + key key = g.NAMESPACE + key
val = JSON.stringify val val = JSON.stringify val
@ -243,6 +255,7 @@ do ->
localStorage.setItem key, val localStorage.setItem key, val
scriptStorage[key] = val scriptStorage[key] = val
<% } else { %> <% } else { %>
# http://wiki.greasespot.net/Main_Page
delete: (key) -> delete: (key) ->
unless keys instanceof Array unless keys instanceof Array
keys = [keys] keys = [keys]
@ -251,11 +264,17 @@ do ->
localStorage.removeItem key localStorage.removeItem key
GM_deleteValue key GM_deleteValue key
return return
get: (key, defaultVal) -> get: (key, val, cb) ->
if val = GM_getValue g.NAMESPACE + key if arguments.length is 2
JSON.parse val items = key
cb = val
else else
defaultVal items = $.item key, val
$.queueTask ->
for key of items
if val = GM_getValue g.NAMESPACE + key
items[key] = JSON.parse val
cb items
set: (key, val) -> set: (key, val) ->
key = g.NAMESPACE + key key = g.NAMESPACE + key
val = JSON.stringify val val = JSON.stringify val

View File

@ -210,10 +210,11 @@ Settings =
order: 110 order: 110
open: -> Conf['Enable 4chan\'s Extension'] open: -> Conf['Enable 4chan\'s Extension']
if (prevVersion = $.get 'previousversion', null) isnt g.VERSION $.get 'previousversion', null, (item) ->
return if item['previousversion'] is g.VERSION
$.set 'lastupdate', Date.now() $.set 'lastupdate', Date.now()
$.set 'previousversion', g.VERSION $.set 'previousversion', g.VERSION
$.on d, '4chanXInitFinished', Settings.open unless prevVersion $.on d, '4chanXInitFinished', Settings.open unless item['previousversion']
Settings.addSection 'Main', Settings.main Settings.addSection 'Main', Settings.main
Settings.addSection 'Filter', Settings.filter Settings.addSection 'Filter', Settings.filter
@ -309,37 +310,54 @@ Settings =
$.on $('.import', section), 'click', Settings.import $.on $('.import', section), 'click', Settings.import
$.on $('input', section), 'change', Settings.onImport $.on $('input', section), 'change', Settings.onImport
items = {}
inputs = {}
for key, obj of Config.main for key, obj of Config.main
fs = $.el 'fieldset', fs = $.el 'fieldset',
innerHTML: "<legend>#{key}</legend>" innerHTML: "<legend>#{key}</legend>"
for key, arr of obj for key, arr of obj
checked = if $.get(key, Conf[key]) then 'checked' else ''
description = arr[1] description = arr[1]
div = $.el 'div', div = $.el 'div',
innerHTML: "<label><input type=checkbox name=\"#{key}\" #{checked}>#{key}</label><span class=description>: #{description}</span>" innerHTML: "<label><input type=checkbox name=\"#{key}\">#{key}</label><span class=description>: #{description}</span>"
$.on $('input', div), 'change', $.cb.checked input = $ 'input', div
$.on input, 'change', $.cb.checked
items[key] = Conf[key]
inputs[key] = input
$.add fs, div $.add fs, div
$.add section, fs $.add section, fs
$.get items, (items) ->
for key, val of items
inputs[key].checked = val
return
div = $.el 'div',
innerHTML: "<button></button><span class=description>: Clear manually hidden threads and posts on /#{g.BOARD}/."
button = $ 'button', div
hiddenNum = 0 hiddenNum = 0
for ID, thread of ThreadHiding.getHiddenThreads().threads ThreadHiding.getHiddenThreads (hiddenThreads) ->
for ID, thread of hiddenThreads.threads
hiddenNum++ hiddenNum++
for ID, thread of ReplyHiding.getHiddenPosts().threads button.textContent = "Hidden: #{hiddenNum}"
ReplyHiding.getHiddenPosts (hiddenPosts) ->
for ID, thread of hiddenPosts.threads
for ID, post of thread for ID, post of thread
hiddenNum++ hiddenNum++
div = $.el 'div', button.textContent = "Hidden: #{hiddenNum}"
innerHTML: "<button>Hidden: #{hiddenNum}</button><span class=description>: Clear manually hidden threads and posts on /#{g.BOARD}/." $.on button, 'click', ->
$.on $('button', div), 'click', ->
@textContent = 'Hidden: 0' @textContent = 'Hidden: 0'
$.delete ["hiddenThreads.#{g.BOARD}", "hiddenPosts.#{g.BOARD}"] $.delete ["hiddenThreads.#{g.BOARD}", "hiddenPosts.#{g.BOARD}"]
$.after $('input[name="Stubs"]', section).parentNode.parentNode, div $.after $('input[name="Stubs"]', section).parentNode.parentNode, div
export: -> export: (now, data) ->
unless typeof now is 'number'
now = Date.now() now = Date.now()
data = data =
version: g.VERSION version: g.VERSION
date: now date: now
Conf: Conf Conf: Conf
WatchedThreads: $.get('WatchedThreads', {}) $.get 'WatchedThreads', {}, (item) ->
data.WatchedThreads = item.WatchedThreads
Settings.export now, data
a = $.el 'a', a = $.el 'a',
className: 'warning' className: 'warning'
textContent: 'Save me!' textContent: 'Save me!'
@ -478,8 +496,9 @@ Settings =
ta = $.el 'textarea', ta = $.el 'textarea',
name: name name: name
className: 'field' className: 'field'
value: $.get name, Conf[name]
spellcheck: false spellcheck: false
$.get name, Conf[name], (item) ->
ta.value = item[name]
$.on ta, 'change', $.cb.value $.on ta, 'change', $.cb.value
$.add div, ta $.add div, ta
return return
@ -529,7 +548,8 @@ Settings =
<textarea name=sauces class=field spellcheck=false></textarea> <textarea name=sauces class=field spellcheck=false></textarea>
""" """
sauce = $ 'textarea', section sauce = $ 'textarea', section
sauce.value = $.get 'sauces', Conf['sauces'] $.get 'sauces', Conf['sauces'], (item) ->
sauce.value = item['sauces']
$.on sauce, 'change', $.cb.value $.on sauce, 'change', $.cb.value
rice: (section) -> rice: (section) ->
@ -592,17 +612,25 @@ Settings =
<textarea name=usercss class=field spellcheck=false #{if Conf['Custom CSS'] then '' else 'disabled'}></textarea> <textarea name=usercss class=field spellcheck=false #{if Conf['Custom CSS'] then '' else 'disabled'}></textarea>
</fieldset> </fieldset>
""" """
items = {}
inputs = {}
for name in ['boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss'] for name in ['boardnav', 'time', 'backlink', 'fileInfo', 'favicon', 'usercss']
input = $ "[name=#{name}]", section input = $ "[name=#{name}]", section
input.value = $.get name, Conf[name] items[name] = Conf[name]
inputs[name] = input
event = if name in ['favicon', 'usercss'] event = if name in ['favicon', 'usercss']
'change' 'change'
else else
'input' 'input'
$.on input, event, $.cb.value $.on input, event, $.cb.value
unless name in ['usercss'] $.get items, (items) ->
$.on input, event, Settings[name] for key, val of items
Settings[name].call input input = inputs[key]
input.value = val
unless key in ['usercss']
$.on input, event, Settings[key]
Settings[key].call input
return
$.on $('input[name="Custom CSS"]', section), 'change', Settings.togglecss $.on $('input[name="Custom CSS"]', section), 'change', Settings.togglecss
$.on $.id('apply-css'), 'click', Settings.usercss $.on $.id('apply-css'), 'click', Settings.usercss
boardnav: -> boardnav: ->
@ -653,15 +681,21 @@ Settings =
</tbody></table> </tbody></table>
""" """
tbody = $ 'tbody', section tbody = $ 'tbody', section
items = {}
inputs = {}
for key, arr of Config.hotkeys for key, arr of Config.hotkeys
tr = $.el 'tr', tr = $.el 'tr',
innerHTML: "<td>#{arr[1]}</td><td><input class=field></td>" innerHTML: "<td>#{arr[1]}</td><td><input class=field></td>"
input = $ 'input', tr input = $ 'input', tr
input.name = key input.name = key
input.value = $.get key, Conf[key]
input.spellcheck = false input.spellcheck = false
items[key] = Conf[key]
inputs[key] = input
$.on input, 'keydown', Settings.keybind $.on input, 'keydown', Settings.keybind
$.add tbody, tr $.add tbody, tr
$.get items, (items) ->
for key, val of items
inputs[key].value = val
return return
keybind: (e) -> keybind: (e) ->
return if e.keyCode is 9 # tab return if e.keyCode is 9 # tab
@ -990,7 +1024,8 @@ Filter =
re += ';op:yes' re += ';op:yes'
# Add a new line before the regexp unless the text is empty. # Add a new line before the regexp unless the text is empty.
save = $.get type, '' $.get type, '', (item) ->
save = item[type]
save = save =
if save if save
"#{save}\n#{re}" "#{save}\n#{re}"
@ -1026,8 +1061,10 @@ ThreadHiding =
return unless Conf['Thread Hiding'] return unless Conf['Thread Hiding']
$.prepend @OP.nodes.root, ThreadHiding.makeButton @, 'hide' $.prepend @OP.nodes.root, ThreadHiding.makeButton @, 'hide'
getHiddenThreads: -> getHiddenThreads: (cb) ->
ThreadHiding.hiddenThreads = $.get "hiddenThreads.#{g.BOARD}", threads: {} $.get "hiddenThreads.#{g.BOARD}", threads: {}, (item) ->
ThreadHiding.hiddenThreads = item["hiddenThreads.#{g.BOARD}"]
cb ThreadHiding.hiddenThreads if cb
syncFromCatalog: -> syncFromCatalog: ->
# Sync hidden threads from the catalog into the index. # Sync hidden threads from the catalog into the index.
@ -1093,7 +1130,7 @@ ThreadHiding =
saveHiddenState: (thread, makeStub) -> saveHiddenState: (thread, makeStub) ->
# Get fresh hidden threads. # Get fresh hidden threads.
hiddenThreads = ThreadHiding.getHiddenThreads() ThreadHiding.getHiddenThreads (hiddenThreads) ->
hiddenThreadsCatalog = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {} hiddenThreadsCatalog = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {}
if thread.isHidden if thread.isHidden
hiddenThreads.threads[thread] = {makeStub} hiddenThreads.threads[thread] = {makeStub}
@ -1173,8 +1210,10 @@ ReplyHiding =
return unless Conf['Reply Hiding'] return unless Conf['Reply Hiding']
$.replace $('.sideArrows', @nodes.root), ReplyHiding.makeButton @, 'hide' $.replace $('.sideArrows', @nodes.root), ReplyHiding.makeButton @, 'hide'
getHiddenPosts: -> getHiddenPosts: (cb) ->
ReplyHiding.hiddenPosts = $.get "hiddenPosts.#{g.BOARD}", threads: {} $.get "hiddenPosts.#{g.BOARD}", threads: {}, (item) ->
ReplyHiding.hiddenPosts = item["hiddenPosts.#{g.BOARD}"]
cb ReplyHiding.hiddenPosts if cb
menu: menu:
init: -> init: ->
@ -1230,7 +1269,7 @@ ReplyHiding =
open: (post) -> open: (post) ->
if !post.isReply or post.isClone if !post.isReply or post.isClone
return false return false
thread = ReplyHiding.getHiddenPosts().threads[post.thread] thread = ReplyHiding.hiddenPosts.threads[post.thread]
unless post.isHidden or data = thread?[post] unless post.isHidden or data = thread?[post]
return false return false
ReplyHiding.menu.post = post ReplyHiding.menu.post = post
@ -1258,7 +1297,7 @@ ReplyHiding =
thisPost = $('input[name=thisPost]', parent).checked thisPost = $('input[name=thisPost]', parent).checked
replies = $('input[name=replies]', parent).checked replies = $('input[name=replies]', parent).checked
{post} = ReplyHiding.menu {post} = ReplyHiding.menu
thread = ReplyHiding.getHiddenPosts().threads[post.thread] thread = ReplyHiding.hiddenPosts.threads[post.thread]
data = thread?[post] data = thread?[post]
if thisPost if thisPost
ReplyHiding.show post, replies ReplyHiding.show post, replies
@ -1281,7 +1320,7 @@ ReplyHiding =
saveHiddenState: (post, isHiding, thisPost, makeStub, hideRecursively) -> saveHiddenState: (post, isHiding, thisPost, makeStub, hideRecursively) ->
# Get fresh hidden posts. # Get fresh hidden posts.
hiddenPosts = ReplyHiding.getHiddenPosts() ReplyHiding.getHiddenPosts (hiddenPosts) ->
if isHiding if isHiding
unless thread = hiddenPosts.threads[post.thread] unless thread = hiddenPosts.threads[post.thread]
thread = hiddenPosts.threads[post.thread] = {} thread = hiddenPosts.threads[post.thread] = {}
@ -2461,8 +2500,13 @@ Get =
Get.insert post, root, context Get.insert post, root, context
Misc = # super semantic Misc = # super semantic
clearThreads: (key) -> clearThreads: (key, data) ->
return unless data = $.get key unless data
$.get key, null, (item) ->
data = item[key]
return unless data
Misc.clearThreads key, data
return
unless Object.keys(data.threads).length unless Object.keys(data.threads).length
$.delete key $.delete key
@ -3571,13 +3615,14 @@ Unread =
node: -> node: ->
Unread.thread = @ Unread.thread = @
Unread.lastReadPost = $.get("lastReadPosts.#{@board}", threads: {}).threads[@] or 0
Unread.posts = [] Unread.posts = []
Unread.postsQuotingYou = [] Unread.postsQuotingYou = []
Unread.title = d.title Unread.title = d.title
posts = [] posts = []
for ID, post of @posts for ID, post of @posts
posts.push post if post.isReply posts.push post if post.isReply
$.get "lastReadPosts.#{@board}", threads: {}, (item) =>
Unread.lastReadPost = item["lastReadPosts.#{@board}"].threads[@] or 0
Unread.addPosts posts Unread.addPosts posts
if Unread.posts.length if Unread.posts.length
# Scroll to before the first unread post. # Scroll to before the first unread post.
@ -3636,11 +3681,11 @@ Unread =
Unread.postsQuotingYou = Unread.postsQuotingYou[i..] Unread.postsQuotingYou = Unread.postsQuotingYou[i..]
Unread.update() if e Unread.update() if e
saveLastReadPost: $.debounce($.SECOND, -> saveLastReadPost: $.debounce $.SECOND, ->
lastReadPosts = $.get "lastReadPosts.#{Unread.thread.board}", threads: {} $.get "lastReadPosts.#{Unread.thread.board}", threads: {}, (item) ->
lastReadPosts = item["lastReadPosts.#{Unread.thread.board}"]
lastReadPosts.threads[Unread.thread] = Unread.lastReadPost lastReadPosts.threads[Unread.thread] = Unread.lastReadPost
$.set "lastReadPosts.#{Unread.thread.board}", lastReadPosts $.set "lastReadPosts.#{Unread.thread.board}", lastReadPosts
)
setLine: (force) -> setLine: (force) ->
return unless d.hidden or force is true return unless d.hidden or force is true
@ -4068,7 +4113,9 @@ ThreadWatcher =
className: 'favicon' className: 'favicon'
$.on favicon, 'click', ThreadWatcher.cb.toggle $.on favicon, 'click', ThreadWatcher.cb.toggle
$.before $('input', @OP.nodes.post), favicon $.before $('input', @OP.nodes.post), favicon
if g.VIEW is 'thread' and @ID is $.get 'AutoWatch', 0 return if g.VIEW isnt 'thread'
$.get 'AutoWatch', 0, (item) =>
return if item['AutoWatch'] isnt @ID
ThreadWatcher.watch @ ThreadWatcher.watch @
$.delete 'AutoWatch' $.delete 'AutoWatch'
@ -4078,7 +4125,10 @@ ThreadWatcher =
$.add d.body, ThreadWatcher.dialog $.add d.body, ThreadWatcher.dialog
refresh: (watched) -> refresh: (watched) ->
watched or= $.get 'WatchedThreads', {} unless watched
$.get 'WatchedThreads', {}, (item) ->
ThreadWatcher.refresh item['WatchedThreads']
return
nodes = [$('.move', ThreadWatcher.dialog)] nodes = [$('.move', ThreadWatcher.dialog)]
for board of watched for board of watched
for id, props of watched[board] for id, props of watched[board]
@ -4126,14 +4176,16 @@ ThreadWatcher =
ThreadWatcher.unwatch thread.board, thread.ID ThreadWatcher.unwatch thread.board, thread.ID
unwatch: (board, threadID) -> unwatch: (board, threadID) ->
watched = $.get 'WatchedThreads', {} $.get 'WatchedThreads', {}, (item) ->
watched = item['WatchedThreads']
delete watched[board][threadID] delete watched[board][threadID]
delete watched[board] unless Object.keys(watched[board]).length delete watched[board] unless Object.keys(watched[board]).length
ThreadWatcher.refresh watched ThreadWatcher.refresh watched
$.set 'WatchedThreads', watched $.set 'WatchedThreads', watched
watch: (thread) -> watch: (thread) ->
watched = $.get 'WatchedThreads', {} $.get 'WatchedThreads', {}, (item) ->
watched = item['WatchedThreads']
watched[thread.board] or= {} watched[thread.board] or= {}
watched[thread.board][thread] = watched[thread.board][thread] =
href: "/#{thread.board}/res/#{thread}" href: "/#{thread.board}/res/#{thread}"

View File

@ -281,7 +281,8 @@ class Clone extends Post
Main = Main =
init: -> init: (items) ->
unless items
# flatten Config into Conf # flatten Config into Conf
# and get saved or default values # and get saved or default values
flatten = (parent, obj) -> flatten = (parent, obj) ->
@ -294,8 +295,10 @@ Main =
Conf[parent] = obj Conf[parent] = obj
return return
flatten null, Config flatten null, Config
for key, val of Conf $.get Conf, Main.init
Conf[key] = $.get key, val return
Conf = items
pathname = location.pathname.split '/' pathname = location.pathname.split '/'
g.BOARD = new Board pathname[1] g.BOARD = new Board pathname[1]
@ -499,7 +502,11 @@ Main =
# After that, check for updates every day if we still haven't updated. # After that, check for updates every day if we still haven't updated.
now = Date.now() now = Date.now()
freq = <% if (type === 'userjs') { %>6 * $.HOUR<% } else { %>7 * $.DAY<% } %> freq = <% if (type === 'userjs') { %>6 * $.HOUR<% } else { %>7 * $.DAY<% } %>
if $.get('lastupdate', 0) > now - freq or $.get('lastchecked', 0) > now - $.DAY items =
lastupdate: 0
lastchecked: 0
$.get items, (items) ->
if items.lastupdate > now - freq or items.lastchecked > now - $.DAY
return return
$.ajax '<%= meta.page %><%= meta.buildsPath %>version', onload: -> $.ajax '<%= meta.page %><%= meta.buildsPath %>version', onload: ->
return unless @status is 200 return unless @status is 200

View File

@ -92,7 +92,8 @@ QR =
if yourPosts if yourPosts
QR.yourPosts = yourPosts QR.yourPosts = yourPosts
return return
QR.yourPosts = $.get "yourPosts.#{g.BOARD}", threads: {} $.get "yourPosts.#{g.BOARD}", threads: {}, (item) ->
QR.syncYourPosts item["yourPosts.#{g.BOARD}"]
$.sync "yourPosts.#{g.BOARD}", QR.syncYourPosts $.sync "yourPosts.#{g.BOARD}", QR.syncYourPosts
error: (err) -> error: (err) ->
@ -145,9 +146,10 @@ QR =
sage: if board is 'q' then 600 else 60 sage: if board is 'q' then 600 else 60
file: if board is 'q' then 300 else 30 file: if board is 'q' then 300 else 30
post: if board is 'q' then 60 else 30 post: if board is 'q' then 60 else 30
QR.cooldown.cooldowns = $.get "cooldown.#{board}", {}
QR.cooldown.upSpd = 0 QR.cooldown.upSpd = 0
QR.cooldown.upSpdAccuracy = .5 QR.cooldown.upSpdAccuracy = .5
$.get "cooldown.#{board}", {}, (item) ->
QR.cooldown.cooldowns = item["cooldown.#{board}"]
QR.cooldown.start() QR.cooldown.start()
$.sync "cooldown.#{board}", QR.cooldown.sync $.sync "cooldown.#{board}", QR.cooldown.sync
start: -> start: ->
@ -358,15 +360,6 @@ QR =
posts: [] posts: []
post: class post: class
constructor: -> constructor: ->
# set values, or null, to avoid 'undefined' values in inputs
prev = QR.posts[QR.posts.length - 1]
persona = $.get 'QR.persona', {}
@name = if prev then prev.name else persona.name or null
@email = if prev and !/^sage$/.test prev.email then prev.email else persona.email or null
@sub = if prev and Conf['Remember Subject'] then prev.sub else if Conf['Remember Subject'] then persona.sub else null
@spoiler = if prev and Conf['Remember Spoiler'] then prev.spoiler else false
@com = null
el = $.el 'a', el = $.el 'a',
className: 'qr-preview' className: 'qr-preview'
draggable: true draggable: true
@ -393,8 +386,29 @@ QR =
for event in ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop'] for event in ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']
$.on el, event.toLowerCase(), @[event] $.on el, event.toLowerCase(), @[event]
@unlock()
QR.posts.push @ QR.posts.push @
# set values, or null, to avoid 'undefined' values in inputs
@com = null
@spoiler = if prev and Conf['Remember Spoiler']
prev.spoiler
else
false
prev = QR.posts[QR.posts.length - 1]
$.get 'QR.persona', {}, (item) =>
persona = item['QR.persona']
@name = if prev
prev.name
else
persona.name or null
@email = if prev and !/^sage$/.test prev.email
prev.email
else
persona.email or null
@sub = if Conf['Remember Subject']
if prev then prev.sub else persona.sub
else
null
@unlock()
rm: -> rm: ->
$.rm @nodes.el $.rm @nodes.el
index = QR.posts.indexOf @ index = QR.posts.indexOf @
@ -606,8 +620,9 @@ QR =
$.on imgContainer, 'click', @reload.bind @ $.on imgContainer, 'click', @reload.bind @
$.on input, 'keydown', @keydown.bind @ $.on input, 'keydown', @keydown.bind @
$.get 'captchas', [], (item) =>
@sync item['captchas']
$.sync 'captchas', @sync $.sync 'captchas', @sync
@sync $.get 'captchas', []
# start with an uncached captcha # start with an uncached captcha
@reload() @reload()
@ -960,7 +975,8 @@ QR =
QR.cleanNotifications() QR.cleanNotifications()
QR.notifications.push new Notification 'success', h1.textContent, 5 QR.notifications.push new Notification 'success', h1.textContent, 5
persona = $.get 'QR.persona', {} $.get 'QR.persona', {}, (item) ->
persona = item['QR.persona']
persona = persona =
name: post.name name: post.name
email: if /^sage$/.test post.email then persona.email else post.email email: if /^sage$/.test post.email then persona.email else post.email