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)
33         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)
39         set(value) = prefs.edit { putBoolean(PREF_MANAGED_EDUCATION, value) }
40 
41     /** Whether education view should show for the collapsed stack. */
42     fun shouldShowStackEducation(bubble: BubbleViewProvider?): Boolean {
43         val shouldShow = bubble != null &&
44                 bubble.isConversationBubble && // show education for conversation bubbles only
45                 (!hasSeenStackEducation || BubbleDebugConfig.forceShowUserEducation(context))
46         logDebug("Show stack edu: $shouldShow")
47         return shouldShow
48     }
49 
50     /** Whether the educational view should show for the expanded view "manage" menu. */
51     fun shouldShowManageEducation(bubble: BubbleViewProvider?): Boolean {
52         val shouldShow = bubble != null &&
53                 bubble.isConversationBubble && // show education for conversation bubbles only
54                 (!hasSeenManageEducation || BubbleDebugConfig.forceShowUserEducation(context))
55         logDebug("Show manage edu: $shouldShow")
56         return shouldShow
57     }
58 
59     private fun logDebug(message: String) {
60         if (DEBUG_USER_EDUCATION) {
61             Log.d(TAG, message)
62         }
63     }
64 
65     companion object {
66         private val TAG = if (TAG_WITH_CLASS_NAME) "BubbleEducationController" else TAG_BUBBLES
67         const val PREF_STACK_EDUCATION: String = "HasSeenBubblesOnboarding"
68         const val PREF_MANAGED_EDUCATION: String = "HasSeenBubblesManageOnboarding"
69     }
70 }
71 
72 /** Convenience extension method to check if the bubble is a conversation bubble */
73 private val BubbleViewProvider.isConversationBubble: Boolean
74     get() = if (this is Bubble) isConversation else false
75