sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

lib/sup/draft.rb (2720B) - raw

      1 module Redwood
      2 
      3 class DraftManager
      4   include Redwood::Singleton
      5 
      6   attr_accessor :source
      7   def initialize dir
      8     @dir = dir
      9     @source = nil
     10   end
     11 
     12   def self.source_name; "sup://drafts"; end
     13   def self.source_id; 9999; end
     14   def new_source; @source = DraftLoader.new @dir; end
     15 
     16   def write_draft
     17     offset = @source.gen_offset
     18     fn = @source.fn_for_offset offset
     19     File.open(fn, "w", :encoding => $encoding) { |f| yield f }
     20     PollManager.poll_from @source
     21   end
     22 
     23   def discard m
     24     raise ArgumentError, "not a draft: source id #{m.source.id.inspect}, should be #{DraftManager.source_id.inspect} for #{m.id.inspect}" unless m.source.id.to_i == DraftManager.source_id
     25     Index.delete m.id
     26     File.delete @source.fn_for_offset(m.source_info) rescue Errno::ENOENT
     27     UpdateManager.relay self, :single_message_deleted, m
     28   end
     29 end
     30 
     31 class DraftLoader < Source
     32   attr_accessor :dir
     33   yaml_properties
     34 
     35   def initialize dir
     36     Dir.mkdir dir unless File.exist? dir
     37     super DraftManager.source_name, true, false
     38     @dir = dir
     39     @cur_offset = 0
     40   end
     41 
     42   def properly_initialized?
     43     !!(@dir && @cur_offset)
     44   end
     45 
     46   def id; DraftManager.source_id; end
     47   def to_s; DraftManager.source_name; end
     48   def uri; DraftManager.source_name; end
     49 
     50   def poll
     51     ids = get_ids
     52     ids.each do |id|
     53       if id >= @cur_offset
     54         @cur_offset = id + 1
     55         yield :add,
     56           :info => id,
     57           :labels => [:draft, :inbox],
     58           :progress => 0.0
     59       end
     60     end
     61   end
     62 
     63   def gen_offset
     64     i = @cur_offset
     65     while File.exist? fn_for_offset(i)
     66       i += 1
     67     end
     68     i
     69   end
     70 
     71   def fn_for_offset o; File.join(@dir, o.to_s); end
     72 
     73   def load_header offset
     74     File.open(fn_for_offset(offset)) { |f| parse_raw_email_header f }
     75   end
     76 
     77   def load_message offset
     78     raise SourceError, "Draft not found" unless File.exist? fn_for_offset(offset)
     79     File.open(fn_for_offset(offset)) do |f|
     80       message = RMail::Parser.read f
     81       message.header.set "Content-Type", "text/plain; charset=#{$encoding}"
     82       message
     83     end
     84   end
     85 
     86   def fallback_date_for_message offset
     87     File.mtime fn_for_offset(offset)
     88   end
     89 
     90   def raw_header offset
     91     ret = ""
     92     File.open(fn_for_offset(offset), "r") do |f|
     93       until f.eof? || (l = f.gets) =~ /^$/
     94         ret += l
     95       end
     96     end
     97     ret
     98   end
     99 
    100   def each_raw_message_line offset
    101     File.open(fn_for_offset(offset), "r") do |f|
    102       yield f.gets until f.eof?
    103     end
    104   end
    105 
    106   def raw_message offset
    107     IO.read fn_for_offset(offset)
    108   end
    109 
    110   def start_offset; 0; end
    111   def end_offset
    112     ids = get_ids
    113     ids.empty? ? 0 : (ids.last + 1)
    114   end
    115 
    116 private
    117 
    118   def get_ids
    119     Dir.entries(@dir).select { |x| x =~ /^\d+$/ }.map { |x| x.to_i }.sort
    120   end
    121 end
    122 
    123 end