From 9183ca0b6a3aee2d0dc76c119141bb9953c6ad8c Mon Sep 17 00:00:00 2001 From: Mayhem Date: Wed, 1 May 2013 00:28:54 +0200 Subject: [PATCH 1/4] Quick Reply Personas! #330. --- CONTRIBUTING.md | 2 +- css/style.css | 9 ++- html/General/Settings-section-QR.html | 16 +++++ html/Posting/QR.html | 13 ++-- src/General/Config.coffee | 5 ++ src/General/Settings.coffee | 16 ++++- src/Menu/DeleteLink.coffee | 8 +-- src/Posting/QR.coffee | 99 +++++++++++++++++++++++---- 8 files changed, 135 insertions(+), 33 deletions(-) create mode 100644 html/General/Settings-section-QR.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5e386b1ee..505072cf3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Reporting bugs: 1. Precise steps to reproduce the problem, with the expected and actual results. 2. Console errors, if any. 3. Browser version. - 4. Your exported settings. + 4. Your exported settings. If your settings contains sensible information (e.g. personas), edit the text file manually. Open your console with: - `Ctrl + Shift + J` on Chrome. diff --git a/css/style.css b/css/style.css index 8511a659c..0aa8ffa2d 100644 --- a/css/style.css +++ b/css/style.css @@ -335,15 +335,20 @@ a[href="javascript:;"] { .section-main label { text-decoration: underline; } -.section-filter ul { +.section-filter ul, +.section-qr ul { padding: 0; } -.section-filter li { +.section-filter li, +.section-qr li { margin: 10px 40px; } .section-filter textarea { height: 500px; } +.section-qr textarea { + height: 200px; +} .section-sauce textarea { height: 350px; } diff --git a/html/General/Settings-section-QR.html b/html/General/Settings-section-QR.html new file mode 100644 index 000000000..372e74c44 --- /dev/null +++ b/html/General/Settings-section-QR.html @@ -0,0 +1,16 @@ +
+ Quick Reply Personas is disabled. + +

+ One item per line.
+ Items will be added in the relevant input's auto-completion list.
+ Password items will always be used, since there is no password input.
+ Lines starting with a # will be ignored. +

