Added folder setting to disable automatically downloading of message texts and attachments

pull/147/head
M66B 6 years ago
parent ae9d35c084
commit e49d09ab9c

File diff suppressed because it is too large Load Diff

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

@ -167,17 +167,18 @@ public interface DaoFolder {
" SET name = :name" + " SET name = :name" +
", display = :display" + ", display = :display" +
", unified = :unified" + ", unified = :unified" +
", notify = :notify" +
", hide = :hide" + ", hide = :hide" +
", synchronize = :synchronize" + ", synchronize = :synchronize" +
", poll = :poll" + ", poll = :poll" +
", notify = :notify" + ", download = :download" +
", `sync_days` = :sync_days" + ", `sync_days` = :sync_days" +
", `keep_days` = :keep_days" + ", `keep_days` = :keep_days" +
" WHERE id = :id") " WHERE id = :id")
int setFolderProperties( int setFolderProperties(
long id, long id,
String name, String display, boolean unified, boolean hide, String name, String display, boolean unified, boolean notify, boolean hide,
boolean synchronize, boolean poll, boolean notify, boolean synchronize, boolean poll, boolean download,
int sync_days, int keep_days); int sync_days, int keep_days);
@Query("UPDATE folder SET keywords = :keywords WHERE id = :id") @Query("UPDATE folder SET keywords = :keywords WHERE id = :id")

