Fixed/improved folder synchronization

This commit is contained in:
M66B 2018-12-22 12:40:47 +01:00
parent 14bc4bd7b6
commit cf185bb744
7 changed files with 1290 additions and 22 deletions

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 23,
version = 24,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -307,6 +307,13 @@ public abstract class DB extends RoomDatabase {
db.execSQL("ALTER TABLE `folder` ADD COLUMN `download` INTEGER NOT NULL DEFAULT 1");
}
})
.addMigrations(new Migration(23, 24) {
@Override
public void migrate(SupportSQLiteDatabase db) {
Log.i(Helper.TAG, "DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `folder` ADD COLUMN `tbc` INTEGER");
}
})
.build();
}

View File

@ -164,8 +164,7 @@ public interface DaoFolder {
int setFoldersUser(long account);
@Query("UPDATE folder" +
" SET name = :name" +
", display = :display" +
" SET display = :display" +
", unified = :unified" +
", notify = :notify" +
", hide = :hide" +
@ -177,7 +176,7 @@ public interface DaoFolder {
" WHERE id = :id")
int setFolderProperties(
long id,
String name, String display, boolean unified, boolean notify, boolean hide,
String display, boolean unified, boolean notify, boolean hide,
boolean synchronize, boolean poll, boolean download,
int sync_days, int keep_days);
@ -190,9 +189,15 @@ public interface DaoFolder {
@Query("UPDATE folder SET initialize = 0 WHERE id = :id")
int setFolderInitialized(long id);
@Query("UPDATE folder SET tbc = 0 WHERE id = :id")
int resetFolderTbc(long id);
@Query("UPDATE folder SET tbd = 1 WHERE id = :id")
int setFolderTbd(long id);
@Query("DELETE FROM folder WHERE id = :id")
void deleteFolder(long id);
@Query("DELETE FROM folder WHERE account = :account AND name = :name")
void deleteFolder(long account, String name);
}

View File

@ -86,7 +86,8 @@ public class EntityFolder implements Serializable {
@NonNull
public Boolean notify = false;
public String[] keywords;
public Boolean tbd;
public Boolean tbc; // to be created
public Boolean tbd; // to be deleted
public String state;
public String sync_state;
public String error;

View File

@ -63,6 +63,7 @@ public class FragmentFolder extends FragmentEx {
private long id = -1;
private long account = -1;
private boolean deletable = false;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -181,6 +182,9 @@ public class FragmentFolder extends FragmentEx {
reload = true;
Log.i(Helper.TAG, "Creating folder=" + name);
if (TextUtils.isEmpty(name))
throw new IllegalArgumentException(getString(R.string.title_folder_name_missing));
EntityFolder create = new EntityFolder();
create.account = aid;
create.name = name;
@ -195,6 +199,7 @@ public class FragmentFolder extends FragmentEx {
create.download = download;
create.sync_days = sync_days;
create.keep_days = keep_days;
create.tbc = true;
db.folder().insertFolder(create);
} else {
reload = (!folder.synchronize.equals(synchronize) ||
@ -214,7 +219,7 @@ public class FragmentFolder extends FragmentEx {
Log.i(Helper.TAG, "Updating folder=" + name);
db.folder().setFolderProperties(id,
name, display, unified, notify, hide,
display, unified, notify, hide,
synchronize, poll, download,
sync_days, keep_days);
@ -274,7 +279,7 @@ public class FragmentFolder extends FragmentEx {
@Override
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.menu_delete).setVisible(id > 0);
menu.findItem(R.id.menu_delete).setVisible(id > 0 && deletable);
super.onPrepareOptionsMenu(menu);
}
@ -383,6 +388,9 @@ public class FragmentFolder extends FragmentEx {
cbPoll.setEnabled(cbSynchronize.isChecked());
cbDownload.setEnabled(cbSynchronize.isChecked());
btnSave.setEnabled(true);
deletable = (folder != null && EntityFolder.USER.equals(folder.type));
getActivity().invalidateOptionsMenu();
}
@Override

View File

@ -870,9 +870,6 @@ public class ServiceSynchronize extends LifecycleService {
try {
wlAccount.acquire();
Log.i(Helper.TAG, "Folder deleted=" + e.getFolder().getFullName());
EntityFolder folder = db.folder().getFolderByName(account.id, e.getFolder().getFullName());
if (folder != null)
db.folder().setFolderTbd(folder.id);
reload(ServiceSynchronize.this, "folder deleted");
} finally {
wlAccount.release();
@ -1908,7 +1905,13 @@ public class ServiceSynchronize extends LifecycleService {
Log.v(Helper.TAG, "Start sync folders account=" + account.name);
List<String> names = new ArrayList<>();
for (EntityFolder folder : db.folder().getUserFolders(account.id))
for (EntityFolder folder : db.folder().getFolders(account.id)) {
if (folder.tbc != null) {
IMAPFolder ifolder = (IMAPFolder) istore.getFolder(folder.name);
ifolder.create(Folder.HOLDS_MESSAGES);
db.folder().resetFolderTbc(folder.id);
}
if (folder.tbd == null)
names.add(folder.name);
else {
@ -1917,6 +1920,7 @@ public class ServiceSynchronize extends LifecycleService {
ifolder.delete(false);
db.folder().deleteFolder(folder.id);
}
}
Log.i(Helper.TAG, "Local folder count=" + names.size());
Folder defaultFolder = istore.getDefaultFolder();
@ -1925,10 +1929,13 @@ public class ServiceSynchronize extends LifecycleService {
Log.i(Helper.TAG, "Remote folder count=" + ifolders.length + " separator=" + separator);
for (Folder ifolder : ifolders) {
String fullName = ifolder.getFullName();
names.remove(fullName);
String type = null;
boolean selectable = true;
String[] attrs = ((IMAPFolder) ifolder).getAttributes();
Log.i(Helper.TAG, ifolder.getFullName() + " attrs=" + TextUtils.join(" ", attrs));
Log.i(Helper.TAG, fullName + " attrs=" + TextUtils.join(" ", attrs));
for (String attr : attrs) {
if ("\\Noselect".equals(attr))
selectable = false;
@ -1942,13 +1949,10 @@ public class ServiceSynchronize extends LifecycleService {
}
// Special case
if (type == null) {
if (ifolder.getFullName().startsWith("INBOX" /*+ separator*/))
type = EntityFolder.INBOX_SUB;
}
if (type == null && fullName.startsWith("INBOX" + separator))
type = EntityFolder.INBOX_SUB;
if (selectable) {
String fullName = ifolder.getFullName();
int level = EntityFolder.getLevel(separator, fullName);
EntityFolder folder = db.folder().getFolderByName(account.id, fullName);
if (folder == null) {
@ -1964,7 +1968,6 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().insertFolder(folder);
Log.i(Helper.TAG, folder.name + " added");
} else {
names.remove(folder.name);
Log.i(Helper.TAG, folder.name + " exists");
db.folder().setFolderLevel(folder.id, level);
if (EntityFolder.USER.equals(folder.type) &&
@ -1974,11 +1977,10 @@ public class ServiceSynchronize extends LifecycleService {
}
}
Log.i(Helper.TAG, "Create remote count=" + names.size());
Log.i(Helper.TAG, "Delete local count=" + names.size());
for (String name : names) {
Log.i(Helper.TAG, name + " create");
IMAPFolder ifolder = (IMAPFolder) istore.getFolder(name);
ifolder.create(Folder.HOLDS_MESSAGES);
Log.i(Helper.TAG, name + " delete");
db.folder().deleteFolder(account.id, name);
}
db.setTransactionSuccessful();

View File

@ -215,6 +215,7 @@
<string name="title_sync_days_remark">Increasing this value will increase battery and data usage</string>
<string name="title_keep_days">Keep messages (days)</string>
<string name="title_keep_all">Keep all messages</string>
<string name="title_folder_name_missing">Folder name missing</string>
<string name="title_folder_exists">Folder %1$s exists</string>
<string name="title_folder_delete">Permanently delete this folder and any messages it contains?</string>