7f2df8c74dc7d302baac3de1f15a76ba14b0283b
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / activity / ErrorsWhileCopyingHandlerActivity.java
1 /* ownCloud Android client application
2 *
3 * @author David A. Velasco
4 * Copyright (C) 2012-2013 ownCloud Inc.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 package com.owncloud.android.ui.activity;
21
22 import java.io.File;
23 import java.util.ArrayList;
24
25 import android.accounts.Account;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.os.AsyncTask;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.support.v4.app.DialogFragment;
32 import android.text.method.ScrollingMovementMethod;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.view.View.OnClickListener;
36 import android.view.ViewGroup;
37 import android.widget.ArrayAdapter;
38 import android.widget.Button;
39 import android.widget.ListView;
40 import android.widget.TextView;
41 import android.widget.Toast;
42
43 import com.actionbarsherlock.app.SherlockFragmentActivity;
44 import com.owncloud.android.R;
45 import com.owncloud.android.datamodel.FileDataStorageManager;
46 import com.owncloud.android.datamodel.OCFile;
47 import com.owncloud.android.lib.common.utils.Log_OC;
48
49 import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
50 import com.owncloud.android.utils.FileStorageUtils;
51
52
53
54 /**
55 * Activity reporting errors occurred when local files uploaded to an ownCloud account with an app in
56 * version under 1.3.16 where being copied to the ownCloud local folder.
57 *
58 * Allows the user move the files to the ownCloud local folder. let them unlinked to the remote
59 * files.
60 *
61 * Shown when the error notification summarizing the list of errors is clicked by the user.
62 */
63 public class ErrorsWhileCopyingHandlerActivity extends SherlockFragmentActivity implements OnClickListener {
64
65 private static final String TAG = ErrorsWhileCopyingHandlerActivity.class.getSimpleName();
66
67 public static final String EXTRA_ACCOUNT = ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_ACCOUNT";
68 public static final String EXTRA_LOCAL_PATHS = ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_LOCAL_PATHS";
69 public static final String EXTRA_REMOTE_PATHS = ErrorsWhileCopyingHandlerActivity.class.getCanonicalName() + ".EXTRA_REMOTE_PATHS";
70
71 private static final String WAIT_DIALOG_TAG = "WAIT_DIALOG";
72
73 protected Account mAccount;
74 protected FileDataStorageManager mStorageManager;
75 protected ArrayList<String> mLocalPaths;
76 protected ArrayList<String> mRemotePaths;
77 protected ArrayAdapter<String> mAdapter;
78 protected Handler mHandler;
79 private DialogFragment mCurrentDialog;
80
81 /**
82 * {@link}
83 */
84 @Override
85 protected void onCreate(Bundle savedInstanceState) {
86 super.onCreate(savedInstanceState);
87
88 /// read extra parameters in intent
89 Intent intent = getIntent();
90 mAccount = intent.getParcelableExtra(EXTRA_ACCOUNT);
91 mRemotePaths = intent.getStringArrayListExtra(EXTRA_REMOTE_PATHS);
92 mLocalPaths = intent.getStringArrayListExtra(EXTRA_LOCAL_PATHS);
93 mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
94 mHandler = new Handler();
95 if (mCurrentDialog != null) {
96 mCurrentDialog.dismiss();
97 mCurrentDialog = null;
98 }
99
100 /// load generic layout
101 setContentView(R.layout.generic_explanation);
102
103 /// customize text message
104 TextView textView = (TextView) findViewById(R.id.message);
105 String appName = getString(R.string.app_name);
106 String message = String.format(getString(R.string.sync_foreign_files_forgotten_explanation), appName, appName, appName, appName, mAccount.name);
107 textView.setText(message);
108 textView.setMovementMethod(new ScrollingMovementMethod());
109
110 /// load the list of local and remote files that failed
111 ListView listView = (ListView) findViewById(R.id.list);
112 if (mLocalPaths != null && mLocalPaths.size() > 0) {
113 mAdapter = new ErrorsWhileCopyingListAdapter();
114 listView.setAdapter(mAdapter);
115 } else {
116 listView.setVisibility(View.GONE);
117 mAdapter = null;
118 }
119
120 /// customize buttons
121 Button cancelBtn = (Button) findViewById(R.id.cancel);
122 Button okBtn = (Button) findViewById(R.id.ok);
123
124 okBtn.setText(R.string.foreign_files_move);
125 cancelBtn.setOnClickListener(this);
126 okBtn.setOnClickListener(this);
127 }
128
129
130 /**
131 * Customized adapter, showing the local files as main text in two-lines list item and the remote files
132 * as the secondary text.
133 */
134 public class ErrorsWhileCopyingListAdapter extends ArrayAdapter<String> {
135
136 ErrorsWhileCopyingListAdapter() {
137 super(ErrorsWhileCopyingHandlerActivity.this, android.R.layout.two_line_list_item, android.R.id.text1, mLocalPaths);
138 }
139
140 @Override
141 public boolean isEnabled(int position) {
142 return false;
143 }
144
145 /**
146 * {@inheritDoc}
147 */
148 @Override
149 public View getView (int position, View convertView, ViewGroup parent) {
150 View view = convertView;
151 if (view == null) {
152 LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
153 view = vi.inflate(android.R.layout.two_line_list_item, null);
154 }
155 if (view != null) {
156 String localPath = getItem(position);
157 if (localPath != null) {
158 TextView text1 = (TextView) view.findViewById(android.R.id.text1);
159 if (text1 != null) {
160 text1.setText(String.format(getString(R.string.foreign_files_local_text), localPath));
161 }
162 }
163 if (mRemotePaths != null && mRemotePaths.size() > 0 && position >= 0 && position < mRemotePaths.size()) {
164 TextView text2 = (TextView) view.findViewById(android.R.id.text2);
165 String remotePath = mRemotePaths.get(position);
166 if (text2 != null && remotePath != null) {
167 text2.setText(String.format(getString(R.string.foreign_files_remote_text), remotePath));
168 }
169 }
170 }
171 return view;
172 }
173 }
174
175
176 /**
177 * Listener method to perform the MOVE / CANCEL action available in this activity.
178 *
179 * @param v Clicked view (button MOVE or CANCEL)
180 */
181 @Override
182 public void onClick(View v) {
183 if (v.getId() == R.id.ok) {
184 /// perform movement operation in background thread
185 Log_OC.d(TAG, "Clicked MOVE, start movement");
186 new MoveFilesTask().execute();
187
188 } else if (v.getId() == R.id.cancel) {
189 /// just finish
190 Log_OC.d(TAG, "Clicked CANCEL, bye");
191 finish();
192
193 } else {
194 Log_OC.e(TAG, "Clicked phantom button, id: " + v.getId());
195 }
196 }
197
198
199 /**
200 * Asynchronous task performing the move of all the local files to the ownCloud folder.
201 */
202 private class MoveFilesTask extends AsyncTask<Void, Void, Boolean> {
203
204 /**
205 * Updates the UI before trying the movement
206 */
207 @Override
208 protected void onPreExecute () {
209 /// progress dialog and disable 'Move' button
210 mCurrentDialog = IndeterminateProgressDialog.newInstance(R.string.wait_a_moment, false);
211 mCurrentDialog.show(getSupportFragmentManager(), WAIT_DIALOG_TAG);
212 findViewById(R.id.ok).setEnabled(false);
213 }
214
215
216 /**
217 * Performs the movement
218 *
219 * @return 'False' when the movement of any file fails.
220 */
221 @Override
222 protected Boolean doInBackground(Void... params) {
223 while (!mLocalPaths.isEmpty()) {
224 String currentPath = mLocalPaths.get(0);
225 File currentFile = new File(currentPath);
226 String expectedPath = FileStorageUtils.getSavePath(mAccount.name) + mRemotePaths.get(0);
227 File expectedFile = new File(expectedPath);
228
229 if (expectedFile.equals(currentFile) || currentFile.renameTo(expectedFile)) {
230 // SUCCESS
231 OCFile file = mStorageManager.getFileByPath(mRemotePaths.get(0));
232 file.setStoragePath(expectedPath);
233 mStorageManager.saveFile(file);
234 mRemotePaths.remove(0);
235 mLocalPaths.remove(0);
236
237 } else {
238 // FAIL
239 return false;
240 }
241 }
242 return true;
243 }
244
245 /**
246 * Updates the activity UI after the movement of local files is tried.
247 *
248 * If the movement was successful for all the files, finishes the activity immediately.
249 *
250 * In other case, the list of remaining files is still available to retry the movement.
251 *
252 * @param result 'True' when the movement was successful.
253 */
254 @Override
255 protected void onPostExecute(Boolean result) {
256 mAdapter.notifyDataSetChanged();
257 mCurrentDialog.dismiss();
258 mCurrentDialog = null;
259 findViewById(R.id.ok).setEnabled(true);
260
261 if (result) {
262 // nothing else to do in this activity
263 Toast t = Toast.makeText(ErrorsWhileCopyingHandlerActivity.this, getString(R.string.foreign_files_success), Toast.LENGTH_LONG);
264 t.show();
265 finish();
266
267 } else {
268 Toast t = Toast.makeText(ErrorsWhileCopyingHandlerActivity.this, getString(R.string.foreign_files_fail), Toast.LENGTH_LONG);
269 t.show();
270 }
271 }
272 }
273
274 }