1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.documentsui.ui;
17 
18 import android.app.Activity;
19 
20 import androidx.fragment.app.FragmentManager;
21 
22 import com.android.documentsui.R;
23 import com.android.documentsui.base.DocumentInfo;
24 import com.android.documentsui.base.Features;
25 import com.android.documentsui.picker.ConfirmFragment;
26 import com.android.documentsui.services.FileOperation;
27 import com.android.documentsui.services.FileOperationService;
28 import com.android.documentsui.services.FileOperationService.OpType;
29 import com.android.documentsui.services.FileOperations;
30 import com.android.documentsui.services.FileOperations.Callback.Status;
31 
32 import com.google.android.material.snackbar.Snackbar;
33 
34 public interface DialogController {
35 
36     // Dialogs used in FilesActivity
showFileOperationStatus(int status, int opType, int docCount)37     void showFileOperationStatus(int status, int opType, int docCount);
38 
39     /**
40      * There can be only one progress dialog active at the time. Each call to this
41      * method will discard any previously created progress dialogs.
42      */
showProgressDialog(String jobId, FileOperation operation)43     void showProgressDialog(String jobId, FileOperation operation);
44 
showNoApplicationFound()45     void showNoApplicationFound();
showOperationUnsupported()46     void showOperationUnsupported();
showViewInArchivesUnsupported()47     void showViewInArchivesUnsupported();
showDocumentsClipped(int size)48     void showDocumentsClipped(int size);
showActionNotAllowed()49     void showActionNotAllowed();
50 
51     /**
52      * Dialogs used when share file count over limit
53      */
showShareOverLimit(int size)54     void showShareOverLimit(int size);
55 
56     // Dialogs used in PickActivity
confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type)57     void confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type);
58 
59     // Should be private, but Java doesn't like me treating an interface like a mini-package.
60     public static final class RuntimeDialogController implements DialogController {
61 
62         private final Activity mActivity;
63         private final Features mFeatures;
64         private OperationProgressDialog mCurrentProgressDialog = null;
65 
RuntimeDialogController(Features features, Activity activity)66         public RuntimeDialogController(Features features, Activity activity) {
67             mFeatures = features;
68             mActivity = activity;
69         }
70 
71         @Override
showFileOperationStatus(@tatus int status, @OpType int opType, int docCount)72         public void showFileOperationStatus(@Status int status, @OpType int opType, int docCount) {
73             if (status == FileOperations.Callback.STATUS_REJECTED) {
74                 showOperationUnsupported();
75                 return;
76             }
77             if (status == FileOperations.Callback.STATUS_FAILED) {
78                 Snackbars.showOperationFailed(mActivity);
79                 return;
80             }
81 
82             if (docCount == 0) {
83                 // Nothing has been pasted, so there is no need to show a snackbar.
84                 return;
85             }
86 
87             if (shouldShowProgressDialogForOperation(opType)) {
88                 // The operation has a progress dialog created, so do not show a snackbar
89                 // for operation start, as it would duplicate the UI.
90                 return;
91             }
92 
93             switch (opType) {
94                 case FileOperationService.OPERATION_MOVE:
95                     Snackbars.showMove(mActivity, docCount);
96                     break;
97                 case FileOperationService.OPERATION_COPY:
98                     Snackbars.showCopy(mActivity, docCount);
99                     break;
100                 case FileOperationService.OPERATION_COMPRESS:
101                     Snackbars.showCompress(mActivity, docCount);
102                     break;
103                 case FileOperationService.OPERATION_EXTRACT:
104                     Snackbars.showExtract(mActivity, docCount);
105                     break;
106                 case FileOperationService.OPERATION_DELETE:
107                     Snackbars.showDelete(mActivity, docCount);
108                     break;
109                 default:
110                     throw new UnsupportedOperationException("Unsupported Operation: " + opType);
111             }
112         }
113 
shouldShowProgressDialogForOperation(@pType int opType)114         private boolean shouldShowProgressDialogForOperation(@OpType int opType) {
115             // TODO: Hook up progress dialog to the delete operation.
116             if (opType == FileOperationService.OPERATION_DELETE) {
117                 return false;
118             }
119 
120             return mFeatures.isJobProgressDialogEnabled();
121         }
122 
123         @Override
showProgressDialog(String jobId, FileOperation operation)124         public void showProgressDialog(String jobId, FileOperation operation) {
125             assert(operation.getOpType() != FileOperationService.OPERATION_UNKNOWN);
126 
127             if (!shouldShowProgressDialogForOperation(operation.getOpType())) {
128                 return;
129             }
130 
131             if (mCurrentProgressDialog != null) {
132                 mCurrentProgressDialog.dismiss();
133             }
134 
135             mCurrentProgressDialog = OperationProgressDialog.create(mActivity, jobId, operation);
136             mCurrentProgressDialog.show();
137         }
138 
139         @Override
showActionNotAllowed()140         public void showActionNotAllowed() {
141             // Shows as a last resort when a document is not allowed to share across users
142             Snackbars.makeSnackbar(
143                     mActivity, R.string.toast_action_not_allowed, Snackbar.LENGTH_LONG).show();
144         }
145 
146         @Override
showNoApplicationFound()147         public void showNoApplicationFound() {
148             Snackbars.makeSnackbar(
149                     mActivity, R.string.toast_no_application, Snackbar.LENGTH_LONG).show();
150         }
151 
152         @Override
showOperationUnsupported()153         public void showOperationUnsupported() {
154             Snackbars.showOperationRejected(mActivity);
155         }
156 
157         @Override
showViewInArchivesUnsupported()158         public void showViewInArchivesUnsupported() {
159             Snackbars.makeSnackbar(mActivity, R.string.toast_view_in_archives_unsupported,
160                     Snackbar.LENGTH_LONG).show();
161         }
162 
163         @Override
showDocumentsClipped(int size)164         public void showDocumentsClipped(int size) {
165             Snackbars.showDocumentsClipped(mActivity, size);
166         }
167 
168         @Override
showShareOverLimit(int size)169         public void showShareOverLimit(int size) {
170             String message = mActivity.getString(R.string.toast_share_over_limit, size);
171             Snackbars.makeSnackbar(mActivity, message, Snackbar.LENGTH_LONG).show();
172         }
173 
174         @Override
confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type)175         public void confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type) {
176             ConfirmFragment.show(fm, pickTarget, type);
177         }
178     }
179 
180     /**
181      * Create DialogController Impl.
182      */
create(Features features, Activity activity)183     static DialogController create(Features features, Activity activity) {
184         return new RuntimeDialogController(features, activity);
185     }
186 }
187