17b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin/* 27b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * Copyright (C) 2016 The Android Open Source Project 37b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * 47b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * Licensed under the Apache License, Version 2.0 (the "License"); 57b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * you may not use this file except in compliance with the License. 67b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * You may obtain a copy of the License at 77b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * 87b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * http://www.apache.org/licenses/LICENSE-2.0 97b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * 107b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * Unless required by applicable law or agreed to in writing, software 117b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * distributed under the License is distributed on an "AS IS" BASIS, 127b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * See the License for the specific language governing permissions and 147b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * limitations under the License. 157b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin */ 167b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 177b38f3465c3779384a17e84cc04609d9d68b56f4Ben Linpackage com.android.documentsui.dirlist; 187b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 197b38f3465c3779384a17e84cc04609d9d68b56f4Ben Linimport android.annotation.Nullable; 20339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Linimport android.app.AuthenticationRequiredException; 21339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Linimport android.app.PendingIntent; 22f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Linimport android.graphics.drawable.Drawable; 23339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Linimport android.util.Log; 247b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 25befdcc94a59e05d05971b28ddd47aa0a7601063aBen Linimport com.android.documentsui.DocumentsApplication; 26339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Linimport com.android.documentsui.Model.Update; 277b38f3465c3779384a17e84cc04609d9d68b56f4Ben Linimport com.android.documentsui.R; 28f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Linimport com.android.documentsui.base.RootInfo; 29e77419c6b4aecf4eb71b49898d6b63034a0771e4Ben Linimport com.android.documentsui.base.Shared; 307b38f3465c3779384a17e84cc04609d9d68b56f4Ben Linimport com.android.documentsui.dirlist.DocumentsAdapter.Environment; 317b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 327b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin/** 337b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin * Data object used by {@link InflateMessageDocumentHolder} and {@link HeaderMessageDocumentHolder}. 347b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin */ 35f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin 367b38f3465c3779384a17e84cc04609d9d68b56f4Ben Linabstract class Message { 377b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin protected final Environment mEnv; 38f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin // If the message has a button, this will be the default button call back. 39f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin protected final Runnable mDefaultCallback; 40f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin // If a message has a new callback when updated, this field should be updated. 41f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin protected @Nullable Runnable mCallback; 42f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin 437b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin private @Nullable CharSequence mMessageString; 44f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin private @Nullable CharSequence mButtonString; 45f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin private @Nullable Drawable mIcon; 467b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin private boolean mShouldShow = false; 477b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 48f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin Message(Environment env, Runnable defaultCallback) { 497b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mEnv = env; 50f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mDefaultCallback = defaultCallback; 517b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 527b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 537b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin abstract void update(Update Event); 547b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 55f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin protected void update(CharSequence messageString, CharSequence buttonString, Drawable icon) { 567b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin if (messageString == null) { 577b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin return; 587b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 597b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mMessageString = messageString; 60f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mButtonString = buttonString; 61f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mIcon = icon; 627b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mShouldShow = true; 637b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 647b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 657b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin void reset() { 667b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mMessageString = null; 67f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mIcon = null; 687b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mShouldShow = false; 697b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 707b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 71f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin void runCallback() { 72f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin if (mCallback != null) { 73f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mCallback.run(); 74f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin } else { 75f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mDefaultCallback.run(); 76f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin } 77f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin } 78f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin 79f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin Drawable getIcon() { 80f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin return mIcon; 817b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 827b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 837b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin boolean shouldShow() { 847b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin return mShouldShow; 857b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 867b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 877b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin CharSequence getMessageString() { 887b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin return mMessageString; 897b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 907b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 91f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin CharSequence getButtonString() { 92f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin return mButtonString; 93f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin } 94f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin 957b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin final static class HeaderMessage extends Message { 967b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 97339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Lin private static final String TAG = "HeaderMessage"; 98f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin 99f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin HeaderMessage(Environment env, Runnable callback) { 100f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin super(env, callback); 1017b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1027b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 1037b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin @Override 1047b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin void update(Update event) { 1057b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin reset(); 1067b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin // Error gets first dibs ... for now 1077b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin // TODO: These should be different Message objects getting updated instead of 1087b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin // overwriting. 109339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Lin if (event.hasAuthenticationException()) { 110befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin updateToAuthenticationExceptionHeader(event); 111f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin } else if (mEnv.getModel().error != null) { 112f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin update(mEnv.getModel().error, null, 113f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mEnv.getContext().getDrawable(R.drawable.ic_dialog_alert)); 1147b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } else if (mEnv.getModel().info != null) { 115f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin update(mEnv.getModel().info, null, 116f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mEnv.getContext().getDrawable(R.drawable.ic_dialog_info)); 1177b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1187b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 119f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin 120befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin private void updateToAuthenticationExceptionHeader(Update event) { 12198f8c5f502e049a6b85439d773949cdbaa0f78aeSteve McKay assert(mEnv.getFeatures().isRemoteActionsEnabled()); 12298f8c5f502e049a6b85439d773949cdbaa0f78aeSteve McKay 123f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin RootInfo root = mEnv.getDisplayState().stack.getRoot(); 124befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin String appName = DocumentsApplication 125befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin .getProvidersCache(mEnv.getContext()).getApplicationName(root.authority); 126befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin update(mEnv.getContext().getString(R.string.authentication_required, appName), 127befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin mEnv.getContext().getResources().getText(R.string.sign_in), 128f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mEnv.getContext().getDrawable(R.drawable.ic_dialog_info)); 129f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin mCallback = () -> { 130339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Lin AuthenticationRequiredException exception = 131339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Lin (AuthenticationRequiredException) event.getException(); 132800300826ebb50f5a26393bc966c27fa26e9a16fBen Lin mEnv.getActionHandler().startAuthentication(exception.getUserAction()); 133f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin }; 134f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin } 1357b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1367b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 1377b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin final static class InflateMessage extends Message { 1387b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 139f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin InflateMessage(Environment env, Runnable callback) { 140f8f06e946bd8d3965b2ea96f83d5e46575193f05Ben Lin super(env, callback); 1417b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1427b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 1437b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin @Override 1447b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin void update(Update event) { 1457b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin reset(); 146339968c3c0a47061afe0b3fc6b9ed0627f5b74c6Ben Lin if (event.hasException() && !event.hasAuthenticationException()) { 14702350fec8f0e47bea279dcecfd75804c8f689215Garfield Tan updateToInflatedErrorMesage(); 148befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin } else if (event.hasAuthenticationException()) { 149befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin updateToCantDisplayContentMessage(); 1507b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } else if (mEnv.getModel().getModelIds().length == 0) { 1517b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin updateToInflatedEmptyMessage(); 1527b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1537b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1547b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 15502350fec8f0e47bea279dcecfd75804c8f689215Garfield Tan private void updateToInflatedErrorMesage() { 15602350fec8f0e47bea279dcecfd75804c8f689215Garfield Tan update(mEnv.getContext().getResources().getText(R.string.query_error), null, 15702350fec8f0e47bea279dcecfd75804c8f689215Garfield Tan mEnv.getContext().getDrawable(R.drawable.hourglass)); 1587b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1597b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin 160befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin private void updateToCantDisplayContentMessage() { 161befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin update(mEnv.getContext().getResources().getText(R.string.cant_display_content), null, 162fe39ef04eec497d171d54423a3d93e85f3162c22Amin Shaikh mEnv.getContext().getDrawable(R.drawable.empty)); 163befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin } 164befdcc94a59e05d05971b28ddd47aa0a7601063aBen Lin 1657b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin private void updateToInflatedEmptyMessage() { 1667b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin final CharSequence message; 1677b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin if (mEnv.isInSearchMode()) { 1687b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin message = String.format( 1697b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin String.valueOf( 1707b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mEnv.getContext().getResources().getText(R.string.no_results)), 1717b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin mEnv.getDisplayState().stack.getRoot().title); 1727b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } else { 1737b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin message = mEnv.getContext().getResources().getText(R.string.empty); 1747b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 175fe39ef04eec497d171d54423a3d93e85f3162c22Amin Shaikh update(message, null, mEnv.getContext().getDrawable(R.drawable.empty)); 1767b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1777b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin } 1787b38f3465c3779384a17e84cc04609d9d68b56f4Ben Lin} 179