Commit c0b6bbd4 authored by Thomas's avatar Thomas
Browse files

Change profile activity to manage featured hashtags

parent d514c7b8
Loading
Loading
Loading
Loading
+91 −18
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -45,10 +46,13 @@ import java.util.Objects;
import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.BuildConfig;
import app.fedilab.android.R;
import app.fedilab.android.databinding.AccountFeaturedHashtagItemBinding;
import app.fedilab.android.databinding.AccountFieldItemBinding;
import app.fedilab.android.databinding.ActivityEditProfileBinding;
import app.fedilab.android.mastodon.client.entities.api.Account;
import app.fedilab.android.mastodon.client.entities.api.FeaturedTag;
import app.fedilab.android.mastodon.client.entities.api.Field;
import app.fedilab.android.mastodon.client.entities.api.Tag;
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
import app.fedilab.android.mastodon.exception.DBException;
import app.fedilab.android.mastodon.helper.Helper;
@@ -62,6 +66,8 @@ public class EditProfileActivity extends BaseBarActivity {
    public static final int PICK_MEDIA_HEADER = 5706;
    private ActivityEditProfileBinding binding;
    private AccountsVM accountsVM;
    private static final int MAX_FIELDS = 4;
    private static final int MAX_FEATURED_HASHTAGS = 10;

    @SuppressLint("ClickableViewAccessibility")
    @Override
@@ -87,8 +93,9 @@ public class EditProfileActivity extends BaseBarActivity {

            return false;
        });
        accountsVM = new ViewModelProvider(EditProfileActivity.this).get(AccountsVM.class);

        new ViewModelProvider(EditProfileActivity.this).get(AccountsVM.class).getConnectedAccount(BaseMainActivity.currentInstance, BaseMainActivity.currentToken)
        accountsVM.getConnectedAccount(BaseMainActivity.currentInstance, BaseMainActivity.currentToken)
                .observe(EditProfileActivity.this, account -> {
                    if (account != null) {
                        Helper.setCurrentAccountMastodonAccount(EditProfileActivity.this, account);
@@ -97,9 +104,10 @@ public class EditProfileActivity extends BaseBarActivity {
                        Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
                    }
                });
    }


    }

    @SuppressWarnings("deprecation")
    private void initializeView() {
        //Hydrate values
@@ -113,6 +121,68 @@ public class EditProfileActivity extends BaseBarActivity {
        else
            bio = Html.fromHtml(Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.note).toString();
        binding.bio.setText(bio);

        accountsVM.getFeaturedTagsSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken).observe(this, featuredTags -> {
            StringBuilder text = new StringBuilder(getString(R.string.no_feature_hashtag_suggestion));
            if(featuredTags != null && !featuredTags.isEmpty()) {
                text = new StringBuilder();
                for (Tag tag : featuredTags) {
                    text.append(String.format("#%s ", tag.name));
                }
            }
            binding.featuredHashtagsSuggestions.setText(text);
        });
        accountsVM.getAccountFeaturedTags(BaseMainActivity.currentInstance, BaseMainActivity.currentToken,  Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.id).observe(this, featuredTags -> {
            if(featuredTags != null && !featuredTags.isEmpty()) {
                for (FeaturedTag featuredTag : featuredTags) {
                    AccountFeaturedHashtagItemBinding featuredHashtagItemBinding = AccountFeaturedHashtagItemBinding.inflate(getLayoutInflater());
                    featuredHashtagItemBinding.name.setText(featuredTag.name);
                    featuredHashtagItemBinding.remove.setOnClickListener(v -> {
                        AlertDialog.Builder deleteConfirm = new MaterialAlertDialogBuilder(EditProfileActivity.this);
                        deleteConfirm.setTitle(getString(R.string.delete_featured_hashtag));
                        deleteConfirm.setMessage(getString(R.string.delete_featured_hashtag_confirm));
                        deleteConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
                        deleteConfirm.setPositiveButton(R.string.delete, (dialog, which) -> {
                            ((ViewGroup)featuredHashtagItemBinding.getRoot().getParent()).removeView(featuredHashtagItemBinding.getRoot());
                            if (binding.featuredHashtagsContainer.getChildCount() >= MAX_FEATURED_HASHTAGS) {
                                binding.addFeaturedHashtags.setVisibility(View.GONE);
                            } else {
                                binding.addFeaturedHashtags.setVisibility(View.VISIBLE);
                            }
                            dialog.dismiss();
                        });
                        deleteConfirm.create().show();
                    });
                    binding.featuredHashtagsContainer.addView(featuredHashtagItemBinding.getRoot());
                }
            }
            binding.addFeaturedHashtags.setOnClickListener(view -> {
                AccountFeaturedHashtagItemBinding featuredHashtagItemBinding = AccountFeaturedHashtagItemBinding.inflate(getLayoutInflater());
                featuredHashtagItemBinding.remove.setOnClickListener(v -> {
                    AlertDialog.Builder deleteConfirm = new MaterialAlertDialogBuilder(EditProfileActivity.this);
                    deleteConfirm.setTitle(getString(R.string.delete_featured_hashtag));
                    deleteConfirm.setMessage(getString(R.string.delete_featured_hashtag_confirm));
                    deleteConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
                    deleteConfirm.setPositiveButton(R.string.delete, (dialog, which) -> {
                        ((ViewGroup)featuredHashtagItemBinding.getRoot().getParent()).removeView(featuredHashtagItemBinding.getRoot());
                        if (binding.featuredHashtagsContainer.getChildCount() >= MAX_FEATURED_HASHTAGS) {
                            binding.addFeaturedHashtags.setVisibility(View.GONE);
                        } else {
                            binding.addFeaturedHashtags.setVisibility(View.VISIBLE);
                        }
                        dialog.dismiss();
                    });
                    deleteConfirm.create().show();
                });
                binding.featuredHashtagsContainer.addView(featuredHashtagItemBinding.getRoot());

                if (binding.featuredHashtagsContainer.getChildCount() >= MAX_FEATURED_HASHTAGS) {
                    binding.addFeaturedHashtags.setVisibility(View.GONE);
                } else {
                    binding.addFeaturedHashtags.setVisibility(View.VISIBLE);
                }
            });
        });
        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) {
@@ -135,7 +205,7 @@ public class EditProfileActivity extends BaseBarActivity {
            binding.unlocked.setChecked(true);
        }
        List<Field> fields = Helper.getCurrentAccount(EditProfileActivity.this).mastodon_account.fields;
        if (fields != null && fields.size() > 0) {
        if (fields != null && !fields.isEmpty()) {
            for (Field field : fields) {
                AccountFieldItemBinding fieldItemBinding = AccountFieldItemBinding.inflate(getLayoutInflater());
                fieldItemBinding.name.setText(field.name);
@@ -151,11 +221,11 @@ public class EditProfileActivity extends BaseBarActivity {
                    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);
                        ((ViewGroup)fieldItemBinding.getRoot().getParent()).removeView(fieldItemBinding.getRoot());
                        if (binding.fieldsContainer.getChildCount() >= MAX_FIELDS) {
                            binding.addField.setVisibility(View.GONE);
                        } else {
                            binding.fieldsContainer.setVisibility(View.GONE);
                            binding.addField.setVisibility(View.VISIBLE);
                        }
                        dialog.dismiss();
                    });
@@ -163,7 +233,11 @@ public class EditProfileActivity extends BaseBarActivity {
                });
                binding.fieldsContainer.addView(fieldItemBinding.getRoot());
            }

            if (binding.fieldsContainer.getChildCount() >= MAX_FIELDS) {
                binding.addField.setVisibility(View.GONE);
            } else {
                binding.addField.setVisibility(View.VISIBLE);
            }
        }
        binding.addField.setOnClickListener(view -> {
            AccountFieldItemBinding fieldItemBinding = AccountFieldItemBinding.inflate(getLayoutInflater());
@@ -173,25 +247,24 @@ public class EditProfileActivity extends BaseBarActivity {
                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);
                    ((ViewGroup)fieldItemBinding.getRoot().getParent()).removeView(fieldItemBinding.getRoot());
                    if (binding.fieldsContainer.getChildCount() >= MAX_FIELDS) {
                        binding.addField.setVisibility(View.GONE);
                    } else {
                        binding.fieldsContainer.setVisibility(View.GONE);
                        binding.addField.setVisibility(View.VISIBLE);
                    }
                    dialog.dismiss();
                });
                deleteConfirm.create().show();
            });
            binding.fieldsContainer.addView(fieldItemBinding.getRoot());
            if (binding.fieldsContainer.getChildCount() >= 4) {

            if (binding.fieldsContainer.getChildCount() >= MAX_FIELDS) {
                binding.addField.setVisibility(View.GONE);
            } else {
                binding.addField.setVisibility(View.VISIBLE);
            }
        });


        //Actions with the activity
        accountsVM = new ViewModelProvider(EditProfileActivity.this).get(AccountsVM.class);
        binding.headerSelect.setOnClickListener(view -> startActivityForResult(prepareIntent(), EditProfileActivity.PICK_MEDIA_HEADER));

        binding.avatarSelect.setOnClickListener(view -> startActivityForResult(prepareIntent(), EditProfileActivity.PICK_MEDIA_AVATAR));
