1package eu.siacs.conversations.ui;
2
3import android.content.Intent;
4import android.graphics.Bitmap;
5import android.net.Uri;
6import android.os.Bundle;
7import android.support.annotation.StringRes;
8import android.util.Log;
9import android.view.View;
10import android.view.View.OnLongClickListener;
11import android.widget.Button;
12import android.widget.ImageView;
13import android.widget.TextView;
14import android.widget.Toast;
15
16import com.theartofdev.edmodo.cropper.CropImage;
17
18import eu.siacs.conversations.Config;
19import eu.siacs.conversations.R;
20import eu.siacs.conversations.entities.Account;
21import eu.siacs.conversations.services.XmppConnectionService;
22import eu.siacs.conversations.ui.interfaces.OnAvatarPublication;
23import eu.siacs.conversations.utils.PhoneHelper;
24
25public class PublishProfilePictureActivity extends XmppActivity implements XmppConnectionService.OnAccountUpdate, OnAvatarPublication {
26
27 private ImageView avatar;
28 private TextView hintOrWarning;
29 private TextView secondaryHint;
30 private Button cancelButton;
31 private Button publishButton;
32 private Uri avatarUri;
33 private Uri defaultUri;
34 private Account account;
35 private boolean support = false;
36 private boolean publishing = false;
37 private OnLongClickListener backToDefaultListener = new OnLongClickListener() {
38
39 @Override
40 public boolean onLongClick(View v) {
41 avatarUri = defaultUri;
42 loadImageIntoPreview(defaultUri);
43 return true;
44 }
45 };
46 private boolean mInitialAccountSetup;
47
48 @Override
49 public void onAvatarPublicationSucceeded() {
50 runOnUiThread(() -> {
51 if (mInitialAccountSetup) {
52 Intent intent = new Intent(getApplicationContext(), StartConversationActivity.class);
53 StartConversationActivity.addInviteUri(intent, getIntent());
54 intent.putExtra("init", true);
55 startActivity(intent);
56 }
57 Toast.makeText(PublishProfilePictureActivity.this,
58 R.string.avatar_has_been_published,
59 Toast.LENGTH_SHORT).show();
60 finish();
61 });
62 }
63
64 @Override
65 public void onAvatarPublicationFailed(int res) {
66 runOnUiThread(() -> {
67 hintOrWarning.setText(res);
68 hintOrWarning.setTextColor(getWarningTextColor());
69 hintOrWarning.setVisibility(View.VISIBLE);
70 publishing = false;
71 togglePublishButton(true, R.string.publish);
72 });
73 }
74
75 @Override
76 public void onCreate(Bundle savedInstanceState) {
77 super.onCreate(savedInstanceState);
78 setContentView(R.layout.activity_publish_profile_picture);
79 setSupportActionBar(findViewById(R.id.toolbar));
80
81 this.avatar = findViewById(R.id.account_image);
82 this.cancelButton = findViewById(R.id.cancel_button);
83 this.publishButton = findViewById(R.id.publish_button);
84 this.hintOrWarning = findViewById(R.id.hint_or_warning);
85 this.secondaryHint = findViewById(R.id.secondary_hint);
86 this.publishButton.setOnClickListener(v -> {
87 if (avatarUri != null) {
88 publishing = true;
89 togglePublishButton(false, R.string.publishing);
90 xmppConnectionService.publishAvatar(account, avatarUri, this);
91 }
92 });
93 this.cancelButton.setOnClickListener(v -> {
94 if (mInitialAccountSetup) {
95 Intent intent = new Intent(getApplicationContext(), StartConversationActivity.class);
96 if (xmppConnectionService != null && xmppConnectionService.getAccounts().size() == 1) {
97 StartConversationActivity.addInviteUri(intent, getIntent());
98 intent.putExtra("init", true);
99 }
100 startActivity(intent);
101 }
102 finish();
103 });
104 this.avatar.setOnClickListener(v -> chooseAvatar());
105 this.defaultUri = PhoneHelper.getProfilePictureUri(getApplicationContext());
106 }
107
108
109 @Override
110 public void onActivityResult(int requestCode, int resultCode, Intent data) {
111 if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
112 CropImage.ActivityResult result = CropImage.getActivityResult(data);
113 if (resultCode == RESULT_OK) {
114 this.avatarUri = result.getUri();
115 if (xmppConnectionServiceBound) {
116 loadImageIntoPreview(this.avatarUri);
117 }
118 } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
119 Exception error = result.getError();
120 if (error != null) {
121 Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
122 }
123 }
124 }
125 }
126
127 private void chooseAvatar() {
128 CropImage.activity()
129 .setOutputCompressFormat(Bitmap.CompressFormat.PNG)
130 .setAspectRatio(1, 1)
131 .setMinCropResultSize(Config.AVATAR_SIZE, Config.AVATAR_SIZE)
132 .start(this);
133 }
134
135 @Override
136 protected void onBackendConnected() {
137 this.account = extractAccount(getIntent());
138 if (this.account != null) {
139 reloadAvatar();
140 }
141 }
142
143 private void reloadAvatar() {
144 this.support = this.account.getXmppConnection() != null && this.account.getXmppConnection().getFeatures().pep();
145 if (this.avatarUri == null) {
146 if (this.account.getAvatar() != null || this.defaultUri == null) {
147 loadImageIntoPreview(null);
148 } else {
149 this.avatarUri = this.defaultUri;
150 loadImageIntoPreview(this.defaultUri);
151 }
152 } else {
153 loadImageIntoPreview(avatarUri);
154 }
155 }
156
157 @Override
158 protected void onStart() {
159 super.onStart();
160 final Intent intent = getIntent();
161 this.mInitialAccountSetup = intent != null && intent.getBooleanExtra("setup", false);
162
163 if (this.mInitialAccountSetup) {
164 this.cancelButton.setText(R.string.skip);
165 }
166 configureActionBar(getSupportActionBar(), !this.mInitialAccountSetup);
167 }
168
169 protected void loadImageIntoPreview(Uri uri) {
170
171 Bitmap bm = null;
172 if (uri == null) {
173 bm = avatarService().get(account, (int) getResources().getDimension(R.dimen.publish_avatar_size));
174 } else {
175 try {
176 bm = xmppConnectionService.getFileBackend().cropCenterSquare(uri, (int) getResources().getDimension(R.dimen.publish_avatar_size));
177 } catch (Exception e) {
178 Log.d(Config.LOGTAG, "unable to load bitmap into image view", e);
179 }
180 }
181
182 if (bm == null) {
183 togglePublishButton(false, R.string.publish);
184 this.hintOrWarning.setVisibility(View.VISIBLE);
185 this.hintOrWarning.setTextColor(getWarningTextColor());
186 this.hintOrWarning.setText(R.string.error_publish_avatar_converting);
187 return;
188 }
189 this.avatar.setImageBitmap(bm);
190 if (support) {
191 togglePublishButton(uri != null, R.string.publish);
192 this.hintOrWarning.setVisibility(View.INVISIBLE);
193 } else {
194 togglePublishButton(false, R.string.publish);
195 this.hintOrWarning.setVisibility(View.VISIBLE);
196 this.hintOrWarning.setTextColor(getWarningTextColor());
197 if (account.getStatus() == Account.State.ONLINE) {
198 this.hintOrWarning.setText(R.string.error_publish_avatar_no_server_support);
199 } else {
200 this.hintOrWarning.setText(R.string.error_publish_avatar_offline);
201 }
202 }
203 if (this.defaultUri == null || this.defaultUri.equals(uri)) {
204 this.secondaryHint.setVisibility(View.INVISIBLE);
205 this.avatar.setOnLongClickListener(null);
206 } else if (this.defaultUri != null) {
207 this.secondaryHint.setVisibility(View.VISIBLE);
208 this.avatar.setOnLongClickListener(this.backToDefaultListener);
209 }
210 }
211
212 protected void togglePublishButton(boolean enabled, @StringRes int res) {
213 final boolean status = enabled && !publishing;
214 this.publishButton.setText(publishing ? R.string.publishing : res);
215 this.publishButton.setEnabled(status);
216 }
217
218 public void refreshUiReal() {
219 if (this.account != null) {
220 reloadAvatar();
221 }
222 }
223
224 @Override
225 public void onAccountUpdate() {
226 refreshUi();
227 }
228
229}