Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added worker to update stats regularly #88

Merged
merged 9 commits into from
Nov 6, 2023
6 changes: 0 additions & 6 deletions .idea/deploymentTargetDropDown.xml

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

24 changes: 24 additions & 0 deletions .idea/kotlinScripting.xml

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

2 changes: 1 addition & 1 deletion .idea/misc.xml

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

Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import androidx.navigation.navOptions
import com.jacob.wakatimeapp.details.ui.DetailsPageNavigator
import com.jacob.wakatimeapp.details.ui.destinations.DetailsPageDestination
import com.jacob.wakatimeapp.home.ui.HomePageNavigator
import com.jacob.wakatimeapp.home.ui.destinations.ExtractUserDataPageDestination
import com.jacob.wakatimeapp.home.ui.destinations.HomePageDestination
import com.jacob.wakatimeapp.home.ui.extract.ExtractUserDataNavigator
import com.jacob.wakatimeapp.login.ui.LoginPageNavigator
import com.jacob.wakatimeapp.login.ui.destinations.ExtractUserDataPageDestination
import com.jacob.wakatimeapp.login.ui.destinations.LoadingPageDestination
import com.jacob.wakatimeapp.login.ui.destinations.LoginPageDestination
import com.jacob.wakatimeapp.login.ui.extract.ExtractUserDataNavigator
import com.jacob.wakatimeapp.search.ui.SearchProjectsNavigator
import com.jacob.wakatimeapp.search.ui.destinations.SearchProjectsDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.jacob.wakatimeapp.navigation

