ShareFileFragment.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. /**
  2. * ownCloud Android client application
  3. *
  4. * @author masensio
  5. * @author David A. Velasco
  6. * @author Juan Carlos González Cabrero
  7. * Copyright (C) 2015 ownCloud Inc.
  8. * <p/>
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2,
  11. * as published by the Free Software Foundation.
  12. * <p/>
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. * <p/>
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. package com.owncloud.android.ui.fragment;
  22. import android.accounts.Account;
  23. import android.app.Activity;
  24. import android.graphics.Bitmap;
  25. import android.os.Bundle;
  26. import android.support.v4.app.Fragment;
  27. import android.support.v7.widget.AppCompatButton;
  28. import android.view.LayoutInflater;
  29. import android.view.View;
  30. import android.view.ViewGroup;
  31. import android.widget.Button;
  32. import android.widget.CompoundButton;
  33. import android.widget.ImageView;
  34. import android.widget.ListAdapter;
  35. import android.widget.ListView;
  36. import android.widget.ScrollView;
  37. import android.widget.Switch;
  38. import android.widget.TextView;
  39. import android.widget.Toast;
  40. import com.owncloud.android.R;
  41. import com.owncloud.android.authentication.AccountUtils;
  42. import com.owncloud.android.datamodel.OCFile;
  43. import com.owncloud.android.datamodel.ThumbnailsCacheManager;
  44. import com.owncloud.android.lib.common.utils.Log_OC;
  45. import com.owncloud.android.lib.resources.shares.OCShare;
  46. import com.owncloud.android.lib.resources.shares.ShareType;
  47. import com.owncloud.android.lib.resources.status.OCCapability;
  48. import com.owncloud.android.ui.activity.FileActivity;
  49. import com.owncloud.android.ui.adapter.ShareUserListAdapter;
  50. import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
  51. import com.owncloud.android.utils.DisplayUtils;
  52. import com.owncloud.android.utils.MimetypeIconUtil;
  53. import java.text.SimpleDateFormat;
  54. import java.util.ArrayList;
  55. import java.util.Date;
  56. /**
  57. * Fragment for Sharing a file with sharees (users or groups) or creating
  58. * a public link.
  59. * <p/>
  60. * A simple {@link Fragment} subclass.
  61. * <p/>
  62. * Activities that contain this fragment must implement the
  63. * {@link ShareFragmentListener} interface
  64. * to handle interaction events.
  65. * <p/>
  66. * Use the {@link ShareFileFragment#newInstance} factory method to
  67. * create an instance of this fragment.
  68. */
  69. public class ShareFileFragment extends Fragment
  70. implements ShareUserListAdapter.ShareUserAdapterListener {
  71. private static final String TAG = ShareFileFragment.class.getSimpleName();
  72. /**
  73. * The fragment initialization parameters
  74. */
  75. private static final String ARG_FILE = "FILE";
  76. private static final String ARG_ACCOUNT = "ACCOUNT";
  77. // /** Tag for dialog */
  78. // private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
  79. /**
  80. * File to share, received as a parameter in construction time
  81. */
  82. private OCFile mFile;
  83. /**
  84. * OC account holding the file to share, received as a parameter in construction time
  85. */
  86. private Account mAccount;
  87. /**
  88. * Reference to parent listener
  89. */
  90. private ShareFragmentListener mListener;
  91. /**
  92. * List of private shares bound to the file
  93. */
  94. private ArrayList<OCShare> mPrivateShares;
  95. /**
  96. * Capabilities of the server
  97. */
  98. private OCCapability mCapabilities;
  99. /**
  100. * Adapter to show private shares
  101. */
  102. private ShareUserListAdapter mUserGroupsAdapter = null;
  103. /**
  104. * Public share bound to the file
  105. */
  106. private OCShare mPublicShare;
  107. /**
  108. * Listener for changes on switch to share / unshare publicly
  109. */
  110. private CompoundButton.OnCheckedChangeListener mOnShareViaLinkSwitchCheckedChangeListener;
  111. /**
  112. * Listener for user actions to set, update or clear password on public link
  113. */
  114. private OnPasswordInteractionListener mOnPasswordInteractionListener = null;
  115. /**
  116. * Listener for user actions to set, update or clear expiration date on public link
  117. */
  118. private OnExpirationDateInteractionListener mOnExpirationDateInteractionListener = null;
  119. /**
  120. * Listener for user actions to set or unset edit permission on public link
  121. */
  122. private OnEditPermissionInteractionListener mOnEditPermissionInteractionListener = null;
  123. /**
  124. * Public factory method to create new ShareFileFragment instances.
  125. *
  126. * @param fileToShare An {@link OCFile} to show in the fragment
  127. * @param account An ownCloud account
  128. * @return A new instance of fragment ShareFileFragment.
  129. */
  130. public static ShareFileFragment newInstance(OCFile fileToShare, Account account) {
  131. ShareFileFragment fragment = new ShareFileFragment();
  132. Bundle args = new Bundle();
  133. args.putParcelable(ARG_FILE, fileToShare);
  134. args.putParcelable(ARG_ACCOUNT, account);
  135. fragment.setArguments(args);
  136. return fragment;
  137. }
  138. /**
  139. * Required empty public constructor
  140. */
  141. public ShareFileFragment() {
  142. }
  143. /**
  144. * {@inheritDoc}
  145. */
  146. @Override
  147. public void onCreate(Bundle savedInstanceState) {
  148. super.onCreate(savedInstanceState);
  149. Log_OC.d(TAG, "onCreate");
  150. if (getArguments() != null) {
  151. mFile = getArguments().getParcelable(ARG_FILE);
  152. mAccount = getArguments().getParcelable(ARG_ACCOUNT);
  153. }
  154. }
  155. /**
  156. * {@inheritDoc}
  157. */
  158. @Override
  159. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  160. Bundle savedInstanceState) {
  161. Log_OC.d(TAG, "onCreateView");
  162. // Inflate the layout for this fragment
  163. View view = inflater.inflate(R.layout.share_file_layout, container, false);
  164. // Setup layout
  165. // Image
  166. ImageView icon = (ImageView) view.findViewById(R.id.shareFileIcon);
  167. icon.setImageResource(MimetypeIconUtil.getFileTypeIconId(mFile.getMimetype(),
  168. mFile.getFileName()));
  169. if (mFile.isImage()) {
  170. String remoteId = String.valueOf(mFile.getRemoteId());
  171. Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(remoteId);
  172. if (thumbnail != null) {
  173. icon.setImageBitmap(thumbnail);
  174. }
  175. }
  176. // Name
  177. TextView filename = (TextView) view.findViewById(R.id.shareFileName);
  178. filename.setText(mFile.getFileName());
  179. // Size
  180. TextView size = (TextView) view.findViewById(R.id.shareFileSize);
  181. if (mFile.isFolder()) {
  182. size.setVisibility(View.GONE);
  183. } else {
  184. size.setText(DisplayUtils.bytesToHumanReadable(mFile.getFileLength()));
  185. }
  186. // Add User Button
  187. Button addUserGroupButton = (Button)
  188. view.findViewById(R.id.addUserButton);
  189. addUserGroupButton.setOnClickListener(new View.OnClickListener() {
  190. @Override
  191. public void onClick(View view) {
  192. boolean shareWithUsersEnable = AccountUtils.hasSearchUsersSupport(mAccount);
  193. if (shareWithUsersEnable) {
  194. // Show Search Fragment
  195. mListener.showSearchUsersAndGroups();
  196. } else {
  197. String message = getString(R.string.share_sharee_unavailable);
  198. Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
  199. }
  200. }
  201. });
  202. // Set listener for user actions on switch for sharing/unsharing via link
  203. initShareViaLinkListener(view);
  204. // Set listener for user actions on expiration date
  205. initExpirationListener(view);
  206. // Set listener for user actions on password
  207. initPasswordListener(view);
  208. // Set listener for user actions on edit permission
  209. initEditPermissionListener(view);
  210. return view;
  211. }
  212. /**
  213. * Binds listener for user actions to create or delete a public share
  214. * to the views receiving the user events.
  215. *
  216. * @param shareView Root view in the fragment.
  217. */
  218. private void initShareViaLinkListener(View shareView) {
  219. mOnShareViaLinkSwitchCheckedChangeListener = new OnShareViaLinkListener();
  220. Switch shareViaLinkSwitch = (Switch) shareView.findViewById(R.id.shareViaLinkSectionSwitch);
  221. shareViaLinkSwitch.setOnCheckedChangeListener(mOnShareViaLinkSwitchCheckedChangeListener);
  222. }
  223. /**
  224. * Listener for user actions that create or delete a public share.
  225. */
  226. private class OnShareViaLinkListener
  227. implements CompoundButton.OnCheckedChangeListener {
  228. /**
  229. * Called by R.id.shareViaLinkSectionSwitch to create or delete a public link.
  230. *
  231. * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkSectionSwitch
  232. * @param isChecked New switch state.
  233. */
  234. @Override
  235. public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
  236. if (!isResumed()) {
  237. // very important, setCheched(...) is called automatically during
  238. // Fragment recreation on device rotations
  239. return;
  240. }
  241. if (isChecked) {
  242. if (mCapabilities != null &&
  243. mCapabilities.getFilesSharingPublicPasswordEnforced().isTrue()) {
  244. // password enforced by server, request to the user before trying to create
  245. ((FileActivity) getActivity()).getFileOperationsHelper().
  246. requestPasswordForShareViaLink(mFile, true);
  247. } else {
  248. // create without password if not enforced by server or we don't know if enforced;
  249. ((FileActivity) getActivity()).getFileOperationsHelper().
  250. shareFileViaLink(mFile, null);
  251. // FileActivtiy#onCreateShareViaLinkOperationFinish still handles the guess of enforcement
  252. // for server in versions previous to OwnCloudVersion#MINIMUM_VERSION_CAPABILITIES_API
  253. }
  254. } else {
  255. ((FileActivity) getActivity()).getFileOperationsHelper().
  256. unshareFileViaLink(mFile);
  257. }
  258. // undo the toggle to grant the view will be correct if any intermediate dialog is cancelled or
  259. // the create/delete operation fails
  260. switchView.setOnCheckedChangeListener(null);
  261. switchView.toggle();
  262. switchView.setOnCheckedChangeListener(mOnShareViaLinkSwitchCheckedChangeListener);
  263. }
  264. }
  265. /**
  266. * Binds listener for user actions that start any update on a expiration date
  267. * for the public link to the views receiving the user events.
  268. *
  269. * @param shareView Root view in the fragment.
  270. */
  271. private void initExpirationListener(View shareView) {
  272. mOnExpirationDateInteractionListener = new OnExpirationDateInteractionListener();
  273. ((Switch) shareView.findViewById(R.id.shareViaLinkExpirationSwitch)).
  274. setOnCheckedChangeListener(mOnExpirationDateInteractionListener);
  275. shareView.findViewById(R.id.shareViaLinkExpirationLabel).
  276. setOnClickListener(mOnExpirationDateInteractionListener);
  277. shareView.findViewById(R.id.shareViaLinkExpirationValue).
  278. setOnClickListener(mOnExpirationDateInteractionListener);
  279. }
  280. /**
  281. * Listener for user actions that start any update on the expiration date for the public link.
  282. */
  283. private class OnExpirationDateInteractionListener
  284. implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {
  285. /**
  286. * Called by R.id.shareViaLinkExpirationSwitch to set or clear the expiration date.
  287. *
  288. * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkExpirationSwitch
  289. * @param isChecked New switch state.
  290. */
  291. @Override
  292. public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
  293. if (!isResumed()) {
  294. // very important, setCheched(...) is called automatically during
  295. // Fragment recreation on device rotations
  296. return;
  297. }
  298. if (isChecked) {
  299. ExpirationDatePickerDialogFragment dialog =
  300. ExpirationDatePickerDialogFragment.newInstance(mFile, -1);
  301. dialog.show(
  302. getActivity().getSupportFragmentManager(),
  303. ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG
  304. );
  305. } else {
  306. ((FileActivity) getActivity()).getFileOperationsHelper().
  307. setExpirationDateToShareViaLink(mFile, -1);
  308. }
  309. // undo the toggle to grant the view will be correct if the dialog is cancelled
  310. switchView.setOnCheckedChangeListener(null);
  311. switchView.toggle();
  312. switchView.setOnCheckedChangeListener(mOnExpirationDateInteractionListener);
  313. }
  314. /**
  315. * Called by R.id.shareViaLinkExpirationLabel or R.id.shareViaLinkExpirationValue
  316. * to change the current expiration date.
  317. *
  318. * @param expirationView Label or value view touched by the user.
  319. */
  320. @Override
  321. public void onClick(View expirationView) {
  322. if (mPublicShare != null && mPublicShare.getExpirationDate() > 0) {
  323. long chosenDateInMillis = -1;
  324. if (mPublicShare != null) {
  325. chosenDateInMillis = mPublicShare.getExpirationDate();
  326. }
  327. ExpirationDatePickerDialogFragment dialog =
  328. ExpirationDatePickerDialogFragment.newInstance(
  329. mFile,
  330. chosenDateInMillis
  331. );
  332. dialog.show(
  333. getActivity().getSupportFragmentManager(),
  334. ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG
  335. );
  336. }
  337. }
  338. }
  339. /**
  340. * Binds listener for user actions that start any update on a password for the public link
  341. * to the views receiving the user events.
  342. *
  343. * @param shareView Root view in the fragment.
  344. */
  345. private void initPasswordListener(View shareView) {
  346. mOnPasswordInteractionListener = new OnPasswordInteractionListener();
  347. ((Switch) shareView.findViewById(R.id.shareViaLinkPasswordSwitch)).
  348. setOnCheckedChangeListener(mOnPasswordInteractionListener);
  349. shareView.findViewById(R.id.shareViaLinkPasswordLabel).
  350. setOnClickListener(mOnPasswordInteractionListener);
  351. shareView.findViewById(R.id.shareViaLinkPasswordValue).
  352. setOnClickListener(mOnPasswordInteractionListener);
  353. }
  354. /**
  355. * Listener for user actions that start any update on a password for the public link.
  356. */
  357. private class OnPasswordInteractionListener
  358. implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {
  359. /**
  360. * Called by R.id.shareViaLinkPasswordSwitch to set or clear the password.
  361. *
  362. * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkPasswordSwitch
  363. * @param isChecked New switch state.
  364. */
  365. @Override
  366. public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
  367. if (!isResumed()) {
  368. // very important, setCheched(...) is called automatically during
  369. // Fragment recreation on device rotations
  370. return;
  371. }
  372. if (isChecked) {
  373. ((FileActivity) getActivity()).getFileOperationsHelper().
  374. requestPasswordForShareViaLink(mFile, false);
  375. } else {
  376. ((FileActivity) getActivity()).getFileOperationsHelper().
  377. setPasswordToShareViaLink(mFile, ""); // "" clears
  378. }
  379. // undo the toggle to grant the view will be correct if the dialog is cancelled
  380. switchView.setOnCheckedChangeListener(null);
  381. switchView.toggle();
  382. switchView.setOnCheckedChangeListener(mOnPasswordInteractionListener);
  383. }
  384. /**
  385. * Called by R.id.shareViaLinkPasswordLabel or R.id.shareViaLinkPasswordValue
  386. * to change the current password.
  387. *
  388. * @param passwordView Label or value view touched by the user.
  389. */
  390. @Override
  391. public void onClick(View passwordView) {
  392. if (mPublicShare != null && mPublicShare.isPasswordProtected()) {
  393. ((FileActivity) getActivity()).getFileOperationsHelper().
  394. requestPasswordForShareViaLink(mFile, false);
  395. }
  396. }
  397. }
  398. /**
  399. * Binds listener for user actions that start any update the edit permissions
  400. * for the public link to the views receiving the user events.
  401. *
  402. * @param shareView Root view in the fragment.
  403. */
  404. private void initEditPermissionListener(View shareView) {
  405. mOnEditPermissionInteractionListener = new OnEditPermissionInteractionListener();
  406. ((Switch) shareView.findViewById(R.id.shareViaLinkEditPermissionSwitch)).
  407. setOnCheckedChangeListener(mOnEditPermissionInteractionListener);
  408. }
  409. /**
  410. * Listener for user actions that start any update on the edit permissions for the public link.
  411. */
  412. private class OnEditPermissionInteractionListener
  413. implements CompoundButton.OnCheckedChangeListener {
  414. /**
  415. * Called by R.id.shareViaLinkEditPermissionSwitch to set or clear the edit permission.
  416. *
  417. * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkEditPermissionSwitch
  418. * @param isChecked New switch state.
  419. */
  420. @Override
  421. public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
  422. if (!isResumed()) {
  423. // very important, setCheched(...) is called automatically during
  424. // Fragment recreation on device rotations
  425. return;
  426. }
  427. ((FileActivity) getActivity()).getFileOperationsHelper().
  428. setUploadPermissionsToShare(
  429. mFile,
  430. isChecked
  431. );
  432. ;
  433. // undo the toggle to grant the view will be correct if the dialog is cancelled
  434. switchView.setOnCheckedChangeListener(null);
  435. switchView.toggle();
  436. switchView.setOnCheckedChangeListener(mOnEditPermissionInteractionListener);
  437. }
  438. }
  439. @Override
  440. public void onActivityCreated(Bundle savedInstanceState) {
  441. super.onActivityCreated(savedInstanceState);
  442. Log_OC.d(TAG, "onActivityCreated");
  443. getActivity().setTitle(R.string.share_dialog_title);
  444. // Load known capabilities of the server from DB
  445. refreshCapabilitiesFromDB();
  446. // Load data into the list of private shares
  447. refreshUsersOrGroupsListFromDB();
  448. // Load data of public share, if exists
  449. refreshPublicShareFromDB();
  450. }
  451. @Override
  452. public void onAttach(Activity activity) {
  453. super.onAttach(activity);
  454. try {
  455. mListener = (ShareFragmentListener) activity;
  456. } catch (ClassCastException e) {
  457. throw new ClassCastException(activity.toString()
  458. + " must implement OnShareFragmentInteractionListener");
  459. }
  460. }
  461. @Override
  462. public void onDetach() {
  463. super.onDetach();
  464. mListener = null;
  465. }
  466. /**
  467. * Get known server capabilities from DB
  468. * <p/>
  469. * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
  470. * instance ready to use. If not ready, does nothing.
  471. */
  472. public void refreshCapabilitiesFromDB() {
  473. if (((FileActivity) mListener).getStorageManager() != null) {
  474. mCapabilities = ((FileActivity) mListener).getStorageManager().
  475. getCapability(mAccount.name);
  476. }
  477. }
  478. /**
  479. * Get users and groups from the DB to fill in the "share with" list.
  480. * <p/>
  481. * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
  482. * instance ready to use. If not ready, does nothing.
  483. */
  484. public void refreshUsersOrGroupsListFromDB() {
  485. if (((FileActivity) mListener).getStorageManager() != null) {
  486. // Get Users and Groups
  487. mPrivateShares = ((FileActivity) mListener).getStorageManager().getSharesWithForAFile(
  488. mFile.getRemotePath(),
  489. mAccount.name
  490. );
  491. // Update list of users/groups
  492. updateListOfUserGroups();
  493. }
  494. }
  495. private void updateListOfUserGroups() {
  496. // Update list of users/groups
  497. // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
  498. mUserGroupsAdapter = new ShareUserListAdapter(
  499. getActivity(),
  500. R.layout.share_user_item,
  501. mPrivateShares,
  502. this
  503. );
  504. // Show data
  505. TextView noShares = (TextView) getView().findViewById(R.id.shareNoUsers);
  506. ListView usersList = (ListView) getView().findViewById(R.id.shareUsersList);
  507. if (mPrivateShares.size() > 0) {
  508. noShares.setVisibility(View.GONE);
  509. usersList.setVisibility(View.VISIBLE);
  510. usersList.setAdapter(mUserGroupsAdapter);
  511. setListViewHeightBasedOnChildren(usersList);
  512. } else {
  513. noShares.setVisibility(View.VISIBLE);
  514. usersList.setVisibility(View.GONE);
  515. }
  516. // Set Scroll to initial position
  517. ScrollView scrollView = (ScrollView) getView().findViewById(R.id.shareScroll);
  518. scrollView.scrollTo(0, 0);
  519. }
  520. @Override
  521. public void unshareButtonPressed(OCShare share) {
  522. // Unshare
  523. Log_OC.d(TAG, "Unsharing " + share.getSharedWithDisplayName());
  524. mListener.unshareWith(share);
  525. }
  526. @Override
  527. public void editShare(OCShare share) {
  528. // move to fragment to edit share
  529. Log_OC.d(TAG, "Editing " + share.getSharedWithDisplayName());
  530. mListener.showEditShare(share);
  531. }
  532. /**
  533. * Get public link from the DB to fill in the "Share link" section in the UI.
  534. * <p/>
  535. * Takes into account server capabilities before reading database.
  536. * <p/>
  537. * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
  538. * instance ready to use. If not ready, does nothing.
  539. */
  540. public void refreshPublicShareFromDB() {
  541. if (isPublicShareDisabled()) {
  542. hidePublicShare();
  543. } else if (((FileActivity) mListener).getStorageManager() != null) {
  544. // Get public share
  545. mPublicShare = ((FileActivity) mListener).getStorageManager().getFirstShareByPathAndType(
  546. mFile.getRemotePath(),
  547. ShareType.PUBLIC_LINK,
  548. ""
  549. );
  550. // Update public share section
  551. updatePublicShareSection();
  552. }
  553. }
  554. /**
  555. * @return 'True' when public share is disabled in the server
  556. */
  557. private boolean isPublicShareDisabled() {
  558. return (mCapabilities != null &&
  559. mCapabilities.getFilesSharingPublicEnabled().isFalse()
  560. );
  561. }
  562. /**
  563. * Updates in the UI the section about public share with the information in the current
  564. * public share bound to mFile, if any
  565. */
  566. private void updatePublicShareSection() {
  567. if (mPublicShare != null && ShareType.PUBLIC_LINK.equals(mPublicShare.getShareType())) {
  568. /// public share bound -> expand section
  569. Switch shareViaLinkSwitch = getShareViaLinkSwitch();
  570. if (!shareViaLinkSwitch.isChecked()) {
  571. // set null listener before setChecked() to prevent infinite loop of calls
  572. shareViaLinkSwitch.setOnCheckedChangeListener(null);
  573. shareViaLinkSwitch.setChecked(true);
  574. shareViaLinkSwitch.setOnCheckedChangeListener(
  575. mOnShareViaLinkSwitchCheckedChangeListener
  576. );
  577. }
  578. getExpirationDateSection().setVisibility(View.VISIBLE);
  579. getPasswordSection().setVisibility(View.VISIBLE);
  580. if (mFile.isFolder() && !mCapabilities.getFilesSharingPublicUpload().isFalse()) {
  581. getEditPermissionSection().setVisibility(View.VISIBLE);
  582. } else {
  583. getEditPermissionSection().setVisibility(View.GONE);
  584. }
  585. // GetLink button
  586. AppCompatButton getLinkButton = getGetLinkButton();
  587. getLinkButton.setVisibility(View.VISIBLE);
  588. getLinkButton.setOnClickListener(new View.OnClickListener() {
  589. @Override
  590. public void onClick(View v) {
  591. //GetLink from the server and show ShareLinkToDialog
  592. ((FileActivity) getActivity()).getFileOperationsHelper().
  593. getFileWithLink(mFile);
  594. }
  595. });
  596. /// update state of expiration date switch and message depending on expiration date
  597. Switch expirationDateSwitch = getExpirationDateSwitch();
  598. // set null listener before setChecked() to prevent infinite loop of calls
  599. expirationDateSwitch.setOnCheckedChangeListener(null);
  600. long expirationDate = mPublicShare.getExpirationDate();
  601. if (expirationDate > 0) {
  602. if (!expirationDateSwitch.isChecked()) {
  603. expirationDateSwitch.toggle();
  604. }
  605. String formattedDate =
  606. SimpleDateFormat.getDateInstance().format(
  607. new Date(expirationDate)
  608. );
  609. getExpirationDateValue().setText(formattedDate);
  610. } else {
  611. if (expirationDateSwitch.isChecked()) {
  612. expirationDateSwitch.toggle();
  613. }
  614. getExpirationDateValue().setText(R.string.empty);
  615. }
  616. // recover listener
  617. expirationDateSwitch.setOnCheckedChangeListener(
  618. mOnExpirationDateInteractionListener
  619. );
  620. /// update state of password switch and message depending on password protection
  621. Switch passwordSwitch = getPasswordSwitch();
  622. // set null listener before setChecked() to prevent infinite loop of calls
  623. passwordSwitch.setOnCheckedChangeListener(null);
  624. if (mPublicShare.isPasswordProtected()) {
  625. if (!passwordSwitch.isChecked()) {
  626. passwordSwitch.toggle();
  627. }
  628. getPasswordValue().setVisibility(View.VISIBLE);
  629. } else {
  630. if (passwordSwitch.isChecked()) {
  631. passwordSwitch.toggle();
  632. }
  633. getPasswordValue().setVisibility(View.INVISIBLE);
  634. }
  635. // recover listener
  636. passwordSwitch.setOnCheckedChangeListener(
  637. mOnPasswordInteractionListener
  638. );
  639. /// update state of the edit permission switch
  640. Switch editPermissionSwitch = getEditPermissionSwitch();
  641. // set null listener before setChecked() to prevent infinite loop of calls
  642. editPermissionSwitch.setOnCheckedChangeListener(null);
  643. if (mPublicShare.getPermissions() > OCShare.READ_PERMISSION_FLAG) {
  644. if (!editPermissionSwitch.isChecked()) {
  645. editPermissionSwitch.toggle();
  646. }
  647. } else {
  648. if (editPermissionSwitch.isChecked()) {
  649. editPermissionSwitch.toggle();
  650. }
  651. }
  652. // recover listener
  653. editPermissionSwitch.setOnCheckedChangeListener(
  654. mOnEditPermissionInteractionListener
  655. );
  656. } else {
  657. /// no public share -> collapse section
  658. Switch shareViaLinkSwitch = getShareViaLinkSwitch();
  659. if (shareViaLinkSwitch.isChecked()) {
  660. shareViaLinkSwitch.setOnCheckedChangeListener(null);
  661. getShareViaLinkSwitch().setChecked(false);
  662. shareViaLinkSwitch.setOnCheckedChangeListener(
  663. mOnShareViaLinkSwitchCheckedChangeListener
  664. );
  665. }
  666. getExpirationDateSection().setVisibility(View.GONE);
  667. getPasswordSection().setVisibility(View.GONE);
  668. getEditPermissionSection().setVisibility(View.GONE);
  669. getGetLinkButton().setVisibility(View.GONE);
  670. }
  671. }
  672. /// BEWARE: next methods will failed with NullPointerException if called before onCreateView() finishes
  673. private Switch getShareViaLinkSwitch() {
  674. return (Switch) getView().findViewById(R.id.shareViaLinkSectionSwitch);
  675. }
  676. private View getExpirationDateSection() {
  677. return getView().findViewById(R.id.shareViaLinkExpirationSection);
  678. }
  679. private Switch getExpirationDateSwitch() {
  680. return (Switch) getView().findViewById(R.id.shareViaLinkExpirationSwitch);
  681. }
  682. private TextView getExpirationDateValue() {
  683. return (TextView) getView().findViewById(R.id.shareViaLinkExpirationValue);
  684. }
  685. private View getPasswordSection() {
  686. return getView().findViewById(R.id.shareViaLinkPasswordSection);
  687. }
  688. private Switch getPasswordSwitch() {
  689. return (Switch) getView().findViewById(R.id.shareViaLinkPasswordSwitch);
  690. }
  691. private TextView getPasswordValue() {
  692. return (TextView) getView().findViewById(R.id.shareViaLinkPasswordValue);
  693. }
  694. private View getEditPermissionSection() {
  695. return getView().findViewById(R.id.shareViaLinkEditPermissionSection);
  696. }
  697. private Switch getEditPermissionSwitch() {
  698. return (Switch) getView().findViewById(R.id.shareViaLinkEditPermissionSwitch);
  699. }
  700. private AppCompatButton getGetLinkButton() {
  701. return (AppCompatButton) getView().findViewById(R.id.shareViaLinkGetLinkButton);
  702. }
  703. /**
  704. * Hides all the UI elements related to public share
  705. */
  706. private void hidePublicShare() {
  707. getShareViaLinkSwitch().setVisibility(View.GONE);
  708. getExpirationDateSection().setVisibility(View.GONE);
  709. getPasswordSection().setVisibility(View.GONE);
  710. getEditPermissionSection().setVisibility(View.GONE);
  711. getGetLinkButton().setVisibility(View.GONE);
  712. }
  713. public static void setListViewHeightBasedOnChildren(ListView listView) {
  714. ListAdapter listAdapter = listView.getAdapter();
  715. if (listAdapter == null) {
  716. return;
  717. }
  718. int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.AT_MOST);
  719. int totalHeight = 0;
  720. View view = null;
  721. for (int i = 0; i < listAdapter.getCount(); i++) {
  722. view = listAdapter.getView(i, view, listView);
  723. if (i == 0) {
  724. view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
  725. }
  726. view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
  727. totalHeight += view.getMeasuredHeight();
  728. }
  729. ViewGroup.LayoutParams params = listView.getLayoutParams();
  730. params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
  731. listView.setLayoutParams(params);
  732. listView.requestLayout();
  733. }
  734. }