aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java170
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java33
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java35
-rw-r--r--src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java24
4 files changed, 156 insertions, 106 deletions
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
index d095e2fa..0b3b2990 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -52,7 +52,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history";
- private static final int DATABASE_VERSION = 27;
+ private static final int DATABASE_VERSION = 28;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -250,86 +250,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL("update " + Account.TABLENAME + " set " + Account.ROSTERVERSION + " = NULL");
}
if (oldVersion < 14 && newVersion >= 14) {
- // migrate db to new, canonicalized JID domainpart representation
-
- // Conversation table
- Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME, new String[0]);
- while (cursor.moveToNext()) {
- String newJid;
- try {
- newJid = Jid.fromString(
- cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
- ).toString();
- } catch (InvalidJidException ignored) {
- Log.e(Config.LOGTAG, "Failed to migrate Conversation CONTACTJID "
- + cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
- + ": " + ignored + ". Skipping...");
- continue;
- }
-
- String updateArgs[] = {
- newJid,
- cursor.getString(cursor.getColumnIndex(Conversation.UUID)),
- };
- db.execSQL("update " + Conversation.TABLENAME
- + " set " + Conversation.CONTACTJID + " = ? "
- + " where " + Conversation.UUID + " = ?", updateArgs);
- }
- cursor.close();
-
- // Contact table
- cursor = db.rawQuery("select * from " + Contact.TABLENAME, new String[0]);
- while (cursor.moveToNext()) {
- String newJid;
- try {
- newJid = Jid.fromString(
- cursor.getString(cursor.getColumnIndex(Contact.JID))
- ).toString();
- } catch (InvalidJidException ignored) {
- Log.e(Config.LOGTAG, "Failed to migrate Contact JID "
- + cursor.getString(cursor.getColumnIndex(Contact.JID))
- + ": " + ignored + ". Skipping...");
- continue;
- }
-
- String updateArgs[] = {
- newJid,
- cursor.getString(cursor.getColumnIndex(Contact.ACCOUNT)),
- cursor.getString(cursor.getColumnIndex(Contact.JID)),
- };
- db.execSQL("update " + Contact.TABLENAME
- + " set " + Contact.JID + " = ? "
- + " where " + Contact.ACCOUNT + " = ? "
- + " AND " + Contact.JID + " = ?", updateArgs);
- }
- cursor.close();
-
- // Account table
- cursor = db.rawQuery("select * from " + Account.TABLENAME, new String[0]);
- while (cursor.moveToNext()) {
- String newServer;
- try {
- newServer = Jid.fromParts(
- cursor.getString(cursor.getColumnIndex(Account.USERNAME)),
- cursor.getString(cursor.getColumnIndex(Account.SERVER)),
- "mobile"
- ).getDomainpart();
- } catch (InvalidJidException ignored) {
- Log.e(Config.LOGTAG, "Failed to migrate Account SERVER "
- + cursor.getString(cursor.getColumnIndex(Account.SERVER))
- + ": " + ignored + ". Skipping...");
- continue;
- }
-
- String updateArgs[] = {
- newServer,
- cursor.getString(cursor.getColumnIndex(Account.UUID)),
- };
- db.execSQL("update " + Account.TABLENAME
- + " set " + Account.SERVER + " = ? "
- + " where " + Account.UUID + " = ?", updateArgs);
- }
- cursor.close();
+ canonicalizeJids(db);
}
if (oldVersion < 15 && newVersion >= 15) {
recreateAxolotlDb(db);
@@ -406,6 +327,93 @@ public class DatabaseBackend extends SQLiteOpenHelper {
if (oldVersion < 27 && newVersion >= 27) {
db.execSQL("DELETE FROM "+ServiceDiscoveryResult.TABLENAME);
}
+
+ if (oldVersion < 28 && newVersion >= 28) {
+ canonicalizeJids(db);
+ }
+ }
+
+ private void canonicalizeJids(SQLiteDatabase db) {
+ // migrate db to new, canonicalized JID domainpart representation
+
+ // Conversation table
+ Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME, new String[0]);
+ while (cursor.moveToNext()) {
+ String newJid;
+ try {
+ newJid = Jid.fromString(
+ cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
+ ).toString();
+ } catch (InvalidJidException ignored) {
+ Log.e(Config.LOGTAG, "Failed to migrate Conversation CONTACTJID "
+ + cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
+ + ": " + ignored + ". Skipping...");
+ continue;
+ }
+
+ String updateArgs[] = {
+ newJid,
+ cursor.getString(cursor.getColumnIndex(Conversation.UUID)),
+ };
+ db.execSQL("update " + Conversation.TABLENAME
+ + " set " + Conversation.CONTACTJID + " = ? "
+ + " where " + Conversation.UUID + " = ?", updateArgs);
+ }
+ cursor.close();
+
+ // Contact table
+ cursor = db.rawQuery("select * from " + Contact.TABLENAME, new String[0]);
+ while (cursor.moveToNext()) {
+ String newJid;
+ try {
+ newJid = Jid.fromString(
+ cursor.getString(cursor.getColumnIndex(Contact.JID))
+ ).toString();
+ } catch (InvalidJidException ignored) {
+ Log.e(Config.LOGTAG, "Failed to migrate Contact JID "
+ + cursor.getString(cursor.getColumnIndex(Contact.JID))
+ + ": " + ignored + ". Skipping...");
+ continue;
+ }
+
+ String updateArgs[] = {
+ newJid,
+ cursor.getString(cursor.getColumnIndex(Contact.ACCOUNT)),
+ cursor.getString(cursor.getColumnIndex(Contact.JID)),
+ };
+ db.execSQL("update " + Contact.TABLENAME
+ + " set " + Contact.JID + " = ? "
+ + " where " + Contact.ACCOUNT + " = ? "
+ + " AND " + Contact.JID + " = ?", updateArgs);
+ }
+ cursor.close();
+
+ // Account table
+ cursor = db.rawQuery("select * from " + Account.TABLENAME, new String[0]);
+ while (cursor.moveToNext()) {
+ String newServer;
+ try {
+ newServer = Jid.fromParts(
+ cursor.getString(cursor.getColumnIndex(Account.USERNAME)),
+ cursor.getString(cursor.getColumnIndex(Account.SERVER)),
+ "mobile"
+ ).getDomainpart();
+ } catch (InvalidJidException ignored) {
+ Log.e(Config.LOGTAG, "Failed to migrate Account SERVER "
+ + cursor.getString(cursor.getColumnIndex(Account.SERVER))
+ + ": " + ignored + ". Skipping...");
+ continue;
+ }
+
+ String updateArgs[] = {
+ newServer,
+ cursor.getString(cursor.getColumnIndex(Account.UUID)),
+ };
+ db.execSQL("update " + Account.TABLENAME
+ + " set " + Account.SERVER + " = ? "
+ + " where " + Account.UUID + " = ?", updateArgs);
+ }
+ cursor.close();
}
public static synchronized DatabaseBackend getInstance(Context context) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index e891f00b..2c8b27b0 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -67,8 +67,6 @@ import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
-import static eu.siacs.conversations.crypto.axolotl.AxolotlService.AxolotlCapability.MISSING_PRESENCE;
-
public class ConversationActivity extends XmppActivity
implements OnAccountUpdate, OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, XmppConnectionService.OnShowErrorToast {
@@ -94,9 +92,12 @@ public class ConversationActivity extends XmppActivity
private static final String STATE_OPEN_CONVERSATION = "state_open_conversation";
private static final String STATE_PANEL_OPEN = "state_panel_open";
private static final String STATE_PENDING_URI = "state_pending_uri";
+ private static final String STATE_FIRST_VISIBLE = "first_visible";
+ private static final String STATE_OFFSET_FROM_TOP = "offset_from_top";
- private String mOpenConverstaion = null;
+ private String mOpenConversation = null;
private boolean mPanelOpen = true;
+ private Pair<Integer,Integer> mScrollPosition = null;
final private List<Uri> mPendingImageUris = new ArrayList<>();
final private List<Uri> mPendingFileUris = new ArrayList<>();
private Uri mPendingGeoUri = null;
@@ -172,8 +173,16 @@ public class ConversationActivity extends XmppActivity
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
- mOpenConverstaion = savedInstanceState.getString(STATE_OPEN_CONVERSATION, null);
+ mOpenConversation = savedInstanceState.getString(STATE_OPEN_CONVERSATION, null);
mPanelOpen = savedInstanceState.getBoolean(STATE_PANEL_OPEN, true);
+ int pos = savedInstanceState.getInt(STATE_FIRST_VISIBLE, -1);
+ int offset = savedInstanceState.getInt(STATE_OFFSET_FROM_TOP, 1);
+ if (pos >= 0 && offset <= 0) {
+ Log.d(Config.LOGTAG,"retrieved scroll position from instanceState "+pos+":"+offset);
+ mScrollPosition = new Pair<>(pos,offset);
+ } else {
+ mScrollPosition = null;
+ }
String pending = savedInstanceState.getString(STATE_PENDING_URI, null);
if (pending != null) {
mPendingImageUris.clear();
@@ -1081,7 +1090,7 @@ public class ConversationActivity extends XmppActivity
@Override
protected void onNewIntent(final Intent intent) {
if (intent != null && ACTION_VIEW_CONVERSATION.equals(intent.getAction())) {
- mOpenConverstaion = null;
+ mOpenConversation = null;
if (xmppConnectionServiceBound) {
handleViewConversationIntent(intent);
intent.setAction(Intent.ACTION_MAIN);
@@ -1131,6 +1140,11 @@ public class ConversationActivity extends XmppActivity
Conversation conversation = getSelectedConversation();
if (conversation != null) {
savedInstanceState.putString(STATE_OPEN_CONVERSATION, conversation.getUuid());
+ Pair<Integer,Integer> scrollPosition = mConversationFragment.getScrollPosition();
+ if (scrollPosition != null) {
+ savedInstanceState.putInt(STATE_FIRST_VISIBLE, scrollPosition.first);
+ savedInstanceState.putInt(STATE_OFFSET_FROM_TOP, scrollPosition.second);
+ }
} else {
savedInstanceState.remove(STATE_OPEN_CONVERSATION);
}
@@ -1190,7 +1204,7 @@ public class ConversationActivity extends XmppActivity
}
finish();
}
- } else if (selectConversationByUuid(mOpenConverstaion)) {
+ } else if (selectConversationByUuid(mOpenConversation)) {
if (mPanelOpen) {
showConversationsOverview();
} else {
@@ -1199,8 +1213,11 @@ public class ConversationActivity extends XmppActivity
updateActionBarTitle(true);
}
}
- this.mConversationFragment.reInit(getSelectedConversation());
- mOpenConverstaion = null;
+ if (this.mConversationFragment.reInit(getSelectedConversation())) {
+ Log.d(Config.LOGTAG,"setting scroll position on fragment");
+ this.mConversationFragment.setScrollPosition(mScrollPosition);
+ }
+ mOpenConversation = null;
} else if (intent != null && ACTION_VIEW_CONVERSATION.equals(intent.getAction())) {
clearPending();
handleViewConversationIntent(intent);
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index edee551b..80b5ff82 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -12,6 +12,8 @@ import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.os.Handler;
import android.text.InputType;
+import android.util.Log;
+import android.util.Pair;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
@@ -153,7 +155,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
View v = messagesView.getChildAt(0);
final int pxOffset = (v == null) ? 0 : v.getTop();
ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
- updateStatusMessages();
+ try {
+ updateStatusMessages();
+ } catch (IllegalStateException e) {
+ Log.d(Config.LOGTAG,"caught illegal state exception while updating status messages");
+ }
messageListAdapter.notifyDataSetChanged();
int pos = Math.max(getIndexOf(uuid,messageList),0);
messagesView.setSelectionFromTop(pos, pxOffset);
@@ -210,6 +216,28 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
return -1;
}
+
+ public Pair<Integer,Integer> getScrollPosition() {
+ if (this.messagesView.getCount() == 0 ||
+ this.messagesView.getLastVisiblePosition() == this.messagesView.getCount() - 1) {
+ return null;
+ } else {
+ final int pos = messagesView.getFirstVisiblePosition();
+ final View view = messagesView.getChildAt(0);
+ if (view == null) {
+ return null;
+ } else {
+ return new Pair<>(pos, view.getTop());
+ }
+ }
+ }
+
+ public void setScrollPosition(Pair<Integer,Integer> scrollPosition) {
+ if (scrollPosition != null) {
+ this.messagesView.setSelectionFromTop(scrollPosition.first, scrollPosition.second);
+ }
+ }
+
protected OnClickListener clickToDecryptListener = new OnClickListener() {
@Override
@@ -736,9 +764,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
- public void reInit(Conversation conversation) {
+ public boolean reInit(Conversation conversation) {
if (conversation == null) {
- return;
+ return false;
}
this.activity = (ConversationActivity) getActivity();
setupIme();
@@ -774,6 +802,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
pos = i < 0 ? bottom : i;
}
messagesView.setSelection(pos);
+ return pos == bottom;
}
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
index a15abe14..6430d41e 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jid/Jid.java
@@ -21,10 +21,6 @@ public final class Jid {
private final String domainpart;
private final String resourcepart;
- // It's much more efficient to store the ful JID as well as the parts instead of figuring them
- // all out every time (since some characters are displayed but aren't used for comparisons).
- private final String displayjid;
-
public String getLocalpart() {
return localpart;
}
@@ -73,7 +69,6 @@ public final class Jid {
Jid fromCache = Jid.cache.get(jid);
if (fromCache != null) {
- displayjid = fromCache.displayjid;
localpart = fromCache.localpart;
domainpart = fromCache.domainpart;
resourcepart = fromCache.resourcepart;
@@ -94,8 +89,6 @@ public final class Jid {
throw new InvalidJidException(InvalidJidException.INVALID_CHARACTER);
}
- String finaljid;
-
final int domainpartStart;
final int atLoc = jid.indexOf("@");
final int slashLoc = jid.indexOf("/");
@@ -103,7 +96,6 @@ public final class Jid {
// or there are one or more "@" signs but they're all in the resourcepart (eg. "example.net/@/rp@"):
if (atCount == 0 || (atCount > 0 && slashLoc != -1 && atLoc > slashLoc)) {
localpart = "";
- finaljid = "";
domainpartStart = 0;
} else {
final String lp = jid.substring(0, atLoc);
@@ -116,7 +108,6 @@ public final class Jid {
throw new InvalidJidException(InvalidJidException.INVALID_PART_LENGTH);
}
domainpartStart = atLoc + 1;
- finaljid = lp + "@";
}
final String dp;
@@ -135,7 +126,6 @@ public final class Jid {
} catch (final StringprepException e) {
throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
}
- finaljid = finaljid + dp + "/" + rp;
} else {
resourcepart = "";
try{
@@ -143,7 +133,6 @@ public final class Jid {
} catch (final StringprepException e) {
throw new InvalidJidException(InvalidJidException.STRINGPREP_FAIL, e);
}
- finaljid = finaljid + dp;
}
// Remove trailing "." before storing the domain part.
@@ -167,8 +156,6 @@ public final class Jid {
}
Jid.cache.put(jid, this);
-
- this.displayjid = finaljid;
}
public Jid toBareJid() {
@@ -191,7 +178,16 @@ public final class Jid {
@Override
public String toString() {
- return displayjid;
+ String out;
+ if (hasLocalpart()) {
+ out = localpart + '@' + domainpart;
+ } else {
+ out = domainpart;
+ }
+ if (!resourcepart.isEmpty()) {
+ out += '/'+resourcepart;
+ }
+ return out;
}
@Override