aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-06-24 21:34:47 +0200
committerChristian Schneppe <christian@pix-art.de>2018-06-29 21:55:43 +0200
commitd9d40ecb4297a7ade4205d6dca411c01aa728663 (patch)
tree2853511ab2432799cbb9d2ab1a7d736e424c8e63
parent6633eedbb75d5fa85186c053aa7797b5b5458fc6 (diff)
WIP: set room avatar and slight redesign of group details
*show jid in group details (in advanced mode)
-rw-r--r--build.gradle2
-rw-r--r--src/main/AndroidManifest.xml7
-rw-r--r--src/main/java/de/pixart/messenger/entities/MucOptions.java15
-rw-r--r--src/main/java/de/pixart/messenger/persistance/FileBackend.java21
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java75
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java44
-rw-r--r--src/main/java/de/pixart/messenger/ui/PublishGroupChatProfilePictureActivity.java155
-rw-r--r--src/main/java/de/pixart/messenger/ui/PublishProfilePictureActivity.java188
-rw-r--r--src/main/java/de/pixart/messenger/ui/interfaces/OnAvatarPublication.java39
-rw-r--r--src/main/res/drawable/account_image_border.xml15
-rw-r--r--src/main/res/layout/activity_muc_details.xml474
-rw-r--r--src/main/res/layout/activity_publish_profile_picture.xml126
-rw-r--r--src/main/res/menu/muc_details.xml6
-rw-r--r--src/main/res/menu/publish_avatar.xml9
-rw-r--r--src/main/res/values/dimens.xml4
-rw-r--r--src/main/res/values/strings.xml4
16 files changed, 721 insertions, 463 deletions
diff --git a/build.gradle b/build.gradle
index 14f80512a..87f9f0b5a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -38,7 +38,7 @@ dependencies {
exclude group: 'com.google.firebase', module: 'firebase-core'
}
implementation 'org.sufficientlysecure:openpgp-api:10.0'
- implementation 'com.soundcloud.android:android-crop:1.0.1@aar'
+ implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.+'
implementation 'org.bouncycastle:bcmail-jdk15on:1.58'
implementation 'org.jitsi:org.otr4j:0.22'
implementation 'org.gnu.inet:libidn:1.15'
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index e7f731fc1..c64f89ef8 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -196,6 +196,9 @@
android:label="@string/mgmt_account_publish_avatar"
android:windowSoftInputMode="stateHidden" />
<activity
+ android:name=".ui.PublishGroupChatProfilePictureActivity"
+ android:label="@string/group_chat_avatar" />
+ <activity
android:name=".ui.VerifyOTRActivity"
android:label="@string/verify_otr"
android:windowSoftInputMode="stateHidden" />
@@ -270,7 +273,9 @@
<action android:name="android.intent.action.CREATE_SHORTCUT" />
</intent-filter>
</activity>
- <activity android:name="com.soundcloud.android.crop.CropImageActivity" />
+ <activity
+ android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
+ android:theme="@style/Base.Theme.AppCompat" />
<activity android:name=".ui.MemorizingActivity" />
<service android:name=".services.ExportLogsService" />
diff --git a/src/main/java/de/pixart/messenger/entities/MucOptions.java b/src/main/java/de/pixart/messenger/entities/MucOptions.java
index a6968b66f..eb5629b2e 100644
--- a/src/main/java/de/pixart/messenger/entities/MucOptions.java
+++ b/src/main/java/de/pixart/messenger/entities/MucOptions.java
@@ -373,7 +373,7 @@ public class MucOptions {
this.self = new User(this, createJoinJid(getProposedNick()));
}
- public boolean updateConfiguration(List<String> features, Data data) {
+ public boolean updateConfiguration(List<String> features, String name, Data data) {
updateFeatures(features);
updateFormData(data == null ? new Data() : data);
Field allowPmField = this.form.getFieldByName("muc#roomconfig_allowpm");
@@ -382,6 +382,7 @@ public class MucOptions {
changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, this.hasFeature("muc_membersonly"));
changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MODERATED, this.hasFeature("muc_moderated"));
changed |= conversation.setAttribute(Conversation.ATTRIBUTE_NON_ANONYMOUS, this.hasFeature("muc_nonanonymous"));
+ changed |= setName(name);
return changed;
}
@@ -402,6 +403,10 @@ public class MucOptions {
return this.features.contains(feature);
}
+ public boolean hasVCards() {
+ return hasFeature("vcard-temp");
+ }
+
public boolean canInvite() {
Field field = this.form.getFieldByName("muc#roomconfig_allowinvites");
return !membersOnly() || self.getRole().ranks(Role.MODERATOR) || (field != null && "1".equals(field.getValue()));
@@ -688,6 +693,14 @@ public class MucOptions {
return this.conversation.getAttribute("subject");
}
+ private boolean setName(String name) {
+ return this.conversation.setAttribute("muc_name", name);
+ }
+
+ public String getName() {
+ return this.conversation.getAttribute("muc_name");
+ }
+
public List<User> getFallbackUsersFromCryptoTargets() {
List<User> users = new ArrayList<>();
for (Jid jid : conversation.getAcceptedCryptoTargets()) {
diff --git a/src/main/java/de/pixart/messenger/persistance/FileBackend.java b/src/main/java/de/pixart/messenger/persistance/FileBackend.java
index e893ea129..3bb1e5c4e 100644
--- a/src/main/java/de/pixart/messenger/persistance/FileBackend.java
+++ b/src/main/java/de/pixart/messenger/persistance/FileBackend.java
@@ -614,6 +614,14 @@ public class FileBackend {
}
public Avatar getPepAvatar(Uri image, int size, Bitmap.CompressFormat format) {
+ final Avatar uncompressAvatar = getUncompressedAvatar(image);
+ if (uncompressAvatar != null && uncompressAvatar.image.length() <= Config.AVATAR_CHAR_LIMIT) {
+ return uncompressAvatar;
+ }
+ if (uncompressAvatar != null) {
+ Log.d(Config.LOGTAG, "uncompressed avatar exceeded char limit by " + (uncompressAvatar.image.length() - Config.AVATAR_CHAR_LIMIT));
+ }
+
Bitmap bm = cropCenterSquare(image, size);
if (bm == null) {
return null;
@@ -627,6 +635,19 @@ public class FileBackend {
return getPepAvatar(bm, format, 100);
}
+ private Avatar getUncompressedAvatar(Uri uri) {
+ Bitmap bitmap = null;
+ try {
+ bitmap = BitmapFactory.decodeStream(mXmppConnectionService.getContentResolver().openInputStream(uri));
+ return getPepAvatar(bitmap, Bitmap.CompressFormat.PNG, 100);
+ } catch (Exception e) {
+ if (bitmap != null) {
+ bitmap.recycle();
+ }
+ }
+ return null;
+ }
+
private Avatar getPepAvatar(Bitmap bitmap, Bitmap.CompressFormat format, int quality) {
try {
ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream();
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index 2556138e8..487308c52 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -109,6 +109,7 @@ import de.pixart.messenger.persistance.DatabaseBackend;
import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.ui.SettingsActivity;
import de.pixart.messenger.ui.UiCallback;
+import de.pixart.messenger.ui.interfaces.OnAvatarPublication;
import de.pixart.messenger.ui.interfaces.OnSearchResultsAvailable;
import de.pixart.messenger.utils.ConversationsFileObserver;
import de.pixart.messenger.utils.CryptoHelper;
@@ -2698,18 +2699,21 @@ public class XmppConnectionService extends Service {
public void onIqPacketReceived(Account account, IqPacket packet) {
Element query = packet.findChild("query", "http://jabber.org/protocol/disco#info");
if (packet.getType() == IqPacket.TYPE.RESULT && query != null) {
+ String name = null;
ArrayList<String> features = new ArrayList<>();
for (Element child : query.getChildren()) {
- if (child != null && child.getName().equals("feature")) {
+ if (child.getName().equals("feature")) {
String var = child.getAttribute("var");
if (var != null) {
features.add(var);
}
+ } else if (child.getName().equals("identity")) {
+ name = child.getAttribute("name");
}
}
Element form = query.findChild("x", Namespace.DATA);
Data data = form == null ? null : Data.parse(form);
- if (conversation.getMucOptions().updateConfiguration(features, data)) {
+ if (conversation.getMucOptions().updateConfiguration(features, name, data)) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": muc configuration changed for " + conversation.getJid().asBareJid());
updateConversation(conversation);
}
@@ -3025,24 +3029,77 @@ public class XmppConnectionService extends Service {
}
}
- public void publishAvatar(final Account account, final Uri image, final UiCallback<Avatar> callback) {
+ public void publishMucAvatar(final Conversation conversation, final Uri image, final OnAvatarPublication callback) {
new Thread(() -> {
final Bitmap.CompressFormat format = Config.AVATAR_FORMAT;
final int size = Config.AVATAR_SIZE;
final Avatar avatar = getFileBackend().getPepAvatar(image, size, format);
if (avatar != null) {
if (!getFileBackend().save(avatar)) {
- callback.error(R.string.error_saving_avatar, avatar);
+ callback.onAvatarPublicationFailed(R.string.error_saving_avatar);
+ return;
+ }
+ avatar.owner = conversation.getJid().asBareJid();
+ publishMucAvatar(conversation, avatar, callback);
+ } else {
+ callback.onAvatarPublicationFailed(R.string.error_publish_avatar_converting);
+ }
+ }).start();
+ }
+
+ public void publishAvatar(final Account account, final Uri image, final OnAvatarPublication callback) {
+ new Thread(() -> {
+ final Bitmap.CompressFormat format = Config.AVATAR_FORMAT;
+ final int size = Config.AVATAR_SIZE;
+ final Avatar avatar = getFileBackend().getPepAvatar(image, size, format);
+ if (avatar != null) {
+ if (!getFileBackend().save(avatar)) {
+ Log.d(Config.LOGTAG, "unable to save vcard");
+ callback.onAvatarPublicationFailed(R.string.error_saving_avatar);
return;
}
publishAvatar(account, avatar, callback);
} else {
- callback.error(R.string.error_publish_avatar_converting, null);
+ callback.onAvatarPublicationFailed(R.string.error_publish_avatar_converting);
}
}).start();
}
- public void publishAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) {
+ private void publishMucAvatar(Conversation conversation, Avatar avatar, OnAvatarPublication callback) {
+ final IqPacket retrieve = mIqGenerator.retrieveVcardAvatar(avatar);
+ sendIqPacket(conversation.getAccount(), retrieve, (account, response) -> {
+ boolean itemNotFound = response.getType() == IqPacket.TYPE.ERROR && response.hasChild("error") && response.findChild("error").hasChild("item-not-found");
+ if (response.getType() == IqPacket.TYPE.RESULT || itemNotFound) {
+ Element vcard = response.findChild("vCard", "vcard-temp");
+ if (vcard == null) {
+ vcard = new Element("vCard", "vcard-temp");
+ }
+ Element photo = vcard.findChild("PHOTO");
+ if (photo == null) {
+ photo = vcard.addChild("PHOTO");
+ }
+ photo.clearChildren();
+ photo.addChild("TYPE").setContent(avatar.type);
+ photo.addChild("BINVAL").setContent(avatar.image);
+ IqPacket publication = new IqPacket(IqPacket.TYPE.SET);
+ publication.setTo(conversation.getJid().asBareJid());
+ publication.addChild(vcard);
+ sendIqPacket(account, publication, (a1, publicationResponse) -> {
+ if (publicationResponse.getType() == IqPacket.TYPE.RESULT) {
+ callback.onAvatarPublicationSucceeded();
+ } else {
+ Log.d(Config.LOGTAG, "failed to publish vcard " + publicationResponse.getError());
+ callback.onAvatarPublicationFailed(R.string.error_publish_avatar_server_reject);
+ }
+ });
+ } else {
+ Log.d(Config.LOGTAG, "failed to request vcard " + response.toString());
+ callback.onAvatarPublicationFailed(R.string.error_publish_avatar_no_server_support);
+ }
+ });
+ }
+
+ public void publishAvatar(Account account, final Avatar avatar, final OnAvatarPublication callback) {
IqPacket packet = this.mIqGenerator.publishAvatar(avatar);
this.sendIqPacket(account, packet, new OnIqPacketReceived() {
@@ -3060,11 +3117,11 @@ public class XmppConnectionService extends Service {
}
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": published avatar "+(avatar.size/1024)+"KiB");
if (callback != null) {
- callback.success(avatar);
+ callback.onAvatarPublicationSucceeded();
}
} else {
if (callback != null) {
- callback.error(R.string.error_publish_avatar_server_reject,avatar);
+ callback.onAvatarPublicationFailed(R.string.error_publish_avatar_server_reject);
}
}
}
@@ -3073,7 +3130,7 @@ public class XmppConnectionService extends Service {
Element error = result.findChild("error");
Log.d(Config.LOGTAG,account.getJid().asBareJid()+": server rejected avatar "+(avatar.size/1024)+"KiB "+(error!=null?error.toString():""));
if (callback != null) {
- callback.error(R.string.error_publish_avatar_server_reject, avatar);
+ callback.onAvatarPublicationFailed(R.string.error_publish_avatar_server_reject);
}
}
}
diff --git a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java
index c55a936cd..ed2dfee04 100644
--- a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java
@@ -299,7 +299,20 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
this.mAdvancedMode = getPreferences().getBoolean("advanced_muc_mode", false);
this.binding.mucInfoMore.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
this.binding.notificationStatusButton.setOnClickListener(this.mNotifyStatusClickListener);
- this.binding.notificationStatusButton.setOnClickListener(this.mNotifyStatusClickListener);
+ this.binding.detailsMucAvatar.setOnClickListener(v -> {
+ final MucOptions mucOptions = mConversation.getMucOptions();
+ if (!mucOptions.hasVCards()) {
+ Toast.makeText(this, R.string.host_does_not_support_group_chat_avatars, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (!mucOptions.getSelf().getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
+ Toast.makeText(this, R.string.only_the_owner_can_change_group_chat_avatar, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ final Intent intent = new Intent(this, PublishGroupChatProfilePictureActivity.class);
+ intent.putExtra("uuid", mConversation.getUuid());
+ startActivity(intent);
+ });
}
@Override
@@ -320,14 +333,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
case android.R.id.home:
finish();
break;
- case R.id.action_edit_subject:
- if (mConversation != null) {
- quickEdit(mConversation.getMucOptions().getSubject(),
- R.string.edit_subject_hint,
- this.onSubjectEdited,
- true);
- }
- break;
case R.id.action_share_http:
shareLink(true);
break;
@@ -363,12 +368,10 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem menuItemAdvancedMode = menu.findItem(R.id.action_advanced_mode);
- MenuItem menuItemChangeSubject = menu.findItem(R.id.action_edit_subject);
menuItemAdvancedMode.setChecked(mAdvancedMode);
if (mConversation == null) {
return true;
}
- menuItemChangeSubject.setVisible(mConversation.getMucOptions().canChangeSubject());
return true;
}
@@ -587,28 +590,25 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
absubtitle.setClickable(false);
}
}
- this.binding.conferenceName.setText(mConversation.getName());
this.binding.detailsAccount.setText(getString(R.string.using_account, account));
+ this.binding.jid.setText(mConversation.getJid().asBareJid().toEscapedString());
if (xmppConnectionService.multipleAccounts()) {
this.binding.detailsAccount.setVisibility(View.VISIBLE);
} else {
this.binding.detailsAccount.setVisibility(View.GONE);
}
this.binding.yourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48)));
- setTitle(mConversation.getName());
- this.binding.mucJabberid.setText(mConversation.getJid().asBareJid().toString());
+
+ this.binding.mucTitle.setText(mucOptions.getName());
+ this.binding.mucSubject.setText(mucOptions.getSubject());
this.binding.mucYourNick.setText(mucOptions.getActualNick());
if (mucOptions.online()) {
this.binding.mucMoreDetails.setVisibility(View.VISIBLE);
this.binding.mucSettings.setVisibility(View.VISIBLE);
this.binding.mucInfoMore.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
- final String status = getStatus(self);
- if (status != null) {
- this.binding.mucRole.setVisibility(View.VISIBLE);
- this.binding.mucRole.setText(status);
- } else {
- this.binding.mucRole.setVisibility(View.GONE);
- }
+ this.binding.jid.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
+ this.binding.mucRole.setVisibility(View.VISIBLE);
+ this.binding.mucRole.setText(getStatus(self));
if (mucOptions.membersOnly()) {
this.binding.mucConferenceType.setText(R.string.private_conference);
} else {
@@ -629,7 +629,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
this.binding.changeConferenceButton.setVisibility(View.VISIBLE);
} else {
this.binding.destroy.setVisibility(View.GONE);
- this.binding.changeConferenceButton.setVisibility(View.GONE);
+ this.binding.changeConferenceButton.setVisibility(View.INVISIBLE);
}
this.binding.leaveMuc.setVisibility(View.VISIBLE);
this.binding.leaveMuc.setOnClickListener(v1 -> {
diff --git a/src/main/java/de/pixart/messenger/ui/PublishGroupChatProfilePictureActivity.java b/src/main/java/de/pixart/messenger/ui/PublishGroupChatProfilePictureActivity.java
new file mode 100644
index 000000000..a4bf6b440
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/PublishGroupChatProfilePictureActivity.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui;
+
+import android.content.Intent;
+import android.databinding.DataBindingUtil;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.StringRes;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+import com.theartofdev.edmodo.cropper.CropImage;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.R;
+import de.pixart.messenger.databinding.ActivityPublishProfilePictureBinding;
+import de.pixart.messenger.entities.Conversation;
+import de.pixart.messenger.ui.interfaces.OnAvatarPublication;
+import de.pixart.messenger.ui.util.PendingItem;
+
+public class PublishGroupChatProfilePictureActivity extends XmppActivity implements OnAvatarPublication {
+
+ private static final int REQUEST_CHOOSE_FILE = 0xac24;
+
+ private ActivityPublishProfilePictureBinding binding;
+
+ private final PendingItem<String> pendingConversationUuid = new PendingItem<>();
+
+ private Conversation conversation;
+ private Uri uri;
+
+ @Override
+ protected void refreshUiReal() {
+
+ }
+
+ @Override
+ void onBackendConnected() {
+ String uuid = pendingConversationUuid.pop();
+ if (uuid != null) {
+ this.conversation = xmppConnectionService.findConversationByUuid(uuid);
+ }
+ if (this.conversation == null) {
+ return;
+ }
+ reloadAvatar();
+ }
+
+ private void reloadAvatar() {
+ final int size = getPixel(Config.AVATAR_SIZE);
+ Bitmap bitmap;
+ if (uri == null) {
+ bitmap = xmppConnectionService.getAvatarService().get(conversation, size);
+ } else {
+ Log.d(Config.LOGTAG, "loading " + uri.toString() + " into preview");
+ bitmap = xmppConnectionService.getFileBackend().cropCenterSquare(uri, size);
+ }
+ this.binding.accountImage.setImageBitmap(bitmap);
+ this.binding.publishButton.setEnabled(uri != null);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_publish_profile_picture);
+ setSupportActionBar((Toolbar) this.binding.toolbar);
+ configureActionBar(getSupportActionBar());
+ this.binding.cancelButton.setOnClickListener((v) -> this.finish());
+ this.binding.secondaryHint.setVisibility(View.GONE);
+ this.binding.accountImage.setOnClickListener((v) -> this.chooseAvatar());
+ Intent intent = getIntent();
+ String uuid = intent == null ? null : intent.getStringExtra("uuid");
+ if (uuid != null) {
+ pendingConversationUuid.push(uuid);
+ }
+ this.binding.publishButton.setEnabled(uri != null);
+ this.binding.publishButton.setOnClickListener(this::publish);
+ }
+
+
+ private void publish(View view) {
+ xmppConnectionService.publishMucAvatar(conversation, uri, this);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
+ CropImage.ActivityResult result = CropImage.getActivityResult(data);
+ if (resultCode == RESULT_OK) {
+ this.uri = result.getUri();
+ if (xmppConnectionServiceBound) {
+ reloadAvatar();
+ }
+ } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
+ Exception error = result.getError();
+ if (error != null) {
+ Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ }
+
+ private void chooseAvatar() {
+ CropImage.activity()
+ .setOutputCompressFormat(Bitmap.CompressFormat.PNG)
+ .setAspectRatio(1, 1)
+ .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE)
+ .start(this);
+ }
+
+ @Override
+ public void onAvatarPublicationSucceeded() {
+ finish();
+ }
+
+ @Override
+ public void onAvatarPublicationFailed(@StringRes int res) {
+ runOnUiThread(() -> {
+ Toast.makeText(this,res,Toast.LENGTH_SHORT).show();
+ this.binding.publishButton.setText(R.string.publish);
+ this.binding.publishButton.setEnabled(true);
+ });
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/PublishProfilePictureActivity.java b/src/main/java/de/pixart/messenger/ui/PublishProfilePictureActivity.java
index 8dfcd11da..a6f158646 100644
--- a/src/main/java/de/pixart/messenger/ui/PublishProfilePictureActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/PublishProfilePictureActivity.java
@@ -1,16 +1,11 @@
package de.pixart.messenger.ui;
-import android.app.PendingIntent;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.Button;
@@ -18,25 +13,18 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-import com.soundcloud.android.crop.Crop;
-
-import java.io.File;
+import com.theartofdev.edmodo.cropper.CropImage;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
import de.pixart.messenger.entities.Account;
-import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.services.XmppConnectionService;
-import de.pixart.messenger.utils.FileUtils;
+import de.pixart.messenger.ui.interfaces.OnAvatarPublication;
import de.pixart.messenger.utils.PhoneHelper;
-import de.pixart.messenger.xmpp.pep.Avatar;
-public class PublishProfilePictureActivity extends XmppActivity implements XmppConnectionService.OnAccountUpdate {
+public class PublishProfilePictureActivity extends XmppActivity implements XmppConnectionService.OnAccountUpdate, OnAvatarPublication {
- private static final int REQUEST_CHOOSE_FILE_AND_CROP = 0xac23;
- private static final int REQUEST_CHOOSE_FILE = 0xac24;
private ImageView avatar;
- private TextView accountTextView;
private TextView hintOrWarning;
private TextView secondaryHint;
private Button cancelButton;
@@ -56,41 +44,33 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
}
};
private boolean mInitialAccountSetup;
- private UiCallback<Avatar> avatarPublication = new UiCallback<Avatar>() {
-
- @Override
- public void success(Avatar object) {
- runOnUiThread(() -> {
- if (mInitialAccountSetup) {
- Intent intent = new Intent(getApplicationContext(), StartConversationActivity.class);
- WelcomeActivity.addInviteUri(intent, getIntent());
- intent.putExtra("init", true);
- startActivity(intent);
- overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
- }
- Toast.makeText(PublishProfilePictureActivity.this,
- R.string.avatar_has_been_published,
- Toast.LENGTH_SHORT).show();
- finish();
- });
- }
-
- @Override
- public void error(final int errorCode, Avatar object) {
- runOnUiThread(() -> {
- hintOrWarning.setText(errorCode);
- hintOrWarning.setTextColor(getWarningTextColor());
- hintOrWarning.setVisibility(View.VISIBLE);
- publishing = false;
- togglePublishButton(true,R.string.publish);
- });
- }
+ @Override
+ public void onAvatarPublicationSucceeded() {
+ runOnUiThread(() -> {
+ if (mInitialAccountSetup) {
+ Intent intent = new Intent(getApplicationContext(), StartConversationActivity.class);
+ WelcomeActivity.addInviteUri(intent, getIntent());
+ intent.putExtra("init", true);
+ startActivity(intent);
+ }
+ Toast.makeText(PublishProfilePictureActivity.this,
+ R.string.avatar_has_been_published,
+ Toast.LENGTH_SHORT).show();
+ finish();
+ });
+ }
- @Override
- public void userInputRequried(PendingIntent pi, Avatar object) {
- }
- };
+ @Override
+ public void onAvatarPublicationFailed(int res) {
+ runOnUiThread(() -> {
+ hintOrWarning.setText(res);
+ hintOrWarning.setTextColor(getWarningTextColor());
+ hintOrWarning.setVisibility(View.VISIBLE);
+ publishing = false;
+ togglePublishButton(true, R.string.publish);
+ });
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -98,6 +78,7 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
setContentView(R.layout.activity_publish_profile_picture);
setSupportActionBar(findViewById(R.id.toolbar));
configureActionBar(getSupportActionBar());
+
this.avatar = findViewById(R.id.account_image);
this.cancelButton = findViewById(R.id.cancel_button);
this.publishButton = findViewById(R.id.publish_button);
@@ -106,8 +87,8 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
this.publishButton.setOnClickListener(v -> {
if (avatarUri != null) {
publishing = true;
- togglePublishButton(false,R.string.publishing);
- xmppConnectionService.publishAvatar(account, avatarUri, avatarPublication);
+ togglePublishButton(false, R.string.publishing);
+ xmppConnectionService.publishAvatar(account, avatarUri, this);
}
});
this.cancelButton.setOnClickListener(v -> {
@@ -118,103 +99,38 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
intent.putExtra("init", true);
}
startActivity(intent);
- overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
}
finish();
});
- this.avatar.setOnClickListener(v -> {
- if (hasStoragePermission(REQUEST_CHOOSE_FILE)) {
- chooseAvatar(false);
- }
- });
+ this.avatar.setOnClickListener(v -> chooseAvatar());
this.defaultUri = PhoneHelper.getProfilePictureUri(getApplicationContext());
}
- private void chooseAvatar(boolean crop) {
- Intent attachFileIntent = new Intent();
- attachFileIntent.setType("image/*");
- attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
- Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
- startActivityForResult(chooser, crop ? REQUEST_CHOOSE_FILE_AND_CROP : REQUEST_CHOOSE_FILE);
- overridePendingTransition(R.animator.fade_in, R.animator.fade_out);
- }
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
- if (grantResults.length > 0)
- if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (requestCode == REQUEST_CHOOSE_FILE_AND_CROP) {
- chooseAvatar(true);
- } else if (requestCode == REQUEST_CHOOSE_FILE) {
- chooseAvatar(false);
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
+ CropImage.ActivityResult result = CropImage.getActivityResult(data);
+ if (resultCode == RESULT_OK) {
+ this.avatarUri = result.getUri();
+ if (xmppConnectionServiceBound) {
+ loadImageIntoPreview(this.avatarUri);
+ }
+ } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
+ Exception error = result.getError();
+ if (error != null) {
+ Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
- } else {
- Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.publish_avatar, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(final MenuItem item) {
- if (item.getItemId() == R.id.action_crop_image) {
- if (hasStoragePermission(REQUEST_CHOOSE_FILE_AND_CROP)) {
- chooseAvatar(true);
}
- return true;
- } else {
- return super.onOptionsItemSelected(item);
}
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (resultCode == RESULT_OK) {
- Uri source = data.getData();
- switch (requestCode) {
- case REQUEST_CHOOSE_FILE_AND_CROP:
- if (FileBackend.weOwnFile(this, source)) {
- Toast.makeText(this, R.string.security_error_invalid_file_access, Toast.LENGTH_SHORT).show();
- return;
- }
- String original = FileUtils.getPath(this, source);
- if (original != null) {
- source = Uri.parse("file://" + original);
- }
- Uri destination = Uri.fromFile(new File(getCacheDir(), "croppedAvatar"));
- final int size = getPixel(Config.AVATAR_SIZE);
- Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this);
- break;
- case REQUEST_CHOOSE_FILE:
- if (FileBackend.weOwnFile(this, source)) {
- Toast.makeText(this, R.string.security_error_invalid_file_access, Toast.LENGTH_SHORT).show();
- return;
- }
- this.avatarUri = source;
- if (xmppConnectionServiceBound) {
- loadImageIntoPreview(this.avatarUri);
- }
- break;
- case Crop.REQUEST_CROP:
- this.avatarUri = Uri.fromFile(new File(getCacheDir(), "croppedAvatar"));
- if (xmppConnectionServiceBound) {
- loadImageIntoPreview(this.avatarUri);
- }
- break;
- }
- } else {
- if (requestCode == Crop.REQUEST_CROP && data != null) {
- Throwable throwable = Crop.getError(data);
- if (throwable != null && throwable instanceof OutOfMemoryError) {
- Toast.makeText(this, R.string.selection_too_large, Toast.LENGTH_SHORT).show();
- }
- }
- }
+ private void chooseAvatar() {
+ CropImage.activity()
+ .setOutputCompressFormat(Bitmap.CompressFormat.PNG)
+ .setAspectRatio(1, 1)
+ .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE)
+ .start(this);
}
@Override
@@ -251,6 +167,7 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
}
protected void loadImageIntoPreview(Uri uri) {
+
Bitmap bm = null;
if (uri == null) {
bm = avatarService().get(account, getPixel(Config.AVATAR_SIZE));
@@ -308,4 +225,5 @@ public class PublishProfilePictureActivity extends XmppActivity implements XmppC
public void onAccountUpdate() {
refreshUi();
}
-}
+
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnAvatarPublication.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnAvatarPublication.java
new file mode 100644
index 000000000..86df8d420
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnAvatarPublication.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package de.pixart.messenger.ui.interfaces;
+
+import android.support.annotation.StringRes;
+
+public interface OnAvatarPublication {
+
+ void onAvatarPublicationSucceeded();
+
+ void onAvatarPublicationFailed(@StringRes int res);
+
+} \ No newline at end of file
diff --git a/src/main/res/drawable/account_image_border.xml b/src/main/res/drawable/account_image_border.xml
new file mode 100644
index 000000000..ba262a1df
--- /dev/null
+++ b/src/main/res/drawable/account_image_border.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <corners android:radius="2dp" />
+
+ <padding
+ android:bottom="1.5dp"
+ android:left="1.5dp"
+ android:right="1.5dp"
+ android:top="1.5dp" />
+
+ <solid android:color="@color/black12" />
+
+</shape> \ No newline at end of file
diff --git a/src/main/res/layout/activity_muc_details.xml b/src/main/res/layout/activity_muc_details.xml
index ac668c70e..015cc2a44 100644
--- a/src/main/res/layout/activity_muc_details.xml
+++ b/src/main/res/layout/activity_muc_details.xml
@@ -34,169 +34,201 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="vertical"
- android:padding="@dimen/card_padding_regular">
+ android:orientation="vertical">
- <android.support.text.emoji.widget.EmojiTextView
- android:id="@+id/conference_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:paddingBottom="5dp"
- android:text="@string/conference_subject"
- android:textAlignment="center"
- android:textAppearance="@style/TextAppearance.Conversations.Title"
- android:textIsSelectable="false"
- android:textStyle="bold" />
-
- <com.makeramen.roundedimageview.RoundedImageView
- android:id="@+id/details_muc_avatar"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:adjustViewBounds="true"
- android:maxHeight="384dp"
- android:maxWidth="384dp"
- android:padding="1dp"
- android:scaleType="centerCrop"
- app:riv_border_color="?attr/color_border"
- app:riv_border_width="1dp"
- app:riv_corner_radius="@dimen/rounded_image_border"/>
-
- <RelativeLayout
- android:id="@+id/muc_settings"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:gravity="center_horizontal"
+ android:orientation="vertical"
+ android:padding="@dimen/card_padding_regular">
- <TextView
- android:id="@+id/muc_conference_type"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:layout_toLeftOf="@+id/change_conference_button"
- android:text="@string/private_conference"
- android:textAppearance="@style/TextAppearance.Conversations.Body1" />
-
- <ImageButton
- android:id="@+id/change_conference_button"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:layout_gravity="center_horizontal"
- android:alpha="?attr/icon_alpha"
- android:background="?attr/selectableItemBackgroundBorderless"
- android:padding="@dimen/image_button_padding"
- android:src="?attr/icon_settings" />
- </RelativeLayout>
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ <android.support.text.emoji.widget.EmojiTextView
+ android:id="@+id/muc_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@+id/edit_muc_name_button"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.Conversations.Title" />
- <TextView
- android:id="@+id/notification_status_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:layout_toLeftOf="@+id/notification_status_button"
- android:text="@string/notify_on_all_messages"
- android:textAppearance="@style/TextAppearance.Conversations.Body1" />
-
- <ImageButton
- android:id="@+id/notification_status_button"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:layout_gravity="center_horizontal"
- android:alpha="?attr/icon_alpha"
- android:background="?attr/selectableItemBackgroundBorderless"
- android:padding="@dimen/image_button_padding"
- android:src="@drawable/ic_notifications_black_24dp" />
- </RelativeLayout>
+ <android.support.text.emoji.widget.EmojiTextView
+ android:id="@+id/muc_subject"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/muc_title"
+ android:layout_toLeftOf="@+id/edit_muc_name_button"
+ android:textAppearance="@style/TextAppearance.Conversations.Subhead" />
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginTop="2dp">
-
- <com.makeramen.roundedimageview.RoundedImageView
- android:id="@+id/your_photo"
- android:layout_width="72dp"
- android:layout_height="72dp"
- android:layout_alignParentEnd="false"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="false"
- android:padding="1dp"
- app:riv_border_color="?attr/color_border"
- app:riv_border_width="1dp"
- app:riv_corner_radius="@dimen/rounded_image_border" />
-
- <LinearLayout
- android:layout_width="fill_parent"
+ <TextView
+ android:id="@+id/jid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/muc_subject"
+ android:layout_toLeftOf="@+id/edit_muc_name_button"
+ android:text="@string/account_settings_example_jabber_id"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1"
+ android:textIsSelectable="true"
+ android:visibility="gone" />
+
+ <ImageButton
+ android:id="@+id/edit_muc_name_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:alpha="?attr/icon_alpha"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="@dimen/image_button_padding"
+ android:src="?attr/icon_edit_body" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toRightOf="@+id/your_photo"
+ android:gravity="center_horizontal"
android:orientation="vertical"
- android:paddingLeft="@dimen/avatar_item_distance">
+ android:paddingTop="@dimen/card_padding_regular">
- <android.support.text.emoji.widget.EmojiTextView
- android:id="@+id/muc_your_nick"
+ <com.makeramen.roundedimageview.RoundedImageView
+ android:id="@+id/details_muc_avatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.Conversations.Subhead" />
+ android:adjustViewBounds="true"
+ android:maxHeight="384dp"
+ android:maxWidth="384dp"
+ android:padding="1dp"
+ android:scaleType="centerCrop"
+ app:riv_border_color="?attr/color_border"
+ app:riv_border_width="1dp"
+ app:riv_corner_radius="@dimen/rounded_image_border" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/muc_settings"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/muc_conference_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:layout_toLeftOf="@+id/change_conference_button"
+ android:text="@string/private_conference"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+
+ <ImageButton
+ android:id="@+id/change_conference_button"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:layout_gravity="center_horizontal"
+ android:alpha="?attr/icon_alpha"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="@dimen/image_button_padding"
+ android:src="?attr/icon_settings" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
<TextView
- android:id="@+id/muc_role"
+ android:id="@+id/notification_status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:layout_toLeftOf="@+id/notification_status_button"
+ android:text="@string/notify_on_all_messages"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+
+ <ImageButton
+ android:id="@+id/notification_status_button"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:layout_gravity="center_horizontal"
+ android:alpha="?attr/icon_alpha"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="@dimen/image_button_padding"
+ android:src="@drawable/ic_notifications_black_24dp" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/muc_info_more"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:layout_toLeftOf="@+id/muc_info_mam"
+ android:ellipsize="end"
android:singleLine="true"
- android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary" />
- </LinearLayout>
+ android:text="@string/server_info_mam"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+
+ <TextView
+ android:id="@+id/muc_info_mam"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:layout_gravity="center_horizontal"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="@dimen/image_button_padding"
+ android:paddingLeft="4dp"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+ </RelativeLayout>
+
+ </LinearLayout>
- <ImageButton
- android:id="@+id/edit_nick_button"
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="@dimen/card_padding_list">
+
+ <Button
+ android:id="@+id/destroy"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="24dp"
+ android:text="@string/destroy_muc" />
+
+ <TextView
+ android:id="@+id/details_account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:alpha="?attr/icon_alpha"
- android:background="?attr/selectableItemBackgroundBorderless"
- android:padding="@dimen/image_button_padding"
- android:src="?attr/icon_edit_body" />
- </RelativeLayout>
-
- <TextView
- android:id="@+id/muc_jabberid"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:text="@string/account_settings_example_jabber_id"
- android:textAppearance="@style/TextAppearance.Conversations.Title"
- android:textIsSelectable="true"
- android:visibility="gone" />
-
- <TextView
- android:id="@+id/details_account"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:layout_marginTop="32dp"
- android:text="@string/using_account"
- android:textAppearance="@style/TextAppearance.Conversations.Caption"
- android:visibility="gone" />
+ android:layout_gravity="right"
+ android:layout_marginTop="24dp"
+ android:text="@string/using_account"
+ android:textAppearance="@style/TextAppearance.Conversations.Caption"
+ android:visibility="visible" />
+ </LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
- android:id="@+id/muc_more_details"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
@@ -207,67 +239,105 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:padding="@dimen/card_padding_list">
+ android:orientation="vertical">
<LinearLayout
- android:id="@+id/muc_members"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:divider="?android:dividerHorizontal"
- android:orientation="vertical"
- android:showDividers="middle"></LinearLayout>
-
- <Button
- android:id="@+id/invite"
- style="?android:attr/buttonStyleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="24dp"
- android:text="@string/invite_contact" />
+ android:gravity="center_horizontal"
+ android:orientation="vertical"
+ android:padding="@dimen/card_padding_regular">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="2dp">
+
+ <com.makeramen.roundedimageview.RoundedImageView
+ android:id="@+id/your_photo"
+ android:layout_width="72dp"
+ android:layout_height="72dp"
+ android:layout_alignParentEnd="false"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="false"
+ android:padding="1dp"
+ app:riv_border_color="?attr/color_border"
+ app:riv_border_width="1dp"
+ app:riv_corner_radius="@dimen/rounded_image_border" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toRightOf="@+id/your_photo"
+ android:orientation="vertical"
+ android:paddingLeft="@dimen/avatar_item_distance">
+
+ <android.support.text.emoji.widget.EmojiTextView
+ android:id="@+id/muc_your_nick"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.Conversations.Subhead" />
+
+ <TextView
+ android:id="@+id/muc_role"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary" />
+ </LinearLayout>
+
+ <ImageButton
+ android:id="@+id/edit_nick_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:alpha="?attr/icon_alpha"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="@dimen/image_button_padding"
+ android:src="?attr/icon_edit_body" />
+ </RelativeLayout>
+ </LinearLayout>
- <Button
- android:id="@+id/leave_muc"
- style="?android:attr/buttonStyleSmall"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="24dp"
- android:text="@string/action_end_conversation_muc" />
+ android:orientation="vertical"
+ android:padding="@dimen/card_padding_list">
- <Button
- android:id="@+id/add_contact_button"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="24dp"
- android:text="@string/add_to_contact_list" />
+ <Button
+ android:id="@+id/leave_muc"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="24dp"
+ android:text="@string/action_end_conversation_muc" />
- <Button
- android:id="@+id/destroy"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="24dp"
- android:text="@string/destroy_muc" />
+ <Button
+ android:id="@+id/add_contact_button"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="24dp"
+ android:text="@string/add_to_contact_list" />
+
+ </LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
- android:id="@+id/muc_info_more"
- android:layout_width="fill_parent"
+ android:id="@+id/muc_more_details"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"
- android:orientation="vertical"
- android:visibility="gone">
-
+ android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
@@ -275,33 +345,25 @@
android:orientation="vertical"
android:padding="@dimen/card_padding_list">
- <TableLayout
+ <Button
+ android:id="@+id/invite"
+ style="?android:attr/buttonStyleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:stretchColumns="1">
-
- <TableRow
- android:layout_width="fill_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="@string/server_info_mam"
- android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="24dp"
+ android:text="@string/invite_contact" />
- <TextView
- android:id="@+id/muc_info_mam"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:paddingLeft="4dp"
- android:textAppearance="@style/TextAppearance.Conversations.Body1" />
- </TableRow>
- </TableLayout>
+ <LinearLayout
+ android:id="@+id/muc_members"
+ android:layout_width="fill_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:divider="?android:dividerHorizontal"
+ android:orientation="vertical"
+ android:showDividers="middle"></LinearLayout>
</LinearLayout>
+
</android.support.v7.widget.CardView>
</LinearLayout>
</ScrollView>
diff --git a/src/main/res/layout/activity_publish_profile_picture.xml b/src/main/res/layout/activity_publish_profile_picture.xml
index 1ede0bea1..eebfa76a6 100644
--- a/src/main/res/layout/activity_publish_profile_picture.xml
+++ b/src/main/res/layout/activity_publish_profile_picture.xml
@@ -1,128 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?attr/color_background_secondary">
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
- <include
- android:id="@+id/toolbar"
- layout="@layout/toolbar" />
-
- <ScrollView
+ <RelativeLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_above="@+id/button_bar"
- android:layout_below="@id/toolbar">
+ android:layout_height="match_parent"
+ android:background="?attr/color_background_secondary">
+
+ <include
+ android:id="@+id/toolbar"
+ layout="@layout/toolbar" />
<android.support.v7.widget.CardView
- android:layout_width="match_parent"
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
+ android:layout_below="@id/toolbar"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin">
<LinearLayout
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="@dimen/card_padding_regular">
- <LinearLayout
+ <FrameLayout
android:id="@+id/account_image_wrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_below="@+id/secondary_hint"
- android:layout_centerHorizontal="true"
- android:layout_gravity="center_horizontal">
+ android:layout_marginBottom="8dp"
+ android:layout_marginTop="@dimen/publish_avatar_top_margin">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/account_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
- android:contentDescription="@string/account_image_description"
android:maxHeight="384dp"
android:maxWidth="384dp"
android:padding="1dp"
- app:riv_border_color="?attr/message_border"
+ android:scaleType="centerCrop"
+ app:riv_border_color="?attr/color_border"
app:riv_border_width="1dp"
app:riv_corner_radius="@dimen/rounded_image_border" />
- </LinearLayout>
+ </FrameLayout>
<TextView
android:id="@+id/hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/account_image_wrapper"
- android:layout_centerHorizontal="true"
- android:layout_gravity="center_horizontal"
android:text="@string/touch_to_choose_picture"
- android:textAlignment="center"
- android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
<TextView
android:id="@+id/secondary_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/hint"
- android:layout_centerHorizontal="true"
- android:layout_gravity="center_horizontal"
android:text="@string/or_long_press_for_default"
- android:textAlignment="center"
- android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
<TextView
android:id="@+id/hint_or_warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
- android:minLines="3"
- android:textAlignment="center"
- android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
+ android:textAppearance="@style/TextAppearance.Conversations.Body1" />
+
</LinearLayout>
</android.support.v7.widget.CardView>
- </ScrollView>
-
- <LinearLayout
- android:id="@+id/button_bar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true">
-
- <Button
- android:id="@+id/cancel_button"
- style="@style/Widget.Conversations.Button.Borderless"
- android:layout_width="0dp"
+ <LinearLayout
+ android:id="@+id/button_bar"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/cancel" />
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true">
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:layout_marginBottom="7dp"
- android:layout_marginTop="7dp" />
+ <Button
+ android:id="@+id/cancel_button"
+ style="@style/Widget.Conversations.Button.Borderless"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/cancel" />
- <Button
- android:id="@+id/publish_button"
- style="@style/Widget.Conversations.Button.Borderless"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:enabled="false"
- android:text="@string/publish" />
- </LinearLayout>
+ <View
+ android:layout_width="1dp"
+ android:layout_height="fill_parent"
+ android:layout_marginBottom="7dp"
+ android:layout_marginTop="7dp"
+ android:background="?attr/divider" />
+
+ <Button
+ android:id="@+id/publish_button"
+ style="@style/Widget.Conversations.Button.Borderless"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:enabled="false"
+ android:text="@string/publish" />
+ </LinearLayout>
-</RelativeLayout>
+ </RelativeLayout>
+</layout> \ No newline at end of file
diff --git a/src/main/res/menu/muc_details.xml b/src/main/res/menu/muc_details.xml
index f0336bdce..b5e74f271 100644
--- a/src/main/res/menu/muc_details.xml
+++ b/src/main/res/menu/muc_details.xml
@@ -3,12 +3,6 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
- android:id="@+id/action_edit_subject"
- android:icon="?attr/icon_edit"
- android:orderInCategory="10"
- android:title="@string/action_edit_subject"
- app:showAsAction="always" />
- <item
android:id="@+id/action_share"
android:icon="?attr/icon_share"
android:orderInCategory="15"
diff --git a/src/main/res/menu/publish_avatar.xml b/src/main/res/menu/publish_avatar.xml
deleted file mode 100644
index 72ceb2d17..000000000
--- a/src/main/res/menu/publish_avatar.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <item
- android:id="@+id/action_crop_image"
- app:showAsAction="always"
- android:icon="@drawable/ic_crop_white_24dp"
- android:title="@string/select_image_and_crop" />
-</menu> \ No newline at end of file
diff --git a/src/main/res/values/dimens.xml b/src/main/res/values/dimens.xml
index 721cc4f9c..50f955c89 100644
--- a/src/main/res/values/dimens.xml
+++ b/src/main/res/values/dimens.xml
@@ -12,6 +12,10 @@
<dimen name="toolbar_elevation">4dp</dimen>
+ <dimen name="publish_avatar_top_margin">8dp</dimen>
+ <dimen name="publish_avatar_size">96dp</dimen>
+ <dimen name="avatar_on_details_screen_size">56dp</dimen>
+
<dimen name="input_label_vertical_spacing">4dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 27366987c..bd7d0e0e1 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -528,7 +528,6 @@
<string name="correct_message">Correct message</string>
<string name="send_corrected_message">Send corrected message</string>
<string name="no_keys_just_confirm">You already trust this contact. By selecting ’done’ you are just confirming that %s is part of this group chat.</string>
- <string name="select_image_and_crop">Select image and crop</string>
<string name="contacts_have_no_pgp_keys">Pix-Art Messenger is unable to encrypt your messages because your contacts are not announcing their public keys.\n\n</string>
<string name="this_account_is_disabled">You have disabled this account</string>
<string name="security_error_invalid_file_access">Security error: Invalid file access</string>
@@ -797,4 +796,7 @@
<string name="pref_start_search">Direct Search</string>
<string name="pref_start_search_summary">At 'Start Conversation' screen open keyboard and place cursor in search field</string>
<string name="paste_as_quote">Paste as quote</string>
+ <string name="group_chat_avatar">Group chat avatar</string>
+ <string name="host_does_not_support_group_chat_avatars">Host does not support group chat avatars</string>
+ <string name="only_the_owner_can_change_group_chat_avatar">Only the owner can change group chat avatar</string>
</resources>