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