FileDetailSharingFragment.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * Nextcloud Android client application
  3. *
  4. * @author Andy Scherzinger
  5. * @author Chris Narkiewicz <hello@ezaquarii.com>
  6. *
  7. * Copyright (C) 2018 Andy Scherzinger
  8. * Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  12. * License as published by the Free Software Foundation; either
  13. * version 3 of the License, or any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public
  21. * License along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. package com.owncloud.android.ui.fragment;
  24. import android.accounts.AccountManager;
  25. import android.app.SearchManager;
  26. import android.content.Context;
  27. import android.content.res.Resources;
  28. import android.graphics.PorterDuff;
  29. import android.graphics.drawable.Drawable;
  30. import android.os.Bundle;
  31. import android.text.InputType;
  32. import android.text.TextUtils;
  33. import android.view.LayoutInflater;
  34. import android.view.Menu;
  35. import android.view.MenuItem;
  36. import android.view.View;
  37. import android.view.ViewGroup;
  38. import android.widget.ImageView;
  39. import android.widget.LinearLayout;
  40. import android.widget.TextView;
  41. import com.nextcloud.client.account.User;
  42. import com.nextcloud.client.account.UserAccountManager;
  43. import com.nextcloud.client.di.Injectable;
  44. import com.owncloud.android.R;
  45. import com.owncloud.android.datamodel.FileDataStorageManager;
  46. import com.owncloud.android.datamodel.OCFile;
  47. import com.owncloud.android.lib.common.OwnCloudAccount;
  48. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  49. import com.owncloud.android.lib.resources.shares.OCShare;
  50. import com.owncloud.android.lib.resources.shares.SharePermissionsBuilder;
  51. import com.owncloud.android.lib.resources.shares.ShareType;
  52. import com.owncloud.android.lib.resources.status.OCCapability;
  53. import com.owncloud.android.ui.activity.FileActivity;
  54. import com.owncloud.android.ui.activity.FileDisplayActivity;
  55. import com.owncloud.android.ui.adapter.PublicShareInterface;
  56. import com.owncloud.android.ui.adapter.PublicShareListAdapter;
  57. import com.owncloud.android.ui.adapter.ShareeListAdapter;
  58. import com.owncloud.android.ui.decoration.SimpleListItemDividerDecoration;
  59. import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
  60. import com.owncloud.android.ui.dialog.NoteDialogFragment;
  61. import com.owncloud.android.ui.dialog.RenamePublicShareDialogFragment;
  62. import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
  63. import com.owncloud.android.ui.fragment.util.FileDetailSharingFragmentHelper;
  64. import com.owncloud.android.ui.fragment.util.SharingMenuHelper;
  65. import com.owncloud.android.ui.helpers.FileOperationsHelper;
  66. import com.owncloud.android.utils.ClipboardUtil;
  67. import com.owncloud.android.utils.DisplayUtils;
  68. import com.owncloud.android.utils.ThemeUtils;
  69. import java.util.List;
  70. import javax.inject.Inject;
  71. import androidx.annotation.NonNull;
  72. import androidx.annotation.Nullable;
  73. import androidx.appcompat.widget.PopupMenu;
  74. import androidx.appcompat.widget.SearchView;
  75. import androidx.fragment.app.Fragment;
  76. import androidx.recyclerview.widget.LinearLayoutManager;
  77. import androidx.recyclerview.widget.RecyclerView;
  78. import butterknife.BindView;
  79. import butterknife.ButterKnife;
  80. import butterknife.OnClick;
  81. import butterknife.Unbinder;
  82. public class FileDetailSharingFragment extends Fragment implements ShareeListAdapter.ShareeListAdapterListener,
  83. DisplayUtils.AvatarGenerationListener,
  84. PublicShareInterface,
  85. Injectable {
  86. private static final String ARG_FILE = "FILE";
  87. private static final String ARG_USER = "USER";
  88. public static final int PERMISSION_EDITING_ALLOWED = 17;
  89. private OCFile file;
  90. private User user;
  91. private OCCapability capabilities;
  92. private FileOperationsHelper fileOperationsHelper;
  93. private FileActivity fileActivity;
  94. private FileDataStorageManager fileDataStorageManager;
  95. private Unbinder unbinder;
  96. @BindView(R.id.searchView)
  97. SearchView searchView;
  98. @BindView(R.id.shareUsersList)
  99. RecyclerView usersList;
  100. @BindView(R.id.publicShareList)
  101. RecyclerView publicShareList;
  102. @BindView(R.id.new_public_share)
  103. View addPublicShare;
  104. @BindView(R.id.shared_with_you_container)
  105. LinearLayout sharedWithYouContainer;
  106. @BindView(R.id.shared_with_you_avatar)
  107. ImageView sharedWithYouAvatar;
  108. @BindView(R.id.shared_with_you_username)
  109. TextView sharedWithYouUsername;
  110. @BindView(R.id.shared_with_you_note_container)
  111. View sharedWithYouNoteContainer;
  112. @BindView(R.id.shared_with_you_note)
  113. TextView sharedWithYouNote;
  114. @BindView(R.id.copy_internal_link_icon)
  115. ImageView internalLinkIcon;
  116. @BindView(R.id.shareInternalLinkText)
  117. TextView internalLinkText;
  118. @Inject UserAccountManager accountManager;
  119. public static FileDetailSharingFragment newInstance(OCFile file, User user) {
  120. FileDetailSharingFragment fragment = new FileDetailSharingFragment();
  121. Bundle args = new Bundle();
  122. args.putParcelable(ARG_FILE, file);
  123. args.putParcelable(ARG_USER, user);
  124. fragment.setArguments(args);
  125. return fragment;
  126. }
  127. @Override
  128. public void onCreate(@Nullable Bundle savedInstanceState) {
  129. super.onCreate(savedInstanceState);
  130. if (savedInstanceState != null) {
  131. file = savedInstanceState.getParcelable(ARG_FILE);
  132. user = savedInstanceState.getParcelable(ARG_USER);
  133. } else {
  134. Bundle arguments = getArguments();
  135. if (arguments != null) {
  136. file = getArguments().getParcelable(ARG_FILE);
  137. user = getArguments().getParcelable(ARG_USER);
  138. }
  139. }
  140. if (file == null) {
  141. throw new IllegalArgumentException("File may not be null");
  142. }
  143. if (user == null) {
  144. throw new IllegalArgumentException("Account may not be null");
  145. }
  146. fileActivity = (FileActivity) getActivity();
  147. if (fileActivity == null) {
  148. throw new IllegalArgumentException("FileActivity may not be null");
  149. }
  150. }
  151. @Override
  152. public void onActivityCreated(Bundle savedInstanceState) {
  153. super.onActivityCreated(savedInstanceState);
  154. refreshCapabilitiesFromDB();
  155. refreshPublicShareFromDB();
  156. }
  157. @Override
  158. public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  159. View view = inflater.inflate(R.layout.file_details_sharing_fragment, container, false);
  160. unbinder = ButterKnife.bind(this, view);
  161. fileOperationsHelper = fileActivity.getFileOperationsHelper();
  162. fileDataStorageManager = fileActivity.getStorageManager();
  163. setupView();
  164. // todo extract
  165. internalLinkIcon.getBackground().setColorFilter(getResources().getColor(R.color.grey_db),
  166. PorterDuff.Mode.SRC_IN);
  167. internalLinkIcon.getDrawable().mutate().setColorFilter(getResources().getColor(R.color.black),
  168. PorterDuff.Mode.SRC_IN);
  169. if (file.isFolder()) {
  170. internalLinkText.setText(getString(R.string.share_internal_link_to_folder_text));
  171. } else {
  172. internalLinkText.setText(getString(R.string.share_internal_link_to_file_text));
  173. }
  174. return view;
  175. }
  176. @Override
  177. public void onDestroy() {
  178. super.onDestroy();
  179. unbinder.unbind();
  180. }
  181. @Override
  182. public void onAttach(@NonNull Context context) {
  183. super.onAttach(context);
  184. if (!(getActivity() instanceof FileActivity)) {
  185. throw new IllegalArgumentException("Calling activity must be of type FileActivity");
  186. }
  187. }
  188. private void setupView() {
  189. setShareWithYou();
  190. FileDetailSharingFragmentHelper.setupSearchView(
  191. (SearchManager) fileActivity.getSystemService(Context.SEARCH_SERVICE), searchView,
  192. fileActivity.getComponentName());
  193. ThemeUtils.themeSearchView(searchView, requireContext());
  194. if (file.canReshare()) {
  195. setShareWithUserInfo();
  196. } else {
  197. searchView.setQueryHint(getResources().getString(R.string.reshare_not_allowed));
  198. searchView.setInputType(InputType.TYPE_NULL);
  199. disableSearchView(searchView);
  200. }
  201. }
  202. private void disableSearchView(View view) {
  203. view.setEnabled(false);
  204. if (view instanceof ViewGroup) {
  205. ViewGroup viewGroup = (ViewGroup) view;
  206. for (int i = 0; i < viewGroup.getChildCount(); i++) {
  207. disableSearchView(viewGroup.getChildAt(i));
  208. }
  209. }
  210. }
  211. private void setShareWithYou() {
  212. if (accountManager.userOwnsFile(file, user)) {
  213. sharedWithYouContainer.setVisibility(View.GONE);
  214. } else {
  215. sharedWithYouUsername.setText(
  216. String.format(getString(R.string.shared_with_you_by), file.getOwnerDisplayName()));
  217. DisplayUtils.setAvatar(user, file.getOwnerId(), this, getResources().getDimension(
  218. R.dimen.file_list_item_avatar_icon_radius), getResources(), sharedWithYouAvatar,
  219. getContext());
  220. sharedWithYouAvatar.setVisibility(View.VISIBLE);
  221. String note = file.getNote();
  222. if (!TextUtils.isEmpty(note)) {
  223. sharedWithYouNote.setText(file.getNote());
  224. sharedWithYouNoteContainer.setVisibility(View.VISIBLE);
  225. } else {
  226. sharedWithYouNoteContainer.setVisibility(View.GONE);
  227. }
  228. }
  229. }
  230. private void setShareWithUserInfo() {
  231. // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
  232. // to show share with users/groups info
  233. List<OCShare> shares = fileDataStorageManager.getSharesWithForAFile(file.getRemotePath(),
  234. user.toPlatformAccount().name);
  235. if (shares.size() > 0) {
  236. AccountManager accountManager = AccountManager.get(getContext());
  237. String userId = accountManager.getUserData(user.toPlatformAccount(),
  238. com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
  239. usersList.setVisibility(View.VISIBLE);
  240. usersList.setAdapter(new ShareeListAdapter(fileActivity.getSupportFragmentManager(),
  241. fileActivity,
  242. shares,
  243. user.toPlatformAccount(),
  244. file,
  245. this,
  246. userId));
  247. usersList.setLayoutManager(new LinearLayoutManager(getContext()));
  248. usersList.addItemDecoration(new SimpleListItemDividerDecoration(getContext()));
  249. } else {
  250. usersList.setVisibility(View.GONE);
  251. }
  252. }
  253. @OnClick(R.id.copy_internal_container)
  254. public void copyInternalLink() {
  255. OwnCloudAccount account = accountManager.getCurrentOwnCloudAccount();
  256. if (account == null) {
  257. DisplayUtils.showSnackMessage(getView(), getString(R.string.could_not_retrieve_url));
  258. return;
  259. }
  260. FileDisplayActivity.showShareLinkDialog(fileActivity, file, createInternalLink(account, file));
  261. }
  262. private String createInternalLink(OwnCloudAccount account, OCFile file) {
  263. return account.getBaseUri() + "/index.php/f/" + file.getLocalId();
  264. }
  265. private void createShareLink() {
  266. if (capabilities != null && (capabilities.getFilesSharingPublicPasswordEnforced().isTrue() ||
  267. capabilities.getFilesSharingPublicAskForOptionalPassword().isTrue())) {
  268. // password enforced by server, request to the user before trying to create
  269. requestPasswordForShareViaLink(true,
  270. capabilities.getFilesSharingPublicAskForOptionalPassword().isTrue());
  271. } else {
  272. // create without password if not enforced by server or we don't know if enforced;
  273. fileOperationsHelper.shareFileViaPublicShare(file, null);
  274. }
  275. }
  276. private void showSendLinkTo() {
  277. if (file.isSharedViaLink()) {
  278. if (TextUtils.isEmpty(file.getPublicLink())) {
  279. fileOperationsHelper.getFileWithLink(file);
  280. } else {
  281. FileDisplayActivity.showShareLinkDialog(fileActivity, file, file.getPublicLink());
  282. }
  283. }
  284. }
  285. public void copyLink(OCShare share) {
  286. if (file.isSharedViaLink()) {
  287. if (TextUtils.isEmpty(file.getPublicLink())) {
  288. fileOperationsHelper.getFileWithLink(file);
  289. } else {
  290. ClipboardUtil.copyToClipboard(getActivity(), file.getPublicLink());
  291. }
  292. }
  293. }
  294. public void showLinkOverflowMenu(OCShare publicShare, ImageView overflowMenuShareLink) {
  295. if (ThemeUtils.themingEnabled(requireContext())) {
  296. // use grey as fallback for elements where custom theming is not available
  297. requireContext().getTheme().applyStyle(R.style.FallbackThemingTheme, true);
  298. }
  299. PopupMenu popup = new PopupMenu(requireContext(), overflowMenuShareLink);
  300. popup.inflate(R.menu.fragment_file_detail_sharing_link);
  301. prepareOptionsMenu(popup.getMenu(), publicShare);
  302. popup.setOnMenuItemClickListener(menuItem -> optionsItemSelected(menuItem, publicShare));
  303. popup.show();
  304. }
  305. private void prepareOptionsMenu(Menu menu, OCShare publicShare) {
  306. Resources res = requireContext().getResources();
  307. SharingMenuHelper.setupHideFileListingMenuItem(menu.findItem(R.id.action_hide_file_listing),
  308. file.isFolder(),
  309. menu.findItem(R.id.action_allow_editing).isChecked(),
  310. publicShare.getPermissions());
  311. SharingMenuHelper.setupHideFileDownload(menu.findItem(R.id.action_hide_file_download),
  312. publicShare.isHideFileDownload(),
  313. capabilities);
  314. SharingMenuHelper.setupPasswordMenuItem(menu.findItem(R.id.action_password),
  315. publicShare.isPasswordProtected());
  316. SharingMenuHelper.setupExpirationDateMenuItem(menu.findItem(R.id.action_share_expiration_date),
  317. publicShare.getExpirationDate(),
  318. res);
  319. menu.findItem(R.id.action_share_send_note).setVisible(capabilities.getVersion().isNoteOnShareSupported());
  320. if (publicShare.getPermissions() > PERMISSION_EDITING_ALLOWED) {
  321. menu.findItem(R.id.action_allow_editing).setChecked(true);
  322. } else {
  323. menu.findItem(R.id.action_allow_editing).setChecked(false);
  324. }
  325. }
  326. public boolean optionsItemSelected(MenuItem item, OCShare publicShare) {
  327. switch (item.getItemId()) {
  328. case R.id.action_allow_editing:
  329. if (file.isSharedViaLink()) {
  330. item.setChecked(!item.isChecked());
  331. fileOperationsHelper.setUploadPermissionsToPublicShare(publicShare, item.isChecked());
  332. }
  333. return true;
  334. case R.id.action_hide_file_listing: {
  335. item.setChecked(!item.isChecked());
  336. fileOperationsHelper.setHideFileListingPermissionsToPublicShare(publicShare, item.isChecked());
  337. return true;
  338. }
  339. case R.id.action_hide_file_download:
  340. item.setChecked(!item.isChecked());
  341. fileOperationsHelper.setHideFileDownloadPermissionsToPublicShare(publicShare, item.isChecked());
  342. return true;
  343. case R.id.action_edit_label:
  344. RenamePublicShareDialogFragment renameDialog = RenamePublicShareDialogFragment.newInstance(publicShare);
  345. renameDialog.show(fileActivity.getSupportFragmentManager(),
  346. RenamePublicShareDialogFragment.RENAME_PUBLIC_SHARE_FRAGMENT);
  347. return true;
  348. case R.id.action_password: {
  349. requestPasswordForShare(publicShare,
  350. capabilities.getFilesSharingPublicAskForOptionalPassword().isTrue());
  351. return true;
  352. }
  353. case R.id.action_share_expiration_date: {
  354. ExpirationDatePickerDialogFragment expirationDialog = ExpirationDatePickerDialogFragment
  355. .newInstance(publicShare, publicShare.getExpirationDate());
  356. expirationDialog.show(fileActivity.getSupportFragmentManager(),
  357. ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG);
  358. return true;
  359. }
  360. case R.id.action_share_send_link: {
  361. if (file.isSharedViaLink() && !TextUtils.isEmpty(file.getPublicLink())) {
  362. FileDisplayActivity.showShareLinkDialog(fileActivity, file, file.getPublicLink());
  363. } else {
  364. showSendLinkTo();
  365. }
  366. return true;
  367. }
  368. case R.id.action_share_send_note:
  369. NoteDialogFragment noteDialog = NoteDialogFragment.newInstance(publicShare);
  370. noteDialog.show(fileActivity.getSupportFragmentManager(), NoteDialogFragment.NOTE_FRAGMENT);
  371. return true;
  372. case R.id.action_add_another_public_share_link:
  373. createShareLink();
  374. return true;
  375. case R.id.action_unshare:
  376. fileOperationsHelper.unshareShare(file, publicShare);
  377. return true;
  378. default:
  379. return super.onOptionsItemSelected(item);
  380. }
  381. }
  382. /**
  383. * Updates the UI after the result of an update operation on the edited {@link OCFile}.
  384. *
  385. * @param result {@link RemoteOperationResult} of an update on the edited {@link OCFile} sharing information.
  386. * @param file the edited {@link OCFile}
  387. */
  388. public void onUpdateShareInformation(RemoteOperationResult result, OCFile file) {
  389. this.file = file;
  390. if (result.isSuccess()) {
  391. refreshUiFromDB();
  392. } else {
  393. setupView();
  394. }
  395. }
  396. /**
  397. * Get {@link OCShare} instance from DB and updates the UI.
  398. */
  399. private void refreshUiFromDB() {
  400. // Updates UI with new state
  401. setupView();
  402. }
  403. @Override
  404. public void unshareWith(OCShare share) {
  405. fileOperationsHelper.unshareShare(file, share);
  406. }
  407. @Override
  408. public int updatePermissionsToShare(OCShare share,
  409. boolean canReshare,
  410. boolean canEdit,
  411. boolean canEditCreate,
  412. boolean canEditChange,
  413. boolean canEditDelete) {
  414. SharePermissionsBuilder spb = new SharePermissionsBuilder();
  415. spb.setSharePermission(canReshare);
  416. if (file.isFolder()) {
  417. spb.setUpdatePermission(canEditChange)
  418. .setCreatePermission(canEditCreate)
  419. .setDeletePermission(canEditDelete);
  420. } else {
  421. spb.setUpdatePermission(canEdit);
  422. }
  423. int permissions = spb.build();
  424. fileOperationsHelper.setPermissionsToShare(share, permissions);
  425. return permissions;
  426. }
  427. /**
  428. * Starts a dialog that requests a password to the user to protect a share link.
  429. *
  430. * @param createShare When 'true', the request for password will be followed by the creation of a new public
  431. * link; when 'false', a public share is assumed to exist, and the password is bound to it.
  432. * @param askForPassword if true, password is optional
  433. */
  434. public void requestPasswordForShareViaLink(boolean createShare, boolean askForPassword) {
  435. SharePasswordDialogFragment dialog = SharePasswordDialogFragment.newInstance(file,
  436. createShare,
  437. askForPassword);
  438. dialog.show(getChildFragmentManager(), SharePasswordDialogFragment.PASSWORD_FRAGMENT);
  439. }
  440. @Override
  441. public void requestPasswordForShare(OCShare share, boolean askForPassword) {
  442. SharePasswordDialogFragment dialog = SharePasswordDialogFragment.newInstance(share, askForPassword);
  443. dialog.show(getChildFragmentManager(), SharePasswordDialogFragment.PASSWORD_FRAGMENT);
  444. }
  445. /**
  446. * Get known server capabilities from DB
  447. */
  448. public void refreshCapabilitiesFromDB() {
  449. capabilities = fileDataStorageManager.getCapability(user.getAccountName());
  450. }
  451. /**
  452. * Get public link from the DB to fill in the "Share link" section in the UI.
  453. *
  454. * Takes into account server capabilities before reading database.
  455. */
  456. public void refreshPublicShareFromDB() {
  457. if (FileDetailSharingFragmentHelper.isPublicShareDisabled(capabilities) || !file.canReshare()) {
  458. publicShareList.setVisibility(View.GONE);
  459. return;
  460. }
  461. // Get public share
  462. List<OCShare> shares = fileDataStorageManager.getSharesByPathAndType(file.getRemotePath(),
  463. ShareType.PUBLIC_LINK,
  464. "");
  465. if (shares.isEmpty()) {
  466. addPublicShare.setVisibility(View.VISIBLE);
  467. publicShareList.setVisibility(View.GONE);
  468. ImageView icon = requireView().findViewById(R.id.copy_internal_link_icon);
  469. icon.getBackground().setColorFilter(requireContext()
  470. .getResources()
  471. .getColor(R.color.primary_button_background_color),
  472. PorterDuff.Mode.SRC_IN);
  473. icon.getDrawable().mutate().setColorFilter(requireContext().getResources().getColor(R.color.black),
  474. PorterDuff.Mode.SRC_IN);
  475. requireView().findViewById(R.id.add_new_public_share_link).setOnClickListener(v -> createShareLink());
  476. } else {
  477. addPublicShare.setVisibility(View.GONE);
  478. publicShareList.setVisibility(View.VISIBLE);
  479. publicShareList.setAdapter(new PublicShareListAdapter(getContext(), shares, this));
  480. publicShareList.setLayoutManager(new LinearLayoutManager(getContext()));
  481. publicShareList.addItemDecoration(new SimpleListItemDividerDecoration(getContext()));
  482. }
  483. }
  484. @Override
  485. public void onSaveInstanceState(@NonNull Bundle outState) {
  486. super.onSaveInstanceState(outState);
  487. outState.putParcelable(ARG_FILE, file);
  488. outState.putParcelable(ARG_USER, user);
  489. }
  490. @Override
  491. public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
  492. sharedWithYouAvatar.setImageDrawable(avatarDrawable);
  493. }
  494. @Override
  495. public boolean shouldCallGeneratedCallback(String tag, Object callContext) {
  496. return false;
  497. }
  498. }