import com.jacob.wakatimeapp.details.ui.destinations.DetailsPageDestination
import com.jacob.wakatimeapp.home.ui.destinations.ExtractUserDataPageDestination
import com.jacob.wakatimeapp.home.ui.destinations.HomePageDestination
import com.jacob.wakatimeapp.login.ui.destinations.ExtractUserDataPageDestination
import com.jacob.wakatimeapp.login.ui.destinations.LoadingPageDestination
import com.jacob.wakatimeapp.login.ui.destinations.LoginPageDestination
import com.jacob.wakatimeapp.search.ui.destinations.SearchProjectsDestination
import com.ramcosta.composedestinations.spec.DestinationSpec
Expand All @@ -12,9 +13,10 @@ object NavGraphs {
val root = object : NavGraphSpec {
override val route = "root"

override val startRoute = LoginPageDestination
override val startRoute = LoadingPageDestination

override val destinationsByRoute = listOf<DestinationSpec<*>>(
LoadingPageDestination,
LoginPageDestination,
HomePageDestination,
SearchProjectsDestination,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ class AuthTokenProvider @Inject constructor(
}
.filterNotNull()
.take(1)

fun logout() = runBlocking {
update(AuthState())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ data class MachineDTO(
@SerialName("total_seconds") val totalSeconds: Double,
)

@Serializable
data class BranchDTO(
val decimal: String,
val digital: String,
val hours: Int,
val minutes: Int,
val name: String,
val percent: Double,
val seconds: Int,
val text: String,
@SerialName("total_seconds") val totalSeconds: Double,
)

@Serializable
data class OperatingSystemDTO(
val decimal: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,7 @@ data class ExtractedDataDTO(
val name: String,
@SerialName("grand_total") val grandTotal: GrandTotalDTO,
@SerialName("operating_systems") val operatingSystems: List<OperatingSystemDTO>,
) {
@Serializable
data class BranchDTO(
val decimal: String,
val digital: String,
val hours: Int,
val minutes: Int,
val name: String,
val percent: Double,
val seconds: Int,
val text: String,
@SerialName("total_seconds") val totalSeconds: Double,
)
}
)
}

@Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.jacob.wakatimeapp.core.common.data.local

import arrow.core.Either
import com.jacob.wakatimeapp.core.common.data.dtos.ExtractedDataDTO
import com.jacob.wakatimeapp.core.common.data.local.dao.ApplicationDao
import com.jacob.wakatimeapp.core.common.data.local.entities.DayEntity
import com.jacob.wakatimeapp.core.common.data.local.entities.ProjectPerDay
import com.jacob.wakatimeapp.core.models.DetailedDailyStats
import com.jacob.wakatimeapp.core.models.Error
import com.jacob.wakatimeapp.core.models.Range
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.datetime.LocalDate
Expand All @@ -10,12 +16,23 @@ import kotlinx.datetime.LocalDate
class WakaTimeAppDB @Inject constructor(
private val applicationDao: ApplicationDao,
) {
suspend fun getStatsForDay(date: LocalDate) = applicationDao.getStatsForDay(date)
suspend fun getStatsForDay(date: LocalDate): Either<Error, List<DayEntity>> = Either.catch {
applicationDao.getStatsForDay(date)
}.mapLeft { Error.DatabaseError.UnknownError("could not get stats for day ($date)", it) }

suspend fun getStatsForProject(name: String) = applicationDao.getStatsForProject(name)
suspend fun getStatsForProject(name: String): Either<Error, List<ProjectPerDay>> = Either.catch {
applicationDao.getStatsForProject(name)
}.mapLeft { Error.DatabaseError.UnknownError("could not get stats for project ($name)", it) }

suspend fun getDateRangeInDb() = applicationDao.getDateRangeInDb()
suspend fun getDateRangeInDb(): Either<Error, Range> = Either.catch {
applicationDao.getDateRangeInDb()
}.mapLeft { Error.DatabaseError.UnknownError("could not get range from db", it) }

suspend fun insertExtractedData(extractedDataDTO: ExtractedDataDTO) =
suspend fun insertExtractedData(extractedDataDTO: ExtractedDataDTO): Either<Error, Unit> = Either.catch {
applicationDao.insertStatesForDay(extractedDataDTO)
}.mapLeft { Error.DatabaseError.UnknownError("could not insert extracted data into db", it) }

suspend fun insertExtractedData(detailedDailyStats: List<DetailedDailyStats>): Either<Error, Unit> = Either.catch {
applicationDao.insertStatesForDay(detailedDailyStats)
}.mapLeft { Error.DatabaseError.UnknownError("could not insert aggregate stats data into db", it) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.jacob.wakatimeapp.core.common.data.dtos.ExtractedDataDTO
import com.jacob.wakatimeapp.core.common.data.local.entities.DayEntity
import com.jacob.wakatimeapp.core.common.data.local.entities.ProjectPerDay
import com.jacob.wakatimeapp.core.common.data.mappers.toEntity
import com.jacob.wakatimeapp.core.models.DetailedDailyStats
import com.jacob.wakatimeapp.core.models.DetailedProjectStatsForDay
import com.jacob.wakatimeapp.core.models.Range
import kotlinx.datetime.LocalDate

Expand All @@ -17,7 +19,7 @@ interface ApplicationDao {
suspend fun getStatsForDay(date: LocalDate): List<DayEntity>

@Query("SELECT min(date) as startDate, max(date) as endDate FROM DayEntity")
suspend fun getDateRangeInDb(): Range?
suspend fun getDateRangeInDb(): Range

@Query("SELECT * FROM ProjectPerDay WHERE name = :name")
suspend fun getStatsForProject(name: String): List<ProjectPerDay>
Expand All @@ -37,4 +39,38 @@ interface ApplicationDao {
.let { projectsPerDays -> insertProjectStatsForDay(projectsPerDays) }
}
}

@Transaction
suspend fun insertStatesForDay(detailedDailyStats: List<DetailedDailyStats>) {
detailedDailyStats.forEach {
val dayId = insertStatesForDay(it.toEntity())
it.projects
.map { project -> project.toEntity(dayId) }
.let { projectsPerDays -> insertProjectStatsForDay(projectsPerDays) }
}
}
}

fun DetailedProjectStatsForDay.toEntity(dayId: Long): ProjectPerDay {
return ProjectPerDay(
projectPerDayId = 0,
dayIdFk = dayId,
name = name,
grandTotal = totalTime,
editors = editors,
languages = languages,
operatingSystems = operatingSystems,
branches = branches,
machines = machines,
)
}

private fun DetailedDailyStats.toEntity() = DayEntity(
dayId = 0,
date = date,
grandTotal = timeSpent,
editors = editors,
languages = languages,
operatingSystems = operatingSystems,
machines = emptyList(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
@file:Suppress("TooManyFunctions")

package com.jacob.wakatimeapp.core.common.data.mappers

import com.jacob.wakatimeapp.core.common.data.dtos.BranchDTO
import com.jacob.wakatimeapp.core.common.data.dtos.EditorDTO
import com.jacob.wakatimeapp.core.common.data.dtos.LanguageDTO
import com.jacob.wakatimeapp.core.common.data.dtos.MachineDTO
import com.jacob.wakatimeapp.core.common.data.dtos.OperatingSystemDTO
import com.jacob.wakatimeapp.core.common.data.dtos.ProjectDTO
import com.jacob.wakatimeapp.core.models.Branch
import com.jacob.wakatimeapp.core.models.Machine
import com.jacob.wakatimeapp.core.models.Time
import com.jacob.wakatimeapp.core.models.secondarystats.Editor
import com.jacob.wakatimeapp.core.models.secondarystats.Editors
import com.jacob.wakatimeapp.core.models.secondarystats.Language
import com.jacob.wakatimeapp.core.models.secondarystats.Languages
import com.jacob.wakatimeapp.core.models.secondarystats.OperatingSystem
import com.jacob.wakatimeapp.core.models.secondarystats.OperatingSystems
import kotlinx.collections.immutable.toImmutableList

fun List<LanguageDTO>.toModel() = map(LanguageDTO::toModel).let(::Languages)

fun List<EditorDTO>.toModel() = map(EditorDTO::toModel).let(::Editors)

fun List<OperatingSystemDTO>.toModel() = map(OperatingSystemDTO::toModel).let(::OperatingSystems)

fun List<ProjectDTO>.toModel() = filterNot(ProjectDTO::isUnknownProject)
.map(ProjectDTO::toModel)
.toImmutableList()

fun LanguageDTO.toModel() = Language(
name = name,
time = Time.fromTotalSeconds(totalSeconds),
)

fun EditorDTO.toModel() = Editor(
name = name,
time = Time.fromTotalSeconds(totalSeconds),
)

fun OperatingSystemDTO.toModel() = OperatingSystem(
name = name,
time = Time.fromTotalSeconds(totalSeconds),
)

fun List<EditorDTO>.fromDto() = map(EditorDTO::toModel).let(::Editors)

fun List<LanguageDTO>.fromDto() = map(LanguageDTO::toModel).let(::Languages)

fun List<OperatingSystemDTO>.fromDto() = map(OperatingSystemDTO::toModel).let(::OperatingSystems)

fun List<BranchDTO>.toBranch() = map { branch ->
Branch(
name = branch.name,
time = Time.fromTotalSeconds(branch.totalSeconds),
)
}

fun List<MachineDTO>.toMachine() = map { machine ->
Machine(
name = machine.name,
time = Time.fromTotalSeconds(machine.totalSeconds),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fun DayDTO.toEntity() = DayEntity(
machines = this.machines.map { machine ->
Machine(
name = machine.name,
time = Time.fromDecimal(machine.totalSeconds.toFloat()),
time = Time.fromTotalSeconds(machine.totalSeconds),
)
},
)
Expand All @@ -27,13 +27,13 @@ fun ProjectDTO.toEntity(dayId: Long): ProjectPerDay {
val branches = branches.map { branch ->
com.jacob.wakatimeapp.core.models.Branch(
name = branch.name,
time = Time.fromDecimal(branch.totalSeconds.toFloat()),
time = Time.fromTotalSeconds(branch.totalSeconds),
)
}
val machines = machines.map { machine ->
Machine(
name = machine.name,
time = Time.fromDecimal(machine.totalSeconds.toFloat()),
time = Time.fromTotalSeconds(machine.totalSeconds),
)
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ package com.jacob.wakatimeapp.core.common.utils
import javax.inject.Inject
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime

interface InstantProvider {
val timeZone: TimeZone
fun now(): Instant

fun date(): LocalDate = now().toLocalDateTime(timeZone).date
}

class DefaultInstantProvider @Inject constructor() : InstantProvider {
Expand Down
Loading
Loading