X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FView.pm;h=65788dbebc01717c6ae49db5563996f23855095d;hb=5c5dfb7d5558ff248477fa57aef08e2a8bbd9800;hp=2b6061aeaaa0655cb621a25c2db686871ff58b5f;hpb=434f5d652a0ef43a850262429c1bce9881bd7d5f;p=public-inbox.git diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 2b6061ae..65788dbe 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -49,8 +49,7 @@ sub msg_html { # /$INBOX/$MESSAGE_ID/#R sub msg_reply { my ($ctx, $hdr) = @_; - my $se_url = - 'https://kernel.org/pub/software/scm/git/docs/git-send-email.html'; + my $se_url = 'https://git-htmldocs.bogomips.org/git-send-email.html'; my ($arg, $link) = mailto_arg_link($hdr); push @$arg, '/path/to/YOUR_REPLY'; @@ -84,71 +83,78 @@ sub in_reply_to { undef; } +sub _hdr_names ($$) { + my ($hdr, $field) = @_; + my $val = $hdr->header($field) or return ''; + ascii_html(join(', ', PublicInbox::Address::names($val))); +} + +sub nr_to_s ($$$) { + my ($nr, $singular, $plural) = @_; + return "0 $plural" if $nr == 0; + $nr == 1 ? "$nr $singular" : "$nr $plural"; +} + # this is already inside a
sub index_entry { my ($mime, $level, $state) = @_; - my $midx = $state->{anchor_idx}++; + $state->{anchor_idx}++; my $ctx = $state->{ctx}; my $srch = $ctx->{srch}; my $hdr = $mime->header_obj; my $subj = $hdr->header('Subject'); my $mid_raw = mid_clean(mid_mime($mime)); - my $id = anchor_for($mid_raw); - my $seen = $state->{seen}; - $seen->{$id} = "#$id"; # save the anchor for children, later - + my $id = id_compress($mid_raw); + my $id_m = 'm'.$id; my $mid = PublicInbox::Hval->new_msgid($mid_raw); - my $from = PublicInbox::Address::from_name($hdr->header('From')); my $root_anchor = $state->{root_anchor} || ''; my $path = $root_anchor ? '../../' : ''; my $href = $mid->as_href; my $irt = in_reply_to($hdr); - my $parent_anchor = $seen->{anchor_for($irt)} if defined $irt; - $from = ascii_html($from); - $subj = ascii_html($subj); - $subj = "$subj"; - $subj = "$subj" if $root_anchor eq $id; + $subj = ''.ascii_html($subj).''; + $subj = "$subj" if $root_anchor eq $id_m; my $ts = _msg_date($hdr); - my $rv = ""; - $rv .= "$subj\n"; - my $txt = "${path}$href/raw"; - my $fh = $state->{fh}; - $fh->write($rv .= "- $from @ $ts UTC (raw)\n\n"); - - my $mhref = "${path}$href/"; + my $rv = ""); # '\n' for lynx } sub thread_html { @@ -168,63 +174,62 @@ sub walk_thread { } } +sub pre_thread { + my ($state, $level, $node) = @_; + my $parent = $node->parent; + if ($parent) { + my $mid = $parent->messageid; + my $m = $state->{mapping}; + $m->{$mid} ||= 0; + $m->{$mid}++; + } + skel_dump($state, $level, $node); +} + # only private functions below. sub emit_thread_html { my ($res, $ctx, $foot, $srch) = @_; my $mid = $ctx->{mid}; - my $flat = $ctx->{flat}; - my $msgs = load_results($srch->get_thread($mid, { asc => $flat })); - my $nr = scalar @$msgs; + my $sres = $srch->get_thread($mid, { asc => 1 }); + my $msgs = load_results($sres); + my $nr = $sres->{total}; return missing_thread($res, $ctx) if $nr == 0; - my $seen = {}; + my $skel = ''; my $state = { - res => $res, - ctx => $ctx, - seen => $seen, - root_anchor => anchor_for($mid), anchor_idx => 0, + ctx => $ctx, cur_level => 0, + dst => \$skel, + mapping => {}, # mid -> reply count + prev_attr => '', + prev_level => 0, + res => $res, + root_anchor => anchor_for($mid), + seen => {}, + srch => $ctx->{srch}, + upfx => '../../', }; - require PublicInbox::Git; - $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir}); - if ($flat) { - pre_anchor_entry($seen, $_) for (@$msgs); - __thread_entry($state, $_, 0) for (@$msgs); - } else { - walk_thread(thread_results($msgs), $state, *thread_entry); - if (my $max = $state->{cur_level}) { - $state->{fh}->write( - ('' x ($max - 1)) . ''); - } - } + walk_thread(thread_results($msgs), $state, *pre_thread); + + thread_entry($state, $_, 0) for @$msgs; # there could be a race due to a message being deleted in git # but still being in the Xapian index: my $fh = delete $state->{fh} or return missing_thread($res, $ctx); - my $final_anchor = $state->{anchor_idx}; - my $next = ""; - $next .= $final_anchor == 1 ? 'only message in' : 'end of'; - $next .= " thread, back to index"; - $next .= "\ndownload thread: "; + my $next = @$msgs == 1 ? 'only message in thread' : 'end of thread'; + $next .= ", back to index"; + $next .= "\n$nr+ messages in thread: (download: "; $next .= "mbox.gz"; - $next .= " / follow: Atom feed"; + $next .= " / follow: Atom feed)\n"; + $next .= $skel; $fh->write('# "; + $rv .= $subj; + my $mhref = $path.$href.'/'; + my $from = _hdr_names($hdr, 'From'); + $rv .= "\n- $from @ $ts UTC\n"; + my @tocc; + foreach my $f (qw(To Cc)) { + my $dst = _hdr_names($hdr, $f); + push @tocc, "$f: $dst" if $dst ne ''; + } + $rv .= ' '.join('; +', @tocc) . "\n" if @tocc; + $rv .= "\n"; # scan through all parts, looking for displayable text - msg_iter($mime, sub { index_walk($fh, $mhref, $_[0]) }); - $rv = "\n" . html_footer($hdr, 0, $ctx, "$path$href/#R"); - + msg_iter($mime, sub { $rv .= add_text_body($mhref, $_[0]) }); + $rv .= "\npermalink" . + " / raw / "; + my $mapping = $state->{mapping}; + my $nr_c = $mapping->{$mid_raw} || 0; + my $nr_s = 0; if (defined $irt) { - unless (defined $parent_anchor) { - my $v = PublicInbox::Hval->new_msgid($irt, 1); - $v = $v->as_href; - $parent_anchor = "${path}$v/"; - } - $rv .= " parent"; + $nr_s = ($mapping->{$irt} || 0) - 1; + $nr_s = 0 if $nr_s < 0; + $irt = anchor_for($irt); + $rv .= "#parent,"; + } else { + $rv .= 'root message:'; } + $nr_s = nr_to_s($nr_s, 'sibling', 'siblings'); + $nr_c = nr_to_s($nr_c, 'reply', 'replies'); + $rv .= " $nr_s, $nr_c"; + $rv .= " / reply"; + if (my $pct = $state->{pct}) { # used by SearchView.pm $rv .= " [relevance $pct->{$mid_raw}%]"; - } elsif ($srch) { - my $threaded = 'threaded'; - my $flat = 'flat'; - my $end = ''; - if ($ctx->{flat}) { - $flat = "$flat"; - $end = "\n"; # for lynx - } else { - $threaded = "$threaded"; - } - $rv .= " [$threaded"; - $rv .= "|$flat]$end"; } - $fh->write($rv .= ''); + $state->{fh}->write($rv .= "\n' . $next . "\n\n". $foot . '