機能 #1250 » 0001-remain_charcount_spell.patch
core/mui/gtk_postbox.rb | ||
---|---|---|
6 | 6 | |
7 | 7 |
require 'gtk2' |
8 | 8 |
require 'thread' |
9 |
require 'twitter-text' |
|
10 | 9 |
miquire :mui, 'miracle_painter' |
11 | 10 |
miquire :mui, 'intelligent_textview' |
12 | 11 | |
... | ... | |
95 | 94 |
def widget_remain |
96 | 95 |
return @remain if defined?(@remain) |
97 | 96 |
@remain = Gtk::Label.new('---') |
97 |
tag = Plugin[:gtk].handler_tag |
|
98 |
@remain.ssc_atonce(:expose_event) { |
|
99 |
Plugin[:gtk].on_world_change_current(tags: tag) { |world| |
|
100 |
update_remain_charcount |
|
101 |
} |
|
102 |
false |
|
103 |
} |
|
104 |
@remain.ssc(:destroy) { |
|
105 |
Plugin[:gtk].detach(tag) |
|
106 |
} |
|
98 | 107 |
Delayer.new{ |
99 |
if not @remain.destroyed?
|
|
100 |
@remain.set_text(remain_charcount.to_s) end }
|
|
108 |
update_remain_charcount
|
|
109 |
} |
|
101 | 110 |
widget_post.buffer.ssc(:changed){ |textview, event| |
102 |
@remain.set_text(remain_charcount.to_s) } |
|
111 |
update_remain_charcount |
|
112 |
} |
|
103 | 113 |
@remain end |
104 | 114 | |
105 | 115 |
def widget_send |
... | ... | |
305 | 315 |
def use_blind_footer? |
306 | 316 |
@use_blind_footer end |
307 | 317 | |
308 |
def remain_charcount |
|
309 |
if not widget_post.destroyed? |
|
310 |
text = trim_hidden_regions(widget_post.buffer.text + UserConfig[:footer]) |
|
311 |
Twitter::TwitterText::Extractor.extract_urls(text).map{|url| |
|
312 |
if url.length < posted_url_length(url) |
|
313 |
-(posted_url_length(url) - url.length) |
|
314 |
else |
|
315 |
url.length - posted_url_length(url) end |
|
316 |
}.inject(140 - text.size, &:+) |
|
317 |
end end |
|
318 | ||
319 |
def trim_hidden_regions(text) |
|
320 |
trim_hidden_header(trim_hidden_footer(text)) |
|
321 |
end |
|
322 | ||
323 |
# 文字列からhidden headerを除いた文字列を返す。 |
|
324 |
# hidden headerが含まれていない場合は、 _text_ を返す。 |
|
325 |
def trim_hidden_header(text) |
|
326 |
return text unless UserConfig[:auto_populate_reply_metadata] |
|
327 |
mentions = text.match(%r[\A((?:@[a-zA-Z0-9_]+\s+)+)]) |
|
328 |
forecast_receivers_sn = Set.new |
|
329 |
if reply? |
|
330 |
@to.first.each_ancestor.each do |m| |
|
331 |
forecast_receivers_sn << m.user.idname |
|
332 |
forecast_receivers_sn.merge(m.receive_user_screen_names) |
|
333 |
end |
|
334 |
end |
|
335 |
if mentions |
|
336 |
specific_screen_names = Set.new(mentions[1].split(/\s+/).map{|s|s[1, s.size]}) |
|
337 |
[*(specific_screen_names - forecast_receivers_sn).map{|s|"@#{s}"}, text[mentions.end(0),text.size]].join(' '.freeze) |
|
338 |
else |
|
339 |
text |
|
340 |
end |
|
318 |
def update_remain_charcount |
|
319 |
remain_charcount.next{ |count| |
|
320 |
@remain.set_text((count || '---').to_s) if not @remain.destroyed? |
|
321 |
}.trap { |
|
322 |
@remain.set_text('---') if not @remain.destroyed? |
|
323 |
} |
|
341 | 324 |
end |
342 | 325 | |
343 |
# 文字列からhidden footerを除いた文字列を返す。 |
|
344 |
# hidden footerが含まれていない場合は、 _text_ を返す。 |
|
345 |
def trim_hidden_footer(text) |
|
346 |
attachment_url = text.match(%r[\A(.*?)\s+(https?://twitter.com/(?:#!/)?(?:[a-zA-Z0-9_]+)/status(?:es)?/(?:\d+)(?:\?.*)?)\Z]m) |
|
347 |
if attachment_url |
|
348 |
attachment_url[1] |
|
349 |
else |
|
350 |
text |
|
326 |
def remain_charcount |
|
327 |
if not widget_post.destroyed? |
|
328 |
current_world, = Plugin.filtering(:world_current, nil) |
|
329 |
Plugin[:gtk].spell(:remain_charcount, current_world, text: widget_post.buffer.text + UserConfig[:footer]) |
|
351 | 330 |
end |
352 | 331 |
end |
353 | 332 | |
354 |
# URL _url_ がTwitterに投稿された時に何文字としてカウントされるかを返す |
|
355 |
# ==== Args |
|
356 |
# [url] String URL |
|
357 |
# ==== Return |
|
358 |
# Fixnum URLの長さ |
|
359 |
def posted_url_length(url) |
|
360 |
Plugin.filtering(:tco_url_length, url, 0).last end |
|
361 | ||
362 | 333 |
def focus_out_event(widget, event=nil) |
363 | 334 |
options = @options |
364 | 335 |
Delayer.new{ |
core/plugin/twitter/twitter.rb | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
require 'json' |
3 |
require 'twitter-text' |
|
3 | 4 | |
4 | 5 |
module Plugin::Twitter; end |
5 | 6 | |
... | ... | |
238 | 239 |
} |
239 | 240 |
end |
240 | 241 | |
242 |
defspell(:remain_charcount, :twitter) do |twitter, text:| |
|
243 |
text = trim_hidden_regions(text) |
|
244 |
Twitter::TwitterText::Extractor.extract_urls(text).map{|url| |
|
245 |
if url.length < posted_url_length(url) |
|
246 |
-(posted_url_length(url) - url.length) |
|
247 |
else |
|
248 |
url.length - posted_url_length(url) |
|
249 |
end |
|
250 |
}.inject(140 - text.size, &:+) |
|
251 |
end |
|
252 | ||
253 |
def trim_hidden_regions(text) |
|
254 |
trim_hidden_header(trim_hidden_footer(text)) |
|
255 |
end |
|
256 | ||
257 |
# 文字列からhidden headerを除いた文字列を返す。 |
|
258 |
# hidden headerが含まれていない場合は、 _text_ を返す。 |
|
259 |
def trim_hidden_header(text) |
|
260 |
return text unless UserConfig[:auto_populate_reply_metadata] |
|
261 |
mentions = text.match(%r[\A((?:@[a-zA-Z0-9_]+\s+)+)]) |
|
262 |
forecast_receivers_sn = Set.new |
|
263 |
if reply? |
|
264 |
@to.first.each_ancestor.each do |m| |
|
265 |
forecast_receivers_sn << m.user.idname |
|
266 |
forecast_receivers_sn.merge(m.receive_user_screen_names) |
|
267 |
end |
|
268 |
end |
|
269 |
if mentions |
|
270 |
specific_screen_names = Set.new(mentions[1].split(/\s+/).map{|s|s[1, s.size]}) |
|
271 |
[*(specific_screen_names - forecast_receivers_sn).map{|s|"@#{s}"}, text[mentions.end(0),text.size]].join(' '.freeze) |
|
272 |
else |
|
273 |
text |
|
274 |
end |
|
275 |
end |
|
276 | ||
277 |
# 文字列からhidden footerを除いた文字列を返す。 |
|
278 |
# hidden footerが含まれていない場合は、 _text_ を返す。 |
|
279 |
def trim_hidden_footer(text) |
|
280 |
attachment_url = text.match(%r[\A(.*?)\s+(https?://twitter.com/(?:#!/)?(?:[a-zA-Z0-9_]+)/status(?:es)?/(?:\d+)(?:\?.*)?)\Z]m) |
|
281 |
if attachment_url |
|
282 |
attachment_url[1] |
|
283 |
else |
|
284 |
text |
|
285 |
end |
|
286 |
end |
|
287 | ||
288 |
# URL _url_ がTwitterに投稿された時に何文字としてカウントされるかを返す |
|
289 |
# ==== Args |
|
290 |
# [url] String URL |
|
291 |
# ==== Return |
|
292 |
# Fixnum URLの長さ |
|
293 |
def posted_url_length(url) |
|
294 |
Plugin.filtering(:tco_url_length, url, 0).last |
|
295 |
end |
|
296 | ||
241 | 297 |
# リツイートを削除した時、ちゃんとリツイートリストからそれを削除する |
242 | 298 |
on_destroyed do |messages| |
243 | 299 |
messages.each{ |message| |