fedilab-Android-App/app/src/main/java/app/fedilab/android/mastodon/activities/EditProfileActivity.java

366 lines
18 KiB
Java
Raw Normal View History

2023-01-22 15:22:59 +01:00
package app.fedilab.android.mastodon.activities;
2022-04-27 15:20:42 +02:00
/* Copyright 2022 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
2024-01-29 15:02:56 +01:00
2022-04-27 15:20:42 +02:00
import static app.fedilab.android.BaseMainActivity.instanceInfo;
import android.annotation.SuppressLint;
2022-04-27 15:20:42 +02:00
import android.content.Intent;
2022-11-05 15:06:21 +01:00
import android.net.Uri;
2022-04-27 15:20:42 +02:00
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
2023-12-12 17:27:05 +01:00
2022-04-27 15:20:42 +02:00
import com.bumptech.glide.Glide;
2023-01-17 14:36:51 +01:00
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
2022-04-27 15:20:42 +02:00
import com.google.android.material.textfield.TextInputEditText;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
2023-12-14 07:33:59 +01:00
import java.util.Objects;
2022-04-27 15:20:42 +02:00
import app.fedilab.android.BaseMainActivity;
2023-12-12 17:27:05 +01:00
import app.fedilab.android.BuildConfig;
2022-04-27 15:20:42 +02:00
import app.fedilab.android.R;
import app.fedilab.android.databinding.AccountFieldItemBinding;
import app.fedilab.android.databinding.ActivityEditProfileBinding;
2023-01-22 15:22:59 +01:00
import app.fedilab.android.mastodon.client.entities.api.Account;
import app.fedilab.android.mastodon.client.entities.api.Field;
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
2023-01-22 15:22:59 +01:00
import app.fedilab.android.mastodon.exception.DBException;
import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.helper.MastodonHelper;
import app.fedilab.android.mastodon.viewmodel.mastodon.AccountsVM;
2022-04-27 15:20:42 +02:00
import es.dmoral.toasty.Toasty;
2022-11-30 11:00:53 +01:00
public class EditProfileActivity extends BaseBarActivity {
2022-04-27 15:20:42 +02:00
public static final int PICK_MEDIA_AVATAR = 5705;
public static final int PICK_MEDIA_HEADER = 5706;
private ActivityEditProfileBinding binding;
private AccountsVM accountsVM;
@SuppressLint("ClickableViewAccessibility")
2022-04-27 15:20:42 +02:00
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
2022-11-28 10:37:57 +01:00
2022-04-27 15:20:42 +02:00
binding = ActivityEditProfileBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
2022-05-08 10:37:47 +02:00
if (getSupportActionBar() != null) {
2022-04-27 15:20:42 +02:00
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2022-05-08 10:37:47 +02:00
}
2022-04-27 15:20:42 +02:00
binding.scrollContainer.setOnTouchListener((v, event) -> {
binding.bio.getParent().requestDisallowInterceptTouchEvent(false);
return false;
});
binding.bio.setOnTouchListener((v, event) -> {
binding.bio.getParent().requestDisallowInterceptTouchEvent(true);
return false;
});
2022-04-27 15:20:42 +02:00
new ViewModelProvider(EditProfileActivity.this).get(AccountsVM.class).getConnectedAccount(BaseMainActivity.currentInstance, BaseMainActivity.currentToken)
.observe(EditProfileActivity.this, account -> {
2022-06-01 16:37:01 +02:00
if (account != null) {
2024-01-29 15:02:56 +01:00
Helper.setCurrentAccountMastodonAccount(EditProfileActivity.this, account);
2022-06-01 16:37:01 +02:00
initializeView();
} else {
Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
}
2022-04-27 15:20:42 +02:00
});
}
@SuppressWarnings("deprecation")
private void initializeView() {
//Hydrate values
2024-01-29 15:02:56 +01:00
MastodonHelper.loadProfileMediaMastodon(EditProfileActivity.this, binding.bannerPp, Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account, MastodonHelper.MediaAccountType.HEADER);
MastodonHelper.loadPPMastodon(binding.accountPp, Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account);
binding.displayName.setText(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.display_name);
binding.acct.setText(String.format(Locale.getDefault(), "%s@%s", Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.acct, BaseMainActivity.currentInstance));
2022-04-27 15:20:42 +02:00
String bio;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
2024-01-29 15:02:56 +01:00
bio = Html.fromHtml(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.note, Html.FROM_HTML_MODE_LEGACY).toString();
2022-04-27 15:20:42 +02:00
else
2024-01-29 15:02:56 +01:00
bio = Html.fromHtml(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.note).toString();
2022-04-27 15:20:42 +02:00
binding.bio.setText(bio);
2024-01-29 15:02:56 +01:00
if (Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.source != null) {
binding.sensitive.setChecked(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.source.sensitive);
switch (Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.source.privacy) {
2023-12-14 07:33:59 +01:00
case "public" -> binding.visibilityPublic.setChecked(true);
case "unlisted" -> binding.visibilityUnlisted.setChecked(true);
case "private" -> binding.visibilityPrivate.setChecked(true);
case "direct" -> binding.visibilityDirect.setChecked(true);
2022-06-20 10:57:02 +02:00
}
} else {
binding.sensitive.setVisibility(View.GONE);
binding.visibilityGroup.setVisibility(View.GONE);
}
2024-01-29 15:02:56 +01:00
binding.bot.setChecked(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.bot);
binding.discoverable.setChecked(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.discoverable);
2022-06-20 10:57:02 +02:00
2024-01-29 15:02:56 +01:00
if (Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.locked) {
2022-04-27 15:20:42 +02:00
binding.locked.setChecked(true);
} else {
binding.unlocked.setChecked(true);
}
2024-01-29 15:02:56 +01:00
List<Field> fields = Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.fields;
2022-04-27 15:20:42 +02:00
if (fields != null && fields.size() > 0) {
for (Field field : fields) {
AccountFieldItemBinding fieldItemBinding = AccountFieldItemBinding.inflate(getLayoutInflater());
fieldItemBinding.name.setText(field.name);
String value;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
value = Html.fromHtml(field.value, Html.FROM_HTML_MODE_LEGACY).toString();
else
value = Html.fromHtml(field.value).toString();
fieldItemBinding.value.setText(value);
fieldItemBinding.remove.setOnClickListener(v -> {
2023-01-30 18:15:12 +01:00
AlertDialog.Builder deleteConfirm = new MaterialAlertDialogBuilder(EditProfileActivity.this);
2022-04-27 15:20:42 +02:00
deleteConfirm.setTitle(getString(R.string.delete_field));
deleteConfirm.setMessage(getString(R.string.delete_field_confirm));
deleteConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
deleteConfirm.setPositiveButton(R.string.delete, (dialog, which) -> {
binding.fieldsContainer.removeView(fieldItemBinding.getRoot());
if (binding.fieldsContainer.getChildCount() < 4) {
binding.fieldsContainer.setVisibility(View.VISIBLE);
} else {
binding.fieldsContainer.setVisibility(View.GONE);
}
dialog.dismiss();
});
deleteConfirm.create().show();
});
binding.fieldsContainer.addView(fieldItemBinding.getRoot());
}
}
binding.addField.setOnClickListener(view -> {
AccountFieldItemBinding fieldItemBinding = AccountFieldItemBinding.inflate(getLayoutInflater());
fieldItemBinding.remove.setOnClickListener(v -> {
2023-01-30 18:15:12 +01:00
AlertDialog.Builder deleteConfirm = new MaterialAlertDialogBuilder(EditProfileActivity.this);
2022-04-27 15:20:42 +02:00
deleteConfirm.setTitle(getString(R.string.delete_field));
deleteConfirm.setMessage(getString(R.string.delete_field_confirm));
deleteConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
deleteConfirm.setPositiveButton(R.string.delete, (dialog, which) -> {
binding.fieldsContainer.removeView(fieldItemBinding.getRoot());
if (binding.fieldsContainer.getChildCount() < 4) {
binding.fieldsContainer.setVisibility(View.VISIBLE);
} else {
binding.fieldsContainer.setVisibility(View.GONE);
}
dialog.dismiss();
});
deleteConfirm.create().show();
});
binding.fieldsContainer.addView(fieldItemBinding.getRoot());
if (binding.fieldsContainer.getChildCount() >= 4) {
binding.addField.setVisibility(View.GONE);
}
});
2022-11-14 15:15:29 +01:00
2022-04-27 15:20:42 +02:00
//Actions with the activity
accountsVM = new ViewModelProvider(EditProfileActivity.this).get(AccountsVM.class);
binding.headerSelect.setOnClickListener(view -> startActivityForResult(prepareIntent(), EditProfileActivity.PICK_MEDIA_HEADER));
2022-04-27 15:20:42 +02:00
binding.avatarSelect.setOnClickListener(view -> startActivityForResult(prepareIntent(), EditProfileActivity.PICK_MEDIA_AVATAR));
2022-04-27 15:20:42 +02:00
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_MEDIA_AVATAR && resultCode == RESULT_OK) {
2022-11-05 15:06:21 +01:00
Uri uri = data.getData();
if (uri != null) {
binding.avatarProgress.setVisibility(View.VISIBLE);
Glide.with(EditProfileActivity.this)
.asDrawable()
.load(uri)
.thumbnail(0.1f)
.into(binding.accountPp);
accountsVM.updateProfilePicture(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, uri, AccountsVM.UpdateMediaType.AVATAR)
.observe(EditProfileActivity.this, account -> {
if (account != null) {
sendBroadCast(account);
binding.avatarProgress.setVisibility(View.GONE);
2024-01-29 15:02:56 +01:00
Helper.setCurrentAccountMastodonAccount(EditProfileActivity.this, account);
2022-11-05 15:06:21 +01:00
Helper.recreateMainActivity(EditProfileActivity.this);
new Thread(() -> {
try {
2024-01-29 15:02:56 +01:00
new app.fedilab.android.mastodon.client.entities.app.Account(EditProfileActivity.this).insertOrUpdate(Helper.getCurrentAccount(EditProfileActivity.this));
2022-11-05 15:06:21 +01:00
} catch (DBException e) {
e.printStackTrace();
}
}).start();
} else {
Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
}
});
} else {
Toasty.error(EditProfileActivity.this, getString(R.string.toast_error), Toasty.LENGTH_LONG).show();
}
2022-04-27 15:20:42 +02:00
} else if (requestCode == PICK_MEDIA_HEADER && resultCode == RESULT_OK) {
Glide.with(EditProfileActivity.this)
.asDrawable()
.load(data.getData())
.thumbnail(0.1f)
.into(binding.bannerPp);
binding.headerProgress.setVisibility(View.VISIBLE);
accountsVM.updateProfilePicture(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, data.getData(), AccountsVM.UpdateMediaType.HEADER)
.observe(EditProfileActivity.this, account -> {
2022-06-01 16:37:01 +02:00
if (account != null) {
sendBroadCast(account);
binding.headerProgress.setVisibility(View.GONE);
2024-01-29 15:02:56 +01:00
Helper.setCurrentAccountMastodonAccount(EditProfileActivity.this, account);
2022-06-01 16:37:01 +02:00
new Thread(() -> {
try {
2024-01-29 15:02:56 +01:00
new app.fedilab.android.mastodon.client.entities.app.Account(EditProfileActivity.this).insertOrUpdate(Helper.getCurrentAccount(EditProfileActivity.this));
2022-06-01 16:37:01 +02:00
} catch (DBException e) {
e.printStackTrace();
}
}).start();
Helper.recreateMainActivity(EditProfileActivity.this);
} else {
Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
}
2022-04-27 15:20:42 +02:00
});
}
}
private void sendBroadCast(Account account) {
Bundle args = new Bundle();
args.putBoolean(Helper.RECEIVE_REDRAW_PROFILE, true);
args.putSerializable(Helper.ARG_ACCOUNT, account);
2024-01-29 15:02:56 +01:00
new CachedBundle(EditProfileActivity.this).insertBundle(args, Helper.getCurrentAccount(EditProfileActivity.this), bundleId -> {
Bundle bundle = new Bundle();
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
Intent intentBD = new Intent(Helper.BROADCAST_DATA);
intentBD.putExtras(bundle);
intentBD.setPackage(BuildConfig.APPLICATION_ID);
sendBroadcast(intentBD);
});
2022-04-27 15:20:42 +02:00
}
private Intent prepareIntent() {
Intent intent;
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
String[] mimetypes;
long max_size = -1;
if (instanceInfo.getMimeTypeImage().size() > 0) {
mimetypes = instanceInfo.getMimeTypeImage().toArray(new String[0]);
max_size = instanceInfo.configuration.media_attachments.image_size_limit;
} else {
mimetypes = new String[]{"image/*"};
}
if (max_size > 0) {
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, max_size);
}
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
return intent;
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.menu_edit_profile, menu);
return super.onCreateOptionsMenu(menu);
}
private String getPrivacy() {
if (binding.visibilityPublic.isChecked()) {
return "public";
} else if (binding.visibilityUnlisted.isChecked()) {
return "unlisted";
} else if (binding.visibilityPrivate.isChecked()) {
return "private";
} else if (binding.visibilityDirect.isChecked()) {
return "direct";
}
return null;
}
LinkedHashMap<Integer, Field.FieldParams> getFields() {
LinkedHashMap<Integer, Field.FieldParams> fields = new LinkedHashMap<>();
for (int i = 0; i < binding.fieldsContainer.getChildCount(); i++) {
Field.FieldParams field = new Field.FieldParams();
2023-12-14 07:33:59 +01:00
field.name = Objects.requireNonNull(((TextInputEditText) binding.fieldsContainer.getChildAt(i).findViewById(R.id.name)).getText()).toString().trim();
field.value = Objects.requireNonNull(((TextInputEditText) binding.fieldsContainer.getChildAt(i).findViewById(R.id.value)).getText()).toString().trim();
2022-04-27 15:20:42 +02:00
fields.put(i, field);
}
return fields;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_save) {
accountsVM.updateCredentials(BaseMainActivity.currentInstance, BaseMainActivity.currentToken,
2022-09-26 17:08:00 +02:00
binding.discoverable.isChecked(),
binding.bot.isChecked(),
2023-12-14 07:33:59 +01:00
Objects.requireNonNull(binding.displayName.getText()).toString().trim(),
Objects.requireNonNull(binding.bio.getText()).toString(),
2022-09-26 17:08:00 +02:00
binding.locked.isChecked(),
getPrivacy(),
binding.sensitive.isChecked(),
null,
getFields()
)
2022-04-27 15:20:42 +02:00
.observe(EditProfileActivity.this, account -> {
2022-06-01 16:37:01 +02:00
if (account != null) {
2024-01-29 15:02:56 +01:00
Helper.setCurrentAccountMastodonAccount(EditProfileActivity.this, account);
2022-06-01 16:37:01 +02:00
new Thread(() -> {
try {
2024-01-29 15:02:56 +01:00
new app.fedilab.android.mastodon.client.entities.app.Account(EditProfileActivity.this).insertOrUpdate(Helper.getCurrentAccount(EditProfileActivity.this));
2022-06-01 16:37:01 +02:00
sendBroadCast(account);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
Toasty.success(EditProfileActivity.this, getString(R.string.profiled_updated), Toasty.LENGTH_LONG).show();
finish();
} else {
Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
}
2022-04-27 15:20:42 +02:00
});
return true;
}
return super.onOptionsItemSelected(item);
}
}