Skip to content

Commit

Permalink
Split app into two activities (#110)
Browse files Browse the repository at this point in the history
* Move settings-related screens into second activity #93 
* Add drop shadow to appcards
* Open google wallpapers by default
* Switch to StateFlow
* fix bug where usage of favorites didn't update #88
  • Loading branch information
simonalveteg authored Jul 14, 2024
1 parent 642f664 commit 230dce4
Show file tree
Hide file tree
Showing 29 changed files with 396 additions and 271 deletions.
3 changes: 3 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 19 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/>
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />

Expand All @@ -27,22 +28,35 @@
android:theme="@style/Theme.MinuteLauncher"
tools:targetApi="31">
<activity
android:name="com.alveteg.simon.minutelauncher.MainActivity"
android:name="com.alveteg.simon.minutelauncher.home.HomeActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=".Home"
android:theme="@style/Theme.MinuteLauncher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".settings.SettingsActivity"
android:taskAffinity=".Settings"
android:launchMode="singleTop"
android:excludeFromRecents="true"
android:theme="@style/Theme.MinuteLauncher.Settings"
android:noHistory="true">

</activity>

<service
android:name="com.alveteg.simon.minutelauncher.MinuteAccessibilityService"
android:enabled="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="false">
android:exported="false"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
Expand Down
25 changes: 2 additions & 23 deletions app/src/main/java/com/alveteg/simon/minutelauncher/Event.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,4 @@
package com.alveteg.simon.minutelauncher

import com.alveteg.simon.minutelauncher.data.AccessTimer
import com.alveteg.simon.minutelauncher.data.AccessTimerMapping
import com.alveteg.simon.minutelauncher.data.App
import com.alveteg.simon.minutelauncher.data.AppInfo
import com.alveteg.simon.minutelauncher.data.FavoriteAppInfo
import com.alveteg.simon.minutelauncher.utilities.Gesture


sealed class Event {
data class OpenApplication(val appInfo: AppInfo) : Event()
data class LaunchActivity(val appInfo: AppInfo) : Event()
data class UpdateSearch(val searchTerm: String) : Event()
data class ToggleFavorite(val app: App) : Event()
data class HandleGesture(val gesture: Gesture) : Event()
data class SetAppGesture(val app: App, val gesture: Gesture) : Event()
data class ClearAppGesture(val gesture: Gesture) : Event()
data class UpdateFavoriteOrder(val favorites: List<FavoriteAppInfo>) : Event()
data class UpdateApp(val app: App) : Event()
data object OpenGestureSettings : Event()
data class OpenGestureList(val gesture: Gesture) : Event()
data object OpenTimerSettings : Event()
data class SetDefaultTimer(val accessTimerMapping: AccessTimerMapping) : Event()
}
interface Event {
}
57 changes: 9 additions & 48 deletions app/src/main/java/com/alveteg/simon/minutelauncher/NavGraph.kt
Original file line number Diff line number Diff line change
@@ -1,80 +1,41 @@
package com.alveteg.simon.minutelauncher

import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.alveteg.simon.minutelauncher.home.HomeScreen
import com.alveteg.simon.minutelauncher.settings.GestureList
import com.alveteg.simon.minutelauncher.settings.GestureScreen
import com.alveteg.simon.minutelauncher.settings.SettingsScreen
import com.alveteg.simon.minutelauncher.settings.TimerScreen
import com.alveteg.simon.minutelauncher.utilities.Gesture

@Composable
fun LauncherNavHost(
navController: NavHostController,
startDestination: String
) {
NavHost(navController = navController,
startDestination = MinuteRoute.HOME,
enterTransition = { EnterTransition.None },
exitTransition = { fadeOut(tween(delayMillis = 2000)) },
popEnterTransition = { EnterTransition.None },
popExitTransition = { ExitTransition.None }) {
composable(
route = MinuteRoute.HOME
) {
HomeScreen(onNavigate = { navController.navigationEvent(event = it) })
}
composable(route = MinuteRoute.GESTURE_SETTINGS,
enterTransition = {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Up
)
},
exitTransition = { fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { fadeOut() }) {
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(route = SettingsScreen.GESTURE_SETTINGS) {
GestureScreen(onNavigate = { navController.navigationEvent(event = it) })
}
composable(
route = MinuteRoute.GESTURE_SETTINGS_LIST + "/{gesture}",
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Up) }
) { backStackEntry ->
composable(route = SettingsScreen.GESTURE_SETTINGS_LIST + "/{gesture}") { backStackEntry ->
val gesture = backStackEntry.arguments?.getString("gesture") ?: Gesture.NONE.toString()
GestureList(
onNavigate = { navController.navigationEvent(event = it) },
gesture = Gesture.valueOf(gesture)
)
}
composable(
route = MinuteRoute.TIMER_SETTINGS,
enterTransition = {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Up
)
},
exitTransition = { fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { fadeOut() }
) {
composable(route = SettingsScreen.TIMER_SETTINGS) {
TimerScreen(onNavigate = { navController.navigationEvent(event = it) })
}
}
}

object MinuteRoute {
const val HOME = "home"
const val GESTURE_SETTINGS = "gesture_settings"
const val GESTURE_SETTINGS_LIST = "gestures_list"
const val TIMER_SETTINGS = "timer_settings"
}

fun NavController.navigationEvent(event: UiEvent.Navigate) {
navigate(event.route) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,33 +69,32 @@ class ApplicationRepository @Inject constructor(
}

suspend fun startUsageUpdater() {
Timber.d("Starting usage updater.")
while (currentCoroutineContext().isActive) {
val usageStats = getDailyStatsForWeek()

_usageStats.emit(usageStats)
Timber.d("Emitting usage stats.")
_usageStats.emit(getDailyStatsForWeek())
delay(TimeUnit.MINUTES.toMillis(1))
}
}

private fun getDailyStatsForWeek(): List<UsageStatistics> {
val today = LocalDate.now()
val dates = listOf(
today,
today.minusDays(1),
today.minusDays(2),
today.minusDays(3),
today.minusDays(4),
today.minusDays(5),
today.minusDays(6)
)
val dates = mutableListOf<LocalDate>()
repeat(7) { dates += today.minusDays(it.toLong()) }

val launcherApps = getLauncherApps()
return dates.flatMap { date ->
Timber.d("Getting stats for date: $date")
getDailyStats(date)
.filter { !launcherApps.contains(it.packageName) }
.filter { context.packageName != it.packageName }
}.also { Timber.d("--- ${it.size} packages, ${it.sumOf { it.usageDuration }.toTimeUsed()} ") }
.also {
Timber.d(
"$date: ${it.size} packages, ${
it.sumOf { it.usageDuration }.toTimeUsed()
}"
)
}
}
}

/**
Expand Down
21 changes: 19 additions & 2 deletions app/src/main/java/com/alveteg/simon/minutelauncher/home/AppCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
Expand All @@ -17,6 +18,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
Expand All @@ -34,11 +36,14 @@ fun AppCard(
onClick: () -> Unit
) {
val appTitle = appInfo.app.appTitle
val appUsage by remember { derivedStateOf { appInfo.usage.firstOrNull { it.usageDate == LocalDate.now() }?.usageDuration } }
val appUsage by remember(appInfo) {
derivedStateOf {
appInfo.usage.firstOrNull { it.usageDate == LocalDate.now() }?.usageDuration
}
}
val interactionSource = remember { MutableInteractionSource() }

Surface(
tonalElevation = 2.dp,
shape = MaterialTheme.shapes.large,
color = Color.Transparent,
modifier = Modifier
Expand All @@ -61,13 +66,25 @@ fun AppCard(
fontSize = 25.sp,
textAlign = TextAlign.Center,
overflow = TextOverflow.Clip,
style = LocalTextStyle.current.copy(
shadow = Shadow(
color = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
blurRadius = 12f
)
),
modifier = Modifier
.fillMaxWidth()
)
Text(
text = appUsage.toTimeUsed(),
fontFamily = archivoFamily,
color = MaterialTheme.colorScheme.primary,
style = LocalTextStyle.current.copy(
shadow = Shadow(
color = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
blurRadius = 12f
)
)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package com.alveteg.simon.minutelauncher.home
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
Expand All @@ -18,6 +18,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
Expand All @@ -37,7 +38,9 @@ fun FavoriteCard(
) {
val interactionSource = remember { MutableInteractionSource() }
val appTitle = appInfo.app.appTitle
val appUsage by remember { derivedStateOf { appInfo.usage.firstOrNull { it.usageDate == LocalDate.now() }?.usageDuration } }
val appUsage by remember(appInfo) {
derivedStateOf { appInfo.usage.firstOrNull { it.usageDate == LocalDate.now() }?.usageDuration }
}

Surface(
shape = MaterialTheme.shapes.large,
Expand All @@ -60,6 +63,12 @@ fun FavoriteCard(
fontFamily = archivoBlackFamily,
fontSize = 25.sp,
textAlign = TextAlign.Center,
style = LocalTextStyle.current.copy(
shadow = Shadow(
color = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
blurRadius = 12f
)
),
overflow = TextOverflow.Clip,
modifier = Modifier
.fillMaxWidth()
Expand All @@ -68,6 +77,12 @@ fun FavoriteCard(
text = appUsage.toTimeUsed(),
fontFamily = archivoFamily,
color = MaterialTheme.colorScheme.primary,
style = LocalTextStyle.current.copy(
shadow = Shadow(
color = MaterialTheme.colorScheme.background.copy(alpha = 0.5f),
blurRadius = 12f
)
)
)
}
}
Expand Down
Loading

0 comments on commit 230dce4

Please sign in to comment.