rafsanjani / superdiary Goto Github PK
View Code? Open in Web Editor NEWKotlin/Compose Multiplatform Diary App with shared UI (Android, iOS, Desktop, Web)
License: MIT License
Kotlin/Compose Multiplatform Diary App with shared UI (Android, iOS, Desktop, Web)
License: MIT License
package com.foreverrafs.superdiary.data
import app.cash.turbine.test
import assertk.assertThat
import assertk.assertions.isNotEmpty
import com.aallam.openai.api.chat.ChatChoice
import com.aallam.openai.api.chat.ChatChunk
import com.aallam.openai.api.chat.ChatCompletion
import com.aallam.openai.api.chat.ChatCompletionChunk
import com.aallam.openai.api.chat.ChatDelta
import com.aallam.openai.api.chat.ChatMessage
import com.aallam.openai.api.chat.ChatRole
import com.aallam.openai.api.model.ModelId
import com.aallam.openai.client.OpenAI
import com.foreverrafs.superdiary.data.diaryai.OpenDiaryAI
import io.mockative.Mock
import io.mockative.any
import io.mockative.coEvery
import io.mockative.every
import io.mockative.mock
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Ignore
import kotlin.test.Test
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
// TODO: Fix OpenDiaryAiTest and get it to pass
@OptIn(ExperimentalCoroutinesApi::class)
@Ignore
class OpenDiaryAiTest {
@Mock
private val openAI: OpenAI = mock(OpenAI::class)
private val openDiaryAI = OpenDiaryAI(openAI)
private val chatCompletionChunk = ChatCompletionChunk(
id = "id",
created = 1230,
model = ModelId("asdf"),
usage = null,
choices = listOf(
ChatChunk(0, ChatDelta(content = "summary"), null),
),
)
private val chatCompletion = ChatCompletion(
id = "id",
created = 1200L,
model = ModelId(""),
usage = null,
choices = listOf(
ChatChoice(
index = 0,
message = ChatMessage(role = ChatRole.Assistant, content = "some message response"),
),
),
)
@BeforeTest
fun setup() {
Dispatchers.setMain(TestAppDispatchers.main)
// every { openAI.chatCompletions(any()) }.returns(flowOf(chatCompletionChunk))
}
@AfterTest
fun teardown() {
Dispatchers.resetMain()
}
@Test
fun `Should return weekly summary`() = runTest {
every { openAI.chatCompletions(any()) }.returns(flowOf(chatCompletionChunk))
openDiaryAI.getWeeklySummary(emptyList()).test {
val summary = awaitItem()
awaitComplete()
assertThat(summary).isNotEmpty()
}
}
@Test
fun `Should query diary entries`() = runTest {
coEvery { openAI.chatCompletion(any()) }.returns(chatCompletion)
val response = openDiaryAI.queryDiaries(emptyList())
assertThat(response).isNotEmpty()
}
@Test
fun `Should generate diary entry`() = runTest {
openDiaryAI.generateDiary("hello", 100).test {
val generated = awaitItem()
cancelAndIgnoreRemainingEvents()
assertThat(generated).isNotEmpty()
}
}
}
The Create Diary Screen
is doubling down as the same place for displaying the Diary Details
. This leads to lots of checks to make sure we are in the proper state. Separate these into two screens. CreateDiaryScreen
and DiaryDetailsScreen
.
Convert the diary entry date into a string from Instant and store the whole values into the database. This will ensure that we have proper sorting of entries
Investigate using a markdown editor to provide rich text editing. This will affect how data is stored as well because we will need to store the format markers as well
Allow users to delete diaries from the diary details screen
This is particularly useful because we are now saving the dashboard ordering state. Users should have a way to bring back the cards that have been dismissed from the dashboard
Implement swipe to favorite on the diary list screen
Currently only streaks are calculated. Find a mechanism to calculate the best streak.
Using datastore multiplatform library
Store the location where diary input is made and tag entries
This feature is dropped!
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
Gemfile
.github/workflows/build.yml
actions/checkout v4
actions/setup-java v4
gradle/actions v3
actions/checkout v4
actions/setup-java v4
gradle/actions v3
gradle/gradle-build-action v3
gradle/gradle-build-action v3
macos 14
macos 14
.github/workflows/danger_checks.yml
actions/checkout v4
actions/setup-java v4
gradle/actions v3
macos 14
.github/workflows/sonar.yml
actions/checkout v4
actions/setup-java v4
gradle/actions v3
actions/checkout v4
actions/setup-java v4
gradle/actions v3
gradle/gradle-build-action v3
gradle/gradle-build-action v3
macos 14
macos 14
.github/workflows/sync_main.yml
actions/checkout v4
macos 14
.github/workflows/unit_test_ios.yml
actions/checkout v4
actions/setup-java v4
gradle/actions v3
actions/checkout v4
actions/setup-java v4
gradle/gradle-build-action v3
macos 14
macos 14
.github/workflows/unit_test_jvm.yml
actions/checkout v4
actions/setup-java v4
gradle/actions v3
actions/checkout v4
actions/setup-java v4
gradle/gradle-build-action v3
gradle/gradle-build-action v3
actions/upload-artifact v4
macos 14
macos 14
gradle.properties
settings.gradle.kts
io.github.rafsanjani:versions 2024.05.19
build.gradle.kts
androidApp/app/build.gradle.kts
androidApp/benchmark/build.gradle.kts
build-logic/settings.gradle.kts
io.github.rafsanjani:versions 2024.05.13
build-logic/convention/build.gradle.kts
core/analytics/build.gradle.kts
core/logging/build.gradle.kts
core/utils/build.gradle.kts
desktopApp/build.gradle.kts
shared-data/build.gradle.kts
shared-ui/build.gradle.kts
swipe/build.gradle.kts
gradle/wrapper/gradle-wrapper.properties
gradle 8.7
This will ensure higher test fidelity
import org.koin.dsl.module
internal fun screenModules(): Module = module {
single<Logger> {
// TODO: Replace with Kermit Logger
Logger
}
singleOf(::DiaryListViewModel)
singleOf(::CreateDiaryViewModel)
singleOf(::FavoriteViewModel)
Automatically save chat history and allow users to clear them if they wish to do so.
Only use a single usecase for deleting both single and multiple diary items instead of two
Actually open the diary item when it is clicked instead of opening the whole diary list
Decide on which analytics library to use in the project and add libraries for it. Best candidates are
When the back button is pressed whilst the list is in selection mode, deselect all selected items instead of performing back navigation
This is a chat screen where users can interact with their entries.
}
fun deleteDiary(diary: Diary) = screenModelScope.launch {
when (val result = deleteDiaryUseCase(listOf(diary))) {
is Result.Failure -> {
// TODO: Handle unhappy path gracefully when deleting diary from details
}
is Result.Success -> {
val deletedItems = result.data
if (deletedItems != 0) {
mutableState.update {
DetailsScreenState.DiaryDeleted
}
}
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.