Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
id("com.google.gms.google-services")
id("de.mannodermaus.android-junit5")
kotlin("plugin.serialization") version "1.9.23"
}
Expand Down Expand Up @@ -45,11 +46,15 @@ android {


dependencies {
//user token
implementation(libs.kotlinx.coroutines.play.services)
implementation(libs.firebase.messaging)
//tests
testImplementation(libs.mockk)
testImplementation(libs.jupiter.junit.jupiter)
androidTestImplementation(libs.ui.test.junit4)
debugImplementation(libs.ui.test.manifest)
implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.lifecycle.process)//Dispatchers.setMain()
implementation(libs.kotlinx.serialization.json)
testImplementation(libs.junit.jupiter)
testRuntimeOnly(libs.junit.vintage.engine)
Expand Down Expand Up @@ -82,6 +87,7 @@ dependencies {
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material)
implementation(libs.androidx.material3)
implementation(libs.androidx.lifecycle.runtime.compose.android)
implementation(libs.androidx.compose.material3)
Expand Down
30 changes: 30 additions & 0 deletions app/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"project_info": {
"project_number": "780456329938",
"firebase_url": "https://smartcalendarru-default-rtdb.firebaseio.com",
"project_id": "smartcalendarru",
"storage_bucket": "smartcalendarru.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:780456329938:android:14d945eb519314b326230b",
"android_client_info": {
"package_name": "org.hse.smartcalendar"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyBBo5NexFhO3bcrOUp9Kjv5Xhbmuu2TluY"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.datetime.LocalTime
import org.hse.smartcalendar.data.DailyTask
import org.hse.smartcalendar.data.DailyTaskType
import org.hse.smartcalendar.data.SharedInfo
import org.hse.smartcalendar.store.StatisticsStore
import org.hse.smartcalendar.ui.screens.model.AchievementType
import org.hse.smartcalendar.ui.theme.SmartCalendarTheme
Expand Down Expand Up @@ -39,6 +40,7 @@ class AchievementsScreenTest {
start = LocalTime.Companion.fromMinutesOfDay(0),
end = LocalTime.Companion.fromMinutesOfDay(300),
date = TimeUtils.Companion.getCurrentDateTime().date,
sharedInfo = SharedInfo()
)
secondTask = DailyTask(
title = "first",
Expand All @@ -50,6 +52,7 @@ class AchievementsScreenTest {
start = LocalTime.Companion.fromMinutesOfDay(300),
end = LocalTime.Companion.fromMinutesOfDay(1440-1),
date = TimeUtils.Companion.getCurrentDateTime().date,
sharedInfo = SharedInfo()
)
}
fun assertAchievementData(type: AchievementType, text: String){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.work.WorkManager
import com.google.firebase.FirebaseApp
import org.hse.smartcalendar.R

//@HiltAndroidApp
Expand All @@ -19,6 +20,7 @@ class BaseApplication : Application(), LifecycleObserver {

override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.channel_name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class DailySchedule (val date : LocalDate = Clock.System.now()
return dailyTasksList
}

class NestedTaskException(oldTask: DailyTask, newTask: DailyTask) : IllegalArgumentException(
class NestedTaskException(val oldTask: DailyTask, newTask: DailyTask) : IllegalArgumentException(
"New task have conflict schedule with previous one:\n" +
"Old task: start = " + oldTask.getDailyTaskStartTime() + "; end = " + oldTask.getDailyTaskEndTime() + "\n" +
"New task: start = " + newTask.getDailyTaskStartTime() + "; end = " + newTask.getDailyTaskEndTime()
Expand Down
33 changes: 29 additions & 4 deletions app/src/main/java/org/hse/smartcalendar/data/DailyTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import kotlinx.serialization.Serializable
import org.hse.smartcalendar.utility.TimeUtils
import org.hse.smartcalendar.utility.UUIDSerializer
import java.util.UUID

@Serializable
data class SharedInfo(
val isShared: Boolean = false,
val invitees: List<String> = listOf(),
val participants: List<String> = listOf(),
val organizerName: String = ""
)
@Serializable
data class DailyTask (
@Serializable(with = UUIDSerializer::class)
Expand All @@ -24,8 +30,9 @@ data class DailyTask (
private var start : LocalTime,//hour, minute
private var end: LocalTime,//hour, minute
private var date: LocalDate,//year, month, day
private var sharedInfo: SharedInfo
) {
companion object {//затычка, можешь убрать
companion object {
val defaultDate = TimeUtils.getCurrentDateTime().date
fun fromTime(start: LocalTime, end: LocalTime, date: LocalDate): DailyTask{
return fromTimeAndType(start,end,date, DailyTaskType.COMMON)
Expand All @@ -37,7 +44,20 @@ data class DailyTask (
end = end,
start = start,
date = date,
type = type
type = type,
sharedInfo = SharedInfo()
)
}
fun example(title: String, type: DailyTaskType, description: String, start: LocalTime, end: LocalTime, isComplete: Boolean=false): DailyTask{
return DailyTask(
isComplete = isComplete,
title = title,
type = type,
description = description,
start = start,
end = end,
date = defaultDate,
sharedInfo = SharedInfo(),
)
}
}
Expand All @@ -64,6 +84,9 @@ data class DailyTask (
fun setCompletion(status: Boolean) {
isComplete = status
}
fun setDate(date: LocalDate) {
this.date = date
}

fun getDailyTaskEndTime() : LocalTime {
return end
Expand Down Expand Up @@ -138,7 +161,9 @@ data class DailyTask (
fun getMinutesLength(): Int{
return (end.toSecondOfDay()-start.toSecondOfDay())/60
}

fun getSharedInfo(): SharedInfo{
return sharedInfo
}
class TimeConflictException(start: LocalTime, end: LocalTime) : IllegalArgumentException(
"Illegal start and end time: start = " +
start.toString() +
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/org/hse/smartcalendar/data/Invite.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.hse.smartcalendar.data

import kotlinx.serialization.Serializable
import org.hse.smartcalendar.utility.UUIDSerializer
import java.util.UUID

@Serializable
data class Invite(
@Serializable(with = UUIDSerializer::class)
val id: UUID,
val inviterName: String,
val task: DailyTask,
)
25 changes: 25 additions & 0 deletions app/src/main/java/org/hse/smartcalendar/data/InviteAction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.hse.smartcalendar.data

import kotlinx.serialization.Serializable
import org.hse.smartcalendar.utility.UUIDSerializer
import java.util.UUID

@Serializable
data class InviteAction(
val type: Type,
@Serializable(with = UUIDSerializer::class)
val eventId: UUID,
val loginOrEmail: String
) {
enum class Type {
ACCEPT,
INVITE,
REMOVE_INVITE;

override fun toString(): String = name
}

companion object {
const val jsonName = "invite_action_json"
}
}
60 changes: 60 additions & 0 deletions app/src/main/java/org/hse/smartcalendar/data/store/InvitesStore.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.hse.smartcalendar.data.store

import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.hse.smartcalendar.data.Invite
import org.hse.smartcalendar.network.ApiClient
import org.hse.smartcalendar.network.NetworkResponse
import org.hse.smartcalendar.network.InviteResponse
import org.hse.smartcalendar.network.toInvite
import org.hse.smartcalendar.repository.InviteRepository

object InvitesStore {
private val _invites = mutableStateListOf<Invite>()
val invites: List<Invite> get() = _invites
private val repository = InviteRepository(ApiClient.inviteApiService)

private var lastFetchedInvites: List<Invite> = emptyList()
private var _hasNewInvites = mutableStateOf(false)
val hasNewInvites: Boolean get() = _hasNewInvites.value

suspend fun init(): NetworkResponse<List<Invite>> = withContext(Dispatchers.IO) {
when (val resp = repository.getMyInvites()) {
is NetworkResponse.Success -> {
val invites = resp.data.map { it.toInvite() }
updateDifference(fetched = invites)
setInvites(invites)
NetworkResponse.Success(invites)
}
is NetworkResponse.Error -> NetworkResponse.Error(resp.message)
is NetworkResponse.NetworkError -> NetworkResponse.NetworkError(resp.exceptionMessage)
is NetworkResponse.Loading -> NetworkResponse.Loading
}
}
private fun updateDifference( fetched: List<Invite>){
val isDifferent = fetched.size != lastFetchedInvites.size ||
fetched.map { it.id } != lastFetchedInvites.map { it.id }
if (isDifferent) {
_hasNewInvites.value = true
}
lastFetchedInvites = fetched
}

private fun setInvites(newList: List<Invite>) {
_invites.clear()
_invites.addAll(newList)
}

fun removeInvite(invite: Invite) {
_invites.remove(invite)
}

fun addInvite(invite: Invite) {
_invites.add(invite)
}
fun markInvitesSeen() {
_hasNewInvites.value = false
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/org/hse/smartcalendar/network/ApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ object ApiClient {
val audioApiService : AudioApiInterface by lazy {
retrofit.create(AudioApiInterface::class.java)
}
val inviteApiService: InviteApiInterface by lazy {
retrofit.create(InviteApiInterface::class.java)
}
}
class AuthInterceptor(private val tokenProvider: () -> String?) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/org/hse/smartcalendar/network/ApiInterface.kt
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,30 @@ interface AudioApiInterface {
@Part file: MultipartBody.Part
): Response<List<ChatTaskResponse>>
}

interface InviteApiInterface {

@GET("api/users/me/invites")
suspend fun getMyInvites(): Response<List<InviteResponse>>

@POST("api/users/events/{eventId}/accept-invite")
suspend fun acceptInvite(@Path("eventId") eventId: UUID): Response<ResponseBody>

@POST("api/users/events/{eventId}/invite")
suspend fun inviteUser(
@Path("eventId") eventId: UUID,
@Body request: InviteRequest
): Response<ResponseBody>

@POST("api/users/events/{eventId}/remove-invite")
suspend fun removeInvite(
@Path("eventId") eventId: UUID,
@Body request: InviteRequest
): Response<ResponseBody>

@POST("api/users/events/{eventId}/remove-participant")
suspend fun removeParticipant(
@Path("eventId") eventId: UUID,
@Body request: InviteRequest
): Response<ResponseBody>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.hse.smartcalendar.data.DailyTaskType
import org.hse.smartcalendar.utility.TimeUtils
import java.util.UUID
import androidx.compose.runtime.MutableState
import org.hse.smartcalendar.data.SharedInfo

data class RegisterResponse (
val id: Long? = null,
Expand Down Expand Up @@ -57,7 +58,8 @@ data class TaskResponse(
date = LocalDate.parse(date),
type = type,
creationTime = creationTime,
isComplete = complete
isComplete = complete,
sharedInfo = SharedInfo()//TODO
)
}
}
Expand All @@ -84,6 +86,7 @@ data class ChatTaskResponse(
type = DailyTaskType.valueOf(type?.uppercase() ?: "COMMON"),
creationTime = creationTime?: TimeUtils.getCurrentDateTime(),
isComplete = complete == true,
sharedInfo = SharedInfo()
)
return task
}
Expand Down
Loading
Loading