зеркало из https://github.com/nextcloud/android.git
Коммит
d544e18960
Двоичные данные
screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testProfileBottomSheet.png
Normal file
Двоичные данные
screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testProfileBottomSheet.png
Normal file
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 13 KiB |
|
@ -31,6 +31,8 @@ import android.view.ViewGroup;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.nextcloud.android.lib.resources.profile.Action;
|
||||
import com.nextcloud.android.lib.resources.profile.HoverCard;
|
||||
import com.nextcloud.client.account.RegisteredUser;
|
||||
import com.nextcloud.client.account.Server;
|
||||
import com.nextcloud.client.device.DeviceInfo;
|
||||
|
@ -54,6 +56,7 @@ import com.owncloud.android.lib.resources.users.StatusType;
|
|||
import com.owncloud.android.ui.activity.FileDisplayActivity;
|
||||
import com.owncloud.android.ui.fragment.OCFileListBottomSheetActions;
|
||||
import com.owncloud.android.ui.fragment.OCFileListBottomSheetDialog;
|
||||
import com.owncloud.android.ui.fragment.ProfileBottomSheetDialog;
|
||||
import com.owncloud.android.utils.MimeTypeUtil;
|
||||
import com.owncloud.android.utils.ScreenshotTest;
|
||||
|
||||
|
@ -64,6 +67,7 @@ import org.junit.Test;
|
|||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
@ -378,6 +382,47 @@ public class DialogFragmentIT extends AbstractIT {
|
|||
screenshot(sut.getWindow().getDecorView());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ScreenshotTest
|
||||
public void testProfileBottomSheet() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
|
||||
// Fixed values for HoverCard
|
||||
List<Action> actions = new ArrayList<>();
|
||||
actions.add(new Action("profile",
|
||||
"View profile",
|
||||
"https://dev.nextcloud.com/core/img/actions/profile.svg",
|
||||
"https://dev.nextcloud.com/index.php/u/christine"));
|
||||
actions.add(new Action("core",
|
||||
"christine.scott@nextcloud.com",
|
||||
"https://dev.nextcloud.com/core/img/actions/mail.svg",
|
||||
"mailto:christine.scott@nextcloud.com"));
|
||||
|
||||
actions.add(new Action("spreed",
|
||||
"Talk to Christine",
|
||||
"https://dev.nextcloud.com/apps/spreed/img/app-dark.svg",
|
||||
"https://dev.nextcloud.com/apps/spreed/?callUser=christine"
|
||||
));
|
||||
|
||||
HoverCard hoverCard = new HoverCard("christine", "Christine Scott", actions);
|
||||
|
||||
// show dialog
|
||||
Intent intent = new Intent(targetContext, FileDisplayActivity.class);
|
||||
FileDisplayActivity fda = activityRule.launchActivity(intent);
|
||||
|
||||
ProfileBottomSheetDialog sut = new ProfileBottomSheetDialog(fda,
|
||||
user,
|
||||
hoverCard);
|
||||
|
||||
fda.runOnUiThread(sut::show);
|
||||
|
||||
waitForIdleSync();
|
||||
|
||||
screenshot(sut.getWindow().getDecorView());
|
||||
}
|
||||
|
||||
private FileDisplayActivity showDialog(DialogFragment dialog) {
|
||||
Intent intent = new Intent(targetContext, FileDisplayActivity.class);
|
||||
FileDisplayActivity sut = activityRule.launchActivity(intent);
|
||||
|
|
|
@ -869,6 +869,7 @@ public final class ThumbnailsCacheManager {
|
|||
private final float mAvatarRadius;
|
||||
private User user;
|
||||
private String mUserId;
|
||||
private String displayName;
|
||||
private String mServerName;
|
||||
private Context mContext;
|
||||
|
||||
|
@ -879,6 +880,7 @@ public final class ThumbnailsCacheManager {
|
|||
Resources resources,
|
||||
float avatarRadius,
|
||||
String userId,
|
||||
String displayName,
|
||||
String serverName,
|
||||
Context context) {
|
||||
mAvatarGenerationListener = new WeakReference<>(avatarGenerationListener);
|
||||
|
@ -887,6 +889,7 @@ public final class ThumbnailsCacheManager {
|
|||
mResources = resources;
|
||||
mAvatarRadius = avatarRadius;
|
||||
mUserId = userId;
|
||||
this.displayName = displayName;
|
||||
mServerName = serverName;
|
||||
mContext = context;
|
||||
}
|
||||
|
@ -1023,7 +1026,7 @@ public final class ThumbnailsCacheManager {
|
|||
|
||||
if (avatar == null) {
|
||||
try {
|
||||
return TextDrawable.createAvatar(user, mAvatarRadius);
|
||||
return TextDrawable.createAvatarByUserId(displayName, mAvatarRadius);
|
||||
} catch (Exception e1) {
|
||||
return ResourcesCompat.getDrawable(mResources, R.drawable.ic_user, null);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,9 @@ class ShareViewHolder extends RecyclerView.ViewHolder {
|
|||
super(itemView);
|
||||
}
|
||||
|
||||
public ShareViewHolder(FileDetailsShareShareItemBinding binding, User user, Context context) {
|
||||
public ShareViewHolder(FileDetailsShareShareItemBinding binding,
|
||||
User user,
|
||||
Context context) {
|
||||
this(binding.getRoot());
|
||||
this.binding = binding;
|
||||
this.user = user;
|
||||
|
@ -91,6 +93,8 @@ class ShareViewHolder extends RecyclerView.ViewHolder {
|
|||
context.getResources(),
|
||||
binding.icon,
|
||||
context);
|
||||
|
||||
binding.icon.setOnClickListener(v -> listener.showProfileBottomSheet(user, share.getShareWith()));
|
||||
default:
|
||||
setImage(binding.icon, name, R.drawable.ic_user);
|
||||
break;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package com.owncloud.android.ui.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -39,6 +38,7 @@ import com.owncloud.android.databinding.FileDetailsSharePublicLinkAddNewItemBind
|
|||
import com.owncloud.android.databinding.FileDetailsShareShareItemBinding;
|
||||
import com.owncloud.android.lib.resources.shares.OCShare;
|
||||
import com.owncloud.android.lib.resources.shares.ShareType;
|
||||
import com.owncloud.android.ui.activity.FileActivity;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -55,24 +55,24 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
|||
implements DisplayUtils.AvatarGenerationListener {
|
||||
|
||||
private ShareeListAdapterListener listener;
|
||||
private Context context;
|
||||
private FileActivity fileActivity;
|
||||
private List<OCShare> shares;
|
||||
private float avatarRadiusDimension;
|
||||
private String userId;
|
||||
private User user;
|
||||
|
||||
public ShareeListAdapter(Context context,
|
||||
public ShareeListAdapter(FileActivity fileActivity,
|
||||
List<OCShare> shares,
|
||||
ShareeListAdapterListener listener,
|
||||
String userId,
|
||||
User user) {
|
||||
this.context = context;
|
||||
this.fileActivity = fileActivity;
|
||||
this.shares = shares;
|
||||
this.listener = listener;
|
||||
this.userId = userId;
|
||||
this.user = user;
|
||||
|
||||
avatarRadiusDimension = context.getResources().getDimension(R.dimen.user_icon_radius);
|
||||
avatarRadiusDimension = fileActivity.getResources().getDimension(R.dimen.user_icon_radius);
|
||||
|
||||
sortShares();
|
||||
}
|
||||
|
@ -89,26 +89,26 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
|||
case PUBLIC_LINK:
|
||||
case EMAIL:
|
||||
return new LinkShareViewHolder(
|
||||
FileDetailsShareLinkShareItemBinding.inflate(LayoutInflater.from(context),
|
||||
FileDetailsShareLinkShareItemBinding.inflate(LayoutInflater.from(fileActivity),
|
||||
parent,
|
||||
false),
|
||||
context);
|
||||
fileActivity);
|
||||
case NEW_PUBLIC_LINK:
|
||||
return new NewLinkShareViewHolder(
|
||||
FileDetailsSharePublicLinkAddNewItemBinding.inflate(LayoutInflater.from(context),
|
||||
FileDetailsSharePublicLinkAddNewItemBinding.inflate(LayoutInflater.from(fileActivity),
|
||||
parent,
|
||||
false)
|
||||
);
|
||||
case INTERNAL:
|
||||
return new InternalShareViewHolder(
|
||||
FileDetailsShareInternalShareLinkBinding.inflate(LayoutInflater.from(context), parent, false),
|
||||
context);
|
||||
FileDetailsShareInternalShareLinkBinding.inflate(LayoutInflater.from(fileActivity), parent, false),
|
||||
fileActivity);
|
||||
default:
|
||||
return new ShareViewHolder(FileDetailsShareShareItemBinding.inflate(LayoutInflater.from(context),
|
||||
return new ShareViewHolder(FileDetailsShareShareItemBinding.inflate(LayoutInflater.from(fileActivity),
|
||||
parent,
|
||||
false),
|
||||
user,
|
||||
context);
|
||||
fileActivity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ package com.owncloud.android.ui.adapter;
|
|||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.owncloud.android.lib.resources.shares.OCShare;
|
||||
|
||||
public interface ShareeListAdapterListener {
|
||||
|
@ -38,4 +39,6 @@ public interface ShareeListAdapterListener {
|
|||
void createPublicShareLink();
|
||||
|
||||
void requestPasswordForShare(OCShare share, boolean askForPassword);
|
||||
|
||||
void showProfileBottomSheet(User user, String shareWith);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2021 Tobias Kaminsky
|
||||
* Copyright (C) 2021 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.ui.asynctasks;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.nextcloud.android.lib.resources.profile.GetHoverCardRemoteOperation;
|
||||
import com.nextcloud.android.lib.resources.profile.HoverCard;
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.nextcloud.common.NextcloudClient;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.ui.fragment.ProfileBottomSheetDialog;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
public class RetrieveHoverCardAsyncTask extends AsyncTask<Void, Void, HoverCard> {
|
||||
private final User user;
|
||||
private final String userId;
|
||||
private final WeakReference<FragmentActivity> activityWeakReference;
|
||||
private final ClientFactory clientFactory;
|
||||
|
||||
public RetrieveHoverCardAsyncTask(User user,
|
||||
String userId,
|
||||
FragmentActivity activity,
|
||||
ClientFactory clientFactory) {
|
||||
this.user = user;
|
||||
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, hoverCard).show();
|
||||
} else {
|
||||
DisplayUtils.showSnackMessage(activity, R.string.no_actions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@ import android.widget.ImageView;
|
|||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.account.UserAccountManager;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.nextcloud.client.network.ClientFactory;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.databinding.FileDetailsSharingFragmentBinding;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
|
@ -50,12 +51,14 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|||
import com.owncloud.android.lib.resources.shares.OCShare;
|
||||
import com.owncloud.android.lib.resources.shares.SharePermissionsBuilder;
|
||||
import com.owncloud.android.lib.resources.shares.ShareType;
|
||||
import com.owncloud.android.lib.resources.status.NextcloudVersion;
|
||||
import com.owncloud.android.lib.resources.status.OCCapability;
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||
import com.owncloud.android.ui.activity.FileActivity;
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity;
|
||||
import com.owncloud.android.ui.adapter.ShareeListAdapter;
|
||||
import com.owncloud.android.ui.adapter.ShareeListAdapterListener;
|
||||
import com.owncloud.android.ui.asynctasks.RetrieveHoverCardAsyncTask;
|
||||
import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.NoteDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.RenamePublicShareDialogFragment;
|
||||
|
@ -110,6 +113,8 @@ public class FileDetailSharingFragment extends Fragment implements ShareeListAda
|
|||
|
||||
@Inject UserAccountManager accountManager;
|
||||
|
||||
@Inject ClientFactory clientFactory;
|
||||
|
||||
public static FileDetailSharingFragment newInstance(OCFile file, User user) {
|
||||
FileDetailSharingFragment fragment = new FileDetailSharingFragment();
|
||||
Bundle args = new Bundle();
|
||||
|
@ -607,6 +612,13 @@ public class FileDetailSharingFragment extends Fragment implements ShareeListAda
|
|||
dialog.show(getChildFragmentManager(), SharePasswordDialogFragment.PASSWORD_FRAGMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showProfileBottomSheet(User user, String shareWith) {
|
||||
if (user.getServer().getVersion().isNewerOrEqual(NextcloudVersion.Companion.getNextcloud_23())) {
|
||||
new RetrieveHoverCardAsyncTask(user, shareWith, fileActivity, clientFactory).execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get known server capabilities from DB
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2021 Tobias Kaminsky
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.owncloud.android.ui.fragment
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
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 com.nextcloud.client.account.User
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.databinding.ProfileBottomSheetActionBinding
|
||||
import com.owncloud.android.databinding.ProfileBottomSheetFragmentBinding
|
||||
import com.owncloud.android.utils.DisplayUtils
|
||||
import com.owncloud.android.utils.theme.ThemeColorUtils
|
||||
import com.owncloud.android.utils.theme.ThemeDrawableUtils
|
||||
|
||||
/**
|
||||
* Show actions of an user
|
||||
*/
|
||||
class ProfileBottomSheetDialog(
|
||||
private val fileActivity: FragmentActivity,
|
||||
private val user: User,
|
||||
private val hoverCard: HoverCard
|
||||
) : BottomSheetDialog(fileActivity), DisplayUtils.AvatarGenerationListener {
|
||||
private var _binding: ProfileBottomSheetFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and onDestroyView.
|
||||
private 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)
|
||||
}
|
||||
val primaryColor = ThemeColorUtils.primaryColor(context, true)
|
||||
|
||||
binding.icon.tag = hoverCard.userId
|
||||
DisplayUtils.setAvatar(
|
||||
user,
|
||||
hoverCard.userId,
|
||||
hoverCard.displayName,
|
||||
this,
|
||||
context.resources.getDimension(R.dimen.list_item_avatar_icon_radius),
|
||||
context.resources,
|
||||
binding.icon,
|
||||
context
|
||||
)
|
||||
|
||||
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_user
|
||||
"email" -> R.drawable.ic_email
|
||||
"spreed" -> R.drawable.ic_talk
|
||||
else -> R.drawable.ic_edit
|
||||
}
|
||||
actionBinding.icon.setImageDrawable(
|
||||
ResourcesCompat.getDrawable(
|
||||
context.resources,
|
||||
icon,
|
||||
null
|
||||
)
|
||||
)
|
||||
ThemeDrawableUtils.tintDrawable(actionBinding.icon.drawable, primaryColor)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
override fun avatarGenerated(avatarDrawable: Drawable?, callContext: Any?) {
|
||||
if (callContext is ImageView) {
|
||||
callContext.setImageDrawable(avatarDrawable)
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldCallGeneratedCallback(tag: String?, callContext: Any?): Boolean {
|
||||
if (callContext is ImageView) {
|
||||
// needs to be changed once federated users have avatars
|
||||
return callContext.tag.toString() == tag!!.split("@").toTypedArray()[0]
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -527,6 +527,7 @@ public final class DisplayUtils {
|
|||
resources,
|
||||
avatarRadius,
|
||||
userId,
|
||||
displayName,
|
||||
serverName,
|
||||
context);
|
||||
|
||||
|
@ -755,10 +756,18 @@ public final class DisplayUtils {
|
|||
}
|
||||
|
||||
static public void startLinkIntent(Activity activity, @StringRes int link) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(activity.getString(link)));
|
||||
startLinkIntent(activity, activity.getString(link));
|
||||
}
|
||||
|
||||
static public void startLinkIntent(Activity activity, Uri url) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, url);
|
||||
DisplayUtils.startIntentIfAppAvailable(intent, activity, R.string.no_browser_available);
|
||||
}
|
||||
|
||||
static public void startLinkIntent(Activity activity, String url) {
|
||||
startLinkIntent(activity, Uri.parse(url));
|
||||
}
|
||||
|
||||
static public void startIntentIfAppAvailable(Intent intent, Activity activity, @StringRes int error) {
|
||||
if (intent.resolveActivity(activity.getPackageManager()) != null) {
|
||||
activity.startActivity(intent);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!--
|
||||
Nextcloud Android client application
|
||||
|
||||
Copyright (C) 2020 Nextcloud GmbH
|
||||
Copyright (C) 2021 Nextcloud GmbH
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
|
@ -17,13 +17,14 @@
|
|||
You should have received a copy of the GNU Affero General Public
|
||||
License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="128"
|
||||
android:viewportHeight="128">
|
||||
<vector android:autoMirrored="true"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="16"
|
||||
android:viewportWidth="16"
|
||||
android:width="16dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path
|
||||
android:fillColor="#757575"
|
||||
android:pathData="M63.992,0.689C29.031,0.689 0.691,29.031 0.692,63.992c0,34.96 28.34,63.301 63.3,63.302 6.982,-0.014 13.881,-1.183 20.426,-3.43 4.317,-1.482 8.48,-3.433 12.411,-5.831 3.383,1.344 8.59,3.838 13.736,5.902 6.688,2.683 13.274,4.639 15.618,2.399 2.317,-2.212 0.703,-8.809 -1.647,-15.575 -2.046,-5.892 -4.649,-11.913 -5.701,-15.282 2.544,-4.415 4.535,-9.101 5.945,-13.954 1.648,-5.674 2.5,-11.574 2.512,-17.532C127.291,29.032 98.952,0.692 63.992,0.691ZM63.999,24.756l0.001,0c21.677,0 39.25,17.573 39.25,39.251 -0.001,21.677 -17.574,39.249 -39.251,39.249 -21.676,0 -39.249,-17.572 -39.25,-39.249 0,-21.678 17.573,-39.251 39.25,-39.251z"
|
||||
android:strokeWidth="4.78543139" />
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="m7.9992,0.999a6.9993,6.9994 0,0 0,-6.9992 6.9996,6.9993 6.9994,0 0,0 6.9992,6.9994 6.9993,6.9994 0,0 0,3.6308 -1.024c0.8602,0.3418 2.7871,1.356 3.2457,0.9179 0.4792,-0.4577 -0.5626,-2.6116 -0.8124,-3.412a6.9993,6.9994 0,0 0,0.935 -3.4814,6.9993 6.9994,0 0,0 -6.9991,-6.9993zM8,3.6601a4.34,4.3401 0,0 1,4.34 4.3401,4.34 4.3401,0 0,1 -4.34,4.3398 4.34,4.3401 0,0 1,-4.34 -4.3398,4.34 4.3401,0 0,1 4.34,-4.3401z"
|
||||
android:strokeWidth=".14" />
|
||||
</vector>
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/bg_default">
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/add_to_cloud"
|
||||
|
@ -31,7 +30,7 @@
|
|||
android:padding="@dimen/standard_padding"
|
||||
android:text="@string/add_to_cloud"
|
||||
android:textSize="@dimen/bottom_sheet_text_size"
|
||||
android:textColor="@color/text_color"/>
|
||||
android:textColor="@color/text_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/menu_upload_files"
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~
|
||||
~ Nextcloud Android client application
|
||||
~
|
||||
~ @author Tobias Kaminsky
|
||||
~ Copyright (C) 2019 Tobias Kaminsky
|
||||
~ Copyright (C) 2019 Nextcloud GmbH
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU Affero General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program 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 Affero General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Affero General Public License
|
||||
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingTop="@dimen/standard_half_padding"
|
||||
android:paddingEnd="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_half_padding"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@null"
|
||||
tools:src="@drawable/ic_email" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingEnd="0dp"
|
||||
tools:text="Compose email"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Nextcloud Android client application
|
||||
|
||||
Copyright (C) 2021 Tobias Kaminsky
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or any later version.
|
||||
|
||||
This program 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 AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public
|
||||
License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/user_icon_size"
|
||||
android:layout_height="@dimen/user_icon_size"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginBottom="@dimen/standard_half_margin"
|
||||
android:layout_marginEnd="@dimen/standard_margin"
|
||||
android:layout_marginLeft="@dimen/standard_margin"
|
||||
android:layout_marginRight="@dimen/standard_margin"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginTop="@dimen/standard_half_margin"
|
||||
android:contentDescription="@string/user_icon"
|
||||
android:src="@drawable/ic_user" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/displayName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingTop="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_padding"
|
||||
tools:text="Christine Scott"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/action_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/creators"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"></LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -781,6 +781,7 @@
|
|||
<string name="hint_note">Note</string>
|
||||
<string name="no_browser_available">No app available to handle links</string>
|
||||
<string name="no_pdf_app_available">No App available to handle PDF</string>
|
||||
<string name="no_email_app_available">No App available to handle mail address</string>
|
||||
<string name="share_via_link_hide_download">Hide download</string>
|
||||
<string name="unread_comments">Unread comments exist</string>
|
||||
<string name="richdocuments_failed_to_load_document">Failed to load document!</string>
|
||||
|
@ -962,4 +963,6 @@
|
|||
<string name="strict_mode">Strict mode: no HTTP connection allowed!</string>
|
||||
<string name="fullscreen">Fullscreen</string>
|
||||
<string name="more">More</string>
|
||||
<string name="write_email">Send email</string>
|
||||
<string name="no_actions">No actions for this user</string>
|
||||
</resources>
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.content.res.Resources
|
|||
import com.nextcloud.client.account.AnonymousUser
|
||||
import com.owncloud.android.lib.resources.shares.OCShare
|
||||
import com.owncloud.android.lib.resources.shares.ShareType
|
||||
import com.owncloud.android.ui.activity.FileActivity
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
|
@ -37,11 +38,15 @@ class ShareeListAdapterTest {
|
|||
@Mock
|
||||
private val context: Context? = null
|
||||
|
||||
@Mock
|
||||
private val fileActivity: FileActivity? = null
|
||||
|
||||
@Test
|
||||
fun testSorting() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
val resources = Mockito.mock(Resources::class.java)
|
||||
Mockito.`when`(context!!.resources).thenReturn(resources)
|
||||
Mockito.`when`(fileActivity!!.resources).thenReturn(resources)
|
||||
val expectedSortOrder: MutableList<OCShare?> = ArrayList()
|
||||
expectedSortOrder.add(
|
||||
OCShare("/1").apply {
|
||||
|
@ -83,7 +88,13 @@ class ShareeListAdapterTest {
|
|||
val randomOrder: MutableList<OCShare?> = ArrayList(expectedSortOrder)
|
||||
randomOrder.shuffle()
|
||||
val user = AnonymousUser("nextcloud")
|
||||
val sut = ShareeListAdapter(context, randomOrder, null, null, user)
|
||||
val sut = ShareeListAdapter(
|
||||
fileActivity,
|
||||
randomOrder,
|
||||
null,
|
||||
user.accountName,
|
||||
user
|
||||
)
|
||||
sut.sortShares()
|
||||
|
||||
// compare
|
||||
|
|
Загрузка…
Ссылка в новой задаче