Since we attempt to fill in threads by Subject, our thread
skeletons can cross actual thread IDs, leading to the
possibility of false ghosts showing up in the skeleton.
Try to fill in the ghosts as well as possible by performing
a message lookup.
my ($self, $mid) = @_;
retry_reopen($self, sub {
my $smsg = lookup_message($self, $mid) or return;
my ($self, $mid) = @_;
retry_reopen($self, sub {
my $smsg = lookup_message($self, $mid) or return;
- PublicInbox::SearchMsg->load_doc($smsg->{doc});
Search::Xapian::sortable_unserialise($doc->get_value($col));
}
Search::Xapian::sortable_unserialise($doc->get_value($col));
}
+sub load_expand {
+ my ($self) = @_;
+ my $doc = $self->{doc};
+ my $data = $doc->get_data or return;
+ $self->{ts} = get_val($doc, &PublicInbox::Search::TS);
+ utf8::decode($data);
+ my ($subj, $from, $refs, $to, $cc, $blob) = split(/\n/, $data);
+ $self->{subject} = $subj;
+ $self->{from} = $from;
+ $self->{references} = $refs;
+ $self->{to} = $to;
+ $self->{cc} = $cc;
+ $self->{blob} = $blob;
+ $self;
+}
+
sub load_doc {
my ($class, $doc) = @_;
my $data = $doc->get_data or return;
sub load_doc {
my ($class, $doc) = @_;
my $data = $doc->get_data or return;
use warnings;
sub thread {
use warnings;
sub thread {
- my ($messages, $ordersub) = @_;
+ my ($messages, $ordersub, $srch) = @_;
my $id_table = {};
_add_message($id_table, $_) foreach @$messages;
my $rootset = [ grep {
my $id_table = {};
_add_message($id_table, $_) foreach @$messages;
my $rootset = [ grep {
- !delete($_->{parent}) && $_->visible } values %$id_table ];
+ !delete($_->{parent}) && $_->visible($srch)
+ } values %$id_table ];
$id_table = undef;
$rootset = $ordersub->($rootset);
$id_table = undef;
$rootset = $ordersub->($rootset);
- $_->order_children($ordersub) for @$rootset;
+ $_->order_children($ordersub, $srch) for @$rootset;
# Do not show/keep ghosts iff they have no children. Sometimes
# a ghost Message-ID is the result of a long header line
# being folded/mangled by a MUA, and not a missing message.
# Do not show/keep ghosts iff they have no children. Sometimes
# a ghost Message-ID is the result of a long header line
# being folded/mangled by a MUA, and not a missing message.
-sub visible ($) {
- my ($self) = @_;
- $self->{smsg} || scalar values %{$self->{children}};
+sub visible ($$) {
+ my ($self, $srch) = @_;
+ ($self->{smsg} ||= eval { $srch->lookup_mail($self->{id}) }) ||
+ (scalar values %{$self->{children}});
- my ($cur, $ordersub) = @_;
+ my ($cur, $ordersub, $srch) = @_;
my %seen = ($cur => 1); # self-referential loop prevention
my @q = ($cur);
while (defined($cur = shift @q)) {
my $c = $cur->{children}; # The hashref here...
my %seen = ($cur => 1); # self-referential loop prevention
my @q = ($cur);
while (defined($cur = shift @q)) {
my $c = $cur->{children}; # The hashref here...
- $c = [ grep { !$seen{$_}++ && visible($_) } values %$c ];
+ $c = [ grep { !$seen{$_}++ && visible($_, $srch) } values %$c ];
$c = $ordersub->($c) if scalar @$c > 1;
$cur->{children} = $c; # ...becomes an arrayref
push @q, @$c;
$c = $ordersub->($c) if scalar @$c > 1;
$cur->{children} = $c; # ...becomes an arrayref
push @q, @$c;
sub mset_thread {
my ($ctx, $mset, $q) = @_;
my %pct;
sub mset_thread {
my ($ctx, $mset, $q) = @_;
my %pct;
- my $msgs = $ctx->{srch}->retry_reopen(sub { [ map {
+ my $srch = $ctx->{srch};
+ my $msgs = $srch->retry_reopen(sub { [ map {
my $i = $_;
my $smsg = PublicInbox::SearchMsg->load_doc($i->get_document);
$pct{$smsg->mid} = $i->get_percent;
my $i = $_;
my $smsg = PublicInbox::SearchMsg->load_doc($i->get_document);
$pct{$smsg->mid} = $i->get_percent;
} ($mset->items) ]});
my $r = $q->{r};
my $rootset = PublicInbox::SearchThread::thread($msgs,
} ($mset->items) ]});
my $r = $q->{r};
my $rootset = PublicInbox::SearchThread::thread($msgs,
- $r ? sort_relevance(\%pct) : *PublicInbox::View::sort_ts);
+ $r ? sort_relevance(\%pct) : *PublicInbox::View::sort_ts,
+ $srch);
my $skel = search_nav_bot($mset, $q). "<pre>";
my $inbox = $ctx->{-inbox};
$ctx->{-upfx} = '';
my $skel = search_nav_bot($mset, $q). "<pre>";
my $inbox = $ctx->{-inbox};
$ctx->{-upfx} = '';
$ctx->{mapping} = {};
$ctx->{s_nr} = "$nr+ messages in thread";
$ctx->{mapping} = {};
$ctx->{s_nr} = "$nr+ messages in thread";
- my $rootset = thread_results($msgs);
+ my $rootset = thread_results($msgs, $srch);
# reduce hash lookups in pre_thread->skel_dump
my $inbox = $ctx->{-inbox};
# reduce hash lookups in pre_thread->skel_dump
my $inbox = $ctx->{-inbox};
# reduce hash lookups in skel_dump
my $ibx = $ctx->{-inbox};
$ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef;
# reduce hash lookups in skel_dump
my $ibx = $ctx->{-inbox};
$ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef;
- walk_thread(thread_results($sres), $ctx, *skel_dump);
+ walk_thread(thread_results($sres, $srch), $ctx, *skel_dump);
$ctx->{parent_msg} = $parent;
}
$ctx->{parent_msg} = $parent;
}
+ my ($msgs, $srch) = @_;
require PublicInbox::SearchThread;
require PublicInbox::SearchThread;
- PublicInbox::SearchThread::thread($msgs, *sort_ts);
+ PublicInbox::SearchThread::thread($msgs, *sort_ts, $srch);
my $nr = scalar @{$sres->{msgs}};
if ($nr) {
$sres = load_results($srch, $sres);
my $nr = scalar @{$sres->{msgs}};
if ($nr) {
$sres = load_results($srch, $sres);
- walk_thread(thread_results($sres), $ctx, *acc_topic);
+ walk_thread(thread_results($sres, $srch), $ctx, *acc_topic);
}
$ctx->{-next_o} = $off+ $nr;
$ctx->{-cur_o} = $off;
}
$ctx->{-next_o} = $off+ $nr;
$ctx->{-cur_o} = $off;