diff --git a/app/src/main/java/eu/faircode/email/DaoFolder.java b/app/src/main/java/eu/faircode/email/DaoFolder.java index f91622dcc8..afac6bfdf5 100644 --- a/app/src/main/java/eu/faircode/email/DaoFolder.java +++ b/app/src/main/java/eu/faircode/email/DaoFolder.java @@ -95,8 +95,11 @@ public interface DaoFolder { @Query("UPDATE folder SET type = :type WHERE id = :id") int setFolderType(long id, String type); - @Query("UPDATE folder SET type = '" + EntityFolder.USER + "' WHERE type = :type") - int setFolderUser(String type); + @Query("UPDATE folder" + + " SET type = '" + EntityFolder.USER + "'" + + " WHERE account = :account" + + " AND type = :type") + int setFolderUser(long account, String type); @Query("UPDATE folder SET synchronize = :synchronize, after = :after WHERE id = :id") int setFolderProperties(long id, boolean synchronize, int after); diff --git a/app/src/main/java/eu/faircode/email/EntityFolder.java b/app/src/main/java/eu/faircode/email/EntityFolder.java index 951c829794..d73a5e3a8f 100644 --- a/app/src/main/java/eu/faircode/email/EntityFolder.java +++ b/app/src/main/java/eu/faircode/email/EntityFolder.java @@ -19,7 +19,9 @@ package eu.faircode.email; Copyright 2018 by Marcel Bokhorst (M66B) */ -import java.io.Serializable; +import android.os.Parcel; +import android.os.Parcelable; + import java.util.Arrays; import java.util.List; @@ -43,7 +45,7 @@ import static androidx.room.ForeignKey.CASCADE; @Index(value = {"type"}) } ) -public class EntityFolder implements Serializable { +public class EntityFolder implements Parcelable { static final String TABLE_NAME = "folder"; @PrimaryKey(autoGenerate = true) @@ -106,6 +108,9 @@ public class EntityFolder implements Serializable { SENT ); + public EntityFolder() { + } + @Override public boolean equals(Object obj) { if (obj instanceof EntityFolder) { @@ -125,4 +130,72 @@ public class EntityFolder implements Serializable { public String toString() { return name; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + if (id == null) { + parcel.writeByte((byte) 0); + } else { + parcel.writeByte((byte) 1); + parcel.writeLong(id); + } + if (account == null) { + parcel.writeByte((byte) 0); + } else { + parcel.writeByte((byte) 1); + parcel.writeLong(account); + } + parcel.writeString(name); + parcel.writeString(type); + parcel.writeByte((byte) (synchronize == null ? 0 : synchronize ? 1 : 2)); + if (after == null) { + parcel.writeByte((byte) 0); + } else { + parcel.writeByte((byte) 1); + parcel.writeInt(after); + } + parcel.writeString(state); + parcel.writeString(error); + } + + protected EntityFolder(Parcel in) { + if (in.readByte() == 0) { + id = null; + } else { + id = in.readLong(); + } + if (in.readByte() == 0) { + account = null; + } else { + account = in.readLong(); + } + name = in.readString(); + type = in.readString(); + byte tmpSynchronize = in.readByte(); + synchronize = tmpSynchronize == 0 ? null : tmpSynchronize == 1; + if (in.readByte() == 0) { + after = null; + } else { + after = in.readInt(); + } + state = in.readString(); + error = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public EntityFolder createFromParcel(Parcel in) { + return new EntityFolder(in); + } + + @Override + public EntityFolder[] newArray(int size) { + return new EntityFolder[size]; + } + }; } diff --git a/app/src/main/java/eu/faircode/email/FragmentAccount.java b/app/src/main/java/eu/faircode/email/FragmentAccount.java index 0b63c1401e..3f2b1e0821 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAccount.java +++ b/app/src/main/java/eu/faircode/email/FragmentAccount.java @@ -62,11 +62,9 @@ import androidx.constraintlayout.widget.Group; import androidx.lifecycle.Observer; public class FragmentAccount extends FragmentEx { - private List providers; - private ViewGroup view; private EditText etName; - private Spinner spProfile; + private Spinner spProvider; private EditText etHost; private EditText etPort; private EditText etUser; @@ -97,12 +95,8 @@ public class FragmentAccount extends FragmentEx { Bundle args = getArguments(); final long id = (args == null ? -1 : args.getLong("id", -1)); - // Get providers - providers = Provider.loadProfiles(getContext()); - providers.add(0, new Provider(getString(R.string.title_custom))); - // Get controls - spProfile = view.findViewById(R.id.spProvider); + spProvider = view.findViewById(R.id.spProvider); etName = view.findViewById(R.id.etName); etHost = view.findViewById(R.id.etHost); etPort = view.findViewById(R.id.etPort); @@ -125,10 +119,15 @@ public class FragmentAccount extends FragmentEx { // Wire controls - spProfile.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + spProvider.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - Provider provider = providers.get(position); + public void onItemSelected(AdapterView adapterView, View view, int position, long id) { + Integer tag = (Integer) adapterView.getTag(); + if (tag != null && tag.equals(position)) + return; + adapterView.setTag(position); + + Provider provider = (Provider) adapterView.getSelectedItem(); if (provider.imap_port != 0) { etName.setText(provider.name); etHost.setText(provider.imap_host); @@ -142,10 +141,6 @@ public class FragmentAccount extends FragmentEx { } }); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), R.layout.spinner_item, providers); - adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); - spProfile.setAdapter(adapter); - cbSynchronize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -370,11 +365,11 @@ public class FragmentAccount extends FragmentEx { args.putString("password", tilPassword.getEditText().getText().toString()); args.putBoolean("synchronize", cbSynchronize.isChecked()); args.putBoolean("primary", cbPrimary.isChecked()); - args.putSerializable("drafts", drafts); - args.putSerializable("sent", sent); - args.putSerializable("all", all); - args.putSerializable("trash", trash); - args.putSerializable("junk", junk); + args.putParcelable("drafts", drafts); + args.putParcelable("sent", sent); + args.putParcelable("all", all); + args.putParcelable("trash", trash); + args.putParcelable("junk", junk); new SimpleTask() { @Override @@ -385,11 +380,11 @@ public class FragmentAccount extends FragmentEx { String user = args.getString("user"); String password = args.getString("password"); boolean synchronize = args.getBoolean("synchronize"); - EntityFolder drafts = (EntityFolder) args.getSerializable("drafts"); - EntityFolder sent = (EntityFolder) args.getSerializable("sent"); - EntityFolder all = (EntityFolder) args.getSerializable("all"); - EntityFolder trash = (EntityFolder) args.getSerializable("trash"); - EntityFolder junk = (EntityFolder) args.getSerializable("junk"); + EntityFolder drafts = args.getParcelable("drafts"); + EntityFolder sent = args.getParcelable("sent"); + EntityFolder all = args.getParcelable("all"); + EntityFolder trash = args.getParcelable("trash"); + EntityFolder junk = args.getParcelable("junk"); if (TextUtils.isEmpty(host)) throw new Throwable(getContext().getString(R.string.title_no_host)); @@ -484,7 +479,7 @@ public class FragmentAccount extends FragmentEx { } for (EntityFolder folder : folders) { - db.folder().setFolderUser(folder.type); + db.folder().setFolderUser(folder.account, folder.type); EntityFolder existing = db.folder().getFolderByName(account.id, folder.name); if (existing == null) { folder.account = account.id; @@ -585,7 +580,31 @@ public class FragmentAccount extends FragmentEx { } @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { + public void onSaveInstanceState(Bundle outState) { + outState.putInt("provider", spProvider.getSelectedItemPosition()); + outState.putString("password", tilPassword.getEditText().getText().toString()); + + boolean checked = (btnSave.getVisibility() == View.VISIBLE); + outState.putBoolean("checked", checked); + + if (checked) { + ArrayList folders = new ArrayList<>(); + for (int i = 0; i < spDrafts.getAdapter().getCount(); i++) + folders.add((EntityFolder) spDrafts.getAdapter().getItem(i)); + + outState.putParcelableArrayList("folders", folders); + outState.putInt("drafts", spDrafts.getSelectedItemPosition()); + outState.putInt("sent", spSent.getSelectedItemPosition()); + outState.putInt("all", spAll.getSelectedItemPosition()); + outState.putInt("trash", spTrash.getSelectedItemPosition()); + outState.putInt("junk", spJunk.getSelectedItemPosition()); + } + + super.onSaveInstanceState(outState); + } + + @Override + public void onActivityCreated(@Nullable final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Get arguments @@ -596,23 +615,64 @@ public class FragmentAccount extends FragmentEx { DB.getInstance(getContext()).account().liveAccount(id).observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(@Nullable EntityAccount account) { + // Get providers + List providers = Provider.loadProfiles(getContext()); + providers.add(0, new Provider(getString(R.string.title_custom))); + + ArrayAdapter padapter = new ArrayAdapter<>(getContext(), R.layout.spinner_item, providers); + padapter.setDropDownViewResource(R.layout.spinner_dropdown_item); + spProvider.setAdapter(padapter); + + if (savedInstanceState == null) { + etName.setText(account == null ? null : account.name); + etHost.setText(account == null ? null : account.host); + etPort.setText(account == null ? null : Long.toString(account.port)); + etUser.setText(account == null ? null : account.user); + tilPassword.getEditText().setText(account == null ? null : account.password); + cbSynchronize.setChecked(account == null ? true : account.synchronize); + cbPrimary.setChecked(account == null ? true : account.primary); + cbPrimary.setEnabled(account == null ? true : account.synchronize); + } else { + int provider = savedInstanceState.getInt("provider"); + spProvider.setTag(provider); + spProvider.setSelection(provider); + + tilPassword.getEditText().setText(savedInstanceState.getString("password")); + } + Helper.setViewsEnabled(view, true); - etName.setText(account == null ? null : account.name); - etHost.setText(account == null ? null : account.host); - etPort.setText(account == null ? null : Long.toString(account.port)); - etUser.setText(account == null ? null : account.user); - tilPassword.getEditText().setText(account == null ? null : account.password); - cbSynchronize.setChecked(account == null ? true : account.synchronize); - cbPrimary.setChecked(account == null ? true : account.primary); - cbPrimary.setEnabled(account == null ? true : account.synchronize); ibDelete.setVisibility(account == null ? View.GONE : View.VISIBLE); - btnCheck.setVisibility(account == null || account.synchronize ? View.VISIBLE : View.GONE); - btnSave.setVisibility(account == null || account.synchronize ? View.GONE : View.VISIBLE); + btnCheck.setVisibility(cbSynchronize.isChecked() ? View.VISIBLE : View.GONE); + btnSave.setVisibility(cbSynchronize.isChecked() ? View.GONE : View.VISIBLE); btnCheck.setEnabled(true); pbWait.setVisibility(View.GONE); + + if (savedInstanceState != null) { + boolean checked = savedInstanceState.getBoolean("checked"); + if (checked) { + List folders = savedInstanceState.getParcelableArrayList("folders"); + + ArrayAdapter adapter = new ArrayAdapter<>(getContext(), R.layout.spinner_item, folders); + adapter.setDropDownViewResource(R.layout.spinner_dropdown_item); + + spDrafts.setAdapter(adapter); + spSent.setAdapter(adapter); + spAll.setAdapter(adapter); + spTrash.setAdapter(adapter); + spJunk.setAdapter(adapter); + + spDrafts.setSelection(savedInstanceState.getInt("drafts")); + spSent.setSelection(savedInstanceState.getInt("sent")); + spAll.setSelection(savedInstanceState.getInt("all")); + spTrash.setSelection(savedInstanceState.getInt("trash")); + spJunk.setSelection(savedInstanceState.getInt("junk")); + grpFolders.setVisibility(View.VISIBLE); + btnSave.setVisibility(View.VISIBLE); + } + } } }); } diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 337ba699ed..eede1c0692 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -258,11 +258,18 @@ public class FragmentCompose extends FragmentEx { super.onDestroyView(); } + @Override + public void onSaveInstanceState(Bundle outState) { + if (autosave) + onAction(R.id.action_save); + outState.putLong("working", working); + } + @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - if (working < 0) { + if (savedInstanceState == null) { Bundle args = new Bundle(); args.putString("action", getArguments().getString("action")); args.putLong("id", getArguments().getLong("id", -1)); @@ -272,7 +279,7 @@ public class FragmentCompose extends FragmentEx { } else { Bundle args = new Bundle(); args.putString("action", "edit"); - args.putLong("id", working); + args.putLong("id", savedInstanceState.getLong("working")); args.putLong("account", -1); args.putLong("reference", -1); draftLoader.load(this, args); diff --git a/app/src/main/java/eu/faircode/email/FragmentFolder.java b/app/src/main/java/eu/faircode/email/FragmentFolder.java index 094f1d04c8..54bc478aa7 100644 --- a/app/src/main/java/eu/faircode/email/FragmentFolder.java +++ b/app/src/main/java/eu/faircode/email/FragmentFolder.java @@ -134,7 +134,12 @@ public class FragmentFolder extends FragmentEx { } @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + @Override + public void onActivityCreated(@Nullable final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Get arguments @@ -150,8 +155,10 @@ public class FragmentFolder extends FragmentEx { return; } - cbSynchronize.setChecked(folder.synchronize); - etAfter.setText(Integer.toString(folder.after)); + if (savedInstanceState == null) { + cbSynchronize.setChecked(folder.synchronize); + etAfter.setText(Integer.toString(folder.after)); + } pbWait.setVisibility(View.GONE); Helper.setViewsEnabled(view, true); diff --git a/app/src/main/java/eu/faircode/email/FragmentIdentity.java b/app/src/main/java/eu/faircode/email/FragmentIdentity.java index 83069078ff..cc5c96962d 100644 --- a/app/src/main/java/eu/faircode/email/FragmentIdentity.java +++ b/app/src/main/java/eu/faircode/email/FragmentIdentity.java @@ -54,13 +54,11 @@ import androidx.appcompat.app.AlertDialog; import androidx.lifecycle.Observer; public class FragmentIdentity extends FragmentEx { - private List providers; - private ViewGroup view; private EditText etName; private EditText etEmail; private EditText etReplyTo; - private Spinner spProfile; + private Spinner spProvider; private Spinner spAccount; private EditText etHost; private CheckBox cbStartTls; @@ -85,15 +83,11 @@ public class FragmentIdentity extends FragmentEx { Bundle args = getArguments(); final long id = (args == null ? -1 : args.getLong("id", -1)); - // Get providers - providers = Provider.loadProfiles(getContext()); - providers.add(0, new Provider(getString(R.string.title_custom))); - // Get controls etName = view.findViewById(R.id.etName); etEmail = view.findViewById(R.id.etEmail); etReplyTo = view.findViewById(R.id.etReplyTo); - spProfile = view.findViewById(R.id.spProvider); + spProvider = view.findViewById(R.id.spProvider); spAccount = view.findViewById(R.id.spAccount); etHost = view.findViewById(R.id.etHost); cbStartTls = view.findViewById(R.id.cbStartTls); @@ -127,14 +121,20 @@ public class FragmentIdentity extends FragmentEx { spAccount.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapterView, View view, int position, long id) { + Integer tag = (Integer) adapterView.getTag(); + if (tag != null && tag.equals(position)) + return; + adapterView.setTag(position); + EntityAccount account = (EntityAccount) adapterView.getAdapter().getItem(position); - for (int pos = 1; pos < providers.size(); pos++) - if (providers.get(pos).imap_host.equals(account.host) && - providers.get(pos).imap_port == account.port) { - spProfile.setSelection(pos); + for (int pos = 1; pos < spProvider.getAdapter().getCount(); pos++) { + Provider provider = (Provider) spProvider.getItemAtPosition(pos); + if (provider.imap_host.equals(account.host) && provider.imap_port == account.port) { + spProvider.setSelection(pos); break; } + } if (position > 0 && TextUtils.isEmpty(etUser.getText())) etUser.setText(account.user); @@ -150,10 +150,15 @@ public class FragmentIdentity extends FragmentEx { } }); - spProfile.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + spProvider.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - Provider provider = providers.get(position); + public void onItemSelected(AdapterView adapterView, View view, int position, long id) { + Integer tag = (Integer) adapterView.getTag(); + if (tag != null && tag.equals(position)) + return; + adapterView.setTag(position); + + Provider provider = (Provider) adapterView.getSelectedItem(); if (provider.smtp_port != 0) { etHost.setText(provider.smtp_host); etPort.setText(Integer.toString(provider.smtp_port)); @@ -166,10 +171,6 @@ public class FragmentIdentity extends FragmentEx { } }); - ArrayAdapter adapterProfile = new ArrayAdapter<>(getContext(), R.layout.spinner_item, providers); - adapterProfile.setDropDownViewResource(R.layout.spinner_dropdown_item); - spProfile.setAdapter(adapterProfile); - cbStartTls.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -370,7 +371,15 @@ public class FragmentIdentity extends FragmentEx { } @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { + public void onSaveInstanceState(Bundle outState) { + outState.putInt("account", spAccount.getSelectedItemPosition()); + outState.putInt("provider", spProvider.getSelectedItemPosition()); + outState.putString("password", tilPassword.getEditText().getText().toString()); + super.onSaveInstanceState(outState); + } + + @Override + public void onActivityCreated(@Nullable final Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Get arguments @@ -383,25 +392,29 @@ public class FragmentIdentity extends FragmentEx { db.identity().liveIdentity(id).observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(@Nullable final EntityIdentity identity) { - etName.setText(identity == null ? null : identity.name); - etEmail.setText(identity == null ? null : identity.email); - etReplyTo.setText(identity == null ? null : identity.replyto); - etHost.setText(identity == null ? null : identity.host); - cbStartTls.setChecked(identity == null ? false : identity.starttls); - etPort.setText(identity == null ? null : Long.toString(identity.port)); - etUser.setText(identity == null ? null : identity.user); - tilPassword.getEditText().setText(identity == null ? null : identity.password); - cbSynchronize.setChecked(identity == null ? true : identity.synchronize); - cbPrimary.setChecked(identity == null ? true : identity.primary); - cbPrimary.setEnabled(identity == null ? true : identity.synchronize); + if (savedInstanceState == null) { + etName.setText(identity == null ? null : identity.name); + etEmail.setText(identity == null ? null : identity.email); + etReplyTo.setText(identity == null ? null : identity.replyto); + etHost.setText(identity == null ? null : identity.host); + cbStartTls.setChecked(identity == null ? false : identity.starttls); + etPort.setText(identity == null ? null : Long.toString(identity.port)); + etUser.setText(identity == null ? null : identity.user); + tilPassword.getEditText().setText(identity == null ? null : identity.password); + cbSynchronize.setChecked(identity == null ? true : identity.synchronize); + cbPrimary.setChecked(identity == null ? true : identity.primary); + + etName.requestFocus(); + } else + tilPassword.getEditText().setText(savedInstanceState.getString("password")); + + cbPrimary.setEnabled(cbSynchronize.isChecked()); ibDelete.setVisibility(identity == null ? View.GONE : View.VISIBLE); Helper.setViewsEnabled(view, true); btnSave.setEnabled(true); pbWait.setVisibility(View.GONE); - etName.requestFocus(); - db.account().liveAccounts().removeObservers(getViewLifecycleOwner()); db.account().liveAccounts().observe(getViewLifecycleOwner(), new Observer>() { @Override @@ -415,15 +428,33 @@ public class FragmentIdentity extends FragmentEx { unselected.primary = false; accounts.add(0, unselected); - ArrayAdapter adapterAccount = new ArrayAdapter<>(getContext(), R.layout.spinner_item, accounts); - adapterAccount.setDropDownViewResource(R.layout.spinner_dropdown_item); - spAccount.setAdapter(adapterAccount); - - for (int pos = 0; pos < accounts.size(); pos++) - if (accounts.get(pos).id == (identity == null ? -1 : identity.account)) { - spAccount.setSelection(pos); - break; - } + ArrayAdapter aa = new ArrayAdapter<>(getContext(), R.layout.spinner_item, accounts); + aa.setDropDownViewResource(R.layout.spinner_dropdown_item); + spAccount.setAdapter(aa); + + // Get providers + List providers = Provider.loadProfiles(getContext()); + providers.add(0, new Provider(getString(R.string.title_custom))); + + ArrayAdapter adapterProfile = new ArrayAdapter<>(getContext(), R.layout.spinner_item, providers); + adapterProfile.setDropDownViewResource(R.layout.spinner_dropdown_item); + spProvider.setAdapter(adapterProfile); + + if (savedInstanceState == null) { + for (int pos = 0; pos < accounts.size(); pos++) + if (accounts.get(pos).id == (identity == null ? -1 : identity.account)) { + spAccount.setSelection(pos); + break; + } + } else { + int provider = savedInstanceState.getInt("provider"); + spProvider.setTag(provider); + spProvider.setSelection(provider); + + int account = savedInstanceState.getInt("account"); + spAccount.setTag(account); + spAccount.setSelection(account); + } } }); }