+ +
diff --git a/html/Posting/QR.html b/html/Posting/QR.html index ef6776598..aed29ba28 100644 --- a/html/Posting/QR.html +++ b/html/Posting/QR.html @@ -8,10 +8,10 @@
- - - - + + + +
@@ -23,7 +23,7 @@
- + No selected file @@ -33,3 +33,6 @@
+ + + diff --git a/src/General/Config.coffee b/src/General/Config.coffee index afccfe169..f53f67de8 100644 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -147,6 +147,11 @@ Config = 'Top Board List': false 'Bottom Board List': false 'Custom Board Navigation': true + QR: + 'QR.personas': [ + '#email:"sage";boards:jp;always' + 'email:"sage"' + ].join '\n' boardnav: '[current-title / toggle-all]' time: '%m/%d/%y(%a)%H:%M:%S' backlink: '>>%id' diff --git a/src/General/Settings.coffee b/src/General/Settings.coffee index 02f7de8ad..5e9292419 100644 --- a/src/General/Settings.coffee +++ b/src/General/Settings.coffee @@ -42,6 +42,7 @@ Settings = Settings.addSection 'Main', Settings.main Settings.addSection 'Filter', Settings.filter + Settings.addSection 'QR', Settings.qr Settings.addSection 'Sauce', Settings.sauce Settings.addSection 'Rice', Settings.rice Settings.addSection 'Keybinds', Settings.keybinds @@ -320,14 +321,23 @@ Settings = <%= grunt.file.read('html/General/Settings-section-Filter-guide.html').replace(/>\s+<').trim() %> """ + qr: (section) -> + section.innerHTML = """ + <%= grunt.file.read('html/General/Settings-section-QR.html').replace(/>\s+<').trim() %> + """ + ta = $ 'textarea', section + $.get 'QR.personas', Conf['QR.personas'], (item) -> + ta.value = item['QR.personas'] + $.on ta, 'change', $.cb.value + sauce: (section) -> section.innerHTML = """ <%= grunt.file.read('html/General/Settings-section-Sauce.html').replace(/>\s+<').trim() %> """ - sauce = $ 'textarea', section + ta = $ 'textarea', section $.get 'sauces', Conf['sauces'], (item) -> - sauce.value = item['sauces'] - $.on sauce, 'change', $.cb.value + ta.value = item['sauces'] + $.on ta, 'change', $.cb.value rice: (section) -> section.innerHTML = """ diff --git a/src/Menu/DeleteLink.coffee b/src/Menu/DeleteLink.coffee index b3c35d673..fa1b5c5fb 100644 --- a/src/Menu/DeleteLink.coffee +++ b/src/Menu/DeleteLink.coffee @@ -46,18 +46,12 @@ DeleteLink = $.off @, 'click', DeleteLink.delete @textContent = "Deleting #{@textContent}..." - pwd = - if m = d.cookie.match /4chan_pass=([^;]+)/ - decodeURIComponent m[1] - else - $.id('delPassword').value - fileOnly = $.hasClass @, 'delete-file' form = mode: 'usrdel' onlyimgdel: fileOnly - pwd: pwd + pwd: QR.persona.getPassword() form[post.ID] = 'delete' link = @ diff --git a/src/Posting/QR.coffee b/src/Posting/QR.coffee index dadde52d0..41385e3cf 100644 --- a/src/Posting/QR.coffee +++ b/src/Posting/QR.coffee @@ -134,6 +134,72 @@ QR = value status.disabled = disabled or false + persona: + name: [] + email: [] + sub: [] + pwd: '' + always: {} + init: -> + QR.persona.getPassword() + $.get 'QR.personas', Conf['QR.personas'], ({'QR.personas': personas}) -> + for item in personas.split '\n' + QR.persona.parseItem item.trim() + for type in ['name', 'email', 'sub'] + QR.persona.loadPersonas type + return + parseItem: (item) -> + return if item[0] is '#' + return unless match = item.match /(name|email|subject|password):"(.*)"/i + [match, type, val] = match + + # Don't mix up item settings with val. + item = item.replace match, '' + + boards = item.match(/boards:([^;]+)/i)?[1].toLowerCase() or 'global' + if boards isnt 'global' and not (g.BOARD.ID in boards.split ',') + return + + if type is 'password' + QR.persona.pwd = val + return + + type = 'sub' if type is 'subject' + + if /always/i.test item + QR.persona.always[type] = val + + unless val in QR.persona[type] + QR.persona[type].push val + loadPersonas: (type) -> + list = $ "#list-#{type}", QR.nodes.el + for val in QR.persona[type] + $.add list, $.el 'option', + textContent: val + return + getPassword: -> + unless QR.persona.pwd + QR.persona.pwd = if m = d.cookie.match /4chan_pass=([^;]+)/ + decodeURIComponent m[1] + else if input = $.id 'postPassword' + input.value + else + # If we're in a closed thread, #postPassword isn't available. + # And since #delPassword.value is only filled on window.onload + # we'd rather use #postPassword when we can. + $.id('delPassword').value + return QR.persona.pwd + get: (cb) -> + $.get 'QR.persona', {}, ({'QR.persona': persona}) -> + cb persona + set: (post) -> + $.get 'QR.persona', {}, ({'QR.persona': persona}) -> + persona = + name: post.name + email: if /^sage$/.test post.email then persona.email else post.email + sub: if Conf['Remember Subject'] then post.sub else undefined + $.set 'QR.persona', persona + cooldown: init: -> return unless Conf['Cooldown'] @@ -403,18 +469,27 @@ QR = prev.spoiler else false - $.get 'QR.persona', {}, (item) => - persona = item['QR.persona'] - @name = if prev + QR.persona.get (persona) => + @name = if 'name' of QR.persona.always + QR.persona.always.name + else if prev prev.name else persona.name - @email = if prev and !/^sage$/.test prev.email + + @email = if 'email' of QR.persona.always + QR.persona.always.email + else if prev and !/^sage$/.test prev.email prev.email else persona.email - if Conf['Remember Subject'] - @sub = if prev then prev.sub else persona.sub + + @sub = if 'sub' of QR.persona.always + QR.persona.always.sub + else if Conf['Remember Subject'] + if prev then prev.sub else persona.sub + else + '' @load() if QR.selected is @ # load persona @select() if select @unlock() @@ -818,8 +893,8 @@ QR = $.set 'QR Size', @style.cssText <% } %> + QR.persona.init() new QR.post true - QR.status() QR.cooldown.init() QR.captcha.init() @@ -899,7 +974,7 @@ QR = spoiler: post.spoiler textonly: textOnly mode: 'regist' - pwd: if m = d.cookie.match(/4chan_pass=([^;]+)/) then decodeURIComponent m[1] else $.id('postPassword').value + pwd: QR.persona.pwd recaptcha_challenge_field: challenge recaptcha_response_field: response @@ -1002,13 +1077,7 @@ QR = QR.cleanNotifications() QR.notifications.push new Notification 'success', h1.textContent, 5 - $.get 'QR.persona', {}, (item) -> - persona = item['QR.persona'] - persona = - name: post.name - email: if /^sage$/.test post.email then persona.email else post.email - sub: if Conf['Remember Subject'] then post.sub else null - $.set 'QR.persona', persona + QR.persona.set post [_, threadID, postID] = h1.nextSibling.textContent.match /thread:(\d+),no:(\d+)/ postID = +postID From 7772ec842d1d3ef2edf8a8130627bf7e5c3fac75 Mon Sep 17 00:00:00 2001 From: Mayhem Date: Wed, 1 May 2013 00:43:05 +0200 Subject: [PATCH 2/4] Changelog. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a50a4f19..cda2ec51f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +- **New feature**: `Quick Reply Personas` + - Add custom auto-completion for the name, e-mail and subject inputs. + - Always use a specific persona. + - Per-board configuration. + - Access it in the `QR` tab of the Settings window. + ### 3.2.3 - *2013-04-30* - Update archive redirection for /c/, /d/, /v/, /vg/, /w/ and /wg/. From e0233198dd262b26d71ccef940bdb99682ae4c41 Mon Sep 17 00:00:00 2001 From: Mayhem Date: Wed, 1 May 2013 00:45:49 +0200 Subject: [PATCH 3/4] Screw these titles. --- html/Posting/QR.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/html/Posting/QR.html b/html/Posting/QR.html index aed29ba28..b02ef3b5f 100644 --- a/html/Posting/QR.html +++ b/html/Posting/QR.html @@ -9,16 +9,16 @@
- - - + + +
+
- +
From f81fafb375c2bb2fdfb7cf0b8147109924edcc87 Mon Sep 17 00:00:00 2001 From: Mayhem Date: Wed, 1 May 2013 21:54:12 +0200 Subject: [PATCH 4/4] No need to keep these in memory. --- src/Posting/QR.coffee | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Posting/QR.coffee b/src/Posting/QR.coffee index 41385e3cf..b0e25f14a 100644 --- a/src/Posting/QR.coffee +++ b/src/Posting/QR.coffee @@ -135,20 +135,21 @@ QR = status.disabled = disabled or false persona: - name: [] - email: [] - sub: [] pwd: '' always: {} init: -> QR.persona.getPassword() $.get 'QR.personas', Conf['QR.personas'], ({'QR.personas': personas}) -> + types = + name: [] + email: [] + sub: [] for item in personas.split '\n' - QR.persona.parseItem item.trim() - for type in ['name', 'email', 'sub'] - QR.persona.loadPersonas type + QR.persona.parseItem item.trim(), types + for type, arr of types + QR.persona.loadPersonas type, arr return - parseItem: (item) -> + parseItem: (item, types) -> return if item[0] is '#' return unless match = item.match /(name|email|subject|password):"(.*)"/i [match, type, val] = match @@ -169,11 +170,11 @@ QR = if /always/i.test item QR.persona.always[type] = val - unless val in QR.persona[type] - QR.persona[type].push val - loadPersonas: (type) -> + unless val in types[type] + types[type].push val + loadPersonas: (type, arr) -> list = $ "#list-#{type}", QR.nodes.el - for val in QR.persona[type] + for val in arr $.add list, $.el 'option', textContent: val return