PreviewImageFragment.java 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /* ownCloud Android client application
  2. * Copyright (C) 2012-2013 ownCloud Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. */
  18. package com.owncloud.android.ui.preview;
  19. import java.io.File;
  20. import java.lang.ref.WeakReference;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import android.accounts.Account;
  24. import android.annotation.SuppressLint;
  25. import android.app.Activity;
  26. import android.content.ActivityNotFoundException;
  27. import android.content.Intent;
  28. import android.graphics.Bitmap;
  29. import android.graphics.BitmapFactory;
  30. import android.graphics.BitmapFactory.Options;
  31. import android.graphics.Point;
  32. import android.net.Uri;
  33. import android.os.AsyncTask;
  34. import android.os.Bundle;
  35. import android.os.Handler;
  36. import android.support.v4.app.FragmentStatePagerAdapter;
  37. import android.util.Log;
  38. import android.view.Display;
  39. import android.view.LayoutInflater;
  40. import android.view.View;
  41. import android.view.View.OnTouchListener;
  42. import android.view.ViewGroup;
  43. import android.webkit.MimeTypeMap;
  44. import android.widget.ImageView;
  45. import android.widget.ProgressBar;
  46. import android.widget.TextView;
  47. import android.widget.Toast;
  48. import com.actionbarsherlock.app.SherlockFragment;
  49. import com.actionbarsherlock.view.Menu;
  50. import com.actionbarsherlock.view.MenuInflater;
  51. import com.actionbarsherlock.view.MenuItem;
  52. import com.owncloud.android.datamodel.FileDataStorageManager;
  53. import com.owncloud.android.datamodel.OCFile;
  54. import com.owncloud.android.network.OwnCloudClientUtils;
  55. import com.owncloud.android.operations.OnRemoteOperationListener;
  56. import com.owncloud.android.operations.RemoteOperation;
  57. import com.owncloud.android.operations.RemoteOperationResult;
  58. import com.owncloud.android.operations.RemoveFileOperation;
  59. import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
  60. import com.owncloud.android.ui.fragment.FileFragment;
  61. import com.owncloud.android.R;
  62. import eu.alefzero.webdav.WebdavClient;
  63. import eu.alefzero.webdav.WebdavUtils;
  64. /**
  65. * This fragment shows a preview of a downloaded image.
  66. *
  67. * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will produce an {@link IllegalStateException}.
  68. *
  69. * If the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on instantiation too.
  70. *
  71. * @author David A. Velasco
  72. */
  73. public class PreviewImageFragment extends SherlockFragment implements FileFragment,
  74. OnRemoteOperationListener,
  75. ConfirmationDialogFragment.ConfirmationDialogFragmentListener {
  76. public static final String EXTRA_FILE = "FILE";
  77. public static final String EXTRA_ACCOUNT = "ACCOUNT";
  78. private View mView;
  79. private OCFile mFile;
  80. private Account mAccount;
  81. private FileDataStorageManager mStorageManager;
  82. private ImageView mImageView;
  83. private TextView mMessageView;
  84. private ProgressBar mProgressWheel;
  85. public Bitmap mBitmap = null;
  86. private Handler mHandler;
  87. private RemoteOperation mLastRemoteOperation;
  88. private static final String TAG = PreviewImageFragment.class.getSimpleName();
  89. private boolean mIgnoreFirstSavedState;
  90. /**
  91. * Creates a fragment to preview an image.
  92. *
  93. * When 'imageFile' or 'ocAccount' are null
  94. *
  95. * @param imageFile An {@link OCFile} to preview as an image in the fragment
  96. * @param ocAccount An ownCloud account; needed to start downloads
  97. * @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStatePagerAdapter}; TODO better solution
  98. */
  99. public PreviewImageFragment(OCFile fileToDetail, Account ocAccount, boolean ignoreFirstSavedState) {
  100. mFile = fileToDetail;
  101. mAccount = ocAccount;
  102. mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
  103. mIgnoreFirstSavedState = ignoreFirstSavedState;
  104. }
  105. /**
  106. * Creates an empty fragment for image previews.
  107. *
  108. * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically (for instance, when the device is turned a aside).
  109. *
  110. * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful construction
  111. */
  112. public PreviewImageFragment() {
  113. mFile = null;
  114. mAccount = null;
  115. mStorageManager = null;
  116. mIgnoreFirstSavedState = false;
  117. }
  118. /**
  119. * {@inheritDoc}
  120. */
  121. @Override
  122. public void onCreate(Bundle savedInstanceState) {
  123. super.onCreate(savedInstanceState);
  124. mHandler = new Handler();
  125. setHasOptionsMenu(true);
  126. }
  127. /**
  128. * {@inheritDoc}
  129. */
  130. @Override
  131. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  132. Bundle savedInstanceState) {
  133. super.onCreateView(inflater, container, savedInstanceState);
  134. mView = inflater.inflate(R.layout.preview_image_fragment, container, false);
  135. mImageView = (ImageView)mView.findViewById(R.id.image);
  136. mImageView.setVisibility(View.GONE);
  137. mView.setOnTouchListener((OnTouchListener)getActivity()); // WATCH OUT THAT CAST
  138. mMessageView = (TextView)mView.findViewById(R.id.message);
  139. mMessageView.setVisibility(View.GONE);
  140. mProgressWheel = (ProgressBar)mView.findViewById(R.id.progressWheel);
  141. mProgressWheel.setVisibility(View.VISIBLE);
  142. return mView;
  143. }
  144. /**
  145. * {@inheritDoc}
  146. */
  147. @Override
  148. public void onAttach(Activity activity) {
  149. super.onAttach(activity);
  150. if (!(activity instanceof FileFragment.ContainerActivity))
  151. throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
  152. }
  153. /**
  154. * {@inheritDoc}
  155. */
  156. @Override
  157. public void onActivityCreated(Bundle savedInstanceState) {
  158. super.onActivityCreated(savedInstanceState);
  159. mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
  160. if (savedInstanceState != null) {
  161. if (!mIgnoreFirstSavedState) {
  162. mFile = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE);
  163. mAccount = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_ACCOUNT);
  164. } else {
  165. mIgnoreFirstSavedState = false;
  166. }
  167. }
  168. if (mFile == null) {
  169. throw new IllegalStateException("Instanced with a NULL OCFile");
  170. }
  171. if (mAccount == null) {
  172. throw new IllegalStateException("Instanced with a NULL ownCloud Account");
  173. }
  174. if (!mFile.isDown()) {
  175. throw new IllegalStateException("There is no local file to preview");
  176. }
  177. }
  178. /**
  179. * {@inheritDoc}
  180. */
  181. @Override
  182. public void onSaveInstanceState(Bundle outState) {
  183. super.onSaveInstanceState(outState);
  184. outState.putParcelable(PreviewImageFragment.EXTRA_FILE, mFile);
  185. outState.putParcelable(PreviewImageFragment.EXTRA_ACCOUNT, mAccount);
  186. }
  187. @Override
  188. public void onStart() {
  189. super.onStart();
  190. if (mFile != null) {
  191. BitmapLoader bl = new BitmapLoader(mImageView, mMessageView, mProgressWheel);
  192. bl.execute(new String[]{mFile.getStoragePath()});
  193. }
  194. }
  195. /**
  196. * {@inheritDoc}
  197. */
  198. @Override
  199. public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
  200. super.onCreateOptionsMenu(menu, inflater);
  201. inflater.inflate(R.menu.file_actions_menu, menu);
  202. List<Integer> toHide = new ArrayList<Integer>();
  203. MenuItem item = null;
  204. toHide.add(R.id.action_cancel_download);
  205. toHide.add(R.id.action_cancel_upload);
  206. toHide.add(R.id.action_download_file);
  207. toHide.add(R.id.action_rename_file); // by now
  208. for (int i : toHide) {
  209. item = menu.findItem(i);
  210. if (item != null) {
  211. item.setVisible(false);
  212. item.setEnabled(false);
  213. }
  214. }
  215. }
  216. /**
  217. * {@inheritDoc}
  218. */
  219. @Override
  220. public boolean onOptionsItemSelected(MenuItem item) {
  221. switch (item.getItemId()) {
  222. case R.id.action_open_file_with: {
  223. openFile();
  224. return true;
  225. }
  226. case R.id.action_remove_file: {
  227. removeFile();
  228. return true;
  229. }
  230. case R.id.action_see_details: {
  231. seeDetails();
  232. return true;
  233. }
  234. default:
  235. return false;
  236. }
  237. }
  238. private void seeDetails() {
  239. ((FileFragment.ContainerActivity)getActivity()).showFragmentWithDetails(mFile);
  240. }
  241. @Override
  242. public void onResume() {
  243. super.onResume();
  244. //Log.e(TAG, "FRAGMENT, ONRESUME");
  245. /*
  246. mDownloadFinishReceiver = new DownloadFinishReceiver();
  247. IntentFilter filter = new IntentFilter(
  248. FileDownloader.DOWNLOAD_FINISH_MESSAGE);
  249. getActivity().registerReceiver(mDownloadFinishReceiver, filter);
  250. mUploadFinishReceiver = new UploadFinishReceiver();
  251. filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
  252. getActivity().registerReceiver(mUploadFinishReceiver, filter);
  253. */
  254. }
  255. @Override
  256. public void onPause() {
  257. super.onPause();
  258. /*
  259. if (mVideoPreview.getVisibility() == View.VISIBLE) {
  260. mSavedPlaybackPosition = mVideoPreview.getCurrentPosition();
  261. }*/
  262. /*
  263. getActivity().unregisterReceiver(mDownloadFinishReceiver);
  264. mDownloadFinishReceiver = null;
  265. getActivity().unregisterReceiver(mUploadFinishReceiver);
  266. mUploadFinishReceiver = null;
  267. */
  268. }
  269. @Override
  270. public void onDestroy() {
  271. super.onDestroy();
  272. if (mBitmap != null) {
  273. mBitmap.recycle();
  274. }
  275. }
  276. /**
  277. * Opens the previewed image with an external application.
  278. *
  279. * TODO - improve this; instead of prioritize the actions available for the MIME type in the server,
  280. * we should get a list of available apps for MIME tpye in the server and join it with the list of
  281. * available apps for the MIME type known from the file extension, to let the user choose
  282. */
  283. private void openFile() {
  284. String storagePath = mFile.getStoragePath();
  285. String encodedStoragePath = WebdavUtils.encodePath(storagePath);
  286. try {
  287. Intent i = new Intent(Intent.ACTION_VIEW);
  288. i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
  289. i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  290. startActivity(i);
  291. } catch (Throwable t) {
  292. Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
  293. boolean toastIt = true;
  294. String mimeType = "";
  295. try {
  296. Intent i = new Intent(Intent.ACTION_VIEW);
  297. mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
  298. if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
  299. if (mimeType != null) {
  300. i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
  301. } else {
  302. // desperate try
  303. i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*-/*");
  304. }
  305. i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  306. startActivity(i);
  307. toastIt = false;
  308. }
  309. } catch (IndexOutOfBoundsException e) {
  310. Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
  311. } catch (ActivityNotFoundException e) {
  312. Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
  313. } catch (Throwable th) {
  314. Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
  315. } finally {
  316. if (toastIt) {
  317. Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
  318. }
  319. }
  320. }
  321. finish();
  322. }
  323. /**
  324. * Starts a the removal of the previewed file.
  325. *
  326. * Shows a confirmation dialog. The action continues in {@link #onConfirmation(String)} , {@link #onNeutral(String)} or {@link #onCancel(String)},
  327. * depending upon the user selection in the dialog.
  328. */
  329. private void removeFile() {
  330. ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
  331. R.string.confirmation_remove_alert,
  332. new String[]{mFile.getFileName()},
  333. R.string.confirmation_remove_remote_and_local,
  334. R.string.confirmation_remove_local,
  335. R.string.common_cancel);
  336. confDialog.setOnConfirmationListener(this);
  337. confDialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
  338. }
  339. /**
  340. * Performs the removal of the previewed file, both locally and in the server.
  341. */
  342. @Override
  343. public void onConfirmation(String callerTag) {
  344. if (mStorageManager.getFileById(mFile.getFileId()) != null) { // check that the file is still there;
  345. mLastRemoteOperation = new RemoveFileOperation( mFile, // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
  346. true,
  347. mStorageManager);
  348. WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
  349. mLastRemoteOperation.execute(wc, this, mHandler);
  350. getActivity().showDialog(PreviewImageActivity.DIALOG_SHORT_WAIT);
  351. }
  352. }
  353. /**
  354. * Removes the file from local storage
  355. */
  356. @Override
  357. public void onNeutral(String callerTag) {
  358. // TODO this code should be made in a secondary thread,
  359. if (mFile.isDown()) { // checks it is still there
  360. File f = new File(mFile.getStoragePath());
  361. f.delete();
  362. mFile.setStoragePath(null);
  363. mStorageManager.saveFile(mFile);
  364. finish();
  365. }
  366. }
  367. /**
  368. * User cancelled the removal action.
  369. */
  370. @Override
  371. public void onCancel(String callerTag) {
  372. // nothing to do here
  373. }
  374. /**
  375. * {@inheritDoc}
  376. */
  377. public OCFile getFile(){
  378. return mFile;
  379. }
  380. /*
  381. /**
  382. * Use this method to signal this Activity that it shall update its view.
  383. *
  384. * @param file : An {@link OCFile}
  385. *-/
  386. public void updateFileDetails(OCFile file, Account ocAccount) {
  387. mFile = file;
  388. if (ocAccount != null && (
  389. mStorageManager == null ||
  390. (mAccount != null && !mAccount.equals(ocAccount))
  391. )) {
  392. mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());
  393. }
  394. mAccount = ocAccount;
  395. updateFileDetails(false);
  396. }
  397. */
  398. private class BitmapLoader extends AsyncTask<String, Void, Bitmap> {
  399. /**
  400. * Weak reference to the target {@link ImageView} where the bitmap will be loaded into.
  401. *
  402. * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes.
  403. */
  404. private final WeakReference<ImageView> mImageViewRef;
  405. /**
  406. * Weak reference to the target {@link TextView} where error messages will be written.
  407. *
  408. * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes.
  409. */
  410. private final WeakReference<TextView> mMessageViewRef;
  411. /**
  412. * Weak reference to the target {@link Progressbar} shown while the load is in progress.
  413. *
  414. * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes.
  415. */
  416. private final WeakReference<ProgressBar> mProgressWheelRef;
  417. /**
  418. * Error message to show when a load fails
  419. */
  420. private int mErrorMessageId;
  421. /**
  422. * Constructor.
  423. *
  424. * @param imageView Target {@link ImageView} where the bitmap will be loaded into.
  425. */
  426. public BitmapLoader(ImageView imageView, TextView messageView, ProgressBar progressWheel) {
  427. mImageViewRef = new WeakReference<ImageView>(imageView);
  428. mMessageViewRef = new WeakReference<TextView>(messageView);
  429. mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
  430. }
  431. @SuppressWarnings("deprecation")
  432. @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20
  433. @Override
  434. protected Bitmap doInBackground(String... params) {
  435. Bitmap result = null;
  436. if (params.length != 1) return result;
  437. String storagePath = params[0];
  438. try {
  439. // set desired options that will affect the size of the bitmap
  440. BitmapFactory.Options options = new Options();
  441. options.inScaled = true;
  442. options.inPurgeable = true;
  443. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
  444. options.inPreferQualityOverSpeed = false;
  445. }
  446. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
  447. options.inMutable = false;
  448. }
  449. // make a false load of the bitmap - just to be able to read outWidth, outHeight and outMimeType
  450. options.inJustDecodeBounds = true;
  451. BitmapFactory.decodeFile(storagePath, options);
  452. int width = options.outWidth;
  453. int height = options.outHeight;
  454. int scale = 1;
  455. Display display = getActivity().getWindowManager().getDefaultDisplay();
  456. Point size = new Point();
  457. int screenWidth;
  458. int screenHeight;
  459. if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
  460. display.getSize(size);
  461. screenWidth = size.x;
  462. screenHeight = size.y;
  463. } else {
  464. screenWidth = display.getWidth();
  465. screenHeight = display.getHeight();
  466. }
  467. if (width > screenWidth) {
  468. // second try to scale down the image , this time depending upon the screen size
  469. scale = (int) Math.floor((float)width / screenWidth);
  470. }
  471. if (height > screenHeight) {
  472. scale = Math.max(scale, (int) Math.floor((float)height / screenHeight));
  473. }
  474. options.inSampleSize = scale;
  475. // really load the bitmap
  476. options.inJustDecodeBounds = false; // the next decodeFile call will be real
  477. result = BitmapFactory.decodeFile(storagePath, options);
  478. //Log.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
  479. if (result == null) {
  480. mErrorMessageId = R.string.preview_image_error_unknown_format;
  481. Log.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
  482. }
  483. } catch (OutOfMemoryError e) {
  484. mErrorMessageId = R.string.preview_image_error_unknown_format;
  485. Log.e(TAG, "Out of memory occured for file " + storagePath, e);
  486. } catch (NoSuchFieldError e) {
  487. mErrorMessageId = R.string.common_error_unknown;
  488. Log.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e);
  489. } catch (Throwable t) {
  490. mErrorMessageId = R.string.common_error_unknown;
  491. Log.e(TAG, "Unexpected error loading " + mFile.getStoragePath(), t);
  492. }
  493. return result;
  494. }
  495. @Override
  496. protected void onPostExecute(Bitmap result) {
  497. hideProgressWheel();
  498. if (result != null) {
  499. showLoadedImage(result);
  500. } else {
  501. showErrorMessage();
  502. }
  503. }
  504. private void showLoadedImage(Bitmap result) {
  505. if (mImageViewRef != null) {
  506. final ImageView imageView = mImageViewRef.get();
  507. if (imageView != null) {
  508. imageView.setImageBitmap(result);
  509. imageView.setVisibility(View.VISIBLE);
  510. mBitmap = result;
  511. } // else , silently finish, the fragment was destroyed
  512. }
  513. if (mMessageViewRef != null) {
  514. final TextView messageView = mMessageViewRef.get();
  515. if (messageView != null) {
  516. messageView.setVisibility(View.GONE);
  517. } // else , silently finish, the fragment was destroyed
  518. }
  519. }
  520. private void showErrorMessage() {
  521. if (mImageViewRef != null) {
  522. final ImageView imageView = mImageViewRef.get();
  523. if (imageView != null) {
  524. // shows the default error icon
  525. imageView.setVisibility(View.VISIBLE);
  526. } // else , silently finish, the fragment was destroyed
  527. }
  528. if (mMessageViewRef != null) {
  529. final TextView messageView = mMessageViewRef.get();
  530. if (messageView != null) {
  531. messageView.setText(mErrorMessageId);
  532. messageView.setVisibility(View.VISIBLE);
  533. } // else , silently finish, the fragment was destroyed
  534. }
  535. }
  536. private void hideProgressWheel() {
  537. if (mProgressWheelRef != null) {
  538. final ProgressBar progressWheel = mProgressWheelRef.get();
  539. if (progressWheel != null) {
  540. progressWheel.setVisibility(View.GONE);
  541. }
  542. }
  543. }
  544. }
  545. /**
  546. * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment} to be previewed.
  547. *
  548. * @param file File to test if can be previewed.
  549. * @return 'True' if the file can be handled by the fragment.
  550. */
  551. public static boolean canBePreviewed(OCFile file) {
  552. return (file != null && file.isImage());
  553. }
  554. /**
  555. * {@inheritDoc}
  556. */
  557. @Override
  558. public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
  559. if (operation.equals(mLastRemoteOperation) && operation instanceof RemoveFileOperation) {
  560. onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
  561. }
  562. }
  563. private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
  564. getActivity().dismissDialog(PreviewImageActivity.DIALOG_SHORT_WAIT);
  565. if (result.isSuccess()) {
  566. Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG);
  567. msg.show();
  568. finish();
  569. } else {
  570. Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG);
  571. msg.show();
  572. if (result.isSslRecoverableException()) {
  573. // TODO show the SSL warning dialog
  574. }
  575. }
  576. }
  577. /**
  578. * Finishes the preview
  579. */
  580. private void finish() {
  581. Activity container = getActivity();
  582. container.finish();
  583. }
  584. }