a7c7a5d6608b7811c344a91a003db6e039920cde
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / fragment / OCFileListFragment.java
1 /**
2 * ownCloud Android client application
3 *
4 * @author Bartek Przybylski
5 * @author masensio
6 * @author David A. Velasco
7 * Copyright (C) 2011 Bartek Przybylski
8 * Copyright (C) 2015 ownCloud Inc.
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23 package com.owncloud.android.ui.fragment;
24
25 import android.app.Activity;
26 import android.content.Intent;
27 import android.content.SharedPreferences;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.preference.PreferenceManager;
31 import android.support.v4.widget.SwipeRefreshLayout;
32 import android.view.ContextMenu;
33 import android.view.Menu;
34 import android.view.MenuInflater;
35 import android.view.MenuItem;
36 import android.view.View;
37 import android.widget.AdapterView;
38 import android.widget.AdapterView.AdapterContextMenuInfo;
39 import android.widget.PopupMenu;
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.FileDataStorageManager;
46 import com.owncloud.android.datamodel.OCFile;
47 import com.owncloud.android.files.FileMenuFilter;
48 import com.owncloud.android.lib.common.utils.Log_OC;
49 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
50 import com.owncloud.android.ui.activity.FileActivity;
51 import com.owncloud.android.ui.activity.FileDisplayActivity;
52 import com.owncloud.android.ui.activity.FolderPickerActivity;
53 import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
54 import com.owncloud.android.ui.activity.UploadFilesActivity;
55 import com.owncloud.android.ui.adapter.FileListListAdapter;
56 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
57 import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
58 import com.owncloud.android.ui.dialog.FileActionsDialogFragment;
59 import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
60 import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
61 import com.owncloud.android.ui.dialog.UploadSourceDialogFragment;
62 import com.owncloud.android.ui.preview.PreviewImageFragment;
63 import com.owncloud.android.ui.preview.PreviewMediaFragment;
64 import com.owncloud.android.utils.FileStorageUtils;
65 import com.owncloud.android.ui.preview.PreviewTextFragment;
66
67 import java.io.File;
68
69 /**
70 * A Fragment that lists all files and folders in a given path.
71 *
72 * TODO refactor to get rid of direct dependency on FileDisplayActivity
73 */
74 public class OCFileListFragment extends ExtendedListFragment implements FileActionsDialogFragment.FileActionsDialogFragmentListener {
75
76 private static final String TAG = OCFileListFragment.class.getSimpleName();
77
78 private static final String MY_PACKAGE = OCFileListFragment.class.getPackage() != null ?
79 OCFileListFragment.class.getPackage().getName() : "com.owncloud.android.ui.fragment";
80
81 public final static String ARG_JUST_FOLDERS = MY_PACKAGE + ".JUST_FOLDERS";
82 public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL";
83
84 private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
85 private static final String KEY_FAB_EVER_CLICKED = "FAB_EVER_CLICKED";
86
87 private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER";
88
89 private FileFragment.ContainerActivity mContainerActivity;
90
91 private OCFile mFile = null;
92 private FileListListAdapter mAdapter;
93 private boolean mJustFolders;
94
95 private OCFile mTargetFile;
96
97 private boolean miniFabClicked = false;
98
99 /**
100 * {@inheritDoc}
101 */
102 @Override
103 public void onAttach(Activity activity) {
104 super.onAttach(activity);
105 Log_OC.e(TAG, "onAttach");
106 try {
107 mContainerActivity = (FileFragment.ContainerActivity) activity;
108
109 } catch (ClassCastException e) {
110 throw new ClassCastException(activity.toString() + " must implement " +
111 FileFragment.ContainerActivity.class.getSimpleName());
112 }
113 try {
114 setOnRefreshListener((OnEnforceableRefreshListener) activity);
115
116 } catch (ClassCastException e) {
117 throw new ClassCastException(activity.toString() + " must implement " +
118 SwipeRefreshLayout.OnRefreshListener.class.getSimpleName());
119 }
120 }
121
122
123 @Override
124 public void onDetach() {
125 setOnRefreshListener(null);
126 mContainerActivity = null;
127 super.onDetach();
128 }
129
130 /**
131 * {@inheritDoc}
132 */
133 @Override
134 public void onActivityCreated(Bundle savedInstanceState) {
135 super.onActivityCreated(savedInstanceState);
136 Log_OC.e(TAG, "onActivityCreated() start");
137
138 if (savedInstanceState != null) {
139 mFile = savedInstanceState.getParcelable(KEY_FILE);
140 }
141
142 if (mJustFolders) {
143 setFooterEnabled(false);
144 } else {
145 setFooterEnabled(true);
146 }
147
148 Bundle args = getArguments();
149 mJustFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false);
150 mAdapter = new FileListListAdapter(
151 mJustFolders,
152 getActivity(),
153 mContainerActivity
154 );
155 setListAdapter(mAdapter);
156
157 registerLongClickListener();
158 registerFabListeners();
159
160 // detect if a mini FAB has ever been clicked
161 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
162 if(prefs.getLong(KEY_FAB_EVER_CLICKED, 0) > 0) {
163 miniFabClicked = true;
164 }
165
166 // add labels to the min FABs when none of them has ever been clicked on
167 if(!miniFabClicked) {
168 setFabLabels();
169 } else {
170 removeFabLabels();
171 }
172 }
173
174 /**
175 * adds labels to all mini FABs.
176 */
177 private void setFabLabels() {
178 getFabUpload().setTitle(getResources().getString(R.string.actionbar_upload));
179 getFabMkdir().setTitle(getResources().getString(R.string.actionbar_mkdir));
180 getFabUploadFromApp().setTitle(getResources().getString(R.string.actionbar_upload_from_apps));
181 }
182
183 /**
184 * registers all listeners on all mini FABs.
185 */
186 private void registerFabListeners() {
187 registerFabUploadListeners();
188 registerFabMkDirListeners();
189 registerFabUploadFromAppListeners();
190 }
191
192 /**
193 * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
194 * on the Upload mini FAB for the linked action and {@link Toast} showing the underlying action.
195 */
196 private void registerFabUploadListeners() {
197 getFabUpload().setOnClickListener(new View.OnClickListener() {
198 @Override
199 public void onClick(View v) {
200 Intent action = new Intent(getActivity(), UploadFilesActivity.class);
201 action.putExtra(
202 UploadFilesActivity.EXTRA_ACCOUNT,
203 ((FileActivity) getActivity()).getAccount()
204 );
205 getActivity().startActivityForResult(action, UploadSourceDialogFragment.ACTION_SELECT_MULTIPLE_FILES);
206 getFabMain().collapse();
207 recordMiniFabClick();
208 }
209 });
210
211 getFabUpload().setOnLongClickListener(new View.OnLongClickListener() {
212 @Override
213 public boolean onLongClick(View v) {
214 Toast.makeText(getActivity(), R.string.actionbar_upload, Toast.LENGTH_SHORT).show();
215 return true;
216 }
217 });
218 }
219
220 /**
221 * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
222 * on the 'Create Dir' mini FAB for the linked action and {@link Toast} showing the underlying action.
223 */
224 private void registerFabMkDirListeners() {
225 getFabMkdir().setOnClickListener(new View.OnClickListener() {
226 @Override
227 public void onClick(View v) {
228 CreateFolderDialogFragment dialog =
229 CreateFolderDialogFragment.newInstance(mFile);
230 dialog.show(getActivity().getSupportFragmentManager(), FileDisplayActivity.DIALOG_CREATE_FOLDER);
231 getFabMain().collapse();
232 recordMiniFabClick();
233 }
234 });
235
236 getFabMkdir().setOnLongClickListener(new View.OnLongClickListener() {
237 @Override
238 public boolean onLongClick(View v) {
239 Toast.makeText(getActivity(), R.string.actionbar_mkdir, Toast.LENGTH_SHORT).show();
240 return true;
241 }
242 });
243 }
244
245 /**
246 * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
247 * on the Upload from App mini FAB for the linked action and {@link Toast} showing the underlying action.
248 */
249 private void registerFabUploadFromAppListeners() {
250 getFabUploadFromApp().setOnClickListener(new View.OnClickListener() {
251 @Override
252 public void onClick(View v) {
253 Intent action = new Intent(Intent.ACTION_GET_CONTENT);
254 action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
255
256 //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean
257 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
258 action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
259 }
260
261 getActivity().startActivityForResult(
262 Intent.createChooser(action, getString(R.string.upload_chooser_title)),
263 UploadSourceDialogFragment.ACTION_SELECT_CONTENT_FROM_APPS
264 );
265 getFabMain().collapse();
266 recordMiniFabClick();
267 }
268 });
269
270 getFabUploadFromApp().setOnLongClickListener(new View.OnLongClickListener() {
271 @Override
272 public boolean onLongClick(View v) {
273 Toast.makeText(getActivity(),
274 R.string.actionbar_upload_from_apps,
275 Toast.LENGTH_SHORT).show();
276 return true;
277 }
278 });
279 }
280
281 /**
282 * records a click on a mini FAB and thus:
283 * <ol>
284 * <li>persists the click fact</li>
285 * <li>removes the mini FAB labels</li>
286 * </ol>
287 */
288 private void recordMiniFabClick() {
289 // only record if it hasn't been done already at some other time
290 if(!miniFabClicked) {
291 final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
292 sp.edit().putLong(KEY_FAB_EVER_CLICKED, 1).commit();
293 miniFabClicked = true;
294 }
295 }
296
297 /**
298 * removes the labels on all known min FABs.
299 */
300 private void removeFabLabels() {
301 getFabUpload().setTitle(null);
302 getFabMkdir().setTitle(null);
303 getFabUploadFromApp().setTitle(null);
304 ((TextView) getFabUpload().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
305 ((TextView) getFabMkdir().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
306 ((TextView) getFabUploadFromApp().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
307 }
308
309 private void registerLongClickListener() {
310 getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
311 public boolean onItemLongClick(AdapterView<?> arg0, View v,
312 int index, long arg3) {
313 showFileAction(index);
314 return true;
315 }
316 });
317 }
318
319 private void showFileAction(int fileIndex) {
320 Bundle args = getArguments();
321 PopupMenu pm = new PopupMenu(getActivity(),null);
322 Menu menu = pm.getMenu();
323
324 boolean allowContextualActions =
325 (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
326
327 if (allowContextualActions) {
328 MenuInflater inflater = getActivity().getMenuInflater();
329
330 inflater.inflate(R.menu.file_actions_menu, menu);
331 OCFile targetFile = (OCFile) mAdapter.getItem(fileIndex);
332
333 if (mContainerActivity.getStorageManager() != null) {
334 FileMenuFilter mf = new FileMenuFilter(
335 targetFile,
336 mContainerActivity.getStorageManager().getAccount(),
337 mContainerActivity,
338 getActivity()
339 );
340 mf.filter(menu);
341 }
342
343 /// TODO break this direct dependency on FileDisplayActivity... if possible
344 MenuItem item = menu.findItem(R.id.action_open_file_with);
345 FileFragment frag = ((FileDisplayActivity)getActivity()).getSecondFragment();
346 if (frag != null && frag instanceof FileDetailFragment &&
347 frag.getFile().getFileId() == targetFile.getFileId()) {
348 item = menu.findItem(R.id.action_see_details);
349 if (item != null) {
350 item.setVisible(false);
351 item.setEnabled(false);
352 }
353 }
354
355 FileActionsDialogFragment dialog = FileActionsDialogFragment.newInstance(menu, fileIndex, targetFile.getFileName());
356 dialog.setTargetFragment(this, 0);
357 dialog.show(getFragmentManager(), FileActionsDialogFragment.FTAG_FILE_ACTIONS);
358 }
359 }
360
361 /**
362 * Saves the current listed folder.
363 */
364 @Override
365 public void onSaveInstanceState(Bundle outState) {
366 super.onSaveInstanceState(outState);
367 outState.putParcelable(KEY_FILE, mFile);
368 }
369
370 /**
371 * Call this, when the user presses the up button.
372 * <p>
373 * Tries to move up the current folder one level. If the parent folder was removed from the
374 * database, it continues browsing up until finding an existing folders.
375 * </p>
376 * @return Count of folder levels browsed up.
377 */
378 public int onBrowseUp() {
379 OCFile parentDir = null;
380 int moveCount = 0;
381
382 if (mFile != null) {
383 FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
384
385 String parentPath = null;
386 if (mFile.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) {
387 parentPath = new File(mFile.getRemotePath()).getParent();
388 parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :
389 parentPath + OCFile.PATH_SEPARATOR;
390 parentDir = storageManager.getFileByPath(parentPath);
391 moveCount++;
392 } else {
393 parentDir = storageManager.getFileByPath(OCFile.ROOT_PATH);
394 }
395 while (parentDir == null) {
396 parentPath = new File(parentPath).getParent();
397 parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :
398 parentPath + OCFile.PATH_SEPARATOR;
399 parentDir = storageManager.getFileByPath(parentPath);
400 moveCount++;
401 } // exit is granted because storageManager.getFileByPath("/") never returns null
402 mFile = parentDir;
403
404 // TODO Enable when "On Device" is recovered ?
405 listDirectory(mFile /*, MainApp.getOnlyOnDevice()*/);
406
407 onRefresh(false);
408
409 // restore index and top position
410 restoreIndexAndTopPosition();
411
412 } // else - should never happen now
413
414 return moveCount;
415 }
416
417 @Override
418 public void onItemClick(AdapterView<?> l, View v, int position, long id) {
419 OCFile file = (OCFile) mAdapter.getItem(position);
420 if (file != null) {
421 if (file.isFolder()) {
422 // update state and view of this fragment
423 // TODO Enable when "On Device" is recovered ?
424 listDirectory(file/*, MainApp.getOnlyOnDevice()*/);
425 // then, notify parent activity to let it update its state and view
426 mContainerActivity.onBrowsedDownTo(file);
427 // save index and top position
428 saveIndexAndTopPosition(position);
429
430 } else { /// Click on a file
431 if (PreviewImageFragment.canBePreviewed(file)) {
432 // preview image - it handles the download, if needed
433 ((FileDisplayActivity)mContainerActivity).startImagePreview(file);
434 } else if (PreviewTextFragment.canBePreviewed(file)){
435 ((FileDisplayActivity)mContainerActivity).startTextPreview(file);
436 } else if (file.isDown()) {
437 if (PreviewMediaFragment.canBePreviewed(file)) {
438 // media preview
439 ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true);
440 } else {
441 mContainerActivity.getFileOperationsHelper().openFile(file);
442 }
443
444 } else {
445 // automatic download, preview on finish
446 ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file);
447 }
448
449 }
450
451 } else {
452 Log_OC.d(TAG, "Null object in ListAdapter!!");
453 }
454
455 }
456
457 /**
458 * {@inheritDoc}
459 */
460 @Override
461 public void onCreateContextMenu(
462 ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
463 Bundle args = getArguments();
464 boolean allowContextualActions =
465 (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
466 if (allowContextualActions) {
467 MenuInflater inflater = getActivity().getMenuInflater();
468 inflater.inflate(R.menu.file_actions_menu, menu);
469 AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
470 OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
471
472 if (mContainerActivity.getStorageManager() != null) {
473 FileMenuFilter mf = new FileMenuFilter(
474 targetFile,
475 mContainerActivity.getStorageManager().getAccount(),
476 mContainerActivity,
477 getActivity()
478 );
479 mf.filter(menu);
480 }
481
482 /// TODO break this direct dependency on FileDisplayActivity... if possible
483 MenuItem item = menu.findItem(R.id.action_open_file_with);
484 FileFragment frag = ((FileDisplayActivity)getActivity()).getSecondFragment();
485 if (frag != null && frag instanceof FileDetailFragment &&
486 frag.getFile().getFileId() == targetFile.getFileId()) {
487 item = menu.findItem(R.id.action_see_details);
488 if (item != null) {
489 item.setVisible(false);
490 item.setEnabled(false);
491 }
492 }
493 }
494 }
495
496 /**
497 * {@inheritDoc}
498 */
499 @Override
500 public boolean onFileActionChosen(int menuId, int filePosition) {
501 mTargetFile = (OCFile) mAdapter.getItem(filePosition);
502 switch (menuId) {
503 case R.id.action_share_file: {
504 mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
505 return true;
506 }
507 case R.id.action_open_file_with: {
508 mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
509 return true;
510 }
511 case R.id.action_unshare_file: {
512 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile);
513 return true;
514 }
515 case R.id.action_rename_file: {
516 RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
517 dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);
518 return true;
519 }
520 case R.id.action_remove_file: {
521 RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
522 dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
523 return true;
524 }
525 case R.id.action_download_file:
526 case R.id.action_sync_file: {
527 mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
528 return true;
529 }
530 case R.id.action_cancel_download:
531 case R.id.action_cancel_upload: {
532 ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
533 return true;
534 }
535 case R.id.action_see_details: {
536 mContainerActivity.showDetails(mTargetFile);
537 return true;
538 }
539 case R.id.action_send_file: {
540 // Obtain the file
541 if (!mTargetFile.isDown()) { // Download the file
542 Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
543 ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile);
544
545 } else {
546 mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
547 }
548 return true;
549 }
550 case R.id.action_move: {
551 Intent action = new Intent(getActivity(), FolderPickerActivity.class);
552
553 // Pass mTargetFile that contains info of selected file/folder
554 action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
555 getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
556 return true;
557 }
558 case R.id.action_favorite_file: {
559 mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
560 return true;
561 }
562 case R.id.action_unfavorite_file: {
563 mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
564 return true;
565 }
566 case R.id.action_copy:
567 Intent action = new Intent(getActivity(), FolderPickerActivity.class);
568
569 // Pass mTargetFile that contains info of selected file/folder
570 action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
571 getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
572 return true;
573 default:
574 return false;
575 }
576 }
577
578 /**
579 * {@inhericDoc}
580 */
581 @Override
582 public boolean onContextItemSelected (MenuItem item) {
583 AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
584 boolean matched = onFileActionChosen(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).position);
585 if(!matched) {
586 return super.onContextItemSelected(item);
587 } else {
588 return matched;
589 }
590 }
591
592
593 /**
594 * Use this to query the {@link OCFile} that is currently
595 * being displayed by this fragment
596 *
597 * @return The currently viewed OCFile
598 */
599 public OCFile getCurrentFile() {
600 return mFile;
601 }
602
603 /**
604 * Calls {@link OCFileListFragment#listDirectory(OCFile)} with a null parameter
605 */
606 public void listDirectory(/*boolean onlyOnDevice*/){
607 listDirectory(null);
608 // TODO Enable when "On Device" is recovered ?
609 // listDirectory(null, onlyOnDevice);
610 }
611
612 public void refreshDirectory(){
613 // TODO Enable when "On Device" is recovered ?
614 listDirectory(getCurrentFile()/*, MainApp.getOnlyOnDevice()*/);
615 }
616
617 /**
618 * Lists the given directory on the view. When the input parameter is null,
619 * it will either refresh the last known directory. list the root
620 * if there never was a directory.
621 *
622 * @param directory File to be listed
623 */
624 public void listDirectory(OCFile directory/*, boolean onlyOnDevice*/) {
625 FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
626 if (storageManager != null) {
627
628 // Check input parameters for null
629 if (directory == null) {
630 if (mFile != null) {
631 directory = mFile;
632 } else {
633 directory = storageManager.getFileByPath("/");
634 if (directory == null) return; // no files, wait for sync
635 }
636 }
637
638
639 // If that's not a directory -> List its parent
640 if (!directory.isFolder()) {
641 Log_OC.w(TAG, "You see, that is not a directory -> " + directory.toString());
642 directory = storageManager.getFileById(directory.getParentId());
643 }
644
645 // TODO Enable when "On Device" is recovered ?
646 mAdapter.swapDirectory(directory, storageManager/*, onlyOnDevice*/);
647 if (mFile == null || !mFile.equals(directory)) {
648 mCurrentListView.setSelection(0);
649 }
650 mFile = directory;
651
652 updateLayout();
653
654 }
655 }
656
657 private void updateLayout() {
658 if (!mJustFolders) {
659 int filesCount = 0, foldersCount = 0, imagesCount = 0;
660 int count = mAdapter.getCount();
661 OCFile file;
662 for (int i=0; i < count ; i++) {
663 file = (OCFile) mAdapter.getItem(i);
664 if (file.isFolder()) {
665 foldersCount++;
666 } else {
667 if (!file.isHidden()) {
668 filesCount++;
669
670 if (file.isImage()) {
671 imagesCount++;
672 }
673 }
674 }
675 }
676 // set footer text
677 setFooterText(generateFooterText(filesCount, foldersCount));
678
679 // decide grid vs list view
680 OwnCloudVersion version = AccountUtils.getServerVersion(
681 ((FileActivity)mContainerActivity).getAccount());
682 if (version != null && version.supportsRemoteThumbnails() &&
683 imagesCount > 0 && imagesCount == filesCount) {
684 switchToGridView();
685 registerLongClickListener();
686 } else {
687 switchToListView();
688 }
689 }
690 }
691
692 private String generateFooterText(int filesCount, int foldersCount) {
693 String output;
694 if (filesCount <= 0) {
695 if (foldersCount <= 0) {
696 output = "";
697
698 } else if (foldersCount == 1) {
699 output = getResources().getString(R.string.file_list__footer__folder);
700
701 } else { // foldersCount > 1
702 output = getResources().getString(R.string.file_list__footer__folders, foldersCount);
703 }
704
705 } else if (filesCount == 1) {
706 if (foldersCount <= 0) {
707 output = getResources().getString(R.string.file_list__footer__file);
708
709 } else if (foldersCount == 1) {
710 output = getResources().getString(R.string.file_list__footer__file_and_folder);
711
712 } else { // foldersCount > 1
713 output = getResources().getString(R.string.file_list__footer__file_and_folders, foldersCount);
714 }
715 } else { // filesCount > 1
716 if (foldersCount <= 0) {
717 output = getResources().getString(R.string.file_list__footer__files, filesCount);
718
719 } else if (foldersCount == 1) {
720 output = getResources().getString(R.string.file_list__footer__files_and_folder, filesCount);
721
722 } else { // foldersCount > 1
723 output = getResources().getString(
724 R.string.file_list__footer__files_and_folders, filesCount, foldersCount
725 );
726
727 }
728 }
729 return output;
730 }
731
732 public void sortByName(boolean descending) {
733 mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
734 }
735
736 public void sortByDate(boolean descending) {
737 mAdapter.setSortOrder(FileStorageUtils.SORT_DATE, descending);
738 }
739
740 public void sortBySize(boolean descending) {
741 mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending);
742 }
743 }