• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2019 The Android Open Source Project
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *       http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.example.android.bubbles.data
17 
18 import android.content.Context
19 import androidx.annotation.MainThread
20 import androidx.lifecycle.LiveData
21 import androidx.lifecycle.MutableLiveData
22 import java.util.concurrent.Executor
23 import java.util.concurrent.Executors
24 
25 interface ChatRepository {
26     fun getContacts(): LiveData<List<Contact>>
27     fun findContact(id: Long): LiveData<Contact?>
28     fun findMessages(id: Long): LiveData<List<Message>>
29     fun sendMessage(id: Long, text: String)
30     fun activateChat(id: Long)
31     fun deactivateChat(id: Long)
32     fun showAsBubble(id: Long)
33     fun canBubble(): Boolean
34 }
35 
36 class DefaultChatRepository internal constructor(
37     private val notificationHelper: NotificationHelper,
38     private val executor: Executor
39 ) : ChatRepository {
40 
41     companion object {
42         private var instance: DefaultChatRepository? = null
43 
getInstancenull44         fun getInstance(context: Context): DefaultChatRepository {
45             return instance ?: synchronized(this) {
46                 instance ?: DefaultChatRepository(
47                     NotificationHelper(context),
48                     Executors.newFixedThreadPool(4)
49                 ).also {
50                     instance = it
51                 }
52             }
53         }
54     }
55 
56     private var currentChat: Long = 0L
57 
contactnull58     private val chats = Contact.CONTACTS.map { contact ->
59         contact.id to Chat(contact)
60     }.toMap()
61 
62     init {
63         notificationHelper.setUpNotificationChannels()
64     }
65 
66     @MainThread
getContactsnull67     override fun getContacts(): LiveData<List<Contact>> {
68         return MutableLiveData<List<Contact>>().apply {
69             postValue(Contact.CONTACTS)
70         }
71     }
72 
73     @MainThread
findContactnull74     override fun findContact(id: Long): LiveData<Contact?> {
75         return MutableLiveData<Contact>().apply {
76             postValue(Contact.CONTACTS.find { it.id == id })
77         }
78     }
79 
80     @MainThread
findMessagesnull81     override fun findMessages(id: Long): LiveData<List<Message>> {
82         val chat = chats.getValue(id)
83         return object : LiveData<List<Message>>() {
84 
85             private val listener = { messages: List<Message> ->
86                 postValue(messages)
87             }
88 
89             override fun onActive() {
90                 value = chat.messages
91                 chat.addListener(listener)
92             }
93 
94             override fun onInactive() {
95                 chat.removeListener(listener)
96             }
97         }
98     }
99 
100     @MainThread
sendMessagenull101     override fun sendMessage(id: Long, text: String) {
102         val chat = chats.getValue(id)
103         chat.addMessage(Message.Builder().apply {
104             sender = 0L // User
105             this.text = text
106             timestamp = System.currentTimeMillis()
107         })
108         executor.execute {
109             // The animal is typing...
110             Thread.sleep(5000L)
111             // Receive a reply.
112             chat.addMessage(chat.contact.reply(text))
113             // Show notification if the chat is not on the foreground.
114             if (chat.contact.id != currentChat) {
115                 notificationHelper.showNotification(chat, false)
116             }
117         }
118     }
119 
activateChatnull120     override fun activateChat(id: Long) {
121         currentChat = id
122         notificationHelper.dismissNotification(id)
123     }
124 
deactivateChatnull125     override fun deactivateChat(id: Long) {
126         if (currentChat == id) {
127             currentChat = 0
128         }
129     }
130 
showAsBubblenull131     override fun showAsBubble(id: Long) {
132         val chat = chats.getValue(id)
133         executor.execute {
134             notificationHelper.showNotification(chat, true)
135         }
136     }
137 
canBubblenull138     override fun canBubble(): Boolean {
139         return notificationHelper.canBubble()
140     }
141 }
142