X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FView.pm;h=a27e93690ccae41ad3feb5385ec793826cc47272;hb=e3b57fe9f68e80fc85cff46ccec9246b670f1312;hp=4cb72bea849e6b28b4bfacc2684af1daf2689128;hpb=77eafbd653d2efac546f2c330d8cf5e84bef2712;p=public-inbox.git diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 4cb72bea..a27e9369 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -7,8 +7,10 @@ package PublicInbox::View; use strict; use warnings; use bytes (); # only for bytes::length +use List::Util qw(max); use PublicInbox::MsgTime qw(msg_datestamp); -use PublicInbox::Hval qw(ascii_html obfuscate_addrs prurl mid_href); +use PublicInbox::Hval qw(ascii_html obfuscate_addrs prurl mid_href + ts2str fmt_ts); use PublicInbox::Linkify; use PublicInbox::MID qw(id_compress mids mids_for_index references $MID_EXTRACT); @@ -18,7 +20,6 @@ use PublicInbox::WwwStream qw(html_oneshot); use PublicInbox::Reply; use PublicInbox::ViewDiff qw(flush_diff); use PublicInbox::Eml; -use POSIX qw(strftime); use Time::Local qw(timegm); use PublicInbox::Smsg qw(subject_normalized); use constant COLS => 72; @@ -47,7 +48,7 @@ sub msg_page_i { # /$INBOX/$MSGID/ for unindexed v1 inboxes sub no_over_html ($) { my ($ctx) = @_; - my $bref = $ctx->{-inbox}->msg_by_mid($ctx->{mid}) or return; # 404 + my $bref = $ctx->{ibx}->msg_by_mid($ctx->{mid}) or return; # 404 my $eml = PublicInbox::Eml->new($bref); $ctx->{mhref} = ''; PublicInbox::WwwStream::init($ctx); @@ -63,12 +64,18 @@ sub no_over_html ($) { sub msg_page { my ($ctx) = @_; - my $ibx = $ctx->{-inbox}; + my $ibx = $ctx->{ibx}; $ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef; my $over = $ctx->{over} = $ibx->over or return no_over_html($ctx); my ($id, $prev); my $next_arg = $ctx->{next_arg} = [ $ctx->{mid}, \$id, \$prev ]; - $ctx->{smsg} = $over->next_by_mid(@$next_arg) or return; # undef == 404 + + my $smsg = $ctx->{smsg} = $over->next_by_mid(@$next_arg) or + return; # undef == 404 + + # allow user to easily browse the range around this message if + # they have ->over + $ctx->{-t_max} = $smsg->{ts}; PublicInbox::WwwStream::aresponse($ctx, 200, \&msg_page_i); } @@ -81,7 +88,7 @@ sub msg_reply ($$) { 'https://en.wikipedia.org/wiki/Posting_style#Interleaved_style'; my $info = ''; - my $ibx = $ctx->{-inbox}; + my $ibx = $ctx->{ibx}; if (my $url = $ibx->{infourl}) { $url = prurl($ctx->{env}, $url); $info = qq(\n List information: $url\n); @@ -168,9 +175,6 @@ sub nr_to_s ($$$) { $nr == 1 ? "$nr $singular" : "$nr $plural"; } -# human-friendly format -sub fmt_ts ($) { strftime('%Y-%m-%d %k:%M', gmtime($_[0])) } - # Displays the text of of the message for /$INBOX/$MSGID/[Tt]/ endpoint # this is already inside a
 sub eml_entry {
@@ -382,7 +386,7 @@ sub next_in_queue ($$) {
 
 sub stream_thread_i { # PublicInbox::WwwStream::getline callback
 	my ($ctx, $eml) = @_;
-	goto &thread_eml_entry if $eml; # tail recursion
+	return thread_eml_entry($ctx, $eml) if $eml;
 	return unless exists($ctx->{skel});
 	my $ghost_ok = $ctx->{nr}++;
 	while (1) {
@@ -417,12 +421,23 @@ sub stream_thread ($$) {
 sub thread_html {
 	my ($ctx) = @_;
 	my $mid = $ctx->{mid};
-	my $ibx = $ctx->{-inbox};
+	my $ibx = $ctx->{ibx};
 	my ($nr, $msgs) = $ibx->over->get_thread($mid);
 	return missing_thread($ctx) if $nr == 0;
+
+	# link $INBOX_DIR/description text to "index_topics" view around
+	# the newest message in this thread
+	my $t = ts2str($ctx->{-t_max} = max(map { delete $_->{ts} } @$msgs));
+	my $t_fmt = fmt_ts($ctx->{-t_max});
+
 	my $skel = '
';
 	$skel .= $nr == 1 ? 'only message in thread' : 'end of thread';
-	$skel .= ", back to index\n\n";
+	$skel .= <~$t_fmt UTC | newest]
+
+EOF
 	$skel .= "Thread overview: ";
 	$skel .= $nr == 1 ? '(only message)' : "$nr+ messages";
 	$skel .= " (download: mbox.gz";
@@ -539,7 +554,7 @@ EOF
 sub add_text_body { # callback for each_part
 	my ($p, $ctx) = @_;
 	my $upfx = $ctx->{mhref};
-	my $ibx = $ctx->{-inbox};
+	my $ibx = $ctx->{ibx};
 	my $l = $ctx->{-linkify} //= PublicInbox::Linkify->new;
 	# $p - from each_part: [ Email::MIME-like, depth, $idx ]
 	my ($part, $depth, $idx) = @$p;
@@ -624,7 +639,7 @@ sub add_text_body { # callback for each_part
 
 sub _msg_page_prepare_obuf {
 	my ($eml, $ctx) = @_;
-	my $over = $ctx->{-inbox}->over;
+	my $over = $ctx->{ibx}->over;
 	my $obfs_ibx = $ctx->{-obfs_ibx};
 	my $rv = '';
 	my $mids = mids_for_index($eml);
@@ -714,7 +729,7 @@ sub SKEL_EXPAND () {
 sub thread_skel ($$$) {
 	my ($skel, $ctx, $hdr) = @_;
 	my $mid = mids($hdr)->[0];
-	my $ibx = $ctx->{-inbox};
+	my $ibx = $ctx->{ibx};
 	my ($nr, $msgs) = $ibx->over->get_thread($mid);
 	my $parent = in_reply_to($hdr);
 	$$skel .= "\nThread overview: ";
@@ -782,15 +797,22 @@ sub _parent_headers {
 	$rv;
 }
 
-# returns a string buffer via ->getline
+# returns a string buffer
 sub html_footer {
 	my ($ctx, $hdr) = @_;
-	my $ibx = $ctx->{-inbox};
+	my $ibx = $ctx->{ibx};
 	my $upfx = '../';
-	my $skel = " index";
+	my $skel;
 	my $rv = '
';
 	if ($ibx->over) {
-		$skel .= "\n";
+		my $t = ts2str($ctx->{-t_max});
+		my $t_fmt = fmt_ts($ctx->{-t_max});
+		$skel .= <~$t_fmt UTC|newest]
+EOF
+
 		thread_skel(\$skel, $ctx, $hdr);
 		my ($next, $prev);
 		my $parent = '       ';
@@ -821,6 +843,8 @@ sub html_footer {
 			$parent = " parent";
 		}
 		$rv .= "$next $prev$parent ";
+	} else { # unindexed inboxes w/o over
+		$skel = qq( latest);
 	}
 	$rv .= qq(reply);
 	$rv .= $skel;
@@ -858,7 +882,7 @@ sub find_mid_root {
 	++$ctx->{root_idx} if $level == 0;
 	if ($node->{mid} eq $ctx->{mid}) {
 		$ctx->{found_mid_at} = $ctx->{root_idx};
-		return 0;
+		return 0; # stop iterating
 	}
 	1;
 }
@@ -1048,7 +1072,7 @@ sub acc_topic { # walk_thread callback
 	my ($ctx, $level, $smsg) = @_;
 	my $mid = $smsg->{mid};
 	my $has_blob = $smsg->{blob} // do {
-		if (my $by_mid = $ctx->{-inbox}->smsg_by_mid($mid)) {
+		if (my $by_mid = $ctx->{ibx}->smsg_by_mid($mid)) {
 			%$smsg = (%$smsg, %$by_mid);
 			1;
 		}
@@ -1092,7 +1116,7 @@ sub dump_topics {
 	}
 
 	my @out;
-	my $ibx = $ctx->{-inbox};
+	my $ibx = $ctx->{ibx};
 	my $obfs_ibx = $ibx->{obfuscate} ? $ibx : undef;
 
 	# sort by recency, this allows new posts to "bump" old topics...
@@ -1142,22 +1166,18 @@ sub dump_topics {
 	200;
 }
 
-# only for the t= query parameter passed to overview DB
-sub ts2str ($) { strftime('%Y%m%d%H%M%S', gmtime($_[0])) };
-
 sub str2ts ($) {
 	my ($yyyy, $mon, $dd, $hh, $mm, $ss) = unpack('A4A2A2A2A2A2', $_[0]);
-	timegm($ss, $mm, $hh, $dd, $mon - 1, $yyyy);
+	timegm($ss || 0, $mm || 0, $hh || 0, $dd, $mon - 1, $yyyy);
 }
 
 sub pagination_footer ($$) {
 	my ($ctx, $latest) = @_;
-	delete $ctx->{qp} or return;
 	my $next = $ctx->{next_page} || '';
 	my $prev = $ctx->{prev_page} || '';
-	if ($prev) {
-		$next = $next ? "$next " : '     ';
-		$prev .= qq! latest!;
+	if ($prev) {  # aligned padding for: 'next (older) | '
+		$next = $next ? "$next | " : '             | ';
+		$prev .= qq[ | latest];
 	}
 	"
page: $next$prev
"; } @@ -1174,7 +1194,7 @@ sub paginate_recent ($$) { $t =~ s/\A([0-9]{8,14})-// and $after = str2ts($1); $t =~ /\A([0-9]{8,14})\z/ and $before = str2ts($1); - my $ibx = $ctx->{-inbox}; + my $ibx = $ctx->{ibx}; my $msgs = $ibx->recent($opts, $after, $before); my $nr = scalar @$msgs; if ($nr < $lim && defined($after)) { @@ -1195,15 +1215,18 @@ sub paginate_recent ($$) { } if (defined($oldest) && $more) { my $s = ts2str($oldest); - $ctx->{next_page} = qq!next!; + $ctx->{next_page} = qq[] . + 'next (older)'; } if (defined($newest) && (defined($before) || defined($after))) { my $s = ts2str($newest); - $ctx->{prev_page} = qq!prev!; + $ctx->{prev_page} = qq[] . + 'prev (newer)'; } $msgs; } +# GET /$INBOX - top-level inbox view for indexed inboxes sub index_topics { my ($ctx) = @_; my $msgs = paginate_recent($ctx, 200); # 200 is our window