Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 1847eda7 authored by alperozturk's avatar alperozturk
Browse files

add RetrieveHoverCardAsyncTask

parent 479124ea
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -53,7 +53,9 @@ import it.niedermann.owncloud.notes.share.dialog.SharePasswordDialogFragment;
import it.niedermann.owncloud.notes.share.listener.FileDetailsSharingMenuBottomSheetActions;
import it.niedermann.owncloud.notes.share.listener.ShareeListAdapterListener;
import it.niedermann.owncloud.notes.share.model.UsersAndGroupsSearchConfig;
import it.niedermann.owncloud.notes.share.operations.RetrieveHoverCardAsyncTask;
import it.niedermann.owncloud.notes.shared.user.User;
import it.niedermann.owncloud.notes.shared.util.DisplayUtils;
import it.niedermann.owncloud.notes.shared.util.clipboard.ClipboardUtil;
import it.niedermann.owncloud.notes.shared.util.extensions.BundleExtensionsKt;

@@ -449,10 +451,10 @@ public class NoteShareFragment extends Fragment implements ShareeListAdapterList
    public void showProfileBottomSheet(User user, String shareWith) {
        if (user.getServer().getVersion().isNewerOrEqual(NextcloudVersion.nextcloud_23)) {
            new RetrieveHoverCardAsyncTask(user,
                    account,
                    shareWith,
                    fileActivity,
                    clientFactory,
                    viewThemeUtils).execute();
                    getActivity(),
                    clientFactory).execute();
        }
    }

+155 −0
Original line number Diff line number Diff line
package it.niedermann.owncloud.notes.share.dialog


import android.content.ActivityNotFoundException
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.android.lib.resources.profile.Action
import com.nextcloud.android.lib.resources.profile.HoverCard
import it.niedermann.nextcloud.sso.glide.SingleSignOnUrl
import it.niedermann.owncloud.notes.R
import it.niedermann.owncloud.notes.databinding.ProfileBottomSheetActionBinding
import it.niedermann.owncloud.notes.databinding.ProfileBottomSheetFragmentBinding
import it.niedermann.owncloud.notes.persistence.entity.Account
import it.niedermann.owncloud.notes.shared.user.User
import it.niedermann.owncloud.notes.shared.util.DisplayUtils

/**
 * Show actions of an user
 */
class ProfileBottomSheetDialog(
    private val fileActivity: FragmentActivity,
    private val user: User,
    private val account: Account,
    private val hoverCard: HoverCard,
) : BottomSheetDialog(fileActivity) {
    private var _binding: ProfileBottomSheetFragmentBinding? = null

    // This property is only valid between onCreateView and onDestroyView.
    val binding get() = _binding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ProfileBottomSheetFragmentBinding.inflate(layoutInflater)
        setContentView(binding.root)
        if (window != null) {
            window!!.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        }

        // viewThemeUtils.platform.themeDialog(binding.root)

        binding.icon.tag = hoverCard.userId


        /*
            // TODO: How to get owner display name from note?

             binding.sharedWithYouUsername.setText(
                    String.format(getString(R.string.note_share_fragment_shared_with_you), file.getOwnerDisplayName()));
             */
        Glide.with(fileActivity)
            .load(
                SingleSignOnUrl(
                    account.accountName,
                    account.url + "/index.php/avatar/" + Uri.encode(account.userName) + "/64"
                )
            )
            .placeholder(R.drawable.ic_account_circle_grey_24dp)
            .error(R.drawable.ic_account_circle_grey_24dp)
            .apply(RequestOptions.circleCropTransform())
            .into(binding.icon)

        binding.displayName.text = hoverCard.displayName

        for (action in hoverCard.actions) {
            val actionBinding = ProfileBottomSheetActionBinding.inflate(
                layoutInflater
            )
            val creatorView: View = actionBinding.root

            if (action.appId == "email") {
                action.hyperlink = action.title
                action.title = context.resources.getString(R.string.write_email)
            }

            actionBinding.name.text = action.title

            val icon = when (action.appId) {
                "profile" -> R.drawable.ic_account_circle_grey_24dp
                "email" -> R.drawable.ic_email
                "spreed" -> R.drawable.ic_talk
                else -> R.drawable.ic_edit
            }
            actionBinding.icon.setImageDrawable(
                ResourcesCompat.getDrawable(
                    context.resources,
                    icon,
                    null
                )
            )
            // viewThemeUtils.platform.tintPrimaryDrawable(context, actionBinding.icon.drawable)

            creatorView.setOnClickListener { v: View? ->
                send(hoverCard.userId, action)
                dismiss()
            }
            binding.creators.addView(creatorView)
        }

        setOnShowListener { d: DialogInterface? ->
            BottomSheetBehavior.from(binding.root.parent as View)
                .setPeekHeight(binding.root.measuredHeight)
        }
    }

    private fun send(userId: String, action: Action) {
        when (action.appId) {
            "profile" -> openWebsite(action.hyperlink)
            "core" -> sendEmail(action.hyperlink)
            "spreed" -> openTalk(userId, action.hyperlink)
        }
    }

    private fun openWebsite(url: String) {
        DisplayUtils.startLinkIntent(fileActivity, url)
    }

    private fun sendEmail(email: String) {
        val intent = Intent(Intent.ACTION_SENDTO).apply {
            data = Uri.parse("mailto:")
            putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
        }

        DisplayUtils.startIntentIfAppAvailable(intent, fileActivity, R.string.no_email_app_available)
    }

    private fun openTalk(userId: String, hyperlink: String) {
        try {
            val sharingIntent = Intent(Intent.ACTION_VIEW)
            sharingIntent.setClassName(
                "com.nextcloud.talk2",
                "com.nextcloud.talk.activities.MainActivity"
            )
            sharingIntent.putExtra("server", user.server.uri)
            sharingIntent.putExtra("userId", userId)
            fileActivity.startActivity(sharingIntent)
        } catch (e: ActivityNotFoundException) {
            openWebsite(hyperlink)
        }
    }

    override fun onStop() {
        super.onStop()
        _binding = null
    }
}
+58 −0
Original line number Diff line number Diff line
package it.niedermann.owncloud.notes.share.operations;


