forked from I2P_Developers/i2p.i2p
Merge branch 'susimail-search-v2' into 'master'
Susimail: Add search See merge request i2p-hackers/i2p.i2p!189
This commit is contained in:
@ -40,7 +40,7 @@ function addClickHandler1(elem)
|
||||
function addClickHandler2(elem)
|
||||
{
|
||||
elem.addEventListener("click", function() {
|
||||
var form = document.forms[0];
|
||||
var form = document.forms[3];
|
||||
form.delete.disabled = false;
|
||||
form.markall.disabled = true;
|
||||
form.clearselection.disabled = false;
|
||||
@ -57,7 +57,7 @@ function addClickHandler2(elem)
|
||||
function addClickHandler3(elem)
|
||||
{
|
||||
elem.addEventListener("click", function() {
|
||||
var form = document.forms[0];
|
||||
var form = document.forms[3];
|
||||
form.delete.disabled = true;
|
||||
form.markall.disabled = false;
|
||||
form.clearselection.disabled = true;
|
||||
@ -82,7 +82,7 @@ function deleteboxclicked() {
|
||||
var hasOne = false;
|
||||
var hasAll = true;
|
||||
var hasNone = true;
|
||||
var form = document.forms[0];
|
||||
var form = document.forms[3];
|
||||
for(i = 0; i < form.elements.length; i++) {
|
||||
var elem = form.elements[i];
|
||||
if (elem.type == 'checkbox') {
|
||||
|
@ -61,12 +61,28 @@ public class Folder<O extends Object> {
|
||||
UP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.63
|
||||
*/
|
||||
public interface Selector<O> {
|
||||
/**
|
||||
* @return non-null
|
||||
*/
|
||||
public String getSelectionKey();
|
||||
/**
|
||||
* @return true if selected
|
||||
*/
|
||||
public boolean select(O element);
|
||||
}
|
||||
|
||||
private int pages, pageSize, currentPage;
|
||||
private O[] elements;
|
||||
private final Map<String, Comparator<O>> sorter;
|
||||
private SortOrder sortingDirection;
|
||||
private Comparator<O> currentSorter;
|
||||
private String currentSortID;
|
||||
private Selector<O> currentSelector;
|
||||
private List<O> selected;
|
||||
|
||||
public Folder()
|
||||
{
|
||||
@ -109,10 +125,18 @@ public class Folder<O extends Object> {
|
||||
/**
|
||||
* Returns the number of pages in the folder.
|
||||
* Minimum of 1 even if empty.
|
||||
* If the selector is non-null, this will be the number of pages in the selected results.
|
||||
*
|
||||
* @return Returns the number of pages.
|
||||
*/
|
||||
public synchronized int getPages() {
|
||||
return pages;
|
||||
if (currentSelector == null || elements == null)
|
||||
return pages;
|
||||
int ps = getPageSize();
|
||||
int rv = selected.size() / ps;
|
||||
if (rv * ps < elements.length)
|
||||
rv++;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,6 +201,7 @@ public class Folder<O extends Object> {
|
||||
if (elements.length > 0) {
|
||||
this.elements = elements;
|
||||
sort();
|
||||
select();
|
||||
} else {
|
||||
this.elements = null;
|
||||
}
|
||||
@ -285,6 +310,27 @@ public class Folder<O extends Object> {
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator containing the elements on the current page.
|
||||
* This iterator is over a copy of the current page, and so
|
||||
* is thread safe w.r.t. other operations on this folder,
|
||||
* but will not reflect subsequent changes, and iter.remove()
|
||||
* will not change the folder.
|
||||
*
|
||||
* @return Iterator containing the elements on the current page.
|
||||
* @since 0.9.63
|
||||
*/
|
||||
public synchronized Iterator<O> currentPageSelectorIterator()
|
||||
{
|
||||
if (currentSelector == null)
|
||||
return currentPageIterator();
|
||||
int pageSize = getPageSize();
|
||||
int offset = ( currentPage - 1 ) * pageSize;
|
||||
if (selected == null || offset > selected.size())
|
||||
return Collections.<O>emptyList().iterator();
|
||||
return selected.subList(offset, Math.min(selected.size(), offset + pageSize)).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns folder to next page.
|
||||
*/
|
||||
@ -370,27 +416,54 @@ public class Folder<O extends Object> {
|
||||
public synchronized SortOrder getCurrentSortingDirection() {
|
||||
return sortingDirection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the element on the current page on the given position.
|
||||
* Warning, this does not do the actual selection, this is done in the iterator.
|
||||
* Resets page to 1 if selector changed.
|
||||
*
|
||||
* @param x Position of the element on the current page.
|
||||
* @return Element on the current page on the given position.
|
||||
* @param selector may be null
|
||||
* @since 0.9.63
|
||||
*/
|
||||
/**** unused, we now fetch by UIDL, not position
|
||||
public synchronized O getElementAtPosXonCurrentPage( int x )
|
||||
{
|
||||
O result = null;
|
||||
if( elements != null ) {
|
||||
int pageSize = getPageSize();
|
||||
int offset = ( currentPage - 1 ) * pageSize;
|
||||
offset += x;
|
||||
if( offset >= 0 && offset < elements.length )
|
||||
result = elements[offset];
|
||||
public synchronized void setSelector(Selector<O> selector) {
|
||||
if ((currentSelector != null && selector == null) ||
|
||||
(currentSelector == null && selector != null) ||
|
||||
(currentSelector != null && selector != null &&
|
||||
!currentSelector.getSelectionKey().equals(selector.getSelectionKey()))) {
|
||||
currentPage = 1;
|
||||
}
|
||||
currentSelector = selector;
|
||||
if (selector != null)
|
||||
select();
|
||||
else
|
||||
selected = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return current selector or null
|
||||
* @since 0.9.63
|
||||
*/
|
||||
public synchronized Selector<O> getCurrentSelector() {
|
||||
return currentSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select and cache results
|
||||
* @since 0.9.63
|
||||
*/
|
||||
private synchronized void select() {
|
||||
if (selected == null)
|
||||
selected = new ArrayList<O>();
|
||||
else
|
||||
selected.clear();
|
||||
if (elements == null || currentSelector == null)
|
||||
return;
|
||||
int sz = getSize();
|
||||
for (int i = 0; i < sz; i++) {
|
||||
if (currentSelector.select(elements[i])) {
|
||||
selected.add(elements[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* Returns the first element of the sorted folder.
|
||||
@ -467,6 +540,47 @@ public class Folder<O extends Object> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the next element in the sorted array.
|
||||
*
|
||||
* @param element
|
||||
* @return The next element
|
||||
*/
|
||||
public synchronized O getNextSelectedElement(O element)
|
||||
{
|
||||
if (currentSelector == null)
|
||||
return getNextElement(element);
|
||||
O result = null;
|
||||
int i = selected.indexOf(element);
|
||||
if (i != -1 && selected != null) {
|
||||
i++;
|
||||
if (i < selected.size())
|
||||
result = selected.get(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the previous element in the sorted array.
|
||||
*
|
||||
* @param element
|
||||
* @return The previous element
|
||||
*/
|
||||
public synchronized O getPreviousSelectedElement(O element)
|
||||
{
|
||||
if (currentSelector == null)
|
||||
return getPreviousElement(element);
|
||||
O result = null;
|
||||
int i = selected.indexOf(element);
|
||||
if (i != -1 && selected != null) {
|
||||
i--;
|
||||
if (i >= 0 && i < selected.size())
|
||||
result = selected.get(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves element at index i.
|
||||
*
|
||||
|
@ -147,6 +147,7 @@ public class WebMail extends HttpServlet
|
||||
private static final String NEXT_PAGE_NUM = "nextpagenum";
|
||||
private static final String CURRENT_SORT = "currentsort";
|
||||
private static final String CURRENT_FOLDER = "folder";
|
||||
private static final String CURRENT_SEARCH = "currentsearch";
|
||||
private static final String NEW_FOLDER = "newfolder";
|
||||
private static final String DRAFT_EXISTS = "draftexists";
|
||||
private static final String DEBUG_STATE = "currentstate";
|
||||
@ -169,6 +170,7 @@ public class WebMail extends HttpServlet
|
||||
private static final String REALLYDELETE = "really_delete";
|
||||
private static final String MOVE_TO = "moveto";
|
||||
private static final String SWITCH_TO = "switchto";
|
||||
private static final String SEARCH = "s";
|
||||
// also a GET param
|
||||
private static final String SHOW = "show";
|
||||
private static final String DOWNLOAD = "download";
|
||||
@ -1193,7 +1195,8 @@ public class WebMail extends HttpServlet
|
||||
buttonPressed( request, CLEAR ) ||
|
||||
buttonPressed( request, INVERT ) ||
|
||||
buttonPressed( request, SORT ) ||
|
||||
buttonPressed( request, REFRESH )) {
|
||||
buttonPressed( request, REFRESH ) ||
|
||||
buttonPressed( request, SEARCH )) {
|
||||
state = State.LIST;
|
||||
} else if (buttonPressed(request, PREV) ||
|
||||
buttonPressed(request, NEXT) ||
|
||||
@ -1221,6 +1224,9 @@ public class WebMail extends HttpServlet
|
||||
} else if (buttonPressed(request, DRAFT_ATTACHMENT)) {
|
||||
// GET params
|
||||
state = State.NEW;
|
||||
} else if (buttonPressed(request, SEARCH)) {
|
||||
// GET params for XHR
|
||||
return State.LIST;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2614,15 +2620,31 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
out.println("<script src=\"/susimail/js/notifications.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>");
|
||||
out.print("</head>\n<body>");
|
||||
String nonce = state == State.AUTH ? LOGIN_NONCE :
|
||||
Long.toString(ctx.random().nextLong());
|
||||
sessionObject.addNonce(nonce);
|
||||
out.println(
|
||||
"<div class=\"page\" id=\"page\">" +
|
||||
"<form method=\"POST\" enctype=\"multipart/form-data\" action=\"" + myself + "\" accept-charset=\"UTF-8\">\n" +
|
||||
"<input type=\"hidden\" name=\"" + SUSI_NONCE + "\" value=\"" + nonce + "\">\n" +
|
||||
// we use this to know if the user thought he was logged in at the time
|
||||
"<input type=\"hidden\" name=\"" + DEBUG_STATE + "\" value=\"" + state + "\">");
|
||||
out.println("<div class=\"page\" id=\"page\">");
|
||||
|
||||
if (state != State.LIST) {
|
||||
// For all states except LIST, we have one big form for the whole page.
|
||||
// LIST has several forms, we will output them in showFolder().
|
||||
String nonce = state == State.AUTH ? LOGIN_NONCE :
|
||||
Long.toString(ctx.random().nextLong());
|
||||
sessionObject.addNonce(nonce);
|
||||
out.println("<form method=\"POST\" enctype=\"multipart/form-data\" action=\"" + myself + "\" accept-charset=\"UTF-8\">\n" +
|
||||
"<input type=\"hidden\" name=\"" + SUSI_NONCE + "\" value=\"" + nonce + "\">\n" +
|
||||
// we use this to know if the user thought he was logged in at the time
|
||||
"<input type=\"hidden\" name=\"" + DEBUG_STATE + "\" value=\"" + state + "\">");
|
||||
if (state != State.AUTH && state != State.CONFIG && state != State.LOADING) {
|
||||
// maintain the search param when changing pages or folders or
|
||||
// going to message view and back
|
||||
String search = request.getParameter(CURRENT_SEARCH);
|
||||
if (search == null || search.length() == 0) {
|
||||
Folder.Selector selector = mc.getFolder().getCurrentSelector();
|
||||
if (selector != null)
|
||||
search = selector.getSelectionKey();
|
||||
}
|
||||
if (search != null && search.length() > 0)
|
||||
out.println("<input type=\"hidden\" name=\"" + CURRENT_SEARCH + "\" value=\"" + DataHelper.escapeHTML(search) + "\">\n");
|
||||
}
|
||||
}
|
||||
if (state == State.NEW) {
|
||||
String newUIDL = request.getParameter(NEW_UIDL);
|
||||
if (newUIDL == null || newUIDL.length() <= 0)
|
||||
@ -2646,8 +2668,6 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
out.println("<input type=\"hidden\" name=\"" + CUR_PAGE + "\" value=\"" + page + "\">");
|
||||
}
|
||||
}
|
||||
if (state == State.SHOW || state == State.NEW || state == State.LIST) {
|
||||
// Save sort order in case it changes later
|
||||
String curSort = folder.getCurrentSortBy();
|
||||
SortOrder curOrder = folder.getCurrentSortingDirection();
|
||||
@ -2698,6 +2718,7 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
out.println("</div>" );
|
||||
}
|
||||
|
||||
/*
|
||||
* now write body
|
||||
*/
|
||||
@ -2735,7 +2756,8 @@ public class WebMail extends HttpServlet
|
||||
else if( state == State.CONFIG )
|
||||
showConfig(out, folder);
|
||||
|
||||
out.println("</form>\n");
|
||||
if (state != State.LIST)
|
||||
out.println("</form>\n");
|
||||
|
||||
out.println("<div class=\"footer\"><p class=\"footer\">\n" +
|
||||
"<img class=\"footer\" src=\"" + myself + "themes/images/susimail.png\" alt=\"susimail\">\n" +
|
||||
@ -3484,18 +3506,9 @@ public class WebMail extends HttpServlet
|
||||
*/
|
||||
private static void showFolder( PrintWriter out, SessionObject sessionObject, MailCache mc, RequestWrapper request )
|
||||
{
|
||||
out.println("<div class=\"topbuttons\">");
|
||||
out.println( button( NEW, _t("New") ) + spacer);
|
||||
// In theory, these are valid and will apply to the first checked message,
|
||||
// but that's not obvious and did it work?
|
||||
//button( REPLY, _t("Reply") ) +
|
||||
//button( REPLYALL, _t("Reply All") ) +
|
||||
//button( FORWARD, _t("Forward") ) + spacer +
|
||||
//button( DELETE, _t("Delete") ) + spacer +
|
||||
String folderName = mc.getFolderName();
|
||||
String floc;
|
||||
if (folderName.equals(DIR_FOLDER)) {
|
||||
out.println((sessionObject.isFetching ? button2(REFRESH, _t("Check Mail")) : button(REFRESH, _t("Check Mail"))) + spacer);
|
||||
floc = "";
|
||||
} else if (folderName.equals(DIR_DRAFTS)) {
|
||||
floc = "";
|
||||
@ -3504,11 +3517,75 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
boolean isSpamFolder = folderName.equals(DIR_SPAM);
|
||||
boolean showToColumn = folderName.equals(DIR_DRAFTS) || folderName.equals(DIR_SENT);
|
||||
//if (Config.hasConfigFile())
|
||||
// out.println(button( RELOAD, _t("Reload Config") ) + spacer);
|
||||
out.println(button( LOGOUT, _t("Logout") ));
|
||||
int page = 1;
|
||||
// For all states except LIST, we have one big form for the whole page.
|
||||
// Here, for LIST, we set up 4-5 forms
|
||||
// to deal with html rules and have a search box that works right.
|
||||
// 1: new/checkmail/logout, inside topbuttons div
|
||||
// 2: search, inside topbuttons div
|
||||
// 3: change folder and page buttons, inside topbuttons div, surrounds pagenav table
|
||||
// 4: mail delete boxes and bottombuttons div, surrounds mailbox table
|
||||
// 5: change folder and page buttons, inside 2nd topbuttons div, surrounds pagenav table,
|
||||
// only shown if more than 30 mails on a page
|
||||
//
|
||||
// Create the common form header
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
String nonce = Long.toString(ctx.random().nextLong());
|
||||
sessionObject.addNonce(nonce);
|
||||
// for all but search
|
||||
String form = "<form method=\"POST\" enctype=\"multipart/form-data\" action=\"" + myself + "\" accept-charset=\"UTF-8\">\n";
|
||||
StringBuilder fbf = new StringBuilder(256);
|
||||
fbf.append("<input type=\"hidden\" name=\"").append(SUSI_NONCE).append("\" value=\"").append(nonce).append("\">\n")
|
||||
.append("<input type=\"hidden\" name=\"").append(DEBUG_STATE).append("\" value=\"").append(State.LIST).append("\">\n");
|
||||
Folder<String> folder = mc.getFolder();
|
||||
String curSort = folder.getCurrentSortBy();
|
||||
SortOrder curOrder = folder.getCurrentSortingDirection();
|
||||
// UP is reverse sort. DOWN is normal sort.
|
||||
String fullSort = curOrder == SortOrder.UP ? '-' + curSort : curSort;
|
||||
fbf.append("<input type=\"hidden\" name=\"").append(CURRENT_SORT).append("\" value=\"").append(fullSort).append("\">\n")
|
||||
.append("<input type=\"hidden\" name=\"").append(CURRENT_FOLDER).append("\" value=\"").append(folderName).append("\">\n");
|
||||
String cursearch = request.getParameter(CURRENT_SEARCH);
|
||||
String search = request.getParameter(SEARCH);
|
||||
if (cursearch != null && cursearch.length() > 0) {
|
||||
if (search == null) {
|
||||
// we came from somewhere else, set search to cursearch, will set selector below
|
||||
search = cursearch;
|
||||
} else {
|
||||
// we came from here, search wins, will set selector below
|
||||
}
|
||||
}
|
||||
if (search != null && search.length() > 0) {
|
||||
fbf.append("<input type=\"hidden\" name=\"").append(CURRENT_SEARCH).append("\" value=\"").append(DataHelper.escapeHTML(search)).append("\">\n");
|
||||
Folder.Selector olds = folder.getCurrentSelector();
|
||||
if (olds == null || !olds.getSelectionKey().equals(search)) {
|
||||
folder.setSelector(new SearchSelector(mc, search));
|
||||
}
|
||||
} else if ((search == null || search.length() == 0) && folder.getCurrentSelector() != null) {
|
||||
folder.setSelector(null);
|
||||
}
|
||||
String hidden = fbf.toString();
|
||||
|
||||
out.println("<div class=\"topbuttons\">");
|
||||
// form 1
|
||||
out.print(form);
|
||||
out.print(hidden);
|
||||
out.println( button( NEW, _t("New") ) + spacer);
|
||||
if (folderName.equals(DIR_FOLDER))
|
||||
out.println((sessionObject.isFetching ? button2(REFRESH, _t("Check Mail")) : button(REFRESH, _t("Check Mail"))) + spacer);
|
||||
out.println(button( LOGOUT, _t("Logout") ));
|
||||
out.println("</form>");
|
||||
|
||||
if (folder.getSize() > 1 || (search != null && search.length() > 0)) {
|
||||
// form 2
|
||||
out.println("<form class=\"search\" id = \"search\" action=\"" + myself + "\" method=\"POST\">");
|
||||
out.print(hidden);
|
||||
out.write("<input type=\"text\" name=\"" + SEARCH + "\" size=\"20\" class=\"search\" id=\"searchbox\"");
|
||||
if (search != null)
|
||||
out.write(" value=\"" + DataHelper.escapeHTML(search) + '"');
|
||||
out.println("><a class=\"cancel\" id=\"searchcancel\" href=\"" + myself + "\"></a>");
|
||||
out.println("</form>");
|
||||
}
|
||||
|
||||
int page = 1;
|
||||
if (folder.getPages() > 1) {
|
||||
String sp = request.getParameter(CUR_PAGE);
|
||||
if (sp != null) {
|
||||
@ -3518,13 +3595,18 @@ public class WebMail extends HttpServlet
|
||||
}
|
||||
folder.setCurrentPage(page);
|
||||
}
|
||||
// form 3
|
||||
out.print(form);
|
||||
out.print(hidden);
|
||||
showPageButtons(out, sessionObject.user, folderName, page, folder.getPages(), true);
|
||||
out.println("</form>");
|
||||
out.println("</div>");
|
||||
|
||||
String curSort = folder.getCurrentSortBy();
|
||||
SortOrder curOrder = folder.getCurrentSortingDirection();
|
||||
out.println("<table id=\"mailbox\" cellspacing=\"0\" cellpadding=\"5\">\n" +
|
||||
"<tr><td colspan=\"9\"><hr></td></tr>\n<tr><th title=\"" + _t("Mark for deletion") + "\"> </th>" +
|
||||
// form 4
|
||||
out.print(form);
|
||||
out.print(hidden);
|
||||
out.println("<table id=\"mailbox\" cellspacing=\"0\" cellpadding=\"5\">\n");
|
||||
out.println("<tr><td colspan=\"9\"><hr></td></tr>\n<tr><th title=\"" + _t("Mark for deletion") + "\"> </th>" +
|
||||
thSpacer + "<th>" + sortHeader(SORT_SENDER, showToColumn ? _t("To") : _t("From"), sessionObject.imgPath, curSort, curOrder, page, folderName) + "</th>" +
|
||||
thSpacer + "<th>" + sortHeader(SORT_SUBJECT, _t("Subject"), sessionObject.imgPath, curSort, curOrder, page, folderName) + "</th>" +
|
||||
thSpacer + "<th>" + sortHeader(SORT_DATE, _t("Date"), sessionObject.imgPath, curSort, curOrder, page, folderName) +
|
||||
@ -3532,7 +3614,7 @@ public class WebMail extends HttpServlet
|
||||
thSpacer + "<th>" + sortHeader(SORT_SIZE, _t("Size"), sessionObject.imgPath, curSort, curOrder, page, folderName) + "</th></tr>" );
|
||||
int bg = 0;
|
||||
int i = 0;
|
||||
for (Iterator<String> it = folder.currentPageIterator(); it != null && it.hasNext(); ) {
|
||||
for (Iterator<String> it = folder.currentPageSelectorIterator(); it != null && it.hasNext(); ) {
|
||||
String uidl = it.next();
|
||||
Mail mail = mc.getMail(uidl, MailCache.FetchMode.HEADER_CACHE_ONLY);
|
||||
if (mail == null || !mail.hasHeader()) {
|
||||
@ -3644,14 +3726,82 @@ public class WebMail extends HttpServlet
|
||||
out.print(button(CONFIGURE, _t("Settings")));
|
||||
out.println("</td></tr>");
|
||||
out.println( "</table>");
|
||||
if (folder.getPages() > 1 && i > 30) {
|
||||
out.println("</form>");
|
||||
int ps = folder.getPageSize();
|
||||
if (ps > 30 && (folder.getCurrentPage() - 1) * ps < folder.getSize() - 30) {
|
||||
// show the buttons again if page is big
|
||||
out.println("<div class=\"topbuttons\">");
|
||||
// form 5
|
||||
out.print(form);
|
||||
out.print(hidden);
|
||||
showPageButtons(out, sessionObject.user, folderName, page, folder.getPages(), false);
|
||||
out.println("</form>");
|
||||
out.println("</div>");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Folder callback to search mails for matching terms.
|
||||
* Only subject and sender (or recipients for drafts).
|
||||
* Mail bodies are not in-memory and would be very slow.
|
||||
*
|
||||
* @since 0.9.63
|
||||
*/
|
||||
private static class SearchSelector implements Folder.Selector<String> {
|
||||
private final String key;
|
||||
private final MailCache mc;
|
||||
private final String[] terms;
|
||||
private final boolean isDrafts;
|
||||
|
||||
/**
|
||||
* @param search non-null, non-empty, and %-encoded, will be decoded here
|
||||
*/
|
||||
public SearchSelector(MailCache cache, String search) {
|
||||
mc = cache;
|
||||
isDrafts = mc.getFolderName().equals(DIR_DRAFTS);
|
||||
key = search;
|
||||
terms = DataHelper.split(search, " ");
|
||||
// decode
|
||||
for (int i = 0; i < terms.length; i++) {
|
||||
terms[i] = terms[i].toLowerCase(Locale.US);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelectionKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public boolean select(String uidl) {
|
||||
Mail mail = mc.getMail(uidl, MailCache.FetchMode.HEADER_CACHE_ONLY);
|
||||
if (mail == null)
|
||||
return false;
|
||||
String subj = mail.subject.toLowerCase(Locale.US);
|
||||
String sender = isDrafts ? null : mail.sender;
|
||||
if (sender != null)
|
||||
sender = sender.toLowerCase(Locale.US);
|
||||
String[] to = isDrafts ? mail.to : null;
|
||||
for (String term : terms) {
|
||||
if (subj.contains(term))
|
||||
return true;
|
||||
if (sender != null && sender.contains(term))
|
||||
return true;
|
||||
if (to != null) {
|
||||
for (int i = 0; i < to.length; i++) {
|
||||
if (to[i].toLowerCase(Locale.US).contains(term))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Search selector for '" + key + "'";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Folder selector, then, if pages greater than 1:
|
||||
* first prev next last
|
||||
@ -3794,7 +3944,11 @@ public class WebMail extends HttpServlet
|
||||
out.println("<div id=\"messagenav\">");
|
||||
Folder<String> folder = mc.getFolder();
|
||||
if (hasHeader) {
|
||||
String uidl = folder.getPreviousElement(showUIDL);
|
||||
String uidl;
|
||||
if (folder.getCurrentSelector() != null)
|
||||
uidl = folder.getPreviousSelectedElement(showUIDL);
|
||||
else
|
||||
uidl = folder.getPreviousElement(showUIDL);
|
||||
String text = _t("Previous");
|
||||
if (uidl == null || folder.isFirstElement(showUIDL)) {
|
||||
out.println(button2(PREV, text));
|
||||
@ -3809,7 +3963,11 @@ public class WebMail extends HttpServlet
|
||||
out.println("<input type=\"hidden\" name=\"" + CUR_PAGE + "\" value=\"" + page + "\">");
|
||||
out.println(button( LIST, _t("Back to Folder") ) + spacer);
|
||||
if (hasHeader) {
|
||||
String uidl = folder.getNextElement(showUIDL);
|
||||
String uidl;
|
||||
if (folder.getCurrentSelector() != null)
|
||||
uidl = folder.getNextSelectedElement(showUIDL);
|
||||
else
|
||||
uidl = folder.getNextElement(showUIDL);
|
||||
String text = _t("Next");
|
||||
if (uidl == null || folder.isLastElement(showUIDL)) {
|
||||
out.println(button2(NEXT, text));
|
||||
|
@ -244,6 +244,30 @@ div.topbuttons br {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
#searchbox {
|
||||
background: #f8f8ff url(/themes/console/images/buttons/search.png) 7px center no-repeat !important;
|
||||
margin: 2px 4px 2px 24px !important;
|
||||
padding: 4px 32px 4px 32px !important;
|
||||
color: #47475f;
|
||||
}
|
||||
|
||||
#searchbox:focus, #searchbox:active {
|
||||
color: #19191f;
|
||||
}
|
||||
|
||||
#searchcancel {
|
||||
background: url(../images/delete.png) 0px center no-repeat;
|
||||
margin: 9px 4px 2px 2px;
|
||||
padding: 6px 12px;
|
||||
color: transparent;
|
||||
border: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#searchcancel.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
table#pagenav {
|
||||
float: right;
|
||||
width: 200px;
|
||||
|
@ -959,7 +959,7 @@ hr {
|
||||
}
|
||||
|
||||
#composemail table {
|
||||
width: auto;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
@ -1187,6 +1187,30 @@ h3#config {
|
||||
float: none !important;
|
||||
}
|
||||
|
||||
#searchbox {
|
||||
background: #f8f8ff url(/themes/console/images/buttons/search.png) 7px center no-repeat !important;
|
||||
margin: 2px 4px 2px 24px !important;
|
||||
padding: 4px 32px 4px 32px !important;
|
||||
color: #47475f;
|
||||
}
|
||||
|
||||
#searchbox:focus, #searchbox:active {
|
||||
color: #19191f;
|
||||
}
|
||||
|
||||
#searchcancel {
|
||||
background: url(../images/delete.png) 0px center no-repeat;
|
||||
margin: 9px 4px 2px 2px;
|
||||
padding: 6px 12px;
|
||||
color: transparent;
|
||||
border: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#searchcancel.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input.moveto {
|
||||
float: left;
|
||||
margin-left: 14px;
|
||||
|
Reference in New Issue
Block a user