1 /*
2  * Copyright (C) 2014 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 
17 package com.android.systemui.statusbar.notification.row;
18 
19 import static android.graphics.PorterDuff.Mode.SRC_ATOP;
20 
21 import android.annotation.ColorInt;
22 import android.content.Context;
23 import android.content.res.ColorStateList;
24 import android.content.res.Configuration;
25 import android.content.res.Resources;
26 import android.graphics.ColorFilter;
27 import android.graphics.PorterDuffColorFilter;
28 import android.graphics.drawable.Drawable;
29 import android.util.AttributeSet;
30 import android.util.IndentingPrintWriter;
31 import android.view.View;
32 import android.widget.TextView;
33 
34 import androidx.annotation.NonNull;
35 
36 import com.android.settingslib.Utils;
37 import com.android.systemui.R;
38 import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
39 import com.android.systemui.statusbar.notification.stack.ViewState;
40 import com.android.systemui.util.DumpUtilsKt;
41 
42 import java.io.PrintWriter;
43 
44 public class FooterView extends StackScrollerDecorView {
45     private FooterViewButton mClearAllButton;
46     private FooterViewButton mManageButton;
47     private boolean mShowHistory;
48     // String cache, for performance reasons.
49     // Reading them from a Resources object can be quite slow sometimes.
50     private String mManageNotificationText;
51     private String mManageNotificationHistoryText;
52 
53     // Footer label
54     private TextView mSeenNotifsFooterTextView;
55     private String mSeenNotifsFilteredText;
56     private Drawable mSeenNotifsFilteredIcon;
57 
FooterView(Context context, AttributeSet attrs)58     public FooterView(Context context, AttributeSet attrs) {
59         super(context, attrs);
60     }
61 
62     @Override
findContentView()63     protected View findContentView() {
64         return findViewById(R.id.content);
65     }
66 
findSecondaryView()67     protected View findSecondaryView() {
68         return findViewById(R.id.dismiss_text);
69     }
70 
71     @Override
dump(PrintWriter pwOriginal, String[] args)72     public void dump(PrintWriter pwOriginal, String[] args) {
73         IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
74         super.dump(pw, args);
75         DumpUtilsKt.withIncreasedIndent(pw, () -> {
76             pw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility()));
77             pw.println("manageButton showHistory: " + mShowHistory);
78             pw.println("manageButton visibility: "
79                     + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility()));
80             pw.println("dismissButton visibility: "
81                     + DumpUtilsKt.visibilityString(mClearAllButton.getVisibility()));
82         });
83     }
84 
85     @Override
onFinishInflate()86     protected void onFinishInflate() {
87         super.onFinishInflate();
88         mClearAllButton = (FooterViewButton) findSecondaryView();
89         mManageButton = findViewById(R.id.manage_text);
90         mSeenNotifsFooterTextView = findViewById(R.id.unlock_prompt_footer);
91         updateResources();
92         updateContent();
93         updateColors();
94     }
95 
setFooterLabelVisible(boolean isVisible)96     public void setFooterLabelVisible(boolean isVisible) {
97         if (isVisible) {
98             mManageButton.setVisibility(View.GONE);
99             mClearAllButton.setVisibility(View.GONE);
100             mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
101         } else {
102             mManageButton.setVisibility(View.VISIBLE);
103             mClearAllButton.setVisibility(View.VISIBLE);
104             mSeenNotifsFooterTextView.setVisibility(View.GONE);
105         }
106     }
107 
setManageButtonClickListener(OnClickListener listener)108     public void setManageButtonClickListener(OnClickListener listener) {
109         mManageButton.setOnClickListener(listener);
110     }
111 
setClearAllButtonClickListener(OnClickListener listener)112     public void setClearAllButtonClickListener(OnClickListener listener) {
113         mClearAllButton.setOnClickListener(listener);
114     }
115 
isOnEmptySpace(float touchX, float touchY)116     public boolean isOnEmptySpace(float touchX, float touchY) {
117         return touchX < mContent.getX()
118                 || touchX > mContent.getX() + mContent.getWidth()
119                 || touchY < mContent.getY()
120                 || touchY > mContent.getY() + mContent.getHeight();
121     }
122 
showHistory(boolean showHistory)123     public void showHistory(boolean showHistory) {
124         if (mShowHistory == showHistory) {
125             return;
126         }
127         mShowHistory = showHistory;
128         updateContent();
129     }
130 
updateContent()131     private void updateContent() {
132         if (mShowHistory) {
133             mManageButton.setText(mManageNotificationHistoryText);
134             mManageButton.setContentDescription(mManageNotificationHistoryText);
135         } else {
136             mManageButton.setText(mManageNotificationText);
137             mManageButton.setContentDescription(mManageNotificationText);
138         }
139         mSeenNotifsFooterTextView.setText(mSeenNotifsFilteredText);
140         mSeenNotifsFooterTextView
141                 .setCompoundDrawablesRelative(mSeenNotifsFilteredIcon, null, null, null);
142     }
143 
isHistoryShown()144     public boolean isHistoryShown() {
145         return mShowHistory;
146     }
147 
148     @Override
onConfigurationChanged(Configuration newConfig)149     protected void onConfigurationChanged(Configuration newConfig) {
150         super.onConfigurationChanged(newConfig);
151         updateColors();
152         mClearAllButton.setText(R.string.clear_all_notifications_text);
153         mClearAllButton.setContentDescription(
154                 mContext.getString(R.string.accessibility_clear_all));
155         updateResources();
156         updateContent();
157     }
158 
159     /**
160      * Update the text and background colors for the current color palette and night mode setting.
161      */
updateColors()162     public void updateColors() {
163         Resources.Theme theme = mContext.getTheme();
164         final @ColorInt int textColor = getResources().getColor(R.color.notif_pill_text, theme);
165         final Drawable clearAllBg = theme.getDrawable(R.drawable.notif_footer_btn_background);
166         final Drawable manageBg = theme.getDrawable(R.drawable.notif_footer_btn_background);
167         // TODO(b/282173943): Remove redundant tinting once Resources are thread-safe
168         final @ColorInt int buttonBgColor =
169                 Utils.getColorAttrDefaultColor(mContext, com.android.internal.R.attr.colorSurface);
170         final ColorFilter bgColorFilter = new PorterDuffColorFilter(buttonBgColor, SRC_ATOP);
171         if (buttonBgColor != 0) {
172             clearAllBg.setColorFilter(bgColorFilter);
173             manageBg.setColorFilter(bgColorFilter);
174         }
175         mClearAllButton.setBackground(clearAllBg);
176         mClearAllButton.setTextColor(textColor);
177         mManageButton.setBackground(manageBg);
178         mManageButton.setTextColor(textColor);
179         final @ColorInt int labelTextColor =
180                 Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
181         mSeenNotifsFooterTextView.setTextColor(labelTextColor);
182         mSeenNotifsFooterTextView.setCompoundDrawableTintList(
183                 ColorStateList.valueOf(labelTextColor));
184     }
185 
updateResources()186     private void updateResources() {
187         mManageNotificationText = getContext().getString(R.string.manage_notifications_text);
188         mManageNotificationHistoryText = getContext()
189                 .getString(R.string.manage_notifications_history_text);
190         int unlockIconSize = getResources()
191                 .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size);
192         mSeenNotifsFilteredText = getContext().getString(R.string.unlock_to_see_notif_text);
193         mSeenNotifsFilteredIcon = getContext().getDrawable(R.drawable.ic_friction_lock_closed);
194         mSeenNotifsFilteredIcon.setBounds(0, 0, unlockIconSize, unlockIconSize);
195     }
196 
197     @Override
198     @NonNull
createExpandableViewState()199     public ExpandableViewState createExpandableViewState() {
200         return new FooterViewState();
201     }
202 
203     public class FooterViewState extends ExpandableViewState {
204         /**
205          * used to hide the content of the footer to animate.
206          * #hide is applied without animation, but #hideContent has animation.
207          */
208         public boolean hideContent;
209 
210         @Override
copyFrom(ViewState viewState)211         public void copyFrom(ViewState viewState) {
212             super.copyFrom(viewState);
213             if (viewState instanceof FooterViewState) {
214                 hideContent = ((FooterViewState) viewState).hideContent;
215             }
216         }
217 
218         @Override
applyToView(View view)219         public void applyToView(View view) {
220             super.applyToView(view);
221             if (view instanceof FooterView) {
222                 FooterView footerView = (FooterView) view;
223                 footerView.setContentVisible(!hideContent);
224             }
225         }
226     }
227 }
228