Normalize line endings to LF
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
@@ -1,36 +1,36 @@
|
||||
package com.flux.data.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.flux.data.model.JournalModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface JournalDao {
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM JournalModel WHERE journalId = :journalId)")
|
||||
suspend fun exists(journalId: String): Boolean
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun upsertEntry(entry: JournalModel)
|
||||
|
||||
@Delete
|
||||
suspend fun deleteEntry(entry: JournalModel)
|
||||
|
||||
@Query("Delete FROM JournalModel where workspaceId = :workspaceId")
|
||||
suspend fun deleteAllWorkspaceEntries(workspaceId: String)
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT * FROM JournalModel
|
||||
WHERE workspaceId = :workspaceId
|
||||
ORDER BY dateTime DESC
|
||||
"""
|
||||
)
|
||||
fun loadAllEntries(workspaceId: String): Flow<List<JournalModel>>
|
||||
|
||||
@Query("SELECT * FROM JournalModel")
|
||||
suspend fun loadAllEntries(): List<JournalModel>
|
||||
package com.flux.data.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.flux.data.model.JournalModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface JournalDao {
|
||||
@Query("SELECT EXISTS(SELECT 1 FROM JournalModel WHERE journalId = :journalId)")
|
||||
suspend fun exists(journalId: String): Boolean
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun upsertEntry(entry: JournalModel)
|
||||
|
||||
@Delete
|
||||
suspend fun deleteEntry(entry: JournalModel)
|
||||
|
||||
@Query("Delete FROM JournalModel where workspaceId = :workspaceId")
|
||||
suspend fun deleteAllWorkspaceEntries(workspaceId: String)
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT * FROM JournalModel
|
||||
WHERE workspaceId = :workspaceId
|
||||
ORDER BY dateTime DESC
|
||||
"""
|
||||
)
|
||||
fun loadAllEntries(workspaceId: String): Flow<List<JournalModel>>
|
||||
|
||||
@Query("SELECT * FROM JournalModel")
|
||||
suspend fun loadAllEntries(): List<JournalModel>
|
||||
}
|
||||
@@ -1,52 +1,52 @@
|
||||
package com.flux.data.model
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Notes
|
||||
import androidx.compose.material.icons.filled.Analytics
|
||||
import androidx.compose.material.icons.filled.AutoStories
|
||||
import androidx.compose.material.icons.filled.CalendarMonth
|
||||
import androidx.compose.material.icons.filled.Event
|
||||
import androidx.compose.material.icons.filled.EventAvailable
|
||||
import androidx.compose.material.icons.filled.TaskAlt
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.util.UUID
|
||||
import com.flux.R
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Entity
|
||||
data class WorkspaceModel(
|
||||
@PrimaryKey
|
||||
val workspaceId: String = UUID.randomUUID().toString(),
|
||||
val title: String = "",
|
||||
val description: String = "",
|
||||
val colorInd: Int = 0,
|
||||
val cover: String = "",
|
||||
val icon: Int = 48,
|
||||
val passKey: String = "",
|
||||
val isPinned: Boolean = false,
|
||||
val selectedSpaces: List<Int> = emptyList()
|
||||
)
|
||||
|
||||
data class Space(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val icon: ImageVector
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun getSpacesList(): List<Space> {
|
||||
return listOf(
|
||||
Space(1, stringResource(R.string.Notes), Icons.AutoMirrored.Default.Notes),
|
||||
Space(2, stringResource(R.string.To_Do), Icons.Default.TaskAlt),
|
||||
Space(3, stringResource(R.string.Events), Icons.Default.Event),
|
||||
Space(4, stringResource(R.string.Calendar), Icons.Default.CalendarMonth),
|
||||
Space(5, stringResource(R.string.Journal), Icons.Default.AutoStories),
|
||||
Space(6, stringResource(R.string.Habits), Icons.Default.EventAvailable),
|
||||
Space(7, stringResource(R.string.Analytics), Icons.Default.Analytics)
|
||||
)
|
||||
package com.flux.data.model
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Notes
|
||||
import androidx.compose.material.icons.filled.Analytics
|
||||
import androidx.compose.material.icons.filled.AutoStories
|
||||
import androidx.compose.material.icons.filled.CalendarMonth
|
||||
import androidx.compose.material.icons.filled.Event
|
||||
import androidx.compose.material.icons.filled.EventAvailable
|
||||
import androidx.compose.material.icons.filled.TaskAlt
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.util.UUID
|
||||
import com.flux.R
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Entity
|
||||
data class WorkspaceModel(
|
||||
@PrimaryKey
|
||||
val workspaceId: String = UUID.randomUUID().toString(),
|
||||
val title: String = "",
|
||||
val description: String = "",
|
||||
val colorInd: Int = 0,
|
||||
val cover: String = "",
|
||||
val icon: Int = 48,
|
||||
val passKey: String = "",
|
||||
val isPinned: Boolean = false,
|
||||
val selectedSpaces: List<Int> = emptyList()
|
||||
)
|
||||
|
||||
data class Space(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val icon: ImageVector
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun getSpacesList(): List<Space> {
|
||||
return listOf(
|
||||
Space(1, stringResource(R.string.Notes), Icons.AutoMirrored.Default.Notes),
|
||||
Space(2, stringResource(R.string.To_Do), Icons.Default.TaskAlt),
|
||||
Space(3, stringResource(R.string.Events), Icons.Default.Event),
|
||||
Space(4, stringResource(R.string.Calendar), Icons.Default.CalendarMonth),
|
||||
Space(5, stringResource(R.string.Journal), Icons.Default.AutoStories),
|
||||
Space(6, stringResource(R.string.Habits), Icons.Default.EventAvailable),
|
||||
Space(7, stringResource(R.string.Analytics), Icons.Default.Analytics)
|
||||
)
|
||||
}
|
||||
@@ -1,246 +1,246 @@
|
||||
package com.flux.navigation
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.navigation.NavController
|
||||
import com.flux.data.model.EventModel
|
||||
import com.flux.data.model.HabitModel
|
||||
import com.flux.data.model.JournalModel
|
||||
import com.flux.data.model.NotesModel
|
||||
import com.flux.data.model.TodoModel
|
||||
import com.flux.ui.screens.auth.AuthScreen
|
||||
import com.flux.ui.screens.events.EventDetails
|
||||
import com.flux.ui.screens.events.NewEvent
|
||||
import com.flux.ui.screens.habits.HabitDetails
|
||||
import com.flux.ui.screens.habits.NewHabit
|
||||
import com.flux.ui.screens.journal.EditJournal
|
||||
import com.flux.ui.screens.notes.EditLabels
|
||||
import com.flux.ui.screens.notes.NoteDetails
|
||||
import com.flux.ui.screens.settings.About
|
||||
import com.flux.ui.screens.settings.Backup
|
||||
import com.flux.ui.screens.settings.Contact
|
||||
import com.flux.ui.screens.settings.Customize
|
||||
import com.flux.ui.screens.settings.Languages
|
||||
import com.flux.ui.screens.settings.Privacy
|
||||
import com.flux.ui.screens.settings.Settings
|
||||
import com.flux.ui.screens.todo.TodoDetail
|
||||
import com.flux.ui.screens.workspaces.WorkSpaces
|
||||
import com.flux.ui.screens.workspaces.WorkspaceDetails
|
||||
import com.flux.ui.state.States
|
||||
import com.flux.ui.viewModel.ViewModels
|
||||
|
||||
sealed class NavRoutes(val route: String) {
|
||||
data object AuthScreen : NavRoutes("biometric") // auth screen
|
||||
data object Workspace : NavRoutes("workspace") // workspaces
|
||||
data object WorkspaceHome : NavRoutes("workspace/details")
|
||||
data object EditLabels : NavRoutes("workspace/labels/edit") //Labels
|
||||
data object NoteDetails : NavRoutes("workspace/note/details") // Notes
|
||||
data object HabitDetails : NavRoutes("workspace/habit/details") // Habit detail
|
||||
data object NewHabit : NavRoutes("workspace/habit/new") // new habit
|
||||
data object EventDetails : NavRoutes("workspace/event/details") // event detail
|
||||
data object TodoDetail : NavRoutes("workspace/todo/details") // TodoList
|
||||
data object EditJournal : NavRoutes("workspace/journal/edit") // Journal
|
||||
data object NewEvent : NavRoutes("workspace/event/edit") // new event
|
||||
|
||||
// Settings
|
||||
data object Settings : NavRoutes("settings")
|
||||
data object Privacy : NavRoutes("settings/privacy")
|
||||
data object Customize : NavRoutes("settings/customize")
|
||||
data object Languages : NavRoutes("settings/language")
|
||||
data object About : NavRoutes("settings/about")
|
||||
data object Contact : NavRoutes("settings/contact")
|
||||
data object Backup : NavRoutes("setting/backup")
|
||||
|
||||
fun withArgs(vararg args: Any): String {
|
||||
return buildString {
|
||||
append(route)
|
||||
args.forEach { arg ->
|
||||
append("/${arg}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val AuthScreen =
|
||||
mapOf<String, @Composable (navController: NavController, states: States) -> Unit>(
|
||||
NavRoutes.AuthScreen.route to { navController, states ->
|
||||
AuthScreen(navController, states.settings.data.isBiometricEnabled)
|
||||
}
|
||||
)
|
||||
|
||||
val NotesScreens =
|
||||
mapOf<String, @Composable (navController: NavController, notesId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.NoteDetails.route + "/{workspaceId}" + "/{notesId}" to { navController, notesId, workspaceId, states, viewModel ->
|
||||
NoteDetails(
|
||||
navController,
|
||||
workspaceId,
|
||||
states.notesState.allNotes.find { it.notesId == notesId }
|
||||
?: NotesModel(workspaceId = workspaceId),
|
||||
states.notesState.allLabels.filter { it.workspaceId == workspaceId },
|
||||
viewModel.notesViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val HabitScreens =
|
||||
mapOf<String, @Composable (navController: NavController, habitId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.HabitDetails.route + "/{workspaceId}" + "/{habitId}" to { navController, habitId, workspaceId, states, viewModel ->
|
||||
HabitDetails(
|
||||
navController,
|
||||
states.settings.data.cornerRadius,
|
||||
workspaceId,
|
||||
states.habitState.allHabits.first { it.id == habitId },
|
||||
states.habitState.allInstances.filter { it.habitId == habitId },
|
||||
viewModel.habitViewModel::onEvent
|
||||
)
|
||||
},
|
||||
NavRoutes.NewHabit.route + "/{workspaceId}" + "/{habitId}" to { navController, habitId, workspaceId, states, viewModel ->
|
||||
NewHabit(
|
||||
navController,
|
||||
states.habitState.allHabits.find { it.id == habitId } ?: HabitModel(workspaceId=workspaceId),
|
||||
states.settings,
|
||||
viewModel.habitViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val TodoScreens =
|
||||
mapOf<String, @Composable (navController: NavController, listId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.TodoDetail.route + "/{workspaceId}" + "/{listId}" to { navController, listId, workspaceId, states, viewModel ->
|
||||
TodoDetail(
|
||||
navController,
|
||||
states.todoState.allLists.find { it.id == listId }
|
||||
?: TodoModel(workspaceId = workspaceId),
|
||||
workspaceId,
|
||||
viewModel.todoViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val JournalScreens =
|
||||
mapOf<String, @Composable (navController: NavController, journalId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.EditJournal.route + "/{workspaceId}" + "/{journalId}" to { navController, journalId, workspaceId, states, viewModel ->
|
||||
EditJournal(
|
||||
navController,
|
||||
states.journalState.allEntries.find { it.journalId == journalId } ?:
|
||||
JournalModel(workspaceId = workspaceId),
|
||||
viewModel.journalViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
val SettingsScreens =
|
||||
mapOf<String, @Composable (navController: NavController, snackbarHostState: SnackbarHostState, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.Settings.route to { navController, _, states, viewModels ->
|
||||
Settings(navController, states.settings)
|
||||
},
|
||||
NavRoutes.Privacy.route to { navController, _, states, viewModels ->
|
||||
Privacy(navController, states.settings, viewModels.settingsViewModel::onEvent)
|
||||
},
|
||||
NavRoutes.About.route to { navController, _, states, _ ->
|
||||
About(navController, states.settings.data.cornerRadius)
|
||||
},
|
||||
NavRoutes.Languages.route to { navController, _, states, _ ->
|
||||
Languages(navController, states.settings)
|
||||
},
|
||||
NavRoutes.Customize.route to { navController, _, states, viewModels ->
|
||||
Customize(navController, states.settings, viewModels.settingsViewModel::onEvent)
|
||||
},
|
||||
NavRoutes.Contact.route to { navController, _, states, _ ->
|
||||
Contact(navController, states.settings.data.cornerRadius)
|
||||
},
|
||||
NavRoutes.Backup.route to { navController, _, states, viewModels ->
|
||||
Backup(navController, states.settings.data.cornerRadius, viewModels.backupViewModel)
|
||||
}
|
||||
)
|
||||
|
||||
val EventScreens =
|
||||
mapOf<String, @Composable (navController: NavController, states: States, viewModels: ViewModels, eventId: String, workspaceId: String, instanceDate: Long, eventDate: Long) -> Unit>(
|
||||
NavRoutes.EventDetails.route + "/{workspaceId}" + "/{eventId}" + "/{instanceDate}" to { navController, states, viewModels, eventId, workspaceId, instanceDate, _ ->
|
||||
EventDetails(
|
||||
navController,
|
||||
workspaceId,
|
||||
states.eventState.allEvent.find { it.id == eventId } ?: EventModel(workspaceId = workspaceId),
|
||||
states.eventState.allEventInstances.find { it.eventId == eventId && it.instanceDate == instanceDate } == null,
|
||||
instanceDate,
|
||||
states.settings,
|
||||
viewModels.eventViewModel::onEvent
|
||||
)
|
||||
},
|
||||
NavRoutes.NewEvent.route + "/{workspaceId}" + "/{eventId}" + "/{eventDate}" to { navController, states, viewModels, eventId, workspaceId, _, eventDate ->
|
||||
NewEvent(
|
||||
navController,
|
||||
states.eventState.allEvent.find { it.id == eventId } ?: EventModel(workspaceId = workspaceId, startDateTime = eventDate),
|
||||
states.settings,
|
||||
viewModels.eventViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
val WorkspaceScreens =
|
||||
mapOf<String, @Composable (navController: NavController, snackbarHostState: SnackbarHostState, states: States, viewModels: ViewModels, workspaceId: String) -> Unit>(
|
||||
NavRoutes.Workspace.route to { navController, snackbarHostState, states, viewModels, _ ->
|
||||
WorkSpaces(
|
||||
snackbarHostState,
|
||||
navController,
|
||||
states.settings.data.workspaceGridColumns,
|
||||
states.settings.data.cornerRadius,
|
||||
states.workspaceState.allSpaces,
|
||||
viewModels.notesViewModel::onEvent,
|
||||
viewModels.eventViewModel::onEvent,
|
||||
viewModels.habitViewModel::onEvent,
|
||||
viewModels.todoViewModel::onEvent,
|
||||
viewModels.workspaceViewModel::onEvent,
|
||||
viewModels.journalViewModel::onEvent
|
||||
)
|
||||
},
|
||||
NavRoutes.WorkspaceHome.route + "/{workspaceId}" to { navController, snackbarHostState, states, viewModels, workspaceId ->
|
||||
WorkspaceDetails(
|
||||
navController,
|
||||
states.notesState.allLabels.filter { it.workspaceId == workspaceId },
|
||||
states.settings,
|
||||
states.notesState.isNotesLoading,
|
||||
states.eventState.isAllEventsLoading,
|
||||
states.eventState.isDatedEventLoading,
|
||||
states.todoState.isLoading,
|
||||
states.journalState.isLoading,
|
||||
states.habitState.isLoading,
|
||||
states.workspaceState.allSpaces.first { it.workspaceId == workspaceId },
|
||||
states.eventState.allEvent,
|
||||
states.notesState.allNotes.filter { it.workspaceId == workspaceId },
|
||||
states.notesState.selectedNotes,
|
||||
states.eventState.selectedYearMonth,
|
||||
states.eventState.selectedDate,
|
||||
states.eventState.datedEvents,
|
||||
states.habitState.allHabits,
|
||||
states.todoState.allLists,
|
||||
states.journalState.allEntries,
|
||||
states.habitState.allInstances,
|
||||
states.eventState.allEventInstances,
|
||||
viewModels.workspaceViewModel::onEvent,
|
||||
viewModels.notesViewModel::onEvent,
|
||||
viewModels.eventViewModel::onEvent,
|
||||
viewModels.habitViewModel::onEvent,
|
||||
viewModels.todoViewModel::onEvent,
|
||||
viewModels.journalViewModel::onEvent,
|
||||
viewModels.settingsViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val LabelScreens =
|
||||
mapOf<String, @Composable (navController: NavController, states: States, viewModels: ViewModels, workspaceId: String) -> Unit>(
|
||||
NavRoutes.EditLabels.route + "/{workspaceId}" to { navController, states, viewModels, workspaceId ->
|
||||
EditLabels(
|
||||
navController,
|
||||
states.notesState.isLabelsLoading,
|
||||
workspaceId,
|
||||
states.notesState.allLabels,
|
||||
viewModels.notesViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
package com.flux.navigation
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.navigation.NavController
|
||||
import com.flux.data.model.EventModel
|
||||
import com.flux.data.model.HabitModel
|
||||
import com.flux.data.model.JournalModel
|
||||
import com.flux.data.model.NotesModel
|
||||
import com.flux.data.model.TodoModel
|
||||
import com.flux.ui.screens.auth.AuthScreen
|
||||
import com.flux.ui.screens.events.EventDetails
|
||||
import com.flux.ui.screens.events.NewEvent
|
||||
import com.flux.ui.screens.habits.HabitDetails
|
||||
import com.flux.ui.screens.habits.NewHabit
|
||||
import com.flux.ui.screens.journal.EditJournal
|
||||
import com.flux.ui.screens.notes.EditLabels
|
||||
import com.flux.ui.screens.notes.NoteDetails
|
||||
import com.flux.ui.screens.settings.About
|
||||
import com.flux.ui.screens.settings.Backup
|
||||
import com.flux.ui.screens.settings.Contact
|
||||
import com.flux.ui.screens.settings.Customize
|
||||
import com.flux.ui.screens.settings.Languages
|
||||
import com.flux.ui.screens.settings.Privacy
|
||||
import com.flux.ui.screens.settings.Settings
|
||||
import com.flux.ui.screens.todo.TodoDetail
|
||||
import com.flux.ui.screens.workspaces.WorkSpaces
|
||||
import com.flux.ui.screens.workspaces.WorkspaceDetails
|
||||
import com.flux.ui.state.States
|
||||
import com.flux.ui.viewModel.ViewModels
|
||||
|
||||
sealed class NavRoutes(val route: String) {
|
||||
data object AuthScreen : NavRoutes("biometric") // auth screen
|
||||
data object Workspace : NavRoutes("workspace") // workspaces
|
||||
data object WorkspaceHome : NavRoutes("workspace/details")
|
||||
data object EditLabels : NavRoutes("workspace/labels/edit") //Labels
|
||||
data object NoteDetails : NavRoutes("workspace/note/details") // Notes
|
||||
data object HabitDetails : NavRoutes("workspace/habit/details") // Habit detail
|
||||
data object NewHabit : NavRoutes("workspace/habit/new") // new habit
|
||||
data object EventDetails : NavRoutes("workspace/event/details") // event detail
|
||||
data object TodoDetail : NavRoutes("workspace/todo/details") // TodoList
|
||||
data object EditJournal : NavRoutes("workspace/journal/edit") // Journal
|
||||
data object NewEvent : NavRoutes("workspace/event/edit") // new event
|
||||
|
||||
// Settings
|
||||
data object Settings : NavRoutes("settings")
|
||||
data object Privacy : NavRoutes("settings/privacy")
|
||||
data object Customize : NavRoutes("settings/customize")
|
||||
data object Languages : NavRoutes("settings/language")
|
||||
data object About : NavRoutes("settings/about")
|
||||
data object Contact : NavRoutes("settings/contact")
|
||||
data object Backup : NavRoutes("setting/backup")
|
||||
|
||||
fun withArgs(vararg args: Any): String {
|
||||
return buildString {
|
||||
append(route)
|
||||
args.forEach { arg ->
|
||||
append("/${arg}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val AuthScreen =
|
||||
mapOf<String, @Composable (navController: NavController, states: States) -> Unit>(
|
||||
NavRoutes.AuthScreen.route to { navController, states ->
|
||||
AuthScreen(navController, states.settings.data.isBiometricEnabled)
|
||||
}
|
||||
)
|
||||
|
||||
val NotesScreens =
|
||||
mapOf<String, @Composable (navController: NavController, notesId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.NoteDetails.route + "/{workspaceId}" + "/{notesId}" to { navController, notesId, workspaceId, states, viewModel ->
|
||||
NoteDetails(
|
||||
navController,
|
||||
workspaceId,
|
||||
states.notesState.allNotes.find { it.notesId == notesId }
|
||||
?: NotesModel(workspaceId = workspaceId),
|
||||
states.notesState.allLabels.filter { it.workspaceId == workspaceId },
|
||||
viewModel.notesViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val HabitScreens =
|
||||
mapOf<String, @Composable (navController: NavController, habitId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.HabitDetails.route + "/{workspaceId}" + "/{habitId}" to { navController, habitId, workspaceId, states, viewModel ->
|
||||
HabitDetails(
|
||||
navController,
|
||||
states.settings.data.cornerRadius,
|
||||
workspaceId,
|
||||
states.habitState.allHabits.first { it.id == habitId },
|
||||
states.habitState.allInstances.filter { it.habitId == habitId },
|
||||
viewModel.habitViewModel::onEvent
|
||||
)
|
||||
},
|
||||
NavRoutes.NewHabit.route + "/{workspaceId}" + "/{habitId}" to { navController, habitId, workspaceId, states, viewModel ->
|
||||
NewHabit(
|
||||
navController,
|
||||
states.habitState.allHabits.find { it.id == habitId } ?: HabitModel(workspaceId=workspaceId),
|
||||
states.settings,
|
||||
viewModel.habitViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val TodoScreens =
|
||||
mapOf<String, @Composable (navController: NavController, listId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.TodoDetail.route + "/{workspaceId}" + "/{listId}" to { navController, listId, workspaceId, states, viewModel ->
|
||||
TodoDetail(
|
||||
navController,
|
||||
states.todoState.allLists.find { it.id == listId }
|
||||
?: TodoModel(workspaceId = workspaceId),
|
||||
workspaceId,
|
||||
viewModel.todoViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val JournalScreens =
|
||||
mapOf<String, @Composable (navController: NavController, journalId: String, workspaceId: String, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.EditJournal.route + "/{workspaceId}" + "/{journalId}" to { navController, journalId, workspaceId, states, viewModel ->
|
||||
EditJournal(
|
||||
navController,
|
||||
states.journalState.allEntries.find { it.journalId == journalId } ?:
|
||||
JournalModel(workspaceId = workspaceId),
|
||||
viewModel.journalViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
val SettingsScreens =
|
||||
mapOf<String, @Composable (navController: NavController, snackbarHostState: SnackbarHostState, states: States, viewModels: ViewModels) -> Unit>(
|
||||
NavRoutes.Settings.route to { navController, _, states, viewModels ->
|
||||
Settings(navController, states.settings)
|
||||
},
|
||||
NavRoutes.Privacy.route to { navController, _, states, viewModels ->
|
||||
Privacy(navController, states.settings, viewModels.settingsViewModel::onEvent)
|
||||
},
|
||||
NavRoutes.About.route to { navController, _, states, _ ->
|
||||
About(navController, states.settings.data.cornerRadius)
|
||||
},
|
||||
NavRoutes.Languages.route to { navController, _, states, _ ->
|
||||
Languages(navController, states.settings)
|
||||
},
|
||||
NavRoutes.Customize.route to { navController, _, states, viewModels ->
|
||||
Customize(navController, states.settings, viewModels.settingsViewModel::onEvent)
|
||||
},
|
||||
NavRoutes.Contact.route to { navController, _, states, _ ->
|
||||
Contact(navController, states.settings.data.cornerRadius)
|
||||
},
|
||||
NavRoutes.Backup.route to { navController, _, states, viewModels ->
|
||||
Backup(navController, states.settings.data.cornerRadius, viewModels.backupViewModel)
|
||||
}
|
||||
)
|
||||
|
||||
val EventScreens =
|
||||
mapOf<String, @Composable (navController: NavController, states: States, viewModels: ViewModels, eventId: String, workspaceId: String, instanceDate: Long, eventDate: Long) -> Unit>(
|
||||
NavRoutes.EventDetails.route + "/{workspaceId}" + "/{eventId}" + "/{instanceDate}" to { navController, states, viewModels, eventId, workspaceId, instanceDate, _ ->
|
||||
EventDetails(
|
||||
navController,
|
||||
workspaceId,
|
||||
states.eventState.allEvent.find { it.id == eventId } ?: EventModel(workspaceId = workspaceId),
|
||||
states.eventState.allEventInstances.find { it.eventId == eventId && it.instanceDate == instanceDate } == null,
|
||||
instanceDate,
|
||||
states.settings,
|
||||
viewModels.eventViewModel::onEvent
|
||||
)
|
||||
},
|
||||
NavRoutes.NewEvent.route + "/{workspaceId}" + "/{eventId}" + "/{eventDate}" to { navController, states, viewModels, eventId, workspaceId, _, eventDate ->
|
||||
NewEvent(
|
||||
navController,
|
||||
states.eventState.allEvent.find { it.id == eventId } ?: EventModel(workspaceId = workspaceId, startDateTime = eventDate),
|
||||
states.settings,
|
||||
viewModels.eventViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
val WorkspaceScreens =
|
||||
mapOf<String, @Composable (navController: NavController, snackbarHostState: SnackbarHostState, states: States, viewModels: ViewModels, workspaceId: String) -> Unit>(
|
||||
NavRoutes.Workspace.route to { navController, snackbarHostState, states, viewModels, _ ->
|
||||
WorkSpaces(
|
||||
snackbarHostState,
|
||||
navController,
|
||||
states.settings.data.workspaceGridColumns,
|
||||
states.settings.data.cornerRadius,
|
||||
states.workspaceState.allSpaces,
|
||||
viewModels.notesViewModel::onEvent,
|
||||
viewModels.eventViewModel::onEvent,
|
||||
viewModels.habitViewModel::onEvent,
|
||||
viewModels.todoViewModel::onEvent,
|
||||
viewModels.workspaceViewModel::onEvent,
|
||||
viewModels.journalViewModel::onEvent
|
||||
)
|
||||
},
|
||||
NavRoutes.WorkspaceHome.route + "/{workspaceId}" to { navController, snackbarHostState, states, viewModels, workspaceId ->
|
||||
WorkspaceDetails(
|
||||
navController,
|
||||
states.notesState.allLabels.filter { it.workspaceId == workspaceId },
|
||||
states.settings,
|
||||
states.notesState.isNotesLoading,
|
||||
states.eventState.isAllEventsLoading,
|
||||
states.eventState.isDatedEventLoading,
|
||||
states.todoState.isLoading,
|
||||
states.journalState.isLoading,
|
||||
states.habitState.isLoading,
|
||||
states.workspaceState.allSpaces.first { it.workspaceId == workspaceId },
|
||||
states.eventState.allEvent,
|
||||
states.notesState.allNotes.filter { it.workspaceId == workspaceId },
|
||||
states.notesState.selectedNotes,
|
||||
states.eventState.selectedYearMonth,
|
||||
states.eventState.selectedDate,
|
||||
states.eventState.datedEvents,
|
||||
states.habitState.allHabits,
|
||||
states.todoState.allLists,
|
||||
states.journalState.allEntries,
|
||||
states.habitState.allInstances,
|
||||
states.eventState.allEventInstances,
|
||||
viewModels.workspaceViewModel::onEvent,
|
||||
viewModels.notesViewModel::onEvent,
|
||||
viewModels.eventViewModel::onEvent,
|
||||
viewModels.habitViewModel::onEvent,
|
||||
viewModels.todoViewModel::onEvent,
|
||||
viewModels.journalViewModel::onEvent,
|
||||
viewModels.settingsViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val LabelScreens =
|
||||
mapOf<String, @Composable (navController: NavController, states: States, viewModels: ViewModels, workspaceId: String) -> Unit>(
|
||||
NavRoutes.EditLabels.route + "/{workspaceId}" to { navController, states, viewModels, workspaceId ->
|
||||
EditLabels(
|
||||
navController,
|
||||
states.notesState.isLabelsLoading,
|
||||
workspaceId,
|
||||
states.notesState.allLabels,
|
||||
viewModels.notesViewModel::onEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,191 +1,191 @@
|
||||
package com.flux.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
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.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.rounded.Search
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SearchBar
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.isTraversalGroup
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.traversalIndex
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.flux.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WorkspaceSearchBar(
|
||||
textFieldState: TextFieldState,
|
||||
onSearch: (String) -> Unit,
|
||||
onSettingsClicked: () -> Unit,
|
||||
onCloseClicked: () -> Unit,
|
||||
) {
|
||||
val query = textFieldState.text.toString()
|
||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.semantics { isTraversalGroup = true }) {
|
||||
SearchBar(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopCenter)
|
||||
.wrapContentHeight()
|
||||
.semantics { traversalIndex = 0f },
|
||||
inputField = {
|
||||
WorkspaceSearchInputField(
|
||||
query,
|
||||
onQueryChange = {
|
||||
textFieldState.edit { replace(0, length, it) }
|
||||
onSearch(it)
|
||||
if (it.isBlank()) {
|
||||
expanded = false
|
||||
}
|
||||
},
|
||||
onSearch = {
|
||||
keyboardController?.hide()
|
||||
onSearch(query)
|
||||
},
|
||||
onSearchClosed = {
|
||||
textFieldState.edit { replace(0, length, "") }
|
||||
onCloseClicked()
|
||||
onSearch("")
|
||||
expanded = false
|
||||
},
|
||||
onSettingsClicked = onSettingsClicked
|
||||
)
|
||||
},
|
||||
colors = SearchBarDefaults.colors(
|
||||
containerColor = if (expanded) MaterialTheme.colorScheme.surfaceContainerLow else MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||
6.dp
|
||||
)
|
||||
),
|
||||
expanded = expanded,
|
||||
onExpandedChange = { },
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WorkspaceSearchInputField(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
onSearch: (String) -> Unit,
|
||||
onSearchClosed: () -> Unit,
|
||||
onSettingsClicked: () -> Unit
|
||||
) {
|
||||
SearchBarDefaults.InputField(
|
||||
query = query,
|
||||
onQueryChange = onQueryChange,
|
||||
onSearch = onSearch,
|
||||
expanded = false,
|
||||
onExpandedChange = { },
|
||||
placeholder = { Text(stringResource(R.string.Search_Workspaces)) },
|
||||
leadingIcon = { Icon(Icons.Rounded.Search, "Search") },
|
||||
trailingIcon = {
|
||||
Row {
|
||||
if (query.isNotBlank()) CloseButton(onSearchClosed)
|
||||
SettingsButton(onSettingsClicked)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NotesSearchBar(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
onCloseClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: String = "Search..."
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.height(40.dp)
|
||||
.clip(RoundedCornerShape(50))
|
||||
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(6.dp))
|
||||
.padding(horizontal = 12.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = "Search",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
|
||||
Spacer(Modifier.width(6.dp))
|
||||
|
||||
BasicTextField(
|
||||
value = query,
|
||||
onValueChange = onQueryChange,
|
||||
singleLine = true,
|
||||
textStyle = MaterialTheme.typography.bodySmall.copy(
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(vertical = 2.dp), // keeps text centered vertically
|
||||
decorationBox = { innerTextField ->
|
||||
if (query.isEmpty()) {
|
||||
Text(
|
||||
text = placeholder,
|
||||
style = MaterialTheme.typography.bodySmall.copy(
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
}
|
||||
)
|
||||
|
||||
IconButton(
|
||||
onClick = {
|
||||
onCloseClicked()
|
||||
onQueryChange("")
|
||||
},
|
||||
modifier = Modifier.size(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = "Clear",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.flux.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
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.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.input.TextFieldState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.rounded.Search
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SearchBar
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.isTraversalGroup
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.traversalIndex
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.flux.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WorkspaceSearchBar(
|
||||
textFieldState: TextFieldState,
|
||||
onSearch: (String) -> Unit,
|
||||
onSettingsClicked: () -> Unit,
|
||||
onCloseClicked: () -> Unit,
|
||||
) {
|
||||
val query = textFieldState.text.toString()
|
||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.semantics { isTraversalGroup = true }) {
|
||||
SearchBar(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopCenter)
|
||||
.wrapContentHeight()
|
||||
.semantics { traversalIndex = 0f },
|
||||
inputField = {
|
||||
WorkspaceSearchInputField(
|
||||
query,
|
||||
onQueryChange = {
|
||||
textFieldState.edit { replace(0, length, it) }
|
||||
onSearch(it)
|
||||
if (it.isBlank()) {
|
||||
expanded = false
|
||||
}
|
||||
},
|
||||
onSearch = {
|
||||
keyboardController?.hide()
|
||||
onSearch(query)
|
||||
},
|
||||
onSearchClosed = {
|
||||
textFieldState.edit { replace(0, length, "") }
|
||||
onCloseClicked()
|
||||
onSearch("")
|
||||
expanded = false
|
||||
},
|
||||
onSettingsClicked = onSettingsClicked
|
||||
)
|
||||
},
|
||||
colors = SearchBarDefaults.colors(
|
||||
containerColor = if (expanded) MaterialTheme.colorScheme.surfaceContainerLow else MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||
6.dp
|
||||
)
|
||||
),
|
||||
expanded = expanded,
|
||||
onExpandedChange = { },
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WorkspaceSearchInputField(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
onSearch: (String) -> Unit,
|
||||
onSearchClosed: () -> Unit,
|
||||
onSettingsClicked: () -> Unit
|
||||
) {
|
||||
SearchBarDefaults.InputField(
|
||||
query = query,
|
||||
onQueryChange = onQueryChange,
|
||||
onSearch = onSearch,
|
||||
expanded = false,
|
||||
onExpandedChange = { },
|
||||
placeholder = { Text(stringResource(R.string.Search_Workspaces)) },
|
||||
leadingIcon = { Icon(Icons.Rounded.Search, "Search") },
|
||||
trailingIcon = {
|
||||
Row {
|
||||
if (query.isNotBlank()) CloseButton(onSearchClosed)
|
||||
SettingsButton(onSettingsClicked)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NotesSearchBar(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
onCloseClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: String = "Search..."
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.height(40.dp)
|
||||
.clip(RoundedCornerShape(50))
|
||||
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(6.dp))
|
||||
.padding(horizontal = 12.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = "Search",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
|
||||
Spacer(Modifier.width(6.dp))
|
||||
|
||||
BasicTextField(
|
||||
value = query,
|
||||
onValueChange = onQueryChange,
|
||||
singleLine = true,
|
||||
textStyle = MaterialTheme.typography.bodySmall.copy(
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(vertical = 2.dp), // keeps text centered vertically
|
||||
decorationBox = { innerTextField ->
|
||||
if (query.isEmpty()) {
|
||||
Text(
|
||||
text = placeholder,
|
||||
style = MaterialTheme.typography.bodySmall.copy(
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
}
|
||||
)
|
||||
|
||||
IconButton(
|
||||
onClick = {
|
||||
onCloseClicked()
|
||||
onQueryChange("")
|
||||
},
|
||||
modifier = Modifier.size(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = "Clear",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +1,111 @@
|
||||
package com.flux.ui.screens.calendar
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import com.flux.data.model.EventInstanceModel
|
||||
import com.flux.data.model.EventModel
|
||||
import com.flux.navigation.Loader
|
||||
import com.flux.navigation.NavRoutes
|
||||
import com.flux.ui.components.DailyViewCalendar
|
||||
import com.flux.ui.components.MonthlyViewCalendar
|
||||
import com.flux.ui.events.TaskEvents
|
||||
import com.flux.ui.screens.events.EmptyEvents
|
||||
import com.flux.ui.screens.events.EventCard
|
||||
import com.flux.ui.state.Settings
|
||||
import java.time.YearMonth
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun LazyListScope.calendarItems(
|
||||
navController: NavController,
|
||||
radius: Int,
|
||||
is24HourFormat: Boolean,
|
||||
isLoading: Boolean,
|
||||
workspaceId: String,
|
||||
selectedMonth: YearMonth,
|
||||
selectedDate: Long,
|
||||
settings: Settings,
|
||||
datedEvents: List<EventModel>,
|
||||
allEventInstances: List<EventInstanceModel>,
|
||||
onTaskEvents: (TaskEvents) -> Unit
|
||||
) {
|
||||
val isMonthlyView = settings.data.isCalendarMonthlyView
|
||||
|
||||
if (isMonthlyView) {
|
||||
item {
|
||||
MonthlyViewCalendar(
|
||||
selectedMonth, selectedDate,
|
||||
onMonthChange = {
|
||||
onTaskEvents(TaskEvents.ChangeMonth(it))
|
||||
},
|
||||
onDateChange = {
|
||||
onTaskEvents(TaskEvents.LoadDateTask(workspaceId, it))
|
||||
onTaskEvents(TaskEvents.ChangeDate(it))
|
||||
})
|
||||
}
|
||||
} else {
|
||||
item {
|
||||
DailyViewCalendar(
|
||||
selectedMonth,
|
||||
selectedDate,
|
||||
onDateChange = {
|
||||
onTaskEvents(TaskEvents.LoadDateTask(workspaceId, it))
|
||||
onTaskEvents(TaskEvents.ChangeDate(it))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
item { Loader() }
|
||||
} else if (datedEvents.isEmpty()) {
|
||||
item { EmptyEvents() }
|
||||
} else {
|
||||
item { Spacer(Modifier.height(24.dp)) }
|
||||
|
||||
val pendingTasks = datedEvents.filter { task ->
|
||||
val instance = allEventInstances.find { it.eventId == task.id && it.instanceDate == selectedDate }
|
||||
instance == null
|
||||
}
|
||||
|
||||
val completedTasks = datedEvents.filter { task ->
|
||||
val instance = allEventInstances.find { it.eventId == task.id && it.instanceDate == selectedDate }
|
||||
instance != null
|
||||
}
|
||||
|
||||
if (pendingTasks.isNotEmpty()) {
|
||||
items(pendingTasks) { task ->
|
||||
EventCard(
|
||||
radius = radius,
|
||||
is24HourFormat = is24HourFormat,
|
||||
isPending = true,
|
||||
title = task.title,
|
||||
repeat = task.recurrence,
|
||||
startDateTime = task.startDateTime,
|
||||
onChangeStatus = { onTaskEvents(TaskEvents.ToggleStatus(true, task.id, workspaceId, selectedDate)) },
|
||||
onClick = { navController.navigate(NavRoutes.EventDetails.withArgs(workspaceId, task.id, selectedDate)) }
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
if (completedTasks.isNotEmpty()) {
|
||||
items(completedTasks) { task ->
|
||||
EventCard(
|
||||
radius = radius,
|
||||
is24HourFormat = is24HourFormat,
|
||||
isPending = false,
|
||||
title = task.title,
|
||||
repeat = task.recurrence,
|
||||
startDateTime = task.startDateTime,
|
||||
onChangeStatus = { onTaskEvents(TaskEvents.ToggleStatus(false, task.id, workspaceId, selectedDate)) },
|
||||
onClick = { navController.navigate(NavRoutes.EventDetails.withArgs(workspaceId, task.id, selectedDate)) }
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.flux.ui.screens.calendar
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import com.flux.data.model.EventInstanceModel
|
||||
import com.flux.data.model.EventModel
|
||||
import com.flux.navigation.Loader
|
||||
import com.flux.navigation.NavRoutes
|
||||
import com.flux.ui.components.DailyViewCalendar
|
||||
import com.flux.ui.components.MonthlyViewCalendar
|
||||
import com.flux.ui.events.TaskEvents
|
||||
import com.flux.ui.screens.events.EmptyEvents
|
||||
import com.flux.ui.screens.events.EventCard
|
||||
import com.flux.ui.state.Settings
|
||||
import java.time.YearMonth
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun LazyListScope.calendarItems(
|
||||
navController: NavController,
|
||||
radius: Int,
|
||||
is24HourFormat: Boolean,
|
||||
isLoading: Boolean,
|
||||
workspaceId: String,
|
||||
selectedMonth: YearMonth,
|
||||
selectedDate: Long,
|
||||
settings: Settings,
|
||||
datedEvents: List<EventModel>,
|
||||
allEventInstances: List<EventInstanceModel>,
|
||||
onTaskEvents: (TaskEvents) -> Unit
|
||||
) {
|
||||
val isMonthlyView = settings.data.isCalendarMonthlyView
|
||||
|
||||
if (isMonthlyView) {
|
||||
item {
|
||||
MonthlyViewCalendar(
|
||||
selectedMonth, selectedDate,
|
||||
onMonthChange = {
|
||||
onTaskEvents(TaskEvents.ChangeMonth(it))
|
||||
},
|
||||
onDateChange = {
|
||||
onTaskEvents(TaskEvents.LoadDateTask(workspaceId, it))
|
||||
onTaskEvents(TaskEvents.ChangeDate(it))
|
||||
})
|
||||
}
|
||||
} else {
|
||||
item {
|
||||
DailyViewCalendar(
|
||||
selectedMonth,
|
||||
selectedDate,
|
||||
onDateChange = {
|
||||
onTaskEvents(TaskEvents.LoadDateTask(workspaceId, it))
|
||||
onTaskEvents(TaskEvents.ChangeDate(it))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
item { Loader() }
|
||||
} else if (datedEvents.isEmpty()) {
|
||||
item { EmptyEvents() }
|
||||
} else {
|
||||
item { Spacer(Modifier.height(24.dp)) }
|
||||
|
||||
val pendingTasks = datedEvents.filter { task ->
|
||||
val instance = allEventInstances.find { it.eventId == task.id && it.instanceDate == selectedDate }
|
||||
instance == null
|
||||
}
|
||||
|
||||
val completedTasks = datedEvents.filter { task ->
|
||||
val instance = allEventInstances.find { it.eventId == task.id && it.instanceDate == selectedDate }
|
||||
instance != null
|
||||
}
|
||||
|
||||
if (pendingTasks.isNotEmpty()) {
|
||||
items(pendingTasks) { task ->
|
||||
EventCard(
|
||||
radius = radius,
|
||||
is24HourFormat = is24HourFormat,
|
||||
isPending = true,
|
||||
title = task.title,
|
||||
repeat = task.recurrence,
|
||||
startDateTime = task.startDateTime,
|
||||
onChangeStatus = { onTaskEvents(TaskEvents.ToggleStatus(true, task.id, workspaceId, selectedDate)) },
|
||||
onClick = { navController.navigate(NavRoutes.EventDetails.withArgs(workspaceId, task.id, selectedDate)) }
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
if (completedTasks.isNotEmpty()) {
|
||||
items(completedTasks) { task ->
|
||||
EventCard(
|
||||
radius = radius,
|
||||
is24HourFormat = is24HourFormat,
|
||||
isPending = false,
|
||||
title = task.title,
|
||||
repeat = task.recurrence,
|
||||
startDateTime = task.startDateTime,
|
||||
onChangeStatus = { onTaskEvents(TaskEvents.ToggleStatus(false, task.id, workspaceId, selectedDate)) },
|
||||
onClick = { navController.navigate(NavRoutes.EventDetails.withArgs(workspaceId, task.id, selectedDate)) }
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+94
-94
@@ -1,94 +1,94 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
||||
Reference in New Issue
Block a user