From 46424c44717adf84ac74a25fddeb6348514d37f2 Mon Sep 17 00:00:00 2001 From: Roei Edri Date: Mon, 4 Jul 2022 22:32:01 +0300 Subject: [PATCH 01/27] Added popup notification option for incoming call #454 #372 --- .../interactor/dialog/DialogsInteractor.kt | 2 + .../dialog/DialogsInteractorImpl.kt | 12 ++ .../preferences/PreferencesInteractor.kt | 17 ++- .../preferences/PreferencesInteractorImpl.kt | 39 +++-- .../com/chooloo/www/chooloolib/model/Call.kt | 19 ++- .../notification/CallNotification.kt | 137 ++++++++++-------- .../www/chooloolib/service/CallService.kt | 12 +- .../src/main/res/drawable/phone_msg.xml | 10 ++ chooloolib/src/main/res/menu/menu_chooloo.xml | 2 + chooloolib/src/main/res/values/strings.xml | 5 + .../java/com/chooloo/www/koler/KolerApp.kt | 3 - .../www/koler/ui/settings/SettingsFragment.kt | 6 + .../koler/ui/settings/SettingsViewState.kt | 8 + koler/src/main/res/menu/menu_koler.xml | 5 + koler/src/main/res/values/strings.xml | 1 + 15 files changed, 190 insertions(+), 88 deletions(-) create mode 100644 chooloolib/src/main/res/drawable/phone_msg.xml diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt index 21fbe534b..6596408e0 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt @@ -9,6 +9,7 @@ import androidx.annotation.RequiresPermission import androidx.annotation.StringRes import com.chooloo.www.chooloolib.interactor.base.BaseInteractor import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.Page import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor.ThemeMode import com.chooloo.www.chooloolib.model.SimAccount @@ -48,6 +49,7 @@ interface DialogsInteractor : BaseInteractor { fun askForSim(callback: (SimAccount?) -> Unit) fun askForDefaultPage(callback: (Page) -> Unit) fun askForThemeMode(callback: (ThemeMode) -> Unit) + fun askForIncomingCallMode(callback: (IncomingCallMode) -> Unit) fun askForRoute(callback: (CallAudiosInteractor.AudioRoute) -> Unit) fun askForPhoneAccountHandle( phonesAccountHandles: List, diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt index 080c86636..0cbcbb565 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt @@ -11,6 +11,7 @@ import com.chooloo.www.chooloolib.R import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.Page import com.chooloo.www.chooloolib.interactor.prompt.PromptsInteractor import com.chooloo.www.chooloolib.interactor.sim.SimsInteractor @@ -143,6 +144,17 @@ class DialogsInteractorImpl @Inject constructor( ) } + override fun askForIncomingCallMode(callback: (IncomingCallMode) -> Unit) { + askForChoice( + choices = IncomingCallMode.values().toList(), + titleRes = R.string.hint_incoming_call_mode, + choiceCallback = callback::invoke, + subtitleRes = R.string.explain_choose_incoming_call_mode, + selectedChoice = preferences.incomingCallMode, + choiceToString = { strings.getString(it.titleRes) } + ) + } + override fun askForRoute(callback: (CallAudiosInteractor.AudioRoute) -> Unit) { askForChoice( choiceCallback = callback::invoke, diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractor.kt index 7ae01c2ce..9e95bed0f 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractor.kt @@ -15,6 +15,7 @@ interface PreferencesInteractor : BaseInteractor var defaultPage: Page var themeMode: ThemeMode var accentTheme: AccentTheme + var incomingCallMode: IncomingCallMode fun setDefaultValues() @@ -34,12 +35,22 @@ interface PreferencesInteractor : BaseInteractor enum class Page(val key: String, val index: Int, val titleRes: Int) { CONTACTS("contacts", 0, R.string.contacts), - RECENTS("recents", 1, R.string.recents), - DEFAULT(CONTACTS.key, CONTACTS.index, R.string.default_page); + RECENTS("recents", 1, R.string.recents); companion object { fun fromKey(key: String?) = - values().associateBy(Page::key).getOrDefault(key ?: "", DEFAULT) + values().associateBy(Page::key).getOrDefault(key ?: "", CONTACTS) + } + } + + enum class IncomingCallMode(val key: String, val index: Int, val titleRes: Int) { + POP_UP("popup_notification", 0, R.string.pop_up_notification), + FULL_SCREEN("full_screen", 1, R.string.full_screen); + + companion object { + fun fromKey(key: String?) = + IncomingCallMode.values().associateBy(IncomingCallMode::key) + .getOrDefault(key ?: "", FULL_SCREEN) } } } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractorImpl.kt index 338c5a97d..f4052b1af 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/preferences/PreferencesInteractorImpl.kt @@ -5,6 +5,7 @@ import androidx.preference.PreferenceManager import com.chooloo.www.chooloolib.R import com.chooloo.www.chooloolib.interactor.base.BaseInteractorImpl import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.AccentTheme +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.Page import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor.ThemeMode import com.chooloo.www.chooloolib.util.PreferencesManager @@ -14,63 +15,69 @@ import javax.inject.Singleton @Singleton class PreferencesInteractorImpl @Inject constructor( - @ApplicationContext private val context: Context, - private val preferencesManager: PreferencesManager + private val prefs: PreferencesManager, + @ApplicationContext private val context: Context ) : BaseInteractorImpl(), PreferencesInteractor { override var isAnimations: Boolean - get() = preferencesManager.getBoolean( + get() = prefs.getBoolean( R.string.pref_key_animations, R.bool.pref_default_value_animations ) set(value) { - preferencesManager.putBoolean(R.string.pref_key_animations, value) + prefs.putBoolean(R.string.pref_key_animations, value) } override var isGroupRecents: Boolean - get() = preferencesManager.getBoolean( + get() = prefs.getBoolean( R.string.pref_key_group_recents, R.bool.pref_default_value_group_recents ) set(value) { - preferencesManager.putBoolean(R.string.pref_key_group_recents, value) + prefs.putBoolean(R.string.pref_key_group_recents, value) } override var isDialpadTones: Boolean - get() = preferencesManager.getBoolean( + get() = prefs.getBoolean( R.string.pref_key_dialpad_tones, R.bool.pref_default_value_dialpad_tones ) set(value) { - preferencesManager.putBoolean(R.string.pref_key_dialpad_tones, value) + prefs.putBoolean(R.string.pref_key_dialpad_tones, value) } override var isDialpadVibrate: Boolean - get() = preferencesManager.getBoolean( + get() = prefs.getBoolean( R.string.pref_key_dialpad_vibrate, R.bool.pref_default_value_dialpad_vibrate ) set(value) { - preferencesManager.putBoolean(R.string.pref_key_dialpad_vibrate, value) + prefs.putBoolean(R.string.pref_key_dialpad_vibrate, value) } override var defaultPage: Page - get() = Page.fromKey(preferencesManager.getString(R.string.pref_key_default_page)) + get() = Page.fromKey(prefs.getString(R.string.pref_key_default_page)) set(value) { - preferencesManager.putString(R.string.pref_key_default_page, value.key) + prefs.putString(R.string.pref_key_default_page, value.key) } override var themeMode: ThemeMode - get() = ThemeMode.fromKey(preferencesManager.getString(R.string.pref_key_theme_mode)) + get() = ThemeMode.fromKey(prefs.getString(R.string.pref_key_theme_mode)) set(value) { - preferencesManager.putString(R.string.pref_key_theme_mode, value.key) + prefs.putString(R.string.pref_key_theme_mode, value.key) } override var accentTheme: AccentTheme - get() = AccentTheme.fromKey(preferencesManager.getString(R.string.pref_key_color)) + get() = AccentTheme.fromKey(prefs.getString(R.string.pref_key_color)) set(value) { - preferencesManager.putString(R.string.pref_key_color, value.key) + prefs.putString(R.string.pref_key_color, value.key) + } + + override var incomingCallMode: IncomingCallMode + get() = IncomingCallMode.fromKey(prefs.getString(R.string.pref_key_incoming_call_mode)) + set(value) { + prefs.putString(R.string.pref_key_incoming_call_mode, value.key) } override fun setDefaultValues() { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt index 0fa6a2b1a..b131b888f 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt @@ -6,8 +6,7 @@ import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.Q import android.os.Bundle import android.telecom.Call.* -import android.telecom.Call.Details.CAPABILITY_HOLD -import android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL +import android.telecom.Call.Details.* import android.telecom.Connection import android.telecom.DisconnectCause import android.telecom.PhoneAccountHandle @@ -32,11 +31,13 @@ class Call(telecomCall: android.telecom.Call) : BaseObservable() private var _phoneAccountSelected: Boolean = false private val _id: String = Call::class.java.simpleName + sIdCounter++ private val _call: android.telecom.Call = telecomCall + private val _pastStates = mutableListOf() init { _call.registerCallback(object : android.telecom.Call.Callback() { override fun onStateChanged(call: android.telecom.Call?, state: Int) { invokeListeners { it.onCallChanged(this@Call) } + _pastStates.add(State.fromTelecomState(state)) } override fun onDetailsChanged(call: android.telecom.Call?, details: Details?) { @@ -143,6 +144,20 @@ class Call(telecomCall: android.telecom.Call) : BaseObservable() val isIncoming: Boolean get() = state == INCOMING + val isDirectionIncoming: Boolean + get() = if (SDK_INT >= Q) { + _call.details.callDirection == DIRECTION_INCOMING + } else { + INCOMING in _pastStates + } + + val isDirectionOutgoing: Boolean + get() = if (SDK_INT >= Q) { + _call.details.callDirection == DIRECTION_OUTGOING + } else { + DIALING in _pastStates + } + val children: List get() = _call.children.map(::Call).toList() diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt index 4d28bbe78..614cd8c88 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt @@ -1,7 +1,9 @@ package com.chooloo.www.chooloolib.notification import android.app.Notification +import android.app.Notification.CATEGORY_CALL import android.app.Notification.EXTRA_NOTIFICATION_ID +import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_HIGH import android.app.PendingIntent import android.app.PendingIntent.FLAG_CANCEL_CURRENT @@ -20,6 +22,8 @@ import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.calls.CallsInteractor import com.chooloo.www.chooloolib.interactor.color.ColorsInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.string.StringsInteractor import com.chooloo.www.chooloolib.model.Call import com.chooloo.www.chooloolib.model.Call.State.DISCONNECTED @@ -43,47 +47,34 @@ class CallNotification @Inject constructor( private val phones: PhonesInteractor, private val strings: StringsInteractor, private val callAudios: CallAudiosInteractor, + private val preferences: PreferencesInteractor, @ApplicationContext private val context: Context, private val notificationManager: NotificationManagerCompat ) : CallsInteractor.Listener, CallAudiosInteractor.Listener { private var _call: Call? = null + private val _channel + get() = if (_call?.isIncoming == true && preferences.incomingCallMode == IncomingCallMode.POP_UP) { + _channelImportanceHigh + } else { + _channelImportanceLow + } - override fun onNoCalls() { - detach() - cancel() - } - - override fun onCallChanged(call: Call) { - } - - override fun onMainCallChanged(call: Call) { - show(call) - _call = call - } - - - override fun onMuteChanged(isMuted: Boolean) { - _call?.let(::show) - } - - override fun onAudioRouteChanged(audiosRoute: CallAudiosInteractor.AudioRoute) { - _call?.let(::show) - } - - - fun attach() { - createNotificationChannel() - calls.registerListener(this) - callAudios.registerListener(this) - Thread.currentThread().setUncaughtExceptionHandler { _, _ -> cancel() } + private val _channelImportanceLow by lazy { + NotificationChannelCompat.Builder(CHANNEL_ID_PRIORITY_LOW, IMPORTANCE_DEFAULT) + .setName(strings.getString(R.string.call_notification_channel_name)) + .setDescription(strings.getString(R.string.call_notification_channel_description)) + .build() + .also(notificationManager::createNotificationChannel) } - fun detach() { - calls.unregisterListener(this) - callAudios.unregisterListener(this) - cancel() + private val _channelImportanceHigh by lazy { + NotificationChannelCompat.Builder(CHANNEL_ID_PRIORITY_HIGH, IMPORTANCE_HIGH) + .setName(strings.getString(R.string.call_notification_channel_name)) + .setDescription(strings.getString(R.string.call_notification_channel_description)) + .build() + .also(notificationManager::createNotificationChannel) } private val _contentPendingIntent by lazy { @@ -145,12 +136,25 @@ class CallNotification @Inject constructor( ) } - private val _channel by lazy { - NotificationChannelCompat.Builder(CHANNEL_ID, IMPORTANCE_HIGH) - .setName(strings.getString(R.string.call_notification_channel_name)) - .setDescription(strings.getString(R.string.call_notification_channel_description)) - .setLightsEnabled(true) - .build() + + override fun onNoCalls() { + detach() + } + + override fun onCallChanged(call: Call) { + } + + override fun onMainCallChanged(call: Call) { + _call = call + refresh() + } + + override fun onMuteChanged(isMuted: Boolean) { + refresh() + } + + override fun onAudioRouteChanged(audioRoute: CallAudiosInteractor.AudioRoute) { + refresh() } @@ -168,56 +172,69 @@ class CallNotification @Inject constructor( FLAG_CANCEL_CURRENT or FLAG_IMMUTABLE ) - private fun buildNotification(call: Call, callback: (Notification) -> Unit) { - phones.lookupAccount(call.number) { - val builder = NotificationCompat.Builder(context, CHANNEL_ID) + phones.lookupAccount(call.number) { phoneAccount -> + val builder = NotificationCompat.Builder(context, _channel.id) .setWhen(0) .setOngoing(true) .setColorized(true) .setPriority(PRIORITY) .setOnlyAlertOnce(true) - .setContentTitle(it?.displayString ?: call.number) + .setCategory(CATEGORY_CALL) + .setContentTitle(phoneAccount?.displayString ?: call.number) .setSmallIcon(R.drawable.icon_full_144) .setContentIntent(_contentPendingIntent) .setColor(colors.getAttrColor(R.attr.colorSecondary)) .setContentText(strings.getString(call.state.stringRes)) - if (call.isIncoming) { - builder.addAction(_answerAction) - } + if (call.state !in arrayOf(DISCONNECTED, DISCONNECTING)) { builder.addAction(_hangupAction) } - callAudios.isMuted?.let { isMuted -> - if (call.isCapable(CAPABILITY_MUTE)) { - builder.addAction(if (isMuted) _unmuteAction else _muteAction) + + if (call.isIncoming) { + builder.addAction(_answerAction) + } else if (call.state !in arrayOf(DISCONNECTED, DISCONNECTING)) { + callAudios.isMuted?.let { isMuted -> + if (call.isCapable(CAPABILITY_MUTE)) { + builder.addAction(if (isMuted) _unmuteAction else _muteAction) + } + } + + callAudios.isSpeakerOn?.let { isSpeakerOn -> + builder.addAction(if (isSpeakerOn) _unspeakerAction else _speakerAction) } } - callAudios.isSpeakerOn?.let { isSpeakerOn -> - builder.addAction(if (isSpeakerOn) _unspeakerAction else _speakerAction) - } + callback.invoke(builder.build()) } } - fun show(call: Call) { - buildNotification(call) { - notificationManager.notify(ID, it) - } + fun attach() { + calls.registerListener(this) + callAudios.registerListener(this) + Thread.currentThread().setUncaughtExceptionHandler { _, _ -> detach() } } - fun cancel() { + fun detach() { + calls.unregisterListener(this) + callAudios.unregisterListener(this) notificationManager.cancel(ID) } - fun createNotificationChannel() { - notificationManager.createNotificationChannel(_channel) + fun show(call: Call) { + buildNotification(call) { notificationManager.notify(ID, it) } } + fun refresh() { + _call?.let(::show) + } + + companion object { const val ID = 420 - const val CHANNEL_ID = "call_notification_channel" - const val PRIORITY = NotificationCompat.PRIORITY_LOW + const val PRIORITY = NotificationCompat.PRIORITY_HIGH + const val CHANNEL_ID_PRIORITY_LOW = "cnc_priority_low" + const val CHANNEL_ID_PRIORITY_HIGH = "cnc_priority_high" } } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt index da689856a..e88eab6f5 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt @@ -8,6 +8,8 @@ import android.telecom.InCallService import androidx.lifecycle.MutableLiveData import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.calls.CallsInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.model.Call import com.chooloo.www.chooloolib.notification.CallNotification import com.chooloo.www.chooloolib.repository.calls.CallsRepository @@ -21,6 +23,7 @@ class CallService : InCallService() { @Inject lateinit var callAudios: CallAudiosInteractor @Inject lateinit var callsRepository: CallsRepository @Inject lateinit var callsInteractor: CallsInteractor + @Inject lateinit var preferences: PreferencesInteractor @Inject lateinit var callNotification: CallNotification val calls = MutableLiveData>() @@ -34,19 +37,20 @@ class CallService : InCallService() { override fun onDestroy() { callNotification.detach() - callNotification.cancel() super.onDestroy() } override fun onCallAdded(telecomCall: android.telecom.Call) { super.onCallAdded(telecomCall) - addCall(Call(telecomCall)) - callsInteractor.entryAddCall(Call(telecomCall)) - if (!sIsActivityActive) { + val call = Call(telecomCall) + addCall(call) + callsInteractor.entryAddCall(call) + if (!sIsActivityActive && (preferences.incomingCallMode == IncomingCallMode.FULL_SCREEN || call.isDirectionOutgoing)) { startCallActivity() } } + override fun onCallRemoved(telecomCall: android.telecom.Call) { super.onCallRemoved(telecomCall) removeCall(Call(telecomCall)) diff --git a/chooloolib/src/main/res/drawable/phone_msg.xml b/chooloolib/src/main/res/drawable/phone_msg.xml new file mode 100644 index 000000000..8880aa5cb --- /dev/null +++ b/chooloolib/src/main/res/drawable/phone_msg.xml @@ -0,0 +1,10 @@ + + + diff --git a/chooloolib/src/main/res/menu/menu_chooloo.xml b/chooloolib/src/main/res/menu/menu_chooloo.xml index d17cf36df..febb48211 100644 --- a/chooloolib/src/main/res/menu/menu_chooloo.xml +++ b/chooloolib/src/main/res/menu/menu_chooloo.xml @@ -16,10 +16,12 @@ android:id="@+id/menu_chooloo_animations" android:icon="@drawable/animation" android:title="@string/pref_title_animations" /> + + System Dynamic In Development... + Pop-Up Notification + Full Screen @@ -55,6 +57,7 @@ Show animations Search Recents Search Contacts + Incoming Call Mode Search contacts & recents Vibrate on dialpad clicks Ask for a sim before each call @@ -67,6 +70,7 @@ %s is on hold Set Koler\'s theme mode, restart the app to see the changes Call with a different sim + Incoming call view mode Route audio to a different source Continue the current call using a specific phone account This contact will be deleted permanently @@ -114,6 +118,7 @@ dialpad_tones manage_blocked dialpad_vibrate + incoming_call_mode diff --git a/koler/src/main/java/com/chooloo/www/koler/KolerApp.kt b/koler/src/main/java/com/chooloo/www/koler/KolerApp.kt index b3374db02..18b178ac6 100644 --- a/koler/src/main/java/com/chooloo/www/koler/KolerApp.kt +++ b/koler/src/main/java/com/chooloo/www/koler/KolerApp.kt @@ -16,8 +16,5 @@ open class KolerApp : BaseApp() { override fun onCreate() { super.onCreate() PreferenceManager.setDefaultValues(this, R.xml.preferences_koler, false) - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - callNotification.createNotificationChannel() - } } } \ No newline at end of file diff --git a/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsFragment.kt b/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsFragment.kt index fdc01f48f..7283231ff 100644 --- a/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsFragment.kt +++ b/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsFragment.kt @@ -41,6 +41,12 @@ class SettingsFragment @Inject constructor() : ChoolooSettingsFragment() { ) } } + + askForIncomingCallModeEvent.observe(this@SettingsFragment) { + it.ifNew?.let { + dialogs.askForIncomingCallMode(viewState::onIncomingCallMode) + } + } } } } \ No newline at end of file diff --git a/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsViewState.kt b/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsViewState.kt index 165a78e04..8893a773b 100644 --- a/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsViewState.kt +++ b/koler/src/main/java/com/chooloo/www/koler/ui/settings/SettingsViewState.kt @@ -3,6 +3,7 @@ package com.chooloo.www.koler.ui.settings import com.chooloo.www.chooloolib.interactor.color.ColorsInteractor import com.chooloo.www.chooloolib.interactor.navigation.NavigationsInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor +import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.Page import com.chooloo.www.chooloolib.interactor.string.StringsInteractor import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor @@ -28,6 +29,8 @@ class SettingsViewState @Inject constructor( val askForGroupRecentsEvent = LiveEvent() val askForDialpadTonesEvent = LiveEvent() val askForDialpadVibrateEvent = LiveEvent() + val askForIncomingCallModeEvent = LiveEvent() + override fun onMenuItemClick(itemId: Int) { when (itemId) { @@ -35,6 +38,7 @@ class SettingsViewState @Inject constructor( R.id.menu_koler_dialpad_tones -> askForDialpadTonesEvent.call() R.id.menu_koler_group_recents -> askForGroupRecentsEvent.call() R.id.menu_koler_dialpad_vibrate -> askForDialpadVibrateEvent.call() + R.id.menu_koler_incoming_call_mode -> askForIncomingCallModeEvent.call() else -> super.onMenuItemClick(itemId) } } @@ -56,4 +60,8 @@ class SettingsViewState @Inject constructor( preferences.isGroupRecents = response navigations.goToLauncherActivity() } + + fun onIncomingCallMode(response: IncomingCallMode) { + preferences.incomingCallMode = response + } } diff --git a/koler/src/main/res/menu/menu_koler.xml b/koler/src/main/res/menu/menu_koler.xml index 777d3dd45..4b71c952d 100644 --- a/koler/src/main/res/menu/menu_koler.xml +++ b/koler/src/main/res/menu/menu_koler.xml @@ -19,4 +19,9 @@ android:id="@+id/menu_koler_group_recents" android:icon="@drawable/recent_actors" android:title="@string/pref_title_group_recents" /> + + \ No newline at end of file diff --git a/koler/src/main/res/values/strings.xml b/koler/src/main/res/values/strings.xml index 5012aa558..eb3e98045 100644 --- a/koler/src/main/res/values/strings.xml +++ b/koler/src/main/res/values/strings.xml @@ -4,6 +4,7 @@ Should ask for sim Dialpad click tones Group similar recents + Incoming Call Mode Vibrate on dialpad clicks dialer button \ No newline at end of file From 32885bf9c41cab6e3abfc9c4555fb68b155bfa3e Mon Sep 17 00:00:00 2001 From: Roei Edri Date: Tue, 26 Jul 2022 12:44:01 +0300 Subject: [PATCH 02/27] Removed call activity from history --- chooloolib/src/main/AndroidManifest.xml | 1 + koler/build.gradle | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/chooloolib/src/main/AndroidManifest.xml b/chooloolib/src/main/AndroidManifest.xml index a88a88862..ab8d82727 100644 --- a/chooloolib/src/main/AndroidManifest.xml +++ b/chooloolib/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ diff --git a/koler/build.gradle b/koler/build.gradle index 41637a86d..1e509ae24 100644 --- a/koler/build.gradle +++ b/koler/build.gradle @@ -28,7 +28,7 @@ android { dataBinding { //noinspection DataBindingWithoutKapt - enabled = true + enabled = true } buildTypes { From dc27c81c911c832a06f1d5fb63b67d980dc9c5f1 Mon Sep 17 00:00:00 2001 From: Roei Edri Date: Thu, 22 Dec 2022 00:13:27 +0200 Subject: [PATCH 03/27] Added permissioned fragment --- build.gradle | 6 +- chooloolib/build.gradle | 11 +- chooloolib/src/main/AndroidManifest.xml | 54 ++++----- .../chooloolib/{BaseApp.kt => ChoolooApp.kt} | 2 +- .../www/chooloolib/adapter/AccountsAdapter.kt | 4 +- .../chooloolib/adapter/CallItemsAdapter.kt | 13 ++- .../www/chooloolib/adapter/ChoicesAdapter.kt | 2 +- .../www/chooloolib/adapter/ContactsAdapter.kt | 13 ++- .../www/chooloolib/adapter/ListAdapter.kt | 4 +- .../www/chooloolib/adapter/MenuAdapter.kt | 2 +- .../www/chooloolib/adapter/PhonesAdapter.kt | 4 +- .../www/chooloolib/adapter/RecentsAdapter.kt | 25 ++-- .../{ => api}/service/CallService.kt | 27 +++-- .../contentresolver/BaseContentResolver.kt | 107 ------------------ .../contentresolver/BaseContentResolver.kt | 91 +++++++++++++++ .../ContactsContentResolver.kt | 16 ++- .../PhoneLookupContentResolver.kt | 16 ++- .../contentresolver/PhonesContentResolver.kt | 16 ++- .../RawContactsContentResolver.kt | 16 ++- .../contentresolver/RecentsContentResolver.kt | 15 ++- .../www/chooloolib/{ => data}/model/Call.kt | 4 +- .../chooloolib/{ => data}/model/CallList.kt | 2 +- .../{ => data}/model/ContactAccount.kt | 2 +- .../chooloolib/{ => data}/model/ListData.kt | 4 +- .../{ => data}/model/PhoneAccount.kt | 2 +- .../{ => data}/model/PhoneLookupAccount.kt | 2 +- .../{ => data}/model/RawContactAccount.kt | 2 +- .../{ => data}/model/RecentAccount.kt | 2 +- .../chooloolib/{ => data}/model/SimAccount.kt | 2 +- .../data/repository/calls/CallsRepository.kt | 8 ++ .../repository/calls/CallsRepositoryImpl.kt | 15 +++ .../repository/contacts/ContactsRepository.kt | 9 ++ .../contacts/ContactsRepositoryImpl.kt | 22 ++++ .../repository/phones/PhonesRepository.kt | 8 ++ .../repository/phones/PhonesRepositoryImpl.kt | 13 +++ .../rawcontacts/RawContactsRepository.kt | 8 ++ .../rawcontacts/RawContactsRepositoryImpl.kt | 13 +++ .../repository/recents/RecentsRepository.kt | 9 ++ .../recents/RecentsRepositoryImpl.kt | 19 ++++ .../contentresolver/ContentResolverFactory.kt | 2 +- .../ContentResolverFactoryImpl.kt | 20 ++-- .../di/factory/fragment/FragmentFactory.kt | 4 +- .../factory/fragment/FragmentFactoryImpl.kt | 5 +- .../di/factory/livedata/LiveDataFactory.kt | 13 --- .../factory/livedata/LiveDataFactoryImpl.kt | 29 ----- .../chooloolib/di/module/ApplicationModule.kt | 29 +++-- .../chooloolib/di/module/DispatcherModule.kt | 37 ++++++ .../www/chooloolib/di/module/ScopeModule.kt | 40 +++++++ .../interactor/audio/AudiosInteractor.kt | 4 +- .../interactor/blocked/BlockedInteractor.kt | 6 +- .../blocked/BlockedInteractorImpl.kt | 35 +++--- .../callaudio/CallAudiosInteractorImpl.kt | 2 +- .../interactor/calls/CallsInteractor.kt | 2 +- .../interactor/calls/CallsInteractorImpl.kt | 7 +- .../interactor/contacts/ContactsInteractor.kt | 13 ++- .../contacts/ContactsInteractorImpl.kt | 46 +++----- .../interactor/dialog/DialogsInteractor.kt | 2 +- .../dialog/DialogsInteractorImpl.kt | 9 +- .../permission/PermissionsInteractor.kt | 9 ++ .../permission/PermissionsInteractorImpl.kt | 33 +++++- .../phoneaccounts/PhonesInteractor.kt | 8 +- .../phoneaccounts/PhonesInteractorImpl.kt | 33 ++---- .../rawcontacts/RawContactsInteractor.kt | 5 +- .../rawcontacts/RawContactsInteractorImpl.kt | 11 +- .../interactor/recents/RecentsInteractor.kt | 8 +- .../recents/RecentsInteractorImpl.kt | 22 +--- .../interactor/sim/SimsInteractor.kt | 10 +- .../interactor/sim/SimsInteractorImpl.kt | 30 ++--- .../interactor/telecom/TelecomInteractor.kt | 2 +- .../telecom/TelecomInteractorImpl.kt | 2 +- .../chooloolib/livedata/ContactsLiveData.kt | 17 --- .../livedata/ContentProviderLiveData.kt | 50 -------- .../www/chooloolib/livedata/PhonesLiveData.kt | 14 --- .../livedata/RawContactsLiveData.kt | 16 --- .../chooloolib/livedata/RecentsLiveData.kt | 14 --- .../notification/CallNotification.kt | 73 ++++++------ .../repository/calls/CallsRepository.kt | 8 -- .../repository/calls/CallsRepositoryImpl.kt | 15 --- .../repository/contacts/ContactsRepository.kt | 9 -- .../contacts/ContactsRepositoryImpl.kt | 23 ---- .../repository/phones/PhonesRepository.kt | 8 -- .../repository/phones/PhonesRepositoryImpl.kt | 12 -- .../rawcontacts/RawContactsRepository.kt | 8 -- .../rawcontacts/RawContactsRepositoryImpl.kt | 12 -- .../repository/recents/RecentsRepository.kt | 9 -- .../recents/RecentsRepositoryImpl.kt | 21 ---- .../ui/accounts/AccountsFragment.kt | 6 +- .../ui/accounts/AccountsViewState.kt | 25 ++-- .../www/chooloolib/ui/base/BaseActivity.kt | 2 +- .../chooloolib/ui/base/BaseChoicesFragment.kt | 2 +- .../www/chooloolib/ui/base/BaseFragment.kt | 8 ++ .../www/chooloolib/ui/base/BaseView.kt | 3 +- .../www/chooloolib/ui/base/BaseViewState.kt | 12 +- .../www/chooloolib/ui/base/BottomFragment.kt | 4 +- .../ui/base/menu/BaseMenuFragment.kt | 2 +- .../ui/briefcontact/BriefContactFragment.kt | 4 +- .../ui/briefcontact/BriefContactViewState.kt | 24 ++-- .../menu/BriefContactMenuFragment.kt | 6 +- .../www/chooloolib/ui/call/CallActivity.kt | 4 +- .../www/chooloolib/ui/call/CallViewState.kt | 27 ++--- .../ui/callitems/CallItemsFragment.kt | 2 +- .../ui/callitems/CallItemsViewState.kt | 15 ++- .../ui/contacts/ContactsFragment.kt | 8 +- .../ui/contacts/ContactsViewState.kt | 34 ++---- .../ContactsSuggestionsFragment.kt | 7 +- .../ContactsSuggestionsViewState.kt | 7 +- .../chooloolib/ui/dialer/DialerFragment.kt | 12 +- .../chooloolib/ui/dialer/DialerViewState.kt | 5 +- .../chooloolib/ui/dialpad/DialpadFragment.kt | 7 +- .../chooloolib/ui/dialpad/DialpadViewState.kt | 3 +- .../www/chooloolib/ui/list/ListFragment.kt | 22 ++-- .../www/chooloolib/ui/list/ListViewState.kt | 30 ++--- .../ui/permission/PermissionFragment.kt | 31 +++++ .../ui/permission/PermissionViewState.kt | 52 +++++++++ .../ui/permissioned/PermissionedFragment.kt | 75 ++++++++++++ .../ui/permissioned/PermissionedViewState.kt | 23 ++++ .../DefaultDialerRequestActivity.kt | 2 +- .../permissions/PermissionRequestActivity.kt | 2 +- .../chooloolib/ui/phones/PhonesFragment.kt | 6 +- .../chooloolib/ui/phones/PhonesViewState.kt | 29 ++--- .../chooloolib/ui/prompt/PromptFragment.kt | 2 +- .../chooloolib/ui/recent/RecentFragment.kt | 3 +- .../chooloolib/ui/recent/RecentViewState.kt | 52 ++++----- .../ui/recent/menu/RecentMenuFragment.kt | 7 +- .../ui/recent/menu/RecentMenuViewState.kt | 12 +- .../chooloolib/ui/recents/RecentsFragment.kt | 12 +- .../chooloolib/ui/recents/RecentsViewState.kt | 43 ++----- .../recentshistory/RecentsHistoryFragment.kt | 4 +- .../recentshistory/RecentsHistoryViewState.kt | 4 +- .../ui/settings/SettingsFragment.kt | 5 +- .../widgets/listitemholder/ListItemHolder.kt | 4 +- .../chooloo/www/chooloolib/util/ViewUtils.kt | 9 -- .../drawable/bubble_background_no_ripple.xml | 6 - chooloolib/src/main/res/drawable/hearing.xml | 10 -- .../drawable/icon_button_color_selector.xml | 29 ----- .../src/main/res/layout/bottom_dialog.xml | 10 -- chooloolib/src/main/res/layout/list_item.xml | 16 +-- chooloolib/src/main/res/layout/permission.xml | 45 ++++++++ .../src/main/res/layout/permissioned.xml | 10 ++ chooloolib/src/main/res/values/array.xml | 9 -- chooloolib/src/main/res/values/bools.xml | 2 - chooloolib/src/main/res/values/dimens.xml | 23 ---- chooloolib/src/main/res/values/strings.xml | 1 + gradle.properties | 1 + gradle/wrapper/gradle-wrapper.properties | 7 +- koler/build.gradle | 2 +- koler/debug/output-metadata.json | 20 ++++ .../java/com/chooloo/www/koler/KolerApp.kt | 5 +- .../chooloo/www/koler/ui/main/MainActivity.kt | 2 +- .../www/koler/ui/main/MainViewState.kt | 7 +- .../www/koler/ui/settings/SettingsFragment.kt | 4 +- kontacts/build.gradle | 2 +- .../com/chooloo/www/kontacts/KontactsApp.kt | 4 +- .../kontacts/ui/contact/ContactFragment.kt | 2 +- .../kontacts/ui/contact/ContactViewState.kt | 22 ++-- .../www/kontacts/ui/main/MainActivity.kt | 2 +- .../www/kontacts/ui/main/MainViewState.kt | 2 +- .../ui/quickcontact/QuickContactActivity.kt | 2 +- 158 files changed, 1180 insertions(+), 1100 deletions(-) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{BaseApp.kt => ChoolooApp.kt} (92%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => api}/service/CallService.kt (81%) delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/BaseContentResolver.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/BaseContentResolver.kt rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/contentresolver/ContactsContentResolver.kt (76%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/contentresolver/PhoneLookupContentResolver.kt (73%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/contentresolver/PhonesContentResolver.kt (72%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/contentresolver/RawContactsContentResolver.kt (71%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/contentresolver/RecentsContentResolver.kt (78%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/Call.kt (98%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/CallList.kt (97%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/ContactAccount.kt (89%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/ListData.kt (96%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/PhoneAccount.kt (85%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/PhoneLookupAccount.kt (91%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/RawContactAccount.kt (95%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/RecentAccount.kt (96%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/{ => data}/model/SimAccount.kt (91%) create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepository.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepositoryImpl.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepository.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepositoryImpl.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepository.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepositoryImpl.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepository.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepositoryImpl.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepository.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepositoryImpl.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactory.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactoryImpl.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/DispatcherModule.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ScopeModule.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContactsLiveData.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContentProviderLiveData.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/PhonesLiveData.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RawContactsLiveData.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RecentsLiveData.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepository.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepositoryImpl.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepository.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepositoryImpl.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepository.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepositoryImpl.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepository.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepositoryImpl.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepository.kt delete mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepositoryImpl.kt rename chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/{ => suggestions}/ContactsSuggestionsFragment.kt (80%) rename chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/{ => suggestions}/ContactsSuggestionsViewState.kt (55%) create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionFragment.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionViewState.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedFragment.kt create mode 100644 chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedViewState.kt delete mode 100644 chooloolib/src/main/res/drawable/bubble_background_no_ripple.xml delete mode 100644 chooloolib/src/main/res/drawable/hearing.xml delete mode 100644 chooloolib/src/main/res/drawable/icon_button_color_selector.xml create mode 100644 chooloolib/src/main/res/layout/permission.xml create mode 100644 chooloolib/src/main/res/layout/permissioned.xml create mode 100644 koler/debug/output-metadata.json diff --git a/build.gradle b/build.gradle index e3706c381..fa17e26ef 100644 --- a/build.gradle +++ b/build.gradle @@ -11,9 +11,9 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.0.4' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10" - classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1' + classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' + classpath 'com.google.dagger:hilt-android-gradle-plugin:2.40.1' } } diff --git a/chooloolib/build.gradle b/chooloolib/build.gradle index b7b160c55..8d6705c23 100644 --- a/chooloolib/build.gradle +++ b/chooloolib/build.gradle @@ -9,11 +9,9 @@ android { compileSdk 31 defaultConfig { - versionCode 2 - versionName "2.0" minSdk 25 - targetSdk 31 + targetSdk 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -86,7 +84,10 @@ dependencies { 'com.google.android.material:material:1.6.0', 'com.github.abdularis:circularimageview:1.5', 'com.daimajia.androidanimations:library:2.4@aar', - 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0', - 'com.pushtorefresh.storio3:content-resolver:3.0.0' + 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1', + 'com.pushtorefresh.storio3:content-resolver:3.0.0', + 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1', + "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4", + "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9", ) } \ No newline at end of file diff --git a/chooloolib/src/main/AndroidManifest.xml b/chooloolib/src/main/AndroidManifest.xml index ab8d82727..7e86d7fa7 100644 --- a/chooloolib/src/main/AndroidManifest.xml +++ b/chooloolib/src/main/AndroidManifest.xml @@ -1,50 +1,50 @@ + xmlns:tools="http://schemas.android.com/tools" package="com.chooloo.www.chooloolib"> - - - - + + + + - + - + + android:name=".ui.call.CallActivity" + android:exported="false" + android:noHistory="true" + android:configChanges="screenSize|keyboardHidden" + android:excludeFromRecents="true" + android:screenOrientation="unspecified"/> + android:name=".ui.permissions.PermissionRequestActivity" + android:screenOrientation="unspecified"/> + android:name=".ui.permissions.DefaultDialerRequestActivity" + android:screenOrientation="unspecified"/> + android:name="preloaded_fonts" + android:resource="@array/preloaded_fonts"/> + android:name="com.chooloo.www.chooloolib.api.service.CallService" + android:exported="true" + android:foregroundServiceType="phoneCall" + android:permission="android.permission.BIND_INCALL_SERVICE"> + android:name="android.telecom.IN_CALL_SERVICE_UI" + android:value="true"/> - + - + \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/BaseApp.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ChoolooApp.kt similarity index 92% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/BaseApp.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/ChoolooApp.kt index f006ccec1..b02b9b4f9 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/BaseApp.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ChoolooApp.kt @@ -5,7 +5,7 @@ import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor import javax.inject.Inject -abstract class BaseApp : Application() { +abstract class ChoolooApp : Application() { @Inject lateinit var themes: ThemesInteractor @Inject lateinit var preferences: PreferencesInteractor diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/AccountsAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/AccountsAdapter.kt index f0481f55e..c15834326 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/AccountsAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/AccountsAdapter.kt @@ -3,8 +3,8 @@ package com.chooloo.www.chooloolib.adapter import com.chooloo.www.chooloolib.R import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor import com.chooloo.www.chooloolib.interactor.string.StringsInteractor -import com.chooloo.www.chooloolib.model.ListData -import com.chooloo.www.chooloolib.model.RawContactAccount +import com.chooloo.www.chooloolib.data.model.ListData +import com.chooloo.www.chooloolib.data.model.RawContactAccount import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import javax.inject.Inject diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/CallItemsAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/CallItemsAdapter.kt index 143bf071c..90e4e63ba 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/CallItemsAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/CallItemsAdapter.kt @@ -3,22 +3,25 @@ package com.chooloo.www.chooloolib.adapter import android.net.Uri import android.telecom.Call.Details.CAPABILITY_SEPARATE_FROM_CONFERENCE import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.Call +import com.chooloo.www.chooloolib.data.model.ListData +import com.chooloo.www.chooloolib.di.module.IoScope import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor -import com.chooloo.www.chooloolib.interactor.color.ColorsInteractor -import com.chooloo.www.chooloolib.interactor.drawable.DrawablesInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor -import com.chooloo.www.chooloolib.model.Call -import com.chooloo.www.chooloolib.model.ListData import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import javax.inject.Inject class CallItemsAdapter @Inject constructor( animationsInteractor: AnimationsInteractor, + @IoScope private val ioScope: CoroutineScope, private val phonesInteractor: PhonesInteractor, ) : ListAdapter(animationsInteractor) { override fun onBindListItem(listItemHolder: ListItemHolder, item: Call) { listItemHolder.apply { - phonesInteractor.lookupAccount(item.number) { account -> + ioScope.launch { + val account = phonesInteractor.lookupAccount(item.number) account?.photoUri?.let { setImageUri(Uri.parse(it)) } ?: run { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ChoicesAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ChoicesAdapter.kt index 271cfb318..7aa8b28cd 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ChoicesAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ChoicesAdapter.kt @@ -5,7 +5,7 @@ import android.view.LayoutInflater import android.view.ViewGroup import com.chooloo.www.chooloolib.databinding.ListItemBinding import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor -import com.chooloo.www.chooloolib.model.ListData +import com.chooloo.www.chooloolib.data.model.ListData import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ChoiceItemHolder import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import javax.inject.Inject diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ContactsAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ContactsAdapter.kt index f71a8ded4..32064f91c 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ContactsAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ContactsAdapter.kt @@ -1,19 +1,22 @@ package com.chooloo.www.chooloolib.adapter import android.net.Uri +import com.chooloo.www.chooloolib.data.model.ContactAccount +import com.chooloo.www.chooloolib.data.model.ListData +import com.chooloo.www.chooloolib.di.module.IoScope import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor -import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor -import com.chooloo.www.chooloolib.model.ContactAccount -import com.chooloo.www.chooloolib.model.ListData import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import com.chooloo.www.chooloolib.util.initials +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import javax.inject.Inject open class ContactsAdapter @Inject constructor( animations: AnimationsInteractor, private val phones: PhonesInteractor, + @IoScope private val ioScope: CoroutineScope ) : ListAdapter(animations) { private var _withFavs: Boolean = true private var _withHeaders: Boolean = true @@ -35,8 +38,8 @@ open class ContactsAdapter @Inject constructor( listItemHolder.apply { titleText = item.name imageInitials = item.name?.initials() - phones.getContactAccounts(item.id) { - captionText = it?.firstOrNull()?.number + ioScope.launch { + captionText = phones.getContactAccounts(item.id).firstOrNull()?.number } setImageUri(if (item.photoUri != null) Uri.parse(item.photoUri) else null) diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ListAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ListAdapter.kt index c5202ed64..cec95e834 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ListAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/ListAdapter.kt @@ -1,11 +1,12 @@ package com.chooloo.www.chooloolib.adapter +import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.chooloo.www.chooloolib.databinding.ListItemBinding import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor -import com.chooloo.www.chooloolib.model.ListData +import com.chooloo.www.chooloolib.data.model.ListData import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import com.l4digital.fastscroll.FastScroller @@ -28,6 +29,7 @@ abstract class ListAdapter( var items: List get() = _data.items + @SuppressLint("NotifyDataSetChanged") set(value) { _data = convertDataToListData(value) notifyDataSetChanged() diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/MenuAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/MenuAdapter.kt index afe242bf5..7f8e1681b 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/MenuAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/MenuAdapter.kt @@ -8,7 +8,7 @@ import android.view.MenuItem import android.view.ViewGroup import com.chooloo.www.chooloolib.databinding.ListItemBinding import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor -import com.chooloo.www.chooloolib.model.ListData +import com.chooloo.www.chooloolib.data.model.ListData import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import com.chooloo.www.chooloolib.ui.widgets.listitemholder.MenuItemHolder import javax.inject.Inject diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/PhonesAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/PhonesAdapter.kt index cefcab14b..ccba30982 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/PhonesAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/PhonesAdapter.kt @@ -4,8 +4,8 @@ import android.content.Context import android.provider.ContactsContract.CommonDataKinds.Phone import com.chooloo.www.chooloolib.R import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor -import com.chooloo.www.chooloolib.model.ListData -import com.chooloo.www.chooloolib.model.PhoneAccount +import com.chooloo.www.chooloolib.data.model.ListData +import com.chooloo.www.chooloolib.data.model.PhoneAccount import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/RecentsAdapter.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/RecentsAdapter.kt index 4103f006e..078e24f5d 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/RecentsAdapter.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/adapter/RecentsAdapter.kt @@ -4,18 +4,19 @@ import android.content.Context import android.net.Uri import android.provider.ContactsContract.CommonDataKinds.Phone import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.ListData +import com.chooloo.www.chooloolib.data.model.RecentAccount +import com.chooloo.www.chooloolib.di.module.IoScope import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor import com.chooloo.www.chooloolib.interactor.drawable.DrawablesInteractor -import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor -import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.recents.RecentsInteractor -import com.chooloo.www.chooloolib.model.ListData -import com.chooloo.www.chooloolib.model.RecentAccount import com.chooloo.www.chooloolib.ui.widgets.listitemholder.ListItemHolder import com.chooloo.www.chooloolib.util.getHoursString import com.chooloo.www.chooloolib.util.initials import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import javax.inject.Inject class RecentsAdapter @Inject constructor( @@ -23,8 +24,7 @@ class RecentsAdapter @Inject constructor( private val phones: PhonesInteractor, private val recents: RecentsInteractor, private val drawables: DrawablesInteractor, - private val preferences: PreferencesInteractor, - private val permissions: PermissionsInteractor, + @IoScope private val ioScope: CoroutineScope, @ApplicationContext private val context: Context ) : ListAdapter(animations) { @@ -43,10 +43,11 @@ class RecentsAdapter @Inject constructor( captionText = if (item.groupCount > 1) "(${item.groupCount}) $date ·" else "$date ·" - phones.lookupAccount(item.number) { - titleText = it?.name ?: item.number - setImageUri(if (it?.photoUri != null) Uri.parse(it.photoUri) else null) - it?.let { + ioScope.launch { + val account = phones.lookupAccount(item.number) + titleText = account?.name ?: item.number + setImageUri(if (account?.photoUri != null) Uri.parse(account.photoUri) else null) + account?.let { captionText = "$captionText ${ Phone.getTypeLabel( @@ -57,7 +58,9 @@ class RecentsAdapter @Inject constructor( } ·" imageInitials = it.name?.initials() if (it.name == null || it.name.isEmpty()) { - drawables.getDrawable(R.drawable.person)?.let(this::setImageDrawable) + drawables.getDrawable(R.drawable.person)?.let { + setImageDrawable(it) + } } } } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/api/service/CallService.kt similarity index 81% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/api/service/CallService.kt index e88eab6f5..cfeb9e8ce 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/service/CallService.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/api/service/CallService.kt @@ -1,33 +1,36 @@ -package com.chooloo.www.chooloolib.service +package com.chooloo.www.chooloolib.api.service import android.annotation.SuppressLint import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.telecom.CallAudioState import android.telecom.InCallService -import androidx.lifecycle.MutableLiveData import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.calls.CallsInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode -import com.chooloo.www.chooloolib.model.Call +import com.chooloo.www.chooloolib.data.model.Call import com.chooloo.www.chooloolib.notification.CallNotification -import com.chooloo.www.chooloolib.repository.calls.CallsRepository +import com.chooloo.www.chooloolib.data.repository.calls.CallsRepository import com.chooloo.www.chooloolib.ui.call.CallActivity import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import javax.inject.Inject @SuppressLint("NewApi") @AndroidEntryPoint class CallService : InCallService() { + private val _calls = MutableStateFlow>(arrayListOf()) + + val calls = _calls.asStateFlow() + @Inject lateinit var callAudios: CallAudiosInteractor @Inject lateinit var callsRepository: CallsRepository @Inject lateinit var callsInteractor: CallsInteractor @Inject lateinit var preferences: PreferencesInteractor @Inject lateinit var callNotification: CallNotification - val calls = MutableLiveData>() - override fun onCreate() { super.onCreate() @@ -70,15 +73,15 @@ class CallService : InCallService() { } private fun addCall(call: Call) { - val list = calls.value?.toMutableList() - list?.add(call) - calls.value = list + val list = calls.value.toMutableList() + list.add(call) + _calls.value = list } private fun removeCall(call: Call) { - val list = calls.value?.toMutableList() - list?.remove(call) - calls.value = list + val list = calls.value.toMutableList() + list.remove(call) + _calls.value = list } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/BaseContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/BaseContentResolver.kt deleted file mode 100644 index 97d0df0db..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/BaseContentResolver.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.chooloo.www.chooloolib.contentresolver - -import android.annotation.SuppressLint -import android.content.Context -import android.database.Cursor -import android.net.Uri -import com.pushtorefresh.storio3.contentresolver.impl.DefaultStorIOContentResolver -import com.pushtorefresh.storio3.contentresolver.queries.Query -import io.reactivex.BackpressureStrategy -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.disposables.Disposable -import io.reactivex.schedulers.Schedulers - -abstract class BaseContentResolver(private val context: Context) { - private var _filter: String? = null - - private val _ioContentResolver by lazy { - DefaultStorIOContentResolver.builder().contentResolver(context.contentResolver).build() - } - - private val _query: Query - get() = Query.builder() - .uri(finalUri) - .columns(*projection) - .whereArgs(*(selectionArgs ?: arrayOf())) - .where(if (selection == "") null else selection) - .sortOrder(if (sortOrder == "") null else sortOrder) - .build() - - val finalUri: Uri - get() = if (filterUri != null && _filter?.isNotEmpty() == true) { - Uri.withAppendedPath(filterUri, _filter) - } else { - uri - } - - - open var filter: String? - get() = _filter - set(value) { - _filter = if (value == "") null else value - } - - - private fun queryCursor() = - _ioContentResolver - .get() - .cursor() - .withQuery(_query) - .prepare() - .executeAsBlocking() - - @SuppressLint("CheckResult") - fun queryCursor(callback: (Cursor?) -> Unit): Disposable = - _ioContentResolver - .get() - .cursor() - .withQuery(_query) - .prepare() - .asRxSingle() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(callback::invoke) - - fun queryItems() = convertCursorToItems(queryCursor()) - - fun queryItems(callback: (List) -> Unit): Disposable = - queryCursor { callback.invoke(convertCursorToItems(it)) } - - @SuppressLint("CheckResult") - fun observeUri(observer: () -> Unit): Disposable = - _ioContentResolver - .observeChangesOfUri(finalUri, BackpressureStrategy.LATEST) - .subscribe { observer.invoke() } - .also { observer.invoke() } - - private fun observeCursor(observer: (Cursor?) -> Unit): Disposable = - _ioContentResolver - .get() - .cursor() - .withQuery(_query) - .prepare() - .asRxFlowable(BackpressureStrategy.LATEST) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(observer::invoke) - - fun observeItems(observer: (List) -> Unit) = - observeCursor { observer.invoke(convertCursorToItems(it)) } - - private fun convertCursorToItems(cursor: Cursor?): ArrayList { - val content = ArrayList() - while (cursor != null && cursor.moveToNext()) { - content.add(convertCursorToItem(cursor)) - } - cursor?.close() - return content - } - - abstract val uri: Uri - abstract val filterUri: Uri? - abstract val selection: String? - abstract val sortOrder: String? - abstract val projection: Array - abstract val selectionArgs: Array? - abstract fun convertCursorToItem(cursor: Cursor): ItemType -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/BaseContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/BaseContentResolver.kt new file mode 100644 index 000000000..127af4671 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/BaseContentResolver.kt @@ -0,0 +1,91 @@ +package com.chooloo.www.chooloolib.data.contentresolver + +import android.content.ContentResolver +import android.database.ContentObserver +import android.database.Cursor +import android.net.Uri +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import com.pushtorefresh.storio3.contentresolver.queries.Query +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +abstract class BaseContentResolver( + private val contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher +) { + private var _filter: String? = null + + private val _query: Query + get() = Query.builder() + .uri(finalUri) + .columns(*projection) + .whereArgs(*(selectionArgs ?: arrayOf())) + .where(if (selection == "") null else selection) + .sortOrder(if (sortOrder == "") null else sortOrder) + .build() + + val finalUri: Uri + get() = if (filterUri != null && _filter?.isNotEmpty() == true) { + Uri.withAppendedPath(filterUri, _filter) + } else { + uri + } + + open var filter: String? + get() = _filter + set(value) { + _filter = if (value == "") null else value + } + + suspend fun queryCursor() = withContext(ioDispatcher) { + contentResolver.query( + finalUri, + projection, + if (selection == "") null else selection, + selectionArgs ?: arrayOf(), + if (sortOrder == "") null else sortOrder + ) + } + + suspend fun queryItems() = convertCursorToItems(queryCursor()) + + fun getCursorFlow() = callbackFlow { + val callback = object : ContentObserver(null) { + override fun onChange(selfChange: Boolean) { + launch { + send(queryCursor()) + } + } + } + send(queryCursor()) + contentResolver.registerContentObserver(finalUri, false, callback) + awaitClose { contentResolver.unregisterContentObserver(callback) } + } + + fun getItemsFlow() = flow { + getCursorFlow().collect { + emit(convertCursorToItems(it)) + } + } + + private fun convertCursorToItems(cursor: Cursor?): ArrayList { + val content = ArrayList() + while (cursor != null && cursor.moveToNext() && !cursor.isClosed) { + content.add(convertCursorToItem(cursor)) + } + cursor?.close() + return content + } + + abstract val uri: Uri + abstract val filterUri: Uri? + abstract val selection: String? + abstract val sortOrder: String? + abstract val projection: Array + abstract val selectionArgs: Array? + abstract fun convertCursorToItem(cursor: Cursor): ItemType +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/ContactsContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/ContactsContentResolver.kt similarity index 76% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/ContactsContentResolver.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/ContactsContentResolver.kt index 857441e81..ec490239e 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/ContactsContentResolver.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/ContactsContentResolver.kt @@ -1,15 +1,21 @@ -package com.chooloo.www.chooloolib.contentresolver +package com.chooloo.www.chooloolib.data.contentresolver import android.annotation.SuppressLint -import android.content.Context +import android.content.ContentResolver import android.database.Cursor import android.net.Uri import android.provider.ContactsContract -import com.chooloo.www.chooloolib.model.ContactAccount +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import com.chooloo.www.chooloolib.data.model.ContactAccount import com.chooloo.www.chooloolib.util.SelectionBuilder +import kotlinx.coroutines.CoroutineDispatcher -class ContactsContentResolver(context: Context, contactId: Long? = null) : - BaseContentResolver(context) { +class ContactsContentResolver( + contactId: Long? = null, + contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher +) : + BaseContentResolver(contentResolver, ioDispatcher) { override val selectionArgs: Array? = null override val uri: Uri = ContactsContract.Contacts.CONTENT_URI diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/PhoneLookupContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/PhoneLookupContentResolver.kt similarity index 73% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/PhoneLookupContentResolver.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/PhoneLookupContentResolver.kt index e2a5353d2..1e8ed4750 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/PhoneLookupContentResolver.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/PhoneLookupContentResolver.kt @@ -1,14 +1,20 @@ -package com.chooloo.www.chooloolib.contentresolver +package com.chooloo.www.chooloolib.data.contentresolver import android.annotation.SuppressLint -import android.content.Context +import android.content.ContentResolver import android.database.Cursor import android.net.Uri import android.provider.ContactsContract.PhoneLookup -import com.chooloo.www.chooloolib.model.PhoneLookupAccount +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import com.chooloo.www.chooloolib.data.model.PhoneLookupAccount +import kotlinx.coroutines.CoroutineDispatcher -class PhoneLookupContentResolver(context: Context, number: String?) : - BaseContentResolver(context) { +class PhoneLookupContentResolver( + number: String?, + contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher +) : + BaseContentResolver(contentResolver, ioDispatcher) { override val selection: String? = null override val sortOrder: String? = null diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/PhonesContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/PhonesContentResolver.kt similarity index 72% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/PhonesContentResolver.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/PhonesContentResolver.kt index e96cc70ab..3754d4498 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/PhonesContentResolver.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/PhonesContentResolver.kt @@ -1,15 +1,21 @@ -package com.chooloo.www.chooloolib.contentresolver +package com.chooloo.www.chooloolib.data.contentresolver import android.annotation.SuppressLint -import android.content.Context +import android.content.ContentResolver import android.database.Cursor import android.net.Uri import android.provider.ContactsContract.CommonDataKinds.Phone -import com.chooloo.www.chooloolib.model.PhoneAccount +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import com.chooloo.www.chooloolib.data.model.PhoneAccount import com.chooloo.www.chooloolib.util.SelectionBuilder +import kotlinx.coroutines.CoroutineDispatcher -class PhonesContentResolver(context: Context, contactId: Long? = null) : - BaseContentResolver(context) { +class PhonesContentResolver( + contactId: Long? = null, + contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher +) : + BaseContentResolver(contentResolver, ioDispatcher) { override val uri: Uri = Phone.CONTENT_URI override val sortOrder: String? = null diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/RawContactsContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/RawContactsContentResolver.kt similarity index 71% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/RawContactsContentResolver.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/RawContactsContentResolver.kt index 8cee9c8d4..08a21e5c3 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/RawContactsContentResolver.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/RawContactsContentResolver.kt @@ -1,14 +1,20 @@ -package com.chooloo.www.chooloolib.contentresolver +package com.chooloo.www.chooloolib.data.contentresolver -import android.content.Context +import android.content.ContentResolver import android.database.Cursor import android.net.Uri import android.provider.ContactsContract.Contacts import androidx.core.database.getStringOrNull -import com.chooloo.www.chooloolib.model.RawContactAccount +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import com.chooloo.www.chooloolib.data.model.RawContactAccount +import kotlinx.coroutines.CoroutineDispatcher -class RawContactsContentResolver(context: Context, contactId: Long) : - BaseContentResolver(context) { +class RawContactsContentResolver( + contactId: Long, + contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher +) : + BaseContentResolver(contentResolver, ioDispatcher) { override val uri: Uri = Uri.withAppendedPath( Uri.withAppendedPath(Contacts.CONTENT_URI, contactId.toString()), Contacts.Entity.CONTENT_DIRECTORY diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/RecentsContentResolver.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/RecentsContentResolver.kt similarity index 78% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/RecentsContentResolver.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/RecentsContentResolver.kt index bbdba2aa1..85270e24e 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/contentresolver/RecentsContentResolver.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/contentresolver/RecentsContentResolver.kt @@ -1,19 +1,22 @@ -package com.chooloo.www.chooloolib.contentresolver +package com.chooloo.www.chooloolib.data.contentresolver import android.annotation.SuppressLint -import android.content.Context +import android.content.ContentResolver import android.database.Cursor import android.net.Uri import android.provider.CallLog -import com.chooloo.www.chooloolib.model.RecentAccount +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import com.chooloo.www.chooloolib.data.model.RecentAccount import com.chooloo.www.chooloolib.util.SelectionBuilder +import kotlinx.coroutines.CoroutineDispatcher import java.util.* class RecentsContentResolver( - context: Context, - private val recentId: Long? = null + private val recentId: Long? = null, + contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher ) : - BaseContentResolver(context) { + BaseContentResolver(contentResolver, ioDispatcher) { override val uri: Uri = CallLog.Calls.CONTENT_URI override val filterUri: Uri? = null diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/Call.kt similarity index 98% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/Call.kt index b131b888f..619a49161 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/Call.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/Call.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import android.net.Uri import android.os.Build @@ -13,7 +13,7 @@ import android.telecom.PhoneAccountHandle import android.telecom.PhoneAccountSuggestion import androidx.annotation.RequiresApi import com.chooloo.www.chooloolib.R -import com.chooloo.www.chooloolib.model.Call.State.* +import com.chooloo.www.chooloolib.data.model.Call.State.* import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable import java.util.stream.Collectors import java.util.stream.Stream diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/CallList.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/CallList.kt similarity index 97% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/CallList.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/CallList.kt index 1ead7a643..fec873a63 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/CallList.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/CallList.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import java.util.* diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/ContactAccount.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/ContactAccount.kt similarity index 89% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/ContactAccount.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/ContactAccount.kt index ea38b8f76..00e4cdc59 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/ContactAccount.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/ContactAccount.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model data class ContactAccount( val id: Long = 0, diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/ListData.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/ListData.kt similarity index 96% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/ListData.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/ListData.kt index 07d0ce77a..94a1d597c 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/ListData.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/ListData.kt @@ -1,6 +1,6 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model -import com.chooloo.www.chooloolib.model.RawContactAccount.RawContactType +import com.chooloo.www.chooloolib.data.model.RawContactAccount.RawContactType import com.chooloo.www.chooloolib.util.getRelativeDateString data class ListData( diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/PhoneAccount.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/PhoneAccount.kt similarity index 85% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/PhoneAccount.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/PhoneAccount.kt index 893b52d66..5fc19921e 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/PhoneAccount.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/PhoneAccount.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import android.provider.ContactsContract.CommonDataKinds.Phone diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/PhoneLookupAccount.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/PhoneLookupAccount.kt similarity index 91% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/PhoneLookupAccount.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/PhoneLookupAccount.kt index b2518e530..16705fe3b 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/PhoneLookupAccount.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/PhoneLookupAccount.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import android.provider.ContactsContract.CommonDataKinds.Phone diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/RawContactAccount.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/RawContactAccount.kt similarity index 95% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/RawContactAccount.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/RawContactAccount.kt index 5bb4b3f7a..1b1a6c2b5 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/RawContactAccount.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/RawContactAccount.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import android.provider.ContactsContract.CommonDataKinds.* import androidx.annotation.StringRes diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/RecentAccount.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/RecentAccount.kt similarity index 96% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/RecentAccount.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/RecentAccount.kt index 5d5c739e7..4b176b640 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/RecentAccount.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/RecentAccount.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import android.provider.CallLog import androidx.annotation.IntDef diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/SimAccount.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/SimAccount.kt similarity index 91% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/model/SimAccount.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/SimAccount.kt index 2cc4f084d..2a6490001 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/model/SimAccount.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/model/SimAccount.kt @@ -1,4 +1,4 @@ -package com.chooloo.www.chooloolib.model +package com.chooloo.www.chooloolib.data.model import android.telecom.PhoneAccount import android.telecom.PhoneAccountHandle diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepository.kt new file mode 100644 index 000000000..d0b6df5cc --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepository.kt @@ -0,0 +1,8 @@ +package com.chooloo.www.chooloolib.data.repository.calls + +import com.chooloo.www.chooloolib.data.model.Call +import kotlinx.coroutines.flow.Flow + +interface CallsRepository { + fun getCalls(): Flow> +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepositoryImpl.kt new file mode 100644 index 000000000..5e836f11c --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/calls/CallsRepositoryImpl.kt @@ -0,0 +1,15 @@ +package com.chooloo.www.chooloolib.data.repository.calls + +import com.chooloo.www.chooloolib.api.service.CallService +import com.chooloo.www.chooloolib.data.model.Call +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CallsRepositoryImpl @Inject constructor() : CallsRepository { + override fun getCalls(): Flow> = flow { + CallService.sInstance?.calls?.collect(this::emit) + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepository.kt new file mode 100644 index 000000000..5a65a9f81 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepository.kt @@ -0,0 +1,9 @@ +package com.chooloo.www.chooloolib.data.repository.contacts + +import com.chooloo.www.chooloolib.data.model.ContactAccount +import kotlinx.coroutines.flow.Flow + +interface ContactsRepository { + fun getContacts(): Flow> + fun getContact(contactId: Long): Flow +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepositoryImpl.kt new file mode 100644 index 000000000..430f50ab7 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/contacts/ContactsRepositoryImpl.kt @@ -0,0 +1,22 @@ +package com.chooloo.www.chooloolib.data.repository.contacts + +import com.chooloo.www.chooloolib.data.model.ContactAccount +import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ContactsRepositoryImpl @Inject constructor( + private val contentResolverFactory: ContentResolverFactory +) : ContactsRepository { + override fun getContacts() = + contentResolverFactory.getContactsContentResolver().getItemsFlow() + + override fun getContact(contactId: Long): Flow = flow { + contentResolverFactory.getContactsContentResolver(contactId).getItemsFlow().collect { + emit(it.getOrNull(0)) + } + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepository.kt new file mode 100644 index 000000000..90252e398 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepository.kt @@ -0,0 +1,8 @@ +package com.chooloo.www.chooloolib.data.repository.phones + +import com.chooloo.www.chooloolib.data.model.PhoneAccount +import kotlinx.coroutines.flow.Flow + +interface PhonesRepository { + fun getPhones(contactId: Long? = null): Flow> +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepositoryImpl.kt new file mode 100644 index 000000000..847dd7dba --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/phones/PhonesRepositoryImpl.kt @@ -0,0 +1,13 @@ +package com.chooloo.www.chooloolib.data.repository.phones + +import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class PhonesRepositoryImpl @Inject constructor( + private val contentResolverFactory: ContentResolverFactory +) : PhonesRepository { + override fun getPhones(contactId: Long?) = + contentResolverFactory.getPhonesContentResolver(contactId).getItemsFlow() +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepository.kt new file mode 100644 index 000000000..3d58bafec --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepository.kt @@ -0,0 +1,8 @@ +package com.chooloo.www.chooloolib.data.repository.rawcontacts + +import com.chooloo.www.chooloolib.data.model.RawContactAccount +import kotlinx.coroutines.flow.Flow + +interface RawContactsRepository { + fun getRawContacts(contactId: Long): Flow> +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepositoryImpl.kt new file mode 100644 index 000000000..8fda21a42 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/rawcontacts/RawContactsRepositoryImpl.kt @@ -0,0 +1,13 @@ +package com.chooloo.www.chooloolib.data.repository.rawcontacts + +import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class RawContactsRepositoryImpl @Inject constructor( + private val contentResolverFactory: ContentResolverFactory +) : RawContactsRepository { + override fun getRawContacts(contactId: Long) = + contentResolverFactory.getRawContactsContentResolver(contactId).getItemsFlow() +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepository.kt new file mode 100644 index 000000000..a10689fd6 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepository.kt @@ -0,0 +1,9 @@ +package com.chooloo.www.chooloolib.data.repository.recents + +import com.chooloo.www.chooloolib.data.model.RecentAccount +import kotlinx.coroutines.flow.Flow + +interface RecentsRepository { + fun getRecent(recentId: Long? = null): Flow + fun getRecents(): Flow> +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepositoryImpl.kt new file mode 100644 index 000000000..f845ea775 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/data/repository/recents/RecentsRepositoryImpl.kt @@ -0,0 +1,19 @@ +package com.chooloo.www.chooloolib.data.repository.recents + +import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory +import kotlinx.coroutines.flow.flow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class RecentsRepositoryImpl @Inject constructor( + private val contentResolverFactory: ContentResolverFactory +) : RecentsRepository { + override fun getRecents() = contentResolverFactory.getRecentsContentResolver().getItemsFlow() + + override fun getRecent(recentId: Long?) = flow { + contentResolverFactory.getRecentsContentResolver(recentId).getItemsFlow().collect { + emit(it.getOrNull(0)) + } + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactory.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactory.kt index 81c110c42..dc00ed975 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactory.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactory.kt @@ -1,6 +1,6 @@ package com.chooloo.www.chooloolib.di.factory.contentresolver -import com.chooloo.www.chooloolib.contentresolver.* +import com.chooloo.www.chooloolib.data.contentresolver.* interface ContentResolverFactory { fun getPhonesContentResolver(contactId: Long? = null): PhonesContentResolver diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactoryImpl.kt index 65d40d069..2984f1282 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactoryImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/contentresolver/ContentResolverFactoryImpl.kt @@ -1,27 +1,29 @@ package com.chooloo.www.chooloolib.di.factory.contentresolver -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.* -import dagger.hilt.android.qualifiers.ApplicationContext +import android.content.ContentResolver +import com.chooloo.www.chooloolib.data.contentresolver.* +import com.chooloo.www.chooloolib.di.module.IoDispatcher +import kotlinx.coroutines.CoroutineDispatcher import javax.inject.Inject import javax.inject.Singleton @Singleton class ContentResolverFactoryImpl @Inject constructor( - @ApplicationContext private val context: Context + private val contentResolver: ContentResolver, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher ) : ContentResolverFactory { override fun getRecentsContentResolver(recentId: Long?) = - RecentsContentResolver(context, recentId) + RecentsContentResolver(recentId, contentResolver, ioDispatcher) override fun getPhonesContentResolver(contactId: Long?) = - PhonesContentResolver(context, contactId) + PhonesContentResolver(contactId, contentResolver, ioDispatcher) override fun getContactsContentResolver(contactId: Long?) = - ContactsContentResolver(context, contactId) + ContactsContentResolver(contactId, contentResolver, ioDispatcher) override fun getRawContactsContentResolver(contactId: Long) = - RawContactsContentResolver(context, contactId) + RawContactsContentResolver(contactId, contentResolver, ioDispatcher) override fun getPhoneLookupContentResolver(number: String?) = - PhoneLookupContentResolver(context, number) + PhoneLookupContentResolver(number, contentResolver, ioDispatcher) } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactory.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactory.kt index 426f59ecf..12f550753 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactory.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactory.kt @@ -7,9 +7,10 @@ import com.chooloo.www.chooloolib.ui.briefcontact.BriefContactFragment import com.chooloo.www.chooloolib.ui.briefcontact.menu.BriefContactMenuFragment import com.chooloo.www.chooloolib.ui.callitems.CallItemsFragment import com.chooloo.www.chooloolib.ui.contacts.ContactsFragment -import com.chooloo.www.chooloolib.ui.contacts.ContactsSuggestionsFragment +import com.chooloo.www.chooloolib.ui.contacts.suggestions.ContactsSuggestionsFragment import com.chooloo.www.chooloolib.ui.dialer.DialerFragment import com.chooloo.www.chooloolib.ui.dialpad.DialpadFragment +import com.chooloo.www.chooloolib.ui.permission.PermissionFragment import com.chooloo.www.chooloolib.ui.phones.PhonesFragment import com.chooloo.www.chooloolib.ui.prompt.PromptFragment import com.chooloo.www.chooloolib.ui.recent.RecentFragment @@ -24,6 +25,7 @@ interface FragmentFactory { fun getContactsFragment(): ContactsFragment fun getCallItemsFragment(): CallItemsFragment fun getRecentMenuFragment(): RecentMenuFragment + fun getPermissionFragment(): PermissionFragment fun getRecentFragment(recentId: Long): RecentFragment fun getBriefContactMenuFragment(): BriefContactMenuFragment fun getDialerFragment(text: String? = null): DialerFragment diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactoryImpl.kt index 9c8b1dd3a..1f1d8ae86 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactoryImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/fragment/FragmentFactoryImpl.kt @@ -7,9 +7,10 @@ import com.chooloo.www.chooloolib.ui.briefcontact.BriefContactFragment import com.chooloo.www.chooloolib.ui.briefcontact.menu.BriefContactMenuFragment import com.chooloo.www.chooloolib.ui.callitems.CallItemsFragment import com.chooloo.www.chooloolib.ui.contacts.ContactsFragment -import com.chooloo.www.chooloolib.ui.contacts.ContactsSuggestionsFragment +import com.chooloo.www.chooloolib.ui.contacts.suggestions.ContactsSuggestionsFragment import com.chooloo.www.chooloolib.ui.dialer.DialerFragment import com.chooloo.www.chooloolib.ui.dialpad.DialpadFragment +import com.chooloo.www.chooloolib.ui.permission.PermissionFragment import com.chooloo.www.chooloolib.ui.phones.PhonesFragment import com.chooloo.www.chooloolib.ui.prompt.PromptFragment import com.chooloo.www.chooloolib.ui.recent.RecentFragment @@ -26,12 +27,12 @@ class FragmentFactoryImpl @Inject constructor() : FragmentFactory { override fun getSettingsFragment() = SettingsFragment() override fun getContactsFragment() = ContactsFragment() override fun getCallItemsFragment() = CallItemsFragment() + override fun getPermissionFragment() = PermissionFragment() override fun getRecentMenuFragment() = RecentMenuFragment() override fun getContactsSuggestionsFragment() = ContactsSuggestionsFragment() override fun getDialerFragment(text: String?) = DialerFragment.newInstance(text) override fun getRecentFragment(recentId: Long) = RecentFragment.newInstance(recentId) override fun getBriefContactMenuFragment() = BriefContactMenuFragment() - override fun getAccountsFragment(contactId: Long?) = AccountsFragment.newInstance(contactId) diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactory.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactory.kt deleted file mode 100644 index 98aaed0cf..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactory.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.chooloo.www.chooloolib.di.factory.livedata - -import com.chooloo.www.chooloolib.livedata.ContactsLiveData -import com.chooloo.www.chooloolib.livedata.PhonesLiveData -import com.chooloo.www.chooloolib.livedata.RawContactsLiveData -import com.chooloo.www.chooloolib.livedata.RecentsLiveData - -interface LiveDataFactory { - fun getPhonesLiveData(contactId: Long? = null): PhonesLiveData - fun getRecentsLiveData(recentId: Long? = null): RecentsLiveData - fun getRawContactsLiveData(contactId: Long): RawContactsLiveData - fun getContactsLiveData(contactId: Long? = null): ContactsLiveData -} diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactoryImpl.kt deleted file mode 100644 index 3b89742d0..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/factory/livedata/LiveDataFactoryImpl.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.chooloo.www.chooloolib.di.factory.livedata - -import android.content.Context -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.livedata.ContactsLiveData -import com.chooloo.www.chooloolib.livedata.PhonesLiveData -import com.chooloo.www.chooloolib.livedata.RawContactsLiveData -import com.chooloo.www.chooloolib.livedata.RecentsLiveData -import dagger.hilt.android.qualifiers.ApplicationContext -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LiveDataFactoryImpl @Inject constructor( - @ApplicationContext private val context: Context, - private val contentResolverFactory: ContentResolverFactory -) : LiveDataFactory { - override fun getRecentsLiveData(recentId: Long?) = - RecentsLiveData(context, recentId, contentResolverFactory) - - override fun getRawContactsLiveData(contactId: Long) = - RawContactsLiveData(context, contactId, contentResolverFactory) - - override fun getPhonesLiveData(contactId: Long?) = - PhonesLiveData(context, contactId, contentResolverFactory) - - override fun getContactsLiveData(contactId: Long?) = - ContactsLiveData(context, contactId, contentResolverFactory) -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ApplicationModule.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ApplicationModule.kt index eb2267557..f8f78816a 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ApplicationModule.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ApplicationModule.kt @@ -2,6 +2,7 @@ package com.chooloo.www.chooloolib.di.module import android.app.KeyguardManager import android.content.ClipboardManager +import android.content.ContentResolver import android.content.Context import android.media.AudioManager import android.os.PowerManager @@ -11,12 +12,20 @@ import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.view.inputmethod.InputMethodManager import androidx.core.app.NotificationManagerCompat +import com.chooloo.www.chooloolib.data.repository.calls.CallsRepository +import com.chooloo.www.chooloolib.data.repository.calls.CallsRepositoryImpl +import com.chooloo.www.chooloolib.data.repository.contacts.ContactsRepository +import com.chooloo.www.chooloolib.data.repository.contacts.ContactsRepositoryImpl +import com.chooloo.www.chooloolib.data.repository.phones.PhonesRepository +import com.chooloo.www.chooloolib.data.repository.phones.PhonesRepositoryImpl +import com.chooloo.www.chooloolib.data.repository.rawcontacts.RawContactsRepository +import com.chooloo.www.chooloolib.data.repository.rawcontacts.RawContactsRepositoryImpl +import com.chooloo.www.chooloolib.data.repository.recents.RecentsRepository +import com.chooloo.www.chooloolib.data.repository.recents.RecentsRepositoryImpl import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactoryImpl import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactoryImpl -import com.chooloo.www.chooloolib.di.factory.livedata.LiveDataFactory -import com.chooloo.www.chooloolib.di.factory.livedata.LiveDataFactoryImpl import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractorImpl import com.chooloo.www.chooloolib.interactor.audio.AudiosInteractor @@ -55,16 +64,6 @@ import com.chooloo.www.chooloolib.interactor.telecom.TelecomInteractor import com.chooloo.www.chooloolib.interactor.telecom.TelecomInteractorImpl import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractorImpl -import com.chooloo.www.chooloolib.repository.calls.CallsRepository -import com.chooloo.www.chooloolib.repository.calls.CallsRepositoryImpl -import com.chooloo.www.chooloolib.repository.contacts.ContactsRepository -import com.chooloo.www.chooloolib.repository.contacts.ContactsRepositoryImpl -import com.chooloo.www.chooloolib.repository.phones.PhonesRepository -import com.chooloo.www.chooloolib.repository.phones.PhonesRepositoryImpl -import com.chooloo.www.chooloolib.repository.rawcontacts.RawContactsRepository -import com.chooloo.www.chooloolib.repository.rawcontacts.RawContactsRepositoryImpl -import com.chooloo.www.chooloolib.repository.recents.RecentsRepository -import com.chooloo.www.chooloolib.repository.recents.RecentsRepositoryImpl import com.chooloo.www.chooloolib.util.PreferencesManager import dagger.Binds import dagger.Module @@ -84,6 +83,9 @@ class ApplicationModule { fun provideVibrator(@ApplicationContext context: Context): Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + @Provides + fun provideContentResolver(@ApplicationContext context: Context): ContentResolver = + context.contentResolver //region manager @Provides @@ -152,9 +154,6 @@ class ApplicationModule { //region factory - @Binds - fun bindLiveDataFactory(liveDataFactoryImpl: LiveDataFactoryImpl): LiveDataFactory - @Binds fun bindFragmentFactory(fragmentFactoryImpl: FragmentFactoryImpl): FragmentFactory diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/DispatcherModule.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/DispatcherModule.kt new file mode 100644 index 000000000..d0968b515 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/DispatcherModule.kt @@ -0,0 +1,37 @@ +package com.chooloo.www.chooloolib.di.module + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import javax.inject.Qualifier + +@InstallIn(SingletonComponent::class) +@Module +class DispatcherModule { + @DefaultDispatcher + @Provides + fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default + + @IoDispatcher + @Provides + fun provideIoDispatcher(): CoroutineDispatcher = Dispatchers.IO + + @MainDispatcher + @Provides + fun provideMainDispatcher(): CoroutineDispatcher = Dispatchers.Main +} + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class DefaultDispatcher + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class IoDispatcher + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class MainDispatcher \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ScopeModule.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ScopeModule.kt new file mode 100644 index 000000000..60d2a6b18 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/di/module/ScopeModule.kt @@ -0,0 +1,40 @@ +package com.chooloo.www.chooloolib.di.module + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import javax.inject.Qualifier + +@InstallIn(SingletonComponent::class) +@Module +class ScopeModule { + @DefaultDispatcher + @Provides + fun provideDefaultScope(@DefaultDispatcher defaultDispatcher: CoroutineDispatcher): CoroutineScope = + CoroutineScope(defaultDispatcher) + + @IoScope + @Provides + fun provideIoScope(@IoDispatcher ioDispatcher: CoroutineDispatcher): CoroutineScope = + CoroutineScope(ioDispatcher) + + @MainScope + @Provides + fun provideMainScope(@MainDispatcher mainDispatcher: CoroutineDispatcher): CoroutineScope = + CoroutineScope(mainDispatcher) +} + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class DefaultScope + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class IoScope + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class MainScope \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/audio/AudiosInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/audio/AudiosInteractor.kt index 30a9de269..106603e39 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/audio/AudiosInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/audio/AudiosInteractor.kt @@ -1,6 +1,7 @@ package com.chooloo.www.chooloolib.interactor.audio import com.chooloo.www.chooloolib.interactor.base.BaseInteractor +import kotlinx.coroutines.flow.StateFlow interface AudiosInteractor : BaseInteractor { interface Listener @@ -17,7 +18,7 @@ interface AudiosInteractor : BaseInteractor { fun vibrate(millis: Long = 10) - + enum class AudioMode(val mode: Int) { NORMAL(android.media.AudioManager.MODE_NORMAL), IN_CALL(android.media.AudioManager.MODE_IN_CALL), @@ -26,7 +27,6 @@ interface AudiosInteractor : BaseInteractor { IN_COMMUNICATION(android.media.AudioManager.MODE_IN_COMMUNICATION) } - companion object { const val SHORT_VIBRATE_LENGTH: Long = 20 } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractor.kt index c4d9f1691..330faf995 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractor.kt @@ -5,7 +5,7 @@ import com.chooloo.www.chooloolib.interactor.base.BaseInteractor interface BlockedInteractor : BaseInteractor { interface Listener - fun blockNumber(number: String) - fun unblockNumber(number: String) - fun isNumberBlocked(number: String): Boolean + suspend fun blockNumber(number: String) + suspend fun unblockNumber(number: String) + suspend fun isNumberBlocked(number: String): Boolean } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractorImpl.kt index 7bf22f0dc..dd100d64a 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/blocked/BlockedInteractorImpl.kt @@ -4,36 +4,45 @@ import android.content.ContentValues import android.content.Context import android.provider.BlockedNumberContract import android.provider.BlockedNumberContract.BlockedNumbers +import com.chooloo.www.chooloolib.di.module.IoDispatcher import com.chooloo.www.chooloolib.interactor.base.BaseInteractorImpl import com.chooloo.www.chooloolib.util.annotation.RequiresDefaultDialer import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.withContext import javax.inject.Inject import javax.inject.Singleton @Singleton class BlockedInteractorImpl @Inject constructor( - @ApplicationContext private val context: Context + @ApplicationContext private val context: Context, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher ) : BaseInteractorImpl(), BlockedInteractor { @RequiresDefaultDialer - override fun isNumberBlocked(number: String) = + override suspend fun isNumberBlocked(number: String) = withContext(ioDispatcher) { BlockedNumberContract.isBlocked(context, number) + } @RequiresDefaultDialer - override fun blockNumber(number: String) { - if (isNumberBlocked(number)) return - val contentValues = ContentValues() - contentValues.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number) - context.contentResolver.insert(BlockedNumbers.CONTENT_URI, contentValues) + override suspend fun blockNumber(number: String) { + withContext(ioDispatcher) { + if (isNumberBlocked(number)) return@withContext + val contentValues = ContentValues() + contentValues.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number) + context.contentResolver.insert(BlockedNumbers.CONTENT_URI, contentValues) + } } @RequiresDefaultDialer - override fun unblockNumber(number: String) { - if (!isNumberBlocked(number)) return - val contentValues = ContentValues() - contentValues.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number) - context.contentResolver.insert(BlockedNumbers.CONTENT_URI, contentValues)?.also { - context.contentResolver.delete(it, null, null) + override suspend fun unblockNumber(number: String) { + withContext(ioDispatcher) { + if (!isNumberBlocked(number)) return@withContext + val contentValues = ContentValues() + contentValues.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number) + context.contentResolver.insert(BlockedNumbers.CONTENT_URI, contentValues)?.also { + context.contentResolver.delete(it, null, null) + } } } } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/callaudio/CallAudiosInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/callaudio/CallAudiosInteractorImpl.kt index da6da81da..cf28e03db 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/callaudio/CallAudiosInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/callaudio/CallAudiosInteractorImpl.kt @@ -3,7 +3,7 @@ package com.chooloo.www.chooloolib.interactor.callaudio import android.telecom.CallAudioState import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor.AudioRoute import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor.AudioRoute.* -import com.chooloo.www.chooloolib.service.CallService +import com.chooloo.www.chooloolib.api.service.CallService import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable import javax.inject.Inject import javax.inject.Singleton diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractor.kt index 52e68c53d..76d12d07d 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractor.kt @@ -1,6 +1,6 @@ package com.chooloo.www.chooloolib.interactor.calls -import com.chooloo.www.chooloolib.model.Call +import com.chooloo.www.chooloolib.data.model.Call import com.chooloo.www.chooloolib.interactor.base.BaseInteractor interface CallsInteractor : BaseInteractor, Call.Listener { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractorImpl.kt index aea340d81..8be1da6a3 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/calls/CallsInteractorImpl.kt @@ -1,8 +1,8 @@ package com.chooloo.www.chooloolib.interactor.calls -import com.chooloo.www.chooloolib.model.Call -import com.chooloo.www.chooloolib.model.Call.State.* -import com.chooloo.www.chooloolib.model.CallList +import com.chooloo.www.chooloolib.data.model.Call +import com.chooloo.www.chooloolib.data.model.Call.State.* +import com.chooloo.www.chooloolib.data.model.CallList import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable import javax.inject.Inject import javax.inject.Singleton @@ -12,7 +12,6 @@ class CallsInteractorImpl @Inject constructor() : BaseObservable(), CallsInteractor { - private val _callList: CallList = CallList() override val mainCall: Call? diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractor.kt index 90d73caf3..7464828ef 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractor.kt @@ -1,16 +1,17 @@ package com.chooloo.www.chooloolib.interactor.contacts +import com.chooloo.www.chooloolib.data.model.ContactAccount import com.chooloo.www.chooloolib.interactor.base.BaseInteractor -import com.chooloo.www.chooloolib.model.ContactAccount +import kotlinx.coroutines.flow.Flow interface ContactsInteractor : BaseInteractor { interface Listener fun deleteContact(contactId: Long) - fun queryContact(contactId: Long, callback: (ContactAccount?) -> Unit) - fun observeContact(contactId: Long, callback: (ContactAccount?) -> Unit) + fun getContact(contactId: Long): Flow + fun getContacts(): Flow> fun toggleContactFavorite(contactId: Long, isFavorite: Boolean) - fun blockContact(contactId: Long, onSuccess: (() -> Unit)? = null) - fun unblockContact(contactId: Long, onSuccess: (() -> Unit)? = null) - fun getIsContactBlocked(contactId: Long, callback: (Boolean) -> Unit) + suspend fun blockContact(contactId: Long) + suspend fun unblockContact(contactId: Long) + suspend fun getIsContactBlocked(contactId: Long): Boolean } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractorImpl.kt index a762b030f..55e230c90 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/contacts/ContactsInteractorImpl.kt @@ -6,14 +6,12 @@ import android.content.Context import android.net.Uri import android.provider.ContactsContract.Contacts import androidx.annotation.RequiresPermission -import com.chooloo.www.chooloolib.contentresolver.ContactsContentResolver +import com.chooloo.www.chooloolib.data.repository.contacts.ContactsRepository import com.chooloo.www.chooloolib.interactor.base.BaseInteractorImpl import com.chooloo.www.chooloolib.interactor.blocked.BlockedInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor -import com.chooloo.www.chooloolib.model.ContactAccount import com.chooloo.www.chooloolib.util.annotation.RequiresDefaultDialer import dagger.hilt.android.qualifiers.ApplicationContext -import io.reactivex.disposables.CompositeDisposable import javax.inject.Inject import javax.inject.Singleton @@ -21,26 +19,13 @@ import javax.inject.Singleton class ContactsInteractorImpl @Inject constructor( private val phones: PhonesInteractor, private val blocked: BlockedInteractor, - private val disposables: CompositeDisposable, + private val contactsRepository: ContactsRepository, @ApplicationContext private val context: Context, ) : BaseInteractorImpl(), ContactsInteractor { - override fun queryContact(contactId: Long, callback: (ContactAccount?) -> Unit) { - disposables.add( - ContactsContentResolver(context, contactId).queryItems { contacts -> - contacts.let { callback.invoke(contacts.getOrNull(0)) } - } - ) - } - - override fun observeContact(contactId: Long, callback: (ContactAccount?) -> Unit) { - disposables.add( - ContactsContentResolver(context, contactId).observeItems { contacts -> - contacts.let { callback.invoke(contacts.getOrNull(0)) } - } - ) - } + override fun getContact(contactId: Long) = contactsRepository.getContact(contactId) + override fun getContacts() = contactsRepository.getContacts() @RequiresPermission(WRITE_CONTACTS) override fun deleteContact(contactId: Long) { @@ -53,18 +38,14 @@ class ContactsInteractorImpl @Inject constructor( } @RequiresDefaultDialer - override fun blockContact(contactId: Long, onSuccess: (() -> Unit)?) { - phones.getContactAccounts(contactId) { accounts -> - accounts?.forEach { blocked.blockNumber(it.number) } - onSuccess?.invoke() - } + override suspend fun blockContact(contactId: Long) { + val contactAccounts = phones.getContactAccounts(contactId) + contactAccounts.forEach { blocked.blockNumber(it.number) } } - override fun unblockContact(contactId: Long, onSuccess: (() -> Unit)?) { - phones.getContactAccounts(contactId) { accounts -> - accounts?.forEach { blocked.unblockNumber(it.number) } - onSuccess?.invoke() - } + override suspend fun unblockContact(contactId: Long) { + val contactAccounts = phones.getContactAccounts(contactId) + contactAccounts.forEach { blocked.unblockNumber(it.number) } } @RequiresPermission(WRITE_CONTACTS) @@ -75,9 +56,8 @@ class ContactsInteractorImpl @Inject constructor( context.contentResolver.update(Contacts.CONTENT_URI, contentValues, filter, null) } - override fun getIsContactBlocked(contactId: Long, callback: (Boolean) -> Unit) { - phones.getContactAccounts(contactId) { accounts -> - callback.invoke(accounts?.all { blocked.isNumberBlocked(it.number) } ?: false) - } + override suspend fun getIsContactBlocked(contactId: Long): Boolean { + val contactAccounts = phones.getContactAccounts(contactId) + return contactAccounts.all { blocked.isNumberBlocked(it.number) } } } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt index 6596408e0..911008cb4 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractor.kt @@ -12,7 +12,7 @@ import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.Page import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor.ThemeMode -import com.chooloo.www.chooloolib.model.SimAccount +import com.chooloo.www.chooloolib.data.model.SimAccount interface DialogsInteractor : BaseInteractor { interface Listener diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt index 0cbcbb565..606febe8a 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/dialog/DialogsInteractorImpl.kt @@ -8,6 +8,7 @@ import android.telecom.TelecomManager import androidx.annotation.RequiresApi import androidx.annotation.StringRes import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.SimAccount import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor @@ -17,13 +18,15 @@ import com.chooloo.www.chooloolib.interactor.prompt.PromptsInteractor import com.chooloo.www.chooloolib.interactor.sim.SimsInteractor import com.chooloo.www.chooloolib.interactor.string.StringsInteractor import com.chooloo.www.chooloolib.interactor.theme.ThemesInteractor.ThemeMode -import com.chooloo.www.chooloolib.model.SimAccount import com.chooloo.www.chooloolib.ui.base.BaseActivity import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable import com.chooloo.www.chooloolib.util.fullLabel import dagger.hilt.android.qualifiers.ActivityContext import dagger.hilt.android.scopes.ActivityScoped import dev.sasikanth.colorsheet.ColorSheet +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import javax.inject.Inject @ActivityScoped @@ -111,9 +114,9 @@ class DialogsInteractorImpl @Inject constructor( } override fun askForSim(callback: (SimAccount?) -> Unit) { - sims.getSimAccounts { simAccounts -> + CoroutineScope(Dispatchers.IO).launch { askForChoice( - choices = simAccounts, + choices = sims.getSimAccounts(), choiceCallback = callback::invoke, choiceToString = SimAccount::label, titleRes = R.string.hint_sim_account, diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractor.kt index a26b7f729..c22daab2e 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractor.kt @@ -22,12 +22,21 @@ interface PermissionsInteractor : BaseInteractor callback: (List) -> Unit ) + suspend fun checkPermission(permission: String): Boolean + suspend fun checkPermissions(vararg permissions: String): Boolean + fun runWithPermissions( permissions: Array, grantedCallback: () -> Unit, deniedCallback: (() -> Unit)? = null ) + fun runWithPermissions( + vararg permissions: String, + callback: (Boolean) -> Unit + ) + + fun runWithDefaultDialer( @StringRes errorMessageRes: Int? = null, callback: () -> Unit, diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractorImpl.kt index 2f6c8ab23..d95c8dd3c 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/permission/PermissionsInteractorImpl.kt @@ -8,6 +8,7 @@ import android.content.pm.PackageManager import android.telecom.TelecomManager import android.widget.Toast import androidx.core.app.ActivityCompat +import com.chooloo.www.chooloolib.di.module.IoDispatcher import com.chooloo.www.chooloolib.ui.permissions.DefaultDialerRequestActivity import com.chooloo.www.chooloolib.ui.permissions.PermissionRequestActivity import com.chooloo.www.chooloolib.ui.permissions.PermissionRequestActivity.Companion.PERMISSIONS_ARGUMENT_KEY @@ -16,14 +17,19 @@ import com.chooloo.www.chooloolib.ui.permissions.PermissionRequestActivity.Compa import com.chooloo.www.chooloolib.ui.permissions.PermissionRequestActivity.Companion.REQUEST_CODE_ARGUMENT_KEY import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject import javax.inject.Singleton +import kotlin.coroutines.resume @Singleton class PermissionsInteractorImpl @Inject constructor( private val telecomManager: TelecomManager, - @ApplicationContext private val context: Context + @ApplicationContext private val context: Context, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher ) : BaseObservable(), PermissionsInteractor { @@ -84,6 +90,23 @@ class PermissionsInteractorImpl @Inject constructor( _onPermissionsResultListeners[_requestCode] = callback } + override suspend fun checkPermissions(vararg permissions: String): Boolean = + withContext(ioDispatcher) { + suspendCancellableCoroutine { continuation -> + checkPermissions(*permissions) { results -> + continuation.resume(results.all { it.state == GRANTED }) + } + } + } + + override suspend fun checkPermission(permission: String): Boolean = withContext(ioDispatcher) { + suspendCancellableCoroutine { continuation -> + checkPermissions(permission) { results -> + continuation.resume(results.all { it.state == GRANTED }) + } + } + } + override fun runWithPermissions( permissions: Array, grantedCallback: () -> Unit, @@ -102,6 +125,14 @@ class PermissionsInteractorImpl @Inject constructor( } } + override fun runWithPermissions(vararg permissions: String, callback: (Boolean) -> Unit) { + runWithPermissions( + permissions as Array, + { callback.invoke(true) }, + { callback.invoke(false) } + ) + } + override fun runWithDefaultDialer(errorMessageRes: Int?, callback: () -> Unit) { checkDefaultDialer { if (it) { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractor.kt index 233a2b8a0..afbc394b7 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractor.kt @@ -1,12 +1,12 @@ package com.chooloo.www.chooloolib.interactor.phoneaccounts -import com.chooloo.www.chooloolib.model.PhoneAccount -import com.chooloo.www.chooloolib.model.PhoneLookupAccount +import com.chooloo.www.chooloolib.data.model.PhoneAccount +import com.chooloo.www.chooloolib.data.model.PhoneLookupAccount import com.chooloo.www.chooloolib.interactor.base.BaseInteractor interface PhonesInteractor : BaseInteractor { interface Listener - fun lookupAccount(number: String?, callback: (PhoneLookupAccount?) -> Unit) - fun getContactAccounts(contactId: Long, callback: (Array?) -> Unit) + suspend fun getContactAccounts(contactId: Long): List + suspend fun lookupAccount(number: String?): PhoneLookupAccount? } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractorImpl.kt index b4bbb00d2..3fde98603 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/phoneaccounts/PhonesInteractorImpl.kt @@ -1,38 +1,27 @@ package com.chooloo.www.chooloolib.interactor.phoneaccounts -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.PhoneLookupContentResolver -import com.chooloo.www.chooloolib.contentresolver.PhonesContentResolver -import com.chooloo.www.chooloolib.model.PhoneAccount -import com.chooloo.www.chooloolib.model.PhoneLookupAccount +import com.chooloo.www.chooloolib.data.model.PhoneAccount +import com.chooloo.www.chooloolib.data.model.PhoneLookupAccount +import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory import com.chooloo.www.chooloolib.interactor.base.BaseInteractorImpl -import dagger.hilt.android.qualifiers.ApplicationContext import io.reactivex.exceptions.OnErrorNotImplementedException import javax.inject.Inject import javax.inject.Singleton @Singleton class PhonesInteractorImpl @Inject constructor( - @ApplicationContext private val context: Context + private val contentResolverFactory: ContentResolverFactory, ) : BaseInteractorImpl(), PhonesInteractor { - override fun lookupAccount(number: String?, callback: (PhoneLookupAccount?) -> Unit) { + override suspend fun lookupAccount(number: String?): PhoneLookupAccount? = if (number == null || number.isEmpty()) { - callback.invoke(PhoneLookupAccount.PRIVATE) - return - } - try { - PhoneLookupContentResolver(context, number).queryItems { phones -> - callback.invoke(phones.getOrNull(0)) - } + PhoneLookupAccount.PRIVATE + } else try { + contentResolverFactory.getPhoneLookupContentResolver(number).queryItems().getOrNull(0) } catch (e: OnErrorNotImplementedException) { - callback.invoke(null) + null } - } - override fun getContactAccounts(contactId: Long, callback: (Array?) -> Unit) { - PhonesContentResolver(context, contactId).queryItems { - callback.invoke(it.toTypedArray()) - } - } + override suspend fun getContactAccounts(contactId: Long): List = + contentResolverFactory.getPhonesContentResolver(contactId).queryItems().toList() } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractor.kt index 05dd16c44..aa0bbdb9d 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractor.kt @@ -1,10 +1,11 @@ package com.chooloo.www.chooloolib.interactor.rawcontacts +import com.chooloo.www.chooloolib.data.model.RawContactAccount import com.chooloo.www.chooloolib.interactor.base.BaseInteractor -import com.chooloo.www.chooloolib.model.RawContactAccount +import kotlinx.coroutines.flow.Flow interface RawContactsInteractor : BaseInteractor { interface Listener - fun queryRawContacts(contactId: Long, callback: (List) -> Unit) + fun getRawContacts(contactId: Long): Flow> } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractorImpl.kt index 7397c9895..6e259dc92 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/rawcontacts/RawContactsInteractorImpl.kt @@ -1,21 +1,16 @@ package com.chooloo.www.chooloolib.interactor.rawcontacts -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.RawContactsContentResolver +import com.chooloo.www.chooloolib.data.repository.rawcontacts.RawContactsRepository import com.chooloo.www.chooloolib.interactor.base.BaseInteractorImpl -import com.chooloo.www.chooloolib.model.RawContactAccount -import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton class RawContactsInteractorImpl @Inject constructor( - @ApplicationContext private val context: Context + private val rawContactsRepository: RawContactsRepository ) : BaseInteractorImpl(), RawContactsInteractor { - override fun queryRawContacts(contactId: Long, callback: (List) -> Unit) { - RawContactsContentResolver(context, contactId).queryItems(callback) - } + override fun getRawContacts(contactId: Long) = rawContactsRepository.getRawContacts(contactId) } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractor.kt index 53844e37c..e9cc79885 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractor.kt @@ -1,15 +1,15 @@ package com.chooloo.www.chooloolib.interactor.recents +import com.chooloo.www.chooloolib.data.model.RecentAccount import com.chooloo.www.chooloolib.interactor.base.BaseInteractor -import com.chooloo.www.chooloolib.model.RecentAccount +import kotlinx.coroutines.flow.Flow interface RecentsInteractor : BaseInteractor { interface Listener fun deleteRecent(recentId: Long) - fun queryRecent(recentId: Long): RecentAccount? - fun queryRecent(recentId: Long, callback: (RecentAccount?) -> Unit) - fun observeRecent(recentId: Long, callback: (RecentAccount?) -> Unit) + fun getRecents(): Flow> + fun getRecent(recentId: Long): Flow fun getCallTypeImage(@RecentAccount.CallType callType: Int): Int fun getLastOutgoingCall(): String } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractorImpl.kt index 4ae359439..8b7278026 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/recents/RecentsInteractorImpl.kt @@ -5,16 +5,17 @@ import android.content.Context import android.provider.CallLog import androidx.annotation.RequiresPermission import com.chooloo.www.chooloolib.R -import com.chooloo.www.chooloolib.contentresolver.RecentsContentResolver +import com.chooloo.www.chooloolib.data.model.RecentAccount +import com.chooloo.www.chooloolib.data.repository.recents.RecentsRepository import com.chooloo.www.chooloolib.interactor.base.BaseInteractorImpl -import com.chooloo.www.chooloolib.model.RecentAccount import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton class RecentsInteractorImpl @Inject constructor( - @ApplicationContext private val context: Context + @ApplicationContext private val context: Context, + private val recentsRepository: RecentsRepository ) : BaseInteractorImpl(), RecentsInteractor { @RequiresPermission(WRITE_CALL_LOG) @@ -26,20 +27,9 @@ class RecentsInteractorImpl @Inject constructor( ) } - override fun queryRecent(recentId: Long) = - RecentsContentResolver(context, recentId).queryItems().getOrNull(0) + override fun getRecent(recentId: Long) = recentsRepository.getRecent(recentId) - override fun queryRecent(recentId: Long, callback: (RecentAccount?) -> Unit) { - RecentsContentResolver(context, recentId).queryItems { - callback.invoke(it.getOrNull(0)) - } - } - - override fun observeRecent(recentId: Long, callback: (RecentAccount?) -> Unit) { - RecentsContentResolver(context, recentId).observeItems { - callback.invoke(it.getOrNull(0)) - } - } + override fun getRecents() = recentsRepository.getRecents() override fun getCallTypeImage(@RecentAccount.CallType callType: Int) = when (callType) { RecentAccount.TYPE_INCOMING -> R.drawable.call_received diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractor.kt index d74e4b0d0..80d2a26bb 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractor.kt @@ -2,14 +2,14 @@ package com.chooloo.www.chooloolib.interactor.sim import android.telecom.PhoneAccount import android.telephony.SubscriptionInfo -import com.chooloo.www.chooloolib.model.SimAccount +import com.chooloo.www.chooloolib.data.model.SimAccount import com.chooloo.www.chooloolib.interactor.base.BaseInteractor interface SimsInteractor : BaseInteractor { interface Listener - fun getIsMultiSim(callback: (Boolean) -> Unit) - fun getSimAccounts(callback: (List) -> Unit) - fun getPhoneAccounts(callback: (List) -> Unit) - fun getSubscriptionInfos(callback: (List) -> Unit) + suspend fun getIsMultiSim(): Boolean + suspend fun getSimAccounts(): List + suspend fun getPhoneAccounts(): List + suspend fun getSubscriptionInfos(): List } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractorImpl.kt index 2c4a29ad2..9c386e9b1 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/sim/SimsInteractorImpl.kt @@ -6,7 +6,7 @@ import android.telecom.TelecomManager import android.telephony.SubscriptionInfo import android.telephony.SubscriptionManager import androidx.annotation.RequiresPermission -import com.chooloo.www.chooloolib.model.SimAccount +import com.chooloo.www.chooloolib.data.model.SimAccount import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable import javax.inject.Inject import javax.inject.Singleton @@ -18,30 +18,18 @@ class SimsInteractorImpl @Inject constructor( ) : BaseObservable(), SimsInteractor { @RequiresPermission(READ_PHONE_STATE) - override fun getIsMultiSim(callback: (isMultiSim: Boolean) -> Unit) { - callback.invoke(telecomManager.callCapablePhoneAccounts.size > 1) - } + override suspend fun getIsMultiSim(): Boolean = + telecomManager.callCapablePhoneAccounts.size > 1 @RequiresPermission(READ_PHONE_STATE) - override fun getSimAccounts(callback: (List) -> Unit) { - getPhoneAccounts { - callback.invoke(it.mapIndexed { index, phoneAccount -> - SimAccount(index, phoneAccount) - }) - } - } + override suspend fun getSimAccounts(): List = + getPhoneAccounts().mapIndexed(::SimAccount) @RequiresPermission(READ_PHONE_STATE) - override fun getPhoneAccounts(callback: (List) -> Unit) { - val phoneAccounts = ArrayList() - telecomManager.callCapablePhoneAccounts.forEach { pah -> - phoneAccounts.add(telecomManager.getPhoneAccount(pah)) - } - callback.invoke(phoneAccounts) - } + override suspend fun getPhoneAccounts(): List = + telecomManager.callCapablePhoneAccounts.map(telecomManager::getPhoneAccount) @RequiresPermission(READ_PHONE_STATE) - override fun getSubscriptionInfos(callback: (List) -> Unit) { - callback.invoke(subscriptionManager.activeSubscriptionInfoList) - } + override suspend fun getSubscriptionInfos(): List = + subscriptionManager.activeSubscriptionInfoList } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractor.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractor.kt index 60724801c..31a8b7148 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractor.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractor.kt @@ -1,7 +1,7 @@ package com.chooloo.www.chooloolib.interactor.telecom import com.chooloo.www.chooloolib.interactor.base.BaseInteractor -import com.chooloo.www.chooloolib.model.SimAccount +import com.chooloo.www.chooloolib.data.model.SimAccount interface TelecomInteractor : BaseInteractor { interface Listener {} diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractorImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractorImpl.kt index 8f2d90673..e7bafaecc 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractorImpl.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/interactor/telecom/TelecomInteractorImpl.kt @@ -11,7 +11,7 @@ import android.telecom.PhoneAccount import android.telecom.TelecomManager import android.telephony.TelephonyManager import androidx.annotation.RequiresPermission -import com.chooloo.www.chooloolib.model.SimAccount +import com.chooloo.www.chooloolib.data.model.SimAccount import com.chooloo.www.chooloolib.util.CallUtils import com.chooloo.www.chooloolib.util.PhoneNumberUtils import com.chooloo.www.chooloolib.util.baseobservable.BaseObservable diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContactsLiveData.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContactsLiveData.kt deleted file mode 100644 index b94c1c4e2..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContactsLiveData.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.chooloo.www.chooloolib.livedata - -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.ContactsContentResolver -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.model.ContactAccount -import dagger.hilt.android.qualifiers.ApplicationContext -import javax.inject.Singleton - -@Singleton -class ContactsLiveData( - @ApplicationContext context: Context, - private val contactId: Long? = null, - private val contentResolverFactory: ContentResolverFactory -) : ContentProviderLiveData(context) { - override val contentResolver by lazy { contentResolverFactory.getContactsContentResolver(contactId) } -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContentProviderLiveData.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContentProviderLiveData.kt deleted file mode 100644 index 69fdb0925..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/ContentProviderLiveData.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.chooloo.www.chooloolib.livedata - -import android.content.Context -import android.database.ContentObserver -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.contentresolver.BaseContentResolver -import dagger.hilt.android.qualifiers.ApplicationContext - -abstract class ContentProviderLiveData, T : Any>( - @ApplicationContext private val context: Context -) : - LiveData>() { - - private var observer = object : ContentObserver(null) { - override fun onChange(selfChange: Boolean) { - super.onChange(selfChange) - postValue(contentResolver.queryItems()) - } - } - - var filter: String? - get() = contentResolver.filter - @Synchronized - set(value) { - contentResolver.filter = value - onActive() - } - - - override fun onActive() { - detachObserver() - attachObserver() - value = contentResolver.queryItems() - } - - override fun onInactive() { - detachObserver() - } - - private fun attachObserver() { - context.contentResolver.registerContentObserver(contentResolver.finalUri, true, observer) - } - - private fun detachObserver() { - context.contentResolver.unregisterContentObserver(observer) - } - - - abstract val contentResolver: ContentResolver -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/PhonesLiveData.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/PhonesLiveData.kt deleted file mode 100644 index 381f1acb3..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/PhonesLiveData.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.chooloo.www.chooloolib.livedata - -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.PhonesContentResolver -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.model.PhoneAccount - -class PhonesLiveData( - context: Context, - private val contactId: Long? = null, - private val contentResolverFactory: ContentResolverFactory, -) : ContentProviderLiveData(context) { - override val contentResolver by lazy { contentResolverFactory.getPhonesContentResolver(contactId) } -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RawContactsLiveData.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RawContactsLiveData.kt deleted file mode 100644 index 0c16ebf84..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RawContactsLiveData.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.chooloo.www.chooloolib.livedata - -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.RawContactsContentResolver -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.model.RawContactAccount - -class RawContactsLiveData( - context: Context, - private val contactId: Long, - private val contentResolverFactory: ContentResolverFactory, -) : ContentProviderLiveData(context) { - override val contentResolver by lazy { - contentResolverFactory.getRawContactsContentResolver(contactId) - } -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RecentsLiveData.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RecentsLiveData.kt deleted file mode 100644 index 6df53b4de..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/livedata/RecentsLiveData.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.chooloo.www.chooloolib.livedata - -import android.content.Context -import com.chooloo.www.chooloolib.contentresolver.RecentsContentResolver -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.model.RecentAccount - -class RecentsLiveData( - context: Context, - private val recentId: Long? = null, - private val contentResolverFactory: ContentResolverFactory -) : ContentProviderLiveData(context) { - override val contentResolver by lazy { contentResolverFactory.getRecentsContentResolver(recentId) } -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt index 614cd8c88..cf2b85b07 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/notification/CallNotification.kt @@ -18,6 +18,10 @@ import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.Call +import com.chooloo.www.chooloolib.data.model.Call.State.DISCONNECTED +import com.chooloo.www.chooloolib.data.model.Call.State.DISCONNECTING +import com.chooloo.www.chooloolib.di.module.IoScope import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor import com.chooloo.www.chooloolib.interactor.calls.CallsInteractor import com.chooloo.www.chooloolib.interactor.color.ColorsInteractor @@ -25,9 +29,6 @@ import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor.Companion.IncomingCallMode import com.chooloo.www.chooloolib.interactor.string.StringsInteractor -import com.chooloo.www.chooloolib.model.Call -import com.chooloo.www.chooloolib.model.Call.State.DISCONNECTED -import com.chooloo.www.chooloolib.model.Call.State.DISCONNECTING import com.chooloo.www.chooloolib.receiver.CallBroadcastReceiver import com.chooloo.www.chooloolib.receiver.CallBroadcastReceiver.Companion.ACTION_HANGUP import com.chooloo.www.chooloolib.receiver.CallBroadcastReceiver.Companion.ACTION_MUTE @@ -36,6 +37,8 @@ import com.chooloo.www.chooloolib.receiver.CallBroadcastReceiver.Companion.ACTIO import com.chooloo.www.chooloolib.receiver.CallBroadcastReceiver.Companion.ACTION_UNSPEAKER import com.chooloo.www.chooloolib.ui.call.CallActivity import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import javax.inject.Inject import javax.inject.Singleton @@ -46,6 +49,7 @@ class CallNotification @Inject constructor( private val colors: ColorsInteractor, private val phones: PhonesInteractor, private val strings: StringsInteractor, + @IoScope private val ioScope: CoroutineScope, private val callAudios: CallAudiosInteractor, private val preferences: PreferencesInteractor, @ApplicationContext private val context: Context, @@ -172,41 +176,40 @@ class CallNotification @Inject constructor( FLAG_CANCEL_CURRENT or FLAG_IMMUTABLE ) - private fun buildNotification(call: Call, callback: (Notification) -> Unit) { - phones.lookupAccount(call.number) { phoneAccount -> - val builder = NotificationCompat.Builder(context, _channel.id) - .setWhen(0) - .setOngoing(true) - .setColorized(true) - .setPriority(PRIORITY) - .setOnlyAlertOnce(true) - .setCategory(CATEGORY_CALL) - .setContentTitle(phoneAccount?.displayString ?: call.number) - .setSmallIcon(R.drawable.icon_full_144) - .setContentIntent(_contentPendingIntent) - .setColor(colors.getAttrColor(R.attr.colorSecondary)) - .setContentText(strings.getString(call.state.stringRes)) - - if (call.state !in arrayOf(DISCONNECTED, DISCONNECTING)) { - builder.addAction(_hangupAction) - } - - if (call.isIncoming) { - builder.addAction(_answerAction) - } else if (call.state !in arrayOf(DISCONNECTED, DISCONNECTING)) { - callAudios.isMuted?.let { isMuted -> - if (call.isCapable(CAPABILITY_MUTE)) { - builder.addAction(if (isMuted) _unmuteAction else _muteAction) - } - } + private suspend fun buildNotification(call: Call, callback: (Notification) -> Unit) { + val phoneAccount = phones.lookupAccount(call.number) + val builder = NotificationCompat.Builder(context, _channel.id) + .setWhen(0) + .setOngoing(true) + .setColorized(true) + .setPriority(PRIORITY) + .setOnlyAlertOnce(true) + .setCategory(CATEGORY_CALL) + .setContentTitle(phoneAccount?.displayString ?: call.number) + .setSmallIcon(R.drawable.icon_full_144) + .setContentIntent(_contentPendingIntent) + .setColor(colors.getAttrColor(R.attr.colorSecondary)) + .setContentText(strings.getString(call.state.stringRes)) + + if (call.state !in arrayOf(DISCONNECTED, DISCONNECTING)) { + builder.addAction(_hangupAction) + } - callAudios.isSpeakerOn?.let { isSpeakerOn -> - builder.addAction(if (isSpeakerOn) _unspeakerAction else _speakerAction) + if (call.isIncoming) { + builder.addAction(_answerAction) + } else if (call.state !in arrayOf(DISCONNECTED, DISCONNECTING)) { + callAudios.isMuted?.let { isMuted -> + if (call.isCapable(CAPABILITY_MUTE)) { + builder.addAction(if (isMuted) _unmuteAction else _muteAction) } } - callback.invoke(builder.build()) + callAudios.isSpeakerOn?.let { isSpeakerOn -> + builder.addAction(if (isSpeakerOn) _unspeakerAction else _speakerAction) + } } + + callback.invoke(builder.build()) } @@ -223,7 +226,9 @@ class CallNotification @Inject constructor( } fun show(call: Call) { - buildNotification(call) { notificationManager.notify(ID, it) } + ioScope.launch { + buildNotification(call) { notificationManager.notify(ID, it) } + } } fun refresh() { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepository.kt deleted file mode 100644 index 1b713e881..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.chooloo.www.chooloolib.repository.calls - -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.model.Call - -interface CallsRepository { - fun getCalls(): LiveData> -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepositoryImpl.kt deleted file mode 100644 index d6ffbfa31..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/calls/CallsRepositoryImpl.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.chooloo.www.chooloolib.repository.calls - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import com.chooloo.www.chooloolib.model.Call -import com.chooloo.www.chooloolib.service.CallService -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CallsRepositoryImpl @Inject constructor() : CallsRepository { - val calls = MutableLiveData>() - - override fun getCalls(): LiveData> = CallService.sInstance?.calls ?: calls -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepository.kt deleted file mode 100644 index a97a9f49f..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.chooloo.www.chooloolib.repository.contacts - -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.model.ContactAccount - -interface ContactsRepository { - fun getContacts(): LiveData> - fun getContact(contactId: Long, callback: (ContactAccount?) -> Unit) -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepositoryImpl.kt deleted file mode 100644 index 60a948325..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/contacts/ContactsRepositoryImpl.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.chooloo.www.chooloolib.repository.contacts - -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.di.factory.livedata.LiveDataFactory -import com.chooloo.www.chooloolib.model.ContactAccount -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ContactsRepositoryImpl @Inject constructor( - private val liveDataFactory: LiveDataFactory, - private val contentResolverFactory: ContentResolverFactory -) : ContactsRepository { - override fun getContacts(): LiveData> = - liveDataFactory.getContactsLiveData() - - override fun getContact(contactId: Long, callback: (ContactAccount?) -> Unit) { - contentResolverFactory.getContactsContentResolver(contactId).queryItems { - callback.invoke(it.getOrNull(0)) - } - } -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepository.kt deleted file mode 100644 index 712eae141..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.chooloo.www.chooloolib.repository.phones - -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.model.PhoneAccount - -interface PhonesRepository { - fun getPhones(contactId: Long? = null): LiveData> -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepositoryImpl.kt deleted file mode 100644 index 6cc5445f5..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/phones/PhonesRepositoryImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.chooloo.www.chooloolib.repository.phones - -import com.chooloo.www.chooloolib.di.factory.livedata.LiveDataFactory -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PhonesRepositoryImpl @Inject constructor( - private val liveDataFactory: LiveDataFactory -) : PhonesRepository { - override fun getPhones(contactId: Long?) = liveDataFactory.getPhonesLiveData(contactId) -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepository.kt deleted file mode 100644 index b53529646..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.chooloo.www.chooloolib.repository.rawcontacts - -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.model.RawContactAccount - -interface RawContactsRepository { - fun getRawContacts(contactId: Long): LiveData> -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepositoryImpl.kt deleted file mode 100644 index e755e851c..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/rawcontacts/RawContactsRepositoryImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.chooloo.www.chooloolib.repository.rawcontacts - -import com.chooloo.www.chooloolib.di.factory.livedata.LiveDataFactory -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RawContactsRepositoryImpl @Inject constructor( - private val liveDataFactory: LiveDataFactory -) : RawContactsRepository { - override fun getRawContacts(contactId: Long) = liveDataFactory.getRawContactsLiveData(contactId) -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepository.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepository.kt deleted file mode 100644 index df5208347..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.chooloo.www.chooloolib.repository.recents - -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.model.RecentAccount - -interface RecentsRepository { - fun getRecents(): LiveData> - fun getRecent(recentId: Long? = null, callback: (RecentAccount?) -> Unit) -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepositoryImpl.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepositoryImpl.kt deleted file mode 100644 index 7bbfd91f3..000000000 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/repository/recents/RecentsRepositoryImpl.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.chooloo.www.chooloolib.repository.recents - -import com.chooloo.www.chooloolib.di.factory.contentresolver.ContentResolverFactory -import com.chooloo.www.chooloolib.di.factory.livedata.LiveDataFactory -import com.chooloo.www.chooloolib.model.RecentAccount -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecentsRepositoryImpl @Inject constructor( - private val liveDataFactory: LiveDataFactory, - private val contentResolverFactory: ContentResolverFactory -) : RecentsRepository { - override fun getRecents() = liveDataFactory.getRecentsLiveData() - - override fun getRecent(recentId: Long?, callback: (RecentAccount?) -> Unit) { - contentResolverFactory.getRecentsContentResolver(recentId).queryItems { - callback.invoke(it.getOrNull(0)) - } - } -} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsFragment.kt index dc8e36dd6..12eef7a9f 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsFragment.kt @@ -5,7 +5,7 @@ import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.adapter.AccountsAdapter import com.chooloo.www.chooloolib.interactor.telecom.TelecomInteractor -import com.chooloo.www.chooloolib.model.RawContactAccount +import com.chooloo.www.chooloolib.data.model.RawContactAccount import com.chooloo.www.chooloolib.ui.briefcontact.BriefContactFragment.Companion.ARG_CONTACT_ID import com.chooloo.www.chooloolib.ui.list.ListFragment import dagger.hilt.android.AndroidEntryPoint @@ -21,9 +21,9 @@ class AccountsFragment @Inject constructor() : @Inject lateinit var telecomInteractor: TelecomInteractor - override fun onSetup() { + override fun _onSetup() { viewState.onContactId(args.getLong(ARG_CONTACT_ID)) - super.onSetup() + super._onSetup() viewState.callEvent.observe(this@AccountsFragment) { it.ifNew?.let(telecomInteractor::callNumber) } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsViewState.kt index 4e541387d..60fc42962 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/accounts/AccountsViewState.kt @@ -1,12 +1,12 @@ package com.chooloo.www.chooloolib.ui.accounts -import androidx.lifecycle.LiveData +import android.Manifest.permission.READ_CONTACTS import androidx.lifecycle.MutableLiveData import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.RawContactAccount +import com.chooloo.www.chooloolib.data.repository.rawcontacts.RawContactsRepository import com.chooloo.www.chooloolib.interactor.navigation.NavigationsInteractor import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor -import com.chooloo.www.chooloolib.model.RawContactAccount -import com.chooloo.www.chooloolib.repository.rawcontacts.RawContactsRepository import com.chooloo.www.chooloolib.ui.list.ListViewState import com.chooloo.www.chooloolib.util.DataLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -14,22 +14,22 @@ import javax.inject.Inject @HiltViewModel class AccountsViewState @Inject constructor( + permissions: PermissionsInteractor, private val navigations: NavigationsInteractor, - private val permissions: PermissionsInteractor, private val rawContactsRepository: RawContactsRepository ) : - ListViewState() { + ListViewState(permissions) { override val noResultsIconRes = R.drawable.call override val noResultsTextRes = R.string.error_no_results_phones - override val noPermissionsTextRes = R.string.error_no_permissions_phones + + override val requiredPermissions = listOf(READ_CONTACTS) + + override val itemsFlow get() = contactId.value?.let(rawContactsRepository::getRawContacts) val contactId = MutableLiveData(0L) val callEvent = DataLiveEvent() - private val accountsLiveData - get() = contactId.value?.let { rawContactsRepository.getRawContacts(it) } - override fun onItemRightClick(item: RawContactAccount) { super.onItemRightClick(item) @@ -38,13 +38,6 @@ class AccountsViewState @Inject constructor( } } - override fun getItemsObservable(callback: (LiveData>) -> Unit) { - permissions.runWithReadContactsPermissions { - onPermissionsChanged(it) - if (it) accountsLiveData?.let(callback::invoke) - } - } - fun onContactId(contactId: Long) { this.contactId.value = contactId } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseActivity.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseActivity.kt index 9ce32dac7..dfbd32172 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseActivity.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseActivity.kt @@ -25,7 +25,7 @@ abstract class BaseActivity : AppCompatActivity(), BaseView< themes.applyThemeMode(preferences.themeMode) contentView?.let { setContentView(it) } - onSetup() + _onSetup() viewState.apply { attach() diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseChoicesFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseChoicesFragment.kt index 50fab603e..e15301ed5 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseChoicesFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseChoicesFragment.kt @@ -20,7 +20,7 @@ open class BaseChoicesFragment @Inject constructor() : BaseFragment : Fragment(), BaseView { @@ -14,6 +16,8 @@ abstract class BaseFragment : Fragment(), BaseView { val args get() = arguments ?: Bundle() @Inject lateinit var baseActivity: BaseActivity<*> + @Inject lateinit var fragmentFactory: FragmentFactory + @Inject lateinit var permissions: PermissionsInteractor override fun onCreateView( @@ -57,6 +61,10 @@ abstract class BaseFragment : Fragment(), BaseView { _onFinishListener.invoke() } + protected open fun onSetup(){ + _onSetup() + } + fun setOnFinishListener(onFinishListener: () -> Unit) { _onFinishListener = onFinishListener } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseView.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseView.kt index 13b6f451b..b05c95390 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseView.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseView.kt @@ -1,12 +1,11 @@ package com.chooloo.www.chooloolib.ui.base import androidx.annotation.StringRes -import androidx.lifecycle.Lifecycle interface BaseView { val viewState: VM? - fun onSetup() + fun _onSetup() fun finish() {} fun showError(@StringRes stringResId: Int) fun showMessage(@StringRes stringResId: Int) diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseViewState.kt index ce30d68da..13885de2f 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BaseViewState.kt @@ -9,6 +9,14 @@ open class BaseViewState : ViewModel() { val errorEvent = DataLiveEvent() val messageEvent = DataLiveEvent() - open fun attach() {} - open fun detach() {} + open fun _attach() {} + open fun _detach() {} + + open fun detach() { + _detach() + } + + open fun attach() { + _attach() + } } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BottomFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BottomFragment.kt index 2b6a9e658..2c2da99e6 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BottomFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/BottomFragment.kt @@ -37,10 +37,10 @@ open class BottomFragment>( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - onSetup() + _onSetup() } - override fun onSetup() { + override fun _onSetup() { fragment.setOnFinishListener { this@BottomFragment.dismiss() } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/menu/BaseMenuFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/menu/BaseMenuFragment.kt index 5228e1cef..b2361aa65 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/menu/BaseMenuFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/base/menu/BaseMenuFragment.kt @@ -24,7 +24,7 @@ open class BaseMenuFragment @Inject constructor() : BaseFragment( @Inject lateinit var adapter: MenuAdapter - override fun onSetup() { + override fun _onSetup() { adapter.setOnItemClickListener(::onMenuItemClick) viewState.apply { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/BriefContactFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/BriefContactFragment.kt index c015de15c..fb17bb5a2 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/BriefContactFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/BriefContactFragment.kt @@ -32,12 +32,10 @@ open class BriefContactFragment @Inject constructor() : BaseFragment - firstNumber = phones?.getOrNull(0)?.number + viewModelScope.launch { + firstNumber = phones.getContactAccounts(it.id).getOrNull(0)?.number callback.invoke(firstNumber) } } @@ -49,13 +51,15 @@ class BriefContactViewState @Inject constructor( fun onContactId(contactId: Long) { this.contactId.value = contactId - contacts.observeContact(contactId) { - contact = it - contactName.value = it?.name - isFavorite.value = it?.starred == true - withFirstNumber { contactNumber.value = it } - it?.photoUri?.let { uri -> - contactImage.value = Uri.parse(uri) + viewModelScope.launch { + contacts.getContact(contactId).collect { + contact = it + contactName.value = it?.name + isFavorite.value = it?.starred == true + withFirstNumber { contactNumber.value = it } + it?.photoUri?.let { uri -> + contactImage.value = Uri.parse(uri) + } } } } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/menu/BriefContactMenuFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/menu/BriefContactMenuFragment.kt index 7ab7521ad..809997903 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/menu/BriefContactMenuFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/briefcontact/menu/BriefContactMenuFragment.kt @@ -3,7 +3,6 @@ package com.chooloo.www.chooloolib.ui.briefcontact.menu import android.view.MenuItem import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.R -import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.interactor.dialog.DialogsInteractor import com.chooloo.www.chooloolib.interactor.prompt.PromptsInteractor import com.chooloo.www.chooloolib.ui.base.menu.BaseMenuFragment @@ -16,11 +15,10 @@ class BriefContactMenuFragment @Inject constructor() : BaseMenuFragment() { @Inject lateinit var dialogs: DialogsInteractor @Inject lateinit var prompts: PromptsInteractor - @Inject lateinit var fragmentFactory: FragmentFactory - override fun onSetup() { - super.onSetup() + override fun _onSetup() { + super._onSetup() viewState.apply { showHistoryEvent.observe(this@BriefContactMenuFragment) { ev -> ev.ifNew?.let { prompts.showFragment(fragmentFactory.getRecentsFragment(viewState.contactName.value)) } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallActivity.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallActivity.kt index 2a955c26a..09c76286a 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallActivity.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallActivity.kt @@ -28,14 +28,14 @@ class CallActivity : BaseActivity() { private val dialpadViewState: DialpadViewState by viewModels() private val binding by lazy { CallBinding.inflate(layoutInflater) } - @Inject lateinit var screens:ScreensInteractor + @Inject lateinit var screens: ScreensInteractor @Inject lateinit var dialogs: DialogsInteractor @Inject lateinit var prompts: PromptsInteractor @Inject lateinit var animations: AnimationsInteractor @Inject lateinit var fragmentFactory: FragmentFactory - override fun onSetup() { + override fun _onSetup() { screens.showWhenLocked() viewState.apply { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallViewState.kt index 98e264a11..dbc23a4e8 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/call/CallViewState.kt @@ -5,9 +5,15 @@ import android.os.Build import android.telecom.Call.Details.* import android.telecom.PhoneAccountHandle import android.telecom.PhoneAccountSuggestion -import android.telecom.TelecomManager import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.api.service.CallService +import com.chooloo.www.chooloolib.data.model.Call +import com.chooloo.www.chooloolib.data.model.Call.State.* +import com.chooloo.www.chooloolib.data.model.CantHoldCallException +import com.chooloo.www.chooloolib.data.model.CantMergeCallException +import com.chooloo.www.chooloolib.data.model.CantSwapCallException import com.chooloo.www.chooloolib.interactor.audio.AudiosInteractor import com.chooloo.www.chooloolib.interactor.audio.AudiosInteractor.AudioMode.NORMAL import com.chooloo.www.chooloolib.interactor.callaudio.CallAudiosInteractor @@ -17,12 +23,6 @@ import com.chooloo.www.chooloolib.interactor.color.ColorsInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor import com.chooloo.www.chooloolib.interactor.proximity.ProximitiesInteractor import com.chooloo.www.chooloolib.interactor.string.StringsInteractor -import com.chooloo.www.chooloolib.model.Call -import com.chooloo.www.chooloolib.model.Call.State.* -import com.chooloo.www.chooloolib.model.CantHoldCallException -import com.chooloo.www.chooloolib.model.CantMergeCallException -import com.chooloo.www.chooloolib.model.CantSwapCallException -import com.chooloo.www.chooloolib.service.CallService import com.chooloo.www.chooloolib.ui.base.BaseViewState import com.chooloo.www.chooloolib.ui.widgets.CallActions import com.chooloo.www.chooloolib.util.DataLiveEvent @@ -32,12 +32,12 @@ import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers +import kotlinx.coroutines.launch import java.util.concurrent.TimeUnit import javax.inject.Inject @HiltViewModel class CallViewState @Inject constructor( - private val telecomManger: TelecomManager, private val calls: CallsInteractor, private val audios: AudiosInteractor, private val colors: ColorsInteractor, @@ -56,7 +56,7 @@ class CallViewState @Inject constructor( val imageRes = MutableLiveData() val uiState = MutableLiveData() val imageURI = MutableLiveData(null) - val bannerText = MutableLiveData() + val bannerText = MutableLiveData() val stateText = MutableLiveData() val elapsedTime = MutableLiveData() val stateTextColor = MutableLiveData() @@ -82,7 +82,7 @@ class CallViewState @Inject constructor( private var _currentCallId: String? = null - override fun attach() { + override fun _attach() { disposables.add(Observable.interval(1, TimeUnit.SECONDS) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) @@ -179,10 +179,10 @@ class CallViewState @Inject constructor( if (calls.getFirstState(HOLDING)?.id == _currentCallId) { bannerText.value = null } else if (call.isHolding && _currentCallId != call.id && !call.isInConference) { - phones.lookupAccount(call.number) { + viewModelScope.launch { bannerText.value = String.format( strings.getString(R.string.explain_is_on_hold), - it?.displayString ?: call.number + phones.lookupAccount(call.number)?.displayString ?: call.number ) } } else if (calls.getStateCount(HOLDING) == 0) { @@ -204,7 +204,8 @@ class CallViewState @Inject constructor( if (call.isConference) { name.value = strings.getString(R.string.conference) } else { - phones.lookupAccount(call.number) { account -> + viewModelScope.launch { + val account = phones.lookupAccount(call.number) account?.photoUri?.let { imageURI.value = Uri.parse(it) } name.value = account?.displayString ?: call.number } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsFragment.kt index 456034457..08bc873f2 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsFragment.kt @@ -3,7 +3,7 @@ package com.chooloo.www.chooloolib.ui.callitems import androidx.core.view.isVisible import androidx.fragment.app.viewModels import com.chooloo.www.chooloolib.adapter.CallItemsAdapter -import com.chooloo.www.chooloolib.model.Call +import com.chooloo.www.chooloolib.data.model.Call import com.chooloo.www.chooloolib.ui.list.ListFragment import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsViewState.kt index db7358bde..d1fb5ff03 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/callitems/CallItemsViewState.kt @@ -1,17 +1,20 @@ package com.chooloo.www.chooloolib.ui.callitems -import androidx.lifecycle.LiveData -import com.chooloo.www.chooloolib.model.Call -import com.chooloo.www.chooloolib.repository.calls.CallsRepository +import com.chooloo.www.chooloolib.data.model.Call +import com.chooloo.www.chooloolib.data.repository.calls.CallsRepository +import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor import com.chooloo.www.chooloolib.ui.list.ListViewState import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel class CallItemsViewState @Inject constructor( + permissions: PermissionsInteractor, private val callsRepository: CallsRepository ) : - ListViewState() { + ListViewState(permissions) { + + override val itemsFlow get() = callsRepository.getCalls() override fun onItemLeftClick(item: Call) { super.onItemLeftClick(item) @@ -24,8 +27,4 @@ class CallItemsViewState @Inject constructor( item.reject() finishEvent.call() } - - override fun getItemsObservable(callback: (LiveData>) -> Unit) { - callback.invoke(callsRepository.getCalls()) - } } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsFragment.kt index fbe4b0078..d4248d175 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsFragment.kt @@ -2,9 +2,8 @@ package com.chooloo.www.chooloolib.ui.contacts import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.adapter.ContactsAdapter -import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.interactor.prompt.PromptsInteractor -import com.chooloo.www.chooloolib.model.ContactAccount +import com.chooloo.www.chooloolib.data.model.ContactAccount import com.chooloo.www.chooloolib.ui.list.ListFragment import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -15,12 +14,11 @@ open class ContactsFragment @Inject constructor() : override val viewState: ContactsViewState by activityViewModels() @Inject lateinit var prompts: PromptsInteractor - @Inject lateinit var fragmentFactory: FragmentFactory @Inject override lateinit var adapter: ContactsAdapter - override fun onSetup() { - super.onSetup() + override fun _onSetup() { + super._onSetup() viewState.showContactEvent.observe(this@ContactsFragment) { ev -> ev.ifNew?.let { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsViewState.kt index 07b985986..dedff9ac8 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsViewState.kt @@ -1,12 +1,10 @@ package com.chooloo.www.chooloolib.ui.contacts import android.Manifest.permission.READ_CONTACTS -import androidx.lifecycle.LiveData import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.ContactAccount +import com.chooloo.www.chooloolib.data.repository.contacts.ContactsRepository import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor -import com.chooloo.www.chooloolib.livedata.ContactsLiveData -import com.chooloo.www.chooloolib.model.ContactAccount -import com.chooloo.www.chooloolib.repository.contacts.ContactsRepository import com.chooloo.www.chooloolib.ui.list.ListViewState import com.chooloo.www.chooloolib.util.DataLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -14,37 +12,25 @@ import javax.inject.Inject @HiltViewModel open class ContactsViewState @Inject constructor( - contactsRepository: ContactsRepository, - private val permissions: PermissionsInteractor, + permissions: PermissionsInteractor, + private val contactsRepository: ContactsRepository, ) : - ListViewState() { + ListViewState(permissions) { override val noResultsIconRes = R.drawable.group override val noResultsTextRes = R.string.error_no_results_contacts - override val noPermissionsTextRes = R.string.error_no_permissions_contacts - private val contactsLiveData = contactsRepository.getContacts() as ContactsLiveData + override val permissionsImageRes = R.drawable.group + override val permissionsTextRes = R.string.error_no_permissions_contacts + override val requiredPermissions = listOf(READ_CONTACTS) - val showContactEvent = DataLiveEvent() + override val itemsFlow get() = contactsRepository.getContacts() + val showContactEvent = DataLiveEvent() - override fun onFilterChanged(filter: String?) { - super.onFilterChanged(filter) - if (permissions.hasSelfPermission(READ_CONTACTS)) { - onPermissionsChanged(true) - contactsLiveData.filter = filter - } - } override fun onItemClick(item: ContactAccount) { super.onItemClick(item) showContactEvent.call(item.id) } - - override fun getItemsObservable(callback: (LiveData>) -> Unit) { - permissions.runWithReadContactsPermissions { - onPermissionsChanged(it) - if (it) callback.invoke(contactsLiveData) - } - } } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsSuggestionsFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/suggestions/ContactsSuggestionsFragment.kt similarity index 80% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsSuggestionsFragment.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/suggestions/ContactsSuggestionsFragment.kt index 094233a6a..075dfcdaf 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsSuggestionsFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/suggestions/ContactsSuggestionsFragment.kt @@ -1,7 +1,8 @@ -package com.chooloo.www.chooloolib.ui.contacts +package com.chooloo.www.chooloolib.ui.contacts.suggestions import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels +import com.chooloo.www.chooloolib.ui.contacts.ContactsFragment import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -10,8 +11,8 @@ class ContactsSuggestionsFragment @Inject constructor() : ContactsFragment() { override val viewState: ContactsSuggestionsViewState by activityViewModels() - override fun onSetup() { - super.onSetup() + override fun _onSetup() { + super._onSetup() adapter.apply { withFavs = false withHeaders = false diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsSuggestionsViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/suggestions/ContactsSuggestionsViewState.kt similarity index 55% rename from chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsSuggestionsViewState.kt rename to chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/suggestions/ContactsSuggestionsViewState.kt index 7b71a8466..c9fa8288a 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/ContactsSuggestionsViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/contacts/suggestions/ContactsSuggestionsViewState.kt @@ -1,7 +1,8 @@ -package com.chooloo.www.chooloolib.ui.contacts +package com.chooloo.www.chooloolib.ui.contacts.suggestions import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor -import com.chooloo.www.chooloolib.repository.contacts.ContactsRepository +import com.chooloo.www.chooloolib.data.repository.contacts.ContactsRepository +import com.chooloo.www.chooloolib.ui.contacts.ContactsViewState import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -9,4 +10,4 @@ import javax.inject.Inject class ContactsSuggestionsViewState @Inject constructor( permissions: PermissionsInteractor, contactsRepository: ContactsRepository -) : ContactsViewState(contactsRepository, permissions) \ No newline at end of file +) : ContactsViewState(permissions,contactsRepository) \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerFragment.kt index 6a9d5e9c9..8803e42fb 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerFragment.kt @@ -7,9 +7,8 @@ import android.view.View import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels -import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.interactor.telecom.TelecomInteractor -import com.chooloo.www.chooloolib.ui.contacts.ContactsSuggestionsViewState +import com.chooloo.www.chooloolib.ui.contacts.suggestions.ContactsSuggestionsViewState import com.chooloo.www.chooloolib.ui.dialpad.DialpadFragment import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -21,12 +20,11 @@ class DialerFragment @Inject constructor() : DialpadFragment() { private val suggestionsViewState: ContactsSuggestionsViewState by activityViewModels() private val _suggestionsFragment by lazy { fragmentFactory.getContactsSuggestionsFragment() } - @Inject lateinit var fragmentFactory: FragmentFactory @Inject lateinit var telecomInteractor: TelecomInteractor - override fun onSetup() { - super.onSetup() + override fun _onSetup() { + super._onSetup() binding.apply { dialpadButtonCall.isVisible = true @@ -109,9 +107,7 @@ class DialerFragment @Inject constructor() : DialpadFragment() { } } - suggestionsViewState.itemsChangedEvent.observe(this@DialerFragment) { - it.peekContent()?.let(viewState::onSuggestionsChanged) - } + suggestionsViewState.items.observe(this@DialerFragment, viewState::onSuggestionsChanged) args.getString(ARG_NUMBER)?.forEach(viewState::onCharClick) } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerViewState.kt index a23c900ad..e5245fc27 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialer/DialerViewState.kt @@ -1,12 +1,13 @@ package com.chooloo.www.chooloolib.ui.dialer +import android.Manifest import android.content.ClipboardManager import androidx.lifecycle.MutableLiveData import com.chooloo.www.chooloolib.interactor.audio.AudiosInteractor import com.chooloo.www.chooloolib.interactor.navigation.NavigationsInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.recents.RecentsInteractor -import com.chooloo.www.chooloolib.model.ContactAccount +import com.chooloo.www.chooloolib.data.model.ContactAccount import com.chooloo.www.chooloolib.ui.dialpad.DialpadViewState import com.chooloo.www.chooloolib.util.DataLiveEvent import com.chooloo.www.chooloolib.util.LiveEvent @@ -23,6 +24,8 @@ class DialerViewState @Inject constructor( ) : DialpadViewState(audios, clipboardManager, preferences) { + override val requiredPermissions = listOf(Manifest.permission.CALL_PHONE) + val callVoicemailEvent = LiveEvent() val callNumberEvent = DataLiveEvent() val isSuggestionsVisible = MutableLiveData(false) diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadFragment.kt index 3f4269c44..2f0505656 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadFragment.kt @@ -6,21 +6,22 @@ import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.databinding.DialpadBinding import com.chooloo.www.chooloolib.interactor.animation.AnimationsInteractor import com.chooloo.www.chooloolib.ui.base.BaseFragment +import com.chooloo.www.chooloolib.ui.permissioned.PermissionedFragment import com.chooloo.www.chooloolib.ui.widgets.DialpadKey import com.chooloo.www.chooloolib.ui.widgets.TextContextMenuItemListener import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @AndroidEntryPoint -open class DialpadFragment @Inject constructor() : BaseFragment(), TextContextMenuItemListener { - override val contentView by lazy { binding.root } +open class DialpadFragment @Inject constructor() : PermissionedFragment(), TextContextMenuItemListener { + override val mainContentView by lazy { binding.root } override val viewState: DialpadViewState by activityViewModels() @Inject lateinit var animationsInteractor: AnimationsInteractor protected val binding by lazy { DialpadBinding.inflate(layoutInflater) } - override fun onSetup() { + override fun _onSetup() { binding.apply { dialpadButtonCall.isVisible = false dialpadButtonDelete.isVisible = false diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadViewState.kt index 72c424d62..4084309b4 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/dialpad/DialpadViewState.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import com.chooloo.www.chooloolib.interactor.audio.AudiosInteractor import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.ui.base.BaseViewState +import com.chooloo.www.chooloolib.ui.permissioned.PermissionedViewState import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -14,7 +15,7 @@ open class DialpadViewState @Inject constructor( private val clipboardManager: ClipboardManager, private val preferences: PreferencesInteractor ) : - BaseViewState() { + PermissionedViewState() { val text = MutableLiveData("") val char = MutableLiveData() diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListFragment.kt index 4cd0e490a..2ac5af526 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListFragment.kt @@ -3,18 +3,24 @@ package com.chooloo.www.chooloolib.ui.list import androidx.core.view.isVisible import com.chooloo.www.chooloolib.adapter.ListAdapter import com.chooloo.www.chooloolib.databinding.ItemsBinding -import com.chooloo.www.chooloolib.ui.base.BaseFragment +import com.chooloo.www.chooloolib.ui.permissioned.PermissionedFragment + +abstract class ListFragment> : PermissionedFragment() { + override val mainContentView by lazy { binding.root } -abstract class ListFragment> : BaseFragment() { - override val contentView by lazy { binding.root } protected val binding by lazy { ItemsBinding.inflate(layoutInflater) } - override fun onSetup() { + + override fun _onSetup() { viewState.apply { isEmpty.observe(this@ListFragment, this@ListFragment::showEmpty) emptyMessage.observe(this@ListFragment, binding.empty.emptyText::setText) emptyIcon.observe(this@ListFragment, binding.empty.emptyIcon::setImageResource) + items.observe(this@ListFragment) { + adapter.items = it + } + filter.observe(this@ListFragment) { adapter.titleFilter = it } @@ -26,14 +32,6 @@ abstract class ListFragment> : BaseFragme isScrollerVisible.observe(this@ListFragment) { binding.itemsScrollView.fastScroller.isVisible = it } - - itemsChangedEvent.observe(this@ListFragment) { ev -> - ev.ifNew?.let { adapter.items = it } - } - - if (args.getBoolean(ARG_OBSERVE, true)) { - getItemsObservable { it.observe(this@ListFragment, viewState::onItemsChanged) } - } } adapter.apply { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListViewState.kt index ae87b0607..47a8c4ed2 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/list/ListViewState.kt @@ -1,11 +1,17 @@ package com.chooloo.www.chooloolib.ui.list -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import com.chooloo.www.chooloolib.ui.base.BaseViewState +import androidx.lifecycle.viewModelScope +import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor +import com.chooloo.www.chooloolib.ui.permissioned.PermissionedViewState import com.chooloo.www.chooloolib.util.DataLiveEvent +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch -abstract class ListViewState : BaseViewState() { +abstract class ListViewState( + private val permissions: PermissionsInteractor +) : PermissionedViewState() { + val items = MutableLiveData>() val filter = MutableLiveData() val emptyIcon = MutableLiveData() val emptyMessage = MutableLiveData() @@ -15,22 +21,23 @@ abstract class ListViewState : BaseViewState() { val itemClickedEvent = DataLiveEvent() val itemLongClickedEvent = DataLiveEvent() - val itemsChangedEvent = DataLiveEvent>() protected open val noResultsIconRes: Int? = null protected open val noResultsTextRes: Int? = null - protected open val noPermissionsTextRes: Int? = null - - override fun attach() { + + override fun _attach() { emptyIcon.value = noResultsIconRes emptyMessage.value = noResultsTextRes + viewModelScope.launch { + itemsFlow?.collect(this@ListViewState::onItemsChanged) + } } open fun onItemsChanged(items: List) { isLoading.value = false isEmpty.value = items.isEmpty() - itemsChangedEvent.call(items) + this.items.value = items } open fun onFilterChanged(filter: String?) { @@ -45,13 +52,8 @@ abstract class ListViewState : BaseViewState() { itemLongClickedEvent.call(item) } - fun onPermissionsChanged(hasPermissions: Boolean) { - emptyMessage.value = if (hasPermissions) noResultsTextRes else noPermissionsTextRes - isEmpty.value = !hasPermissions - } - open fun onItemLeftClick(item: ItemType) {} open fun onItemRightClick(item: ItemType) {} - abstract fun getItemsObservable(callback: (LiveData>) -> Unit) + abstract protected val itemsFlow: Flow>? } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionFragment.kt new file mode 100644 index 000000000..74228ff8f --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionFragment.kt @@ -0,0 +1,31 @@ +package com.chooloo.www.chooloolib.ui.permission + +import androidx.fragment.app.viewModels +import com.chooloo.www.chooloolib.databinding.PermissionBinding +import com.chooloo.www.chooloolib.ui.base.BaseFragment +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject + +@AndroidEntryPoint +class PermissionFragment @Inject constructor() : BaseFragment() { + override val contentView by lazy { _binding.root } + override val viewState: PermissionViewState by viewModels( + ownerProducer = { requireParentFragment() } + ) + + private val _binding by lazy { PermissionBinding.inflate(layoutInflater) } + + + override fun _onSetup() { + viewState.apply { + textRes.observe(this@PermissionFragment, _binding.noPermissionText::setText) + imageRes.observe(this@PermissionFragment) { + _binding.noPermissionImage.setImageResource(it) + } + } + + _binding.apply { + noPermissionButton.setOnClickListener { viewState.onGrantClick() } + } + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionViewState.kt new file mode 100644 index 000000000..1e3e3842f --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permission/PermissionViewState.kt @@ -0,0 +1,52 @@ +package com.chooloo.www.chooloolib.ui.permission + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor +import com.chooloo.www.chooloolib.ui.base.BaseViewState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class PermissionViewState @Inject constructor( + private val permissions: PermissionsInteractor +) : BaseViewState() { + private val _textRes = MutableLiveData() + private val _imageRes = MutableLiveData() + private var _isGranted = MutableLiveData() + private var _permissions: List = emptyList() + + val textRes: LiveData = _textRes + val imageRes: LiveData = _imageRes + val isGranted: LiveData = _isGranted + + + override fun _attach() { + super._attach() + checkPermission() + } + + private fun checkPermission() { + viewModelScope.launch { + _isGranted.value = permissions.checkPermissions(*_permissions.toTypedArray()) + } + } + + fun onGrantClick() { + checkPermission() + } + + fun onTextRes(textRes: Int) { + _textRes.value = textRes + } + + fun onImageRes(imageRes: Int) { + _imageRes.value = imageRes + } + + fun onPermissions(permissions: List) { + _permissions = permissions + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedFragment.kt new file mode 100644 index 000000000..65d8f8365 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedFragment.kt @@ -0,0 +1,75 @@ +package com.chooloo.www.chooloolib.ui.permissioned + +import android.view.View +import android.view.ViewGroup +import androidx.core.view.children +import androidx.core.view.isVisible +import androidx.fragment.app.viewModels +import com.chooloo.www.chooloolib.databinding.PermissionedBinding +import com.chooloo.www.chooloolib.ui.base.BaseFragment +import com.chooloo.www.chooloolib.ui.permission.PermissionViewState + +abstract class PermissionedFragment : BaseFragment() { + + override val contentView by lazy { _binding.root } + + private val _permissionViewState: PermissionViewState by viewModels() + private val _binding by lazy { PermissionedBinding.inflate(layoutInflater) } + private val _permissionFragment by lazy { fragmentFactory.getPermissionFragment() } + + + override fun onSetup() { + viewState.apply { + if (permissions.hasSelfPermissions(requiredPermissions.toTypedArray())) { + addMainFragment() + } else { + addPermissionsFragment() + _permissionViewState.apply { + onPermissions(requiredPermissions) + permissionsTextRes?.let(::onTextRes) + permissionsImageRes?.let(::onImageRes) + isGranted.observe(this@PermissionedFragment) { + if (it) { + addMainFragment() + } + onIsPermissionGranted(it) + } + } + } + } + } + + private fun addMainFragment() { + removePermissionsFragment() + mainContentView.parent?.let { (it as ViewGroup).removeView(mainContentView) } + _binding.root.addView(mainContentView) + _onSetup() + } + + private fun addPermissionsFragment() { + _binding.permissionedPermissionContainer.isVisible = true + + childFragmentManager.beginTransaction() + .add( + _binding.permissionedPermissionContainer.id, + fragmentFactory.getPermissionFragment(), + PERMISSIONS_FRAGMENT_TAG + ) + .commit() + } + + private fun removePermissionsFragment() { + childFragmentManager.findFragmentByTag(PERMISSIONS_FRAGMENT_TAG)?.let { + childFragmentManager.beginTransaction().remove(it).commit() + } + + _binding.permissionedPermissionContainer.isVisible = false + } + + abstract val mainContentView: View + + + companion object { + const val PERMISSIONS_FRAGMENT_TAG = "permissions_fragment" + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedViewState.kt new file mode 100644 index 000000000..4256258a5 --- /dev/null +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissioned/PermissionedViewState.kt @@ -0,0 +1,23 @@ +package com.chooloo.www.chooloolib.ui.permissioned + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.chooloo.www.chooloolib.ui.base.BaseViewState + +abstract class PermissionedViewState : BaseViewState() { + private val _isPermissionGranted = MutableLiveData() + + open val permissionsTextRes: Int? = null + open val permissionsImageRes: Int? = null + open val requiredPermissions: List = emptyList() + + val isPermissionGranted: LiveData = _isPermissionGranted + + + fun onIsPermissionGranted(isGranted: Boolean) { + _isPermissionGranted.value = isGranted + if (isGranted) { + _attach() + } + } +} \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/DefaultDialerRequestActivity.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/DefaultDialerRequestActivity.kt index 3afa03ad5..110c5243e 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/DefaultDialerRequestActivity.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/DefaultDialerRequestActivity.kt @@ -29,7 +29,7 @@ class DefaultDialerRequestActivity : BaseActivity() { } } - override fun onSetup() {} + override fun _onSetup() {} override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/PermissionRequestActivity.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/PermissionRequestActivity.kt index a55d8434b..b97567cee 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/PermissionRequestActivity.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/permissions/PermissionRequestActivity.kt @@ -26,7 +26,7 @@ class PermissionRequestActivity : BaseActivity() { } } - override fun onSetup() {} + override fun _onSetup() {} private fun requestPermissions() { val permissions = intent?.getStringArrayExtra(PERMISSIONS_ARGUMENT_KEY) ?: arrayOf() diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/phones/PhonesFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/phones/PhonesFragment.kt index c70c6e915..0b89babff 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/phones/PhonesFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/phones/PhonesFragment.kt @@ -5,7 +5,7 @@ import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.adapter.PhonesAdapter import com.chooloo.www.chooloolib.interactor.telecom.TelecomInteractor -import com.chooloo.www.chooloolib.model.PhoneAccount +import com.chooloo.www.chooloolib.data.model.PhoneAccount import com.chooloo.www.chooloolib.ui.briefcontact.BriefContactFragment.Companion.ARG_CONTACT_ID import com.chooloo.www.chooloolib.ui.list.ListFragment import dagger.hilt.android.AndroidEntryPoint @@ -18,9 +18,9 @@ class PhonesFragment @Inject constructor() : ListFragment() { + ListViewState(permissions) { override val noResultsIconRes = R.drawable.call override val noResultsTextRes = R.string.error_no_results_phones - override val noPermissionsTextRes = R.string.error_no_permissions_phones + + override val requiredPermissions = listOf(READ_CONTACTS) + + override val itemsFlow get() = phonesRepository.getPhones(if (contactId.value == 0L) null else contactId.value) + val callEvent = DataLiveEvent() val contactId = MutableLiveData(0L) - private val phonesLiveData get() = phonesRepository.getPhones(if (contactId.value == 0L) null else contactId.value) as PhonesLiveData - override fun onFilterChanged(filter: String?) { super.onFilterChanged(filter) - phonesLiveData.filter = filter + // TODO implement filter +// phones.filter = filter } override fun onItemRightClick(item: PhoneAccount) { @@ -55,13 +55,6 @@ class PhonesViewState @Inject constructor( messageEvent.call(R.string.number_copied_to_clipboard) } - override fun getItemsObservable(callback: (LiveData>) -> Unit) { - permissions.runWithReadContactsPermissions { - onPermissionsChanged(it) - if (it) callback.invoke(phonesLiveData) - } - } - fun onContactId(contactId: Long) { this.contactId.value = contactId } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/prompt/PromptFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/prompt/PromptFragment.kt index af791dfbb..c1123dd0a 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/prompt/PromptFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/prompt/PromptFragment.kt @@ -17,7 +17,7 @@ class PromptFragment @Inject constructor() : BaseFragment() { private val binding by lazy { PromptBinding.inflate(layoutInflater) } - override fun onSetup() { + override fun _onSetup() { binding.apply { viewState.title.value = args.getString(ARG_TITLE) viewState.subtitle.value = args.getString(ARG_SUBTITLE) diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentFragment.kt index c3a400762..3160c7f2f 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentFragment.kt @@ -28,11 +28,10 @@ class RecentFragment @Inject constructor() : BaseFragment() { @Inject lateinit var prompts: PromptsInteractor @Inject lateinit var dialogs: DialogsInteractor - @Inject lateinit var fragmentFactory: FragmentFactory @Inject lateinit var telecomInteractor: TelecomInteractor - override fun onSetup() { + override fun _onSetup() { binding.recentContactImage.isVisible = false binding.apply { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentViewState.kt index c41ab5bfd..1caaacec6 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/RecentViewState.kt @@ -2,30 +2,24 @@ package com.chooloo.www.chooloolib.ui.recent import android.net.Uri import androidx.lifecycle.MutableLiveData -import com.chooloo.www.chooloolib.interactor.blocked.BlockedInteractor -import com.chooloo.www.chooloolib.interactor.drawable.DrawablesInteractor +import androidx.lifecycle.viewModelScope +import com.chooloo.www.chooloolib.data.model.RecentAccount import com.chooloo.www.chooloolib.interactor.navigation.NavigationsInteractor -import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor import com.chooloo.www.chooloolib.interactor.phoneaccounts.PhonesInteractor -import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.recents.RecentsInteractor -import com.chooloo.www.chooloolib.model.RecentAccount import com.chooloo.www.chooloolib.ui.base.BaseViewState import com.chooloo.www.chooloolib.util.DataLiveEvent import com.chooloo.www.chooloolib.util.LiveEvent import com.chooloo.www.chooloolib.util.getElapsedTimeString import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class RecentViewState @Inject constructor( private val phones: PhonesInteractor, private val recents: RecentsInteractor, - private val blocked: BlockedInteractor, - private val drawables: DrawablesInteractor, - private val preferences: PreferencesInteractor, private val navigations: NavigationsInteractor, - private val permissions: PermissionsInteractor ) : BaseViewState() { val name = MutableLiveData() @@ -48,29 +42,30 @@ class RecentViewState @Inject constructor( private var _recent: RecentAccount? = null - override fun attach() { - super.attach() + override fun _attach() { + super._attach() if (_recent == null) return } fun onRecentId(recentId: Long) { this.recentId.value = recentId - recents.observeRecent(recentId) { - _recent = it - recentNumber.value = it?.number - name.value = - if (_recent!!.cachedName?.isNotEmpty() == true) it?.cachedName else it?.number - it?.type?.let { typeImage.value = recents.getCallTypeImage(it) } - - caption.value = "${it?.relativeTime} • ${ - if (it?.duration ?: -1 > 0L) "${ - getElapsedTimeString(it?.duration!!) - } •" else "" - }" - phones.lookupAccount(it?.number) { - it?.photoUri?.let { imageUri.value = Uri.parse(it) } - isContactVisible.value = it?.name != null - isAddContactVisible.value = it?.name == null + viewModelScope.launch { + recents.getRecent(recentId).collect { + _recent = it + recentNumber.value = it?.number + name.value = + if (_recent!!.cachedName?.isNotEmpty() == true) it?.cachedName else it?.number + it?.type?.let { typeImage.value = recents.getCallTypeImage(it) } + + caption.value = "${it?.relativeTime} • ${ + if (it?.duration ?: -1 > 0L) "${ + getElapsedTimeString(it?.duration!!) + } •" else "" + }" + val lookupAccount = phones.lookupAccount(it?.number) + lookupAccount?.photoUri?.let { pu -> imageUri.value = Uri.parse(pu) } + isContactVisible.value = lookupAccount?.name != null + isAddContactVisible.value = lookupAccount?.name == null } } } @@ -88,7 +83,8 @@ class RecentViewState @Inject constructor( } fun onOpenContact() { - phones.lookupAccount(recentNumber.value) { account -> + viewModelScope.launch { + val account = phones.lookupAccount(recentNumber.value) account?.contactId?.let(navigations::viewContact) } } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuFragment.kt index 195c7ee54..02e8cacec 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuFragment.kt @@ -3,7 +3,6 @@ package com.chooloo.www.chooloolib.ui.recent.menu import android.view.MenuItem import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.R -import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory import com.chooloo.www.chooloolib.interactor.dialog.DialogsInteractor import com.chooloo.www.chooloolib.interactor.prompt.PromptsInteractor import com.chooloo.www.chooloolib.ui.base.menu.BaseMenuFragment @@ -16,10 +15,10 @@ class RecentMenuFragment @Inject constructor() : BaseMenuFragment() { @Inject lateinit var prompts: PromptsInteractor @Inject lateinit var dialogs: DialogsInteractor - @Inject lateinit var fragmentFactory: FragmentFactory - override fun onSetup() { - super.onSetup() + + override fun _onSetup() { + super._onSetup() viewState.apply { showHistoryEvent.observe(this@RecentMenuFragment) { ev -> ev.ifNew?.let { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuViewState.kt index 190df08cb..8c42d0166 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recent/menu/RecentMenuViewState.kt @@ -2,6 +2,7 @@ package com.chooloo.www.chooloolib.ui.recent.menu import android.Manifest import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope import com.chooloo.www.chooloolib.R import com.chooloo.www.chooloolib.interactor.blocked.BlockedInteractor import com.chooloo.www.chooloolib.interactor.navigation.NavigationsInteractor @@ -10,6 +11,7 @@ import com.chooloo.www.chooloolib.interactor.recents.RecentsInteractor import com.chooloo.www.chooloolib.ui.base.menu.BaseMenuViewState import com.chooloo.www.chooloolib.util.LiveEvent import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -47,10 +49,12 @@ class RecentMenuViewState @Inject constructor( fun onBlock(isBlock: Boolean) { permissions.runWithDefaultDialer(R.string.error_not_default_dialer_blocked) { recentNumber.value?.let { - if (isBlock) { - blocked.blockNumber(it) - } else { - blocked.unblockNumber(it) + viewModelScope.launch { + if (isBlock) { + blocked.blockNumber(it) + } else { + blocked.unblockNumber(it) + } } isBlocked.value = isBlock finishEvent.call() diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsFragment.kt index 92765e134..38f273576 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsFragment.kt @@ -3,10 +3,9 @@ package com.chooloo.www.chooloolib.ui.recents import android.os.Bundle import androidx.fragment.app.activityViewModels import com.chooloo.www.chooloolib.adapter.RecentsAdapter -import com.chooloo.www.chooloolib.di.factory.fragment.FragmentFactory +import com.chooloo.www.chooloolib.data.model.RecentAccount import com.chooloo.www.chooloolib.interactor.preferences.PreferencesInteractor import com.chooloo.www.chooloolib.interactor.prompt.PromptsInteractor -import com.chooloo.www.chooloolib.model.RecentAccount import com.chooloo.www.chooloolib.ui.list.ListFragment import com.chooloo.www.chooloolib.ui.recentshistory.RecentsHistoryViewState import dagger.hilt.android.AndroidEntryPoint @@ -17,14 +16,15 @@ open class RecentsFragment @Inject constructor() : ListFragment diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsViewState.kt index 72145e037..456d914cc 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recents/RecentsViewState.kt @@ -4,12 +4,10 @@ import android.Manifest.permission.READ_CALL_LOG import android.Manifest.permission.READ_CONTACTS import android.content.ClipData import android.content.ClipboardManager -import androidx.lifecycle.LiveData import com.chooloo.www.chooloolib.R +import com.chooloo.www.chooloolib.data.model.RecentAccount +import com.chooloo.www.chooloolib.data.repository.recents.RecentsRepository import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor -import com.chooloo.www.chooloolib.livedata.RecentsLiveData -import com.chooloo.www.chooloolib.model.RecentAccount -import com.chooloo.www.chooloolib.repository.recents.RecentsRepository import com.chooloo.www.chooloolib.ui.list.ListViewState import com.chooloo.www.chooloolib.util.DataLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -17,32 +15,27 @@ import javax.inject.Inject @HiltViewModel open class RecentsViewState @Inject constructor( - recentsRepository: RecentsRepository, - private val permissions: PermissionsInteractor, - private val clipboardManager: ClipboardManager + permissions: PermissionsInteractor, + private val clipboardManager: ClipboardManager, + private val recentsRepository: RecentsRepository, ) : - ListViewState() { + ListViewState(permissions) { override val noResultsIconRes = R.drawable.history override val noResultsTextRes = R.string.error_no_results_recents - override var noPermissionsTextRes = R.string.error_no_permissions_recents - private val recentsLiveData = recentsRepository.getRecents() as RecentsLiveData + override val permissionsImageRes = R.drawable.history + override val permissionsTextRes = R.string.error_no_permissions_recents + override val requiredPermissions = listOf(READ_CALL_LOG, READ_CONTACTS) - val showRecentEvent = DataLiveEvent() + override val itemsFlow get() = recentsRepository.getRecents() + val showRecentEvent = DataLiveEvent() - override fun onFilterChanged(filter: String?) { - super.onFilterChanged(filter) - if (permissions.hasSelfPermissions(arrayOf(READ_CONTACTS, READ_CALL_LOG))) { - onPermissionsChanged(true) - recentsLiveData.filter = filter - } - } override fun onItemClick(item: RecentAccount) { super.onItemClick(item) - permissions.runWithReadCallLogPermissions { showRecentEvent.call(item) } + showRecentEvent.call(item) } override fun onItemLongClick(item: RecentAccount) { @@ -50,16 +43,4 @@ open class RecentsViewState @Inject constructor( clipboardManager.setPrimaryClip(ClipData.newPlainText("Copied number", item.number)) messageEvent.call(R.string.number_copied_to_clipboard) } - - override fun getItemsObservable(callback: (LiveData>) -> Unit) { - permissions.runWithReadCallLogPermissions { clp -> - if (!clp) noPermissionsTextRes = R.string.error_no_permissions_recents - onPermissionsChanged(clp) - permissions.runWithReadContactsPermissions { rcp -> - if (!rcp) noPermissionsTextRes = R.string.error_no_permissions_contacts - onPermissionsChanged(clp && rcp) - if (clp && rcp) callback.invoke(recentsLiveData) - } - } - } } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryFragment.kt index a66a58b3f..7af5efa07 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryFragment.kt @@ -9,8 +9,8 @@ import dagger.hilt.android.AndroidEntryPoint class RecentsHistoryFragment : RecentsFragment() { override val viewState: RecentsHistoryViewState by activityViewModels() - override fun onSetup() { - super.onSetup() + override fun _onSetup() { + super._onSetup() adapter.groupSimilar = false } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryViewState.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryViewState.kt index bfa389689..0f427db3d 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryViewState.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/recentshistory/RecentsHistoryViewState.kt @@ -2,7 +2,7 @@ package com.chooloo.www.chooloolib.ui.recentshistory import android.content.ClipboardManager import com.chooloo.www.chooloolib.interactor.permission.PermissionsInteractor -import com.chooloo.www.chooloolib.repository.recents.RecentsRepository +import com.chooloo.www.chooloolib.data.repository.recents.RecentsRepository import com.chooloo.www.chooloolib.ui.recents.RecentsViewState import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -12,5 +12,5 @@ class RecentsHistoryViewState @Inject constructor( permissions: PermissionsInteractor, clipboardManager: ClipboardManager, recentsRepository: RecentsRepository -) : RecentsViewState(recentsRepository, permissions, clipboardManager) { +) : RecentsViewState(permissions, clipboardManager, recentsRepository) { } \ No newline at end of file diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/settings/SettingsFragment.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/settings/SettingsFragment.kt index 30cd1f121..cbf46eb30 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/settings/SettingsFragment.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/settings/SettingsFragment.kt @@ -1,6 +1,5 @@ package com.chooloo.www.chooloolib.ui.settings -import android.view.MenuItem import androidx.fragment.app.viewModels import com.chooloo.www.chooloolib.R import com.chooloo.www.chooloolib.interactor.dialog.DialogsInteractor @@ -15,8 +14,8 @@ open class SettingsFragment @Inject constructor() : BaseMenuFragment() { @Inject lateinit var dialogs: DialogsInteractor - override fun onSetup() { - super.onSetup() + override fun _onSetup() { + super._onSetup() viewState.apply { askForColorEvent.observe(this@SettingsFragment) { ev -> ev.ifNew?.let { dialogs.askForColor(it, viewState::onColorResponse) } diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/widgets/listitemholder/ListItemHolder.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/widgets/listitemholder/ListItemHolder.kt index 2b80e2560..b1b4f975b 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/widgets/listitemholder/ListItemHolder.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/ui/widgets/listitemholder/ListItemHolder.kt @@ -137,12 +137,12 @@ open class ListItemHolder(protected val binding: ListItemBinding) : fun setImageUri(imageUri: Uri?) { showImageOrInitials = imageUri != null - Picasso.with(context).load(imageUri).into(binding.listItemImage) + binding.listItemImage.setImageURI(imageUri) } fun setImageResource(imageRes: Int) { showImageOrInitials = true - Picasso.with(context).load(imageRes).into(binding.listItemImage) + binding.listItemImage.setImageResource(imageRes) } fun setImageDrawable(drawable: Drawable) { diff --git a/chooloolib/src/main/java/com/chooloo/www/chooloolib/util/ViewUtils.kt b/chooloolib/src/main/java/com/chooloo/www/chooloolib/util/ViewUtils.kt index 3760ce757..bdee81fa2 100644 --- a/chooloolib/src/main/java/com/chooloo/www/chooloolib/util/ViewUtils.kt +++ b/chooloolib/src/main/java/com/chooloo/www/chooloolib/util/ViewUtils.kt @@ -7,15 +7,6 @@ import android.util.TypedValue import androidx.annotation.ColorInt import androidx.core.content.ContextCompat -fun Context.navBarHeight(): Int { - val resource = resources.getIdentifier("navigation_bar_height", "dimen", "android") - return if (resource > 0) resources.getDimensionPixelSize(resource) else 0 -} - -fun Context.hasNavBar(): Boolean { - val resource = resources.getIdentifier("config_showNavigationBar", "bool", "android") - return resource > 0 && resources.getBoolean(resource) -} fun Context.getSizeInDp(px: Int) = (px * resources.displayMetrics.density + 0.5f).toInt() diff --git a/chooloolib/src/main/res/drawable/bubble_background_no_ripple.xml b/chooloolib/src/main/res/drawable/bubble_background_no_ripple.xml deleted file mode 100644 index 490c5d596..000000000 --- a/chooloolib/src/main/res/drawable/bubble_background_no_ripple.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/chooloolib/src/main/res/drawable/hearing.xml b/chooloolib/src/main/res/drawable/hearing.xml deleted file mode 100644 index 3883d6783..000000000 --- a/chooloolib/src/main/res/drawable/hearing.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/chooloolib/src/main/res/drawable/icon_button_color_selector.xml b/chooloolib/src/main/res/drawable/icon_button_color_selector.xml deleted file mode 100644 index 2472d18bc..000000000 --- a/chooloolib/src/main/res/drawable/icon_button_color_selector.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/chooloolib/src/main/res/layout/bottom_dialog.xml b/chooloolib/src/main/res/layout/bottom_dialog.xml index 9a0940fff..4fbd2b1b6 100644 --- a/chooloolib/src/main/res/layout/bottom_dialog.xml +++ b/chooloolib/src/main/res/layout/bottom_dialog.xml @@ -6,16 +6,6 @@ android:layout_height="wrap_content" android:fitsSystemWindows="true"> - - - - - - - - - - + android:id="@+id/list_item_caption_image" + android:layout_width="wrap_content" + android:layout_height="0dp" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="@id/list_item_caption" + app:layout_constraintStart_toEndOf="@id/list_item_caption" + app:layout_constraintTop_toTopOf="@id/list_item_caption" + app:tint="?android:textColorHint" android:contentDescription="TODO"/> + + + + + + +