From 0805da43f886f9bad36ca2f33845e047390388ae Mon Sep 17 00:00:00 2001 From: Maksim Mishenko Date: Tue, 5 Dec 2023 19:33:59 +0600 Subject: [PATCH 1/2] [~] write simple timer --- .../tv/domain/newYear/NewYearUseCase.kt | 42 +++++++++++++++++++ .../components/EventStoryScreenContent.kt | 21 ++++++++++ .../screen/eventStory/EventStoryViewModel.kt | 18 ++++++++ .../screen/eventStory/models/EventInfoUI.kt | 10 +++-- 4 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt diff --git a/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt b/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt new file mode 100644 index 00000000..c6d7f93f --- /dev/null +++ b/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt @@ -0,0 +1,42 @@ +package band.effective.office.tv.domain.newYear + +import band.effective.office.tv.screen.eventStory.models.NewYearCounter +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import java.util.Calendar +import java.util.GregorianCalendar + +class NewYearUseCase { + suspend fun getCounter(): Flow = flow { + while (true) { + emit(counter()) + delay(1000) // TODO + } + } + + fun counter(): NewYearCounter { + val today = GregorianCalendar() + val newYear = GregorianCalendar().apply { + set(Calendar.MILLISECOND, 0) + set(Calendar.SECOND, 0) + set(Calendar.MINUTE, 0) + set(Calendar.DAY_OF_YEAR, 0) + set(Calendar.MONTH, 0) + add(Calendar.YEAR, 1) + } + var duration = newYear.time.time - today.time.time + val mils = (duration % 1000).apply { duration /= 1000 } + val sec = (duration % 60).apply { duration /= 60 } + val min = (duration % 60).apply { duration /= 60 } + val hour = (duration % 24).apply { duration /= 24 } + val day = duration + return NewYearCounter( + day = day.toInt(), + hour = hour.toInt(), + min = min.toInt(), + sec = sec.toInt(), + mil = mils.toInt() + ) + } +} \ No newline at end of file diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt b/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt index 31a86a4e..9dd092f7 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt @@ -1,18 +1,24 @@ package band.effective.office.tv.screen.components +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.Surface +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import band.effective.office.tv.screen.duolingo.DuolingoScreen import band.effective.office.tv.screen.eventStory.models.DuolingoUserInfo import band.effective.office.tv.screen.eventStory.models.EmployeeInfoUI import band.effective.office.tv.screen.eventStory.models.MessageInfo +import band.effective.office.tv.screen.eventStory.models.NewYearCounter import band.effective.office.tv.screen.eventStory.models.StoryModel import band.effective.office.tv.screen.eventStory.models.StoryType import band.effective.office.tv.screen.message.component.OneMessageScreen @@ -52,6 +58,7 @@ fun EventStoryScreenContent( .padding(horizontal = 64.dp) ) } + StoryType.Duolingo -> { val duolingoItem = eventsInfo[currentStoryIndex] as DuolingoUserInfo DuolingoScreen( @@ -59,6 +66,7 @@ fun EventStoryScreenContent( duolingoUser = duolingoItem.users.take(10) ) } + StoryType.Message -> { val messageItem = eventsInfo[currentStoryIndex] as MessageInfo OneMessageScreen( @@ -67,8 +75,21 @@ fun EventStoryScreenContent( message = messageItem.message ) } + + StoryType.NewYear -> NewYearTimer(counter = (eventsInfo[currentStoryIndex] as NewYearCounter)) } } } } + +@Composable +private fun NewYearTimer(counter: NewYearCounter) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text( + text = "${counter.day}:${counter.hour}:${counter.min}:${counter.sec}", + color = Color.Black, + fontSize = 50.sp + ) + } +} diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt b/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt index 72286c0b..89db375b 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt @@ -6,6 +6,7 @@ import band.effective.office.tv.core.network.entity.Either import band.effective.office.tv.core.ui.screen_with_controls.TimerSlideShow import band.effective.office.tv.domain.model.message.BotMessage import band.effective.office.tv.domain.model.message.MessageQueue +import band.effective.office.tv.domain.newYear.NewYearUseCase import band.effective.office.tv.domain.use_cases.EventStoryDataCombinerUseCase import band.effective.office.tv.network.MattermostClient import band.effective.office.tv.screen.autoplayController.AutoplayController @@ -13,6 +14,7 @@ import band.effective.office.tv.screen.autoplayController.model.AutoplayState import band.effective.office.tv.screen.autoplayController.model.OnSwitchCallbacks import band.effective.office.tv.screen.autoplayController.model.ScreenState import band.effective.office.tv.screen.eventStory.models.MessageInfo +import band.effective.office.tv.screen.eventStory.models.NewYearCounter import band.effective.office.tv.screen.eventStory.models.StoryModel import band.effective.office.tv.screen.navigation.Screen import coil.ImageLoader @@ -107,6 +109,22 @@ class EventStoryViewModel @Inject constructor( } } } + viewModelScope.launch { + val useCase = NewYearUseCase() + if (useCase.counter().day < 32) { + useCase.getCounter().collect { newCounter -> + val newEventList = mutableState.value.eventsInfo.toMutableList() + val oldCounterIndex = + mutableState.value.eventsInfo.indexOfFirst { it is NewYearCounter } + if (oldCounterIndex != -1) { + newEventList[oldCounterIndex] = newCounter + } else { + newEventList.add(newCounter) + } + mutableState.update { state.value.copy(eventsInfo = newEventList) } + } + } + } startTimer() } diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/models/EventInfoUI.kt b/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/models/EventInfoUI.kt index a7b1a9b7..fb2734e0 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/models/EventInfoUI.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/models/EventInfoUI.kt @@ -9,7 +9,7 @@ sealed class EmployeeInfoUI( val name: String, val photoUrl: String, val eventType: EventType - ) : StoryModel(StoryType.Employee) +) : StoryModel(StoryType.Employee) data class BirthdayUI( val employeeName: String, @@ -38,14 +38,16 @@ data class NewEmployeeUI( data class DuolingoUserInfo( val keySort: KeySortDuolingoUser, val users: List -): StoryModel(StoryType.Duolingo) +) : StoryModel(StoryType.Duolingo) data class MessageInfo( val message: BotMessage -): StoryModel(StoryType.Message) +) : StoryModel(StoryType.Message) + +data class NewYearCounter(val day: Int, val hour: Int, val min: Int, val sec: Int, val mil: Int): StoryModel(StoryType.NewYear) enum class StoryType { - Duolingo, Employee, Message + Duolingo, Employee, Message, NewYear } abstract class StoryModel(val storyType: StoryType) -- GitLab From 3171fb5dbd37fba441e88a4c2a04c733112ffe8d Mon Sep 17 00:00:00 2001 From: Maksim Mishenko Date: Tue, 5 Dec 2023 21:56:21 +0600 Subject: [PATCH 2/2] [~] clean up --- .../di/view_models/MessageViewModelModule.kt | 5 ++ .../tv/domain/newYear/NewYearUseCase.kt | 2 +- .../components/EventStoryScreenContent.kt | 18 +---- .../tv/screen/components/NewYearTimer.kt | 66 +++++++++++++++++++ .../screen/eventStory/EventStoryViewModel.kt | 32 ++++----- 5 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 tvApp/src/main/java/band/effective/office/tv/screen/components/NewYearTimer.kt diff --git a/tvApp/src/main/java/band/effective/office/tv/di/view_models/MessageViewModelModule.kt b/tvApp/src/main/java/band/effective/office/tv/di/view_models/MessageViewModelModule.kt index 0b7f04c7..c65fd868 100644 --- a/tvApp/src/main/java/band/effective/office/tv/di/view_models/MessageViewModelModule.kt +++ b/tvApp/src/main/java/band/effective/office/tv/di/view_models/MessageViewModelModule.kt @@ -3,6 +3,7 @@ package band.effective.office.tv.di.view_models import android.content.Context import band.effective.office.tv.domain.botLogic.MessengerBot import band.effective.office.tv.domain.botLogic.impl.MattermostBot +import band.effective.office.tv.domain.newYear.NewYearUseCase import band.effective.office.tv.network.MattermostClient import band.effective.office.tv.repository.uselessFactRepository.UselessFactRepository import band.effective.office.tv.repository.uselessFactRepository.impl.UselessFactRepositoryImpl @@ -39,4 +40,8 @@ class MessageViewModelModule { @MattermostClient okHttpClient: OkHttpClient ): ImageLoader = ImageLoader.Builder(context).okHttpClient(okHttpClient).build() + + @ViewModelScoped + @Provides + fun provideNewYearUseCase(): NewYearUseCase = NewYearUseCase() } \ No newline at end of file diff --git a/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt b/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt index c6d7f93f..c24cdde8 100644 --- a/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt +++ b/tvApp/src/main/java/band/effective/office/tv/domain/newYear/NewYearUseCase.kt @@ -11,7 +11,7 @@ class NewYearUseCase { suspend fun getCounter(): Flow = flow { while (true) { emit(counter()) - delay(1000) // TODO + delay(1000) } } diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt b/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt index 9dd092f7..0228c768 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/components/EventStoryScreenContent.kt @@ -1,19 +1,14 @@ package band.effective.office.tv.screen.components -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.Surface -import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import band.effective.office.tv.screen.duolingo.DuolingoScreen import band.effective.office.tv.screen.eventStory.models.DuolingoUserInfo import band.effective.office.tv.screen.eventStory.models.EmployeeInfoUI @@ -81,15 +76,4 @@ fun EventStoryScreenContent( } } -} - -@Composable -private fun NewYearTimer(counter: NewYearCounter) { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Text( - text = "${counter.day}:${counter.hour}:${counter.min}:${counter.sec}", - color = Color.Black, - fontSize = 50.sp - ) - } -} +} \ No newline at end of file diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/components/NewYearTimer.kt b/tvApp/src/main/java/band/effective/office/tv/screen/components/NewYearTimer.kt new file mode 100644 index 00000000..61a0a78f --- /dev/null +++ b/tvApp/src/main/java/band/effective/office/tv/screen/components/NewYearTimer.kt @@ -0,0 +1,66 @@ +package band.effective.office.tv.screen.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.sp +import band.effective.office.tv.screen.eventStory.models.NewYearCounter +import band.effective.office.tv.utils.getCorrectDeclension + +@Composable +fun NewYearTimer(counter: NewYearCounter) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "У вас есть", + color = Color.Black, + fontSize = 40.sp + ) + Text( + text = "${counter.day} ${ + getCorrectDeclension( + counter.day, + "день", + "дня", + "дней" + ) + } ${counter.hour} ${ + getCorrectDeclension( + counter.hour, + "час", + "часа", + "часов" + ) + } ${counter.min} ${ + getCorrectDeclension( + counter.min, + "минута", + "минуты", + "минут" + ) + } ${counter.sec} ${ + getCorrectDeclension( + counter.sec, + "секунда", + "секунды", + "секунд" + ) + }", + color = Color.Black, + fontSize = 40.sp + ) + Text( + text = "чтобы приготовить оливьешку", + color = Color.Black, + fontSize = 40.sp + ) + } +} \ No newline at end of file diff --git a/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt b/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt index 89db375b..11eb59a5 100644 --- a/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt +++ b/tvApp/src/main/java/band/effective/office/tv/screen/eventStory/EventStoryViewModel.kt @@ -34,7 +34,8 @@ class EventStoryViewModel @Inject constructor( private val eventStoryData: EventStoryDataCombinerUseCase, private val timer: TimerSlideShow, @MattermostClient val imageLoader: ImageLoader, - private val autoplayController: AutoplayController + private val autoplayController: AutoplayController, + private val newYearUseCase: NewYearUseCase ) : ViewModel() { private val mutableState = MutableStateFlow(LatestEventInfoUiState.empty) val state = mutableState.asStateFlow() @@ -109,23 +110,24 @@ class EventStoryViewModel @Inject constructor( } } } - viewModelScope.launch { - val useCase = NewYearUseCase() - if (useCase.counter().day < 32) { - useCase.getCounter().collect { newCounter -> - val newEventList = mutableState.value.eventsInfo.toMutableList() - val oldCounterIndex = - mutableState.value.eventsInfo.indexOfFirst { it is NewYearCounter } - if (oldCounterIndex != -1) { - newEventList[oldCounterIndex] = newCounter - } else { - newEventList.add(newCounter) - } - mutableState.update { state.value.copy(eventsInfo = newEventList) } + newYearTimerInit() + startTimer() + } + + private fun newYearTimerInit() = viewModelScope.launch { + if (newYearUseCase.counter().day < 32) { + newYearUseCase.getCounter().collect { newCounter -> + val newEventList = mutableState.value.eventsInfo.toMutableList() + val oldCounterIndex = + mutableState.value.eventsInfo.indexOfFirst { it is NewYearCounter } + if (oldCounterIndex != -1) { + newEventList[oldCounterIndex] = newCounter + } else { + newEventList.add(newCounter) } + mutableState.update { state.value.copy(eventsInfo = newEventList) } } } - startTimer() } private fun updateStateAsException(error: String) { -- GitLab