I am looking at folder management inside kairos and it's really messy.
There is one part inside SMMailAccount.j where we can find methods
like :
- (SMMailBox)createMailbox:(id)sender
- (void)removeMailbox:(SMMailbox)aMailbox
...
and another part inside SMMailBox.j with methods like :
- (void)renameTo:(CPString)aName
- (void)remove
...
And those methods generally calls methods from SMMailAccount.j.
But what's the point ? Why is it so complex ?
About the fact that you create a renameOrCreateFolder because you
didn't know if it was a creation or a rename operation I don't think
this is a good idea. For the moment (maybe it will be necessary one
day) I would prefer to be able to separate and clearly identify those
operations.
I am quite sure that when we choose new folder inside the context menu
or when we click on the + icon we could set a member variable like
_creationMode and pass this information to some other method.
About renameOrCreateFolder maybe instead of returning null or string I
would prefer something more general because I am not even sure we can
return null for object different from String.
And sometimes we may want to pass more information than just a string
about the object state, what about the following prototype :
def renameOrCreateFolder(oldName: String, destName: String):
SMMailbox = {
}
And add a member variable error to all remote objects.
But actually the returned value doesn't seem to be used, if I follow
the workflow I get this :
1) A user creates a new folder(clicking on + or using context menu)
- (IBAction)addMailbox:(id)sender (MailSourceViewController.j)
{
- (SMMailBox)createMailbox:(id)sender (inside this method we
create a new SMMailBox and we add it to the mailboxes)
we reload data source => it will update the ui and display a new
folder in edit mode with a default name
}
Then when user validate the new name for the folder I suppose the
following event will be triggered :
- (void)outlineView:(CPOutlineView)anOutlineView setObjectValue:
(id)aValue forTableColumn:(CPTableColumn)aColumn byItem:(id)anItem
{
[mailbox renameTo:aValue]; // The creation is really done
here
[self reload]; // once again we reload data source
}
With this logic we never hanlde the value returned by
renameOrCreateFolder.
- (void)imapServerDidRenameOrCreateFolder:(String)err
{
CPLog("imapServerDidRenameOrCreateFolder");
if (err != "")
{
// Output error to user
alert(err)
}
}
package test1pckg;
import java.util.*;
import javax.mail.*;
import com.sun.mail.imap.*;
public class StartUp {
/**
* @param args
*/
public static void main(String[] args) {
try {
IMAPStore store = null;
Session sessionIMAP = Session.getInstance(System.getProperties(), null);
sessionIMAP.setDebug(true);
try {
store = (IMAPStore) sessionIMAP.getStore("imap");
store.connect("mail.smartmobili.com",143,"webg...@smartmobili.com","password_here");
} catch (Exception e) {
e.printStackTrace();
}
IMAPFolder folder = (IMAPFolder) store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
System.out.println("start");
Message[] msgs = folder.getMessages(1,folder.getMessageCount());
long ftime = System.currentTimeMillis();
FetchProfile fp=new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add("Newsgroups");
folder.fetch(msgs, fp);
long time = System.currentTimeMillis();
String fetchTimeStr = "----!!!!!fetch time: "+(time-ftime) + " ms (1000ms = 1 sec)";
System.out.println(fetchTimeStr);
for (Message message : msgs) {
System.out.println("Subject: " + message.getSubject());
Address[] from = message.getFrom();
for (Address address : from) {
System.out.println("From: " + address);
}
Address[] recipients = message.getAllRecipients();
for (Address address : recipients) {
System.out.println("To: " + address);
}
System.out.println("--------");
}
long newTime = System.currentTimeMillis();
System.out.println(fetchTimeStr);
System.out.println("----!!!!output headers time: "+(newTime-time) + "ms (1000ms = 1 sec)");
}catch (Exception e) {
e.printStackTrace();
}
}
}
I am also worried about the fact that we instanciate a HNRemoteService
too many times I think, wouln't be possible to have a kind of
singleton and always call the same instance ?
But in this case why don't we get all imap responses inside the same
file ?
By the way maybe _editMode or _updateMode would be a better name for
the variable or why not _upsertMode(for update or insert)
[mailbox save:aValue withEditMode:_editMode]
[mailbox save:aValue withUpsertMode:_upsertMode];
Hi Vincent,No, there is no need cache. I made investigation if IMAP performance and found a bottleneck (one of it). It is a function "imapHeadersForFolder(…)" in ImapService.scala. It supposed to download all headers. Note, that we working with IMAP and it should download all requested headers with just one request to IMAP server. That imapHeadersForFolder(…) function currently makes a huge count of IMAP "FETCH" command requests to IMAP server, and this is why it is working slow, and it works more slowly with remote IMAP server, because of delay between client and server and every FETCH request takes time (delay).I wrote small program in Java with using javamail library (mail-1.4.4.jar). It download headers from IMAP with just one FETCH request. It download headers for all mails from kairos test account in just 1 second!! If you will try this code, don't forget to add javamail lib to the project, and fix password in "password_here" placeholder.Bellow the code there is more thoughts, please don't miss it.
Hi Vincent,I have done implementing folder creation with separate function to create folder from renaming folders. I used new _folderEditMode member variable and enum FolderEditModes. Please review latest commit ( https://github.com/smartmobili/kairos/commit/387cce93272a62076b886ddab752631ad9780b7d ) and let me know if you satisfied with current solution with using _folderEditMode and separate createFolder function.Current TODOs for folder creation/renaming:
1. Renaming of folders not yet implemented2. Returned errors from folder creation function is still string (need to think out an standard for errors returning from ImapService to webapp), and this string is not using localization yet.And I found the bug:3. Bug: when renaming folder and after editing folder name user not press enter, but press mouse outside of edit field, event "setObjectValue" is not triggered, and so name of folder is not saved. Also here I see not usual behavior of edit field: when edit field is active, if we click to other item in list, edit field will disappear as expected (but setObjectValue not triggered), but if we will click outside of list of folders, e.g. on white field of email content in kairos, then edit field of folder name will be with white text and will remain on screen, what is not expected behavior, and of course setObjectValue is also not triggered as expected, so folder name changes is not saved at server.Right now I will work on folder renaming (1).