aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/AndroidManifest.xml56
-rw-r--r--src/main/java/eu/siacs/conversations/entities/Contact.java49
-rw-r--r--src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java2
-rw-r--r--src/main/java/eu/siacs/conversations/parser/MessageParser.java16
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java9
-rw-r--r--src/main/java/eu/siacs/conversations/services/AvatarService.java48
-rw-r--r--src/main/java/eu/siacs/conversations/services/NotificationService.java47
-rw-r--r--src/main/java/eu/siacs/conversations/ui/AboutActivity.java15
-rw-r--r--src/main/java/eu/siacs/conversations/ui/AboutPreference.java41
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java169
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java438
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java6
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java135
-rw-r--r--src/main/res/layout/activity_about.xml21
-rw-r--r--src/main/res/values-w820dp/dimens.xml7
-rw-r--r--src/main/res/values/dimens.xml5
-rw-r--r--src/main/res/values/strings.xml33
-rw-r--r--src/main/res/xml/preferences.xml3
18 files changed, 587 insertions, 513 deletions
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 95663a87..225091f9 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -19,10 +19,10 @@
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/ConversationsTheme"
- tools:replace="android:label">
- <service android:name="eu.siacs.conversations.services.XmppConnectionService" />
+ tools:replace="android:label" >
+ <service android:name=".services.XmppConnectionService" />
- <receiver android:name="eu.siacs.conversations.services.EventReceiver">
+ <receiver android:name=".services.EventReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
@@ -31,10 +31,10 @@
</receiver>
<activity
- android:name="eu.siacs.conversations.ui.ConversationActivity"
+ android:name=".ui.ConversationActivity"
android:label="@string/title_activity_conversations"
android:launchMode="singleTask"
- android:windowSoftInputMode="stateHidden">
+ android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -42,9 +42,9 @@
</intent-filter>
</activity>
<activity
- android:name="eu.siacs.conversations.ui.StartConversationActivity"
+ android:name=".ui.StartConversationActivity"
android:configChanges="orientation|screenSize"
- android:label="@string/title_activity_start_conversation">
+ android:label="@string/title_activity_start_conversation" >
<intent-filter>
<action android:name="android.intent.action.SENDTO" />
@@ -63,38 +63,40 @@
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
+
<category android:name="android.intent.category.DEFAULT" />
+
<data android:scheme="xmpp" />
</intent-filter>
</activity>
<activity
- android:name="eu.siacs.conversations.ui.SettingsActivity"
- android:label="@string/title_activity_settings"></activity>
+ android:name=".ui.SettingsActivity"
+ android:label="@string/title_activity_settings" />
<activity
- android:name="eu.siacs.conversations.ui.ChooseContactActivity"
- android:label="@string/title_activity_choose_contact"></activity>
+ android:name=".ui.ChooseContactActivity"
+ android:label="@string/title_activity_choose_contact" />
<activity
- android:name="eu.siacs.conversations.ui.ManageAccountActivity"
+ android:name=".ui.ManageAccountActivity"
android:configChanges="orientation|screenSize"
- android:label="@string/title_activity_manage_accounts"></activity>
+ android:label="@string/title_activity_manage_accounts" />
<activity
- android:name="eu.siacs.conversations.ui.EditAccountActivity"
- android:windowSoftInputMode="stateHidden|adjustResize"></activity>
+ android:name=".ui.EditAccountActivity"
+ android:windowSoftInputMode="stateHidden|adjustResize" />
<activity
- android:name="eu.siacs.conversations.ui.ConferenceDetailsActivity"
+ android:name=".ui.ConferenceDetailsActivity"
android:label="@string/title_activity_conference_details"
- android:windowSoftInputMode="stateHidden"></activity>
+ android:windowSoftInputMode="stateHidden" />
<activity
- android:name="eu.siacs.conversations.ui.ContactDetailsActivity"
+ android:name=".ui.ContactDetailsActivity"
android:label="@string/title_activity_contact_details"
- android:windowSoftInputMode="stateHidden"></activity>
+ android:windowSoftInputMode="stateHidden" />
<activity
- android:name="eu.siacs.conversations.ui.PublishProfilePictureActivity"
+ android:name=".ui.PublishProfilePictureActivity"
android:label="@string/mgmt_account_publish_avatar"
- android:windowSoftInputMode="stateHidden"></activity>
+ android:windowSoftInputMode="stateHidden" />
<activity
- android:name="eu.siacs.conversations.ui.ShareWithActivity"
- android:label="@string/title_activity_conversations">
+ android:name=".ui.ShareWithActivity"
+ android:label="@string/title_activity_conversations" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
@@ -111,6 +113,14 @@
</intent-filter>
</activity>
<activity android:name="de.duenndns.ssl.MemorizingActivity" />
+ <activity
+ android:name=".ui.AboutActivity"
+ android:label="@string/title_activity_about"
+ android:parentActivityName=".ui.SettingsActivity" >
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value="eu.siacs.conversations.ui.SettingsActivity" />
+ </activity>
</application>
</manifest>
diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java
index 60c31a42..af5172d3 100644
--- a/src/main/java/eu/siacs/conversations/entities/Contact.java
+++ b/src/main/java/eu/siacs/conversations/entities/Contact.java
@@ -24,6 +24,8 @@ public class Contact implements ListItem {
public static final String KEYS = "pgpkey";
public static final String ACCOUNT = "accountUuid";
public static final String AVATAR = "avatar";
+ public static final String LAST_PRESENCE = "last_presence";
+ public static final String LAST_TIME = "last_time";
protected String accountUuid;
protected String systemName;
@@ -43,9 +45,18 @@ public class Contact implements ListItem {
public Lastseen lastseen = new Lastseen();
- public Contact(String account, String systemName, String serverName,
- String jid, int subscription, String photoUri,
- String systemAccount, String keys, String avatar) {
+ public Contact(final String account, final String systemName, final String serverName,
+ final String jid, final int subscription, final String photoUri,
+ final String systemAccount, final String keys, final String avatar,
+ final Lastseen lastseen) {
+ this(account, systemName, serverName, jid, subscription, photoUri, systemAccount, keys,
+ avatar);
+ this.lastseen = lastseen;
+ }
+
+ public Contact(final String account, final String systemName, final String serverName,
+ final String jid, final int subscription, final String photoUri,
+ final String systemAccount, final String keys, final String avatar) {
this.accountUuid = account;
this.systemName = systemName;
this.serverName = serverName;
@@ -53,18 +64,15 @@ public class Contact implements ListItem {
this.subscription = subscription;
this.photoUri = photoUri;
this.systemAccount = systemAccount;
- if (keys == null) {
- keys = "";
- }
try {
- this.keys = new JSONObject(keys);
+ this.keys = (keys == null ? new JSONObject("") : new JSONObject(keys));
} catch (JSONException e) {
this.keys = new JSONObject();
}
this.avatar = avatar;
}
- public Contact(String jid) {
+ public Contact(final String jid) {
this.jid = jid;
}
@@ -106,10 +114,15 @@ public class Contact implements ListItem {
values.put(PHOTOURI, photoUri);
values.put(KEYS, keys.toString());
values.put(AVATAR, avatar);
+ values.put(LAST_PRESENCE, lastseen.presence);
+ values.put(LAST_TIME, lastseen.time);
return values;
}
- public static Contact fromCursor(Cursor cursor) {
+ public static Contact fromCursor(final Cursor cursor) {
+ final Lastseen lastseen = new Lastseen(
+ cursor.getString(cursor.getColumnIndex(LAST_PRESENCE)),
+ cursor.getLong(cursor.getColumnIndex(LAST_TIME)));
return new Contact(cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(SYSTEMNAME)),
cursor.getString(cursor.getColumnIndex(SERVERNAME)),
@@ -118,7 +131,8 @@ public class Contact implements ListItem {
cursor.getString(cursor.getColumnIndex(PHOTOURI)),
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
cursor.getString(cursor.getColumnIndex(KEYS)),
- cursor.getString(cursor.getColumnIndex(AVATAR)));
+ cursor.getString(cursor.getColumnIndex(AVATAR)),
+ lastseen);
}
public int getSubscription() {
@@ -306,9 +320,18 @@ public class Contact implements ListItem {
public static final int DIRTY_DELETE = 7;
}
- public class Lastseen {
- public long time = 0;
- public String presence = null;
+ public static class Lastseen {
+ public long time;
+ public String presence;
+
+ public Lastseen() {
+ time = 0;
+ presence = null;
+ }
+ public Lastseen(final String presence, final long time) {
+ this.time = time;
+ this.presence = presence;
+ }
}
@Override
diff --git a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java
index b8454d5e..dde01789 100644
--- a/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java
+++ b/src/main/java/eu/siacs/conversations/generator/AbstractGenerator.java
@@ -20,7 +20,7 @@ public abstract class AbstractGenerator {
"http://jabber.org/protocol/disco#info",
"urn:xmpp:avatar:metadata+notify",
"urn:xmpp:ping"};
- public final String IDENTITY_NAME = "Conversations 0.8.1";
+ public final String IDENTITY_NAME = "Conversations 0.8.2";
public final String IDENTITY_TYPE = "phone";
protected XmppConnectionService mXmppConnectionService;
diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
index 5b22ad61..472a2e46 100644
--- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java
+++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java
@@ -401,12 +401,6 @@ public class MessageParser extends AbstractParser implements
@Override
public void onMessagePacketReceived(Account account, MessagePacket packet) {
Message message = null;
- boolean notify = mXmppConnectionService.getPreferences().getBoolean(
- "show_notification", true);
- boolean alwaysNotifyInConference = notify
- && mXmppConnectionService.getPreferences().getBoolean(
- "always_notify_in_conference", false);
-
this.parseNick(packet, account);
if ((packet.getType() == MessagePacket.TYPE_CHAT || packet.getType() == MessagePacket.TYPE_NORMAL)) {
@@ -429,7 +423,6 @@ public class MessageParser extends AbstractParser implements
if (message != null) {
if (message.getStatus() == Message.STATUS_SEND) {
account.activateGracePeriod();
- notify = false;
mXmppConnectionService.markRead(
message.getConversation(), false);
} else {
@@ -444,14 +437,10 @@ public class MessageParser extends AbstractParser implements
if (message != null) {
if (message.getStatus() == Message.STATUS_RECEIVED) {
message.markUnread();
- notify = alwaysNotifyInConference
- || NotificationService
- .wasHighlightedOrPrivate(message);
} else {
mXmppConnectionService.markRead(message.getConversation(),
false);
account.activateGracePeriod();
- notify = false;
}
}
} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
@@ -498,10 +487,7 @@ public class MessageParser extends AbstractParser implements
if (message.trusted() && message.bodyContainsDownloadable()) {
this.mXmppConnectionService.getHttpConnectionManager()
.createNewConnection(message);
- notify = false;
- }
- notify = notify && !conversation.isMuted();
- if (notify) {
+ } else {
mXmppConnectionService.getNotificationService().push(message);
}
mXmppConnectionService.updateConversationUi();
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
index 12e5e251..ef045546 100644
--- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java
@@ -20,7 +20,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history";
- private static final int DATABASE_VERSION = 8;
+ private static final int DATABASE_VERSION = 9;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -28,6 +28,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ Contact.JID + " TEXT," + Contact.KEYS + " TEXT,"
+ Contact.PHOTOURI + " TEXT," + Contact.OPTIONS + " NUMBER,"
+ Contact.SYSTEMACCOUNT + " NUMBER, " + Contact.AVATAR + " TEXT, "
+ + Contact.LAST_PRESENCE + " TEXT, " + Contact.LAST_TIME + " NUMBER, "
+ "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
+ Account.TABLENAME + "(" + Account.UUID
+ ") ON DELETE CASCADE, UNIQUE(" + Contact.ACCOUNT + ", "
@@ -101,6 +102,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + Conversation.TABLENAME + " ADD COLUMN "
+ Conversation.ATTRIBUTES + " TEXT");
}
+ if (oldVersion < 9 && newVersion >= 9) {
+ db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN "
+ + Contact.LAST_TIME + " NUMBER");
+ db.execSQL("ALTER TABLE " + Contact.TABLENAME + " ADD COLUMN "
+ + Contact.LAST_PRESENCE + " TEXT");
+ }
}
public static synchronized DatabaseBackend getInstance(Context context) {
diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java
index bd27b555..778fd4dd 100644
--- a/src/main/java/eu/siacs/conversations/services/AvatarService.java
+++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java
@@ -1,5 +1,12 @@
package eu.siacs.conversations.services;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.net.Uri;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -10,12 +17,6 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.entities.MucOptions;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.net.Uri;
public class AvatarService {
@@ -41,19 +42,14 @@ public class AvatarService {
if (avatar != null) {
return avatar;
}
- avatar = mXmppConnectionService.getFileBackend().getAvatar(
- contact.getAvatar(), size);
+ if (contact.getProfilePhoto() != null) {
+ avatar = mXmppConnectionService.getFileBackend().cropCenterSquare(Uri.parse(contact.getProfilePhoto()), size);
+ }
+ if (avatar == null && contact.getAvatar() != null) {
+ avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size);
+ }
if (avatar == null) {
- if (contact.getProfilePhoto() != null) {
- avatar = mXmppConnectionService.getFileBackend()
- .cropCenterSquare(Uri.parse(contact.getProfilePhoto()),
- size);
- if (avatar == null) {
- avatar = get(contact.getDisplayName(), size);
- }
- } else {
- avatar = get(contact.getDisplayName(), size);
- }
+ avatar = get(contact.getDisplayName(), size);
}
this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
return avatar;
@@ -225,7 +221,7 @@ public class AvatarService {
}
private void drawTile(Canvas canvas, String letter, int tileColor,
- int left, int top, int right, int bottom) {
+ int left, int top, int right, int bottom) {
letter = letter.toUpperCase(Locale.getDefault());
Paint tilePaint = new Paint(), textPaint = new Paint();
tilePaint.setColor(tileColor);
@@ -244,15 +240,15 @@ public class AvatarService {
}
private void drawTile(Canvas canvas, MucOptions.User user, int left,
- int top, int right, int bottom) {
+ int top, int right, int bottom) {
Contact contact = user.getContact();
if (contact != null) {
Uri uri = null;
- if (contact.getAvatar() != null) {
+ if (contact.getProfilePhoto() != null) {
+ uri = Uri.parse(contact.getProfilePhoto());
+ } else if (contact.getAvatar() != null) {
uri = mXmppConnectionService.getFileBackend().getAvatarUri(
contact.getAvatar());
- } else if (contact.getProfilePhoto() != null) {
- uri = Uri.parse(contact.getProfilePhoto());
}
if (uri != null) {
Bitmap bitmap = mXmppConnectionService.getFileBackend()
@@ -277,15 +273,15 @@ public class AvatarService {
}
private void drawTile(Canvas canvas, Bitmap bm, int dstleft, int dsttop,
- int dstright, int dstbottom) {
+ int dstright, int dstbottom) {
Rect dst = new Rect(dstleft, dsttop, dstright, dstbottom);
canvas.drawBitmap(bm, null, dst, null);
}
private int getColorForName(String name) {
- int holoColors[] = { 0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5,
+ int holoColors[] = {0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5,
0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722,
- 0xFF795548, 0xFF607d8b };
+ 0xFF795548, 0xFF607d8b};
return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)];
}
diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java
index 7b2e16df..4cb28145 100644
--- a/src/main/java/eu/siacs/conversations/services/NotificationService.java
+++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java
@@ -1,11 +1,5 @@
package eu.siacs.conversations.services;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -23,6 +17,12 @@ import android.support.v4.app.TaskStackBuilder;
import android.text.Html;
import android.util.DisplayMetrics;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
@@ -46,7 +46,28 @@ public class NotificationService {
this.mXmppConnectionService = service;
}
+ public boolean notify(Message message) {
+ return (message.getStatus() == Message.STATUS_RECEIVED)
+ && notificationsEnabled()
+ && !message.getConversation().isMuted()
+ && (message.getConversation().getMode() == Conversation.MODE_SINGLE
+ || conferenceNotificationsEnabled()
+ || wasHighlightedOrPrivate(message)
+ );
+ }
+
+ public boolean notificationsEnabled() {
+ return mXmppConnectionService.getPreferences().getBoolean("show_notification", true);
+ }
+
+ public boolean conferenceNotificationsEnabled() {
+ return mXmppConnectionService.getPreferences().getBoolean("always_notify_in_conference", false);
+ }
+
public void push(Message message) {
+ if (!notify(message)) {
+ return;
+ }
PowerManager pm = (PowerManager) mXmppConnectionService
.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
@@ -110,7 +131,7 @@ public class NotificationService {
if (notify) {
if (vibrate) {
int dat = 70;
- long[] pattern = { 0, 3 * dat, dat, dat };
+ long[] pattern = {0, 3 * dat, dat, dat};
mBuilder.setVibrate(pattern);
}
if (ringtone != null) {
@@ -132,7 +153,7 @@ public class NotificationService {
style.setBigContentTitle(notifications.size()
+ " "
+ mXmppConnectionService
- .getString(R.string.unread_conversations));
+ .getString(R.string.unread_conversations));
StringBuilder names = new StringBuilder();
Conversation conversation = null;
for (ArrayList<Message> messages : notifications.values()) {
@@ -151,7 +172,7 @@ public class NotificationService {
mBuilder.setContentTitle(notifications.size()
+ " "
+ mXmppConnectionService
- .getString(R.string.unread_conversations));
+ .getString(R.string.unread_conversations));
mBuilder.setContentText(names.toString());
mBuilder.setStyle(style);
if (conversation != null) {
@@ -184,7 +205,7 @@ public class NotificationService {
}
private void modifyForImage(Builder builder, Message message,
- ArrayList<Message> messages, boolean notify) {
+ ArrayList<Message> messages, boolean notify) {
try {
Bitmap bitmap = mXmppConnectionService.getFileBackend()
.getThumbnail(message, getPixel(288), false);
@@ -210,7 +231,7 @@ public class NotificationService {
}
private void modifyForTextOnly(Builder builder,
- ArrayList<Message> messages, boolean notify) {
+ ArrayList<Message> messages, boolean notify) {
builder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(getMergedBodies(messages)));
builder.setContentText(getReadableBody(messages.get(0)));
@@ -244,7 +265,7 @@ public class NotificationService {
private String getReadableBody(Message message) {
if (message.getDownloadable() != null
&& (message.getDownloadable().getStatus() == Downloadable.STATUS_OFFER || message
- .getDownloadable().getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE)) {
+ .getDownloadable().getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE)) {
return mXmppConnectionService.getText(
R.string.image_offered_for_download).toString();
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
@@ -287,7 +308,7 @@ public class NotificationService {
return PendingIntent.getService(mXmppConnectionService, 0, intent, 0);
}
- public static boolean wasHighlightedOrPrivate(Message message) {
+ private boolean wasHighlightedOrPrivate(Message message) {
String nick = message.getConversation().getMucOptions().getActualNick();
Pattern highlight = generateNickHighlightPattern(nick);
if (message.getBody() == null || nick == null) {
diff --git a/src/main/java/eu/siacs/conversations/ui/AboutActivity.java b/src/main/java/eu/siacs/conversations/ui/AboutActivity.java
new file mode 100644
index 00000000..a61b872a
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/AboutActivity.java
@@ -0,0 +1,15 @@
+package eu.siacs.conversations.ui;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import eu.siacs.conversations.R;
+
+public class AboutActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_about);
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/AboutPreference.java b/src/main/java/eu/siacs/conversations/ui/AboutPreference.java
new file mode 100644
index 00000000..804b4e23
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/AboutPreference.java
@@ -0,0 +1,41 @@
+package eu.siacs.conversations.ui;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.preference.Preference;
+import android.util.AttributeSet;
+
+public class AboutPreference extends Preference {
+ public AboutPreference(final Context context, final AttributeSet attrs, final int defStyle) {
+ super(context, attrs, defStyle);
+ setSummary();
+ }
+
+ public AboutPreference(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ setSummary();
+ }
+
+ @Override
+ protected void onClick() {
+ super.onClick();
+ final Intent intent = new Intent(getContext(), AboutActivity.class);
+ getContext().startActivity(intent);
+ }
+
+ private void setSummary() {
+ if (getContext() != null && getContext().getPackageManager() != null) {
+ final String packageName = getContext().getPackageName();
+ final String versionName;
+ try {
+ versionName = getContext().getPackageManager().getPackageInfo(packageName, 0).versionName;
+ setSummary("Conversations " + versionName);
+ } catch (final PackageManager.NameNotFoundException e) {
+ // Using try/catch as part of the logic is sort of like this:
+ // https://xkcd.com/292/
+ }
+ }
+ }
+}
+
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index 6c3dff87..2a4ddd2b 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -10,10 +10,6 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.MediaStore;
@@ -35,6 +31,7 @@ import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
+import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
@@ -55,33 +52,33 @@ public class ConversationActivity extends XmppActivity implements
public static final int REQUEST_SEND_MESSAGE = 0x0201;
public static final int REQUEST_DECRYPT_PGP = 0x0202;
+ public static final int REQUEST_ENCRYPT_MESSAGE = 0x0207;
private static final int REQUEST_ATTACH_FILE_DIALOG = 0x0203;
private static final int REQUEST_IMAGE_CAPTURE = 0x0204;
private static final int REQUEST_RECORD_AUDIO = 0x0205;
private static final int REQUEST_SEND_PGP_IMAGE = 0x0206;
- public static final int REQUEST_ENCRYPT_MESSAGE = 0x0207;
-
private static final int ATTACHMENT_CHOICE_CHOOSE_IMAGE = 0x0301;
private static final int ATTACHMENT_CHOICE_TAKE_PHOTO = 0x0302;
private static final int ATTACHMENT_CHOICE_RECORD_VOICE = 0x0303;
private static final String STATE_OPEN_CONVERSATION = "state_open_conversation";
private static final String STATE_PANEL_OPEN = "state_panel_open";
+ private static final String STATE_PENDING_URI = "state_pending_uri";
private String mOpenConverstaion = null;
private boolean mPanelOpen = true;
+ private Uri mPendingImageUri = null;
private View mContentView;
private List<Conversation> conversationList = new ArrayList<Conversation>();
private Conversation selectedConversation = null;
private ListView listView;
+ private ConversationFragment mConversationFragment;
- private boolean paneShouldBeOpen = true;
private ArrayAdapter<Conversation> listAdapter;
private Toast prepareImageToast;
- private Uri pendingImageUri = null;
public List<Conversation> getConversationList() {
return this.conversationList;
@@ -99,10 +96,6 @@ public class ConversationActivity extends XmppActivity implements
return this.listView;
}
- public boolean shouldPaneBeOpen() {
- return paneShouldBeOpen;
- }
-
public void showConversationsOverview() {
if (mContentView instanceof SlidingPaneLayout) {
SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
@@ -113,8 +106,8 @@ public class ConversationActivity extends XmppActivity implements
@Override
protected String getShareableUri() {
Conversation conversation = getSelectedConversation();
- if (conversation!=null) {
- return "xmpp:"+conversation.getAccount().getJid();
+ if (conversation != null) {
+ return "xmpp:" + conversation.getAccount().getJid();
} else {
return "";
}
@@ -148,34 +141,39 @@ public class ConversationActivity extends XmppActivity implements
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- if (savedInstanceState != null) {
- mOpenConverstaion = savedInstanceState.getString(
+ if (savedInstanceState != null) {mOpenConverstaion = savedInstanceState.getString(
STATE_OPEN_CONVERSATION, null);
mPanelOpen = savedInstanceState.getBoolean(STATE_PANEL_OPEN, true);
+ String pending = savedInstanceState.getString(STATE_PENDING_URI, null);
+ if (pending != null) {
+ mPendingImageUri = Uri.parse(pending);
+ }
}
setContentView(R.layout.fragment_conversations_overview);
+ this.mConversationFragment = new ConversationFragment();
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.selected_conversation, this.mConversationFragment, "conversation");
+ transaction.commit();
+
listView = (ListView) findViewById(R.id.list);
+ this.listAdapter = new ConversationAdapter(this, conversationList);
+ listView.setAdapter(this.listAdapter);
getActionBar().setDisplayHomeAsUpEnabled(false);
getActionBar().setHomeButtonEnabled(false);
- this.listAdapter = new ConversationAdapter(this, conversationList);
- listView.setAdapter(this.listAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View clickedView,
int position, long arg3) {
- paneShouldBeOpen = false;
if (getSelectedConversation() != conversationList.get(position)) {
setSelectedConversation(conversationList.get(position));
- swapConversationFragment();
- } else {
- hideConversationsOverview();
+ ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation());
}
+ hideConversationsOverview();
}
});
mContentView = findViewById(R.id.content_view_spl);
@@ -192,7 +190,6 @@ public class ConversationActivity extends XmppActivity implements
@Override
public void onPanelOpened(View arg0) {
- paneShouldBeOpen = true;
ActionBar ab = getActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(false);
@@ -210,16 +207,7 @@ public class ConversationActivity extends XmppActivity implements
@Override
public void onPanelClosed(View arg0) {
- paneShouldBeOpen = false;
- if ((conversationList.size() > 0)
- && (getSelectedConversation() != null)) {
- openConversation(getSelectedConversation());
- if (!getSelectedConversation().isRead()) {
- xmppConnectionService.markRead(
- getSelectedConversation(), true);
- listView.invalidateViews();
- }
- }
+ openConversation();
}
@Override
@@ -231,7 +219,7 @@ public class ConversationActivity extends XmppActivity implements
}
}
- public void openConversation(Conversation conversation) {
+ public void openConversation() {
ActionBar ab = getActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
@@ -247,8 +235,11 @@ public class ConversationActivity extends XmppActivity implements
}
invalidateOptionsMenu();
if (xmppConnectionServiceBound) {
- xmppConnectionService.getNotificationService().setOpenConversation(
- conversation);
+ xmppConnectionService.getNotificationService().setOpenConversation(getSelectedConversation());
+ if (!getSelectedConversation().isRead()) {
+ xmppConnectionService.markRead(getSelectedConversation(), true);
+ listView.invalidateViews();
+ }
}
}
@@ -301,12 +292,12 @@ public class ConversationActivity extends XmppActivity implements
@Override
public void onPresenceSelected() {
if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_PHOTO) {
- pendingImageUri = xmppConnectionService.getFileBackend()
+ mPendingImageUri = xmppConnectionService.getFileBackend()
.getTakePhotoUri();
Intent takePictureIntent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
- pendingImageUri);
+ mPendingImageUri);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent,
REQUEST_IMAGE_CAPTURE);
@@ -437,11 +428,11 @@ public class ConversationActivity extends XmppActivity implements
public void endConversation(Conversation conversation) {
conversation.setStatus(Conversation.STATUS_ARCHIVED);
- paneShouldBeOpen = true;
showConversationsOverview();
xmppConnectionService.archiveConversation(conversation);
if (conversationList.size() > 0) {
setSelectedConversation(conversationList.get(0));
+ this.mConversationFragment.reInit(getSelectedConversation());
} else {
setSelectedConversation(null);
}
@@ -609,23 +600,6 @@ public class ConversationActivity extends XmppActivity implements
builder.create().show();
}
- protected ConversationFragment swapConversationFragment() {
- ConversationFragment selectedFragment = new ConversationFragment();
- if (!isFinishing()) {
-
- FragmentTransaction transaction = getFragmentManager()
- .beginTransaction();
- transaction.replace(R.id.selected_conversation, selectedFragment,
- "conversation");
- try {
- transaction.commitAllowingStateLoss();
- } catch (IllegalStateException e) {
- return selectedFragment;
- }
- }
- return selectedFragment;
- }
-
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
@@ -680,6 +654,9 @@ public class ConversationActivity extends XmppActivity implements
}
savedInstanceState.putBoolean(STATE_PANEL_OPEN,
isConversationsOverviewVisable());
+ if (this.mPendingImageUri != null) {
+ savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUri.toString());
+ }
super.onSaveInstanceState(savedInstanceState);
}
@@ -696,42 +673,43 @@ public class ConversationActivity extends XmppActivity implements
} else if (getIntent() != null
&& VIEW_CONVERSATION.equals(getIntent().getType())) {
handleViewConversationIntent(getIntent());
- setIntent(null);
} else if (mOpenConverstaion != null) {
selectConversationByUuid(mOpenConverstaion);
- paneShouldBeOpen = mPanelOpen;
- if (paneShouldBeOpen) {
+ if (mPanelOpen) {
showConversationsOverview();
+ } else {
+ if (isConversationsOverviewHideable()) {
+ openConversation();
+ }
}
- swapConversationFragment();
+ this.mConversationFragment.reInit(getSelectedConversation());
mOpenConverstaion = null;
- } else {
+ } else if (getSelectedConversation() == null) {
showConversationsOverview();
- ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
- .findFragmentByTag("conversation");
- if (selectedFragment != null) {
- selectedFragment.onBackendConnected();
- } else {
- pendingImageUri = null;
- setSelectedConversation(conversationList.get(0));
- swapConversationFragment();
- }
+ mPendingImageUri = null;
+ setSelectedConversation(conversationList.get(0));
+ this.mConversationFragment.reInit(getSelectedConversation());
}
- if (pendingImageUri != null) {
+ if (mPendingImageUri != null) {
attachImageToConversation(getSelectedConversation(),
- pendingImageUri);
- pendingImageUri = null;
+ mPendingImageUri);
+ mPendingImageUri = null;
}
ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
+ setIntent(new Intent());
}
private void handleViewConversationIntent(Intent intent) {
String uuid = (String) intent.getExtras().get(CONVERSATION);
- String text = intent.getExtras().getString(TEXT, null);
+ String text = intent.getExtras().getString(TEXT, "");
selectConversationByUuid(uuid);
- paneShouldBeOpen = false;
- swapConversationFragment().setText(text);
+ this.mConversationFragment.reInit(getSelectedConversation());
+ this.mConversationFragment.appendText(text);
+ hideConversationsOverview();
+ if (mContentView instanceof SlidingPaneLayout) {
+ openConversation();
+ }
}
private void selectConversationByUuid(String uuid) {
@@ -761,11 +739,11 @@ public class ConversationActivity extends XmppActivity implements
selectedFragment.updateMessages();
}
} else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
- pendingImageUri = data.getData();
+ mPendingImageUri = data.getData();
if (xmppConnectionServiceBound) {
attachImageToConversation(getSelectedConversation(),
- pendingImageUri);
- pendingImageUri = null;
+ mPendingImageUri);
+ mPendingImageUri = null;
}
} else if (requestCode == REQUEST_SEND_PGP_IMAGE) {
@@ -778,15 +756,15 @@ public class ConversationActivity extends XmppActivity implements
getSelectedConversation());
} else if (requestCode == REQUEST_ENCRYPT_MESSAGE) {
// encryptTextMessage();
- } else if (requestCode == REQUEST_IMAGE_CAPTURE) {
+ } else if (requestCode == REQUEST_IMAGE_CAPTURE && mPendingImageUri != null) {
if (xmppConnectionServiceBound) {
attachImageToConversation(getSelectedConversation(),
- pendingImageUri);
- pendingImageUri = null;
+ mPendingImageUri);
+ mPendingImageUri = null;
}
Intent intent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
- intent.setData(pendingImageUri);
+ intent.setData(mPendingImageUri);
sendBroadcast(intent);
} else if (requestCode == REQUEST_RECORD_AUDIO) {
attachAudioToConversation(getSelectedConversation(),
@@ -794,7 +772,7 @@ public class ConversationActivity extends XmppActivity implements
}
} else {
if (requestCode == REQUEST_IMAGE_CAPTURE) {
- pendingImageUri = null;
+ mPendingImageUri = null;
}
}
}
@@ -915,19 +893,12 @@ public class ConversationActivity extends XmppActivity implements
@Override
public void run() {
updateConversationList();
- if (paneShouldBeOpen) {
- if (conversationList.size() >= 1) {
- swapConversationFragment();
- } else {
+ if (conversationList.size() == 0) {
startActivity(new Intent(getApplicationContext(),
StartConversationActivity.class));
finish();
- }
- }
- ConversationFragment selectedFragment = (ConversationFragment) getFragmentManager()
- .findFragmentByTag("conversation");
- if (selectedFragment != null) {
- selectedFragment.updateMessages();
+ } else {
+ ConversationActivity.this.mConversationFragment.updateMessages();
}
}
});
@@ -935,16 +906,12 @@ public class ConversationActivity extends XmppActivity implements
@Override
public void onRosterUpdate() {
- final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
- .findFragmentByTag("conversation");
- if (fragment != null) {
- runOnUiThread(new Runnable() {
+ runOnUiThread(new Runnable() {
@Override
public void run() {
- fragment.updateMessages();
+ ConversationActivity.this.mConversationFragment.updateMessages();
}
});
- }
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 20eeeb30..8754b953 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -1,27 +1,5 @@
package eu.siacs.conversations.ui;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import net.java.otr4j.session.SessionStatus;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.crypto.PgpEngine;
-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.MucOptions;
-import eu.siacs.conversations.entities.Presences;
-import eu.siacs.conversations.services.XmppConnectionService;
-import eu.siacs.conversations.ui.EditMessage.OnEnterPressed;
-import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
-import eu.siacs.conversations.ui.XmppActivity.OnValueEdited;
-import eu.siacs.conversations.ui.adapter.MessageAdapter;
-import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked;
-import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked;
-import eu.siacs.conversations.utils.UIHelper;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.PendingIntent;
@@ -31,8 +9,6 @@ import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
-import android.text.Editable;
-import android.text.Selection;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
@@ -44,95 +20,44 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.TextView.OnEditorActionListener;
import android.widget.AbsListView;
-
+import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.ListView;
import android.widget.ImageButton;
+import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
-public class ConversationFragment extends Fragment {
-
- protected Conversation conversation;
- protected ListView messagesView;
- protected LayoutInflater inflater;
- protected List<Message> messageList = new ArrayList<Message>();
- protected MessageAdapter messageListAdapter;
- protected Contact contact;
-
- protected String queuedPqpMessage = null;
-
- private EditMessage mEditMessage;
- private ImageButton mSendButton;
- private String pastedText = null;
- private RelativeLayout snackbar;
- private TextView snackbarMessage;
- private TextView snackbarAction;
-
- private boolean messagesLoaded = false;
-
- private IntentSender askForPassphraseIntent = null;
-
- private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<Message>();
- private boolean mDecryptJobRunning = false;
-
- private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() {
-
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (actionId == EditorInfo.IME_ACTION_SEND) {
- InputMethodManager imm = (InputMethodManager) v.getContext()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
- sendMessage();
- return true;
- } else {
- return false;
- }
- }
- };
-
- private OnClickListener mSendButtonListener = new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- sendMessage();
- }
- };
- protected OnClickListener clickToDecryptListener = new OnClickListener() {
+import net.java.otr4j.session.SessionStatus;
- @Override
- public void onClick(View v) {
- if (activity.hasPgp() && askForPassphraseIntent != null) {
- try {
- getActivity().startIntentSenderForResult(
- askForPassphraseIntent,
- ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
- 0, 0);
- } catch (SendIntentException e) {
- //
- }
- }
- }
- };
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
- private OnClickListener clickToMuc = new OnClickListener() {
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.crypto.PgpEngine;
+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.MucOptions;
+import eu.siacs.conversations.entities.Presences;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.ui.EditMessage.OnEnterPressed;
+import eu.siacs.conversations.ui.XmppActivity.OnPresenceSelected;
+import eu.siacs.conversations.ui.XmppActivity.OnValueEdited;
+import eu.siacs.conversations.ui.adapter.MessageAdapter;
+import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureClicked;
+import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClicked;
+import eu.siacs.conversations.utils.UIHelper;
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(getActivity(),
- ConferenceDetailsActivity.class);
- intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
- intent.putExtra("uuid", conversation.getUuid());
- startActivity(intent);
- }
- };
+public class ConversationFragment extends Fragment {
+ protected Conversation conversation;
private OnClickListener leaveMuc = new OnClickListener() {
@Override
@@ -140,7 +65,6 @@ public class ConversationFragment extends Fragment {
activity.endConversation(conversation);
}
};
-
private OnClickListener joinMuc = new OnClickListener() {
@Override
@@ -148,7 +72,6 @@ public class ConversationFragment extends Fragment {
activity.xmppConnectionService.joinMuc(conversation);
}
};
-
private OnClickListener enterPassword = new OnClickListener() {
@Override
@@ -168,7 +91,18 @@ public class ConversationFragment extends Fragment {
});
}
};
-
+ protected ListView messagesView;
+ protected LayoutInflater inflater;
+ protected List<Message> messageList = new ArrayList<Message>();
+ protected MessageAdapter messageListAdapter;
+ protected Contact contact;
+ protected String queuedPqpMessage = null;
+ private EditMessage mEditMessage;
+ private ImageButton mSendButton;
+ private RelativeLayout snackbar;
+ private TextView snackbarMessage;
+ private TextView snackbarAction;
+ private boolean messagesLoaded = false;
private OnScrollListener mOnScrollListener = new OnScrollListener() {
@Override
@@ -179,7 +113,7 @@ public class ConversationFragment extends Fragment {
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
+ int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0 && messagesLoaded) {
long timestamp = messageList.get(0).getTimeSent();
messagesLoaded = false;
@@ -196,7 +130,58 @@ public class ConversationFragment extends Fragment {
}
}
};
+ private IntentSender askForPassphraseIntent = null;
+ protected OnClickListener clickToDecryptListener = new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (activity.hasPgp() && askForPassphraseIntent != null) {
+ try {
+ getActivity().startIntentSenderForResult(
+ askForPassphraseIntent,
+ ConversationActivity.REQUEST_DECRYPT_PGP, null, 0,
+ 0, 0);
+ } catch (SendIntentException e) {
+ //
+ }
+ }
+ }
+ };
+ private ConcurrentLinkedQueue<Message> mEncryptedMessages = new ConcurrentLinkedQueue<Message>();
+ private boolean mDecryptJobRunning = false;
+ private OnEditorActionListener mEditorActionListener = new OnEditorActionListener() {
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_SEND) {
+ InputMethodManager imm = (InputMethodManager) v.getContext()
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ sendMessage();
+ return true;
+ } else {
+ return false;
+ }
+ }
+ };
+ private OnClickListener mSendButtonListener = new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ sendMessage();
+ }
+ };
+ private OnClickListener clickToMuc = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(getActivity(),
+ ConferenceDetailsActivity.class);
+ intent.setAction(ConferenceDetailsActivity.ACTION_VIEW_MUC);
+ intent.putExtra("uuid", conversation.getUuid());
+ startActivity(intent);
+ }
+ };
private ConversationActivity activity;
private Message selectedMessage;
@@ -238,25 +223,25 @@ public class ConversationFragment extends Fragment {
conversation.getNextPresence()));
} else {
switch (conversation.getNextEncryption(activity.forceEncryption())) {
- case Message.ENCRYPTION_NONE:
- mEditMessage
- .setHint(getString(R.string.send_plain_text_message));
- break;
- case Message.ENCRYPTION_OTR:
- mEditMessage.setHint(getString(R.string.send_otr_message));
- break;
- case Message.ENCRYPTION_PGP:
- mEditMessage.setHint(getString(R.string.send_pgp_message));
- break;
- default:
- break;
+ case Message.ENCRYPTION_NONE:
+ mEditMessage
+ .setHint(getString(R.string.send_plain_text_message));
+ break;
+ case Message.ENCRYPTION_OTR:
+ mEditMessage.setHint(getString(R.string.send_otr_message));
+ break;
+ case Message.ENCRYPTION_PGP:
+ mEditMessage.setHint(getString(R.string.send_pgp_message));
+ break;
+ default:
+ break;
}
}
}
@Override
public View onCreateView(final LayoutInflater inflater,
- ViewGroup container, Bundle savedInstanceState) {
+ ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_conversation,
container, false);
mEditMessage = (EditMessage) view.findViewById(R.id.textinput);
@@ -311,6 +296,11 @@ public class ConversationFragment extends Fragment {
.getConversation());
}
}
+ } else {
+ Account account = message.getConversation().getAccount();
+ Intent intent = new Intent(activity, EditAccountActivity.class);
+ intent.putExtra("jid", account.getJid());
+ startActivity(intent);
}
}
});
@@ -339,7 +329,7 @@ public class ConversationFragment extends Fragment {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
+ ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
this.selectedMessage = this.messageList.get(acmi.position);
@@ -383,23 +373,23 @@ public class ConversationFragment extends Fragment {
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.share_image:
- shareImage(selectedMessage);
- return true;
- case R.id.copy_text:
- copyText(selectedMessage);
- return true;
- case R.id.send_again:
- resendMessage(selectedMessage);
- return true;
- case R.id.copy_url:
- copyUrl(selectedMessage);
- return true;
- case R.id.download_image:
- downloadImage(selectedMessage);
- return true;
- default:
- return super.onContextItemSelected(item);
+ case R.id.share_image:
+ shareImage(selectedMessage);
+ return true;
+ case R.id.copy_text:
+ copyText(selectedMessage);
+ return true;
+ case R.id.send_again:
+ resendMessage(selectedMessage);
+ return true;
+ case R.id.copy_url:
+ copyUrl(selectedMessage);
+ return true;
+ case R.id.download_image:
+ downloadImage(selectedMessage);
+ return true;
+ default:
+ return super.onContextItemSelected(item);
}
}
@@ -461,15 +451,6 @@ public class ConversationFragment extends Fragment {
}
@Override
- public void onStart() {
- super.onStart();
- this.activity = (ConversationActivity) getActivity();
- if (activity.xmppConnectionServiceBound) {
- this.onBackendConnected();
- }
- }
-
- @Override
public void onStop() {
mDecryptJobRunning = false;
super.onStop();
@@ -478,36 +459,18 @@ public class ConversationFragment extends Fragment {
}
}
- public void onBackendConnected() {
- this.activity = (ConversationActivity) getActivity();
- this.conversation = activity.getSelectedConversation();
- if (this.conversation == null) {
- return;
- }
- String oldString = conversation.getNextMessage().trim();
- if (this.pastedText == null) {
- this.mEditMessage.setText(oldString);
- } else {
-
- if (oldString.isEmpty()) {
- mEditMessage.setText(pastedText);
- } else {
- mEditMessage.setText(oldString + " " + pastedText);
- }
- pastedText = null;
- }
- int position = mEditMessage.length();
- Editable etext = mEditMessage.getText();
- Selection.setSelection(etext, position);
- if (activity.isConversationsOverviewHideable()) {
- if (!activity.shouldPaneBeOpen()) {
- activity.hideConversationsOverview();
- activity.openConversation(conversation);
- }
+ public void reInit(Conversation conversation) {
+ if (this.conversation != null) {
+ this.conversation.setNextMessage(mEditMessage.getText().toString());
}
+ this.activity = (ConversationActivity) getActivity();
+ this.conversation = conversation;
if (this.conversation.getMode() == Conversation.MODE_MULTI) {
- conversation.setNextPresence(null);
+ this.conversation.setNextPresence(null);
}
+ this.mEditMessage.setText("");
+ this.mEditMessage.append(this.conversation.getNextMessage());
+ this.messagesView.invalidate();
updateMessages();
}
@@ -533,7 +496,7 @@ public class ConversationFragment extends Fragment {
});
} else if (!contact.showInRoster()
&& contact
- .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
+ .getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
showSnackbar(R.string.contact_added_you, R.string.add_back,
new OnClickListener() {
@@ -548,7 +511,7 @@ public class ConversationFragment extends Fragment {
for (Message message : this.conversation.getMessages()) {
if (message.getEncryption() == Message.ENCRYPTION_PGP
&& (message.getStatus() == Message.STATUS_RECEIVED || message
- .getStatus() >= Message.STATUS_SEND)
+ .getStatus() >= Message.STATUS_SEND)
&& message.getDownloadable() == null) {
if (!mEncryptedMessages.contains(message)) {
mEncryptedMessages.add(message);
@@ -574,38 +537,37 @@ public class ConversationFragment extends Fragment {
&& conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
int error = conversation.getMucOptions().getError();
switch (error) {
- case MucOptions.ERROR_NICK_IN_USE:
- showSnackbar(R.string.nick_in_use, R.string.edit,
- clickToMuc);
- break;
- case MucOptions.ERROR_ROOM_NOT_FOUND:
- showSnackbar(R.string.conference_not_found,
- R.string.leave, leaveMuc);
- break;
- case MucOptions.ERROR_PASSWORD_REQUIRED:
- showSnackbar(R.string.conference_requires_password,
- R.string.enter_password, enterPassword);
- break;
- case MucOptions.ERROR_BANNED:
- showSnackbar(R.string.conference_banned,
- R.string.leave, leaveMuc);
- break;
- case MucOptions.ERROR_MEMBERS_ONLY:
- showSnackbar(R.string.conference_members_only,
- R.string.leave, leaveMuc);
- break;
- case MucOptions.KICKED_FROM_ROOM:
- showSnackbar(R.string.conference_kicked, R.string.join,
- joinMuc);
- break;
- default:
- break;
+ case MucOptions.ERROR_NICK_IN_USE:
+ showSnackbar(R.string.nick_in_use, R.string.edit,
+ clickToMuc);
+ break;
+ case MucOptions.ERROR_ROOM_NOT_FOUND:
+ showSnackbar(R.string.conference_not_found,
+ R.string.leave, leaveMuc);
+ break;
+ case MucOptions.ERROR_PASSWORD_REQUIRED:
+ showSnackbar(R.string.conference_requires_password,
+ R.string.enter_password, enterPassword);
+ break;
+ case MucOptions.ERROR_BANNED:
+ showSnackbar(R.string.conference_banned,
+ R.string.leave, leaveMuc);
+ break;
+ case MucOptions.ERROR_MEMBERS_ONLY:
+ showSnackbar(R.string.conference_members_only,
+ R.string.leave, leaveMuc);
+ break;
+ case MucOptions.KICKED_FROM_ROOM:
+ showSnackbar(R.string.conference_kicked, R.string.join,
+ joinMuc);
+ break;
+ default:
+ break;
}
}
}
- getActivity().invalidateOptionsMenu();
updateChatMsgHint();
- if (!activity.shouldPaneBeOpen()) {
+ if (!activity.isConversationsOverviewVisable() || !activity.isConversationsOverviewHideable()) {
activity.xmppConnectionService.markRead(conversation, true);
activity.updateConversationList();
}
@@ -660,30 +622,30 @@ public class ConversationFragment extends Fragment {
&& c.getAccount().getStatus() == Account.STATUS_ONLINE) {
if (c.getMode() == Conversation.MODE_SINGLE) {
switch (c.getContact().getMostAvailableStatus()) {
- case Presences.CHAT:
- this.mSendButton
- .setImageResource(R.drawable.ic_action_send_now_online);
- break;
- case Presences.ONLINE:
- this.mSendButton
- .setImageResource(R.drawable.ic_action_send_now_online);
- break;
- case Presences.AWAY:
- this.mSendButton
- .setImageResource(R.drawable.ic_action_send_now_away);
- break;
- case Presences.XA:
- this.mSendButton
- .setImageResource(R.drawable.ic_action_send_now_away);
- break;
- case Presences.DND:
- this.mSendButton
- .setImageResource(R.drawable.ic_action_send_now_dnd);
- break;
- default:
- this.mSendButton
- .setImageResource(R.drawable.ic_action_send_now_offline);
- break;
+ case Presences.CHAT:
+ this.mSendButton
+ .setImageResource(R.drawable.ic_action_send_now_online);
+ break;
+ case Presences.ONLINE:
+ this.mSendButton
+ .setImageResource(R.drawable.ic_action_send_now_online);
+ break;
+ case Presences.AWAY:
+ this.mSendButton
+ .setImageResource(R.drawable.ic_action_send_now_away);
+ break;
+ case Presences.XA:
+ this.mSendButton
+ .setImageResource(R.drawable.ic_action_send_now_away);
+ break;
+ case Presences.DND:
+ this.mSendButton
+ .setImageResource(R.drawable.ic_action_send_now_dnd);
+ break;
+ default:
+ this.mSendButton
+ .setImageResource(R.drawable.ic_action_send_now_offline);
+ break;
}
} else if (c.getMode() == Conversation.MODE_MULTI) {
if (c.getMucOptions().online()) {
@@ -723,9 +685,9 @@ public class ConversationFragment extends Fragment {
Set<String> knownFingerprints = conversation.getContact()
.getOtrFingerprints();
if (conversation.hasValidOtrSession()
- && (!conversation.isMuted())
- && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
- .contains(conversation.getOtrFingerprint()))) {
+ && (!conversation.isMuted())
+ && (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
+ .contains(conversation.getOtrFingerprint()))) {
showSnackbar(R.string.unknown_otr_fingerprint, R.string.verify,
new OnClickListener() {
@@ -744,7 +706,7 @@ public class ConversationFragment extends Fragment {
}
protected void showSnackbar(int message, int action,
- OnClickListener clickListener) {
+ OnClickListener clickListener) {
snackbar.setVisibility(View.VISIBLE);
snackbar.setOnClickListener(null);
snackbarMessage.setText(message);
@@ -775,7 +737,7 @@ public class ConversationFragment extends Fragment {
@Override
public void userInputRequried(PendingIntent pi,
- Contact contact) {
+ Contact contact) {
activity.runIntent(
pi,
ConversationActivity.REQUEST_ENCRYPT_MESSAGE);
@@ -799,7 +761,7 @@ public class ConversationFragment extends Fragment {
@Override
public void onClick(DialogInterface dialog,
- int which) {
+ int which) {
conversation
.setNextEncryption(Message.ENCRYPTION_NONE);
xmppService.databaseBackend
@@ -828,7 +790,7 @@ public class ConversationFragment extends Fragment {
@Override
public void onClick(DialogInterface dialog,
- int which) {
+ int which) {
conversation
.setNextEncryption(Message.ENCRYPTION_NONE);
message.setEncryption(Message.ENCRYPTION_NONE);
@@ -846,7 +808,7 @@ public class ConversationFragment extends Fragment {
}
public void showNoPGPKeyDialog(boolean plural,
- DialogInterface.OnClickListener listener) {
+ DialogInterface.OnClickListener listener) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setIconAttribute(android.R.attr.alertDialogIcon);
if (plural) {
@@ -882,8 +844,12 @@ public class ConversationFragment extends Fragment {
}
}
- public void setText(String text) {
- this.pastedText = text;
+ public void appendText(String text) {
+ String previous = this.mEditMessage.getText().toString();
+ if (previous.length() != 0 && !previous.endsWith(" ")) {
+ text = " " + text;
+ }
+ this.mEditMessage.append(text);
}
public void clearInputField() {
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index e0ec2899..c1da35f5 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -400,8 +400,10 @@ public class EditAccountActivity extends XmppActivity {
private void updateAccountInformation() {
this.mAccountJid.setText(this.mAccount.getJid());
this.mPassword.setText(this.mAccount.getPassword());
- this.mAvatar.setVisibility(View.VISIBLE);
- this.mAvatar.setImageBitmap(avatarService().get(this.mAccount,getPixel(72)));
+ if (this.jidToEdit != null) {
+ this.mAvatar.setVisibility(View.VISIBLE);
+ this.mAvatar.setImageBitmap(avatarService().get(this.mAccount, getPixel(72)));
+ }
if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) {
this.mRegisterNew.setVisibility(View.VISIBLE);
this.mRegisterNew.setChecked(true);
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 a24f90d7..f2227308 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -1,16 +1,5 @@
package eu.siacs.conversations.ui.adapter;
-import java.util.List;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.R;
-import eu.siacs.conversations.entities.Contact;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.entities.Downloadable;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.entities.Message.ImageParams;
-import eu.siacs.conversations.ui.ConversationActivity;
-import eu.siacs.conversations.utils.UIHelper;
import android.content.Intent;
import android.graphics.Typeface;
import android.text.Spannable;
@@ -19,9 +8,9 @@ import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.DisplayMetrics;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
@@ -29,6 +18,18 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
+import java.util.List;
+
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.Downloadable;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.Message.ImageParams;
+import eu.siacs.conversations.ui.ConversationActivity;
+import eu.siacs.conversations.utils.UIHelper;
+
public class MessageAdapter extends ArrayAdapter<Message> {
private static final int SENT = 0;
@@ -323,10 +324,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
.findViewById(R.id.message_box);
viewHolder.contact_picture = (ImageView) view
.findViewById(R.id.message_photo);
- viewHolder.contact_picture.setImageBitmap(activity
- .avatarService().get(
- item.getConversation().getAccount(),
- activity.getPixel(48)));
viewHolder.download_button = (Button) view
.findViewById(R.id.download_button);
viewHolder.indicator = (ImageView) view
@@ -350,11 +347,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
.findViewById(R.id.message_photo);
viewHolder.download_button = (Button) view
.findViewById(R.id.download_button);
- if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
- viewHolder.contact_picture.setImageBitmap(activity
- .avatarService().get(item.getContact(),
- activity.getPixel(48)));
- }
viewHolder.indicator = (ImageView) view
.findViewById(R.id.security_indicator);
viewHolder.image = (ImageView) view
@@ -363,6 +355,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
.findViewById(R.id.message_body);
viewHolder.time = (TextView) view
.findViewById(R.id.message_time);
+ viewHolder.indicatorReceived = (ImageView) view
+ .findViewById(R.id.indicator_received);
view.setTag(viewHolder);
break;
case STATUS:
@@ -370,30 +364,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
R.layout.message_status, parent, false);
viewHolder.contact_picture = (ImageView) view
.findViewById(R.id.message_photo);
- if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
-
- viewHolder.contact_picture.setImageBitmap(activity
- .avatarService().get(
- item.getConversation().getContact(),
- activity.getPixel(32)));
- viewHolder.contact_picture.setAlpha(0.5f);
- viewHolder.contact_picture
- .setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- String name = item.getConversation()
- .getName();
- String read = getContext()
- .getString(
- R.string.contact_has_read_up_to_this_point,
- name);
- Toast.makeText(getContext(), read,
- Toast.LENGTH_SHORT).show();
- }
- });
-
- }
+ view.setTag(viewHolder);
break;
default:
viewHolder = null;
@@ -404,9 +375,31 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
if (type == STATUS) {
+ if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
+ viewHolder.contact_picture.setImageBitmap(activity
+ .avatarService().get(
+ item.getConversation().getContact(),
+ activity.getPixel(32)));
+ viewHolder.contact_picture.setAlpha(0.5f);
+ viewHolder.contact_picture
+ .setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ String name = item.getConversation()
+ .getName();
+ String read = getContext()
+ .getString(
+ R.string.contact_has_read_up_to_this_point,
+ name);
+ Toast.makeText(getContext(), read,
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ }
return view;
- }
- if (type == NULL) {
+ } else if (type == NULL) {
if (position == getCount() - 1) {
view.getLayoutParams().height = 1;
} else {
@@ -415,6 +408,19 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
view.setLayoutParams(view.getLayoutParams());
return view;
+ } else if (type == RECEIVED) {
+ Contact contact = item.getContact();
+ if (contact != null) {
+ viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(contact, activity.getPixel(48)));
+ } else if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
+ String name = item.getPresence();
+ if (name == null) {
+ name = item.getCounterpart();
+ }
+ viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(name, activity.getPixel(48)));
+ }
+ } else if (type == SENT) {
+ viewHolder.contact_picture.setImageBitmap(activity.avatarService().get(item.getConversation().getAccount(), activity.getPixel(48)));
}
if (viewHolder.contact_picture != null) {
@@ -426,7 +432,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
if (MessageAdapter.this.mOnContactPictureClickedListener != null) {
MessageAdapter.this.mOnContactPictureClickedListener
.onContactPictureClicked(item);
- ;
}
}
@@ -447,24 +452,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
});
}
- if (type == RECEIVED) {
- if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
- Contact contact = item.getContact();
- if (contact != null) {
- viewHolder.contact_picture.setImageBitmap(activity
- .avatarService()
- .get(contact, activity.getPixel(48)));
- } else {
- String name = item.getPresence();
- if (name == null) {
- name = item.getCounterpart();
- }
- viewHolder.contact_picture.setImageBitmap(activity
- .avatarService().get(name, activity.getPixel(48)));
- }
- }
- }
-
if (item.getType() == Message.TYPE_IMAGE
|| item.getDownloadable() != null) {
Downloadable d = item.getDownloadable();
@@ -532,6 +519,14 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
+ public interface OnContactPictureClicked {
+ public void onContactPictureClicked(Message message);
+ }
+
+ public interface OnContactPictureLongClicked {
+ public void onContactPictureLongClicked(Message message);
+ }
+
private static class ViewHolder {
protected LinearLayout message_box;
@@ -544,12 +539,4 @@ public class MessageAdapter extends ArrayAdapter<Message> {
protected ImageView contact_picture;
}
-
- public interface OnContactPictureClicked {
- public void onContactPictureClicked(Message message);
- }
-
- public interface OnContactPictureLongClicked {
- public void onContactPictureLongClicked(Message message);
- }
}
diff --git a/src/main/res/layout/activity_about.xml b/src/main/res/layout/activity_about.xml
new file mode 100644
index 00000000..bd76457f
--- /dev/null
+++ b/src/main/res/layout/activity_about.xml
@@ -0,0 +1,21 @@
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="eu.siacs.conversations.ui.AboutActivity"
+ android:background="@color/primarybackground"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:text="@string/pref_about_message"
+ android:autoLink="web"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:linksClickable="true"
+ android:textColor="@color/primarytext"
+ android:textSize="?attr/TextSizeBody"
+ android:typeface="monospace"/>
+</ScrollView>
diff --git a/src/main/res/values-w820dp/dimens.xml b/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..3aeac9e7
--- /dev/null
+++ b/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+ <!-- Customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available
+ width. This would include 7" and 10" devices in landscape (~960dp and
+ ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/src/main/res/values/dimens.xml b/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..47c82246
--- /dev/null
+++ b/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 0dbb49ad..28a1e326 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -25,8 +25,8 @@
<string name="minute_ago">1 min ago</string>
<string name="minutes_ago">%d mins ago</string>
<string name="unread_conversations">unread Conversations</string>
- <string name="sending">sending&#8230;</string>
- <string name="encrypted_message">Decrypting message. Please wait&#8230;</string>
+ <string name="sending">sending…</string>
+ <string name="encrypted_message">Decrypting message. Please wait…</string>
<string name="nick_in_use">Nickname is already in use</string>
<string name="admin">Admin</string>
<string name="owner">Owner</string>
@@ -58,7 +58,7 @@
<string name="add_contact">Add contact</string>
<string name="send_failed">delivery failed</string>
<string name="send_rejected">rejected</string>
- <string name="receiving_image">Receiving image file. Please wait&#8230;</string>
+ <string name="receiving_image">Receiving image file. Please wait…</string>
<string name="preparing_image">Preparing image for transmission</string>
<string name="action_clear_history">Clear history</string>
<string name="clear_conversation_history">Clear Conversation History</string>
@@ -78,8 +78,8 @@
<string name="openkeychain_required_long">Conversations utilizes a third party app called <b>OpenKeychain</b> to encrypt and decrypt messages and to manage your public keys.\n\nOpenKeychain is licensed under GPLv3 and available on F-Droid and Google Play.\n\n<small>(Please restart Conversations afterwards.)</small></string>
<string name="restart">Restart</string>
<string name="install">Install</string>
- <string name="offering">offering&#8230;</string>
- <string name="waiting">waiting&#8230;</string>
+ <string name="offering">offering…</string>
+ <string name="waiting">waiting…</string>
<string name="no_pgp_key">No OpenPGP Key found</string>
<string name="contact_has_no_pgp_key">Conversations is unable to encrypt your messages because your contact is not announcing his or hers public key.\n\n<small>Please ask your contact to setup OpenPGP.</small></string>
<string name="no_pgp_keys">No OpenPGP Keys found</string>
@@ -91,7 +91,7 @@
<string name="pref_xmpp_resource">XMPP resource</string>
<string name="pref_xmpp_resource_summary">The name this client identifies itself with</string>
<string name="pref_accept_files">Accept files</string>
- <string name="pref_accept_files_summary">Automatically accept files smaller than&#8230;</string>
+ <string name="pref_accept_files_summary">Automatically accept files smaller than…</string>
<string name="pref_notification_settings">Notification Settings</string>
<string name="pref_notifications">Notifications</string>
<string name="pref_notifications_summary">Notify when a new message arrives</string>
@@ -217,7 +217,7 @@
<string name="publish">Publish</string>
<string name="touch_to_choose_picture">Touch avatar to select picture from gallery</string>
<string name="publish_avatar_explanation">Please note: Everyone subscribed to your presence updates will be allowed to see this picture.</string>
- <string name="publishing">Publishing&#8230;</string>
+ <string name="publishing">Publishing…</string>
<string name="error_publish_avatar_server_reject">The server rejected your publication</string>
<string name="error_publish_avatar_converting">Something went wrong while converting your picture</string>
<string name="error_saving_avatar">Could not save avatar to disk</string>
@@ -254,6 +254,23 @@
<string name="pref_enable_legacy_ssl_summary">Enables SSLv3 support for legacy servers. Warning: SSLv3 is considered insecure.</string>
<string name="pref_expert_options">Expert options</string>
<string name="pref_expert_options_summary">Please be careful with these</string>
+ <string name="title_activity_about">About Conversations</string>
+ <string name="pref_about_conversations_summary">Build and licensing information</string>
+ <string name="pref_about_message">Conversations © 2014 Daniel Gultsch\n
+ \nThis program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 3 as published
+ by the Free Software Foundation.
+ \nhttps://www.gnu.org/licenses/gpl-3.0.html\n
+ \nOpenPGP API is licensed under the Apache License, Version 2.0
+ \nhttps://www.apache.org/licenses/LICENSE-2.0\n
+ \nMinidns © 2014 Rene Treffer and is provided under the WTFPL
+ \nhttp://wtfpl.org\n
+ \nMemorizingTrustManager © 2010 Georg Lukas under the terms of the MIT
+ License
+ \nhttp://opensource.org/licenses/MIT\n
+ \nDownload the full source code at
+ \nhttps://github.com/siacs/Conversations
+ </string>
<string name="pref_use_larger_font">Increase font size</string>
<string name="pref_use_larger_font_summary">Use larger font sizes across the entire app</string>
<string name="pref_use_send_button_to_indicate_status">Send button indicates status</string>
@@ -285,4 +302,4 @@
<string name="scan_qr_code">Scan QR code</string>
<string name="show_qr_code">Show QR code</string>
<string name="account_details">Account details</string>
-</resources> \ No newline at end of file
+</resources>
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
index 06ab7560..15a61e87 100644
--- a/src/main/res/xml/preferences.xml
+++ b/src/main/res/xml/preferences.xml
@@ -110,5 +110,8 @@
android:summary="@string/pref_never_send_crash_summary"
android:title="@string/pref_never_send_crash" />
</PreferenceCategory>
+ <eu.siacs.conversations.ui.AboutPreference
+ android:summary="@string/pref_about_conversations_summary"
+ android:title="@string/title_activity_about" />
</PreferenceScreen>