Improved read only folder support

pull/157/head
M66B 6 years ago
parent beba3b3815
commit 9e5ccb28b9

@ -507,7 +507,7 @@ public class ActivitySetup extends ActivityBase implements FragmentManager.OnBac
// Folders // Folders
JSONArray jfolders = new JSONArray(); JSONArray jfolders = new JSONArray();
for (EntityFolder folder : db.folder().getFolders(account.id, true)) { for (EntityFolder folder : db.folder().getFolders(account.id, false, true)) {
JSONObject jfolder = folder.toJSON(); JSONObject jfolder = folder.toJSON();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

@ -380,7 +380,8 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
popupMenu.getMenu().add(Menu.NONE, R.string.title_synchronize_enabled, 9, R.string.title_synchronize_enabled) popupMenu.getMenu().add(Menu.NONE, R.string.title_synchronize_enabled, 9, R.string.title_synchronize_enabled)
.setCheckable(true).setChecked(folder.synchronize); .setCheckable(true).setChecked(folder.synchronize);
popupMenu.getMenu().add(Menu.NONE, R.string.title_edit_rules, 10, R.string.title_edit_rules); if (!folder.read_only)
popupMenu.getMenu().add(Menu.NONE, R.string.title_edit_rules, 10, R.string.title_edit_rules);
popupMenu.getMenu().add(Menu.NONE, R.string.title_edit_properties, 11, R.string.title_edit_properties); popupMenu.getMenu().add(Menu.NONE, R.string.title_edit_properties, 11, R.string.title_edit_properties);
if (folder.notify && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (folder.notify && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

@ -851,7 +851,9 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
ivFlagged.setImageTintList(ColorStateList.valueOf(flagged > 0 ivFlagged.setImageTintList(ColorStateList.valueOf(flagged > 0
? message.color == null || !Helper.isPro(context) ? message.color == null || !Helper.isPro(context)
? colorAccent : message.color : textColorSecondary)); ? colorAccent : message.color : textColorSecondary));
ivFlagged.setVisibility(flags ? (message.uid == null ? View.INVISIBLE : View.VISIBLE) : View.GONE); ivFlagged.setVisibility(flags && !message.folderReadOnly
? message.uid == null ? View.INVISIBLE : View.VISIBLE
: View.GONE);
} }
private void bindContactInfo(ContactInfo info, TupleMessageEx message) { private void bindContactInfo(ContactInfo info, TupleMessageEx message) {
@ -1064,25 +1066,27 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
bnvActions.getMenu().findItem(R.id.action_more).setVisible(!inOutbox); bnvActions.getMenu().findItem(R.id.action_more).setVisible(!inOutbox);
bnvActions.getMenu().findItem(R.id.action_delete).setVisible(debug || if (!message.folderReadOnly) {
(inTrash && (message.uid != null || message.msgid != null)) || bnvActions.getMenu().findItem(R.id.action_delete).setVisible(debug ||
(!inTrash && hasTrash && message.uid != null)); (inTrash && (message.uid != null || message.msgid != null)) ||
bnvActions.getMenu().findItem(R.id.action_delete).setTitle( (!inTrash && hasTrash && message.uid != null));
data.delete ? R.string.title_delete : R.string.title_trash); bnvActions.getMenu().findItem(R.id.action_delete).setTitle(
data.delete ? R.string.title_delete : R.string.title_trash);
bnvActions.getMenu().findItem(R.id.action_move).setVisible(
message.uid != null || inOutbox); bnvActions.getMenu().findItem(R.id.action_move).setVisible(
bnvActions.getMenu().findItem(R.id.action_move).setTitle( message.uid != null || inOutbox);
inOutbox ? R.string.title_folder_drafts : R.string.title_move); bnvActions.getMenu().findItem(R.id.action_move).setTitle(
bnvActions.getMenu().findItem(R.id.action_move).setIcon( inOutbox ? R.string.title_folder_drafts : R.string.title_move);
inOutbox ? R.drawable.baseline_drafts_24 : R.drawable.baseline_folder_24); bnvActions.getMenu().findItem(R.id.action_move).setIcon(
inOutbox ? R.drawable.baseline_drafts_24 : R.drawable.baseline_folder_24);
bnvActions.getMenu().findItem(R.id.action_archive).setVisible(
message.uid != null && (inJunk || (!inArchive && hasArchive))); bnvActions.getMenu().findItem(R.id.action_archive).setVisible(
bnvActions.getMenu().findItem(R.id.action_archive).setTitle( message.uid != null && (inJunk || (!inArchive && hasArchive)));
inJunk ? R.string.title_folder_inbox : R.string.title_archive); bnvActions.getMenu().findItem(R.id.action_archive).setTitle(
bnvActions.getMenu().findItem(R.id.action_archive).setIcon( inJunk ? R.string.title_folder_inbox : R.string.title_archive);
inJunk ? R.drawable.baseline_inbox_24 : R.drawable.baseline_archive_24); bnvActions.getMenu().findItem(R.id.action_archive).setIcon(
inJunk ? R.drawable.baseline_inbox_24 : R.drawable.baseline_archive_24);
}
bnvActions.getMenu().findItem(R.id.action_reply).setEnabled(message.content); bnvActions.getMenu().findItem(R.id.action_reply).setEnabled(message.content);
bnvActions.getMenu().findItem(R.id.action_reply).setVisible(!inOutbox); bnvActions.getMenu().findItem(R.id.action_reply).setVisible(!inOutbox);
@ -1435,7 +1439,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean doubletap = prefs.getBoolean("doubletap", false); boolean doubletap = prefs.getBoolean("doubletap", false);
if (!doubletap || EntityFolder.OUTBOX.equals(message.folderType)) { if (!doubletap || message.folderReadOnly || EntityFolder.OUTBOX.equals(message.folderType)) {
lbm.sendBroadcast(viewThread); lbm.sendBroadcast(viewThread);
return; return;
} }
@ -1493,7 +1497,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
@Override @Override
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
final TupleMessageEx message = getMessage(); final TupleMessageEx message = getMessage();
if (message == null) if (message == null || message.folderReadOnly)
return false; return false;
if (view.getId() == R.id.ivFlagged) { if (view.getId() == R.id.ivFlagged) {
@ -2528,13 +2532,13 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
popupMenu.getMenu().findItem(R.id.menu_forward).setEnabled(data.message.content); popupMenu.getMenu().findItem(R.id.menu_forward).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_unseen).setEnabled(data.message.uid != null); popupMenu.getMenu().findItem(R.id.menu_unseen).setEnabled(data.message.uid != null && !data.message.folderReadOnly);
popupMenu.getMenu().findItem(R.id.menu_flag_color).setEnabled(data.message.uid != null); popupMenu.getMenu().findItem(R.id.menu_flag_color).setEnabled(data.message.uid != null && !data.message.folderReadOnly);
popupMenu.getMenu().findItem(R.id.menu_copy).setEnabled(data.message.uid != null); popupMenu.getMenu().findItem(R.id.menu_copy).setEnabled(data.message.uid != null && !data.message.folderReadOnly);
popupMenu.getMenu().findItem(R.id.menu_delete).setVisible(debug); popupMenu.getMenu().findItem(R.id.menu_delete).setVisible(debug);
popupMenu.getMenu().findItem(R.id.menu_junk).setEnabled(data.message.uid != null); popupMenu.getMenu().findItem(R.id.menu_junk).setEnabled(data.message.uid != null && !data.message.folderReadOnly);
popupMenu.getMenu().findItem(R.id.menu_junk).setVisible( popupMenu.getMenu().findItem(R.id.menu_junk).setVisible(
data.hasJunk && !EntityFolder.JUNK.equals(data.message.folderType)); data.hasJunk && !EntityFolder.JUNK.equals(data.message.folderType));
@ -2550,7 +2554,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
popupMenu.getMenu().findItem(R.id.menu_raw).setTitle( popupMenu.getMenu().findItem(R.id.menu_raw).setTitle(
data.message.raw == null || !data.message.raw ? R.string.title_raw_download : R.string.title_raw_save); data.message.raw == null || !data.message.raw ? R.string.title_raw_download : R.string.title_raw_save);
popupMenu.getMenu().findItem(R.id.menu_manage_keywords).setEnabled(data.message.uid != null); popupMenu.getMenu().findItem(R.id.menu_manage_keywords).setEnabled(data.message.uid != null && !data.message.folderReadOnly);
popupMenu.getMenu().findItem(R.id.menu_decrypt).setEnabled( popupMenu.getMenu().findItem(R.id.menu_decrypt).setEnabled(
data.message.content && data.message.to != null && data.message.to.length > 0); data.message.content && data.message.to != null && data.message.to.length > 0);

@ -783,7 +783,7 @@ class Core {
// Get folder names // Get folder names
Map<String, EntityFolder> local = new HashMap<>(); Map<String, EntityFolder> local = new HashMap<>();
for (EntityFolder folder : db.folder().getFolders(account.id, true)) for (EntityFolder folder : db.folder().getFolders(account.id, false, false))
if (folder.tbc != null) { if (folder.tbc != null) {
Log.i(folder.name + " creating"); Log.i(folder.name + " creating");
Folder ifolder = istore.getFolder(folder.name); Folder ifolder = istore.getFolder(folder.name);

@ -30,8 +30,9 @@ import java.util.List;
public interface DaoFolder { public interface DaoFolder {
@Query("SELECT * FROM folder" + @Query("SELECT * FROM folder" +
" WHERE account = :account" + " WHERE account = :account" +
" AND (NOT :writable OR NOT read_only)" +
" AND (NOT :selectable OR selectable)") " AND (NOT :selectable OR selectable)")
List<EntityFolder> getFolders(long account, boolean selectable); List<EntityFolder> getFolders(long account, boolean writable, boolean selectable);
@Query("SELECT folder.*" + @Query("SELECT folder.*" +
", account.id AS accountId, account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor, account.state AS accountState" + ", account.id AS accountId, account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +

@ -43,7 +43,7 @@ public interface DaoMessage {
@Query("SELECT message.*" + @Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" + ", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType, folder.read_only AS folderReadOnly" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" + ", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", COUNT(message.id) AS count" + ", COUNT(message.id) AS count" +
", " + unseen_unified + " AS unseen" + ", " + unseen_unified + " AS unseen" +
@ -89,7 +89,7 @@ public interface DaoMessage {
@Query("SELECT message.*" + @Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" + ", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType, folder.read_only AS folderReadOnly" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" + ", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", COUNT(message.id) AS count" + ", COUNT(message.id) AS count" +
", " + unseen_folder + " AS unseen" + ", " + unseen_folder + " AS unseen" +
@ -132,7 +132,7 @@ public interface DaoMessage {
@Query("SELECT message.*" + @Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" + ", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType, folder.read_only AS folderReadOnly" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" + ", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", 1 AS count" + ", 1 AS count" +
", CASE WHEN message.ui_seen THEN 0 ELSE 1 END AS unseen" + ", CASE WHEN message.ui_seen THEN 0 ELSE 1 END AS unseen" +
@ -244,7 +244,7 @@ public interface DaoMessage {
@Query("SELECT message.*" + @Query("SELECT message.*" +
", account.name AS accountName, identity.color AS accountColor, account.notify AS accountNotify" + ", account.name AS accountName, identity.color AS accountColor, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType, folder.read_only AS folderReadOnly" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" + ", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", 1 AS count" + ", 1 AS count" +
", CASE WHEN message.ui_seen THEN 0 ELSE 1 END AS unseen" + ", CASE WHEN message.ui_seen THEN 0 ELSE 1 END AS unseen" +
@ -262,7 +262,7 @@ public interface DaoMessage {
@Query("SELECT message.*" + @Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" + ", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" + ", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType, folder.read_only AS folderReadOnly" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" + ", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", 1 AS count" + ", 1 AS count" +
", 1 AS unseen" + ", 1 AS unseen" +

@ -1215,7 +1215,7 @@ public class FragmentAccount extends FragmentBase {
long account = args.getLong("account"); long account = args.getLong("account");
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
List<EntityFolder> folders = db.folder().getFolders(account, true); List<EntityFolder> folders = db.folder().getFolders(account, false, true);
if (folders != null && folders.size() > 0) if (folders != null && folders.size() > 0)
Collections.sort(folders, folders.get(0).getComparator(null)); Collections.sort(folders, folders.get(0).getComparator(null));

@ -1196,6 +1196,9 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (message == null) if (message == null)
return 0; return 0;
if (message.folderReadOnly)
return 0;
if (EntityFolder.OUTBOX.equals(message.folderType)) if (EntityFolder.OUTBOX.equals(message.folderType))
return 0; return 0;
@ -2846,7 +2849,9 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
boolean archivable = false; boolean archivable = false;
for (EntityMessage message : messages) { for (EntityMessage message : messages) {
EntityFolder folder = db.folder().getFolder(message.folder); EntityFolder folder = db.folder().getFolder(message.folder);
if (!EntityFolder.DRAFTS.equals(folder.type) &&
if (!folder.read_only &&
!EntityFolder.DRAFTS.equals(folder.type) &&
!EntityFolder.OUTBOX.equals(folder.type) && !EntityFolder.OUTBOX.equals(folder.type) &&
// allow sent // allow sent
!EntityFolder.TRASH.equals(folder.type) && !EntityFolder.TRASH.equals(folder.type) &&
@ -2856,7 +2861,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (!EntityFolder.OUTBOX.equals(folder.type)) if (!EntityFolder.OUTBOX.equals(folder.type))
snoozable = true; snoozable = true;
if (!EntityFolder.isOutgoing(folder.type) && if (!folder.read_only &&
!EntityFolder.isOutgoing(folder.type) &&
!EntityFolder.TRASH.equals(folder.type) && !EntityFolder.TRASH.equals(folder.type) &&
!EntityFolder.JUNK.equals(folder.type) && !EntityFolder.JUNK.equals(folder.type) &&
!EntityFolder.ARCHIVE.equals(folder.type)) !EntityFolder.ARCHIVE.equals(folder.type))
@ -2912,10 +2918,14 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (message == null) if (message == null)
return null; return null;
EntityFolder folder = db.folder().getFolder(message.folder);
if (folder == null)
return null;
if (message.uid != null) { if (message.uid != null) {
if (!message.content) if (!message.content)
EntityOperation.queue(context, message, EntityOperation.BODY); EntityOperation.queue(context, message, EntityOperation.BODY);
if (!message.ui_seen) if (!message.ui_seen && !folder.read_only)
EntityOperation.queue(context, message, EntityOperation.SEEN, true); EntityOperation.queue(context, message, EntityOperation.SEEN, true);
} }

@ -372,7 +372,7 @@ public class FragmentRule extends FragmentBase {
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
data.folder = db.folder().getFolder(fid); data.folder = db.folder().getFolder(fid);
data.folders = db.folder().getFolders(aid, true); data.folders = db.folder().getFolders(aid, true, true);
if (data.folders == null) if (data.folders == null)
data.folders = new ArrayList<>(); data.folders = new ArrayList<>();

@ -46,7 +46,7 @@ public class SelectionPredicateMessage extends SelectionTracker.SelectionPredica
if (message == null) // happens when restoring state if (message == null) // happens when restoring state
return true; return true;
if (message.uid != null) if (message.uid != null && !message.folderReadOnly)
return true; return true;
return false; return false;
@ -62,7 +62,7 @@ public class SelectionPredicateMessage extends SelectionTracker.SelectionPredica
if (message == null) // happens when restoring state if (message == null) // happens when restoring state
return true; return true;
if (message.uid != null) if (message.uid != null && !message.folderReadOnly)
return true; return true;
return false; return false;

@ -739,7 +739,7 @@ public class ServiceSynchronize extends LifecycleService {
// Open synchronizing folders // Open synchronizing folders
final ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory); final ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
List<EntityFolder> folders = db.folder().getFolders(account.id, true); List<EntityFolder> folders = db.folder().getFolders(account.id, false, true);
Collections.sort(folders, new Comparator<EntityFolder>() { Collections.sort(folders, new Comparator<EntityFolder>() {
@Override @Override
public int compare(EntityFolder f1, EntityFolder f2) { public int compare(EntityFolder f1, EntityFolder f2) {
@ -761,13 +761,12 @@ public class ServiceSynchronize extends LifecycleService {
final IMAPFolder ifolder = (IMAPFolder) istore.getFolder(folder.name); final IMAPFolder ifolder = (IMAPFolder) istore.getFolder(folder.name);
try { try {
//if ("Postausgang".equals(folder.name)) if (BuildConfig.DEBUG && "Postausgang".equals(folder.name))
// throw new ReadOnlyFolderException(ifolder); throw new ReadOnlyFolderException(ifolder);
ifolder.open(Folder.READ_WRITE); ifolder.open(Folder.READ_WRITE);
db.folder().setFolderReadOnly(folder.id, false); db.folder().setFolderReadOnly(folder.id, false);
} catch (ReadOnlyFolderException ex) { } catch (ReadOnlyFolderException ex) {
Log.w(folder.name + " read only"); Log.w(folder.name + " read only");
db.folder().setFolderError(folder.id, Helper.formatThrowable(ex));
try { try {
ifolder.open(Folder.READ_ONLY); ifolder.open(Folder.READ_ONLY);
db.folder().setFolderReadOnly(folder.id, true); db.folder().setFolderReadOnly(folder.id, true);

@ -30,6 +30,7 @@ public class TupleMessageEx extends EntityMessage {
public String folderName; public String folderName;
public String folderDisplay; public String folderDisplay;
public String folderType; public String folderType;
public boolean folderReadOnly;
public String identityName; public String identityName;
public String identityEmail; public String identityEmail;
public Boolean identitySynchronize; public Boolean identitySynchronize;
@ -40,6 +41,7 @@ public class TupleMessageEx extends EntityMessage {
public int drafts; public int drafts;
public int visible; public int visible;
public Long totalSize; public Long totalSize;
@Ignore @Ignore
public boolean duplicate; public boolean duplicate;
@ -54,6 +56,7 @@ public class TupleMessageEx extends EntityMessage {
this.folderName.equals(other.folderName) && this.folderName.equals(other.folderName) &&
Objects.equals(this.folderDisplay, other.folderDisplay) && Objects.equals(this.folderDisplay, other.folderDisplay) &&
this.folderType.equals(other.folderType) && this.folderType.equals(other.folderType) &&
this.folderReadOnly == other.folderReadOnly &&
Objects.equals(this.identityName, other.identityName) && Objects.equals(this.identityName, other.identityName) &&
Objects.equals(this.identityEmail, other.identityEmail) && Objects.equals(this.identityEmail, other.identityEmail) &&
Objects.equals(this.identitySynchronize, other.identitySynchronize) && Objects.equals(this.identitySynchronize, other.identitySynchronize) &&

Loading…
Cancel
Save