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