1 /*
2  * Copyright (C) 2023 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.wm.shell.bubbles
17 
18 import android.content.Context
19 import android.util.Log
20 import androidx.core.content.edit
21 import com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_USER_EDUCATION
22 import com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES
23 import com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME
24 
25 /** Manages bubble education flags. Provides convenience methods to check the education state */
26 class BubbleEducationController(private val context: Context) {
27     private val prefs = context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE)
28 
29     /** Whether the user has seen the stack education */
30     @get:JvmName(name = "hasSeenStackEducation")
31     var hasSeenStackEducation: Boolean
32         get() = prefs.getBoolean(PREF_STACK_EDUCATION, false)
<lambda>null33         set(value) = prefs.edit { putBoolean(PREF_STACK_EDUCATION, value) }
34 
35     /** Whether the user has seen the expanded view "manage" menu education */
36     @get:JvmName(name = "hasSeenManageEducation")
37     var hasSeenManageEducation: Boolean
38         get() = prefs.getBoolean(PREF_MANAGED_EDUCATION, false)
<lambda>null39         set(value) = prefs.edit { putBoolean(PREF_MANAGED_EDUCATION, value) }
40 
41     /** Whether education view should show for the collapsed stack. */
shouldShowStackEducationnull42     fun shouldShowStackEducation(bubble: BubbleViewProvider?): Boolean {
43         if (BubbleDebugConfig.neverShowUserEducation(context)) {
44             logDebug("Show stack edu: never")
45             return false
46         }
47 
48         val shouldShow =
49             bubble != null &&
50                 bubble.isConversationBubble && // show education for conversation bubbles only
51                 (!hasSeenStackEducation || BubbleDebugConfig.forceShowUserEducation(context))
52         logDebug("Show stack edu: $shouldShow")
53         return shouldShow
54     }
55 
56     /** Whether the educational view should show for the expanded view "manage" menu. */
shouldShowManageEducationnull57     fun shouldShowManageEducation(bubble: BubbleViewProvider?): Boolean {
58         if (BubbleDebugConfig.neverShowUserEducation(context)) {
59             logDebug("Show manage edu: never")
60             return false
61         }
62 
63         val shouldShow =
64             bubble != null &&
65                 bubble.isConversationBubble && // show education for conversation bubbles only
66                 (!hasSeenManageEducation || BubbleDebugConfig.forceShowUserEducation(context))
67         logDebug("Show manage edu: $shouldShow")
68         return shouldShow
69     }
70 
logDebugnull71     private fun logDebug(message: String) {
72         if (DEBUG_USER_EDUCATION) {
73             Log.d(TAG, message)
74         }
75     }
76 
77     companion object {
78         private val TAG = if (TAG_WITH_CLASS_NAME) "BubbleEducationController" else TAG_BUBBLES
79         const val PREF_STACK_EDUCATION: String = "HasSeenBubblesOnboarding"
80         const val PREF_MANAGED_EDUCATION: String = "HasSeenBubblesManageOnboarding"
81     }
82 }
83 
84 /** Convenience extension method to check if the bubble is a conversation bubble */
85 private val BubbleViewProvider.isConversationBubble: Boolean
86     get() = if (this is Bubble) isConversation else false
87