Skip to content

Commit

Permalink
refactor(reader): simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
Irineu333 committed Nov 20, 2023
1 parent 04be3c6 commit 0c33362
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,11 @@ class SpeechController(
}

fun speak(text: Text) {
Timber.i("speak: $text")

speak(text.resolved(context))
}

fun speak(nodeInfo: AccessibilityNodeInfoCompat) {

Timber.i("speak: ${nodeInfo.getLog()}")

speak(reader.getContent(nodeInfo))
speak(reader.readContent(nodeInfo))
}

fun stop() {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/neo/speaktouch/model/Type.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ sealed class Type {

if (node.collectionInfo != null) return List

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && node.isHeading) return Title
if (node.isHeading) return Title

return null
}
Expand Down
128 changes: 47 additions & 81 deletions app/src/main/java/com/neo/speaktouch/utils/Reader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,108 +22,74 @@ import android.content.Context
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import com.neo.speaktouch.R
import com.neo.speaktouch.model.Type
import com.neo.speaktouch.utils.extension.filterNotNullOrEmpty
import com.neo.speaktouch.utils.extension.getLog
import com.neo.speaktouch.utils.extension.ifEmptyOrNull
import com.neo.speaktouch.utils.extension.iterator
import com.neo.speaktouch.utils.extension.toText
import timber.log.Timber
import javax.inject.Inject

class Reader @Inject constructor(
private val context: Context
) {
fun getContent(
nodeInfo: AccessibilityNodeInfoCompat
) = getContent(
nodeInfo,
Level.Text(
mustReadSelection = true,
mustReadType = true
)
)

private fun getContent(
fun readContent(
node: AccessibilityNodeInfoCompat,
level: Level
): String {
Timber.d(
node.getLog(
"level: $level"
)
)
options: Options = Options()
) = with(node) {

return when (level) {
is Level.Text -> with(node) {
val content = contentDescription.ifEmptyOrNull {
text.ifEmptyOrNull {
hintText.ifEmptyOrNull {
getContent(
node,
Level.Children
)
}
}
val content = contentDescription.ifEmptyOrNull {
text.ifEmptyOrNull {
hintText.ifEmptyOrNull {
readChildren(node)
}

listOf(
content,
getType(node, level.mustReadType),
getSelection(node, level.mustReadSelection)
).filterNotNullOrEmpty()
}
}

is Level.Children -> buildList {
for (child in node) {

if (!NodeValidator.isValidForAccessibility(child)) continue
if (!NodeValidator.isReadableAsChild(child)) continue
buildList {
add(content)

add(
getContent(
child,
Level.Text(
mustReadSelection = false,
mustReadType = listOf(
Type.Checkable.Switch,
Type.Checkable.Toggle,
Type.Checkable.Radio,
Type.Checkable.Checkbox
).any { it == Type.get(child) }
)
)
)
if (options.mustReadType) {
node.toText()?.let {
add(it.resolved(context))
}
}
}.joinToString(", ")
}

private fun getType(
node: AccessibilityNodeInfoCompat,
mustRead: Boolean
): String? {

if (!mustRead) return null
if (options.mustReadSelection && node.isSelected) {
add(context.getString(R.string.text_selected))
}

return node.toText()?.resolved(context)
}.joinToString(
separator = ", ",
postfix = "."
)
}

private fun getSelection(
node: AccessibilityNodeInfoCompat,
mustRead: Boolean
) = if (mustRead && node.isSelected) {
context.getString(R.string.text_selected)
} else {
null
fun readChildren(
node: AccessibilityNodeInfoCompat
): CharSequence {
return buildList {
for (child in node) {

if (!NodeValidator.isValidForAccessibility(child)) continue
if (!NodeValidator.isReadableAsChild(child)) continue

add(
readContent(
node = child,
options = Options(
mustReadSelection = false,
mustReadType = Type.get(child) is Type.Checkable
)
)
)
}
}.joinToString(
separator = ", ",
postfix = "."
)
}

sealed interface Level {

data class Text(
val mustReadSelection: Boolean,
val mustReadType: Boolean,
) : Level

data object Children : Level
}
data class Options(
val mustReadSelection: Boolean = true,
val mustReadType: Boolean = true,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ inline fun <T : CharSequence> T?.ifEmptyOrNull(
}
}

fun <T : List<CharSequence?>> T.filterNotNullOrEmpty() = filterNot { it.isNullOrEmpty() }

infix fun CharSequence.`is`(childClass: Class<*>): Boolean {
if (equals(childClass.name)) return true
if (isEmpty()) return false
Expand Down

0 comments on commit 0c33362

Please sign in to comment.