FileDisplayActivity.java 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. /* ownCloud Android client application
  2. * Copyright (C) 2011 Bartek Przybylski
  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 3 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.activity;
  19. import java.io.File;
  20. import android.accounts.Account;
  21. import android.app.AlertDialog;
  22. import android.app.ProgressDialog;
  23. import android.app.AlertDialog.Builder;
  24. import android.app.Dialog;
  25. import android.content.BroadcastReceiver;
  26. import android.content.ComponentName;
  27. import android.content.ContentResolver;
  28. import android.content.Context;
  29. import android.content.DialogInterface;
  30. import android.content.DialogInterface.OnClickListener;
  31. import android.content.Intent;
  32. import android.content.IntentFilter;
  33. import android.content.ServiceConnection;
  34. import android.content.SharedPreferences;
  35. import android.content.pm.PackageInfo;
  36. import android.content.pm.PackageManager.NameNotFoundException;
  37. import android.content.res.Resources.NotFoundException;
  38. import android.database.Cursor;
  39. import android.net.Uri;
  40. import android.os.Bundle;
  41. import android.os.Handler;
  42. import android.os.IBinder;
  43. import android.preference.PreferenceManager;
  44. import android.provider.MediaStore;
  45. import android.support.v4.app.FragmentTransaction;
  46. import android.util.Log;
  47. import android.view.View;
  48. import android.view.ViewGroup;
  49. import android.widget.ArrayAdapter;
  50. import android.widget.EditText;
  51. import android.widget.TextView;
  52. import android.widget.Toast;
  53. import com.actionbarsherlock.app.ActionBar;
  54. import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
  55. import com.actionbarsherlock.app.SherlockFragmentActivity;
  56. import com.actionbarsherlock.view.Menu;
  57. import com.actionbarsherlock.view.MenuInflater;
  58. import com.actionbarsherlock.view.MenuItem;
  59. import com.actionbarsherlock.view.Window;
  60. import com.owncloud.android.AccountUtils;
  61. import com.owncloud.android.authenticator.AccountAuthenticator;
  62. import com.owncloud.android.datamodel.DataStorageManager;
  63. import com.owncloud.android.datamodel.FileDataStorageManager;
  64. import com.owncloud.android.datamodel.OCFile;
  65. import com.owncloud.android.files.services.FileDownloader;
  66. import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  67. import com.owncloud.android.files.services.FileObserverService;
  68. import com.owncloud.android.files.services.FileUploader;
  69. import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
  70. import com.owncloud.android.network.OwnCloudClientUtils;
  71. import com.owncloud.android.operations.OnRemoteOperationListener;
  72. import com.owncloud.android.operations.RemoteOperation;
  73. import com.owncloud.android.operations.RemoteOperationResult;
  74. import com.owncloud.android.operations.RemoveFileOperation;
  75. import com.owncloud.android.operations.RenameFileOperation;
  76. import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
  77. import com.owncloud.android.syncadapter.FileSyncService;
  78. import com.owncloud.android.ui.dialog.SslValidatorDialog;
  79. import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
  80. import com.owncloud.android.ui.fragment.FileDetailFragment;
  81. import com.owncloud.android.ui.fragment.OCFileListFragment;
  82. import com.owncloud.android.R;
  83. import eu.alefzero.webdav.WebdavClient;
  84. /**
  85. * Displays, what files the user has available in his ownCloud.
  86. *
  87. * @author Bartek Przybylski
  88. *
  89. */
  90. public class FileDisplayActivity extends SherlockFragmentActivity implements
  91. OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, OnRemoteOperationListener {
  92. private ArrayAdapter<String> mDirectories;
  93. private OCFile mCurrentDir = null;
  94. private OCFile mCurrentFile = null;
  95. private DataStorageManager mStorageManager;
  96. private SyncBroadcastReceiver mSyncBroadcastReceiver;
  97. private UploadFinishReceiver mUploadFinishReceiver;
  98. private DownloadFinishReceiver mDownloadFinishReceiver;
  99. private FileDownloaderBinder mDownloaderBinder = null;
  100. private FileUploaderBinder mUploaderBinder = null;
  101. private ServiceConnection mDownloadConnection = null, mUploadConnection = null;
  102. private RemoteOperationResult mLastSslUntrustedServerResult = null;
  103. private OCFileListFragment mFileList;
  104. private boolean mDualPane;
  105. private static final int DIALOG_SETUP_ACCOUNT = 0;
  106. private static final int DIALOG_CREATE_DIR = 1;
  107. private static final int DIALOG_ABOUT_APP = 2;
  108. public static final int DIALOG_SHORT_WAIT = 3;
  109. private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4;
  110. private static final int DIALOG_SSL_VALIDATOR = 5;
  111. private static final int DIALOG_CERT_NOT_SAVED = 6;
  112. private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
  113. private static final int ACTION_SELECT_MULTIPLE_FILES = 2;
  114. private static final String TAG = "FileDisplayActivity";
  115. @Override
  116. public void onCreate(Bundle savedInstanceState) {
  117. Log.d(getClass().toString(), "onCreate() start");
  118. super.onCreate(savedInstanceState);
  119. /// Load of parameters from received intent
  120. mCurrentDir = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE); // no check necessary, mCurrenDir == null if the parameter is not in the intent
  121. Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
  122. if (account != null)
  123. AccountUtils.setCurrentOwnCloudAccount(this, account.name);
  124. /// Load of saved instance state: keep this always before initDataFromCurrentAccount()
  125. if(savedInstanceState != null) {
  126. // TODO - test if savedInstanceState should take precedence over file in the intent ALWAYS (now), NEVER, or SOME TIMES
  127. mCurrentDir = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE);
  128. }
  129. if (!AccountUtils.accountsAreSetup(this)) {
  130. /// no account available: FORCE ACCOUNT CREATION
  131. mStorageManager = null;
  132. createFirstAccount();
  133. } else { /// at least an account is available
  134. initDataFromCurrentAccount(); // it checks mCurrentDir and mCurrentFile with the current account
  135. }
  136. mUploadConnection = new ListServiceConnection();
  137. mDownloadConnection = new ListServiceConnection();
  138. bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);
  139. bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);
  140. // PIN CODE request ; best location is to decide, let's try this first
  141. if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) {
  142. requestPinCode();
  143. }
  144. // file observer
  145. Intent observer_intent = new Intent(this, FileObserverService.class);
  146. observer_intent.putExtra(FileObserverService.KEY_FILE_CMD, FileObserverService.CMD_INIT_OBSERVED_LIST);
  147. startService(observer_intent);
  148. /// USER INTERFACE
  149. requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
  150. // Drop-down navigation
  151. mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
  152. OCFile currFile = mCurrentDir;
  153. while(currFile != null && currFile.getFileName() != OCFile.PATH_SEPARATOR) {
  154. mDirectories.add(currFile.getFileName());
  155. currFile = mStorageManager.getFileById(currFile.getParentId());
  156. }
  157. mDirectories.add(OCFile.PATH_SEPARATOR);
  158. // Inflate and set the layout view
  159. setContentView(R.layout.files);
  160. mFileList = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
  161. mDualPane = (findViewById(R.id.file_details_container) != null);
  162. if (mDualPane) {
  163. initFileDetailsInDualPane();
  164. }
  165. // Action bar setup
  166. ActionBar actionBar = getSupportActionBar();
  167. actionBar.setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation
  168. actionBar.setDisplayHomeAsUpEnabled(mCurrentDir != null && mCurrentDir.getParentId() != 0);
  169. actionBar.setDisplayShowTitleEnabled(false);
  170. actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
  171. actionBar.setListNavigationCallbacks(mDirectories, this);
  172. setSupportProgressBarIndeterminateVisibility(false); // always AFTER setContentView(...) ; to workaround bug in its implementation
  173. Log.d(getClass().toString(), "onCreate() end");
  174. }
  175. /**
  176. * Launches the account creation activity. To use when no ownCloud account is available
  177. */
  178. private void createFirstAccount() {
  179. Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
  180. intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
  181. startActivity(intent); // the new activity won't be created until this.onStart() and this.onResume() are finished;
  182. }
  183. /**
  184. * Load of state dependent of the existence of an ownCloud account
  185. */
  186. private void initDataFromCurrentAccount() {
  187. /// Storage manager initialization - access to local database
  188. mStorageManager = new FileDataStorageManager(
  189. AccountUtils.getCurrentOwnCloudAccount(this),
  190. getContentResolver());
  191. /// Check if mCurrentDir is a directory
  192. if(mCurrentDir != null && !mCurrentDir.isDirectory()) {
  193. mCurrentFile = mCurrentDir;
  194. mCurrentDir = mStorageManager.getFileById(mCurrentDir.getParentId());
  195. }
  196. /// Check if mCurrentDir and mCurrentFile are in the current account, and update them
  197. if (mCurrentDir != null) {
  198. mCurrentDir = mStorageManager.getFileByPath(mCurrentDir.getRemotePath()); // mCurrentDir == null if it is not in the current account
  199. }
  200. if (mCurrentFile != null) {
  201. if (mCurrentFile.fileExists()) {
  202. mCurrentFile = mStorageManager.getFileByPath(mCurrentFile.getRemotePath()); // mCurrentFile == null if it is not in the current account
  203. } // else : keep mCurrentFile with the received value; this is currently the case of an upload in progress, when the user presses the status notification in a landscape tablet
  204. }
  205. /// Default to root if mCurrentDir was not found
  206. if (mCurrentDir == null) {
  207. mCurrentDir = mStorageManager.getFileByPath("/"); // will be NULL if the database was never synchronized
  208. }
  209. }
  210. private void initFileDetailsInDualPane() {
  211. if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) {
  212. FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  213. if (mCurrentFile != null) {
  214. transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG); // empty FileDetailFragment
  215. mCurrentFile = null;
  216. } else {
  217. transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment
  218. }
  219. transaction.commit();
  220. }
  221. }
  222. @Override
  223. public void onDestroy() {
  224. super.onDestroy();
  225. if (mDownloadConnection != null)
  226. unbindService(mDownloadConnection);
  227. if (mUploadConnection != null)
  228. unbindService(mUploadConnection);
  229. }
  230. @Override
  231. public boolean onCreateOptionsMenu(Menu menu) {
  232. MenuInflater inflater = getSherlock().getMenuInflater();
  233. inflater.inflate(R.menu.menu, menu);
  234. return true;
  235. }
  236. @Override
  237. public boolean onOptionsItemSelected(MenuItem item) {
  238. boolean retval = true;
  239. switch (item.getItemId()) {
  240. case R.id.createDirectoryItem: {
  241. showDialog(DIALOG_CREATE_DIR);
  242. break;
  243. }
  244. case R.id.startSync: {
  245. startSynchronization();
  246. break;
  247. }
  248. case R.id.action_upload: {
  249. showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
  250. break;
  251. }
  252. case R.id.action_settings: {
  253. Intent settingsIntent = new Intent(this, Preferences.class);
  254. startActivity(settingsIntent);
  255. break;
  256. }
  257. case R.id.about_app : {
  258. showDialog(DIALOG_ABOUT_APP);
  259. break;
  260. }
  261. case android.R.id.home: {
  262. if(mCurrentDir != null && mCurrentDir.getParentId() != 0){
  263. onBackPressed();
  264. }
  265. break;
  266. }
  267. default:
  268. retval = super.onOptionsItemSelected(item);
  269. }
  270. return retval;
  271. }
  272. private void startSynchronization() {
  273. ContentResolver.cancelSync(null, AccountAuthenticator.AUTH_TOKEN_TYPE); // cancel the current synchronizations of any ownCloud account
  274. Bundle bundle = new Bundle();
  275. bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
  276. ContentResolver.requestSync(
  277. AccountUtils.getCurrentOwnCloudAccount(this),
  278. AccountAuthenticator.AUTH_TOKEN_TYPE, bundle);
  279. }
  280. @Override
  281. public boolean onNavigationItemSelected(int itemPosition, long itemId) {
  282. int i = itemPosition;
  283. while (i-- != 0) {
  284. onBackPressed();
  285. }
  286. // the next operation triggers a new call to this method, but it's necessary to
  287. // ensure that the name exposed in the action bar is the current directory when the
  288. // user selected it in the navigation list
  289. if (itemPosition != 0)
  290. getSupportActionBar().setSelectedNavigationItem(0);
  291. return true;
  292. }
  293. /**
  294. * Called, when the user selected something for uploading
  295. */
  296. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  297. if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && resultCode == RESULT_OK) {
  298. requestSimpleUpload(data);
  299. } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && resultCode == RESULT_OK) {
  300. requestMultipleUpload(data);
  301. }
  302. }
  303. private void requestMultipleUpload(Intent data) {
  304. String[] filePaths = data.getStringArrayExtra(UploadFilesActivity.EXTRA_CHOSEN_FILES);
  305. if (filePaths != null) {
  306. String[] remotePaths = new String[filePaths.length];
  307. String remotePathBase = "";
  308. for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
  309. remotePathBase += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
  310. }
  311. if (!remotePathBase.endsWith(OCFile.PATH_SEPARATOR))
  312. remotePathBase += OCFile.PATH_SEPARATOR;
  313. for (int j = 0; j< remotePaths.length; j++) {
  314. remotePaths[j] = remotePathBase + (new File(filePaths[j])).getName();
  315. }
  316. Intent i = new Intent(this, FileUploader.class);
  317. i.putExtra(FileUploader.KEY_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
  318. i.putExtra(FileUploader.KEY_LOCAL_FILE, filePaths);
  319. i.putExtra(FileUploader.KEY_REMOTE_FILE, remotePaths);
  320. i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
  321. startService(i);
  322. } else {
  323. Log.d("FileDisplay", "User clicked on 'Update' with no selection");
  324. Toast t = Toast.makeText(this, getString(R.string.filedisplay_no_file_selected), Toast.LENGTH_LONG);
  325. t.show();
  326. return;
  327. }
  328. }
  329. private void requestSimpleUpload(Intent data) {
  330. String filepath = null;
  331. try {
  332. Uri selectedImageUri = data.getData();
  333. String filemanagerstring = selectedImageUri.getPath();
  334. String selectedImagePath = getPath(selectedImageUri);
  335. if (selectedImagePath != null)
  336. filepath = selectedImagePath;
  337. else
  338. filepath = filemanagerstring;
  339. } catch (Exception e) {
  340. Log.e("FileDisplay", "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e);
  341. e.printStackTrace();
  342. } finally {
  343. if (filepath == null) {
  344. Log.e("FileDisplay", "Couldnt resolve path to file");
  345. Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG);
  346. t.show();
  347. return;
  348. }
  349. }
  350. Intent i = new Intent(this, FileUploader.class);
  351. i.putExtra(FileUploader.KEY_ACCOUNT,
  352. AccountUtils.getCurrentOwnCloudAccount(this));
  353. String remotepath = new String();
  354. for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
  355. remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
  356. }
  357. if (!remotepath.endsWith(OCFile.PATH_SEPARATOR))
  358. remotepath += OCFile.PATH_SEPARATOR;
  359. remotepath += new File(filepath).getName();
  360. i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath);
  361. i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath);
  362. i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
  363. startService(i);
  364. }
  365. @Override
  366. public void onBackPressed() {
  367. if (mDirectories.getCount() <= 1) {
  368. finish();
  369. return;
  370. }
  371. popDirname();
  372. mFileList.onNavigateUp();
  373. mCurrentDir = mFileList.getCurrentFile();
  374. if (mDualPane) {
  375. // Resets the FileDetailsFragment on Tablets so that it always displays
  376. FileDetailFragment fileDetails = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  377. if (fileDetails != null && !fileDetails.isEmpty()) {
  378. FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  379. transaction.remove(fileDetails);
  380. transaction.add(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG);
  381. transaction.commit();
  382. }
  383. }
  384. if(mCurrentDir.getParentId() == 0){
  385. ActionBar actionBar = getSupportActionBar();
  386. actionBar.setDisplayHomeAsUpEnabled(false);
  387. }
  388. }
  389. @Override
  390. protected void onSaveInstanceState(Bundle outState) {
  391. // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
  392. Log.d(getClass().toString(), "onSaveInstanceState() start");
  393. super.onSaveInstanceState(outState);
  394. outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir);
  395. if (mDualPane) {
  396. FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  397. if (fragment != null) {
  398. OCFile file = fragment.getDisplayedFile();
  399. if (file != null) {
  400. outState.putParcelable(FileDetailFragment.EXTRA_FILE, file);
  401. }
  402. }
  403. }
  404. Log.d(getClass().toString(), "onSaveInstanceState() end");
  405. }
  406. @Override
  407. protected void onResume() {
  408. Log.d(getClass().toString(), "onResume() start");
  409. super.onResume();
  410. if (AccountUtils.accountsAreSetup(this)) {
  411. if (mStorageManager == null) {
  412. // this is necessary for handling the come back to FileDisplayActivity when the first ownCloud account is created
  413. initDataFromCurrentAccount();
  414. if (mDualPane) {
  415. initFileDetailsInDualPane();
  416. }
  417. }
  418. // Listen for sync messages
  419. IntentFilter syncIntentFilter = new IntentFilter(FileSyncService.SYNC_MESSAGE);
  420. mSyncBroadcastReceiver = new SyncBroadcastReceiver();
  421. registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
  422. // Listen for upload messages
  423. IntentFilter uploadIntentFilter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
  424. mUploadFinishReceiver = new UploadFinishReceiver();
  425. registerReceiver(mUploadFinishReceiver, uploadIntentFilter);
  426. // Listen for download messages
  427. IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
  428. mDownloadFinishReceiver = new DownloadFinishReceiver();
  429. registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
  430. // List current directory
  431. mFileList.listDirectory(mCurrentDir); // TODO we should find the way to avoid the need of this (maybe it's not necessary yet; to check)
  432. } else {
  433. mStorageManager = null; // an invalid object will be there if all the ownCloud accounts are removed
  434. showDialog(DIALOG_SETUP_ACCOUNT);
  435. }
  436. Log.d(getClass().toString(), "onResume() end");
  437. }
  438. @Override
  439. protected void onPause() {
  440. Log.d(getClass().toString(), "onPause() start");
  441. super.onPause();
  442. if (mSyncBroadcastReceiver != null) {
  443. unregisterReceiver(mSyncBroadcastReceiver);
  444. mSyncBroadcastReceiver = null;
  445. }
  446. if (mUploadFinishReceiver != null) {
  447. unregisterReceiver(mUploadFinishReceiver);
  448. mUploadFinishReceiver = null;
  449. }
  450. if (mDownloadFinishReceiver != null) {
  451. unregisterReceiver(mDownloadFinishReceiver);
  452. mDownloadFinishReceiver = null;
  453. }
  454. if (!AccountUtils.accountsAreSetup(this)) {
  455. dismissDialog(DIALOG_SETUP_ACCOUNT);
  456. }
  457. Log.d(getClass().toString(), "onPause() end");
  458. }
  459. @Override
  460. protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
  461. if (id == DIALOG_SSL_VALIDATOR && mLastSslUntrustedServerResult != null) {
  462. ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult);
  463. }
  464. }
  465. @Override
  466. protected Dialog onCreateDialog(int id) {
  467. Dialog dialog = null;
  468. AlertDialog.Builder builder;
  469. switch (id) {
  470. case DIALOG_SETUP_ACCOUNT: {
  471. builder = new AlertDialog.Builder(this);
  472. builder.setTitle(R.string.main_tit_accsetup);
  473. builder.setMessage(R.string.main_wrn_accsetup);
  474. builder.setCancelable(false);
  475. builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
  476. public void onClick(DialogInterface dialog, int which) {
  477. createFirstAccount();
  478. dialog.dismiss();
  479. }
  480. });
  481. builder.setNegativeButton(R.string.common_exit, new OnClickListener() {
  482. public void onClick(DialogInterface dialog, int which) {
  483. dialog.dismiss();
  484. finish();
  485. }
  486. });
  487. //builder.setNegativeButton(android.R.string.cancel, this);
  488. dialog = builder.create();
  489. break;
  490. }
  491. case DIALOG_ABOUT_APP: {
  492. builder = new AlertDialog.Builder(this);
  493. builder.setTitle(getString(R.string.about_title));
  494. PackageInfo pkg;
  495. try {
  496. pkg = getPackageManager().getPackageInfo(getPackageName(), 0);
  497. builder.setMessage(String.format(getString(R.string.about_message), pkg.versionName));
  498. builder.setIcon(android.R.drawable.ic_menu_info_details);
  499. dialog = builder.create();
  500. } catch (NameNotFoundException e) {
  501. builder = null;
  502. dialog = null;
  503. Log.e(TAG, "Error while showing about dialog", e);
  504. }
  505. break;
  506. }
  507. case DIALOG_CREATE_DIR: {
  508. builder = new Builder(this);
  509. final EditText dirNameInput = new EditText(getBaseContext());
  510. builder.setView(dirNameInput);
  511. builder.setTitle(R.string.uploader_info_dirname);
  512. int typed_color = getResources().getColor(R.color.setup_text_typed);
  513. dirNameInput.setTextColor(typed_color);
  514. builder.setPositiveButton(android.R.string.ok,
  515. new OnClickListener() {
  516. public void onClick(DialogInterface dialog, int which) {
  517. String directoryName = dirNameInput.getText().toString();
  518. if (directoryName.trim().length() == 0) {
  519. dialog.cancel();
  520. return;
  521. }
  522. // Figure out the path where the dir needs to be created
  523. String path;
  524. if (mCurrentDir == null) {
  525. // this is just a patch; we should ensure that mCurrentDir never is null
  526. if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
  527. OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
  528. mStorageManager.saveFile(file);
  529. }
  530. mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
  531. }
  532. path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
  533. // Create directory
  534. path += directoryName + OCFile.PATH_SEPARATOR;
  535. Thread thread = new Thread(new DirectoryCreator(path, AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
  536. thread.start();
  537. dialog.dismiss();
  538. showDialog(DIALOG_SHORT_WAIT);
  539. }
  540. });
  541. builder.setNegativeButton(R.string.common_cancel,
  542. new OnClickListener() {
  543. public void onClick(DialogInterface dialog, int which) {
  544. dialog.cancel();
  545. }
  546. });
  547. dialog = builder.create();
  548. break;
  549. }
  550. case DIALOG_SHORT_WAIT: {
  551. ProgressDialog working_dialog = new ProgressDialog(this);
  552. working_dialog.setMessage(getResources().getString(
  553. R.string.wait_a_moment));
  554. working_dialog.setIndeterminate(true);
  555. working_dialog.setCancelable(false);
  556. dialog = working_dialog;
  557. break;
  558. }
  559. case DIALOG_CHOOSE_UPLOAD_SOURCE: {
  560. final String [] items = { getString(R.string.actionbar_upload_files),
  561. getString(R.string.actionbar_upload_from_apps) };
  562. builder = new AlertDialog.Builder(this);
  563. builder.setTitle(R.string.actionbar_upload);
  564. builder.setItems(items, new DialogInterface.OnClickListener() {
  565. public void onClick(DialogInterface dialog, int item) {
  566. if (item == 0) {
  567. //if (!mDualPane) {
  568. Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class);
  569. startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES);
  570. //} else {
  571. // TODO create and handle new fragment LocalFileListFragment
  572. //}
  573. } else if (item == 1) {
  574. Intent action = new Intent(Intent.ACTION_GET_CONTENT);
  575. action = action.setType("*/*")
  576. .addCategory(Intent.CATEGORY_OPENABLE);
  577. startActivityForResult(
  578. Intent.createChooser(action, getString(R.string.upload_chooser_title)),
  579. ACTION_SELECT_CONTENT_FROM_APPS);
  580. }
  581. }
  582. });
  583. dialog = builder.create();
  584. break;
  585. }
  586. case DIALOG_SSL_VALIDATOR: {
  587. dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this);
  588. break;
  589. }
  590. case DIALOG_CERT_NOT_SAVED: {
  591. builder = new AlertDialog.Builder(this);
  592. builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
  593. builder.setCancelable(false);
  594. builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
  595. @Override
  596. public void onClick(DialogInterface dialog, int which) {
  597. dialog.dismiss();
  598. };
  599. });
  600. dialog = builder.create();
  601. break;
  602. }
  603. default:
  604. dialog = null;
  605. }
  606. return dialog;
  607. }
  608. /**
  609. * Translates a content URI of an image to a physical path
  610. * on the disk
  611. * @param uri The URI to resolve
  612. * @return The path to the image or null if it could not be found
  613. */
  614. public String getPath(Uri uri) {
  615. String[] projection = { MediaStore.Images.Media.DATA };
  616. Cursor cursor = managedQuery(uri, projection, null, null, null);
  617. if (cursor != null) {
  618. int column_index = cursor
  619. .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
  620. cursor.moveToFirst();
  621. return cursor.getString(column_index);
  622. }
  623. return null;
  624. }
  625. /**
  626. * Pushes a directory to the drop down list
  627. * @param directory to push
  628. * @throws IllegalArgumentException If the {@link OCFile#isDirectory()} returns false.
  629. */
  630. public void pushDirname(OCFile directory) {
  631. if(!directory.isDirectory()){
  632. throw new IllegalArgumentException("Only directories may be pushed!");
  633. }
  634. mDirectories.insert(directory.getFileName(), 0);
  635. mCurrentDir = directory;
  636. }
  637. /**
  638. * Pops a directory name from the drop down list
  639. * @return True, unless the stack is empty
  640. */
  641. public boolean popDirname() {
  642. mDirectories.remove(mDirectories.getItem(0));
  643. return !mDirectories.isEmpty();
  644. }
  645. private class DirectoryCreator implements Runnable {
  646. private String mTargetPath;
  647. private Account mAccount;
  648. private Handler mHandler;
  649. public DirectoryCreator(String targetPath, Account account, Handler handler) {
  650. mTargetPath = targetPath;
  651. mAccount = account;
  652. mHandler = handler;
  653. }
  654. @Override
  655. public void run() {
  656. WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
  657. boolean created = wdc.createDirectory(mTargetPath);
  658. if (created) {
  659. mHandler.post(new Runnable() {
  660. @Override
  661. public void run() {
  662. dismissDialog(DIALOG_SHORT_WAIT);
  663. // Save new directory in local database
  664. OCFile newDir = new OCFile(mTargetPath);
  665. newDir.setMimetype("DIR");
  666. newDir.setParentId(mCurrentDir.getFileId());
  667. mStorageManager.saveFile(newDir);
  668. // Display the new folder right away
  669. mFileList.listDirectory();
  670. }
  671. });
  672. } else {
  673. mHandler.post(new Runnable() {
  674. @Override
  675. public void run() {
  676. dismissDialog(DIALOG_SHORT_WAIT);
  677. try {
  678. Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG);
  679. msg.show();
  680. } catch (NotFoundException e) {
  681. Log.e(TAG, "Error while trying to show fail message " , e);
  682. }
  683. }
  684. });
  685. }
  686. }
  687. }
  688. // Custom array adapter to override text colors
  689. private class CustomArrayAdapter<T> extends ArrayAdapter<T> {
  690. public CustomArrayAdapter(FileDisplayActivity ctx, int view) {
  691. super(ctx, view);
  692. }
  693. public View getView(int position, View convertView, ViewGroup parent) {
  694. View v = super.getView(position, convertView, parent);
  695. ((TextView) v).setTextColor(getResources().getColorStateList(
  696. android.R.color.white));
  697. return v;
  698. }
  699. public View getDropDownView(int position, View convertView,
  700. ViewGroup parent) {
  701. View v = super.getDropDownView(position, convertView, parent);
  702. ((TextView) v).setTextColor(getResources().getColorStateList(
  703. android.R.color.white));
  704. return v;
  705. }
  706. }
  707. private class SyncBroadcastReceiver extends BroadcastReceiver {
  708. /**
  709. * {@link BroadcastReceiver} to enable syncing feedback in UI
  710. */
  711. @Override
  712. public void onReceive(Context context, Intent intent) {
  713. boolean inProgress = intent.getBooleanExtra(
  714. FileSyncService.IN_PROGRESS, false);
  715. String accountName = intent
  716. .getStringExtra(FileSyncService.ACCOUNT_NAME);
  717. Log.d("FileDisplay", "sync of account " + accountName
  718. + " is in_progress: " + inProgress);
  719. if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name)) {
  720. String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
  721. boolean fillBlankRoot = false;
  722. if (mCurrentDir == null) {
  723. mCurrentDir = mStorageManager.getFileByPath("/");
  724. fillBlankRoot = (mCurrentDir != null);
  725. }
  726. if ((synchFolderRemotePath != null && mCurrentDir != null && (mCurrentDir.getRemotePath().equals(synchFolderRemotePath)))
  727. || fillBlankRoot ) {
  728. if (!fillBlankRoot)
  729. mCurrentDir = getStorageManager().getFileByPath(synchFolderRemotePath);
  730. OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
  731. .findFragmentById(R.id.fileList);
  732. if (fileListFragment != null) {
  733. fileListFragment.listDirectory(mCurrentDir);
  734. }
  735. }
  736. setSupportProgressBarIndeterminateVisibility(inProgress);
  737. }
  738. RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
  739. if (synchResult != null) {
  740. if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) {
  741. mLastSslUntrustedServerResult = synchResult;
  742. showDialog(DIALOG_SSL_VALIDATOR);
  743. }
  744. }
  745. }
  746. }
  747. private class UploadFinishReceiver extends BroadcastReceiver {
  748. /**
  749. * Once the file upload has finished -> update view
  750. * @author David A. Velasco
  751. * {@link BroadcastReceiver} to enable upload feedback in UI
  752. */
  753. @Override
  754. public void onReceive(Context context, Intent intent) {
  755. String uploadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
  756. String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);
  757. boolean sameAccount = accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name);
  758. boolean isDescendant = (mCurrentDir != null) && (uploadedRemotePath != null) && (uploadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
  759. if (sameAccount && isDescendant) {
  760. OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
  761. if (fileListFragment != null) {
  762. fileListFragment.listDirectory();
  763. }
  764. }
  765. }
  766. }
  767. /**
  768. * Once the file download has finished -> update view
  769. */
  770. private class DownloadFinishReceiver extends BroadcastReceiver {
  771. @Override
  772. public void onReceive(Context context, Intent intent) {
  773. String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
  774. String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
  775. boolean sameAccount = accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name);
  776. boolean isDescendant = (mCurrentDir != null) && (downloadedRemotePath != null) && (downloadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
  777. if (sameAccount && isDescendant) {
  778. OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
  779. if (fileListFragment != null) {
  780. fileListFragment.listDirectory();
  781. }
  782. }
  783. }
  784. }
  785. /**
  786. * {@inheritDoc}
  787. */
  788. @Override
  789. public DataStorageManager getStorageManager() {
  790. return mStorageManager;
  791. }
  792. /**
  793. * {@inheritDoc}
  794. */
  795. @Override
  796. public void onDirectoryClick(OCFile directory) {
  797. pushDirname(directory);
  798. ActionBar actionBar = getSupportActionBar();
  799. actionBar.setDisplayHomeAsUpEnabled(true);
  800. if (mDualPane) {
  801. // Resets the FileDetailsFragment on Tablets so that it always displays
  802. FileDetailFragment fileDetails = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  803. if (fileDetails != null && !fileDetails.isEmpty()) {
  804. FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  805. transaction.remove(fileDetails);
  806. transaction.add(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG);
  807. transaction.commit();
  808. }
  809. }
  810. }
  811. /**
  812. * {@inheritDoc}
  813. */
  814. @Override
  815. public void onFileClick(OCFile file) {
  816. // If we are on a large device -> update fragment
  817. if (mDualPane) {
  818. // buttons in the details view are problematic when trying to reuse an existing fragment; create always a new one solves some of them, BUT no all; downloads are 'dangerous'
  819. FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  820. transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
  821. transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
  822. transaction.commit();
  823. } else { // small or medium screen device -> new Activity
  824. Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
  825. showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
  826. showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
  827. startActivity(showDetailsIntent);
  828. }
  829. }
  830. /**
  831. * {@inheritDoc}
  832. */
  833. @Override
  834. public OCFile getInitialDirectory() {
  835. return mCurrentDir;
  836. }
  837. /**
  838. * {@inheritDoc}
  839. */
  840. @Override
  841. public void onFileStateChanged() {
  842. OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
  843. if (fileListFragment != null) {
  844. fileListFragment.listDirectory();
  845. }
  846. }
  847. /**
  848. * {@inheritDoc}
  849. */
  850. @Override
  851. public FileDownloaderBinder getFileDownloaderBinder() {
  852. return mDownloaderBinder;
  853. }
  854. /**
  855. * {@inheritDoc}
  856. */
  857. @Override
  858. public FileUploaderBinder getFileUploaderBinder() {
  859. return mUploaderBinder;
  860. }
  861. /** Defines callbacks for service binding, passed to bindService() */
  862. private class ListServiceConnection implements ServiceConnection {
  863. @Override
  864. public void onServiceConnected(ComponentName component, IBinder service) {
  865. if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
  866. Log.d(TAG, "Download service connected");
  867. mDownloaderBinder = (FileDownloaderBinder) service;
  868. } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
  869. Log.d(TAG, "Upload service connected");
  870. mUploaderBinder = (FileUploaderBinder) service;
  871. } else {
  872. return;
  873. }
  874. // a new chance to get the mDownloadBinder through getFileDownloadBinder() - THIS IS A MESS
  875. if (mFileList != null)
  876. mFileList.listDirectory();
  877. if (mDualPane) {
  878. FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  879. if (fragment != null)
  880. fragment.updateFileDetails(false);
  881. }
  882. }
  883. @Override
  884. public void onServiceDisconnected(ComponentName component) {
  885. if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
  886. Log.d(TAG, "Download service disconnected");
  887. mDownloaderBinder = null;
  888. } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
  889. Log.d(TAG, "Upload service disconnected");
  890. mUploaderBinder = null;
  891. }
  892. }
  893. };
  894. /**
  895. * Launch an intent to request the PIN code to the user before letting him use the app
  896. */
  897. private void requestPinCode() {
  898. boolean pinStart = false;
  899. SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  900. pinStart = appPrefs.getBoolean("set_pincode", false);
  901. if (pinStart) {
  902. Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
  903. i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "FileDisplayActivity");
  904. startActivity(i);
  905. }
  906. }
  907. @Override
  908. public void onSavedCertificate() {
  909. startSynchronization();
  910. }
  911. @Override
  912. public void onFailedSavingCertificate() {
  913. showDialog(DIALOG_CERT_NOT_SAVED);
  914. }
  915. /**
  916. * Updates the view associated to the activity after the finish of some operation over files
  917. * in the current account.
  918. *
  919. * @param operation Removal operation performed.
  920. * @param result Result of the removal.
  921. */
  922. @Override
  923. public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
  924. if (operation instanceof RemoveFileOperation) {
  925. onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
  926. } else if (operation instanceof RenameFileOperation) {
  927. onRenameFileOperationFinish((RenameFileOperation)operation, result);
  928. }
  929. }
  930. /**
  931. * Updates the view associated to the activity after the finish of an operation trying to remove a
  932. * file.
  933. *
  934. * @param operation Removal operation performed.
  935. * @param result Result of the removal.
  936. */
  937. private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
  938. dismissDialog(DIALOG_SHORT_WAIT);
  939. if (result.isSuccess()) {
  940. Toast msg = Toast.makeText(this, R.string.remove_success_msg, Toast.LENGTH_LONG);
  941. msg.show();
  942. OCFile removedFile = operation.getFile();
  943. if (mDualPane) {
  944. FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  945. if (details != null && removedFile.equals(details.getDisplayedFile()) ) {
  946. FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  947. transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment
  948. transaction.commit();
  949. }
  950. }
  951. if (mStorageManager.getFileById(removedFile.getParentId()).equals(mCurrentDir)) {
  952. mFileList.listDirectory();
  953. }
  954. } else {
  955. Toast msg = Toast.makeText(this, R.string.remove_fail_msg, Toast.LENGTH_LONG);
  956. msg.show();
  957. if (result.isSslRecoverableException()) {
  958. mLastSslUntrustedServerResult = result;
  959. showDialog(DIALOG_SSL_VALIDATOR);
  960. }
  961. }
  962. }
  963. /**
  964. * Updates the view associated to the activity after the finish of an operation trying to rename a
  965. * file.
  966. *
  967. * @param operation Renaming operation performed.
  968. * @param result Result of the renaming.
  969. */
  970. private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) {
  971. dismissDialog(DIALOG_SHORT_WAIT);
  972. OCFile renamedFile = operation.getFile();
  973. if (result.isSuccess()) {
  974. if (mDualPane) {
  975. FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  976. if (details != null && renamedFile.equals(details.getDisplayedFile()) ) {
  977. details.updateFileDetails(renamedFile, AccountUtils.getCurrentOwnCloudAccount(this));
  978. }
  979. }
  980. if (mStorageManager.getFileById(renamedFile.getParentId()).equals(mCurrentDir)) {
  981. mFileList.listDirectory();
  982. }
  983. } else {
  984. if (result.getCode().equals(ResultCode.INVALID_LOCAL_FILE_NAME)) {
  985. Toast msg = Toast.makeText(this, R.string.rename_local_fail_msg, Toast.LENGTH_LONG);
  986. msg.show();
  987. // TODO throw again the new rename dialog
  988. } else {
  989. Toast msg = Toast.makeText(this, R.string.rename_server_fail_msg, Toast.LENGTH_LONG);
  990. msg.show();
  991. if (result.isSslRecoverableException()) {
  992. mLastSslUntrustedServerResult = result;
  993. showDialog(DIALOG_SSL_VALIDATOR);
  994. }
  995. }
  996. }
  997. }
  998. /**
  999. * {@inheritDoc}
  1000. */
  1001. @Override
  1002. public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) {
  1003. /*OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
  1004. if (fileListFragment != null) {
  1005. fileListFragment.listDirectory();
  1006. }*/
  1007. if (mDualPane) {
  1008. FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
  1009. if (details != null && file.equals(details.getDisplayedFile()) ) {
  1010. if (downloading || uploading) {
  1011. details.updateFileDetails(file, AccountUtils.getCurrentOwnCloudAccount(this));
  1012. } else {
  1013. details.updateFileDetails(downloading || uploading);
  1014. }
  1015. }
  1016. }
  1017. }
  1018. }