| /**************************************************************** |
| * 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 java.util.Collection; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.apache.hupa.client.place.AbstractPlace; |
| import org.apache.hupa.client.place.FolderPlace; |
| import org.apache.hupa.client.place.MessagePlace; |
| import org.apache.hupa.client.rf.DeleteMessageByUidRequest; |
| import org.apache.hupa.client.rf.GetMessageDetailsRequest; |
| import org.apache.hupa.client.rf.MoveMessageRequest; |
| import org.apache.hupa.client.storage.HupaStorage; |
| import org.apache.hupa.client.ui.MessagesCellTable; |
| import org.apache.hupa.client.ui.MessagesCellTable.MessageListDataProvider; |
| import org.apache.hupa.client.ui.ToolBarView; |
| import org.apache.hupa.shared.data.MessageImpl.IMAPFlag; |
| import org.apache.hupa.shared.domain.DeleteMessageByUidAction; |
| import org.apache.hupa.shared.domain.DeleteMessageResult; |
| import org.apache.hupa.shared.domain.FetchMessagesResult; |
| import org.apache.hupa.shared.domain.GenericResult; |
| import org.apache.hupa.shared.domain.GetMessageDetailsAction; |
| import org.apache.hupa.shared.domain.ImapFolder; |
| import org.apache.hupa.shared.domain.Message; |
| import org.apache.hupa.shared.domain.MoveMessageAction; |
| import org.apache.hupa.shared.domain.User; |
| import org.apache.hupa.shared.events.DeleteClickEvent; |
| import org.apache.hupa.shared.events.DeleteClickEventHandler; |
| import org.apache.hupa.shared.events.MessageListRangeChangedEvent; |
| import org.apache.hupa.shared.events.MessageListRangeChangedEventHandler; |
| import org.apache.hupa.shared.events.MessageViewEvent; |
| import org.apache.hupa.shared.events.MessageViewEventHandler; |
| import org.apache.hupa.shared.events.MoveMessageEvent; |
| import org.apache.hupa.shared.events.MoveMessageEventHandler; |
| import org.apache.hupa.shared.events.RefreshFoldersEvent; |
| import org.apache.hupa.shared.events.RefreshMessagesEvent; |
| import org.apache.hupa.shared.events.RefreshMessagesEventHandler; |
| import org.apache.hupa.widgets.dialog.Dialog; |
| |
| import com.google.gwt.event.shared.EventBus; |
| import com.google.gwt.query.client.Function; |
| import com.google.gwt.query.client.Promise; |
| import com.google.gwt.storage.client.Storage; |
| import com.google.gwt.user.client.Command; |
| import com.google.gwt.user.client.Timer; |
| import com.google.gwt.user.client.ui.AcceptsOneWidget; |
| import com.google.gwt.user.client.ui.IsWidget; |
| import com.google.gwt.view.client.CellPreviewEvent; |
| import com.google.gwt.view.client.CellPreviewEvent.Handler; |
| import com.google.inject.Inject; |
| import com.google.web.bindery.requestfactory.shared.Receiver; |
| import com.google.web.bindery.requestfactory.shared.ServerFailure; |
| |
| public class MessageListActivity extends AppBaseActivity { |
| |
| @Inject protected Displayable display; |
| @Inject protected ToolBarActivity.Displayable toolBar; |
| @Inject protected HupaStorage hupaStorage; |
| |
| protected String folderName; |
| protected User user; |
| FetchMessagesResult currentFechResult; |
| Promise gettingMessages; |
| |
| boolean first = true; |
| |
| @Inject |
| public MessageListActivity(EventBus eventBus) { |
| bindTo(eventBus); |
| } |
| |
| private Timer refreshMessagesTimer = new Timer() { |
| public void run() { |
| display.refresh(); |
| } |
| }; |
| |
| @Override |
| public void onStop() { |
| super.onStop(); |
| refreshMessagesTimer.cancel(); |
| } |
| |
| @Override |
| public void start(AcceptsOneWidget container, final EventBus eventBus) { |
| refreshMessagesTimer.scheduleRepeating(5*60*1000); |
| |
| container.setWidget(display.asWidget()); |
| if (!first) { |
| display.refresh(); |
| first = false; |
| } |
| rf.sessionRequest().getUser().fire(new Receiver<User>() { |
| @Override |
| public void onSuccess(User u) { |
| if (u == null) { |
| onFailure(null); |
| } else { |
| user = u; |
| } |
| } |
| @Override |
| public void onFailure(ServerFailure error) { |
| } |
| }); |
| this.registerHandler(display.getGrid().addCellPreviewHandler(new Handler<Message>() { |
| @Override |
| public void onCellPreview(final CellPreviewEvent<Message> event) { |
| if (hasClickedButFirstCol(event)) { |
| onMessageSelected(event.getValue()); |
| } |
| } |
| })); |
| } |
| |
| protected void onMessageSelected(Message message) { |
| antiSelectMessages(display.getGrid().getVisibleItems()); |
| GetMessageDetailsRequest req = rf.messageDetailsRequest(); |
| GetMessageDetailsAction action = req.create(GetMessageDetailsAction.class); |
| final ImapFolder f = req.create(ImapFolder.class); |
| f.setFullName(folderName); |
| action.setFolder(f); |
| action.setUid(message.getUid()); |
| String token = getToken(message); |
| MessagePlace place = new MessagePlace(token); |
| pc.goTo(place); |
| display.getGrid().getSelectionModel().setSelected(message, true); |
| toolBar.enableSendingTools(true); |
| toolBar.enableDealingTools(true); |
| ToolBarView.Parameters p = new ToolBarView.Parameters(user, folderName, message, null); |
| toolBar.setParameters(p); |
| |
| // display.refresh(); |
| // eventBus.fireEvent(new RefreshFoldersEvent(event.getValue())); |
| |
| } |
| |
| private String getToken(Message message) { |
| String token = folderName + AbstractPlace.SPLITTER + message.getUid(); |
| return token; |
| } |
| |
| private boolean hasClickedButFirstCol(CellPreviewEvent<Message> event) { |
| return "click".equals(event.getNativeEvent().getType()) && 0 != event.getColumn(); |
| } |
| |
| private void bindTo(final EventBus eventBus) { |
| |
| registerHandler(eventBus.addHandler(DeleteClickEvent.TYPE, new DeleteClickEventHandler() { |
| @Override |
| public void onDeleteClickEvent(DeleteClickEvent event) { |
| deleteSelectedMessages(); |
| } |
| })); |
| |
| registerHandler(eventBus.addHandler(RefreshMessagesEvent.TYPE, new RefreshMessagesEventHandler() { |
| @Override |
| public void onRefresh(RefreshMessagesEvent event) { |
| display.setSearchValue(event.getSearchValue()); |
| display.refresh(); |
| System.out.println("REFRESH DISPLAY"); |
| } |
| })); |
| |
| registerHandler(eventBus.addHandler(MoveMessageEvent.TYPE, new MoveMessageEventHandler() { |
| |
| @Override |
| public void onMoveMessageHandler(final MoveMessageEvent event) { |
| hc.showTopLoading("Moving..."); |
| MoveMessageRequest req = rf.moveMessageRequest(); |
| ImapFolder f = req.create(ImapFolder.class); |
| ImapFolder newF = req.create(ImapFolder.class); |
| |
| String fullName = null; |
| if (pc.getWhere() instanceof FolderPlace) { |
| fullName = ((FolderPlace) pc.getWhere()).getToken(); |
| } else { |
| fullName = ((MessagePlace) pc.getWhere()).getTokenWrapper().getFolder(); |
| } |
| f.setFullName(fullName); |
| newF.setFullName(event.getNewFolder().getFullName()); |
| MoveMessageAction action = req.create(MoveMessageAction.class); |
| |
| final List<Long> uids = display.getSelectedMessagesIds(); |
| // TODO can move more than one message once. |
| if (uids.isEmpty() || uids.size() > 1) { |
| hc.hideTopLoading(); |
| hc.showNotice("Please select one and only one message", 10000); |
| return; |
| } |
| action.setMessageUid(uids.get(0)); |
| action.setNewFolder(newF); |
| action.setOldFolder(f); |
| req.move(action).fire(new Receiver<GenericResult>() { |
| |
| @Override |
| public void onSuccess(GenericResult response) { |
| display.refresh(); |
| eventBus.fireEvent(new RefreshFoldersEvent()); |
| hc.hideTopLoading(); |
| hc.showNotice("The conversation has been moved to \"" + event.getNewFolder() + "\"", 10000); |
| } |
| |
| @Override |
| public void onFailure(ServerFailure error) { |
| super.onFailure(error); |
| hc.hideTopLoading(); |
| hc.showNotice(error.getMessage(), 10000); |
| } |
| |
| }); |
| } |
| |
| })); |
| |
| registerHandler(eventBus.addHandler(MessageViewEvent.TYPE, new MessageViewEventHandler() { |
| public void onMessageViewEvent(final MessageViewEvent event) { |
| if (event.messageDetails != null && gettingMessages != null) { |
| gettingMessages.done(new Function() { |
| public void f() { |
| List<Message> messages = currentFechResult.getMessages(); |
| int l = messages.size(); |
| for (int i = 0; i < l; i++){ |
| Message m = messages.get(i); |
| if (m.getUid() == event.messageDetails.getUid()) { |
| List<IMAPFlag> flags = m.getFlags(); |
| if (!flags.contains(IMAPFlag.SEEN)) { |
| flags.add(IMAPFlag.SEEN); |
| m = rf.deleteMessageByUidRequest().edit(m); |
| m.setFlags(flags); |
| messages.set(i, m); |
| display.getDataProvider().setFechMessagesResult(currentFechResult); |
| } |
| display.getGrid().getSelectionModel().setSelected(m, true); |
| display.getGrid().getRowElement(i).scrollIntoView(); |
| ToolBarView.Parameters p = new ToolBarView.Parameters(user, folderName, m, event.messageDetails); |
| toolBar.setParameters(p); |
| break; |
| } |
| } |
| } |
| }); |
| } |
| } |
| })); |
| |
| registerHandler(eventBus.addHandler(MessageListRangeChangedEvent.TYPE, new MessageListRangeChangedEventHandler() { |
| public void onRangeChangedEvent(MessageListRangeChangedEvent event) { |
| gettingMessages = hupaStorage |
| .gettingMessages(true, folderName, event.start, event.size, event.search) |
| .done(new Function() { |
| public void f() { |
| FetchMessagesResult response = arguments(0); |
| display.getDataProvider().setFechMessagesResult(response); |
| currentFechResult = response; |
| cacheContacts(); |
| } |
| }) |
| .fail(new Function() { |
| public void f() { |
| hc.showNotice("" + arguments(0), 3000); |
| } |
| }) |
| .always(new Function() { |
| public void f() { |
| hc.hideTopLoading(); |
| } |
| }); |
| |
| } |
| })); |
| |
| } |
| |
| public MessageListActivity with(String folderName) { |
| this.folderName = folderName; |
| return this; |
| } |
| |
| public interface Displayable extends IsWidget { |
| MessagesCellTable getGrid(); |
| |
| void refresh(); |
| |
| List<Long> getSelectedMessagesIds(); |
| |
| Set<Message> getSelectedMessages(); |
| |
| void setSearchValue(String searchValue); |
| |
| MessageListDataProvider getDataProvider(); |
| } |
| |
| private void antiSelectMessages(Collection<Message> c) { |
| toolBar.enableAllTools(false); |
| for (Message msg : c) { |
| if (!display.getGrid().getSelectionModel().isSelected(msg)) |
| continue; |
| display.getGrid().getSelectionModel().setSelected(msg, false); |
| } |
| } |
| private void deleteSelectedMessages() { |
| |
| final List<Long> uids = display.getSelectedMessagesIds(); |
| |
| if (uids.size() > 0) { |
| Dialog.confirm("Do you want to delete selected messages?", new Command() { |
| public void execute() { |
| doDelete(uids); |
| } |
| }); |
| } |
| |
| } |
| |
| protected void doDelete(final List<Long> uids) { |
| hc.showTopLoading("Deleting..."); |
| |
| String fullName = null; |
| if (pc.getWhere() instanceof FolderPlace) { |
| fullName = ((FolderPlace) pc.getWhere()).getToken(); |
| } else { |
| fullName = ((MessagePlace) pc.getWhere()).getTokenWrapper().getFolder(); |
| } |
| |
| DeleteMessageByUidRequest req = rf.deleteMessageByUidRequest(); |
| DeleteMessageByUidAction action = req.create(DeleteMessageByUidAction.class); |
| ImapFolder f = req.create(ImapFolder.class); |
| f.setFullName(fullName); |
| action.setMessageUids(uids); |
| action.setFolder(f); |
| req.delete(action).fire(new Receiver<DeleteMessageResult>() { |
| @Override |
| public void onSuccess(DeleteMessageResult response) { |
| antiSelectMessages(display.getSelectedMessages()); |
| display.refresh(); |
| hc.hideTopLoading(); |
| pc.goTo(new FolderPlace(folderName)); |
| eventBus.fireEvent(new RefreshFoldersEvent()); |
| for (Long uid : uids) { |
| removeMessage(uid); |
| } |
| display.getDataProvider().setFechMessagesResult(currentFechResult); |
| // display.getGrid().getRowElement(0).scrollIntoView(); |
| } |
| |
| @Override |
| public void onFailure(ServerFailure error) { |
| hc.hideTopLoading(); |
| hc.showNotice("Error removing messages", 5000); |
| super.onFailure(error); |
| } |
| |
| private void removeMessage(Long uid) { |
| List<Message> messages = currentFechResult.getMessages(); |
| int l = messages.size(); |
| for (int i = 0; i < l; i++){ |
| Message m = messages.get(i); |
| if (m.getUid() == uid) { |
| messages.remove(i); |
| return; |
| } |
| } |
| } |
| }); |
| } |
| |
| |
| // TODO move this stuff to hupaStorage |
| private void cacheContacts() { |
| for (Message message : currentFechResult.getMessages()) { |
| message.getFrom(); |
| message.getTo(); |
| message.getCc(); |
| message.getReplyto(); |
| |
| contacts.add(message.getFrom()); |
| contacts.add(message.getReplyto()); |
| |
| for (String to : message.getTo()) { |
| contacts.add(to); |
| } |
| for (String cc : message.getCc()) { |
| contacts.add(cc); |
| } |
| } |
| saveToLocalStorage(contacts); |
| } |
| |
| private void saveToLocalStorage(Set<String> contacts) { |
| contactsStore = Storage.getLocalStorageIfSupported(); |
| if (contactsStore != null) { |
| String contactsString = contactsStore.getItem(CONTACTS_STORE); |
| if (null != contactsString) { |
| for (String contact : contactsString.split(",")) { |
| contacts.add(contact.replace("[", "").replace("]", "").trim()); |
| } |
| } |
| contactsStore.setItem(CONTACTS_STORE, contacts.toString()); |
| } |
| } |
| |
| public static final String CONTACTS_STORE = "hupa-contacts"; |
| Set<String> contacts = new LinkedHashSet<String>(); |
| private Storage contactsStore = null; |
| } |