X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FView.pm;h=cbed91639c08458987da1c3ee7bcaebcf4b8847c;hb=b9534449ecce2c59bb4aebad6051f91c3116b187;hp=c151f221cc9ea1667fafd20253157c1bc9d7c7a5;hpb=f886760b1b5c79181143743814a576a8fa5cf4d9;p=public-inbox.git diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index c151f221..cbed9163 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -15,6 +15,7 @@ use PublicInbox::Address; use PublicInbox::WwwStream; use PublicInbox::Reply; require POSIX; +use Time::Local qw(timegm); use constant INDENT => ' '; use constant TCHILD => '` '; @@ -408,9 +409,7 @@ sub thread_html { my ($ctx) = @_; my $mid = $ctx->{mid}; my $srch = $ctx->{srch}; - my $sres = $srch->get_thread($mid); - my $msgs = $sres->{msgs}; - my $nr = $sres->{total}; + my ($nr, $msgs) = $srch->get_thread($mid); return missing_thread($ctx) if $nr == 0; my $skel = '
';
 	$skel .= $nr == 1 ? 'only message in thread' : 'end of thread';
@@ -649,8 +648,7 @@ sub thread_skel {
 	my ($dst, $ctx, $hdr, $tpfx) = @_;
 	my $srch = $ctx->{srch};
 	my $mid = mids($hdr)->[0];
-	my $sres = $srch->get_thread($mid);
-	my $nr = $sres->{total};
+	my ($nr, $msgs) = $srch->get_thread($mid);
 	my $expand = qq(expand[flat) .
 	                qq(|nested]  ) .
 			qq(mbox.gz  ) .
@@ -680,12 +678,11 @@ sub thread_skel {
 	$ctx->{prev_attr} = '';
 	$ctx->{prev_level} = 0;
 	$ctx->{dst} = $dst;
-	$sres = $sres->{msgs};
 
 	# reduce hash lookups in skel_dump
 	my $ibx = $ctx->{-inbox};
 	$ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef;
-	walk_thread(thread_results($ctx, $sres), $ctx, *skel_dump);
+	walk_thread(thread_results($ctx, $msgs), $ctx, *skel_dump);
 
 	$ctx->{parent_msg} = $parent;
 }
@@ -1036,59 +1033,82 @@ sub dump_topics {
 	200;
 }
 
-sub index_nav { # callback for WwwStream
-	my (undef, $ctx) = @_;
-	delete $ctx->{qp} or return;
-	my ($next, $prev);
-	$next = $prev = '    ';
-	my $latest = '';
+sub ts2str ($) {
+	my ($ts) = @_;
+	POSIX::strftime('%Y%m%d%H%M%S', gmtime($ts));
+}
 
-	my $next_o = $ctx->{-next_o};
-	if ($next_o) {
-		$next = qq!next!;
-	}
-	if (my $cur_o = $ctx->{-cur_o}) {
-		$latest = qq! latest!;
-
-		my $o = $cur_o - ($next_o - $cur_o);
-		if ($o > 0) {
-			$prev = qq!prev!;
-		} elsif ($o == 0) {
-			$prev = qq!prev!;
-		}
+sub str2ts ($) {
+	my ($yyyy, $mon, $dd, $hh, $mm, $ss) = unpack('A4A2A2A2A2A2', $_[0]);
+	timegm($ss, $mm, $hh, $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!;
 	}
-	"
page: $next $prev$latest
"; + "
page: $next$prev
"; } -sub index_topics { +sub index_nav { # callback for WwwStream + my (undef, $ctx) = @_; + pagination_footer($ctx, '.') +} + +sub paginate_recent ($) { my ($ctx) = @_; - my ($off) = (($ctx->{qp}->{o} || '0') =~ /(\d+)/); - my $lim = 200; - my $opts = { offset => $off, limit => $lim }; + my $t = $ctx->{qp}->{t} || ''; + my $lim = 200; # this is our window + my $opts = { limit => $lim }; + my ($after, $before); - $ctx->{order} = []; - my $srch = $ctx->{srch}; + # Xapian uses '..' but '-' is perhaps friendier to URL linkifiers + # if only $after exists "YYYYMMDD.." because "." could be skipped + # if interpreted as an end-of-sentence + $t =~ s/\A(\d{8,14})-// and $after = str2ts($1); + $t =~ /\A(\d{8,14})\z/ and $before = str2ts($1); - my $qs = ''; - # this complicated bit cuts loading time by over 400ms on my system: - if ($off == 0) { - my ($min, $max) = $ctx->{-inbox}->mm->minmax; - my $n = $max - $lim; - $n = $min if $n < $min; - for (; $qs eq '' && $n >= $min; --$n) { - my $smsg = $srch->lookup_article($n) or next; - $qs = POSIX::strftime('d:%Y%m%d..', gmtime($smsg->ts)); + my $ibx = $ctx->{-inbox}; + my $msgs = $ibx->recent($opts, $after, $before); + my $nr = scalar @$msgs; + if ($nr < $lim && defined($after)) { + $after = $before = undef; + $msgs = $ibx->recent($opts); + $nr = scalar @$msgs; + } + my $more = $nr == $lim; + my ($newest, $oldest); + if ($nr) { + $newest = $msgs->[0]->{ts}; + $oldest = $msgs->[-1]->{ts}; + # if we only had $after, our SQL query in ->recent ordered + if ($newest < $oldest) { + ($oldest, $newest) = ($newest, $oldest); + $more = 0 if defined($after) && $after < $oldest; } } + if (defined($oldest) && $more) { + my $s = ts2str($oldest); + $ctx->{next_page} = qq!next!; + } + if (defined($newest) && (defined($before) || defined($after))) { + my $s = ts2str($newest); + $ctx->{prev_page} = qq!prev!; + } + $msgs; +} - my $sres = $srch->query($qs, $opts); - $sres = $sres->{msgs}; - my $nr = scalar @$sres; - if ($nr) { - walk_thread(thread_results($ctx, $sres), $ctx, *acc_topic); +sub index_topics { + my ($ctx) = @_; + my $msgs = paginate_recent($ctx); + if (@$msgs) { + walk_thread(thread_results($ctx, $msgs), $ctx, *acc_topic); } - $ctx->{-next_o} = $off + $nr; - $ctx->{-cur_o} = $off; PublicInbox::WwwStream->response($ctx, dump_topics($ctx), *index_nav); }