heathrow 0.7.3 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 123f2c7c6134d4ea1add0517f649b94353918d1e76583a9f714a1e49d7879f96
4
- data.tar.gz: 26e26497ec050fc246cb2ee1eff2389ceb3088dccb8c83d09257425dd152888a
3
+ metadata.gz: 5157385f8be9722ca5d2920debecea14751c93ba6bdba10840004ee6a9ae301a
4
+ data.tar.gz: f4eae36abc3446bc257c49ff60aca3ed6ef6b1bb981bb753aa9cc5884a74796d
5
5
  SHA512:
6
- metadata.gz: 2130ee038cbc2d9bc8ee4b7855809afaa1c171aba9b8b0967a85d71c9397b39b2ef86afcef58b3301d15556dfc3d07ab8d91d8d12ed77d4a90879904562829a5
7
- data.tar.gz: 3557ffc9cf7af99441c6c4062e63d7bc9c18145b1f537d10607d420f059221f36c33d1f1a86cad76036a69d003eedb39f26c471013c2dba839187350a10c6aff
6
+ metadata.gz: dd461568292aef77abb3ef404d6a7d4d8472ef225f4da407a0dedb604ce8c590b0649455053a56c2a18e4d6023bcba81fcfa5bafaf5498eefe1756e6ee5870a1
7
+ data.tar.gz: 97503edee0d70789701ccdccf02cbf7eff5aa91311deeca2c3d8d28197581ae243f1e04fb693b0780d34c1ae38162e3c1deb89feb34e8210105c76c246004f96
@@ -419,9 +419,10 @@ module Heathrow
419
419
  @initial_load_done = false
420
420
  Thread.new do
421
421
  begin
422
+ @load_limit = 200
422
423
  case @default_view
423
424
  when 'N'
424
- @filtered_messages = @db.get_messages({is_read: false}, 1000, 0, light: true)
425
+ @filtered_messages = @db.get_messages({is_read: false}, @load_limit, 0, light: true)
425
426
  when /^[0-9]$/, /^F\d+$/
426
427
  view = @views[@default_view]
427
428
  if view && view[:filters] && !view[:filters].empty?
@@ -430,16 +431,17 @@ module Heathrow
430
431
  end
431
432
  apply_view_filters(view)
432
433
  else
433
- @filtered_messages = @db.get_messages({}, 1000, 0, light: true)
434
+ @filtered_messages = @db.get_messages({}, @load_limit, 0, light: true)
434
435
  @current_view = 'A'
435
436
  end
436
437
  else
437
- @filtered_messages = @db.get_messages({}, 1000, 0, light: true)
438
+ @filtered_messages = @db.get_messages({}, @load_limit, 0, light: true)
438
439
  @current_view = 'A'
439
440
  end
440
441
  sort_messages
441
442
  @index = 0
442
443
  reset_threading if respond_to?(:reset_threading)
444
+ restore_view_thread_mode if respond_to?(:restore_view_thread_mode)
443
445
  @initial_load_done = true
444
446
  @needs_redraw = true
445
447
  # Preload the heavy mail gem so 'v' (attachments) doesn't lag
@@ -508,9 +510,17 @@ module Heathrow
508
510
  render_all
509
511
  @needs_redraw = false
510
512
  end
513
+ # Check for mailto trigger (from wezterm or external script)
514
+ check_mailto_trigger
515
+
511
516
  chr = getchr(2, flush: false) # 2s timeout to check for new mail
512
517
  begin
513
518
  if chr
519
+ # Clear sticky feedback (errors, "message sent") on any keypress
520
+ if @feedback_sticky
521
+ @feedback_sticky = false
522
+ @feedback_expires_at = Time.now # Expire now so render_bottom_bar clears it
523
+ end
514
524
  @needs_redraw = false # Handlers that need redraw call render_all directly
515
525
  handle_input_key(chr)
516
526
  else
@@ -2254,7 +2264,13 @@ module Heathrow
2254
2264
  def set_feedback(message, color = 156, duration = 3)
2255
2265
  @feedback_message = message
2256
2266
  @feedback_color = color
