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