- push @recent, $cur if $cur;
- @recent = map { $_->[1] } sort { $b->[0] <=> $a->[0] } @recent;
- $fh->write(join('', @recent) . '</pre>');
-}
-
-sub emit_index_topics {
- my ($state) = @_;
- my ($off) = (($state->{ctx}->{cgi}->param('o') || '0') =~ /(\d+)/);
- $state->{order} = [];
- $state->{subjs} = {};
- $state->{latest} = {};
- my $max = 25;
- my %opts = ( offset => $off, limit => $max * 4 );
- while (scalar @{$state->{order}} < $max) {
- my $sres = $state->{srch}->query('', \%opts);
- my $nr = scalar @{$sres->{msgs}} or last;
- $sres = load_results($sres);
- walk_thread(thread_results($sres), $state, *add_topic);
- $opts{offset} += $nr;
- }
-
- emit_topics($state);
- $opts{offset};
+ $ctx->{-html_tip} = '<pre>' . join("\n", @out) . '</pre>';
+ 200;
+}
+
+sub index_nav { # callback for WwwStream
+ my (undef, $ctx) = @_;
+ delete $ctx->{qp} or return;
+ my ($next, $prev);
+ $next = $prev = ' ';
+ my $latest = '';
+
+ my $next_o = $ctx->{-next_o};
+ if ($next_o) {
+ $next = qq!<a\nhref="?o=$next_o"\nrel=next>next</a>!;
+ }
+ if (my $cur_o = $ctx->{-cur_o}) {
+ $latest = qq! <a\nhref=.>latest</a>!;
+
+ my $o = $cur_o - ($next_o - $cur_o);
+ if ($o > 0) {
+ $prev = qq!<a\nhref="?o=$o"\nrel=prev>prev</a>!;
+ } elsif ($o == 0) {
+ $prev = qq!<a\nhref=.\nrel=prev>prev</a>!;
+ }
+ }
+ "<hr><pre>page: $next $prev$latest</pre>";
+}
+
+sub index_topics {
+ my ($ctx) = @_;
+ my ($off) = (($ctx->{qp}->{o} || '0') =~ /(\d+)/);
+ my $lim = 200;
+ my $opts = { offset => $off, limit => $lim };
+
+ $ctx->{order} = [];
+ my $srch = $ctx->{srch};
+
+ 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 $sres = $srch->query($qs, $opts);
+ $sres = $sres->{msgs};
+ my $nr = scalar @$sres;
+ if ($nr) {
+ walk_thread(thread_results($ctx, $sres), $ctx, *acc_topic);
+ }
+ $ctx->{-next_o} = $off + $nr;
+ $ctx->{-cur_o} = $off;
+ PublicInbox::WwwStream->response($ctx, dump_topics($ctx), *index_nav);
+}
+
+sub thread_adj_level {
+ my ($ctx, $level) = @_;
+
+ my $max = $ctx->{cur_level};
+ if ($level <= 0) {
+ return ('', '') if $max == 0; # flat output
+
+ # reset existing lists
+ my $beg = $max > 1 ? ('</ul></li>' x ($max - 1)) : '';
+ $ctx->{cur_level} = 0;
+ ("$beg</ul>", '');
+ } elsif ($level == $max) { # continue existing list
+ qw(<li> </li>);
+ } elsif ($level < $max) {
+ my $beg = $max > 1 ? ('</ul></li>' x ($max - $level)) : '';
+ $ctx->{cur_level} = $level;
+ ("$beg<li>", '</li>');
+ } else { # ($level > $max) # start a new level
+ $ctx->{cur_level} = $level;
+ my $beg = ($max ? '<li>' : '') . '<ul><li>';
+ ($beg, '</li>');
+ }
+}
+
+sub ghost_index_entry {
+ my ($ctx, $level, $node) = @_;
+ my ($beg, $end) = thread_adj_level($ctx, $level);
+ $beg . '<pre>'. ghost_parent($ctx->{-upfx}, $node->{id})
+ . '</pre>' . $end;