Updated ShareFileFragment layout with extra section for public shares
[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.ListView;
37 import android.widget.Switch;
38 import android.widget.TextView;
39 import android.widget.Toast;
40
41 import com.owncloud.android.R;
42 import com.owncloud.android.authentication.AccountUtils;
43 import com.owncloud.android.datamodel.OCFile;
44 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
45 import com.owncloud.android.lib.common.utils.Log_OC;
46 import com.owncloud.android.lib.resources.shares.OCShare;
47 import com.owncloud.android.lib.resources.shares.ShareType;
48 import com.owncloud.android.ui.activity.FileActivity;
49 import com.owncloud.android.ui.adapter.ShareUserListAdapter;
50 import com.owncloud.android.utils.DisplayUtils;
51 import com.owncloud.android.utils.MimetypeIconUtil;
52
53 import java.util.ArrayList;
54
55 /**
56 * Fragment for Sharing a file with sharees (users or groups) or creating
57 * a public link.
58 *
59 * A simple {@link Fragment} subclass.
60 *
61 * Activities that contain this fragment must implement the
62 * {@link ShareFileFragment.OnShareFragmentInteractionListener} interface
63 * to handle interaction events.
64 *
65 * Use the {@link ShareFileFragment#newInstance} factory method to
66 * create an instance of this fragment.
67 */
68 public class ShareFileFragment extends Fragment
69 implements ShareUserListAdapter.ShareUserAdapterListener{
70
71 private static final String TAG = ShareFileFragment.class.getSimpleName();
72
73 // the fragment initialization parameters
74 private static final String ARG_FILE = "FILE";
75 private static final String ARG_ACCOUNT = "ACCOUNT";
76
77 /** File to share, received as a parameter in construction time */
78 private OCFile mFile;
79
80 /** OC account holding the file to share, received as a parameter in construction time */
81 private Account mAccount;
82
83 /** Reference to parent listener */
84 private OnShareFragmentInteractionListener mListener;
85
86 /** List of private shares bound to the file */
87 private ArrayList<OCShare> mPrivateShares;
88
89 /** Adapter to show private shares */
90 private ShareUserListAdapter mUserGroupsAdapter = null;
91
92 /** Public share bound to the file */
93 private OCShare mPublicShare;
94
95
96 /**
97 * Public factory method to create new ShareFileFragment instances.
98 *
99 * @param fileToShare An {@link OCFile} to show in the fragment
100 * @param account An ownCloud account
101 * @return A new instance of fragment ShareFileFragment.
102 */
103 public static ShareFileFragment newInstance(OCFile fileToShare, Account account) {
104 ShareFileFragment fragment = new ShareFileFragment();
105 Bundle args = new Bundle();
106 args.putParcelable(ARG_FILE, fileToShare);
107 args.putParcelable(ARG_ACCOUNT, account);
108 fragment.setArguments(args);
109 return fragment;
110 }
111
112 public ShareFileFragment() {
113 // Required empty public constructor
114 }
115
116 /**
117 * {@inheritDoc}
118 */
119 @Override
120 public void onCreate(Bundle savedInstanceState) {
121 super.onCreate(savedInstanceState);
122 if (getArguments() != null) {
123 mFile = getArguments().getParcelable(ARG_FILE);
124 mAccount = getArguments().getParcelable(ARG_ACCOUNT);
125 }
126 }
127
128 /**
129 * {@inheritDoc}
130 */
131 @Override
132 public View onCreateView(LayoutInflater inflater, ViewGroup container,
133 Bundle savedInstanceState) {
134 // Inflate the layout for this fragment
135 View view = inflater.inflate(R.layout.share_file_layout, container, false);
136
137 // Setup layout
138 // Image
139 ImageView icon = (ImageView) view.findViewById(R.id.shareFileIcon);
140 icon.setImageResource(MimetypeIconUtil.getFileTypeIconId(mFile.getMimetype(),
141 mFile.getFileName()));
142 if (mFile.isImage()) {
143 String remoteId = String.valueOf(mFile.getRemoteId());
144 Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(remoteId);
145 if (thumbnail != null) {
146 icon.setImageBitmap(thumbnail);
147 }
148 }
149 // Name
150 TextView filename = (TextView) view.findViewById(R.id.shareFileName);
151 filename.setText(mFile.getFileName());
152 // Size
153 TextView size = (TextView) view.findViewById(R.id.shareFileSize);
154 if (mFile.isFolder()) {
155 size.setVisibility(View.GONE);
156 } else {
157 size.setText(DisplayUtils.bytesToHumanReadable(mFile.getFileLength()));
158 }
159
160 // Add User Button
161 Button addUserGroupButton = (Button)
162 view.findViewById(R.id.addUserButton);
163 addUserGroupButton.setOnClickListener(new View.OnClickListener() {
164 @Override
165 public void onClick(View view) {
166 boolean shareWithUsersEnable = AccountUtils.hasSearchUsersSupport(mAccount);
167 if (shareWithUsersEnable) {
168 // Show Search Fragment
169 mListener.showSearchUsersAndGroups();
170 } else {
171 String message = getString(R.string.share_sharee_unavailable);
172 Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
173 }
174 }
175 });
176
177 // Switch to create public share
178 Switch shareViaLinkSwitch = (Switch) view.findViewById(R.id.shareViaLinkSectionSwitch);
179 shareViaLinkSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
180 @Override
181 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
182 if (isChecked) {
183 // TODO real implementation: create public share
184 // expand section
185 getExpirationDateSection().setVisibility(View.VISIBLE);
186 getPasswordSection().setVisibility(View.VISIBLE);
187 getGetLinkButton().setVisibility(View.VISIBLE);
188
189 } else {
190 // TODO real implementation: unshare
191 // collapse section
192 getExpirationDateSection().setVisibility(View.GONE);
193 getPasswordSection().setVisibility(View.GONE);
194 getGetLinkButton().setVisibility(View.GONE);
195 }
196 }
197 });
198
199 // Switch for expiration date
200 Switch shareViaLinkExpirationSwitch = (Switch) view.findViewById(R.id.shareViaLinkExpirationSwitch);
201 shareViaLinkExpirationSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
202 @Override
203 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
204 if (isChecked) {
205 // TODO real implementation: update share with expiration date
206 // show value of expiration date
207 getExpirationDateValue().setText(R.string.placeholder_timestamp);
208
209 } else {
210 // TODO real implementation: update share without expiration date
211 // empty value
212 getExpirationDateValue().setText(R.string.empty);
213 }
214 }
215 });
216
217 // Switch for password
218 Switch shareViaLinkPasswordSwitch = (Switch) view.findViewById(R.id.shareViaLinkPasswordSwitch);
219 shareViaLinkPasswordSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
220 @Override
221 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
222 if (isChecked) {
223 // TODO real implementation: update share with password
224 // show
225 getExpirationPasswordValue().setVisibility(View.VISIBLE);
226
227 } else {
228 // TODO real implementation: update share without password
229 // empty value
230 getExpirationPasswordValue().setVisibility(View.INVISIBLE);
231 }
232 }
233 });
234
235
236 return view;
237 }
238
239 @Override
240 public void onActivityCreated(Bundle savedInstanceState) {
241 super.onActivityCreated(savedInstanceState);
242
243 // Load data into the list of private shares
244 refreshUsersOrGroupsListFromDB();
245
246 // Load data of public share, if exists
247 refreshPublicShareFromDB();
248 }
249
250 @Override
251 public void onAttach(Activity activity) {
252 super.onAttach(activity);
253 try {
254 mListener = (OnShareFragmentInteractionListener) activity;
255 } catch (ClassCastException e) {
256 throw new ClassCastException(activity.toString()
257 + " must implement OnShareFragmentInteractionListener");
258 }
259 }
260
261 @Override
262 public void onDetach() {
263 super.onDetach();
264 mListener = null;
265 }
266
267 /**
268 * Get users and groups from the DB to fill in the "share with" list
269 *
270 * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
271 * instance ready to use. If not ready, does nothing.
272 */
273 public void refreshUsersOrGroupsListFromDB (){
274 if (((FileActivity) mListener).getStorageManager() != null) {
275 // Get Users and Groups
276 mPrivateShares = ((FileActivity) mListener).getStorageManager().getSharesWithForAFile(
277 mFile.getRemotePath(),
278 mAccount.name
279 );
280
281 // Update list of users/groups
282 updateListOfUserGroups();
283 }
284 }
285
286 private void updateListOfUserGroups() {
287 // Update list of users/groups
288 // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
289 mUserGroupsAdapter = new ShareUserListAdapter(
290 getActivity(),
291 R.layout.share_user_item,
292 mPrivateShares,
293 this
294 );
295
296 // Show data
297 TextView noShares = (TextView) getView().findViewById(R.id.shareNoUsers);
298 ListView usersList = (ListView) getView().findViewById(R.id.shareUsersList);
299
300 if (mPrivateShares.size() > 0) {
301 noShares.setVisibility(View.GONE);
302 usersList.setVisibility(View.VISIBLE);
303 usersList.setAdapter(mUserGroupsAdapter);
304
305 } else {
306 noShares.setVisibility(View.VISIBLE);
307 usersList.setVisibility(View.GONE);
308 }
309 }
310
311 @Override
312 public void unshareButtonPressed(OCShare share) {
313 // Unshare
314 mListener.unshareWith(share);
315 Log_OC.d(TAG, "Unshare - " + share.getSharedWithDisplayName());
316 }
317
318
319
320 /**
321 * Get public link from the DB to fill in the "Share link" section
322 *
323 * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
324 * instance ready to use. If not ready, does nothing.
325 */
326 public void refreshPublicShareFromDB() {
327 if (((FileActivity) mListener).getStorageManager() != null) {
328 // Get public share
329 mPublicShare = ((FileActivity) mListener).getStorageManager().getFirstShareByPathAndType(
330 mFile.getRemotePath(),
331 ShareType.PUBLIC_LINK,
332 ""
333 );
334
335 // Update list of users/groups
336 updatePublicShareSection();
337 }
338 }
339
340 /**
341 * Updates in the UI the section about public share with the information in the current
342 * public share bound to mFile, if any
343 */
344 private void updatePublicShareSection() {
345 if (mPublicShare != null && ShareType.PUBLIC_LINK.equals(mPublicShare.getShareType())) {
346 // public share bound -> expand section
347 getShareViaLinkSwitch().setChecked(true);
348 getExpirationDateSection().setVisibility(View.VISIBLE);
349 getPasswordSection().setVisibility(View.VISIBLE);
350 getGetLinkButton().setVisibility(View.VISIBLE);
351
352 } else {
353 // no public share -> collapse section
354 getShareViaLinkSwitch().setChecked(false);
355 getExpirationDateSection().setVisibility(View.GONE);
356 getPasswordSection().setVisibility(View.GONE);
357 getGetLinkButton().setVisibility(View.GONE);
358 }
359 }
360
361 private Switch getShareViaLinkSwitch() {
362 return (Switch) getView().findViewById(R.id.shareViaLinkSectionSwitch);
363 }
364
365 private View getExpirationDateSection() {
366 return getView().findViewById(R.id.shareViaLinkExpirationSection);
367 }
368
369 private TextView getExpirationDateValue() {
370 return (TextView) getView().findViewById(R.id.shareViaLinkExpirationValue);
371 }
372
373 private View getPasswordSection() {
374 return getView().findViewById(R.id.shareViaLinkPasswordSection);
375 }
376
377 private TextView getExpirationPasswordValue() {
378 return (TextView) getView().findViewById(R.id.shareViaLinkPasswordValue);
379 }
380
381 private AppCompatButton getGetLinkButton() {
382 return (AppCompatButton) getView().findViewById(R.id.shareViewLinkGetLinkButton);
383 }
384
385
386 /**
387 * This interface must be implemented by activities that contain this
388 * fragment to allow an interaction in this fragment to be communicated
389 * to the activity and potentially other fragments contained in that
390 * activity.
391 * <p/>
392 * See the Android Training lesson <a href=
393 * "http://developer.android.com/training/basics/fragments/communicating.html"
394 * >Communicating with Other Fragments</a> for more information.
395 */
396 public interface OnShareFragmentInteractionListener {
397 void showSearchUsersAndGroups();
398 void refreshUsersOrGroupsListFromServer();
399 void unshareWith(OCShare share);
400 }
401
402 }