diff --git a/src/General/Config.coffee b/src/General/Config.coffee index fa8f09aa6..c20d3f558 100644 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -576,6 +576,10 @@ Config = false 'Thread conversations' ] + 'Upvotes': [ + true + 'Upvote posts.' + ] imageExpansion: 'Fit width': [ diff --git a/src/General/Main.coffee b/src/General/Main.coffee index 7c891c09a..fe171ac48 100644 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -410,6 +410,7 @@ Main = ['Edit Link', QR.oekaki.menu] ['Download Link', DownloadLink] ['Archive Link', ArchiveLink] + ['Upvotes', Upvotes] ['Quote Inlining', QuoteInline] ['Quote Previewing', QuotePreview] ['Quote Backlinks', QuoteBacklink] diff --git a/src/Quotelinks/Upvotes.coffee b/src/Quotelinks/Upvotes.coffee new file mode 100644 index 000000000..8315a5191 --- /dev/null +++ b/src/Quotelinks/Upvotes.coffee @@ -0,0 +1,91 @@ +Upvotes = + count: {} + text: '\u305D\u3046\u3060\u306D' + regexp: /// + (?:^>.*\n)+ + (?: + i + |top + |holy + |shit + |ay* + |oh? + |omg + |god + |jesus + |christ + |fuck + |fukken + |fucking? + |\s + |[.,-] + )* + (?: + \u305D\u3046\u3060\u306D + |this(?!\ ) + |\+1 + |upvote(?!\ )d? + |under[\ -]?rated + |\/thread + |10\/10 + |(?:lol|kek|lel|lmao)(?:'?d|[.!]?$) + |(?:ha)+[.!]?$ + |saved + |nice(?!\ ) + |my\ sides + ) + (?=\b|\W|$) + ///gmi + + init: -> + return unless g.VIEW in ['thread', 'index'] and Conf['Upvotes'] + @textPosted = if g.BOARD.ID is 'r9k' then 'This.' else @text + Post.callbacks.push + name: 'Upvotes' + cb: @node + + node: -> + return if @isFetchedQuote or @origin?.isFetchedQuote + + if @isClone + @nodes.vote = $ '.upvote', @nodes.info + $.on @nodes.vote, 'click', Upvotes.vote + return + + a = $.el 'a', + className: 'upvote' + href: 'javascript:;' + textContent: '+' + $.add @nodes.info, a + @nodes.vote = a + $.on a, 'click', Upvotes.vote + + return unless g.VIEW is 'thread' + + Upvotes.count[@fullID] = 0 + + quotes = {} + for context in @info.comment.match(Upvotes.regexp) or [] + for quote in context.match(/>>\d+/g) or [] + quotes[quote[2..]] = true + for quote of quotes + Upvotes.increment "#{g.BOARD}.#{quote}" + + increment: (fullID) -> + return unless fullID of Upvotes.count + count = ++Upvotes.count[fullID] + post = g.posts[fullID] + for post in [post, post.clones...] + post.nodes.vote.textContent = "#{Upvotes.text}x#{count}" + return + + vote: -> + return unless QR.postingIsEnabled + QR.quote.call @ + {com} = QR.nodes + text = "#{Upvotes.textPosted}\n" + pos = com.selectionStart + com.value = com.value[..pos] + text + com.value[pos...] + pos += text.length + com.setSelectionRange pos, pos + $.event 'input', null, com diff --git a/src/css/style.css b/src/css/style.css index 915086aa3..a4afebec7 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -2084,3 +2084,11 @@ grunt.file.expand('src/Linkification/icons/*.png').map(function(file) { :root.gallery-open.fixed #header-bar:not(.autohide) #shortcuts .fa::before { visibility: hidden; } + +/* Upvotes */ +.upvote { + margin: 0 4px; +} +.post .menu-button:not(:last-of-type) { + margin-right: -4px; +}