blob: 316dd77b8005beb319bec5d7509458b3a0e1251e [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. *
****************************************************************/
package org.apache.hupa.client.activity;
import gwtupload.client.IUploadStatus.Status;
import gwtupload.client.IUploader;
import gwtupload.client.IUploader.OnCancelUploaderHandler;
import gwtupload.client.IUploader.OnFinishUploaderHandler;
import gwtupload.client.IUploader.OnStatusChangedHandler;
import gwtupload.client.IUploader.UploadedInfo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.hupa.client.HupaController;
import org.apache.hupa.client.place.ComposePlace;
import org.apache.hupa.client.rf.SendForwardMessageRequest;
import org.apache.hupa.client.rf.SendMessageRequest;
import org.apache.hupa.client.rf.SendReplyMessageRequest;
import org.apache.hupa.client.validation.EmailListValidator;
import org.apache.hupa.shared.Util;
import org.apache.hupa.shared.data.MessageAttachmentImpl;
import org.apache.hupa.shared.domain.GenericResult;
import org.apache.hupa.shared.domain.ImapFolder;
import org.apache.hupa.shared.domain.Message;
import org.apache.hupa.shared.domain.MessageAttachment;
import org.apache.hupa.shared.domain.MessageDetails;
import org.apache.hupa.shared.domain.SendForwardMessageAction;
import org.apache.hupa.shared.domain.SendMessageAction;
import org.apache.hupa.shared.domain.SendReplyMessageAction;
import org.apache.hupa.shared.domain.SmtpMessage;
import org.apache.hupa.shared.domain.User;
import org.apache.hupa.shared.events.AddressClickEvent;
import org.apache.hupa.shared.events.AddressClickEventHandler;
import org.apache.hupa.shared.events.AttachClickEvent;
import org.apache.hupa.shared.events.AttachClickEventHandler;
import org.apache.hupa.shared.events.LoginEvent;
import org.apache.hupa.shared.events.LoginEventHandler;
import org.apache.hupa.shared.events.MailToEvent;
import org.apache.hupa.shared.events.MailToEventHandler;
import org.apache.hupa.shared.events.SendClickEvent;
import org.apache.hupa.shared.events.SendClickEventHandler;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.ListBox;
import com.google.inject.Inject;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.RequestContext;
public class ComposeActivity extends AppBaseActivity {
@Inject private Displayable display;
@Inject private HupaController hupaController;
private List<MessageAttachment> attachments = new ArrayList<MessageAttachment>();
protected ComposePlace place;
private User user;
public Activity with(ComposePlace place) {
this.place = place;
return this;
}
@Override
public void start(AcceptsOneWidget container, EventBus eventBus) {
container.setWidget(display.asWidget());
bindTo(eventBus);
fillHeader();
}
@Override
public String mayStop() {
super.mayStop();
if (noContent()) {
return null;
}
return null;
// return "Do you want to leave this page?"; TODO
}
@Override
public void onStop() {
super.onStop();
}
private boolean noContent() {
return "".equals(display.getMessage().getText()) && "".equals(display.getSubject().getText());
}
@Override
public void onCancel() {
}
protected void fillHeader() {
if (place == null || place.getParameters() == null)
return;
if (user == null) {
user = place.getParameters().getUser();
}
if (user == null) {
user = HupaController.user;
}
display.getFromList().addItem(user.getName());
display.getUploader().reset();
if ("new".equals(place.getToken())) {
display.getTo().setText("");
display.getCc().setText("");
display.getBcc().setText("");
display.getSubject().setText(place.getSubject() == null ? "" : place.getSubject());
display.getMessageHTML().setHTML(place.getBody() == null ? "" : place.getBody());
attachments.clear();
return;
}
Message oldMessage = place.getParameters().getOldmessage();
display.getMessageHTML().setHTML(
wrapMessage(oldMessage, place.getParameters().getOldDetails(), place.getToken()));
if ("forward".equals(place.getToken())) {
String subject = oldMessage.getSubject() != null ? oldMessage.getSubject().trim() : "";
if (!subject.toLowerCase().startsWith("fwd:")) {
subject = "Fwd: " + subject;
}
display.getSubject().setText(subject);
} else if ("reply".equals(place.getToken()) || "replyAll".equals(place.getToken())) {
String subject = oldMessage.getSubject() != null ? oldMessage.getSubject().trim() : "";
if (!subject.toLowerCase().startsWith("re:")) {
subject = "Re: " + subject;
}
if ("reply".equals(place.getToken())) {
display.getSubject().setText(subject);
if (oldMessage.getReplyto() != null && !oldMessage.getFrom().contains(oldMessage.getReplyto())) {
display.getTo().setText(oldMessage.getReplyto());
} else {
display.getTo().setText(oldMessage.getFrom());
}
} else if ("replyAll".equals(place.getToken())) {
ArrayList<String> list = new ArrayList<String>();
if (oldMessage.getReplyto() != null && !oldMessage.getFrom().contains(oldMessage.getReplyto()))
list.add(oldMessage.getReplyto());
if (oldMessage.getTo() != null)
list.addAll(oldMessage.getTo());
if (oldMessage.getCc() != null)
list.addAll(oldMessage.getCc());
list = removeEmailFromList(list, user.getName());
display.getCc().setText(Util.listToString(list));
if (oldMessage.getTo() != null) {
oldMessage.getTo().remove(user.getName());
}
display.getTo().setText(oldMessage.getFrom());
}
}
}
protected ArrayList<String> removeEmailFromList(List<String> list, String email) {
ArrayList<String> ret = new ArrayList<String>();
String regex = ".*<?\\s*" + email.trim() + "\\s*>?\\s*";
for (String e : list) {
if (!e.matches(regex)) {
ret.add(e);
}
}
return ret;
}
private static String generateHeader(Message message, String type) {
String ret = "<br>";
if (message != null) {
if (type.equals("forward")) {
ret += "--------- Forwarded message --------- <br>";
ret += "From: " + message.getFrom().replaceAll("<", "&lt;").replaceAll(">", "&gt;") + "<br>";
ret += "Date: " + message.getReceivedDate() + "<br>";
ret += "Subject: " + message.getSubject() + "<br>";
ArrayList<String> to = new ArrayList<String>();
to.addAll(message.getTo());
to.addAll(message.getCc());
ret += "To: " + Util.listToString(to).replaceAll("<", "&lt;").replaceAll(">", "&gt;") + "<br>";
} else if (type.equals("reply") || type.equals("replyAll")) {
ret += "On " + message.getReceivedDate();
ret += ", " + message.getFrom().replaceAll("<", "&lt;").replaceAll(">", "&gt;");
ret += ". wrote:<br>";
}
}
return ret + "<br>";
}
public static String wrapMessage(Message message, MessageDetails details, String type) {
String ret = "";
if (message != null) {
ret += generateHeader(message, type);
}
if (details != null && details.getText() != null && details.getText().length() > 0) {
ret += "<blockquote style='border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;'>";
ret += details.getText();
ret += "</blockquote>";
}
return ret;
}
protected void bindTo(EventBus eventBus) {
eventBus.addHandler(AddressClickEvent.TYPE, new AddressClickEventHandler() {
@Override
public void onClick(AddressClickEvent event) {
String to = display.getTo().getText();
if(to != null && to.trim().length() > 0){
display.getTo().setText(to + ";" + event.getEmail());
}else {
display.getTo().setText(event.getEmail());
}
}
});
eventBus.addHandler(SendClickEvent.TYPE, new SendClickEventHandler() {
public void onSendClick(SendClickEvent event) {
send();
}
});
eventBus.addHandler(LoginEvent.TYPE, new LoginEventHandler() {
public void onLogin(LoginEvent event) {
user = event.getUser();
}
});
eventBus.addHandler(AttachClickEvent.TYPE, new AttachClickEventHandler() {
public void onAttachClick(AttachClickEvent event) {
display.getAttachButton().fireEvent(new ClickEvent() {
});
}
});
registerHandler(display.getSendClick().addClickHandler(sendClickHandler));
registerHandler(display.getCancelClick().addClickHandler(cancelClickHandler));
registerHandler(display.getCcClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.showCc();
}
}));
registerHandler(display.get_CcClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.hideCc();
}
}));
registerHandler(display.getBccClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.showBcc();
}
}));
registerHandler(display.get_BccClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.hideBcc();
}
}));
registerHandler(display.getReplyClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.showReply();
}
}));
registerHandler(display.get_ReplyClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.hideReply();
}
}));
registerHandler(display.getFollowupClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.showFollowup();
}
}));
registerHandler(display.get_FollowupClick().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
display.hideFollowup();
}
}));
registerHandler(display.getUploader().addOnStatusChangedHandler(onStatusChangedHandler));
registerHandler(display.getUploader().addOnFinishUploadHandler(onFinishUploadHandler));
registerHandler(display.getUploader().addOnCancelUploadHandler(onCancelUploadHandler));
eventBus.addHandler(MailToEvent.TYPE, new MailToEventHandler() {
@Override
public void onMailTo(MailToEvent event) {
display.getTo().setText(event.getMailto());
}
});
fillSuggestList();
}
private void fillSuggestList() {
// TODO move this to hupaStorage
Storage contactStore = Storage.getLocalStorageIfSupported();
if (contactStore != null) {
String contactsString = contactStore.getItem(MessageListActivity.CONTACTS_STORE);
if (contactsString != null) {
display.fillContactList(contactsString.replace("[", "").replace("]", "").trim().split(","));
}
}
}
private OnFinishUploaderHandler onFinishUploadHandler = new OnFinishUploaderHandler() {
public void onFinish(IUploader uploader) {
if (uploader.getStatus() == Status.SUCCESS) {
// We use the fileInputName (unique) instead of the fileName so
// as we
// can find the item in the registry.
for (UploadedInfo info : uploader.getServerMessage().getUploadedInfos()) {
MessageAttachment attachment = new MessageAttachmentImpl();
attachment.setName(info.getField());
attachment.setContentType(info.getCtype());
attachment.setSize(info.getSize());
attachments.add(attachment);
}
}
}
};
private OnStatusChangedHandler onStatusChangedHandler = new OnStatusChangedHandler() {
public void onStatusChanged(IUploader uploader) {
Status stat = display.getUploader().getStatus();
((HasEnabled) display.getSendClick()).setEnabled(stat != Status.INPROGRESS);
}
};
private OnCancelUploaderHandler onCancelUploadHandler = new OnCancelUploaderHandler() {
public void onCancel(IUploader uploader) {
for (Iterator<MessageAttachment> i = attachments.iterator(); i.hasNext();) {
MessageAttachment attachment = i.next();
if (attachment.getName().equals(uploader.getInputName()))
i.remove();
}
}
};
private ClickHandler cancelClickHandler = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
History.back();
}
};
protected ClickHandler sendClickHandler = new ClickHandler() {
public void onClick(ClickEvent event) {
send();
}
};
protected void send() {
if (!validate())
return;
hupaController.showTopLoading("Sending...");
MessageDetails oldDetails = place.getParameters().getOldDetails();
if ("new".equals(place.getToken())) {
SendMessageRequest sendReq = rf.sendMessageRequest();
SendMessageAction sendAction = sendReq.create(SendMessageAction.class);
sendAction.setMessage(parseMessage(sendReq));
sendReq.send(sendAction).fire(new Receiver<GenericResult>() {
@Override
public void onSuccess(GenericResult response) {
afterSend(response);
}
});
} else if ("forward".equals(place.getToken())) {
// FIXME will get a NullPointerException given accessing
// directly from some URL like #/compose:forward
SendForwardMessageRequest req = rf.sendForwardMessageRequest();
SendForwardMessageAction action = req.create(SendForwardMessageAction.class);
action.setReferences(oldDetails.getReferences());
action.setMessage(parseMessage(req));
ImapFolder f = req.create(ImapFolder.class);
f.setFullName(place.getParameters().getFolderName());
action.setFolder(f);
action.setUid(place.getParameters().getOldmessage().getUid());
req.send(action).fire(new Receiver<GenericResult>() {
@Override
public void onSuccess(GenericResult response) {
afterSend(response);
}
});
} else {
SendReplyMessageRequest replyReq = rf.sendReplyMessageRequest();
SendReplyMessageAction action = replyReq.create(SendReplyMessageAction.class);
action.setReferences(oldDetails.getReferences());
action.setMessage(parseMessage(replyReq));
ImapFolder folder = replyReq.create(ImapFolder.class);
folder.setFullName(place.getParameters().getFolderName());
action.setFolder(folder);
action.setUid(place.getParameters().getOldmessage().getUid());
replyReq.send(action).fire(new Receiver<GenericResult>() {
@Override
public void onSuccess(GenericResult response) {
afterSend(response);
}
});
}
}
private boolean validate() {
// Don't trust only in view validation
return display.validate() && display.getTo().getText().trim().length() > 0
&& EmailListValidator.isValidAddressList(display.getTo().getText())
&& EmailListValidator.isValidAddressList(display.getCc().getText())
&& EmailListValidator.isValidAddressList(display.getBcc().getText());
}
protected SmtpMessage parseMessage(RequestContext rc) {
SmtpMessage message = rc.create(SmtpMessage.class);
List<MessageAttachment> attaches = new ArrayList<MessageAttachment>();
for (MessageAttachment attach : attachments) {
MessageAttachment attachMent = rc.create(MessageAttachment.class);
attachMent.setName(attach.getName());
attachMent.setSize(attach.getSize());
attachMent.setContentType(attach.getContentType());
attaches.add(attachMent);
}
message.setFrom(display.getFromText());
message.setSubject(display.getSubject().getText());
message.setText(display.getMessageHTML().getHTML());
message.setMessageAttachments(attaches);
message.setTo(emailTextToArray(display.getTo().getText()));
message.setCc(emailTextToArray(display.getCc().getText()));
message.setBcc(emailTextToArray(display.getBcc().getText()));
return message;
}
private List<String> emailTextToArray(String emails) {
List<String> cc = new ArrayList<String>();
for (String ccRaw : emails.split("[,;]+")) {
String ccRecip = ccRaw.trim();
if (ccRecip.length() > 0) {
cc.add(ccRaw.trim());
}
}
return cc;
}
private void afterSend(GenericResult response) {
hupaController.hideTopLoading();
hupaController.showNotice("Your mail has been sent.", 10000);
History.back();
}
public interface Displayable extends IsWidget {
String getFromText();
void showCc();
void hideCc();
void showBcc();
void hideBcc();
void showReply();
void hideReply();
void showFollowup();
void hideFollowup();
HasText getTo();
HasText getCc();
HasText getBcc();
HasText getSubject();
HasClickHandlers getSendClick();
HasClickHandlers getCancelClick();
HasClickHandlers getCcClick();
HasClickHandlers get_CcClick();
HasClickHandlers getBccClick();
HasClickHandlers get_BccClick();
HasClickHandlers getReplyClick();
HasClickHandlers get_ReplyClick();
HasClickHandlers getFollowupClick();
HasClickHandlers get_FollowupClick();
boolean validate();
HasText getMessage();
HasHTML getMessageHTML();
ListBox getFromList();
IUploader getUploader();
void fillContactList(String[] contacts);
HasFocusHandlers getAttachButton();
}
}