diff options
author | Christian Schneppe <christian@pix-art.de> | 2018-06-24 21:34:47 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2018-06-29 21:55:43 +0200 |
commit | d9d40ecb4297a7ade4205d6dca411c01aa728663 (patch) | |
tree | 2853511ab2432799cbb9d2ab1a7d736e424c8e63 | |
parent | 6633eedbb75d5fa85186c053aa7797b5b5458fc6 (diff) |
WIP: set room avatar and slight redesign of group details
*show jid in group details (in advanced mode)
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> |