Skip to content

Commit

Permalink
Updated dependencies
Browse files Browse the repository at this point in the history
Implemented swipe to delete
Improved tutorial to get started
Improved accessibility service description
  • Loading branch information
denzilferreira committed Apr 22, 2024
1 parent 1fd6128 commit b101d65
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 43 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ dependencies {
implementation libs.androidx.material3
implementation libs.androidx.lifecycle.viewmodel.compose
implementation libs.androidx.room.runtime
implementation libs.accompanist.swiperefresh
kapt libs.androidx.room.compiler
implementation libs.androidx.room.ktx
testImplementation libs.junit
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/com/hisense/einkservice/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ class MainActivity : ComponentActivity() {
mutableStateOf(false)
}

val repository = EinkAccessibility.getRepository(applicationContext)
val viewModel by viewModels<MainActivityViewModel> {
MainActivityViewModelFactory(repository)
MainActivityViewModelFactory(EinkAccessibility.getRepository(applicationContext))
}

val apps by viewModel.apps.collectAsState(initial = emptyList())

HisenseTheme {
Expand All @@ -65,6 +65,9 @@ class MainActivity : ComponentActivity() {
),
)
},
onSwipe = { app ->
viewModel.removeApp(app)
},
)
}
}
Expand Down Expand Up @@ -99,6 +102,7 @@ private fun AppPreview() {
isAccessibilityEnabled = false,
onAccessibilityClicked = { },
onOverlayClicked = { },
onSwipe = { },
)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.hisense.einkservice.repository

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
Expand All @@ -16,9 +17,12 @@ interface EinkAppDao {
@Update
suspend fun update(einkApp: EinkApp)

@Delete
suspend fun delete(einkApp: EinkApp)

@Query("SELECT * FROM eink_apps")
fun getAll(): Flow<List<EinkApp>>
suspend fun getAll(): List<EinkApp>

@Query("SELECT * FROM eink_apps WHERE packageName = :packageName")
fun getByPackageName(packageName: String): EinkApp?
suspend fun getByPackageName(packageName: String): EinkApp?
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ interface EinkAppRepository {

suspend fun update(einkApp: EinkApp)

fun getAll(): Flow<List<EinkApp>>
suspend fun delete(einkApp: EinkApp)

fun getByPackageName(packageName: String): EinkApp?
suspend fun getAll(): List<EinkApp>

suspend fun getByPackageName(packageName: String): EinkApp?
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ class EinkAppRepositoryImpl(private val einkAppDao: EinkAppDao) : EinkAppReposit
einkAppDao.update(einkApp)
}

override fun getAll(): Flow<List<EinkApp>> {
override suspend fun delete(einkApp: EinkApp) {
einkAppDao.delete(einkApp)
}

override suspend fun getAll(): List<EinkApp> {
return einkAppDao.getAll()
}

override fun getByPackageName(packageName: String): EinkApp? {
override suspend fun getByPackageName(packageName: String): EinkApp? {
return einkAppDao.getByPackageName(packageName)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
package com.hisense.einkservice.ui.views

import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SwipeToDismissBox
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.rememberSwipeToDismissBoxState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
Expand All @@ -39,6 +50,7 @@ fun EinkMainActivityScreen(
isAccessibilityEnabled: Boolean,
onAccessibilityClicked: () -> Unit,
onOverlayClicked: () -> Unit,
onSwipe: (EinkApp) -> Unit,
) {
Scaffold(
topBar = {
Expand Down Expand Up @@ -69,7 +81,7 @@ fun EinkMainActivityScreen(
if (apps.isEmpty()) {
TutorialNotice()
}
AppsList(apps = apps)
AppsList(apps = apps, onSwipe = onSwipe)
Spacer(modifier = Modifier.weight(1f))
Text(
"Made with ❤\uFE0F - Denzil Ferreira, and you? \uD83D\uDE09",
Expand All @@ -80,35 +92,73 @@ fun EinkMainActivityScreen(
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun AppsList(apps: List<EinkApp>) {
val lazyListState = rememberLazyListState()
private fun AppsList(
apps: List<EinkApp>,
onSwipe: (app: EinkApp) -> Unit,
) {
val context = LocalContext.current

LazyColumn(
modifier = Modifier.fillMaxWidth(),
state = lazyListState,
modifier = Modifier.fillMaxWidth().animateContentSize(),
verticalArrangement = Arrangement.spacedBy(8.dp),
userScrollEnabled = true,
) {
items(apps.size) { index ->
items(apps.size, { index -> apps[index].packageName } ) { index ->
val item = apps[index]
EinkAppItemView(
item = item,
onSetNewSpeed = { newSpeed ->
CoroutineScope(Dispatchers.IO).launch {
val repository = EinkAccessibility.getRepository(context)
val einkApp = repository.getByPackageName(item.packageName)
val dismissState = rememberSwipeToDismissBoxState(
confirmValueChange = {
if (it == SwipeToDismissBoxValue.EndToStart) {
onSwipe(item)
true
} else {
false
}
}
)

SwipeToDismissBox(
modifier = Modifier.animateContentSize(),
enableDismissFromEndToStart = true,
backgroundContent = {
val success = dismissState.targetValue == SwipeToDismissBoxValue.EndToStart
val color by animateColorAsState(
if (success) MaterialTheme.colorScheme.errorContainer else Color.Transparent,
label = "color"
)
Box(
Modifier
.fillMaxSize()
.background(color),
contentAlignment = Alignment.CenterEnd
) {
Icon(Icons.Default.Delete, contentDescription = "Delete")
}
},
content = {
EinkAppItemView(
item = item,
onSetNewSpeed = { newSpeed ->
CoroutineScope(Dispatchers.IO).launch {
val repository = EinkAccessibility.getRepository(context)
val einkApp = repository.getByPackageName(item.packageName)

einkApp?.let {
einkApp.preferredSpeed = newSpeed.getSpeed()
repository.update(einkApp)
einkApp?.let {
einkApp.preferredSpeed = newSpeed.getSpeed()
repository.update(einkApp)

// apply immediately the new speed for Eink Center
if (einkApp.packageName == context.packageName) {
EinkAccessibility.einkService().setSpeed(newSpeed.getSpeed())
// apply immediately the new speed for Eink Center
if (einkApp.packageName == context.packageName) {
EinkAccessibility.einkService()
.setSpeed(newSpeed.getSpeed())
}
}
}
}
}
}
)
},
state = dismissState,
)
}
}
Expand Down Expand Up @@ -166,8 +216,14 @@ private fun TutorialNotice() {
"No apps yet \uD83D\uDE2D. Let's change that!",
fontWeight = FontWeight.Bold,
)
Text(stringResource(id = R.string.eink_tutorial_text), style = MaterialTheme.typography.bodySmall)
Text("This tutorial will disappear once you add an app. Let's GO! \uD83D\uDE80", style = MaterialTheme.typography.labelSmall)
Text(
text = stringResource(id = R.string.eink_tutorial_text),
style = MaterialTheme.typography.bodySmall
)
Text(
text = "This tutorial will disappear once you add an app. Let's GO! \uD83D\uDE80",
style = MaterialTheme.typography.labelSmall
)
}
}
}
Expand All @@ -182,6 +238,7 @@ fun EinkActivityScreenPreview() {
isAccessibilityEnabled = true,
onAccessibilityClicked = { },
onOverlayClicked = { },
onSwipe = { },
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,31 @@ package com.hisense.einkservice.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.hisense.einkservice.model.EinkApp
import com.hisense.einkservice.repository.EinkAppRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class MainActivityViewModel(
repository: EinkAppRepository,
private val repository: EinkAppRepository,
) : ViewModel() {
val apps: Flow<List<EinkApp>> = repository.getAll()
private val _apps = MutableStateFlow<List<EinkApp>>(emptyList())
var apps: StateFlow<List<EinkApp>> = _apps

init {
viewModelScope.launch {
_apps.value = repository.getAll()
}
}

fun removeApp(app: EinkApp) {
viewModelScope.launch {
repository.delete(app)
_apps.value = repository.getAll()
}
}
}

class MainActivityViewModelFactory(
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<resources>
<string name="app_name">Eink Center</string>
<string name="eink_accessibility_service">
This service is responsible to showing an overlay to set and restore a refresh speed for the eink display.\n
Eink Center is open-source. You can check the source code at \n
This service is responsible to showing an overlay to set and restore a refresh speed for the eink display. Eink Center is open-source. You can check the source code at \n
https://github.com/denzilferreira/vendor_hisense
</string>
<string name="eink_tutorial_text">
Using the Eink Button\n
- Press Eink button once quickly to refresh.\n
- Open an app, press twice quickly to select and save an app speed.\n
- Hold and release for 1 second to open Eink Center.\n
- Hold and release for 1 second to open Eink Center.\n\n
Did you know?\n
- Eink Center restores automatically the last speed you set for an app.\n
- Set a default speed for unknown apps by setting the speed of Eink Center.\n
- Change the default speed of an app by selecting the speed of the app here.\n
- Tweak an app speed from Eink Center.\n
- Swipe to remove an app from the list.\n
</string>
</resources>
10 changes: 6 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
[versions]
agp = "8.3.1"
kotlin = "1.9.0"
coreKtx = "1.12.0"
coreKtx = "1.13.0"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.7.0"
activityCompose = "1.8.2"
composeBom = "2024.04.00"
activityCompose = "1.9.0"
composeBom = "2024.04.01"
lifecycleViewmodelCompose = "2.7.0"
roomRuntime = "2.6.1"
roomCompiler = "2.6.1"
roomKtx = "2.6.1"
accompanistSwiperefresh = "0.35.0-alpha"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
Expand All @@ -25,13 +26,14 @@ androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version = "1.6.5" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version = "1.6.6" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "roomRuntime" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "roomCompiler" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomKtx" }
accompanist-swiperefresh = { group = "com.google.accompanist", name = "accompanist-swiperefresh", version.ref = "accompanistSwiperefresh" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
Expand Down

0 comments on commit b101d65

Please sign in to comment.