import android.accounts.Account;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.net.Uri;

import com.nextcloud.common.NextcloudClient;
import com.nextcloud.common.PlainClient;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.accounts.AccountUtils;

import java.io.IOException;

import it.niedermann.owncloud.notes.shared.user.User;

public interface ClientFactory {

    /**
     * This exception wraps all possible errors thrown by trigger-happy OwnCloudClient constructor, making try-catch
     * blocks manageable.
     * <p>
     * This is a temporary refactoring measure, until a better error handling method can be procured.
     */
    @Deprecated
    class CreationException extends Exception {

        private static final long serialVersionUID = 0L;

        CreationException(Throwable t) {
            super(t);
        }
    }

    OwnCloudClient create(User user) throws CreationException;

    NextcloudClient createNextcloudClient(User user) throws CreationException;

    @Deprecated
    OwnCloudClient create(Account account)
            throws OperationCanceledException, AuthenticatorException, IOException,
            AccountUtils.AccountNotFoundException;

    @Deprecated
    OwnCloudClient create(Account account, Activity currentActivity)
            throws OperationCanceledException, AuthenticatorException, IOException,
            AccountUtils.AccountNotFoundException;

    OwnCloudClient create(Uri uri,
                          boolean followRedirects,
                          boolean useNextcloudUserAgent);

    OwnCloudClient create(Uri uri, boolean followRedirects);

    PlainClient createPlainClient();
}
+73 −0
Original line number Diff line number Diff line
package it.niedermann.owncloud.notes.share.operations;


import android.os.AsyncTask;

import com.nextcloud.android.lib.resources.profile.GetHoverCardRemoteOperation;
import com.nextcloud.android.lib.resources.profile.HoverCard;
import com.nextcloud.common.NextcloudClient;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;

import java.lang.ref.WeakReference;

import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;

import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.persistence.entity.Account;
import it.niedermann.owncloud.notes.share.dialog.ProfileBottomSheetDialog;
import it.niedermann.owncloud.notes.shared.user.User;
import it.niedermann.owncloud.notes.shared.util.DisplayUtils;

public class RetrieveHoverCardAsyncTask extends AsyncTask<Void, Void, HoverCard> {
    private final User user;
    private final Account account;
    private final String userId;
    private final WeakReference<FragmentActivity> activityWeakReference;
    private final ClientFactory clientFactory;

