Merge remote-tracking branch 'origin/master' into text_file_preview_pr_707_with_develop
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / preview / PreviewTextFragment.java
1 package com.owncloud.android.ui.preview;
2
3 import android.accounts.Account;
4 import android.os.AsyncTask;
5 import android.os.Bundle;
6 import android.support.v4.app.Fragment;
7 import android.support.v4.app.FragmentManager;
8 import android.support.v4.app.FragmentTransaction;
9 import android.view.LayoutInflater;
10 import android.view.Menu;
11 import android.view.MenuInflater;
12 import android.view.MenuItem;
13 import android.view.View;
14 import android.view.ViewGroup;
15 import android.widget.TextView;
16
17 import com.owncloud.android.R;
18 import com.owncloud.android.datamodel.OCFile;
19 import com.owncloud.android.files.FileMenuFilter;
20 import com.owncloud.android.lib.common.utils.Log_OC;
21 import com.owncloud.android.ui.activity.FileDisplayActivity;
22 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
23 import com.owncloud.android.ui.dialog.LoadingDialog;
24 import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
25 import com.owncloud.android.ui.fragment.FileFragment;
26
27 import java.io.BufferedWriter;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.io.StringWriter;
31 import java.lang.ref.WeakReference;
32 import java.util.Scanner;
33
34 public class PreviewTextFragment extends FileFragment {
35 private static final String EXTRA_FILE = "FILE";
36 private static final String EXTRA_ACCOUNT = "ACCOUNT";
37 private static final String TAG = PreviewTextFragment.class.getSimpleName();
38
39 private Account mAccount;
40 private TextView mTextPreview;
41 private TextLoadAsyncTask mTextLoadTask;
42
43 /**
44 * Creates an empty fragment for previews.
45 * <p/>
46 * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
47 * (for instance, when the device is turned a aside).
48 * <p/>
49 * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
50 * construction
51 */
52 public PreviewTextFragment() {
53 super();
54 mAccount = null;
55 }
56
57 /**
58 * {@inheritDoc}
59 */
60 @Override
61 public View onCreateView(LayoutInflater inflater, ViewGroup container,
62 Bundle savedInstanceState) {
63 super.onCreateView(inflater, container, savedInstanceState);
64 Log_OC.e(TAG, "onCreateView");
65
66
67 View ret = inflater.inflate(R.layout.text_file_preview, container, false);
68
69 mTextPreview = (TextView) ret.findViewById(R.id.text_preview);
70
71 return ret;
72 }
73
74 /**
75 * {@inheritDoc}
76 */
77 @Override
78 public void onCreate(Bundle savedInstanceState) {
79 super.onCreate(savedInstanceState);
80
81 OCFile file = getFile();
82
83 Bundle args = getArguments();
84
85 if (file == null) {
86 file = args.getParcelable(FileDisplayActivity.EXTRA_FILE);
87 }
88
89 if (mAccount == null) {
90 mAccount = args.getParcelable(FileDisplayActivity.EXTRA_ACCOUNT);
91 }
92
93 if (savedInstanceState == null) {
94 if (file == null) {
95 throw new IllegalStateException("Instanced with a NULL OCFile");
96 }
97 if (mAccount == null) {
98 throw new IllegalStateException("Instanced with a NULL ownCloud Account");
99 }
100 } else {
101 file = savedInstanceState.getParcelable(EXTRA_FILE);
102 mAccount = savedInstanceState.getParcelable(EXTRA_ACCOUNT);
103 }
104 setFile(file);
105 setHasOptionsMenu(true);
106 }
107
108 /**
109 * {@inheritDoc}
110 */
111 @Override
112 public void onSaveInstanceState(Bundle outState) {
113 super.onSaveInstanceState(outState);
114 outState.putParcelable(PreviewTextFragment.EXTRA_FILE, getFile());
115 outState.putParcelable(PreviewTextFragment.EXTRA_ACCOUNT, mAccount);
116 }
117
118 @Override
119 public void onStart() {
120 super.onStart();
121 Log_OC.e(TAG, "onStart");
122
123 loadAndShowTextPreview();
124 }
125
126 private void loadAndShowTextPreview() {
127 mTextLoadTask = new TextLoadAsyncTask(new WeakReference<TextView>(mTextPreview));
128 mTextLoadTask.execute(getFile().getStoragePath());
129 }
130
131
132 /**
133 * Reads the file to preview and shows its contents. Too critical to be anonymous.
134 */
135 private class TextLoadAsyncTask extends AsyncTask<Object, Void, StringWriter> {
136 private final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
137 private final WeakReference<TextView> mTextViewReference;
138
139 private TextLoadAsyncTask(WeakReference<TextView> textView) {
140 mTextViewReference = textView;
141 }
142
143
144 @Override
145 protected void onPreExecute() {
146 showLoadingDialog();
147 }
148
149 @Override
150 protected StringWriter doInBackground(java.lang.Object... params) {
151 if (params.length != 1) {
152 throw new IllegalArgumentException("The parameter to " + TextLoadAsyncTask.class.getName() + " must be (1) the file location");
153 }
154 final String location = (String) params[0];
155
156 FileInputStream inputStream = null;
157 Scanner sc = null;
158 StringWriter source = new StringWriter();
159 BufferedWriter bufferedWriter = new BufferedWriter(source);
160 try {
161 inputStream = new FileInputStream(location);
162 sc = new Scanner(inputStream);
163 while (sc.hasNextLine()) {
164 bufferedWriter.append(sc.nextLine());
165 if (sc.hasNextLine()) bufferedWriter.append("\n");
166 }
167 bufferedWriter.close();
168 IOException exc = sc.ioException();
169 if (exc != null) throw exc;
170 } catch (IOException e) {
171 Log_OC.e(TAG, e.getMessage(), e);
172 finish();
173 } finally {
174 if (inputStream != null) {
175 try {
176 inputStream.close();
177 } catch (IOException e) {
178 Log_OC.e(TAG, e.getMessage(), e);
179 finish();
180 }
181 }
182 if (sc != null) {
183 sc.close();
184 }
185 }
186 return source;
187 }
188
189 @Override
190 protected void onPostExecute(final StringWriter stringWriter) {
191 final TextView textView = mTextViewReference.get();
192
193 if (textView != null) {
194 textView.setText(new String(stringWriter.getBuffer()));
195 textView.setVisibility(View.VISIBLE);
196 }
197
198 dismissLoadingDialog();
199 }
200
201 /**
202 * Show loading dialog
203 */
204 public void showLoadingDialog() {
205 // Construct dialog
206 LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
207 FragmentManager fm = getActivity().getSupportFragmentManager();
208 FragmentTransaction ft = fm.beginTransaction();
209 loading.show(ft, DIALOG_WAIT_TAG);
210 }
211
212 /**
213 * Dismiss loading dialog
214 */
215 public void dismissLoadingDialog() {
216 final Fragment frag = getActivity().getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
217 if (frag != null) {
218 LoadingDialog loading = (LoadingDialog) frag;
219 loading.dismiss();
220 }
221 }
222 }
223
224 /**
225 * {@inheritDoc}
226 */
227 @Override
228 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
229 super.onCreateOptionsMenu(menu, inflater);
230 inflater.inflate(R.menu.file_actions_menu, menu);
231 }
232
233 /**
234 * {@inheritDoc}
235 */
236 @Override
237 public void onPrepareOptionsMenu(Menu menu) {
238 super.onPrepareOptionsMenu(menu);
239
240 if (mContainerActivity.getStorageManager() != null) {
241 FileMenuFilter mf = new FileMenuFilter(
242 getFile(),
243 mContainerActivity.getStorageManager().getAccount(),
244 mContainerActivity,
245 getActivity()
246 );
247 mf.filter(menu);
248 }
249
250 // additional restriction for this fragment
251 MenuItem item = menu.findItem(R.id.action_rename_file);
252 if (item != null) {
253 item.setVisible(false);
254 item.setEnabled(false);
255 }
256
257 // additional restriction for this fragment
258 item = menu.findItem(R.id.action_move);
259 if (item != null) {
260 item.setVisible(false);
261 item.setEnabled(false);
262 }
263
264 // this one doesn't make sense since the file has to be down in order to be previewed
265 item = menu.findItem(R.id.action_download_file);
266 if (item != null) {
267 item.setVisible(false);
268 item.setEnabled(false);
269 }
270
271 item = menu.findItem(R.id.action_sync_file);
272 if (item != null) {
273 item.setVisible(false);
274 item.setEnabled(false);
275 }
276
277 item = menu.findItem(R.id.action_sync_account);
278 if (item != null) {
279 item.setVisible(false);
280 item.setEnabled(false);
281 }
282 }
283
284 /**
285 * {@inheritDoc}
286 */
287 @Override
288 public boolean onOptionsItemSelected(MenuItem item) {
289 switch (item.getItemId()) {
290 case R.id.action_share_file: {
291 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
292 return true;
293 }
294 case R.id.action_unshare_file: {
295 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
296 return true;
297 }
298 case R.id.action_open_file_with: {
299 openFile();
300 return true;
301 }
302 case R.id.action_remove_file: {
303 RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
304 dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
305 return true;
306 }
307 case R.id.action_see_details: {
308 seeDetails();
309 return true;
310 }
311 case R.id.action_send_file: {
312 sendFile();
313 return true;
314 }
315 case R.id.action_sync_file: {
316 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
317 return true;
318 }
319
320 default:
321 return false;
322 }
323 }
324
325 /**
326 * Update the file of the fragment with file value
327 *
328 * @param file The new file to set
329 */
330 public void updateFile(OCFile file) {
331 setFile(file);
332 }
333
334 private void sendFile() {
335 mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
336 }
337
338 private void seeDetails() {
339 mContainerActivity.showDetails(getFile());
340 }
341
342 @Override
343 public void onPause() {
344 Log_OC.e(TAG, "onPause");
345 super.onPause();
346 }
347
348 @Override
349 public void onResume() {
350 super.onResume();
351 Log_OC.e(TAG, "onResume");
352 }
353
354 @Override
355 public void onDestroy() {
356 Log_OC.e(TAG, "onDestroy");
357 super.onDestroy();
358 }
359
360 @Override
361 public void onStop() {
362 super.onStop();
363 Log_OC.e(TAG, "onStop");
364 if (mTextLoadTask != null)
365 mTextLoadTask.cancel(Boolean.TRUE);
366 }
367
368 /**
369 * Opens the previewed file with an external application.
370 */
371 private void openFile() {
372 mContainerActivity.getFileOperationsHelper().openFile(getFile());
373 finish();
374 }
375
376 /**
377 * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewTextFragment} to be previewed.
378 *
379 * @param file File to test if can be previewed.
380 * @return 'True' if the file can be handled by the fragment.
381 */
382 public static boolean canBePreviewed(OCFile file) {
383 return (file != null && file.isDown() && file.isText());
384 }
385
386 /**
387 * Finishes the preview
388 */
389 private void finish() {
390 getActivity().runOnUiThread(new Runnable() {
391 @Override
392 public void run() {
393 getActivity().onBackPressed();
394 }
395 });
396 }
397 }