mirror of
https://github.com/M66B/FairEmail.git
synced 2025-03-15 16:39:37 +00:00
Added option to set poll interval per folder
This commit is contained in:
parent
703d8af6e8
commit
11e9333f14
9 changed files with 1063 additions and 11 deletions
1000
app/schemas/eu.faircode.email.DB/20.json
Normal file
1000
app/schemas/eu.faircode.email.DB/20.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -45,7 +45,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||||
// https://developer.android.com/topic/libraries/architecture/room.html
|
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 19,
|
version = 20,
|
||||||
entities = {
|
entities = {
|
||||||
EntityIdentity.class,
|
EntityIdentity.class,
|
||||||
EntityAccount.class,
|
EntityAccount.class,
|
||||||
|
@ -250,6 +250,13 @@ public abstract class DB extends RoomDatabase {
|
||||||
db.execSQL("ALTER TABLE `folder` ADD COLUMN `hide` INTEGER NOT NULL DEFAULT 0");
|
db.execSQL("ALTER TABLE `folder` ADD COLUMN `hide` INTEGER NOT NULL DEFAULT 0");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.addMigrations(new Migration(19, 20) {
|
||||||
|
@Override
|
||||||
|
public void migrate(SupportSQLiteDatabase db) {
|
||||||
|
Log.i(Helper.TAG, "DB migration from version " + startVersion + " to " + endVersion);
|
||||||
|
db.execSQL("ALTER TABLE `folder` ADD COLUMN `poll_interval` INTEGER");
|
||||||
|
}
|
||||||
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,8 +124,9 @@ public interface DaoFolder {
|
||||||
", synchronize = :synchronize" +
|
", synchronize = :synchronize" +
|
||||||
", unified = :unified" +
|
", unified = :unified" +
|
||||||
", `after` = :after" +
|
", `after` = :after" +
|
||||||
|
", `poll_interval` = :poll_interval" +
|
||||||
" WHERE id = :id")
|
" WHERE id = :id")
|
||||||
int setFolderProperties(long id, String name, String display, boolean hide, boolean synchronize, boolean unified, int after);
|
int setFolderProperties(long id, String name, String display, boolean hide, boolean synchronize, boolean unified, int after, Integer poll_interval);
|
||||||
|
|
||||||
@Query("UPDATE folder SET name = :name WHERE account = :account AND name = :old")
|
@Query("UPDATE folder SET name = :name WHERE account = :account AND name = :old")
|
||||||
int renameFolder(long account, String old, String name);
|
int renameFolder(long account, String old, String name);
|
||||||
|
|
|
@ -62,6 +62,7 @@ public class EntityFolder implements Parcelable {
|
||||||
public String type;
|
public String type;
|
||||||
@NonNull
|
@NonNull
|
||||||
public Boolean synchronize;
|
public Boolean synchronize;
|
||||||
|
public Integer poll_interval;
|
||||||
@NonNull
|
@NonNull
|
||||||
public Integer after; // days
|
public Integer after; // days
|
||||||
public String display;
|
public String display;
|
||||||
|
|
|
@ -44,6 +44,7 @@ import javax.mail.Session;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.Group;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
|
|
||||||
public class FragmentFolder extends FragmentEx {
|
public class FragmentFolder extends FragmentEx {
|
||||||
|
@ -54,10 +55,12 @@ public class FragmentFolder extends FragmentEx {
|
||||||
private CheckBox cbSynchronize;
|
private CheckBox cbSynchronize;
|
||||||
private CheckBox cbUnified;
|
private CheckBox cbUnified;
|
||||||
private EditText etAfter;
|
private EditText etAfter;
|
||||||
|
private EditText etInterval;
|
||||||
private Button btnSave;
|
private Button btnSave;
|
||||||
private ImageButton ibDelete;
|
private ImageButton ibDelete;
|
||||||
private ProgressBar pbSave;
|
private ProgressBar pbSave;
|
||||||
private ProgressBar pbWait;
|
private ProgressBar pbWait;
|
||||||
|
private Group grpInterval;
|
||||||
|
|
||||||
private long id = -1;
|
private long id = -1;
|
||||||
private long account = -1;
|
private long account = -1;
|
||||||
|
@ -86,10 +89,12 @@ public class FragmentFolder extends FragmentEx {
|
||||||
cbSynchronize = view.findViewById(R.id.cbSynchronize);
|
cbSynchronize = view.findViewById(R.id.cbSynchronize);
|
||||||
cbUnified = view.findViewById(R.id.cbUnified);
|
cbUnified = view.findViewById(R.id.cbUnified);
|
||||||
etAfter = view.findViewById(R.id.etAfter);
|
etAfter = view.findViewById(R.id.etAfter);
|
||||||
|
etInterval = view.findViewById(R.id.etInterval);
|
||||||
btnSave = view.findViewById(R.id.btnSave);
|
btnSave = view.findViewById(R.id.btnSave);
|
||||||
ibDelete = view.findViewById(R.id.ibDelete);
|
ibDelete = view.findViewById(R.id.ibDelete);
|
||||||
pbSave = view.findViewById(R.id.pbSave);
|
pbSave = view.findViewById(R.id.pbSave);
|
||||||
pbWait = view.findViewById(R.id.pbWait);
|
pbWait = view.findViewById(R.id.pbWait);
|
||||||
|
grpInterval = view.findViewById(R.id.grpInterval);
|
||||||
|
|
||||||
btnSave.setOnClickListener(new View.OnClickListener() {
|
btnSave.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -108,6 +113,7 @@ public class FragmentFolder extends FragmentEx {
|
||||||
args.putBoolean("unified", cbUnified.isChecked());
|
args.putBoolean("unified", cbUnified.isChecked());
|
||||||
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
args.putBoolean("synchronize", cbSynchronize.isChecked());
|
||||||
args.putString("after", etAfter.getText().toString());
|
args.putString("after", etAfter.getText().toString());
|
||||||
|
args.putString("interval", etInterval.getText().toString());
|
||||||
|
|
||||||
new SimpleTask<Void>() {
|
new SimpleTask<Void>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,10 +126,12 @@ public class FragmentFolder extends FragmentEx {
|
||||||
boolean unified = args.getBoolean("unified");
|
boolean unified = args.getBoolean("unified");
|
||||||
boolean synchronize = args.getBoolean("synchronize");
|
boolean synchronize = args.getBoolean("synchronize");
|
||||||
String after = args.getString("after");
|
String after = args.getString("after");
|
||||||
|
String interval = args.getString("interval");
|
||||||
|
|
||||||
if (TextUtils.isEmpty(display) || display.equals(name))
|
if (TextUtils.isEmpty(display) || display.equals(name))
|
||||||
display = null;
|
display = null;
|
||||||
int days = (TextUtils.isEmpty(after) ? EntityFolder.DEFAULT_USER_SYNC : Integer.parseInt(after));
|
int days = (TextUtils.isEmpty(after) ? EntityFolder.DEFAULT_USER_SYNC : Integer.parseInt(after));
|
||||||
|
Integer poll_interval = (TextUtils.isEmpty(interval) ? null : Integer.parseInt(interval));
|
||||||
|
|
||||||
IMAPStore istore = null;
|
IMAPStore istore = null;
|
||||||
DB db = DB.getInstance(getContext());
|
DB db = DB.getInstance(getContext());
|
||||||
|
@ -157,6 +165,7 @@ public class FragmentFolder extends FragmentEx {
|
||||||
create.unified = unified;
|
create.unified = unified;
|
||||||
create.synchronize = synchronize;
|
create.synchronize = synchronize;
|
||||||
create.after = days;
|
create.after = days;
|
||||||
|
create.poll_interval = poll_interval;
|
||||||
db.folder().insertFolder(create);
|
db.folder().insertFolder(create);
|
||||||
} else {
|
} else {
|
||||||
Log.i(Helper.TAG, "Renaming folder=" + name);
|
Log.i(Helper.TAG, "Renaming folder=" + name);
|
||||||
|
@ -171,7 +180,7 @@ public class FragmentFolder extends FragmentEx {
|
||||||
|
|
||||||
if (folder != null) {
|
if (folder != null) {
|
||||||
Log.i(Helper.TAG, "Updating folder=" + name);
|
Log.i(Helper.TAG, "Updating folder=" + name);
|
||||||
db.folder().setFolderProperties(id, name, display, hide, synchronize, unified, days);
|
db.folder().setFolderProperties(id, name, display, hide, synchronize, unified, days, poll_interval);
|
||||||
if (!synchronize)
|
if (!synchronize)
|
||||||
db.folder().setFolderError(id, null);
|
db.folder().setFolderError(id, null);
|
||||||
}
|
}
|
||||||
|
@ -294,6 +303,7 @@ public class FragmentFolder extends FragmentEx {
|
||||||
ibDelete.setVisibility(View.GONE);
|
ibDelete.setVisibility(View.GONE);
|
||||||
pbSave.setVisibility(View.GONE);
|
pbSave.setVisibility(View.GONE);
|
||||||
pbWait.setVisibility(View.VISIBLE);
|
pbWait.setVisibility(View.VISIBLE);
|
||||||
|
grpInterval.setVisibility(View.GONE);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@ -320,12 +330,14 @@ public class FragmentFolder extends FragmentEx {
|
||||||
cbUnified.setChecked(folder == null ? false : folder.unified);
|
cbUnified.setChecked(folder == null ? false : folder.unified);
|
||||||
cbSynchronize.setChecked(folder == null || folder.synchronize);
|
cbSynchronize.setChecked(folder == null || folder.synchronize);
|
||||||
etAfter.setText(Integer.toString(folder == null ? EntityFolder.DEFAULT_USER_SYNC : folder.after));
|
etAfter.setText(Integer.toString(folder == null ? EntityFolder.DEFAULT_USER_SYNC : folder.after));
|
||||||
|
etInterval.setText(folder == null || folder.poll_interval == null ? null : Integer.toString(folder.poll_interval));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider previous save as cancelled
|
// Consider previous save as cancelled
|
||||||
pbWait.setVisibility(View.GONE);
|
pbWait.setVisibility(View.GONE);
|
||||||
Helper.setViewsEnabled(view, true);
|
Helper.setViewsEnabled(view, true);
|
||||||
etRename.setEnabled(folder == null || EntityFolder.USER.equals(folder.type));
|
etRename.setEnabled(folder == null || EntityFolder.USER.equals(folder.type));
|
||||||
|
grpInterval.setVisibility(folder == null || EntityFolder.USER.equals(folder.type) ? View.VISIBLE : View.GONE);
|
||||||
btnSave.setEnabled(true);
|
btnSave.setEnabled(true);
|
||||||
ibDelete.setVisibility(folder == null || !EntityFolder.USER.equals(folder.type) ? View.GONE : View.VISIBLE);
|
ibDelete.setVisibility(folder == null || !EntityFolder.USER.equals(folder.type) ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -814,9 +814,8 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
Log.i(Helper.TAG, folder.name + " start noop");
|
Log.i(Helper.TAG, folder.name + " start noop");
|
||||||
while (state.running && ifolder.isOpen()) {
|
while (state.running && ifolder.isOpen()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(account.poll_interval * 60 * 1000L);
|
|
||||||
|
|
||||||
if (!EntityFolder.USER.equals(folder.type) && capIdle) {
|
if (!EntityFolder.USER.equals(folder.type) && capIdle) {
|
||||||
|
Thread.sleep(account.poll_interval * 60 * 1000L);
|
||||||
Log.i(Helper.TAG, folder.name + " request NOOP");
|
Log.i(Helper.TAG, folder.name + " request NOOP");
|
||||||
ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
||||||
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
||||||
|
@ -826,8 +825,13 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else
|
} else {
|
||||||
|
if (folder.poll_interval == null)
|
||||||
|
Thread.sleep(account.poll_interval * 60 * 1000L);
|
||||||
|
else
|
||||||
|
Thread.sleep(folder.poll_interval * 60 * 1000L);
|
||||||
synchronizeMessages(account, folder, ifolder, state);
|
synchronizeMessages(account, folder, ifolder, state);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
Log.w(Helper.TAG, folder.name + " noop " + ex.toString());
|
Log.w(Helper.TAG, folder.name + " noop " + ex.toString());
|
||||||
|
|
|
@ -318,14 +318,14 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/cbSynchronize" />
|
app:layout_constraintTop_toBottomOf="@id/cbSynchronize" />
|
||||||
|
|
||||||
<!-- port -->
|
<!-- keep alive -->
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvInterval"
|
android:id="@+id/tvInterval"
|
||||||
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_poll_interval"
|
android:text="@string/title_keep_alive_interval"
|
||||||
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/cbPrimary" />
|
app:layout_constraintTop_toBottomOf="@id/cbPrimary" />
|
||||||
|
|
|
@ -102,6 +102,26 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvAfter" />
|
app:layout_constraintTop_toBottomOf="@id/tvAfter" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvInterval"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:text="@string/title_poll_interval"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/etAfter" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etInterval"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="9"
|
||||||
|
android:inputType="number"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvInterval" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnSave"
|
android:id="@+id/btnSave"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -109,7 +129,7 @@
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:text="@string/title_save"
|
android:text="@string/title_save"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etAfter" />
|
app:layout_constraintTop_toBottomOf="@id/etInterval" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/ibDelete"
|
android:id="@+id/ibDelete"
|
||||||
|
@ -118,7 +138,7 @@
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:src="@drawable/baseline_delete_24"
|
android:src="@drawable/baseline_delete_24"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/etAfter" />
|
app:layout_constraintTop_toBottomOf="@id/etInterval" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/pbSave"
|
android:id="@+id/pbSave"
|
||||||
|
@ -141,5 +161,11 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Group
|
||||||
|
android:id="@+id/grpInterval"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:constraint_referenced_ids="tvInterval,etInterval" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
|
@ -113,7 +113,7 @@
|
||||||
<string name="title_synchronize_identity">Synchronize (send messages)</string>
|
<string name="title_synchronize_identity">Synchronize (send messages)</string>
|
||||||
<string name="title_primary_account">Primary (default account)</string>
|
<string name="title_primary_account">Primary (default account)</string>
|
||||||
<string name="title_primary_identity">Primary (default identity)</string>
|
<string name="title_primary_identity">Primary (default identity)</string>
|
||||||
<string name="title_poll_interval">Poll interval (minutes)</string>
|
<string name="title_keep_alive_interval">Keep alive interval (minutes)</string>
|
||||||
<string name="title_check">Check</string>
|
<string name="title_check">Check</string>
|
||||||
<string name="title_no_name">Name missing</string>
|
<string name="title_no_name">Name missing</string>
|
||||||
<string name="title_no_email">Email address missing</string>
|
<string name="title_no_email">Email address missing</string>
|
||||||
|
@ -147,6 +147,7 @@
|
||||||
<string name="title_synchronize_folder">Synchronize (receive messages)</string>
|
<string name="title_synchronize_folder">Synchronize (receive messages)</string>
|
||||||
<string name="title_unified_folder">Show in unified inbox</string>
|
<string name="title_unified_folder">Show in unified inbox</string>
|
||||||
<string name="title_after">Synchronize (days)</string>
|
<string name="title_after">Synchronize (days)</string>
|
||||||
|
<string name="title_poll_interval">Poll interval (minutes)</string>
|
||||||
<string name="title_folder_exists">Folder %1$s exists</string>
|
<string name="title_folder_exists">Folder %1$s exists</string>
|
||||||
<string name="title_folder_delete">Delete folder permanently?</string>
|
<string name="title_folder_delete">Delete folder permanently?</string>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue