Skip to content

Commit

Permalink
Merge pull request #202 from gavine99/texttospeech
Browse files Browse the repository at this point in the history
Text to speech
  • Loading branch information
octoshrimpy authored Jan 12, 2025
2 parents 4df0117 + 714cec2 commit 61293ce
Show file tree
Hide file tree
Showing 19 changed files with 660 additions and 5 deletions.
50 changes: 50 additions & 0 deletions data/src/main/java/com/moez/QKSMS/receiver/SpeakThreadsReceiver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 Moez Bhatti <[email protected]>
*
* This file is part of QKSMS.
*
* QKSMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QKSMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
*/
package dev.octoshrimpy.quik.receiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import dev.octoshrimpy.quik.interactor.SpeakThreads
import dagger.android.AndroidInjection
import dev.octoshrimpy.quik.repository.ConversationRepository
import javax.inject.Inject

class SpeakThreadsReceiver : BroadcastReceiver() {

@Inject lateinit var speakThread: SpeakThreads
@Inject lateinit var conversationRepo: ConversationRepository


override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)

val pendingResult = goAsync()
val threadId = intent.getLongExtra("threadId", 0)

val threads = when {
(threadId == -1L) -> conversationRepo.getUnseenIds()
(threadId == -2L) -> conversationRepo.getUnreadIds()
else -> listOf(threadId)
}

speakThread.execute(threads) { pendingResult.finish() }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package dev.octoshrimpy.quik.repository
import android.content.ContentUris
import android.content.Context
import android.provider.Telephony
import android.view.View.OnLongClickListener
import dev.octoshrimpy.quik.compat.TelephonyCompat
import dev.octoshrimpy.quik.extensions.anyOf
import dev.octoshrimpy.quik.extensions.asObservable
Expand Down Expand Up @@ -201,10 +202,69 @@ class ConversationRepositoryImpl @Inject constructor(

override fun getConversation(threadId: Long): Conversation? {
return Realm.getDefaultInstance()
.apply { refresh() }
.where(Conversation::class.java)
.equalTo("id", threadId)
.findFirst()
.apply { refresh() }
.where(Conversation::class.java)
.equalTo("id", threadId)
.findFirst()
}

override fun getUnseenIds(archived: Boolean): List<Long> {
val conversationIds = ArrayList<Long>()

Realm.getDefaultInstance()
.where(Conversation::class.java)
.notEqualTo("id", 0L)
.equalTo("archived", archived)
.equalTo("blocked", false)
.equalTo("lastMessage.seen", false)
.sort(
arrayOf("lastMessage.date"),
arrayOf(Sort.DESCENDING)
)
.findAllAsync()
.forEach { conversation -> conversationIds.add(conversation.id) }

return conversationIds
}

override fun getUnreadIds(archived: Boolean): List<Long> {
val conversationIds = ArrayList<Long>()

Realm.getDefaultInstance()
.where(Conversation::class.java)
.notEqualTo("id", 0L)
.equalTo("archived", archived)
.equalTo("blocked", false)
.equalTo("lastMessage.read", false)
.sort(
arrayOf("lastMessage.date"),
arrayOf(Sort.DESCENDING)
)
.findAllAsync()
.forEach { conversation -> conversationIds.add(conversation.id) }

return conversationIds
}

override fun getConversationAndLastSenderContactName(threadId: Long): Pair<Conversation?, String?>? {
val conversation = Realm.getDefaultInstance()
.apply { refresh() }
.where(Conversation::class.java)
.equalTo("id", threadId)
.findFirst()

if (conversation === null)
return null

var conversationLastSmsSender: String? = null

if (conversation !== null) {
conversationLastSmsSender = conversation?.recipients?.find { recipient ->
phoneNumberUtils.compare(recipient.address, conversation.lastMessage!!.address)
}?.contact?.name
}

return return Pair(conversation, conversationLastSmsSender)
}

override fun getConversations(vararg threadIds: Long): RealmResults<Conversation> {
Expand Down
64 changes: 64 additions & 0 deletions domain/src/main/java/com/moez/QKSMS/interactor/SpeakThreads.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2017 Moez Bhatti <[email protected]>
*
* This file is part of QKSMS.
*
* QKSMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QKSMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
*/
package dev.octoshrimpy.quik.interactor

import android.content.res.Resources
import com.moez.QKSMS.manager.SpeakManager
import dev.octoshrimpy.quik.domain.R
import dev.octoshrimpy.quik.extensions.mapNotNull
import dev.octoshrimpy.quik.repository.ConversationRepository
import dev.octoshrimpy.quik.repository.MessageRepository
import io.reactivex.Flowable
import io.reactivex.Single
import javax.inject.Inject

class SpeakThreads @Inject constructor(
private val conversationRepo: ConversationRepository,
private val messageRepo: MessageRepository,
) : Interactor<List<Long>>() {

companion object {
private var noMessagesStr = "No messages" // default value

fun setNoMessagesString(newNoMessagesString: String) {
noMessagesStr = newNoMessagesString
}
}

override fun buildObservable(threadIds: List<Long>): Flowable<*> {
val speakManager = SpeakManager()

if (threadIds.isEmpty())
return Single.just(0)
.doOnSubscribe { speakManager.startSpeakSession(noMessagesStr) }
.map { speakManager.speak(noMessagesStr) }
.doOnTerminate { speakManager.endSpeakSession() }
.toFlowable()

return Flowable.fromIterable(threadIds)
.doOnSubscribe { speakManager.startSpeakSession("threads:" + threadIds.sorted().joinToString()) }
.mapNotNull { threadId -> conversationRepo.getConversationAndLastSenderContactName(threadId) }
.map { conversationAndSender ->
if (speakManager.speakConversationLastSms(conversationAndSender))
messageRepo.markSeen(conversationAndSender.first!!.id)
}
.doOnTerminate { speakManager.endSpeakSession() }
}

}
Loading

0 comments on commit 61293ce

Please sign in to comment.