blob: f5541efbe4d1cc09d7f75e27c38695f5dfde5bb3 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
function calc_email_width() {
// Get email width; used for calculating reply nesting offsets
let body = document.body;
let html = document.documentElement;
return Math.max(body.scrollWidth, body.offsetWidth,
html.clientWidth, html.scrollWidth, html.offsetWidth);
}
function listview_threaded(json, start) {
let list = document.getElementById('emails');
list.innerHTML = "";
let s = start || 0;
if (json.thread_struct && json.thread_struct.length) {
for (let n = s; n < (s + G_current_per_page); n++) {
let z = json.thread_struct.length - n - 1; // reverse order by default
if (json.thread_struct[z]) {
let item = listview_threaded_element(json.thread_struct[z], z);
list.inject(item);
// Hidden placeholder for expanding email(s)
let placeholder = new HTML('div', {
class: G_chatty_layout ? 'email_placeholder_chatty' : 'email_placeholder',
id: 'email_%u'.format(z)
});
list.inject(placeholder);
}
}
} else {
list.inject(txt("No emails found..."));
}
}
function find_email(id) {
if (!G_current_json.emails) return null;
for (let email of G_current_json.emails) {
if (email.id == id) return email;
}
return null;
}
function count_replies(thread) {
let reps = 0;
if (isArray(thread.children)) {
for (let child of thread.children) {
if (child.tid == thread.tid) reps--;
reps++;
reps += count_replies(child);
}
}
return reps;
}
function count_people(thread, hash) {
let ppl = hash || {};
let eml = find_email(thread.tid);
if (eml) ppl[eml.from] = true;
if (isArray(thread.children)) {
for (let child of thread.children) {
count_people(child, ppl);
}
}
let n = 0;
for (let _ in ppl) n++;
return n;
}
function last_email(thread) {
let newest = thread.epoch;
if (isArray(thread.children)) {
for (let child of thread.children) {
newest = Math.max(newest, last_email(child));
}
}
return newest;
}
function listview_threaded_element(thread, idx) {
let eml = find_email(thread.tid);
if (!eml) {
return;
}
let link_wrapper = new HTML('a', {
href: 'thread/%s'.format(eml.id),
onclick: 'return(expand_email_threaded(%u));'.format(idx)
});
let element = new HTML('div', {
class: G_current_listmode_compact ? "listview_email_compact" : "listview_email_flat"
}, " ");
let date = new Date(eml.epoch * 1000.0);
let now = new Date();
// Add gravatar
let gravatar = new HTML('img', {
class: "gravatar",
src: GRAVATAR_URL.format(eml.gravatar)
});
element.inject(gravatar);
// Add author
let authorName = eml.from.replace(/\s*<.+>/, "").replace(/"/g, '');
let authorEmail = eml.from.match(/\s*<(.+@.+)>\s*/);
if (authorName.length == 0) authorName = authorEmail ? authorEmail[1] : "(No author?)";
let author = new HTML('span', {
class: "listview_email_author"
}, authorName);
element.inject(author);
// reasons to show the list name
let showList = G_current_domain == 'inbox' || G_current_list == '*' || G_current_domain == '*';
// If space and needed, inject ML name
if (!G_current_listmode_compact && showList) {
author.style.lineHeight = '16px';
author.inject(new HTML('br'));
author.inject(new HTML('span', {
class: "label label-primary",
style: "font-style: italic; font-size: 1rem;"
}, eml.list_raw.replace(/[<>]/g, '').replace('.', '@', 1)));
}
// Combined space for subject + body teaser
let as = new HTML('div', {
class: 'listview_email_as'
});
let suba = new HTML('a', {}, eml.subject === '' ? '(No subject)' : eml.subject);
if (G_current_listmode_compact && showList) {
let kbd = new HTML('kbd', {
class: 'listview_kbd'
}, eml.list_raw.replace(/[<>]/g, '').replace('.', '@', 1))
suba = [kbd, suba];
}
let subject = new HTML('div', {
class: 'listview_email_subject email_unread'
}, suba);
as.inject(subject);
if (!G_current_listmode_compact) { // No body teaser in compact mode
let body = new HTML('div', {
class: 'listview_email_body'
}, eml.body);
as.inject(body);
}
element.inject(as);
// Labels
let labels = new HTML('div', {
class: 'listview_email_labels'
});
// Participants
let ppl = count_people(thread);
let ptitle = (ppl == 1) ? "one participant" : "%u participants".format(ppl);
let people = new HTML('span', {
class: 'label label-default',
title: ptitle
}, [
new HTML('span', {
class: 'glyphicon glyphicon-user'
}, ' '),
" %u".format(ppl)
]);
labels.inject(people);
// Replies
let reps = count_replies(thread);
let rtitle = (reps == 1) ? "one reply" : "%u replies".format(reps);
let repl = new HTML('span', {
class: 'label label-default',
title: rtitle
}, [
new HTML('span', {
class: 'glyphicon glyphicon-envelope'
}, ' '),
" %u".format(reps)
]);
labels.inject(repl);
// Date
date = new Date(last_email(thread) * 1000.0);
let dl = new HTML('span', {
class: 'label label-default'
}, date.ISOBare());
if (now - date < 86400000) {
dl.setAttribute("class", "label label-primary");
}
labels.inject(dl);
element.inject(labels);
link_wrapper.inject(element);
return link_wrapper;
}