@@ -280,7 +353,7 @@ public class EditProfileActivity extends BaseBarActivity {
        intent.setType("*/*");
        String[] mimetypes;
        long max_size = -1;
        if (instanceInfo.getMimeTypeImage().size() > 0) {
        if (!instanceInfo.getMimeTypeImage().isEmpty()) {
            mimetypes = instanceInfo.getMimeTypeImage().toArray(new String[0]);
            max_size = instanceInfo.configuration.media_attachments.image_size_limit;
        } else {
+63 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
    Copyright 2025 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>
-->
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:layout_marginTop="6dp"
    app:cardElevation="0dp"
    app:strokeWidth="0dp">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            tools:text="@tools:sample/first_names" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/remove"
            style="@style/Widget.Material3.Button.OutlinedButton.Icon"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:contentDescription="@string/delete_field"
            android:insetTop="0dp"
            android:insetBottom="0dp"
            android:padding="0dp"
            android:textColor="?colorError"
            app:icon="@drawable/ic_compose_attachment_remove"
            app:iconGravity="textStart"
            app:iconPadding="0dp"
            app:iconTint="?colorError"
            app:layout_constraintStart_toStartOf="@id/banner_pp"
            app:layout_constraintTop_toTopOf="@id/banner_pp"
            app:strokeColor="?colorError" />

    </androidx.appcompat.widget.LinearLayoutCompat>

</com.google.android.material.card.MaterialCardView>
+66 −2
Original line number Diff line number Diff line
@@ -161,6 +161,16 @@
                app:layout_constraintTop_toBottomOf="@id/acct"
                tools:text="@tools:sample/lorem/random" />


            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/fields_label"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="12dp"
                android:layout_marginTop="12dp"
                android:text="@string/fields_title"
                android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
                app:layout_constraintTop_toBottomOf="@id/bio" />
            <androidx.appcompat.widget.LinearLayoutCompat
                android:id="@+id/fields"
                android:layout_width="match_parent"
@@ -168,7 +178,7 @@
                android:layout_marginHorizontal="12dp"
                android:layout_marginTop="12dp"
                android:orientation="vertical"
                app:layout_constraintTop_toBottomOf="@id/bio">
                app:layout_constraintTop_toBottomOf="@id/fields_label">

                <androidx.appcompat.widget.LinearLayoutCompat
                    android:id="@+id/fields_container"
@@ -188,6 +198,60 @@

            </androidx.appcompat.widget.LinearLayoutCompat>

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/featured_hashtags_label"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="12dp"
                android:layout_marginTop="12dp"
                android:text="@string/featured_hashtags_title"
                android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
                app:layout_constraintTop_toBottomOf="@id/fields" />


            <androidx.appcompat.widget.LinearLayoutCompat
                android:id="@+id/featured_hashtags"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="12dp"
                android:layout_marginTop="12dp"
                android:orientation="vertical"
                app:layout_constraintTop_toBottomOf="@id/featured_hashtags_label">

                <androidx.appcompat.widget.LinearLayoutCompat
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">
                    <com.google.android.material.textview.MaterialTextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/Suggestions"/>
                    <com.google.android.material.textview.MaterialTextView
                        android:id="@+id/featured_hashtags_suggestions"
                        android:layout_marginStart="10dp"
                        android:layout_width="0dp"
                        android:layout_weight="1"
                        android:layout_height="wrap_content"
                        android:text="@string/Suggestions"/>
                </androidx.appcompat.widget.LinearLayoutCompat>
                <androidx.appcompat.widget.LinearLayoutCompat
                    android:layout_marginTop="5dp"
                    android:id="@+id/featured_hashtags_container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical" />
                <com.google.android.material.button.MaterialButton
                    android:id="@+id/add_featured_hashtags"
                    style="@style/Widget.Material3.Button.OutlinedButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="end"
                    android:layout_marginVertical="6dp"
                    android:text="@string/add_featured_hashtag"
                    app:icon="@drawable/ic_baseline_add_24" />

            </androidx.appcompat.widget.LinearLayoutCompat>

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/visibility_label"
                android:layout_width="match_parent"
@@ -196,7 +260,7 @@
                android:layout_marginTop="12dp"
                android:text="@string/toots_visibility_title"
                android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
                app:layout_constraintTop_toBottomOf="@id/fields" />
                app:layout_constraintTop_toBottomOf="@id/featured_hashtags" />

            <com.google.android.material.button.MaterialButtonToggleGroup
                android:id="@+id/visibility_group"
+6 −0
Original line number Diff line number Diff line
@@ -732,13 +732,19 @@
    <string name="interactions">Interactions</string>
    <string name="add_filter">Add filter</string>
    <string name="add_field">Add Field</string>
    <string name="add_featured_hashtag">Add Featured Hashtag</string>
    <string name="no_feature_hashtag_suggestion">No suggestions for featured hashtags!</string>
    <string name="unlocked">Unlocked</string>
    <string name="locked">Locked</string>
    <string name="save_changes">Save changes</string>
    <string name="set_bot_content">Bot account</string>
    <string name="fields_title">Add or remove fields</string>
    <string name="featured_hashtags_title">Add or remove featured hashtags</string>
    <string name="set_discoverable_content">Account discoverable</string>
    <string name="delete_field">Delete field</string>
    <string name="delete_featured_hashtag">Delete featured hashtag</string>
    <string name="delete_field_confirm">Are you sure you want to delete that field?</string>
    <string name="delete_featured_hashtag_confirm">Are you sure you want to delete that featured hashtag?</string>
    <string name="profiled_updated">Profile has been updated!</string>
    <string name="not_valid_list_name">List name is not valid!</string>
    <string name="no_account_in_list">No accounts found for this list!</string>