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