Quick Reply Personas! #330.
This commit is contained in:
parent
363753fc19
commit
9183ca0b6a
@ -8,7 +8,7 @@ Reporting bugs:
|
|||||||
1. Precise steps to reproduce the problem, with the expected and actual results.
|
1. Precise steps to reproduce the problem, with the expected and actual results.
|
||||||
2. Console errors, if any.
|
2. Console errors, if any.
|
||||||
3. Browser version.
|
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:
|
Open your console with:
|
||||||
- `Ctrl + Shift + J` on Chrome.
|
- `Ctrl + Shift + J` on Chrome.
|
||||||
|
|||||||
@ -335,15 +335,20 @@ a[href="javascript:;"] {
|
|||||||
.section-main label {
|
.section-main label {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
.section-filter ul {
|
.section-filter ul,
|
||||||
|
.section-qr ul {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.section-filter li {
|
.section-filter li,
|
||||||
|
.section-qr li {
|
||||||
margin: 10px 40px;
|
margin: 10px 40px;
|
||||||
}
|
}
|
||||||
.section-filter textarea {
|
.section-filter textarea {
|
||||||
height: 500px;
|
height: 500px;
|
||||||
}
|
}
|
||||||
|
.section-qr textarea {
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
.section-sauce textarea {
|
.section-sauce textarea {
|
||||||
height: 350px;
|
height: 350px;
|
||||||
}
|
}
|
||||||
|
|||||||
16
html/General/Settings-section-QR.html
Normal file
16
html/General/Settings-section-QR.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<fieldset>
|
||||||
|
<legend>Quick Reply Personas <span class="warning" #{if Conf['Quick Reply'] then 'hidden' else ''}>is disabled.</span></legend>
|
||||||
|
<textarea name="QR.personas" class="field" spellcheck="false"></textarea>
|
||||||
|
<p>
|
||||||
|
One item per line.<br>
|
||||||
|
Items will be added in the relevant input's auto-completion list.<br>
|
||||||
|
Password items will always be used, since there is no password input.<br>
|
||||||
|
Lines starting with a <code>#</code> will be ignored.
|
||||||
|
</p>
|
||||||
|
<ul>You can use these settings with each item, separate them with semicolons:
|
||||||
|
<li>Possible items are: <code>name</code>, <code>email</code>, <code>subject</code> and <code>password</code>.</li>
|
||||||
|
<li>Wrap values of items with quotes, like this: <code>email:"sage"</code>.</li>
|
||||||
|
<li>Force values as defaults with the <code>always</code> keyword, for example: <code>email:"sage";always</code>.</li>
|
||||||
|
<li>Select specific boards for an item, separated with commas, for example: <code>email:"sage";boards:jp;always</code>.</li>
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
@ -8,10 +8,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<form>
|
<form>
|
||||||
<div class="persona">
|
<div class="persona">
|
||||||
<input id="dump-button" type="button" title="Dump list" value="+">
|
<input type="button" id="dump-button" title="Dump list" value="+">
|
||||||
<input name="name" data-name="name" title="Name" placeholder="Name" class="field" size="1">
|
<input data-name="name" list="list-name" title="Name" placeholder="Name" class="field" size="1">
|
||||||
<input name="email" data-name="email" title="E-mail" placeholder="E-mail" class="field" size="1">
|
<input data-name="email" list="list-email" title="E-mail" placeholder="E-mail" class="field" size="1">
|
||||||
<input name="sub" data-name="sub" title="Subject" placeholder="Subject" class="field" size="1">
|
<input data-name="sub" list="list-sub" title="Subject" placeholder="Subject" class="field" size="1">
|
||||||
</div>
|
</div>
|
||||||
<div id="dump-list-container">
|
<div id="dump-list-container">
|
||||||
<div id="dump-list"></div>
|
<div id="dump-list"></div>
|
||||||
@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="file-n-submit">
|
<div id="file-n-submit">
|
||||||
<input type="submit">
|
<input type="submit">
|
||||||
<input id="qr-file-button" type="button" value="Choose files">
|
<input type="button" id="qr-file-button" value="Choose files">
|
||||||
<span id="qr-filename-container">
|
<span id="qr-filename-container">
|
||||||
<span id="qr-no-file">No selected file</span>
|
<span id="qr-no-file">No selected file</span>
|
||||||
<span id="qr-filename"></span>
|
<span id="qr-filename"></span>
|
||||||
@ -33,3 +33,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<input type="file" multiple>
|
<input type="file" multiple>
|
||||||
</form>
|
</form>
|
||||||
|
<datalist id="list-name"></datalist>
|
||||||
|
<datalist id="list-email"></datalist>
|
||||||
|
<datalist id="list-sub"></datalist>
|
||||||
|
|||||||
@ -147,6 +147,11 @@ Config =
|
|||||||
'Top Board List': false
|
'Top Board List': false
|
||||||
'Bottom Board List': false
|
'Bottom Board List': false
|
||||||
'Custom Board Navigation': true
|
'Custom Board Navigation': true
|
||||||
|
QR:
|
||||||
|
'QR.personas': [
|
||||||
|
'#email:"sage";boards:jp;always'
|
||||||
|
'email:"sage"'
|
||||||
|
].join '\n'
|
||||||
boardnav: '[current-title / toggle-all]'
|
boardnav: '[current-title / toggle-all]'
|
||||||
time: '%m/%d/%y(%a)%H:%M:%S'
|
time: '%m/%d/%y(%a)%H:%M:%S'
|
||||||
backlink: '>>%id'
|
backlink: '>>%id'
|
||||||
|
|||||||
@ -42,6 +42,7 @@ Settings =
|
|||||||
|
|
||||||
Settings.addSection 'Main', Settings.main
|
Settings.addSection 'Main', Settings.main
|
||||||
Settings.addSection 'Filter', Settings.filter
|
Settings.addSection 'Filter', Settings.filter
|
||||||
|
Settings.addSection 'QR', Settings.qr
|
||||||
Settings.addSection 'Sauce', Settings.sauce
|
Settings.addSection 'Sauce', Settings.sauce
|
||||||
Settings.addSection 'Rice', Settings.rice
|
Settings.addSection 'Rice', Settings.rice
|
||||||
Settings.addSection 'Keybinds', Settings.keybinds
|
Settings.addSection 'Keybinds', Settings.keybinds
|
||||||
@ -320,14 +321,23 @@ Settings =
|
|||||||
<%= grunt.file.read('html/General/Settings-section-Filter-guide.html').replace(/>\s+</g, '><').trim() %>
|
<%= grunt.file.read('html/General/Settings-section-Filter-guide.html').replace(/>\s+</g, '><').trim() %>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
qr: (section) ->
|
||||||
|
section.innerHTML = """
|
||||||
|
<%= grunt.file.read('html/General/Settings-section-QR.html').replace(/>\s+</g, '><').trim() %>
|
||||||
|
"""
|
||||||
|
ta = $ 'textarea', section
|
||||||
|
$.get 'QR.personas', Conf['QR.personas'], (item) ->
|
||||||
|
ta.value = item['QR.personas']
|
||||||
|
$.on ta, 'change', $.cb.value
|
||||||
|
|
||||||
sauce: (section) ->
|
sauce: (section) ->
|
||||||
section.innerHTML = """
|
section.innerHTML = """
|
||||||
<%= grunt.file.read('html/General/Settings-section-Sauce.html').replace(/>\s+</g, '><').trim() %>
|
<%= grunt.file.read('html/General/Settings-section-Sauce.html').replace(/>\s+</g, '><').trim() %>
|
||||||
"""
|
"""
|
||||||
sauce = $ 'textarea', section
|
ta = $ 'textarea', section
|
||||||
$.get 'sauces', Conf['sauces'], (item) ->
|
$.get 'sauces', Conf['sauces'], (item) ->
|
||||||
sauce.value = item['sauces']
|
ta.value = item['sauces']
|
||||||
$.on sauce, 'change', $.cb.value
|
$.on ta, 'change', $.cb.value
|
||||||
|
|
||||||
rice: (section) ->
|
rice: (section) ->
|
||||||
section.innerHTML = """
|
section.innerHTML = """
|
||||||
|
|||||||
@ -46,18 +46,12 @@ DeleteLink =
|
|||||||
$.off @, 'click', DeleteLink.delete
|
$.off @, 'click', DeleteLink.delete
|
||||||
@textContent = "Deleting #{@textContent}..."
|
@textContent = "Deleting #{@textContent}..."
|
||||||
|
|
||||||
pwd =
|
|
||||||
if m = d.cookie.match /4chan_pass=([^;]+)/
|
|
||||||
decodeURIComponent m[1]
|
|
||||||
else
|
|
||||||
$.id('delPassword').value
|
|
||||||
|
|
||||||
fileOnly = $.hasClass @, 'delete-file'
|
fileOnly = $.hasClass @, 'delete-file'
|
||||||
|
|
||||||
form =
|
form =
|
||||||
mode: 'usrdel'
|
mode: 'usrdel'
|
||||||
onlyimgdel: fileOnly
|
onlyimgdel: fileOnly
|
||||||
pwd: pwd
|
pwd: QR.persona.getPassword()
|
||||||
form[post.ID] = 'delete'
|
form[post.ID] = 'delete'
|
||||||
|
|
||||||
link = @
|
link = @
|
||||||
|
|||||||
@ -134,6 +134,72 @@ QR =
|
|||||||
value
|
value
|
||||||
status.disabled = disabled or false
|
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:
|
cooldown:
|
||||||
init: ->
|
init: ->
|
||||||
return unless Conf['Cooldown']
|
return unless Conf['Cooldown']
|
||||||
@ -403,18 +469,27 @@ QR =
|
|||||||
prev.spoiler
|
prev.spoiler
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
$.get 'QR.persona', {}, (item) =>
|
QR.persona.get (persona) =>
|
||||||
persona = item['QR.persona']
|
@name = if 'name' of QR.persona.always
|
||||||
@name = if prev
|
QR.persona.always.name
|
||||||
|
else if prev
|
||||||
prev.name
|
prev.name
|
||||||
else
|
else
|
||||||
persona.name
|
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
|
prev.email
|
||||||
else
|
else
|
||||||
persona.email
|
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
|
@load() if QR.selected is @ # load persona
|
||||||
@select() if select
|
@select() if select
|
||||||
@unlock()
|
@unlock()
|
||||||
@ -818,8 +893,8 @@ QR =
|
|||||||
$.set 'QR Size', @style.cssText
|
$.set 'QR Size', @style.cssText
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
QR.persona.init()
|
||||||
new QR.post true
|
new QR.post true
|
||||||
|
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.cooldown.init()
|
QR.cooldown.init()
|
||||||
QR.captcha.init()
|
QR.captcha.init()
|
||||||
@ -899,7 +974,7 @@ QR =
|
|||||||
spoiler: post.spoiler
|
spoiler: post.spoiler
|
||||||
textonly: textOnly
|
textonly: textOnly
|
||||||
mode: 'regist'
|
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_challenge_field: challenge
|
||||||
recaptcha_response_field: response
|
recaptcha_response_field: response
|
||||||
|
|
||||||
@ -1002,13 +1077,7 @@ QR =
|
|||||||
QR.cleanNotifications()
|
QR.cleanNotifications()
|
||||||
QR.notifications.push new Notification 'success', h1.textContent, 5
|
QR.notifications.push new Notification 'success', h1.textContent, 5
|
||||||
|
|
||||||
$.get 'QR.persona', {}, (item) ->
|
QR.persona.set post
|
||||||
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
|
|
||||||
|
|
||||||
[_, threadID, postID] = h1.nextSibling.textContent.match /thread:(\d+),no:(\d+)/
|
[_, threadID, postID] = h1.nextSibling.textContent.match /thread:(\d+),no:(\d+)/
|
||||||
postID = +postID
|
postID = +postID
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user