Add Notifications.
Add error handling. I don't feel like I did a good job of it, might revisit later.
This commit is contained in:
parent
b6cf7220c4
commit
8b836aec8d
459
4chan_x.user.js
459
4chan_x.user.js
File diff suppressed because one or more lines are too long
@ -35,25 +35,28 @@ a[href="javascript:;"] {
|
||||
#qr, #watcher {
|
||||
position: fixed;
|
||||
}
|
||||
#qp, #ihover {
|
||||
z-index: 100;
|
||||
}
|
||||
#menu {
|
||||
z-index: 95;
|
||||
}
|
||||
#updater, #stats {
|
||||
z-index: 90;
|
||||
}
|
||||
#header:hover {
|
||||
#notifications {
|
||||
z-index: 80;
|
||||
}
|
||||
#qr {
|
||||
#qp, #ihover {
|
||||
z-index: 70;
|
||||
}
|
||||
#menu {
|
||||
z-index: 60;
|
||||
}
|
||||
#updater, #stats {
|
||||
z-index: 50;
|
||||
}
|
||||
#watcher {
|
||||
#header:hover {
|
||||
z-index: 40;
|
||||
}
|
||||
#qr {
|
||||
z-index: 30;
|
||||
}
|
||||
#header {
|
||||
z-index: 20;
|
||||
}
|
||||
#watcher {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@ -68,7 +71,7 @@ a[href="javascript:;"] {
|
||||
}
|
||||
|
||||
/* header */
|
||||
body.fourchan_x {
|
||||
.fourchan_x body {
|
||||
margin-top: 2em;
|
||||
}
|
||||
#header {
|
||||
@ -85,6 +88,7 @@ body.fourchan_x {
|
||||
-webkit-transition: all .1s ease-in-out;
|
||||
}
|
||||
#header-bar.autohide:not(:hover) {
|
||||
margin-bottom: -1em;
|
||||
transform: translateY(-100%);
|
||||
-o-transform: translateY(-100%);
|
||||
-moz-transform: translateY(-100%);
|
||||
@ -119,6 +123,51 @@ body > #boardNavDesktop,
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* notifications */
|
||||
#notifications {
|
||||
text-align: center;
|
||||
}
|
||||
.notification {
|
||||
color: #FFF;
|
||||
font-weight: 700;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
|
||||
border-radius: 2px;
|
||||
margin: 1px auto;
|
||||
width: 500px;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
transition: all .25s ease-in-out;
|
||||
-o-transition: all .25s ease-in-out;
|
||||
-moz-transition: all .25s ease-in-out;
|
||||
-webkit-transition: all .25s ease-in-out;
|
||||
}
|
||||
.notification.error {
|
||||
background-color: hsl(0, 100%, 40%);
|
||||
}
|
||||
.notification.warning {
|
||||
background-color: hsl(36, 100%, 40%);
|
||||
}
|
||||
.notification.info {
|
||||
background-color: hsl(200, 100%, 40%);
|
||||
}
|
||||
.notification.success {
|
||||
background-color: hsl(104, 100%, 40%);
|
||||
}
|
||||
.notification > .close {
|
||||
color: white;
|
||||
padding: 4px 6px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.message {
|
||||
box-sizing: border-box;
|
||||
padding: 4px 20px;
|
||||
max-height: 200px;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* thread updater */
|
||||
#updater {
|
||||
text-align: right;
|
||||
|
||||
@ -22,7 +22,7 @@ $.extend $,
|
||||
id: (id) ->
|
||||
d.getElementById id
|
||||
ready: (fc) ->
|
||||
if /interactive|complete/.test d.readyState
|
||||
if d.readyState in ['interactive', 'complete']
|
||||
$.queueTask fc
|
||||
return
|
||||
cb = ->
|
||||
@ -106,9 +106,6 @@ $.extend $,
|
||||
tn: (s) ->
|
||||
d.createTextNode s
|
||||
nodes: (nodes) ->
|
||||
# In (at least) Chrome, elements created inside different
|
||||
# scripts/window contexts inherit from unequal prototypes.
|
||||
# window_context1.Node !== window_context2.Node
|
||||
unless nodes instanceof Array
|
||||
return nodes
|
||||
frag = d.createDocumentFragment()
|
||||
|
||||
@ -57,8 +57,8 @@ Config =
|
||||
'Quote Preview': [true, 'Show quoted post on hover.']
|
||||
'Quote Highlighting': [true, 'Highlight the previewed post.']
|
||||
'Resurrect Quotes': [true, 'Linkify dead quotes to archives.']
|
||||
'Indicate OP Quotes': [true, 'Add \'(OP)\' to OP quotes.']
|
||||
'Indicate Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes.']
|
||||
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.']
|
||||
'Mark Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes.']
|
||||
filter:
|
||||
name: [
|
||||
'# Filter any namefags:'
|
||||
|
||||
@ -40,8 +40,9 @@ Header =
|
||||
try
|
||||
@setBoardList()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Header - board list'
|
||||
Main.handleErrors
|
||||
message: '"Header (board list)" crashed.'
|
||||
error: err
|
||||
|
||||
$.asap (-> d.body), ->
|
||||
$.prepend d.body, Header.headerEl
|
||||
@ -74,6 +75,31 @@ Header =
|
||||
menuToggle: (e) ->
|
||||
Header.menu.toggle e, @, g
|
||||
|
||||
class Notification
|
||||
constructor: (@type, content, timeout) ->
|
||||
@el = $.el 'div',
|
||||
className: "notification #{type}"
|
||||
innerHTML: '<a href=javascript:; class=close title=Close>×</a><div class=message></div>'
|
||||
$.on @el.firstElementChild, 'click', @close.bind @
|
||||
if typeof content is 'string'
|
||||
content = $.tn content
|
||||
$.add @el.lastElementChild, content
|
||||
|
||||
if timeout
|
||||
setTimeout @close.bind(@), timeout * $.SECOND
|
||||
|
||||
el = @el
|
||||
$.ready ->
|
||||
$.add $.id('notifications'), el
|
||||
|
||||
setType: (type) ->
|
||||
$.rmClass @el, @type
|
||||
$.addClass @el, type
|
||||
@type = type
|
||||
|
||||
close: ->
|
||||
$.rm @el
|
||||
|
||||
Settings =
|
||||
init: ->
|
||||
# 4chan X settings link
|
||||
@ -107,6 +133,8 @@ Settings =
|
||||
Filter =
|
||||
filters: {}
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Filter']
|
||||
|
||||
for key of Config.filter
|
||||
@filters[key] = []
|
||||
for filter in Conf[key].split '\n'
|
||||
@ -134,8 +162,7 @@ Filter =
|
||||
regexp = RegExp regexp[1], regexp[2]
|
||||
catch err
|
||||
# I warned you, bro.
|
||||
# XXX handle error
|
||||
alert err.message
|
||||
new Notification 'warning', err.message, 60
|
||||
continue
|
||||
|
||||
# Filter OPs along with their threads, replies only, or both.
|
||||
@ -274,6 +301,8 @@ Filter =
|
||||
|
||||
menu:
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Filter']
|
||||
|
||||
div = $.el 'div',
|
||||
textContent: 'Filter'
|
||||
|
||||
@ -376,7 +405,8 @@ Filter =
|
||||
|
||||
ThreadHiding =
|
||||
init: ->
|
||||
return if g.VIEW isnt 'index'
|
||||
return if g.VIEW isnt 'index' or !Conf['Thread Hiding']
|
||||
|
||||
@getHiddenThreads()
|
||||
@syncFromCatalog()
|
||||
@clean()
|
||||
@ -438,7 +468,8 @@ ThreadHiding =
|
||||
|
||||
menu:
|
||||
init: ->
|
||||
return if g.VIEW isnt 'index'
|
||||
return if g.VIEW isnt 'index' or !Conf['Menu'] or !Conf['Thread Hiding']
|
||||
|
||||
div = $.el 'div',
|
||||
className: 'hide-thread-link'
|
||||
textContent: 'Hide thread'
|
||||
@ -535,6 +566,8 @@ ThreadHiding =
|
||||
|
||||
ReplyHiding =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Reply Hiding']
|
||||
|
||||
@getHiddenPosts()
|
||||
@clean()
|
||||
Post::callbacks.push
|
||||
@ -583,6 +616,8 @@ ReplyHiding =
|
||||
|
||||
menu:
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Reply Hiding']
|
||||
|
||||
div = $.el 'div',
|
||||
className: 'hide-reply-link'
|
||||
textContent: 'Hide reply'
|
||||
@ -726,6 +761,8 @@ Recursive =
|
||||
|
||||
Menu =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu']
|
||||
|
||||
@menu = new UI.Menu 'post'
|
||||
Post::callbacks.push
|
||||
name: 'Menu'
|
||||
@ -758,6 +795,8 @@ Menu =
|
||||
|
||||
ReportLink =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Report Link']
|
||||
|
||||
a = $.el 'a',
|
||||
className: 'report-link'
|
||||
href: 'javascript:;'
|
||||
@ -777,6 +816,8 @@ ReportLink =
|
||||
|
||||
DeleteLink =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Delete Link']
|
||||
|
||||
div = $.el 'div',
|
||||
className: 'delete-link'
|
||||
textContent: 'Delete'
|
||||
@ -881,6 +922,8 @@ DeleteLink =
|
||||
|
||||
DownloadLink =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Download Link']
|
||||
|
||||
# Test for download feature support.
|
||||
return if $.el('a').download is undefined
|
||||
a = $.el 'a',
|
||||
@ -896,6 +939,8 @@ DownloadLink =
|
||||
|
||||
ArchiveLink =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Menu'] or !Conf['Archive Link']
|
||||
|
||||
div = $.el 'div',
|
||||
textContent: 'Archive'
|
||||
|
||||
@ -1554,6 +1599,8 @@ Get =
|
||||
|
||||
Quotify =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Resurrect Quotes']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Resurrect Quotes'
|
||||
cb: @node
|
||||
@ -1621,6 +1668,8 @@ Quotify =
|
||||
|
||||
QuoteInline =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Quote Inline']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Quote Inline'
|
||||
cb: @node
|
||||
@ -1701,6 +1750,8 @@ QuoteInline =
|
||||
|
||||
QuotePreview =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Quote Preview']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Quote Preview'
|
||||
cb: @node
|
||||
@ -1767,6 +1818,8 @@ QuoteBacklink =
|
||||
# This is is so that fetched posts can get their backlinks,
|
||||
# and that as much backlinks are appended in the background as possible.
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Quote Backlinks']
|
||||
|
||||
format = Conf['backlink'].replace /%id/g, "' + id + '"
|
||||
@funk = Function 'id', "return '#{format}'"
|
||||
@containers = {}
|
||||
@ -1810,10 +1863,12 @@ QuoteBacklink =
|
||||
|
||||
QuoteOP =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Mark OP Quotes']
|
||||
|
||||
# \u00A0 is nbsp
|
||||
@text = '\u00A0(OP)'
|
||||
Post::callbacks.push
|
||||
name: 'Indicate OP Quotes'
|
||||
name: 'Mark OP Quotes'
|
||||
cb: @node
|
||||
node: ->
|
||||
# Stop there if it's a clone of a post in the same thread.
|
||||
@ -1838,10 +1893,12 @@ QuoteOP =
|
||||
|
||||
QuoteCT =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Mark Cross-thread Quotes']
|
||||
|
||||
# \u00A0 is nbsp
|
||||
@text = '\u00A0(Cross-thread)'
|
||||
Post::callbacks.push
|
||||
name: 'Indicate Cross-thread Quotes'
|
||||
name: 'Mark Cross-thread Quotes'
|
||||
cb: @node
|
||||
node: ->
|
||||
# Stop there if it's a clone of a post in the same thread.
|
||||
@ -1862,6 +1919,8 @@ QuoteCT =
|
||||
|
||||
Anonymize =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Anonymize']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Anonymize'
|
||||
cb: @node
|
||||
@ -1882,6 +1941,8 @@ Anonymize =
|
||||
|
||||
Time =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Time Formatting']
|
||||
|
||||
@funk = @createFunc Conf['time']
|
||||
Post::callbacks.push
|
||||
name: 'Time Formatting'
|
||||
@ -1940,6 +2001,8 @@ Time =
|
||||
|
||||
FileInfo =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['File Info Formatting']
|
||||
|
||||
@funk = @createFunc Conf['fileInfo']
|
||||
Post::callbacks.push
|
||||
name: 'File Info Formatting'
|
||||
@ -1990,6 +2053,8 @@ FileInfo =
|
||||
|
||||
Sauce =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Sauce']
|
||||
|
||||
links = []
|
||||
for link in Conf['sauces'].split '\n'
|
||||
continue if link[0] is '#'
|
||||
@ -2031,6 +2096,8 @@ Sauce =
|
||||
|
||||
RevealSpoilers =
|
||||
init: ->
|
||||
return if g.VIEW is 'catalog' or !Conf['Reveal Spoilers']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Reveal Spoilers'
|
||||
cb: @node
|
||||
@ -2042,7 +2109,8 @@ RevealSpoilers =
|
||||
|
||||
AutoGIF =
|
||||
init: ->
|
||||
return if g.BOARD.ID in ['gif', 'wsg']
|
||||
return if g.VIEW is 'catalog' or !Conf['Auto-GIF'] or g.BOARD.ID in ['gif', 'wsg']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Auto-GIF'
|
||||
cb: @node
|
||||
@ -2062,7 +2130,8 @@ AutoGIF =
|
||||
|
||||
ImageHover =
|
||||
init: ->
|
||||
return if g.BOARD.ID in ['gif', 'wsg']
|
||||
return if g.VIEW is 'catalog' or !Conf['Image Hover']
|
||||
|
||||
Post::callbacks.push
|
||||
name: 'Auto-GIF'
|
||||
cb: @node
|
||||
@ -2101,7 +2170,8 @@ ImageHover =
|
||||
|
||||
ThreadUpdater =
|
||||
init: ->
|
||||
return if g.VIEW isnt 'thread'
|
||||
return if g.VIEW isnt 'thread' or !Conf['Thread Updater']
|
||||
|
||||
Thread::callbacks.push
|
||||
name: 'Thread Updater'
|
||||
cb: @node
|
||||
|
||||
304
src/main.coffee
304
src/main.coffee
@ -277,211 +277,56 @@ Main =
|
||||
location.href = url if url
|
||||
return
|
||||
|
||||
return if g.VIEW is 'catalog'
|
||||
|
||||
$.addStyle Main.css
|
||||
$.asap (-> d.body), (->
|
||||
$.addClass d.body, $.engine
|
||||
$.addClass d.body, 'fourchan_x'
|
||||
)
|
||||
$.addClass d.documentElement, $.engine
|
||||
$.addClass d.documentElement, 'fourchan_x'
|
||||
|
||||
try
|
||||
Header.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Header'
|
||||
|
||||
try
|
||||
Settings.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Settings'
|
||||
|
||||
if Conf['Resurrect Quotes']
|
||||
initFeature = (name, module) ->
|
||||
console.time "#{name} initialization"
|
||||
try
|
||||
Quotify.init()
|
||||
module.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Resurrect Quotes'
|
||||
Main.handleErrors
|
||||
message: "\"#{name}\" initialization crashed."
|
||||
error: err
|
||||
console.timeEnd "#{name} initialization"
|
||||
|
||||
if Conf['Filter']
|
||||
try
|
||||
Filter.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Filter'
|
||||
|
||||
if Conf['Thread Hiding']
|
||||
try
|
||||
ThreadHiding.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Thread Hiding'
|
||||
|
||||
if Conf['Reply Hiding']
|
||||
try
|
||||
ReplyHiding.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Reply Hiding'
|
||||
|
||||
try
|
||||
Recursive.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Recursive'
|
||||
|
||||
if Conf['Menu']
|
||||
try
|
||||
Menu.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Menu'
|
||||
|
||||
if Conf['Report Link']
|
||||
try
|
||||
ReportLink.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Report Link'
|
||||
|
||||
if Conf['Thread Hiding']
|
||||
try
|
||||
ThreadHiding.menu.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Thread Hiding - Menu'
|
||||
|
||||
if Conf['Reply Hiding']
|
||||
try
|
||||
ReplyHiding.menu.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Reply Hiding - Menu'
|
||||
|
||||
if Conf['Delete Link']
|
||||
try
|
||||
DeleteLink.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Delete Link'
|
||||
|
||||
if Conf['Filter']
|
||||
try
|
||||
Filter.menu.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Filter - Menu'
|
||||
|
||||
if Conf['Download Link']
|
||||
try
|
||||
DownloadLink.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Download Link'
|
||||
|
||||
if Conf['Archive Link']
|
||||
try
|
||||
ArchiveLink.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Archive Link'
|
||||
|
||||
if Conf['Quote Inline']
|
||||
try
|
||||
QuoteInline.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Quote Inline'
|
||||
|
||||
if Conf['Quote Preview']
|
||||
try
|
||||
QuotePreview.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Quote Preview'
|
||||
|
||||
if Conf['Quote Backlinks']
|
||||
try
|
||||
QuoteBacklink.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Quote Backlinks'
|
||||
|
||||
if Conf['Indicate OP Quotes']
|
||||
try
|
||||
QuoteOP.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Indicate OP Quotes'
|
||||
|
||||
if Conf['Indicate Cross-thread Quotes']
|
||||
try
|
||||
QuoteCT.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Indicate Cross-thread Quotes'
|
||||
|
||||
if Conf['Anonymize']
|
||||
try
|
||||
Anonymize.init()
|
||||
catch e
|
||||
# XXX handle error
|
||||
$.log err, 'Anonymize'
|
||||
|
||||
if Conf['Time Formatting']
|
||||
try
|
||||
Time.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Time Formatting'
|
||||
|
||||
if Conf['File Info Formatting']
|
||||
try
|
||||
FileInfo.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'File Info Formatting'
|
||||
|
||||
if Conf['Sauce']
|
||||
try
|
||||
Sauce.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Sauce'
|
||||
|
||||
if Conf['Reveal Spoilers']
|
||||
try
|
||||
RevealSpoilers.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Reveal Spoilers'
|
||||
|
||||
if Conf['Auto-GIF']
|
||||
try
|
||||
AutoGIF.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Auto-GIF'
|
||||
|
||||
if Conf['Image Hover']
|
||||
try
|
||||
ImageHover.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Image Hover'
|
||||
|
||||
if Conf['Thread Updater']
|
||||
try
|
||||
ThreadUpdater.init()
|
||||
catch err
|
||||
# XXX handle error
|
||||
$.log err, 'Thread Updater'
|
||||
console.time 'All initializations'
|
||||
initFeature 'Header', Header
|
||||
initFeature 'Settings', Settings
|
||||
initFeature 'Resurrect Quotes', Quotify
|
||||
initFeature 'Filter', Filter
|
||||
initFeature 'Thread Hiding', ThreadHiding
|
||||
initFeature 'Reply Hiding', ReplyHiding
|
||||
initFeature 'Recursive', Recursive
|
||||
initFeature 'Menu', Menu
|
||||
initFeature 'Report Link', ReportLink
|
||||
initFeature 'Thread Hiding (Menu)', ThreadHiding.menu
|
||||
initFeature 'Reply Hiding (Menu)', ReplyHiding.menu
|
||||
initFeature 'Delete Link', DeleteLink
|
||||
initFeature 'Filter (Menu)', Filter.menu
|
||||
initFeature 'Download Link', DownloadLink
|
||||
initFeature 'Archive Link', ArchiveLink
|
||||
initFeature 'Quote Inline', QuoteInline
|
||||
initFeature 'Quote Preview', QuotePreview
|
||||
initFeature 'Quote Backlinks', QuoteBacklink
|
||||
initFeature 'Mark OP Quotes', QuoteOP
|
||||
initFeature 'Mark Cross-thread Quotes', QuoteCT
|
||||
initFeature 'Anonymize', Anonymize
|
||||
initFeature 'Time Formatting', Time
|
||||
initFeature 'File Info Formatting', FileInfo
|
||||
initFeature 'Sauce', Sauce
|
||||
initFeature 'Reveal Spoilers', RevealSpoilers
|
||||
initFeature 'Auto-GIF', AutoGIF
|
||||
initFeature 'Image Hover', ImageHover
|
||||
initFeature 'Thread Updater', ThreadUpdater
|
||||
console.timeEnd 'All initializations'
|
||||
|
||||
$.ready Main.initReady
|
||||
|
||||
initReady: ->
|
||||
if d.title is '4chan - 404 Not Found'
|
||||
$.rmClass d.documentElement, 'fourchan_x'
|
||||
if Conf['404 Redirect'] and g.VIEW is 'thread'
|
||||
location.href = Redirect.to
|
||||
board: g.BOARD
|
||||
@ -505,25 +350,66 @@ Main =
|
||||
posts.push new Post threadChild, thread, g.BOARD
|
||||
catch err
|
||||
# Skip posts that we failed to parse.
|
||||
# XXX handle error
|
||||
# Post parser crashed for post No.#{threadChild.id[2..]}
|
||||
$.log threadChild, err
|
||||
unless errors
|
||||
errors = []
|
||||
errors.push
|
||||
message: "Parsing of Post No.#{threadChild.id.match(/\d+/)} failed. Post will be skipped."
|
||||
error: err
|
||||
Main.handleErrors errors if errors
|
||||
|
||||
Main.callbackNodes Thread, threads, true
|
||||
Main.callbackNodes Post, posts, true
|
||||
Main.callbackNodes Thread, threads
|
||||
Main.callbackNodes Post, posts
|
||||
|
||||
callbackNodes: (klass, nodes, notify) ->
|
||||
callbackNodes: (klass, nodes) ->
|
||||
# get the nodes' length only once
|
||||
len = nodes.length
|
||||
for callback in klass::callbacks
|
||||
try
|
||||
for i in [0...len]
|
||||
callback.cb.call nodes[i]
|
||||
catch err
|
||||
# XXX handle error if notify
|
||||
$.log callback.name, 'crashed. error:', err.message, nodes[i]
|
||||
$.log err.stack
|
||||
return
|
||||
for i in [0...len]
|
||||
node = nodes[i]
|
||||
try
|
||||
callback.cb.call node
|
||||
catch err
|
||||
unless errors
|
||||
errors = []
|
||||
errors.push
|
||||
message: "\"#{callback.name}\" crashed on #{klass.name} No.#{node} (/#{node.board}/)."
|
||||
error: err
|
||||
Main.handleErrors errors if errors
|
||||
|
||||
handleErrors: (errors) ->
|
||||
unless 'length' of errors
|
||||
error = errors
|
||||
else if errors.length is 1
|
||||
error = errors[0]
|
||||
if error
|
||||
new Notification 'error', Main.parseError(error), 15
|
||||
return
|
||||
|
||||
div = $.el 'div',
|
||||
innerHTML: "#{errors.length} errors occured. [<a href=javascript:;>show</a>]"
|
||||
$.on div.lastElementChild, 'click', ->
|
||||
if @textContent is 'show'
|
||||
@textContent = 'hide'
|
||||
logs.hidden = false
|
||||
else
|
||||
@textContent = 'show'
|
||||
logs.hidden = true
|
||||
|
||||
logs = $.el 'div',
|
||||
hidden: true
|
||||
for error in errors
|
||||
$.add logs, Main.parseError error
|
||||
|
||||
new Notification 'error', [div, logs], 30
|
||||
|
||||
parseError: (data) ->
|
||||
{message, error} = data
|
||||
$.log message, error.stack
|
||||
message = $.el 'div',
|
||||
textContent: message
|
||||
error = $.el 'div',
|
||||
textContent: error
|
||||
[message, error]
|
||||
|
||||
css: """<%= grunt.file.read('css/style.css') %>"""
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user