aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/AndroidManifest.xml6
-rw-r--r--src/main/java/eu/siacs/conversations/Config.java7
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Account.java36
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Bookmark.java17
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Contact.java34
-rw-r--r--src/main/java/eu/siacs/conversations/entities/ListItem.java6
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Presence.java43
-rw-r--r--src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java55
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Presences.java14
-rw-r--r--src/main/java/eu/siacs/conversations/parser/PresenceParser.java5
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java68
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java33
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java45
-rw-r--r--src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java22
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java2
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java17
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java26
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java12
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java182
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java21
-rw-r--r--src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java3
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java20
-rw-r--r--src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java200
-rw-r--r--src/main/java/eu/siacs/conversations/ui/SettingsActivity.java6
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java6
-rw-r--r--src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java30
-rw-r--r--src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java1
-rw-r--r--src/main/java/eu/siacs/conversations/ui/XmppActivity.java38
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java5
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java3
-rw-r--r--src/main/java/eu/siacs/conversations/utils/UIHelper.java17
-rw-r--r--src/main/java/eu/siacs/conversations/utils/Xmlns.java2
-rw-r--r--src/main/res/drawable-hdpi/ic_account_box_white_24dp.pngbin0 -> 337 bytes
-rw-r--r--src/main/res/drawable-hdpi/ic_announcement_white_24dp.pngbin0 -> 251 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_account_box_white_24dp.pngbin0 -> 290 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_announcement_white_24dp.pngbin0 -> 214 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_account_box_white_24dp.pngbin0 -> 431 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_announcement_white_24dp.pngbin0 -> 285 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_account_box_white_24dp.pngbin0 -> 578 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_announcement_white_24dp.pngbin0 -> 355 bytes
-rw-r--r--src/main/res/drawable-xxxhdpi/ic_account_box_white_24dp.pngbin0 -> 894 bytes
-rw-r--r--src/main/res/drawable-xxxhdpi/ic_announcement_white_24dp.pngbin0 -> 519 bytes
-rw-r--r--src/main/res/layout/activity_change_password.xml22
-rw-r--r--src/main/res/layout/activity_contact_details.xml10
-rw-r--r--src/main/res/layout/activity_set_presence.xml72
-rw-r--r--src/main/res/layout/captcha.xml27
-rw-r--r--src/main/res/layout/presence_template.xml49
-rw-r--r--src/main/res/layout/simple_list_item.xml26
-rw-r--r--src/main/res/menu/change_presence.xml17
-rw-r--r--src/main/res/menu/editaccount.xml6
-rw-r--r--src/main/res/menu/manageaccounts_context.xml3
-rw-r--r--src/main/res/values/arrays.xml8
-rw-r--r--src/main/res/values/strings.xml15
-rw-r--r--src/main/res/xml/preferences.xml12
57 files changed, 1004 insertions, 261 deletions
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index bbec8f12d..57fdd4c69 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -92,6 +92,12 @@
android:screenOrientation="portrait"
android:launchMode="singleTask"/>
<activity
+ android:name=".ui.SetPresenceActivity"
+ android:label="@string/change_presence"
+ android:configChanges="orientation|screenSize"
+ android:windowSoftInputMode="stateHidden|adjustResize"
+ android:launchMode="singleTask"/>
+ <activity
android:name=".ui.SettingsActivity"
android:label="@string/title_activity_settings"/>
<activity
diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java
index 305055847..2aff98dc2 100644
--- a/src/main/java/eu/siacs/conversations/Config.java
+++ b/src/main/java/eu/siacs/conversations/Config.java
@@ -41,9 +41,6 @@ public final class Config {
public static final String DOMAIN_LOCK = "pix-art.de"; //only allow account creation for this domain
public static final String MAGIC_CREATE_DOMAIN = "pix-art.de";
- public static final String CONFERENCE_DOMAIN_LOCK = null; //only allow conference creation for this domain
- public static final boolean LOCK_DOMAINS_IN_CONVERSATIONS = false; //only add contacts and conferences for own domains
- public static final boolean LOCK_SETTINGS = false; //set to true to disallow account and settings editing
public static final boolean SINGLE_ACCOUNT = true; //set to true to allow only one account
public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox
@@ -56,8 +53,6 @@ public final class Config {
public static final boolean SHOW_DISABLE_FOREGROUND = false; //if set to true the foreground notification has a button to disable it
public static final boolean USE_ALWAYS_FOREGROUND = true; //if set to true the foreground service is always enabled
- public static final boolean LEGACY_NAMESPACE_HTTP_UPLOAD = false; // true = 'eu:siacs:conversations:http:upload' false = 'urn:xmpp:http:upload'
-
public static final int PING_MAX_INTERVAL = 300;
public static final int PING_MIN_INTERVAL = 30;
public static final int PING_TIMEOUT = 15;
@@ -103,8 +98,6 @@ public final class Config {
public static final boolean IGNORE_ID_REWRITE_IN_MUC = true;
- public static final boolean REQUEST_DISCO = true;
-
public static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
public static final long MAM_MAX_CATCHUP = MILLISECONDS_IN_DAY / 2;
public static final int MAM_MAX_MESSAGES = 500;
diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java
index 2356ffb94..2c0ec7ff9 100644
--- a/src/main/java/eu/siacs/conversations/entities/Account.java
+++ b/src/main/java/eu/siacs/conversations/entities/Account.java
@@ -43,6 +43,8 @@ public class Account extends AbstractEntity {
public static final String DISPLAY_NAME = "display_name";
public static final String HOSTNAME = "hostname";
public static final String PORT = "port";
+ public static final String STATUS = "status";
+ public static final String STATUS_MESSAGE = "status_message";
public static final String PINNED_MECHANISM_KEY = "pinned_mechanism";
@@ -50,6 +52,7 @@ public class Account extends AbstractEntity {
public static final int OPTION_DISABLED = 1;
public static final int OPTION_REGISTER = 2;
public static final int OPTION_USECOMPRESSION = 3;
+ public static final int OPTION_MAGIC_CREATE = 4;
public final HashSet<Pair<String, String>> inProgressDiscoFetches = new HashSet<>();
public boolean httpUploadAvailable(long filesize) {
@@ -168,15 +171,18 @@ public class Account extends AbstractEntity {
private final Roster roster = new Roster(this);
private List<Bookmark> bookmarks = new CopyOnWriteArrayList<>();
private final Collection<Jid> blocklist = new CopyOnWriteArraySet<>();
+ private Presence.Status presenceStatus = Presence.Status.ONLINE;
+ private String presenceStatusMessage = null;
public Account(final Jid jid, final String password) {
this(java.util.UUID.randomUUID().toString(), jid,
- password, 0, null, "", null, null, null, 5222);
+ password, 0, null, "", null, null, null, 5222, Presence.Status.ONLINE, null);
}
private Account(final String uuid, final Jid jid,
- final String password, final int options, final String rosterVersion, final String keys,
- final String avatar, String displayName, String hostname, int port) {
+ final String password, final int options, final String rosterVersion, final String keys,
+ final String avatar, String displayName, String hostname, int port,
+ final Presence.Status status, String statusMessage) {
this.uuid = uuid;
this.jid = jid;
if (jid.isBareJid()) {
@@ -194,6 +200,8 @@ public class Account extends AbstractEntity {
this.displayName = displayName;
this.hostname = hostname;
this.port = port;
+ this.presenceStatus = status;
+ this.presenceStatusMessage = statusMessage;
}
public static Account fromCursor(final Cursor cursor) {
@@ -212,7 +220,9 @@ public class Account extends AbstractEntity {
cursor.getString(cursor.getColumnIndex(AVATAR)),
cursor.getString(cursor.getColumnIndex(DISPLAY_NAME)),
cursor.getString(cursor.getColumnIndex(HOSTNAME)),
- cursor.getInt(cursor.getColumnIndex(PORT)));
+ cursor.getInt(cursor.getColumnIndex(PORT)),
+ Presence.Status.fromShowString(cursor.getString(cursor.getColumnIndex(STATUS))),
+ cursor.getString(cursor.getColumnIndex(STATUS_MESSAGE)));
}
public boolean isOptionSet(final int option) {
@@ -287,6 +297,22 @@ public class Account extends AbstractEntity {
return getXmppConnection() != null && getStatus().isError() && getXmppConnection().getAttempt() >= 3;
}
+ public void setPresenceStatus(Presence.Status status) {
+ this.presenceStatus = status;
+ }
+
+ public Presence.Status getPresenceStatus() {
+ return this.presenceStatus;
+ }
+
+ public void setPresenceStatusMessage(String message) {
+ this.presenceStatusMessage = message;
+ }
+
+ public String getPresenceStatusMessage() {
+ return this.presenceStatusMessage;
+ }
+
public String getResource() {
return jid.getResourcepart();
}
@@ -347,6 +373,8 @@ public class Account extends AbstractEntity {
values.put(DISPLAY_NAME, displayName);
values.put(HOSTNAME, hostname);
values.put(PORT, port);
+ values.put(STATUS, presenceStatus.toShowString());
+ values.put(STATUS_MESSAGE, presenceStatusMessage);
return values;
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java
index 088dfd8ae..fd6a5dab9 100644
--- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java
+++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java
@@ -1,5 +1,7 @@
package eu.siacs.conversations.entities;
+import android.content.Context;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -61,9 +63,7 @@ public class Bookmark extends Element implements ListItem {
@Override
public String getDisplayJid() {
Jid jid = getJid();
- if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && jid != null && jid.getDomainpart().equals(Config.CONFERENCE_DOMAIN_LOCK)) {
- return jid.getLocalpart();
- } else if (jid != null) {
+ if (jid != null) {
return jid.toString();
} else {
return null;
@@ -76,7 +76,7 @@ public class Bookmark extends Element implements ListItem {
}
@Override
- public List<Tag> getTags() {
+ public List<Tag> getTags(Context context) {
ArrayList<Tag> tags = new ArrayList<Tag>();
for (Element element : getChildren()) {
if (element.getName().equals("group") && element.getContent() != null) {
@@ -114,7 +114,8 @@ public class Bookmark extends Element implements ListItem {
}
}
- public boolean match(String needle) {
+ @Override
+ public boolean match(Context context, String needle) {
if (needle == null) {
return true;
}
@@ -122,12 +123,12 @@ public class Bookmark extends Element implements ListItem {
final Jid jid = getJid();
return (jid != null && jid.toString().contains(needle)) ||
getDisplayName().toLowerCase(Locale.US).contains(needle) ||
- matchInTag(needle);
+ matchInTag(context, needle);
}
- private boolean matchInTag(String needle) {
+ private boolean matchInTag(Context context, String needle) {
needle = needle.toLowerCase(Locale.US);
- for (Tag tag : getTags()) {
+ for (Tag tag : getTags(context)) {
if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
return true;
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java
index 691fc3e45..8721d9c46 100644
--- a/src/main/java/eu/siacs/conversations/entities/Contact.java
+++ b/src/main/java/eu/siacs/conversations/entities/Contact.java
@@ -1,6 +1,7 @@
package eu.siacs.conversations.entities;
import android.content.ContentValues;
+import android.content.Context;
import android.database.Cursor;
import org.json.JSONArray;
@@ -123,9 +124,7 @@ public class Contact implements ListItem, Blockable {
@Override
public String getDisplayJid() {
- if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && jid != null && jid.getDomainpart().equals(Config.DOMAIN_LOCK)) {
- return jid.getLocalpart();
- } else if (jid != null) {
+ if (jid != null) {
return jid.toString();
} else {
return null;
@@ -141,25 +140,14 @@ public class Contact implements ListItem, Blockable {
}
@Override
- public List<Tag> getTags() {
+ public List<Tag> getTags(Context context) {
final ArrayList<Tag> tags = new ArrayList<>();
for (final String group : getGroups()) {
tags.add(new Tag(group, UIHelper.getColorForName(group)));
}
- switch (getMostAvailableStatus()) {
- case CHAT:
- case ONLINE:
- tags.add(new Tag("online", 0xff259b24));
- break;
- case AWAY:
- tags.add(new Tag("away", 0xffff9800));
- break;
- case XA:
- tags.add(new Tag("not available", 0xfff44336));
- break;
- case DND:
- tags.add(new Tag("dnd", 0xfff44336));
- break;
+ Presence.Status status = getMostAvailableStatus();
+ if (status != Presence.Status.OFFLINE) {
+ tags.add(UIHelper.getTagForStatus(context, status));
}
if (isBlocked()) {
tags.add(new Tag("blocked", 0xff2e2f3b));
@@ -167,7 +155,7 @@ public class Contact implements ListItem, Blockable {
return tags;
}
- public boolean match(String needle) {
+ public boolean match(Context context, String needle) {
if (needle == null || needle.isEmpty()) {
return true;
}
@@ -175,7 +163,7 @@ public class Contact implements ListItem, Blockable {
String[] parts = needle.split("\\s+");
if (parts.length > 1) {
for(int i = 0; i < parts.length; ++i) {
- if (!match(parts[i])) {
+ if (!match(context, parts[i])) {
return false;
}
}
@@ -183,13 +171,13 @@ public class Contact implements ListItem, Blockable {
} else {
return jid.toString().contains(needle) ||
getDisplayName().toLowerCase(Locale.US).contains(needle) ||
- matchInTag(needle);
+ matchInTag(context, needle);
}
}
- private boolean matchInTag(String needle) {
+ private boolean matchInTag(Context context, String needle) {
needle = needle.toLowerCase(Locale.US);
- for (Tag tag : getTags()) {
+ for (Tag tag : getTags(context)) {
if (tag.getName().toLowerCase(Locale.US).contains(needle)) {
return true;
}
diff --git a/src/main/java/eu/siacs/conversations/entities/ListItem.java b/src/main/java/eu/siacs/conversations/entities/ListItem.java
index 22aedd4b3..178df2d16 100644
--- a/src/main/java/eu/siacs/conversations/entities/ListItem.java
+++ b/src/main/java/eu/siacs/conversations/entities/ListItem.java
@@ -1,5 +1,7 @@
package eu.siacs.conversations.entities;
+import android.content.Context;
+
import java.util.List;
import eu.siacs.conversations.xmpp.jid.Jid;
@@ -11,7 +13,7 @@ public interface ListItem extends Comparable<ListItem> {
Jid getJid();
- List<Tag> getTags();
+ List<Tag> getTags(Context context);
final class Tag {
private final String name;
@@ -31,5 +33,5 @@ public interface ListItem extends Comparable<ListItem> {
}
}
- boolean match(final String needle);
+ boolean match(Context context, final String needle);
}
diff --git a/src/main/java/eu/siacs/conversations/entities/Presence.java b/src/main/java/eu/siacs/conversations/entities/Presence.java
index 442f1bcac..485adaa13 100644
--- a/src/main/java/eu/siacs/conversations/entities/Presence.java
+++ b/src/main/java/eu/siacs/conversations/entities/Presence.java
@@ -17,41 +17,46 @@ public class Presence implements Comparable {
case XA: return "xa";
case DND: return "dnd";
}
-
return null;
}
+
+ public static Status fromShowString(String show) {
+ if (show == null) {
+ return ONLINE;
+ } else {
+ switch (show.toLowerCase(Locale.US)) {
+ case "away":
+ return AWAY;
+ case "xa":
+ return XA;
+ case "dnd":
+ return DND;
+ case "chat":
+ return CHAT;
+ default:
+ return ONLINE;
+ }
+ }
+ }
}
protected final Status status;
protected ServiceDiscoveryResult disco;
protected final String ver;
protected final String hash;
+ protected final String message;
- private Presence(Status status, String ver, String hash) {
+ private Presence(Status status, String ver, String hash, String message) {
this.status = status;
this.ver = ver;
this.hash = hash;
+ this.message = message;
}
- public static Presence parse(String show, Element caps) {
+ public static Presence parse(String show, Element caps, String message) {
final String hash = caps == null ? null : caps.getAttribute("hash");
final String ver = caps == null ? null : caps.getAttribute("ver");
- if (show == null) {
- return new Presence(Status.ONLINE, ver, hash);
- } else {
- switch (show.toLowerCase(Locale.US)) {
- case "away":
- return new Presence(Status.AWAY, ver, hash);
- case "xa":
- return new Presence(Status.XA, ver, hash);
- case "dnd":
- return new Presence(Status.DND, ver, hash);
- case "chat":
- return new Presence(Status.CHAT, ver, hash);
- default:
- return new Presence(Status.ONLINE, ver, hash);
- }
- }
+ return new Presence(Status.fromShowString(show), ver, hash, message);
}
public int compareTo(Object other) {
diff --git a/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java
new file mode 100644
index 000000000..dd45d7e46
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/entities/PresenceTemplate.java
@@ -0,0 +1,55 @@
+package eu.siacs.conversations.entities;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+
+
+public class PresenceTemplate extends AbstractEntity {
+
+ public static final String TABELNAME = "presence_templates";
+ public static final String LAST_USED = "last_used";
+ public static final String MESSAGE = "message";
+ public static final String STATUS = "status";
+
+ private long lastUsed = 0;
+ private String statusMessage;
+ private Presence.Status status = Presence.Status.ONLINE;
+
+ public PresenceTemplate(Presence.Status status, String statusMessage) {
+ this.status = status;
+ this.statusMessage = statusMessage;
+ this.lastUsed = System.currentTimeMillis();
+ this.uuid = java.util.UUID.randomUUID().toString();
+ }
+
+ private PresenceTemplate() {
+
+ }
+
+ @Override
+ public ContentValues getContentValues() {
+ ContentValues values = new ContentValues();
+ values.put(LAST_USED, lastUsed);
+ values.put(MESSAGE, statusMessage);
+ values.put(STATUS, status.toShowString());
+ values.put(UUID, uuid);
+ return values;
+ }
+
+ public static PresenceTemplate fromCursor(Cursor cursor) {
+ PresenceTemplate template = new PresenceTemplate();
+ template.uuid = cursor.getString(cursor.getColumnIndex(UUID));
+ template.lastUsed = cursor.getLong(cursor.getColumnIndex(LAST_USED));
+ template.statusMessage = cursor.getString(cursor.getColumnIndex(MESSAGE));
+ template.status = Presence.Status.fromShowString(cursor.getString(cursor.getColumnIndex(STATUS)));
+ return template;
+ }
+
+ public Presence.Status getStatus() {
+ return status;
+ }
+
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java
index 813eda7a9..5fe10de0f 100644
--- a/src/main/java/eu/siacs/conversations/entities/Presences.java
+++ b/src/main/java/eu/siacs/conversations/entities/Presences.java
@@ -1,8 +1,10 @@
package eu.siacs.conversations.entities;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.List;
import eu.siacs.conversations.xml.Element;
@@ -57,4 +59,16 @@ public class Presences {
return presences.containsKey(presence);
}
}
+
+ public List<String> getStatusMessages() {
+ ArrayList<String> messages = new ArrayList<>();
+ synchronized (this.presences) {
+ for(Presence presence : this.presences.values()) {
+ if (presence.message != null && !presence.message.trim().isEmpty()) {
+ messages.add(presence.message.trim());
+ }
+ }
+ }
+ return messages;
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java
index c2782d232..e6cfa38fe 100644
--- a/src/main/java/eu/siacs/conversations/parser/PresenceParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/PresenceParser.java
@@ -196,9 +196,10 @@ public class PresenceParser extends AbstractParser implements
final String show = packet.findChildContent("show");
final Element caps = packet.findChild("c", "http://jabber.org/protocol/caps");
- final Presence presence = Presence.parse(show, caps);
+ final String message = packet.findChildContent("status");
+ final Presence presence = Presence.parse(show, caps, message);
contact.updatePresence(resource, presence);
- if (presence.hasCaps() && Config.REQUEST_DISCO) {
+ if (presence.hasCaps() && !from.equals(account.getJid())) {
mXmppConnectionService.fetchCaps(account, from, presence);
}
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
index 04c532382..dde385bd9 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -41,6 +41,7 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.PresenceTemplate;
import eu.siacs.conversations.entities.Roster;
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
@@ -51,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 = 25;
+ private static final int DATABASE_VERSION = 26;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -73,6 +74,14 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ "UNIQUE(" + ServiceDiscoveryResult.HASH + ", "
+ ServiceDiscoveryResult.VER + ") ON CONFLICT REPLACE);";
+ private static String CREATE_PRESENCE_TEMPLATES_STATEMENT = "CREATE TABLE "
+ + PresenceTemplate.TABELNAME + "("
+ + PresenceTemplate.UUID + " TEXT, "
+ + PresenceTemplate.LAST_USED + " NUMBER,"
+ + PresenceTemplate.MESSAGE + " TEXT,"
+ + PresenceTemplate.STATUS + " TEXT,"
+ + "UNIQUE("+PresenceTemplate.MESSAGE + "," +PresenceTemplate.STATUS+") ON CONFLICT REPLACE);";
+
private static String CREATE_PREKEYS_STATEMENT = "CREATE TABLE "
+ SQLiteAxolotlStore.PREKEY_TABLENAME + "("
+ SQLiteAxolotlStore.ACCOUNT + " TEXT, "
@@ -135,13 +144,19 @@ public class DatabaseBackend extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("PRAGMA foreign_keys=ON;");
- db.execSQL("create table " + Account.TABLENAME + "(" + Account.UUID
- + " TEXT PRIMARY KEY," + Account.USERNAME + " TEXT,"
- + Account.SERVER + " TEXT," + Account.PASSWORD + " TEXT,"
+ db.execSQL("create table " + Account.TABLENAME + "(" + Account.UUID+ " TEXT PRIMARY KEY,"
+ + Account.USERNAME + " TEXT,"
+ + Account.SERVER + " TEXT,"
+ + Account.PASSWORD + " TEXT,"
+ Account.DISPLAY_NAME + " TEXT, "
- + Account.ROSTERVERSION + " TEXT," + Account.OPTIONS
- + " NUMBER, " + Account.AVATAR + " TEXT, " + Account.KEYS
- + " TEXT, " + Account.HOSTNAME + " TEXT, " + Account.PORT + " NUMBER DEFAULT 5222)");
+ + Account.STATUS + " TEXT,"
+ + Account.STATUS_MESSAGE + " TEXT,"
+ + Account.ROSTERVERSION + " TEXT,"
+ + Account.OPTIONS + " NUMBER, "
+ + Account.AVATAR + " TEXT, "
+ + Account.KEYS + " TEXT, "
+ + Account.HOSTNAME + " TEXT, "
+ + Account.PORT + " NUMBER DEFAULT 5222)");
db.execSQL("create table " + Conversation.TABLENAME + " ("
+ Conversation.UUID + " TEXT PRIMARY KEY, " + Conversation.NAME
+ " TEXT, " + Conversation.CONTACT + " TEXT, "
@@ -175,6 +190,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL(CREATE_PREKEYS_STATEMENT);
db.execSQL(CREATE_SIGNED_PREKEYS_STATEMENT);
db.execSQL(CREATE_IDENTITIES_STATEMENT);
+ db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT);
}
@Override
@@ -319,6 +335,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
recreateAxolotlDb(db);
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
+ Message.FINGERPRINT + " TEXT");
+ } else if (oldVersion < 22 && newVersion >= 22) {
+ db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE);
}
if (oldVersion < 16 && newVersion >= 16) {
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN "
@@ -331,6 +349,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.HOSTNAME + " TEXT");
db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.PORT + " NUMBER DEFAULT 5222");
}
+ if (oldVersion < 26 && newVersion >= 26) {
+ db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.STATUS + " TEXT");
+ db.execSQL("ALTER TABLE " + Account.TABLENAME + " ADD COLUMN " + Account.STATUS_MESSAGE + " TEXT");
+ }
/* Any migrations that alter the Account table need to happen BEFORE this migration, as it
* depends on account de-serialization.
*/
@@ -365,10 +387,6 @@ public class DatabaseBackend extends SQLiteOpenHelper {
}
}
- if (oldVersion < 22 && newVersion >= 22) {
- db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE);
- }
-
if (oldVersion < 23 && newVersion >= 23) {
db.execSQL(CREATE_DISCOVERY_RESULTS_STATEMENT);
}
@@ -380,6 +398,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
if (oldVersion < 25 && newVersion >= 25) {
db.execSQL("ALTER TABLE " + Message.TABLENAME + " ADD COLUMN " + Message.OOB + " INTEGER");
}
+
+ if (oldVersion < 26 && newVersion >= 26) {
+ db.execSQL(CREATE_PRESENCE_TEMPLATES_STATEMENT);
+ }
}
public static synchronized DatabaseBackend getInstance(Context context) {
@@ -430,6 +452,30 @@ public class DatabaseBackend extends SQLiteOpenHelper {
return result;
}
+ public void insertPresenceTemplate(PresenceTemplate template) {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.insert(PresenceTemplate.TABELNAME, null, template.getContentValues());
+ }
+
+ public List<PresenceTemplate> getPresenceTemplates() {
+ ArrayList<PresenceTemplate> templates = new ArrayList<>();
+ SQLiteDatabase db = this.getReadableDatabase();
+ Cursor cursor = db.query(PresenceTemplate.TABELNAME,null,null,null,null,null,PresenceTemplate.LAST_USED+" desc");
+ while (cursor.moveToNext()) {
+ templates.add(PresenceTemplate.fromCursor(cursor));
+ }
+ cursor.close();
+ return templates;
+ }
+
+ public void deletePresenceTemplate(PresenceTemplate template) {
+ Log.d(Config.LOGTAG,"deleting presence template with uuid "+template.getUuid());
+ SQLiteDatabase db = this.getWritableDatabase();
+ String where = PresenceTemplate.UUID+"=?";
+ String[] whereArgs = {template.getUuid()};
+ db.delete(PresenceTemplate.TABELNAME,where,whereArgs);
+ }
+
public CopyOnWriteArrayList<Conversation> getConversations(int status) {
CopyOnWriteArrayList<Conversation> list = new CopyOnWriteArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
index 306092141..c63ce870f 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -20,6 +20,7 @@ import android.system.StructStat;
import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
+import android.util.LruCache;
import android.webkit.MimeTypeMap;
import java.io.ByteArrayOutputStream;
@@ -344,20 +345,28 @@ public class FileBackend {
}
}
- public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
- throws FileNotFoundException {
- Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get(message.getUuid());
+ public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) throws FileNotFoundException {
+ final String uuid = message.getUuid();
+ final LruCache<String,Bitmap> cache = mXmppConnectionService.getBitmapCache();
+ Log.d(Config.LOGTAG,"get thumbnail for "+uuid+" cacheOnly="+Boolean.toString(cacheOnly));
+ Bitmap thumbnail = cache.get(uuid);
if ((thumbnail == null) && (!cacheOnly)) {
- File file = getFile(message);
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = calcSampleSize(file, size);
- Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options);
- if (fullsize == null) {
- throw new FileNotFoundException();
+ synchronized (cache) {
+ thumbnail = cache.get(uuid);
+ if (thumbnail != null) {
+ return thumbnail;
+ }
+ File file = getFile(message);
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = calcSampleSize(file, size);
+ Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
+ if (fullsize == null) {
+ throw new FileNotFoundException();
+ }
+ thumbnail = resize(fullsize, size);
+ thumbnail = rotate(thumbnail, getRotation(file));
+ this.mXmppConnectionService.getBitmapCache().put(uuid, thumbnail);
}
- thumbnail = resize(fullsize, size);
- thumbnail = rotate(thumbnail, getRotation(file));
- this.mXmppConnectionService.getBitmapCache().put(message.getUuid(),thumbnail);
}
return thumbnail;
}
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 90e8470db..ec06410f9 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -73,6 +73,7 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
import eu.siacs.conversations.entities.Presence;
+import eu.siacs.conversations.entities.PresenceTemplate;
import eu.siacs.conversations.entities.Roster;
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
import eu.siacs.conversations.entities.Transferable;
@@ -624,6 +625,10 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
return getPreferences().getBoolean("xa_on_silent_mode", false);
}
+ private boolean manuallyChangePresence() {
+ return getPreferences().getBoolean("manually_change_presence", false);
+ }
+
private boolean treatVibrateAsSilent() {
return getPreferences().getBoolean("treat_vibrate_as_silent", false);
}
@@ -757,7 +762,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void toggleScreenEventReceiver() {
- if (awayWhenScreenOff()) {
+ if (awayWhenScreenOff() && !manuallyChangePresence()) {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(this.mEventReceiver, filter);
@@ -1503,6 +1508,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void onIqPacketReceived(final Account account, final IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.RESULT) {
account.setPassword(newPassword);
+ account.setOption(Account.OPTION_MAGIC_CREATE, false);
databaseBackend.updateAccount(account);
callback.onPasswordChangeSucceeded();
} else {
@@ -2993,7 +2999,17 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void sendPresence(final Account account) {
- sendPresencePacket(account, mPresenceGenerator.selfPresence(account, getTargetPresence()));
+ PresencePacket packet;
+ if (manuallyChangePresence()) {
+ packet = mPresenceGenerator.selfPresence(account, account.getPresenceStatus());
+ String message = account.getPresenceStatusMessage();
+ if (message != null && !message.isEmpty()) {
+ packet.addChild(new Element("status").setContent(message));
+ }
+ } else {
+ packet = mPresenceGenerator.selfPresence(account, getTargetPresence());
+ }
+ sendPresencePacket(account, packet);
}
public void refreshAllPresences() {
@@ -3224,6 +3240,31 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
return pending;
}
+ public void changeStatus(Account account, Presence.Status status, String statusMessage) {
+ if (!statusMessage.isEmpty()) {
+ databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage));
+ }
+ changeStatusReal(account, status, statusMessage);
+ }
+
+ private void changeStatusReal(Account account, Presence.Status status, String statusMessage) {
+ account.setPresenceStatus(status);
+ account.setPresenceStatusMessage(statusMessage);
+ databaseBackend.updateAccount(account);
+ if (!account.isOptionSet(Account.OPTION_DISABLED)) {
+ sendPresence(account);
+ }
+ }
+
+ public void changeStatus(Presence.Status status, String statusMessage) {
+ if (!statusMessage.isEmpty()) {
+ databaseBackend.insertPresenceTemplate(new PresenceTemplate(status, statusMessage));
+ }
+ for(Account account : getAccounts()) {
+ changeStatusReal(account, status, statusMessage);
+ }
+ }
+
public interface OnMamPreferencesFetched {
void onPreferencesFetched(Element prefs);
void onPreferencesFetchFailed();
diff --git a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
index 5a85c17bd..abec8ed76 100644
--- a/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/BlocklistActivity.java
@@ -49,7 +49,7 @@ public class BlocklistActivity extends AbstractSearchableListItemActivity implem
if (account != null) {
for (final Jid jid : account.getBlocklist()) {
final Contact contact = account.getRoster().getContact(jid);
- if (contact.match(needle) && contact.isBlocked()) {
+ if (contact.match(this, needle) && contact.isBlocked()) {
getListItems().add(contact);
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java
index ccb3a22e3..d4ef40901 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChangePasswordActivity.java
@@ -1,9 +1,11 @@
package eu.siacs.conversations.ui;
+import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.TextView;
import android.widget.Toast;
import eu.siacs.conversations.R;
@@ -22,7 +24,7 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti
final String currentPassword = mCurrentPassword.getText().toString();
final String newPassword = mNewPassword.getText().toString();
final String newPasswordConfirm = mNewPasswordConfirm.getText().toString();
- if (!currentPassword.equals(mAccount.getPassword())) {
+ if (!mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && !currentPassword.equals(mAccount.getPassword())) {
mCurrentPassword.requestFocus();
mCurrentPassword.setError(getString(R.string.account_status_unauthorized));
} else if (!newPassword.equals(newPasswordConfirm)) {
@@ -43,6 +45,7 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti
}
}
};
+ private TextView mCurrentPasswordLabel;
private EditText mCurrentPassword;
private EditText mNewPassword;
private EditText mNewPasswordConfirm;
@@ -51,7 +54,13 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti
@Override
void onBackendConnected() {
this.mAccount = extractAccount(getIntent());
-
+ if (this.mAccount != null && this.mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
+ this.mCurrentPasswordLabel.setVisibility(View.GONE);
+ this.mCurrentPassword.setVisibility(View.GONE);
+ } else {
+ this.mCurrentPasswordLabel.setVisibility(View.VISIBLE);
+ this.mCurrentPassword.setVisibility(View.VISIBLE);
+ }
}
@Override
@@ -67,12 +76,21 @@ public class ChangePasswordActivity extends XmppActivity implements XmppConnecti
});
this.mChangePasswordButton = (Button) findViewById(R.id.right_button);
this.mChangePasswordButton.setOnClickListener(this.mOnChangePasswordButtonClicked);
+ this.mCurrentPasswordLabel = (TextView) findViewById(R.id.current_password_label);
this.mCurrentPassword = (EditText) findViewById(R.id.current_password);
this.mNewPassword = (EditText) findViewById(R.id.new_password);
this.mNewPasswordConfirm = (EditText) findViewById(R.id.new_password_confirm);
}
@Override
+ protected void onStart() {
+ super.onStart();
+ Intent intent = getIntent();
+ String password = intent != null ? intent.getStringExtra("password") : "";
+ this.mNewPassword.getEditableText().append(password);
+ }
+
+ @Override
public void onPasswordChangeSucceeded() {
runOnUiThread(new Runnable() {
@Override
diff --git a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
index c5357a5ef..1698343b0 100644
--- a/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ChooseContactActivity.java
@@ -144,7 +144,7 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity {
for (final Contact contact : account.getRoster().getContacts()) {
if (contact.showInRoster() &&
!filterContacts.contains(contact.getJid().toBareJid().toString())
- && contact.match(needle)) {
+ && contact.match(this, needle)) {
getListItems().add(contact);
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
index a27570704..c806a03e4 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java
@@ -528,11 +528,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
mAccountJid.setText(getString(R.string.using_account, account));
mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48)));
setTitle(mConversation.getName());
- if (Config.LOCK_DOMAINS_IN_CONVERSATIONS && mConversation.getJid().getDomainpart().equals(Config.CONFERENCE_DOMAIN_LOCK)) {
- mFullJid.setText(mConversation.getJid().getLocalpart());
- } else {
- mFullJid.setText(mConversation.getJid().toBareJid().toString());
- }
+ mFullJid.setText(mConversation.getJid().toBareJid().toString());
mYourNick.setText(mucOptions.getActualNick());
mRoleAffiliaton = (TextView) findViewById(R.id.muc_role);
if (mucOptions.online()) {
@@ -643,17 +639,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
}
}
- @SuppressWarnings("deprecation")
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private void setListItemBackgroundOnView(View view) {
- int sdk = android.os.Build.VERSION.SDK_INT;
- if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground));
- } else {
- view.setBackground(getResources().getDrawable(R.drawable.greybackground));
- }
- }
-
private void viewPgpKey(User user) {
PgpEngine pgp = xmppConnectionService.getPgpEngine();
if (pgp != null) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
index a43709ae5..415269d74 100644
--- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -42,6 +42,7 @@ import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.ListItem;
+import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate;
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.utils.CryptoHelper;
@@ -107,6 +108,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
private TextView contactJidTv;
private TextView accountJidTv;
private TextView lastseen;
+ private TextView statusMessage;
private CheckBox send;
private CheckBox receive;
private Button addContactButton;
@@ -203,6 +205,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
contactJidTv = (TextView) findViewById(R.id.details_contactjid);
accountJidTv = (TextView) findViewById(R.id.details_account);
lastseen = (TextView) findViewById(R.id.details_lastseen);
+ statusMessage = (TextView) findViewById(R.id.status_message);
send = (CheckBox) findViewById(R.id.details_send_presence);
receive = (CheckBox) findViewById(R.id.details_receive_presence);
badge = (QuickContactBadge) findViewById(R.id.details_contact_badge);
@@ -310,6 +313,25 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
send.setOnCheckedChangeListener(null);
receive.setOnCheckedChangeListener(null);
+ List<String> statusMessages = contact.getPresences().getStatusMessages();
+ if (statusMessages.size() == 0) {
+ statusMessage.setVisibility(View.GONE);
+ } else {
+ StringBuilder builder = new StringBuilder();
+ statusMessage.setVisibility(View.VISIBLE);
+ int s = statusMessages.size();
+ for(int i = 0; i < s; ++i) {
+ if (s > 1) {
+ builder.append("• ");
+ }
+ builder.append(statusMessages.get(i));
+ if (i < s - 1) {
+ builder.append("\n");
+ }
+ }
+ statusMessage.setText(builder);
+ }
+
if (contact.getOption(Contact.Options.FROM)) {
send.setText(R.string.send_presence_updates);
send.setChecked(true);
@@ -342,13 +364,13 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
receive.setEnabled(false);
send.setEnabled(false);
}
-
send.setOnCheckedChangeListener(this.mOnSendCheckedChange);
receive.setOnCheckedChangeListener(this.mOnReceiveCheckedChange);
} else {
addContactButton.setVisibility(View.VISIBLE);
send.setVisibility(View.GONE);
receive.setVisibility(View.GONE);
+ statusMessage.setVisibility(View.GONE);
}
if (contact.isBlocked() && !this.showDynamicTags) {
@@ -439,7 +461,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
keys.setVisibility(View.GONE);
}
- List<ListItem.Tag> tagList = contact.getTags();
+ List<ListItem.Tag> tagList = contact.getTags(this);
if (tagList.size() == 0 || !this.showDynamicTags) {
tags.setVisibility(View.GONE);
} else {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index a7f0f8d72..11bff7d95 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -5,6 +5,7 @@ import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
@@ -1471,7 +1472,11 @@ public class ConversationActivity extends XmppActivity
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
Uri uri = Uri.parse("package:" + getPackageName());
intent.setData(uri);
- startActivityForResult(intent, REQUEST_BATTERY_OP);
+ try {
+ startActivityForResult(intent, REQUEST_BATTERY_OP);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(ConversationActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show();
+ }
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 6abf76c25..091f11a95 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -485,9 +485,15 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
} else {
Account account = message.getConversation().getAccount();
- Intent intent = new Intent(activity, EditAccountActivity.class);
- intent.putExtra("jid", account.getJid().toBareJid().toString());
- intent.putExtra("fingerprint", message.getFingerprint());
+ Intent intent;
+ if (activity.manuallyChangePresence()) {
+ intent = new Intent(activity, SetPresenceActivity.class);
+ intent.putExtra(SetPresenceActivity.EXTRA_ACCOUNT, account.getJid().toBareJid().toString());
+ } else {
+ intent = new Intent(activity, EditAccountActivity.class);
+ intent.putExtra("jid", account.getJid().toBareJid().toString());
+ intent.putExtra("fingerprint", message.getFingerprint());
+ }
startActivity(intent);
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index 14c96b7a0..501a3ab7e 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -3,6 +3,7 @@ package eu.siacs.conversations.ui;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -36,6 +37,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.whispersystems.libaxolotl.IdentityKey;
import java.util.Set;
+import android.util.Log;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -109,6 +111,13 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
@Override
public void onClick(final View v) {
+ final String password = mPassword.getText().toString();
+ final String passwordConfirm = mPasswordConfirm.getText().toString();
+
+ if (!mInitMode && passwordChangedInMagicCreateMode()) {
+ gotoChangePassword(password);
+ return;
+ }
if (mInitMode && mAccount != null) {
mAccount.setOption(Account.OPTION_DISABLED, false);
}
@@ -173,9 +182,12 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
mAccountJid.requestFocus();
return;
}
+
final String password = mPassword.getText().toString();
-
if (mAccount != null) {
+ if (mInitMode && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
+ mAccount.setOption(Account.OPTION_MAGIC_CREATE, mAccount.getPassword().contains(password));
+ }
mAccount.setJid(jid);
mAccount.setPort(numericPort);
mAccount.setHostname(hostname);
@@ -297,9 +309,10 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
public void run() {
final Intent intent;
final XmppConnection connection = mAccount.getXmppConnection();
+ final boolean wasFirstAccount = xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1;
if (avatar != null || (connection != null && !connection.getFeatures().pep())) {
intent = new Intent(getApplicationContext(), StartConversationActivity.class);
- if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) {
+ if (wasFirstAccount) {
intent.putExtra("init", true);
}
} else {
@@ -307,6 +320,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
intent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toBareJid().toString());
intent.putExtra("setup", true);
}
+ if (wasFirstAccount) {
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ }
startActivity(intent);
finish();
}
@@ -322,7 +338,13 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
}
protected void updateSaveButton() {
- if (accountInfoEdited() && !mInitMode) {
+ boolean accountInfoEdited = accountInfoEdited();
+
+ if (!mInitMode && passwordChangedInMagicCreateMode()) {
+ this.mSaveButton.setText(R.string.change_password);
+ this.mSaveButton.setEnabled(true);
+ this.mSaveButton.setTextColor(getPrimaryTextColor());
+ } else if (accountInfoEdited && !mInitMode) {
this.mSaveButton.setText(R.string.save);
this.mSaveButton.setEnabled(true);
this.mSaveButton.setTextColor(getPrimaryTextColor());
@@ -341,7 +363,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
if (!mInitMode) {
if (mAccount != null && mAccount.isOnlineAndConnected()) {
this.mSaveButton.setText(R.string.save);
- if (!accountInfoEdited()) {
+ if (!accountInfoEdited) {
this.mSaveButton.setEnabled(false);
this.mSaveButton.setTextColor(getSecondaryTextColor());
}
@@ -358,16 +380,28 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
if (this.mAccount == null) {
return false;
}
+ return jidEdited() ||
+ !this.mAccount.getPassword().equals(this.mPassword.getText().toString()) ||
+ !this.mAccount.getHostname().equals(this.mHostname.getText().toString()) ||
+ !String.valueOf(this.mAccount.getPort()).equals(this.mPort.getText().toString());
+ }
+
+ protected boolean jidEdited() {
final String unmodified;
if (Config.DOMAIN_LOCK != null) {
unmodified = this.mAccount.getJid().getLocalpart();
} else {
unmodified = this.mAccount.getJid().toBareJid().toString();
}
- return !unmodified.equals(this.mAccountJid.getText().toString()) ||
- !this.mAccount.getPassword().equals(this.mPassword.getText().toString()) ||
- !this.mAccount.getHostname().equals(this.mHostname.getText().toString()) ||
- !String.valueOf(this.mAccount.getPort()).equals(this.mPort.getText().toString());
+ return !unmodified.equals(this.mAccountJid.getText().toString());
+ }
+
+ protected boolean passwordChangedInMagicCreateMode() {
+ return mAccount != null
+ && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)
+ && !this.mAccount.getPassword().equals(this.mPassword.getText().toString())
+ && !this.jidEdited()
+ && mAccount.isOnlineAndConnected();
}
@Override
@@ -404,7 +438,11 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
Uri uri = Uri.parse("package:"+getPackageName());
intent.setData(uri);
- startActivityForResult(intent,REQUEST_BATTERY_OP);
+ try {
+ startActivityForResult(intent, REQUEST_BATTERY_OP);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(EditAccountActivity.this, R.string.device_does_not_support_battery_op, Toast.LENGTH_SHORT).show();
+ }
}
});
this.mSessionEst = (TextView) findViewById(R.id.session_est);
@@ -455,7 +493,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices);
final MenuItem renewCertificate = menu.findItem(R.id.action_renew_certificate);
final MenuItem mamPrefs = menu.findItem(R.id.action_mam_prefs);
-
+ final MenuItem changePresence = menu.findItem(R.id.action_change_presence);
renewCertificate.setVisible(mAccount != null && mAccount.getPrivateKeyAlias() != null);
if (mAccount != null && mAccount.isOnlineAndConnected()) {
@@ -470,6 +508,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
if (otherDevices == null || otherDevices.isEmpty()) {
clearDevices.setVisible(false);
}
+ changePresence.setVisible(manuallyChangePresence());
} else {
showQrCode.setVisible(false);
showBlocklist.setVisible(false);
@@ -477,6 +516,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
changePassword.setVisible(false);
clearDevices.setVisible(false);
mamPrefs.setVisible(false);
+ changePresence.setVisible(false);
}
return super.onCreateOptionsMenu(menu);
}
@@ -515,8 +555,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
protected void onBackendConnected() {
if (this.jidToEdit != null) {
this.mAccount = xmppConnectionService.findAccountByJid(jidToEdit);
- this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER);
if (this.mAccount != null) {
+ this.mInitMode |= this.mAccount.isOptionSet(Account.OPTION_REGISTER);
if (this.mAccount.getPrivateKeyAlias() != null) {
this.mPassword.setHint(R.string.authenticate_with_certificate);
if (this.mInitMode) {
@@ -526,8 +566,8 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
updateAccountInformation(true);
}
}
- if (this.xmppConnectionService.getAccounts().size() == 0
- || this.mAccount == xmppConnectionService.getPendingAccount()) {
+ if ((Config.MAGIC_CREATE_DOMAIN == null && this.xmppConnectionService.getAccounts().size() == 0)
+ || (this.mAccount != null && this.mAccount == xmppConnectionService.getPendingAccount())) {
if (getActionBar() != null) {
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setDisplayShowHomeEnabled(false);
@@ -538,7 +578,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
}
if (Config.DOMAIN_LOCK == null) {
final KnownHostsAdapter mKnownHostsAdapter = new KnownHostsAdapter(this,
- android.R.layout.simple_list_item_1,
+ R.layout.simple_list_item,
xmppConnectionService.getKnownHosts());
this.mAccountJid.setAdapter(mKnownHostsAdapter);
}
@@ -559,9 +599,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
item.setChecked(!item.isChecked());
break;
case R.id.action_change_password_on_server:
- final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
- changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
- startActivity(changePasswordIntent);
+ gotoChangePassword(null);
break;
case R.id.action_mam_prefs:
editMamPrefs();
@@ -572,14 +610,32 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
case R.id.action_renew_certificate:
renewCertificate();
break;
+ case R.id.action_change_presence:
+ changePresence();
+ break;
}
return super.onOptionsItemSelected(item);
}
+ private void gotoChangePassword(String newPassword) {
+ final Intent changePasswordIntent = new Intent(this, ChangePasswordActivity.class);
+ changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
+ if (newPassword != null) {
+ changePasswordIntent.putExtra("password", newPassword);
+ }
+ startActivity(changePasswordIntent);
+ }
+
private void renewCertificate() {
KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null);
}
+ private void changePresence() {
+ Intent intent = new Intent(this, SetPresenceActivity.class);
+ intent.putExtra(SetPresenceActivity.EXTRA_ACCOUNT,mAccount.getJid().toBareJid().toString());
+ startActivity(intent);
+ }
+
@Override
public void alias(String alias) {
if (alias != null) {
@@ -828,65 +884,55 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
}
@Override
- public void onCaptchaRequested(final Account account, final String id, final Data data,
- final Bitmap captcha) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(this);
- final ImageView view = new ImageView(this);
- final LinearLayout layout = new LinearLayout(this);
- final EditText input = new EditText(this);
-
- view.setImageBitmap(captcha);
- view.setScaleType(ImageView.ScaleType.FIT_CENTER);
-
- input.setHint(getString(R.string.captcha_hint));
-
- layout.setOrientation(LinearLayout.VERTICAL);
- layout.addView(view);
- layout.addView(input);
+ public void onCaptchaRequested(final Account account, final String id, final Data data, final Bitmap captcha) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if ((mCaptchaDialog != null) && mCaptchaDialog.isShowing()) {
+ mCaptchaDialog.dismiss();
+ }
+ final AlertDialog.Builder builder = new AlertDialog.Builder(EditAccountActivity.this);
+ final View view = getLayoutInflater().inflate(R.layout.captcha, null);
+ final ImageView imageView = (ImageView) view.findViewById(R.id.captcha);
+ final EditText input = (EditText) view.findViewById(R.id.input);
+ imageView.setImageBitmap(captcha);
- builder.setTitle(getString(R.string.captcha_required));
- builder.setView(layout);
+ builder.setTitle(getString(R.string.captcha_required));
+ builder.setView(view);
- builder.setPositiveButton(getString(R.string.ok),
- new DialogInterface.OnClickListener() {
+ builder.setPositiveButton(getString(R.string.ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String rc = input.getText().toString();
+ data.put("username", account.getUsername());
+ data.put("password", account.getPassword());
+ data.put("ocr", rc);
+ data.submit();
+
+ if (xmppConnectionServiceBound) {
+ xmppConnectionService.sendCreateAccountWithCaptchaPacket(
+ account, id, data);
+ }
+ }
+ });
+ builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- String rc = input.getText().toString();
- data.put("username", account.getUsername());
- data.put("password", account.getPassword());
- data.put("ocr", rc);
- data.submit();
-
- if (xmppConnectionServiceBound) {
- xmppConnectionService.sendCreateAccountWithCaptchaPacket(
- account, id, data);
+ if (xmppConnectionService != null) {
+ xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null);
}
}
});
- builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (xmppConnectionService != null) {
- xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null);
- }
- }
- });
- builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- if (xmppConnectionService != null) {
- xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null);
- }
- }
- });
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if ((mCaptchaDialog != null) && mCaptchaDialog.isShowing()) {
- mCaptchaDialog.dismiss();
- }
+ builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (xmppConnectionService != null) {
+ xmppConnectionService.sendCreateAccountWithCaptchaPacket(account, null, null);
+ }
+ }
+ });
mCaptchaDialog = builder.create();
mCaptchaDialog.show();
}
diff --git a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
index a6b3c73c7..f77d9c0a8 100644
--- a/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
+++ b/src/main/java/eu/siacs/conversations/ui/EnterJidDialog.java
@@ -43,17 +43,14 @@ public class EnterJidDialog {
final String title, final String positiveButton,
final String prefilledJid, final String account, boolean allowEditJid
) {
- final boolean lock = Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.DOMAIN_LOCK != null;
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title);
View dialogView = LayoutInflater.from(context).inflate(R.layout.enter_jid_dialog, null);
final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id);
- jabberIdDesc.setText(lock ? R.string.username : R.string.account_settings_jabber_id);
+ jabberIdDesc.setText(R.string.account_settings_jabber_id);
final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
- if (!lock) {
- jid.setAdapter(new KnownHostsAdapter(context, android.R.layout.simple_list_item_1, knownHosts));
- }
+ jid.setAdapter(new KnownHostsAdapter(context, R.layout.simple_list_item, knownHosts));
if (prefilledJid != null) {
jid.append(prefilledJid);
if (!allowEditJid) {
@@ -64,16 +61,16 @@ public class EnterJidDialog {
}
}
- jid.setHint(Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.DOMAIN_LOCK != null ? R.string.username_hint : R.string.account_settings_example_jabber_id);
+ jid.setHint(R.string.account_settings_example_jabber_id);
if (account == null) {
StartConversationActivity.populateAccountSpinner(context, activatedAccounts, spinner);
} else {
ArrayAdapter<String> adapter = new ArrayAdapter<>(context,
- android.R.layout.simple_spinner_item,
+ R.layout.simple_list_item,
new String[] { account });
spinner.setEnabled(false);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ adapter.setDropDownViewResource(R.layout.simple_list_item);
spinner.setAdapter(adapter);
}
@@ -100,13 +97,9 @@ public class EnterJidDialog {
}
final Jid contactJid;
try {
- if (lock) {
- contactJid = Jid.fromParts(jid.getText().toString(), Config.DOMAIN_LOCK, null);
- } else {
- contactJid = Jid.fromString(jid.getText().toString());
- }
+ contactJid = Jid.fromString(jid.getText().toString());
} catch (final InvalidJidException e) {
- jid.setError(context.getString(lock ? R.string.invalid_username : R.string.invalid_jid));
+ jid.setError(context.getString(R.string.invalid_jid));
return;
}
diff --git a/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java b/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java
index 6b32bdc28..1b16e565d 100644
--- a/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/MagicCreateActivity.java
@@ -8,6 +8,7 @@ import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
+import android.widget.Toast;
import java.security.SecureRandom;
@@ -60,12 +61,14 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher {
account = new Account(jid, createPassword());
account.setOption(Account.OPTION_REGISTER, true);
account.setOption(Account.OPTION_DISABLED, true);
+ account.setOption(Account.OPTION_MAGIC_CREATE, true);
xmppConnectionService.createAccount(account);
}
Intent intent = new Intent(MagicCreateActivity.this, EditAccountActivity.class);
intent.putExtra("jid", account.getJid().toBareJid().toString());
intent.putExtra("init", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ Toast.makeText(MagicCreateActivity.this, R.string.secure_password_generated, Toast.LENGTH_SHORT).show();
startActivity(intent);
} catch (InvalidJidException e) {
mUsername.setError(getString(R.string.invalid_username));
diff --git a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
index 800d84c48..b117e55ff 100644
--- a/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ManageAccountActivity.java
@@ -121,8 +121,10 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
menu.findItem(R.id.mgmt_account_reconnect).setVisible(false);
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(false);
menu.findItem(R.id.mgmt_account_publish_avatar).setVisible(false);
+ menu.findItem(R.id.mgmt_account_change_presence).setVisible(false);
} else {
menu.findItem(R.id.mgmt_account_announce_pgp).setVisible(Config.supportOpenPgp());
+ menu.findItem(R.id.mgmt_account_change_presence).setVisible(manuallyChangePresence());
}
menu.setHeaderTitle(this.selectedAccount.getJid().toBareJid().toString());
}
@@ -156,7 +158,6 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
addAccount.setVisible(!(Config.LOCK_SETTINGS || Config.SINGLE_ACCOUNT));
}
addAccountWithCertificate.setVisible(!(Config.LOCK_SETTINGS || Config.SINGLE_ACCOUNT));
-
return true;
}
@@ -176,6 +177,9 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
case R.id.mgmt_account_announce_pgp:
publishOpenPGPPublicKey(selectedAccount);
return true;
+ case R.id.mgmt_account_change_presence:
+ changePresence(selectedAccount);
+ return true;
default:
return super.onContextItemSelected(item);
}
@@ -218,6 +222,20 @@ public class ManageAccountActivity extends XmppActivity implements OnAccountUpda
}
}
+ private void changePresence(Account account) {
+ Intent intent = new Intent(this, SetPresenceActivity.class);
+ intent.putExtra(SetPresenceActivity.EXTRA_ACCOUNT,account.getJid().toBareJid().toString());
+ startActivity(intent);
+ }
+
+ public void onClickTglAccountState(Account account, boolean enable) {
+ if (enable) {
+ enableAccount(account);
+ } else {
+ disableAccount(account);
+ }
+ }
+
private void addAccountFromKey() {
try {
KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null);
diff --git a/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java
new file mode 100644
index 000000000..5fe9c5d8c
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/SetPresenceActivity.java
@@ -0,0 +1,200 @@
+package eu.siacs.conversations.ui;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import android.util.Log;
+
+import java.util.List;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.ListItem;
+import eu.siacs.conversations.entities.Presence;
+import eu.siacs.conversations.entities.PresenceTemplate;
+import eu.siacs.conversations.utils.UIHelper;
+
+public class SetPresenceActivity extends XmppActivity implements View.OnClickListener {
+
+ //data
+ protected Account mAccount;
+ private List<PresenceTemplate> mTemplates;
+
+ //UI Elements
+ protected ScrollView mScrollView;
+ protected EditText mStatusMessage;
+ protected Spinner mShowSpinner;
+ protected CheckBox mAllAccounts;
+ protected LinearLayout mTemplatesView;
+
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_set_presence);
+ mScrollView = (ScrollView) findViewById(R.id.scroll_view);
+ mShowSpinner = (Spinner) findViewById(R.id.presence_show);
+ ArrayAdapter adapter = ArrayAdapter.createFromResource(this,
+ R.array.presence_show_options,
+ R.layout.simple_list_item);
+ mShowSpinner.setAdapter(adapter);
+ mShowSpinner.setSelection(1);
+ mStatusMessage = (EditText) findViewById(R.id.presence_status_message);
+ mAllAccounts = (CheckBox) findViewById(R.id.all_accounts);
+ mTemplatesView = (LinearLayout) findViewById(R.id.templates);
+ final Button changePresence = (Button) findViewById(R.id.change_presence);
+ changePresence.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ executeChangePresence();
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.change_presence, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ if (item.getItemId() == R.id.action_account_details) {
+ if (mAccount != null) {
+ switchToAccount(mAccount);
+ }
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void executeChangePresence() {
+ Presence.Status status = getStatusFromSpinner();
+ boolean allAccounts = mAllAccounts.isChecked();
+ String statusMessage = mStatusMessage.getText().toString().trim();
+ if (allAccounts) {
+ xmppConnectionService.changeStatus(status, statusMessage);
+ } else if (mAccount != null) {
+ xmppConnectionService.changeStatus(mAccount, status, statusMessage);
+ }
+ finish();
+ }
+
+ private Presence.Status getStatusFromSpinner() {
+ switch (mShowSpinner.getSelectedItemPosition()) {
+ case 0:
+ return Presence.Status.CHAT;
+ case 2:
+ return Presence.Status.AWAY;
+ case 3:
+ return Presence.Status.XA;
+ case 4:
+ return Presence.Status.DND;
+ default:
+ return Presence.Status.ONLINE;
+ }
+ }
+
+ private void setStatusInSpinner(Presence.Status status) {
+ switch(status) {
+ case AWAY:
+ mShowSpinner.setSelection(2);
+ break;
+ case XA:
+ mShowSpinner.setSelection(3);
+ break;
+ case CHAT:
+ mShowSpinner.setSelection(0);
+ break;
+ case DND:
+ mShowSpinner.setSelection(4);
+ break;
+ default:
+ mShowSpinner.setSelection(1);
+ break;
+ }
+ }
+
+ @Override
+ protected void refreshUiReal() {
+
+ }
+
+ @Override
+ void onBackendConnected() {
+ mAccount = extractAccount(getIntent());
+ if (mAccount != null) {
+ setStatusInSpinner(mAccount.getPresenceStatus());
+ String message = mAccount.getPresenceStatusMessage();
+ if (mStatusMessage.getText().length() == 0 && message != null) {
+ mStatusMessage.append(message);
+ }
+ mTemplates = xmppConnectionService.databaseBackend.getPresenceTemplates();
+ }
+ redrawTemplates();
+ }
+
+ private void redrawTemplates() {
+ if (mTemplates == null || mTemplates.size() == 0) {
+ mTemplatesView.setVisibility(View.GONE);
+ } else {
+ mTemplatesView.removeAllViews();
+ mTemplatesView.setVisibility(View.VISIBLE);
+ LayoutInflater inflater = getLayoutInflater();
+ for (PresenceTemplate template : mTemplates) {
+ View templateLayout = inflater.inflate(R.layout.presence_template, mTemplatesView, false);
+ templateLayout.setTag(template);
+ setListItemBackgroundOnView(templateLayout);
+ templateLayout.setOnClickListener(this);
+ TextView message = (TextView) templateLayout.findViewById(R.id.presence_status_message);
+ TextView status = (TextView) templateLayout.findViewById(R.id.status);
+ ImageButton button = (ImageButton) templateLayout.findViewById(R.id.delete_button);
+ button.setTag(template);
+ button.setOnClickListener(this);
+ ListItem.Tag tag = UIHelper.getTagForStatus(this, template.getStatus());
+ status.setText(tag.getName());
+ status.setBackgroundColor(tag.getColor());
+ message.setText(template.getStatusMessage());
+ mTemplatesView.addView(templateLayout);
+ }
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ PresenceTemplate template = (PresenceTemplate) v.getTag();
+ if (template == null) {
+ return;
+ }
+ if (v.getId() == R.id.presence_template) {
+ setStatusInSpinner(template.getStatus());
+ mStatusMessage.getEditableText().clear();
+ mStatusMessage.getEditableText().append(template.getStatusMessage());
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ mScrollView.smoothScrollTo(0,0);
+ }
+ });
+ } else if (v.getId() == R.id.delete_button) {
+ xmppConnectionService.databaseBackend.deletePresenceTemplate(template);
+ mTemplates.remove(template);
+ redrawTemplates();
+ }
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
index 7e501f034..a1d4aa103 100644
--- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
@@ -161,7 +161,8 @@ public class SettingsActivity extends XmppActivity implements
"xa_on_silent_mode",
"away_when_screen_off",
"allow_message_correction",
- "treat_vibrate_as_silent");
+ "treat_vibrate_as_silent",
+ "manually_change_presence");
if (name.equals("resource")) {
String resource = preferences.getString("resource", "mobile")
.toLowerCase(Locale.US);
@@ -180,7 +181,8 @@ public class SettingsActivity extends XmppActivity implements
}
} else if (resendPresence.contains(name)) {
if (xmppConnectionServiceBound) {
- if (name.equals("away_when_screen_off")) {
+ if (name.equals("away_when_screen_off")
+ || name.equals("manually_change_presence")) {
xmppConnectionService.toggleScreenEventReceiver();
}
xmppConnectionService.refreshAllPresences();
diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
index 4ed015f4b..9a7414efb 100644
--- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
@@ -27,6 +27,7 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.adapter.ConversationAdapter;
+import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
@@ -264,6 +265,8 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
private void share(final Conversation conversation) {
final Account account = conversation.getAccount();
+ final XmppConnection connection = account.getXmppConnection();
+ final long max = connection == null ? -1 : connection.getFeatures().getMaxHttpUploadSize();
mListView.setEnabled(false);
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP && !hasPgp()) {
if (share.uuid == null) {
@@ -275,9 +278,6 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
return;
}
if (share.uris.size() != 0) {
- final long max = account.getXmppConnection()
- .getFeatures()
- .getMaxHttpUploadSize();
OnPresenceSelected callback = new OnPresenceSelected() {
@Override
public void onPresenceSelected() {
diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
index 7d650e5bb..78c05e41d 100644
--- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
@@ -390,13 +390,10 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
final View dialogView = getLayoutInflater().inflate(R.layout.join_conference_dialog, null);
final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
- final boolean lock = Config.LOCK_DOMAINS_IN_CONVERSATIONS && Config.CONFERENCE_DOMAIN_LOCK != null;
final TextView jabberIdDesc = (TextView) dialogView.findViewById(R.id.jabber_id);
- jabberIdDesc.setText(lock ? R.string.conference_name : R.string.conference_address);
- jid.setHint(lock ? R.string.conference_name : R.string.conference_address_example);
- if (!lock) {
- jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownConferenceHosts));
- }
+ jabberIdDesc.setText(R.string.conference_address);
+ jid.setHint(R.string.conference_address_example);
+ jid.setAdapter(new KnownHostsAdapter(this, R.layout.simple_list_item, mKnownConferenceHosts));
if (prefilledJid != null) {
jid.append(prefilledJid);
}
@@ -422,13 +419,9 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
}
final Jid conferenceJid;
try {
- if (lock) {
- conferenceJid = Jid.fromParts(jid.getText().toString(),Config.CONFERENCE_DOMAIN_LOCK, null);
- } else {
- conferenceJid = Jid.fromString(jid.getText().toString());
- }
+ conferenceJid = Jid.fromString(jid.getText().toString());
} catch (final InvalidJidException e) {
- jid.setError(getString(lock ? R.string.invalid_conference_name : R.string.invalid_jid));
+ jid.setError(getString(R.string.invalid_jid));
return;
}
@@ -494,16 +487,15 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
public static void populateAccountSpinner(Context context, List<String> accounts, Spinner spinner) {
if (accounts.size() > 0) {
- ArrayAdapter<String> adapter = new ArrayAdapter<>(context,
- android.R.layout.simple_spinner_item, accounts);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ ArrayAdapter<String> adapter = new ArrayAdapter<>(context, R.layout.simple_list_item, accounts);
+ adapter.setDropDownViewResource(R.layout.simple_list_item);
spinner.setAdapter(adapter);
spinner.setEnabled(true);
} else {
ArrayAdapter<String> adapter = new ArrayAdapter<>(context,
- android.R.layout.simple_spinner_item,
+ R.layout.simple_list_item,
Arrays.asList(new String[]{context.getString(R.string.no_accounts)}));
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ adapter.setDropDownViewResource(R.layout.simple_list_item);
spinner.setAdapter(adapter);
spinner.setEnabled(false);
}
@@ -738,7 +730,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
for (Contact contact : account.getRoster().getContacts()) {
Presence p = contact.getPresences().getMostAvailablePresence();
Presence.Status s = p == null ? Presence.Status.OFFLINE : p.getStatus();
- if (contact.showInRoster() && contact.match(needle)
+ if (contact.showInRoster() && contact.match(this, needle)
&& (!this.mHideOfflineContacts
|| (needle != null && !needle.trim().isEmpty())
|| s.compareTo(Presence.Status.OFFLINE) < 0)) {
@@ -756,7 +748,7 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
for (Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.State.DISABLED) {
for (Bookmark bookmark : account.getBookmarks()) {
- if (bookmark.match(needle)) {
+ if (bookmark.match(this, needle)) {
this.conferences.add(bookmark);
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
index ad6f7ba77..d4e8fa9f6 100644
--- a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java
@@ -28,7 +28,6 @@ public class WelcomeActivity extends Activity {
@Override
public void onClick(View v) {
startActivity(new Intent(WelcomeActivity.this, EditAccountActivity.class));
- finish();
}
});
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index 646c9d3f4..899d45412 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -381,19 +381,6 @@ public abstract class XmppActivity extends Activity {
}
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- final MenuItem menuSettings = menu.findItem(R.id.action_settings);
- final MenuItem menuManageAccounts = menu.findItem(R.id.action_accounts);
- if (menuSettings != null) {
- menuSettings.setVisible(!Config.LOCK_SETTINGS);
- }
- if (menuManageAccounts != null) {
- menuManageAccounts.setVisible(!Config.LOCK_SETTINGS);
- }
- return super.onCreateOptionsMenu(menu);
- }
-
protected boolean isOptimizingBattery() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
@@ -539,6 +526,17 @@ public abstract class XmppActivity extends Activity {
}
}
+ @SuppressWarnings("deprecation")
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ protected void setListItemBackgroundOnView(View view) {
+ int sdk = android.os.Build.VERSION.SDK_INT;
+ if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground));
+ } else {
+ view.setBackground(getResources().getDrawable(R.drawable.greybackground));
+ }
+ }
+
protected void choosePgpSignId(Account account) {
xmppConnectionService.getPgpEngine().chooseKey(account, new UiCallback<Account>() {
@Override
@@ -1009,6 +1007,10 @@ public abstract class XmppActivity extends Activity {
return getPreferences().getString("picture_compression", "auto").equals("never");
}
+ protected boolean manuallyChangePresence() {
+ return getPreferences().getBoolean("manually_change_presence", false);
+ }
+
protected void unregisterNdefPushMessageCallback() {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter != null && nfcAdapter.isEnabled()) {
@@ -1147,6 +1149,9 @@ public abstract class XmppActivity extends Activity {
@Override
protected Bitmap doInBackground(Message... params) {
+ if (isCancelled()) {
+ return null;
+ }
message = params[0];
try {
return xmppConnectionService.getFileBackend().getThumbnail(
@@ -1158,7 +1163,7 @@ public abstract class XmppActivity extends Activity {
@Override
protected void onPostExecute(Bitmap bitmap) {
- if (bitmap != null) {
+ if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
@@ -1177,6 +1182,7 @@ public abstract class XmppActivity extends Activity {
bm = null;
}
if (bm != null) {
+ cancelPotentialWork(message, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
@@ -1190,13 +1196,13 @@ public abstract class XmppActivity extends Activity {
try {
task.execute(message);
} catch (final RejectedExecutionException ignored) {
+ ignored.printStackTrace();
}
}
}
}
- public static boolean cancelPotentialWork(Message message,
- ImageView imageView) {
+ public static boolean cancelPotentialWork(Message message, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java
index f5f48a262..34c9d7b32 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java
@@ -126,12 +126,12 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
@Override
protected Bitmap doInBackground(Conversation... params) {
- return activity.avatarService().get(params[0], activity.getPixel(56));
+ return activity.avatarService().get(params[0], activity.getPixel(56), isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
- if (bitmap != null) {
+ if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
@@ -145,6 +145,7 @@ public class ConversationAdapter extends ArrayAdapter<Conversation> {
if (cancelPotentialWork(conversation, imageView)) {
final Bitmap bm = activity.avatarService().get(conversation, activity.getPixel(56), true);
if (bm != null) {
+ cancelPotentialWork(conversation, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
index da8e39101..c29b01bcf 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java
@@ -62,7 +62,7 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
ImageView picture = (ImageView) view.findViewById(R.id.contact_photo);
LinearLayout tagLayout = (LinearLayout) view.findViewById(R.id.tags);
- List<ListItem.Tag> tags = item.getTags();
+ List<ListItem.Tag> tags = item.getTags(activity);
if (tags.size() == 0 || !this.showDynamicTags) {
tagLayout.setVisibility(View.GONE);
} else {
@@ -106,12 +106,12 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
@Override
protected Bitmap doInBackground(ListItem... params) {
- return activity.avatarService().get(params[0], activity.getPixel(48));
+ return activity.avatarService().get(params[0], activity.getPixel(48), isCancelled());
}
@Override
protected void onPostExecute(Bitmap bitmap) {
- if (bitmap != null) {
+ if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
@@ -125,6 +125,7 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
if (cancelPotentialWork(item, imageView)) {
final Bitmap bm = activity.avatarService().get(item,activity.getPixel(48),true);
if (bm != null) {
+ cancelPotentialWork(item, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
index d69fa4b95..88ce1dfd5 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -760,7 +760,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
@Override
protected void onPostExecute(Bitmap bitmap) {
- if (bitmap != null) {
+ if (bitmap != null && !isCancelled()) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
@@ -774,6 +774,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
if (cancelPotentialWork(message, imageView)) {
final Bitmap bm = activity.avatarService().get(message, activity.getPixel(48), true);
if (bm != null) {
+ cancelPotentialWork(message, imageView);
imageView.setImageBitmap(bm);
imageView.setBackgroundColor(0x00000000);
} else {
diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
index add3d80cb..5ab058d14 100644
--- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java
+++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java
@@ -14,7 +14,9 @@ import java.util.Locale;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.xmpp.jid.Jid;
@@ -267,4 +269,19 @@ public class UIHelper {
body = body.replace("?","").replace("¿","");
return LOCATION_QUESTIONS.contains(body);
}
+
+ public static ListItem.Tag getTagForStatus(Context context, Presence.Status status) {
+ switch (status) {
+ case CHAT:
+ return new ListItem.Tag(context.getString(R.string.presence_chat), 0xff259b24);
+ case AWAY:
+ return new ListItem.Tag(context.getString(R.string.presence_away), 0xffff9800);
+ case XA:
+ return new ListItem.Tag(context.getString(R.string.presence_xa), 0xfff44336);
+ case DND:
+ return new ListItem.Tag(context.getString(R.string.presence_dnd), 0xfff44336);
+ default:
+ return new ListItem.Tag(context.getString(R.string.presence_online), 0xff259b24);
+ }
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/utils/Xmlns.java b/src/main/java/eu/siacs/conversations/utils/Xmlns.java
index a19ec791f..ad30b3e63 100644
--- a/src/main/java/eu/siacs/conversations/utils/Xmlns.java
+++ b/src/main/java/eu/siacs/conversations/utils/Xmlns.java
@@ -7,5 +7,5 @@ public final class Xmlns {
public static final String ROSTER = "jabber:iq:roster";
public static final String REGISTER = "jabber:iq:register";
public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams";
- public static final String HTTP_UPLOAD = Config.LEGACY_NAMESPACE_HTTP_UPLOAD ? "eu:siacs:conversations:http:upload" : "urn:xmpp:http:upload";
+ public static final String HTTP_UPLOAD = "urn:xmpp:http:upload";
}
diff --git a/src/main/res/drawable-hdpi/ic_account_box_white_24dp.png b/src/main/res/drawable-hdpi/ic_account_box_white_24dp.png
new file mode 100644
index 000000000..2f0f491d6
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_account_box_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-hdpi/ic_announcement_white_24dp.png b/src/main/res/drawable-hdpi/ic_announcement_white_24dp.png
new file mode 100644
index 000000000..034702001
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_announcement_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_account_box_white_24dp.png b/src/main/res/drawable-mdpi/ic_account_box_white_24dp.png
new file mode 100644
index 000000000..895b2ebf0
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_account_box_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_announcement_white_24dp.png b/src/main/res/drawable-mdpi/ic_announcement_white_24dp.png
new file mode 100644
index 000000000..e1039350b
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_announcement_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_account_box_white_24dp.png b/src/main/res/drawable-xhdpi/ic_account_box_white_24dp.png
new file mode 100644
index 000000000..1fbad8ca1
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_account_box_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_announcement_white_24dp.png b/src/main/res/drawable-xhdpi/ic_announcement_white_24dp.png
new file mode 100644
index 000000000..b1e9aa6ef
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_announcement_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_account_box_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_account_box_white_24dp.png
new file mode 100644
index 000000000..56cbb9566
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_account_box_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_announcement_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_announcement_white_24dp.png
new file mode 100644
index 000000000..d56a8f8e0
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_announcement_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxxhdpi/ic_account_box_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_account_box_white_24dp.png
new file mode 100644
index 000000000..a543c76b9
--- /dev/null
+++ b/src/main/res/drawable-xxxhdpi/ic_account_box_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxxhdpi/ic_announcement_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_announcement_white_24dp.png
new file mode 100644
index 000000000..3731138a3
--- /dev/null
+++ b/src/main/res/drawable-xxxhdpi/ic_announcement_white_24dp.png
Binary files differ
diff --git a/src/main/res/layout/activity_change_password.xml b/src/main/res/layout/activity_change_password.xml
index 1a4d00d81..6fb1d0131 100644
--- a/src/main/res/layout/activity_change_password.xml
+++ b/src/main/res/layout/activity_change_password.xml
@@ -2,23 +2,25 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/grey50">
+ android:background="@color/grey200">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/button_bar">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:layout_marginLeft="@dimen/activity_horizontal_margin"
- android:layout_marginRight="@dimen/activity_horizontal_margin"
- android:layout_marginTop="@dimen/activity_vertical_margin"
- android:layout_marginBottom="@dimen/activity_vertical_margin">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/activity_horizontal_margin"
+ android:layout_marginRight="@dimen/activity_horizontal_margin"
+ android:layout_marginTop="@dimen/activity_vertical_margin"
+ android:layout_marginBottom="@dimen/activity_vertical_margin"
+ android:background="@drawable/infocard_border"
+ android:padding="@dimen/infocard_padding"
+ android:orientation="vertical">
<TextView
+ android:id="@+id/current_password_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/current_password"
diff --git a/src/main/res/layout/activity_contact_details.xml b/src/main/res/layout/activity_contact_details.xml
index dd399e9a3..c5fe775a5 100644
--- a/src/main/res/layout/activity_contact_details.xml
+++ b/src/main/res/layout/activity_contact_details.xml
@@ -57,6 +57,7 @@
android:textIsSelectable="true" />
<LinearLayout
+ android:id="@+id/tags"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -71,6 +72,15 @@
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
</LinearLayout>
+
+ <TextView
+ android:layout_marginTop="8dp"
+ android:id="@+id/status_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/black87"
+ android:textStyle="italic"
+ android:textSize="?attr/TextSizeBody" />
<TextView
android:id="@+id/details_lastseen"
diff --git a/src/main/res/layout/activity_set_presence.xml b/src/main/res/layout/activity_set_presence.xml
new file mode 100644
index 000000000..8195092ff
--- /dev/null
+++ b/src/main/res/layout/activity_set_presence.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/grey200"
+ android:id="@+id/scroll_view">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/activity_horizontal_margin"
+ android:layout_marginRight="@dimen/activity_horizontal_margin"
+ android:layout_marginTop="@dimen/activity_vertical_margin"
+ android:layout_marginBottom="@dimen/activity_vertical_margin"
+ android:background="@drawable/infocard_border"
+ android:padding="@dimen/infocard_padding"
+ android:orientation="vertical">
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textMultiLine"
+ android:hint="@string/status_message"
+ android:id="@+id/presence_status_message"
+ android:textColor="@color/black87"
+ android:layout_marginBottom="8dp"
+ android:textSize="?attr/TextSizeBody"/>
+ <Spinner
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/presence_show"
+ android:layout_gravity="center_horizontal"/>
+ <CheckBox
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/all_accounts_on_this_device"
+ android:id="@+id/all_accounts"
+ android:textColor="@color/black87"
+ android:textSize="?attr/TextSizeBody"/>
+ <Button
+ android:id="@+id/change_presence"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_marginRight="-8dp"
+ android:layout_marginBottom="-8dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:text="@string/change_presence"
+ android:textColor="@color/accent"/>
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/templates"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/activity_horizontal_margin"
+ android:layout_marginRight="@dimen/activity_horizontal_margin"
+ android:layout_marginTop="@dimen/activity_vertical_margin"
+ android:layout_marginBottom="@dimen/activity_vertical_margin"
+ android:background="@drawable/infocard_border"
+ android:padding="@dimen/infocard_padding"
+ android:orientation="vertical"
+ android:divider="?android:dividerHorizontal"
+ android:showDividers="middle">
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView> \ No newline at end of file
diff --git a/src/main/res/layout/captcha.xml b/src/main/res/layout/captcha.xml
new file mode 100644
index 000000000..ea77b8354
--- /dev/null
+++ b/src/main/res/layout/captcha.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="16dp" >
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/captcha"
+ android:layout_gravity="center_horizontal"/>
+ <EditText
+ android:id="@+id/input"
+ android:layout_marginTop="8dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textNoSuggestions"
+ android:textColor="@color/black87"
+ android:textColorHint="@color/black54"
+ android:textSize="?attr/TextSizeBody"
+ android:hint="@string/captcha_hint">
+
+ <requestFocus />
+ </EditText>
+
+</LinearLayout> \ No newline at end of file
diff --git a/src/main/res/layout/presence_template.xml b/src/main/res/layout/presence_template.xml
new file mode 100644
index 000000000..aa4ded5a6
--- /dev/null
+++ b/src/main/res/layout/presence_template.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:paddingTop="8dp"
+ android:paddingLeft="8dp"
+ android:paddingBottom="8dp"
+ android:id="@+id/presence_template">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_centerVertical="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_toLeftOf="@+id/delete_button"
+ android:layout_toStartOf="@+id/delete_button"
+ android:layout_marginRight="8dp">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/presence_status_message"
+ android:textColor="@color/black87"
+ android:textSize="?attr/TextSizeBody"/>
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="1dp"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp"
+ android:paddingTop="1dp"
+ android:textAllCaps="true"
+ android:textColor="@color/white"
+ android:textSize="?attr/TextSizeInfo"
+ android:layout_marginTop="4dp"/>
+ </LinearLayout>
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/delete_button"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:background="?android:selectableItemBackground"
+ android:padding="@dimen/image_button_padding"
+ android:src="?attr/icon_remove"/>
+</RelativeLayout> \ No newline at end of file
diff --git a/src/main/res/layout/simple_list_item.xml b/src/main/res/layout/simple_list_item.xml
new file mode 100644
index 000000000..8cbc1f923
--- /dev/null
+++ b/src/main/res/layout/simple_list_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@color/black87"
+ android:textSize="?attr/TextSizeBody"
+ android:gravity="center_vertical"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall" />
diff --git a/src/main/res/menu/change_presence.xml b/src/main/res/menu/change_presence.xml
new file mode 100644
index 000000000..f3dfadfd0
--- /dev/null
+++ b/src/main/res/menu/change_presence.xml
@@ -0,0 +1,17 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/action_account_details"
+ android:title="@string/account_details"
+ android:showAsAction="always"
+ android:icon="@drawable/ic_account_box_white_24dp"/>
+ <item
+ android:id="@+id/action_accounts"
+ android:orderInCategory="90"
+ android:showAsAction="never"
+ android:title="@string/action_accounts"/>
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+</menu> \ No newline at end of file
diff --git a/src/main/res/menu/editaccount.xml b/src/main/res/menu/editaccount.xml
index 5b0711954..3e449007b 100644
--- a/src/main/res/menu/editaccount.xml
+++ b/src/main/res/menu/editaccount.xml
@@ -1,6 +1,12 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
+ android:id="@+id/action_change_presence"
+ android:showAsAction="always"
+ android:title="@string/change_presence"
+ android:icon="@drawable/ic_announcement_white_24dp"/>
+
+ <item
android:id="@+id/action_show_qr_code"
android:showAsAction="never"
android:title="@string/show_qr_code"/>
diff --git a/src/main/res/menu/manageaccounts_context.xml b/src/main/res/menu/manageaccounts_context.xml
index ddfcb5535..1205b3291 100644
--- a/src/main/res/menu/manageaccounts_context.xml
+++ b/src/main/res/menu/manageaccounts_context.xml
@@ -2,6 +2,9 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
+ android:id="@+id/mgmt_account_change_presence"
+ android:title="@string/change_presence"/>
+ <item
android:id="@+id/mgmt_account_publish_avatar"
android:title="@string/mgmt_account_publish_avatar"/>
<item
diff --git a/src/main/res/values/arrays.xml b/src/main/res/values/arrays.xml
index cc04d98ba..ced7f54f1 100644
--- a/src/main/res/values/arrays.xml
+++ b/src/main/res/values/arrays.xml
@@ -75,4 +75,12 @@
<item>@string/contacts</item>
<item>@string/always</item>
</string-array>
+
+ <string-array name="presence_show_options">
+ <item>@string/presence_chat</item>
+ <item>@string/presence_online</item>
+ <item>@string/presence_away</item>
+ <item>@string/presence_xa</item>
+ <item>@string/presence_dnd</item>
+ </string-array>
</resources>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 7cdec8723..c983a9ce6 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -573,9 +573,8 @@
<string name="server_side_mam_prefs">Server-side archiving preferences</string>
<string name="fetching_mam_prefs">Fetching archiving preferences. Please wait…</string>
<string name="unable_to_fetch_mam_prefs">Unable to fetch archiving preferences</string>
- <string name="captcha_ocr">Captcha text</string>
<string name="captcha_required">Captcha required</string>
- <string name="captcha_hint">enter the text from the image</string>
+ <string name="captcha_hint">Enter the text from the image above</string>
<string name="certificate_chain_is_not_trusted">Certificate chain is not trusted</string>
<string name="jid_does_not_match_certificate">Jabber ID does not match certificate</string>
<string name="action_renew_certificate">Renew certificate</string>
@@ -654,4 +653,16 @@
<string name="create_account">Create new account</string>
<string name="use_existing_accout">Use an existing account</string>
<string name="pick_your_username">Choose your username</string>
+ <string name="pref_manually_change_presence">Manually change status</string>
+ <string name="pref_manually_change_presence_summary">Touch your avatar to change your status</string>
+ <string name="change_presence">Change Status</string>
+ <string name="status_message">Status message</string>
+ <string name="all_accounts_on_this_device">Set for all accounts on this device</string>
+ <string name="presence_chat">Free for Chat</string>
+ <string name="presence_online">Online</string>
+ <string name="presence_away">Away</string>
+ <string name="presence_xa">Not Available</string>
+ <string name="presence_dnd">Busy</string>
+ <string name="secure_password_generated">A secure password has been generated</string>
+ <string name="device_does_not_support_battery_op">Your device does not support opting out of battery optimization</string>
</resources>
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
index 5ce392765..b468363e5 100644
--- a/src/main/res/xml/preferences.xml
+++ b/src/main/res/xml/preferences.xml
@@ -214,14 +214,22 @@
<PreferenceCategory android:title="@string/pref_presence_settings">
<CheckBoxPreference
android:defaultValue="false"
+ android:key="manually_change_presence"
+ android:title="@string/pref_manually_change_presence"
+ android:summary="@string/pref_manually_change_presence_summary"
+ android:disableDependentsState="true"/>
+ <CheckBoxPreference
+ android:defaultValue="false"
android:key="away_when_screen_off"
android:summary="@string/pref_away_when_screen_off_summary"
- android:title="@string/pref_away_when_screen_off"/>
+ android:title="@string/pref_away_when_screen_off"
+ android:dependency="manually_change_presence"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="xa_on_silent_mode"
android:summary="@string/pref_xa_on_silent_mode_summary"
- android:title="@string/pref_xa_on_silent_mode"/>
+ android:title="@string/pref_xa_on_silent_mode"
+ android:dependency="manually_change_presence"/>
<CheckBoxPreference
android:dependency="xa_on_silent_mode"
android:defaultValue="false"