2257
- @feedback_expires_at = duration > 0 ? Time.now + duration : Time.now + 86400
2267
+ # duration 0 or errors: persist until next user action (cleared by clear_sticky_feedback)
2268
+ @feedback_sticky = (duration == 0 || color == 196)
2269
+ @feedback_expires_at = if @feedback_sticky
2270
+ nil # Never auto-expire; cleared on keypress
2271
+ else
2272
+ Time.now + duration
2273
+ end
2258
2274
  if @panes[:bottom]
2259
2275
  @panes[:bottom].text = " #{message}".fg(color)
2260
2276
  @panes[:bottom].refresh
@@ -3027,6 +3043,7 @@ module Heathrow
3027
3043
  msg = current_message
3028
3044
  return unless msg
3029
3045
  return if msg['is_header'] || msg['is_channel_header'] || msg['is_thread_header']
3046
+ msg = ensure_full_message(msg)
3030
3047
 
3031
3048
  # Mark as read
3032
3049
  if msg['is_read'].to_i == 0
@@ -5324,7 +5341,24 @@ module Heathrow
5324
5341
  render_bottom_bar
5325
5342
  end
5326
5343
 
5327
- def compose_new_mail(source)
5344
+ # Check for mailto trigger file (written by wezterm or external scripts)
5345
+ def check_mailto_trigger
5346
+ mailto_file = File.join(HEATHROW_HOME, 'mailto')
5347
+ return unless File.exist?(mailto_file)
5348
+ addr = File.read(mailto_file).strip
5349
+ File.delete(mailto_file)
5350
+ return if addr.empty?
5351
+
5352
+ # Find the first mail source
5353
+ mail_source = @source_manager.sources.values.find do |s|
5354
+ s['enabled'] && %w[maildir gmail imap].include?(s['plugin_type'] || s['type'])
5355
+ end
5356
+ return unless mail_source
5357
+
5358
+ compose_new_mail(mail_source, mailto: addr)
5359
+ end
5360
+
5361
+ def compose_new_mail(source, mailto: nil)
5328
5362
  require_relative '../message_composer'
5329
5363
  identity = current_identity
5330
5364
 
@@ -5347,7 +5381,7 @@ module Heathrow
5347
5381
  @panes[:bottom].text = " Opening editor for new message...".fg(226)
5348
5382
  @panes[:bottom].refresh
5349
5383
 
5350
- composed = composer.compose_new
5384
+ composed = composer.compose_new(mailto)
5351
5385
  end
5352
5386
  setup_display
5353
5387
  create_panes
@@ -5732,8 +5766,8 @@ module Heathrow
5732
5766
  if composed[:attachments] && !composed[:attachments].empty?
5733
5767
  msg += " (#{composed[:attachments].size} attachment(s))"
5734
5768
  end
5735
- set_feedback(msg, 156, 3)
5736
- render_left_pane if orig_id
5769
+ set_feedback(msg, 156, 0)
5770
+ render_message_list if orig_id
5737
5771
  else
5738
5772
  set_feedback(result[:message], 196, 4)
5739
5773
  end
@@ -7743,8 +7777,10 @@ Required: URL, optional CSS selector
7743
7777
  color = quote_colors[[level - 1, quote_colors.length - 1].min]
7744
7778
  result << colorize_links(stripped, color, link_color)
7745
7779
  else
7746
- # Detect "wrote:" attribution lines (start of indented quote block)
7747
- if stripped =~ /\bwrote:\s*$/
7780
+ # Detect attribution lines (start of indented quote block)
7781
+ # Matches: "wrote:", "skrev ...:", "schrieb ...:", "a écrit :", or "date ... <email>:"
7782
+ if stripped =~ /\b(wrote|skrev|schrieb|geschreven|scrisse|escribi[oó]|a\s+[eé]crit)\b.*:\s*$/ ||
7783
+ stripped =~ /\d\d[:\.]\d\d\s.*<[^>]+>:\s*$/
7748
7784
  indent_quote_level += 1
7749
7785
  color = quote_colors[[indent_quote_level - 1, quote_colors.length - 1].min]
7750
7786
  result << colorize_links(stripped, color, link_color)
@@ -1,3 +1,3 @@
1
1
  module Heathrow
2
- VERSION = '0.7.3'
2
+ VERSION = '0.7.4'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heathrow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-03-18 00:00:00.000000000 Z
12
+ date: 2026-03-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rcurses