@ -71,6 +71,8 @@ public class EntityFolder implements Serializable {
@NonNull @NonNull
public Boolean poll = false; public Boolean poll = false;
@NonNull @NonNull
public Boolean download = true;
@NonNull
public Integer sync_days; public Integer sync_days;
@NonNull @NonNull
public Integer keep_days; public Integer keep_days;

@ -50,9 +50,10 @@ public class FragmentFolder extends FragmentEx {
private EditText etDisplay; private EditText etDisplay;
private CheckBox cbHide; private CheckBox cbHide;
private CheckBox cbUnified; private CheckBox cbUnified;
private CheckBox cbNotify;
private CheckBox cbSynchronize; private CheckBox cbSynchronize;
private CheckBox cbPoll; private CheckBox cbPoll;
private CheckBox cbNotify; private CheckBox cbDownload;
private EditText etSyncDays; private EditText etSyncDays;
private EditText etKeepDays; private EditText etKeepDays;
private CheckBox cbKeepAll; private CheckBox cbKeepAll;
@ -86,9 +87,10 @@ public class FragmentFolder extends FragmentEx {
etDisplay = view.findViewById(R.id.etDisplay); etDisplay = view.findViewById(R.id.etDisplay);
cbHide = view.findViewById(R.id.cbHide); cbHide = view.findViewById(R.id.cbHide);
cbUnified = view.findViewById(R.id.cbUnified); cbUnified = view.findViewById(R.id.cbUnified);
cbNotify = view.findViewById(R.id.cbNotify);
cbSynchronize = view.findViewById(R.id.cbSynchronize); cbSynchronize = view.findViewById(R.id.cbSynchronize);
cbPoll = view.findViewById(R.id.cbPoll); cbPoll = view.findViewById(R.id.cbPoll);
cbNotify = view.findViewById(R.id.cbNotify); cbDownload = view.findViewById(R.id.cbDownload);
etSyncDays = view.findViewById(R.id.etSyncDays); etSyncDays = view.findViewById(R.id.etSyncDays);
etKeepDays = view.findViewById(R.id.etKeepDays); etKeepDays = view.findViewById(R.id.etKeepDays);
cbKeepAll = view.findViewById(R.id.cbKeepAll); cbKeepAll = view.findViewById(R.id.cbKeepAll);
@ -104,17 +106,16 @@ public class FragmentFolder extends FragmentEx {
} }
}); });
// Navigating to individual messages requires notification grouping
cbNotify.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? View.VISIBLE : View.GONE);
cbSynchronize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { cbSynchronize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
cbPoll.setEnabled(isChecked); cbPoll.setEnabled(isChecked);
cbNotify.setEnabled(isChecked);
} }
}); });
// Navigating to individual messages requires notification grouping
cbNotify.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? View.VISIBLE : View.GONE);
cbKeepAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { cbKeepAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@ -136,9 +137,10 @@ public class FragmentFolder extends FragmentEx {
args.putString("display", etDisplay.getText().toString()); args.putString("display", etDisplay.getText().toString());
args.putBoolean("hide", cbHide.isChecked()); args.putBoolean("hide", cbHide.isChecked());
args.putBoolean("unified", cbUnified.isChecked()); args.putBoolean("unified", cbUnified.isChecked());
args.putBoolean("notify", cbNotify.getVisibility() == View.VISIBLE && cbNotify.isChecked());
args.putBoolean("synchronize", cbSynchronize.isChecked()); args.putBoolean("synchronize", cbSynchronize.isChecked());
args.putBoolean("poll", cbPoll.isChecked()); args.putBoolean("poll", cbPoll.isChecked());
args.putBoolean("notify", cbNotify.getVisibility() == View.VISIBLE && cbNotify.isChecked()); args.putBoolean("download", cbDownload.isChecked());
args.putString("sync", etSyncDays.getText().toString()); args.putString("sync", etSyncDays.getText().toString());
args.putString("keep", cbKeepAll.isChecked() args.putString("keep", cbKeepAll.isChecked()
? Integer.toString(Integer.MAX_VALUE) ? Integer.toString(Integer.MAX_VALUE)
@ -153,9 +155,10 @@ public class FragmentFolder extends FragmentEx {
String display = args.getString("display"); String display = args.getString("display");
boolean hide = args.getBoolean("hide"); boolean hide = args.getBoolean("hide");
boolean unified = args.getBoolean("unified"); boolean unified = args.getBoolean("unified");
boolean notify = args.getBoolean("notify");
boolean synchronize = args.getBoolean("synchronize"); boolean synchronize = args.getBoolean("synchronize");
boolean poll = args.getBoolean("poll"); boolean poll = args.getBoolean("poll");
boolean notify = args.getBoolean("notify"); boolean download = args.getBoolean("download");
String sync = args.getString("sync"); String sync = args.getString("sync");
String keep = args.getString("keep"); String keep = args.getString("keep");
@ -185,14 +188,17 @@ public class FragmentFolder extends FragmentEx {
create.hide = hide; create.hide = hide;
create.type = EntityFolder.USER; create.type = EntityFolder.USER;
create.unified = unified; create.unified = unified;
create.notify = notify;
create.synchronize = synchronize; create.synchronize = synchronize;
create.poll = poll; create.poll = poll;
create.notify = notify; create.download = download;
create.sync_days = sync_days; create.sync_days = sync_days;
create.keep_days = keep_days; create.keep_days = keep_days;
db.folder().insertFolder(create); db.folder().insertFolder(create);
} else { } else {
reload = (!folder.synchronize.equals(synchronize) || !folder.poll.equals(poll)); reload = (!folder.synchronize.equals(synchronize) ||
!folder.poll.equals(poll) ||
!folder.download.equals(download));
Calendar cal_keep = Calendar.getInstance(); Calendar cal_keep = Calendar.getInstance();
cal_keep.add(Calendar.DAY_OF_MONTH, -keep_days); cal_keep.add(Calendar.DAY_OF_MONTH, -keep_days);
@ -207,8 +213,8 @@ public class FragmentFolder extends FragmentEx {
Log.i(Helper.TAG, "Updating folder=" + name); Log.i(Helper.TAG, "Updating folder=" + name);
db.folder().setFolderProperties(id, db.folder().setFolderProperties(id,
name, display, unified, hide, name, display, unified, hide, notify,
synchronize, poll, notify, synchronize, poll, download,
sync_days, keep_days); sync_days, keep_days);
db.message().deleteMessagesBefore(id, keep_time, true); db.message().deleteMessagesBefore(id, keep_time, true);
@ -358,9 +364,10 @@ public class FragmentFolder extends FragmentEx {
etDisplay.setHint(folder == null ? null : folder.name); etDisplay.setHint(folder == null ? null : folder.name);
cbHide.setChecked(folder == null ? false : folder.hide); cbHide.setChecked(folder == null ? false : folder.hide);
cbUnified.setChecked(folder == null ? false : folder.unified); cbUnified.setChecked(folder == null ? false : folder.unified);
cbNotify.setChecked(folder == null ? false : folder.notify);
cbSynchronize.setChecked(folder == null || folder.synchronize); cbSynchronize.setChecked(folder == null || folder.synchronize);
cbPoll.setChecked(folder == null ? false : folder.poll); cbPoll.setChecked(folder == null ? false : folder.poll);
cbNotify.setChecked(folder == null ? false : folder.notify); cbDownload.setChecked(folder == null ? true : folder.download);
etSyncDays.setText(Integer.toString(folder == null ? EntityFolder.DEFAULT_SYNC : folder.sync_days)); etSyncDays.setText(Integer.toString(folder == null ? EntityFolder.DEFAULT_SYNC : folder.sync_days));
if (folder != null && folder.keep_days == Integer.MAX_VALUE) if (folder != null && folder.keep_days == Integer.MAX_VALUE)
cbKeepAll.setChecked(true); cbKeepAll.setChecked(true);

@ -987,17 +987,19 @@ public class ServiceSynchronize extends LifecycleService {
db.endTransaction(); db.endTransaction();
} }
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this); if (folder.download) {
boolean metered = (isMetered == null || isMetered); Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
boolean metered = (isMetered == null || isMetered);
try { try {
db.beginTransaction(); db.beginTransaction();
downloadMessage( downloadMessage(
ServiceSynchronize.this, metered, ServiceSynchronize.this, metered,
folder, ifolder, (IMAPMessage) imessage, message.id); folder, ifolder, (IMAPMessage) imessage, message.id);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
}
} }
} catch (MessageRemovedException ex) { } catch (MessageRemovedException ex) {
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
@ -1071,17 +1073,19 @@ public class ServiceSynchronize extends LifecycleService {
db.endTransaction(); db.endTransaction();
} }
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this); if (folder.download) {
boolean metered = (isMetered == null || isMetered); Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
boolean metered = (isMetered == null || isMetered);
try { try {
db.beginTransaction(); db.beginTransaction();
downloadMessage( downloadMessage(
ServiceSynchronize.this, metered, ServiceSynchronize.this, metered,
folder, ifolder, (IMAPMessage) e.getMessage(), message.id); folder, ifolder, (IMAPMessage) e.getMessage(), message.id);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
}
} }
} catch (MessageRemovedException ex) { } catch (MessageRemovedException ex) {
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
@ -2104,46 +2108,48 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderSyncState(folder.id, "downloading"); db.folder().setFolderSyncState(folder.id, "downloading");
//fp.add(IMAPFolder.FetchProfileItem.MESSAGE); if (folder.download) {
//fp.add(IMAPFolder.FetchProfileItem.MESSAGE);
// Download messages/attachments // Download messages/attachments
Log.i(Helper.TAG, folder.name + " download=" + imessages.length); Log.i(Helper.TAG, folder.name + " download=" + imessages.length);
for (int i = imessages.length - 1; i >= 0 && state.running(); i -= DOWNLOAD_BATCH_SIZE) { for (int i = imessages.length - 1; i >= 0 && state.running(); i -= DOWNLOAD_BATCH_SIZE) {
int from = Math.max(0, i - DOWNLOAD_BATCH_SIZE + 1); int from = Math.max(0, i - DOWNLOAD_BATCH_SIZE + 1);
Message[] isub = Arrays.copyOfRange(imessages, from, i + 1); Message[] isub = Arrays.copyOfRange(imessages, from, i + 1);
// Fetch on demand // Fetch on demand
Boolean isMetered = Helper.isMetered(ServiceSynchronize.this); Boolean isMetered = Helper.isMetered(ServiceSynchronize.this);
boolean metered = (isMetered == null || isMetered); boolean metered = (isMetered == null || isMetered);
for (int j = isub.length - 1; j >= 0 && state.running(); j--) for (int j = isub.length - 1; j >= 0 && state.running(); j--)
try { try {
db.beginTransaction(); db.beginTransaction();
if (ids[from + j] != null) { if (ids[from + j] != null) {
downloadMessage( downloadMessage(
this, metered, this, metered,
folder, ifolder, (IMAPMessage) isub[j], ids[from + j]); folder, ifolder, (IMAPMessage) isub[j], ids[from + j]);
Thread.sleep(20); Thread.sleep(20);
}
db.setTransactionSuccessful();
} catch (FolderClosedException ex) {
throw ex;
} catch (FolderClosedIOException ex) {
throw ex;
} catch (Throwable ex) {
Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
} finally {
db.endTransaction();
// Free memory
((IMAPMessage) isub[j]).invalidateHeaders();
} }
db.setTransactionSuccessful();
} catch (FolderClosedException ex) {
throw ex;
} catch (FolderClosedIOException ex) {
throw ex;
} catch (Throwable ex) {
Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
} finally {
db.endTransaction();
// Free memory
((IMAPMessage) isub[j]).invalidateHeaders();
}
if (state.running()) if (state.running())
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
}
} }
if (state.running) if (state.running)

@ -71,6 +71,15 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbHide" /> app:layout_constraintTop_toBottomOf="@id/cbHide" />
<CheckBox
android:id="@+id/cbNotify"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_notify_folder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbUnified" />
<CheckBox <CheckBox
android:id="@+id/cbSynchronize" android:id="@+id/cbSynchronize"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -78,7 +87,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:text="@string/title_synchronize_folder" android:text="@string/title_synchronize_folder"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbUnified" /> app:layout_constraintTop_toBottomOf="@id/cbNotify" />
<CheckBox <CheckBox
android:id="@+id/cbPoll" android:id="@+id/cbPoll"
@ -90,11 +99,11 @@
app:layout_constraintTop_toBottomOf="@id/cbSynchronize" /> app:layout_constraintTop_toBottomOf="@id/cbSynchronize" />
<CheckBox <CheckBox
android:id="@+id/cbNotify" android:id="@+id/cbDownload"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:text="@string/title_notify_folder" android:text="@string/title_download_folder"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbPoll" /> app:layout_constraintTop_toBottomOf="@id/cbPoll" />
@ -108,7 +117,7 @@
android:text="@string/title_sync_days" android:text="@string/title_sync_days"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbNotify" /> app:layout_constraintTop_toBottomOf="@id/cbDownload" />
<TextView <TextView
android:id="@+id/tvSyncDaysRemark" android:id="@+id/tvSyncDaysRemark"

@ -195,6 +195,7 @@
<string name="title_unified_folder">Show in unified inbox</string> <string name="title_unified_folder">Show in unified inbox</string>
<string name="title_synchronize_folder">Synchronize (receive messages)</string> <string name="title_synchronize_folder">Synchronize (receive messages)</string>
<string name="title_poll_folder">Check periodically instead of continuous synchronize</string> <string name="title_poll_folder">Check periodically instead of continuous synchronize</string>
<string name="title_download_folder">Automatically download message texts and attachments</string>
<string name="title_notify_folder">Notify new messages</string> <string name="title_notify_folder">Notify new messages</string>
<string name="title_sync_days">Synchronize messages (days)</string> <string name="title_sync_days">Synchronize messages (days)</string>
<string name="title_sync_days_remark">Increasing this value will increase battery and data usage</string> <string name="title_sync_days_remark">Increasing this value will increase battery and data usage</string>
@ -249,7 +250,7 @@
<string name="title_no_saf">Storage access framework not available</string> <string name="title_no_saf">Storage access framework not available</string>
<string name="title_no_contacts">Contact picker not available</string> <string name="title_no_contacts">Contact picker not available</string>
<string name="title_attachment_saved">Attachment saved</string> <string name="title_attachment_saved">Attachment saved</string>
<string name="title_attachment_unavailable">Some attachments are not downloaded and will not be forwarded, continue?</string> <string name="title_attachment_unavailable">Some attachments are not downloaded and will not be added, continue?</string>
<string name="title_image_unavailable">Some images are not downloaded and will not be added, continue?</string> <string name="title_image_unavailable">Some images are not downloaded and will not be added, continue?</string>
<string name="title_ask_delete">Delete message permanently?</string> <string name="title_ask_delete">Delete message permanently?</string>
<string name="title_ask_delete_selected">Delete selected messages permanently?</string> <string name="title_ask_delete_selected">Delete selected messages permanently?</string>

Loading…
Cancel
Save