    public RetrieveHoverCardAsyncTask(User user,
                                      Account account,
                                      String userId,
                                      FragmentActivity activity,
                                      ClientFactory clientFactory) {
        this.user = user;
        this.account = account;
        this.userId = userId;
        this.activityWeakReference = new WeakReference<>(activity);
        this.clientFactory = clientFactory;
    }

    @Override
    protected HoverCard doInBackground(Void... voids) {
        try {
            NextcloudClient client = clientFactory.createNextcloudClient(user);
            RemoteOperationResult<HoverCard> result = new GetHoverCardRemoteOperation(userId).execute(client);

            if (result.isSuccess()) {
                return result.getResultData();
            } else {
                return null;
            }
        } catch (ClientFactory.CreationException | NullPointerException e) {
            return null;
        }
    }

    @Override
    protected void onPostExecute(HoverCard hoverCard) {
        FragmentActivity activity = this.activityWeakReference.get();

        if (activity != null && activity.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
            if (hoverCard.getActions().size() > 0) {
                new ProfileBottomSheetDialog(activity,
                        user,
                        account,
                        hoverCard)
                        .show();
            } else {
                DisplayUtils.showSnackMessage(activity, R.string.no_actions);
            }
        }
    }
}
+81 −0
Original line number Diff line number Diff line
@@ -10,18 +10,25 @@ import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowInsets;

import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.view.ViewCompat;

import com.google.android.material.snackbar.Snackbar;

import java.util.Collection;
import java.util.List;
import java.util.Locale;
@@ -108,4 +115,78 @@ public class DisplayUtils {
        final int heightDiff = parentView.getRootView().getHeight() - (rect.bottom - rect.top);
        return heightDiff >= estimatedKeyboardHeight;
    }

    static public void startLinkIntent(Activity activity, @StringRes int link) {
        startLinkIntent(activity, activity.getString(link));
    }

    static public void startLinkIntent(Activity activity, String url) {
        if (!TextUtils.isEmpty(url)) {
            startLinkIntent(activity, Uri.parse(url));
        }
    }

    static public void startLinkIntent(Activity activity, Uri uri) {
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
    }

    static public void startIntentIfAppAvailable(Intent intent, Activity activity, @StringRes int error) {
        if (intent.resolveActivity(activity.getPackageManager()) != null) {
            activity.startActivity(intent);
        } else {
            DisplayUtils.showSnackMessage(activity, error);
        }
    }

    /**
     * Show a temporary message in a {@link Snackbar} bound to the content view.
     *
     * @param activity        The {@link Activity} to which's content view the {@link Snackbar} is bound.
     * @param messageResource The resource id of the string resource to use. Can be formatted text.
     * @return The created {@link Snackbar}
     */
    public static Snackbar showSnackMessage(Activity activity, @StringRes int messageResource) {
        return showSnackMessage(activity.findViewById(android.R.id.content), messageResource);
    }

    /**
     * Show a temporary message in a {@link Snackbar} bound to the content view.
     *
     * @param activity The {@link Activity} to which's content view the {@link Snackbar} is bound.
     * @param message  Message to show.
     * @return The created {@link Snackbar}
     */
    public static Snackbar showSnackMessage(Activity activity, String message) {
        final Snackbar snackbar = Snackbar.make(activity.findViewById(android.R.id.content), message, Snackbar.LENGTH_LONG);
        snackbar.show();
        return snackbar;
    }

    /**
     * Show a temporary message in a {@link Snackbar} bound to the given view.
     *
     * @param view            The view the {@link Snackbar} is bound to.
     * @param messageResource The resource id of the string resource to use. Can be formatted text.
     * @return The created {@link Snackbar}
     */
    public static Snackbar showSnackMessage(View view, @StringRes int messageResource) {
        final Snackbar snackbar = Snackbar.make(view, messageResource, Snackbar.LENGTH_LONG);
        snackbar.show();
        return snackbar;
    }

    /**
     * Show a temporary message in a {@link Snackbar} bound to the given view.
     *
     * @param view    The view the {@link Snackbar} is bound to.
     * @param message The message.
     * @return The created {@link Snackbar}
     */
    public static Snackbar showSnackMessage(View view, String message) {
        final Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
        snackbar.show();
        return snackbar;
    }

}
Loading