Skip to content

Commit

Permalink
Merge pull request #373 from apeun-gidaechi/feature/372-setting-gener…
Browse files Browse the repository at this point in the history
…al-and-alarm-screen

Feature/Setting general and Alarm screen
  • Loading branch information
8954sood authored Dec 3, 2024
2 parents 841e872 + b029d05 commit 2f40d3c
Show file tree
Hide file tree
Showing 30 changed files with 403 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.seugi.data.core.mapper

import com.seugi.data.core.model.TokenModel
import com.seugi.local.room.model.TokenEntity
import com.seugi.local.room.entity.TokenEntity
import com.seugi.network.core.response.TokenResponse

fun TokenResponse.toModel(): TokenModel = TokenModel(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.seugi.data.firebasetoken.mapper

import com.seugi.data.firebasetoken.model.FirebaseTokenModel
import com.seugi.local.room.model.FirebaseTokenEntity
import com.seugi.local.room.entity.FirebaseTokenEntity

fun FirebaseTokenEntity?.toModel(): FirebaseTokenModel = FirebaseTokenModel(
firebaseToken = this?.firebaseToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.seugi.data.firebasetoken.FirebaseTokenRepository
import com.seugi.data.firebasetoken.mapper.toModel
import com.seugi.data.firebasetoken.model.FirebaseTokenModel
import com.seugi.local.room.dao.FirebaseTokenDao
import com.seugi.local.room.model.FirebaseTokenEntity
import com.seugi.local.room.entity.FirebaseTokenEntity
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.seugi.common.utiles.toKotlinLocalDate
import com.seugi.common.utiles.toNotSpaceString
import com.seugi.data.core.mapper.toMealType
import com.seugi.data.core.model.MealModel
import com.seugi.local.room.model.MealEntity
import com.seugi.local.room.entity.MealEntity
import kotlinx.collections.immutable.toImmutableList

internal fun MealEntity.toModel() = MealModel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.seugi.data.core.mapper.toModel
import com.seugi.data.core.model.TokenModel
import com.seugi.data.token.TokenRepository
import com.seugi.local.room.dao.TokenDao
import com.seugi.local.room.model.TokenEntity
import com.seugi.local.room.entity.TokenEntity
import com.seugi.network.token.TokenDatasource
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ interface WorkspaceRepository {
suspend fun getWorkspaceCode(workspaceId: String): Flow<Result<String>>
suspend fun addMember(workspaceId: String, userSet: List<Long>, role: String): Flow<Result<Boolean>>
suspend fun cancelMember(workspaceId: String, userSet: List<Long>, role: String): Flow<Result<Boolean>>

suspend fun getIsWorkspaceReceiveFCM(workspaceId: String): Flow<Result<Boolean>>
suspend fun changeIsWorkspaceReceiveFCM(isReceiveFCM: Boolean, workspaceId: String): Flow<Result<Boolean>>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.seugi.data.workspace.mapper

import com.seugi.data.workspace.model.WorkspaceModel
import com.seugi.local.room.model.WorkspaceEntity
import com.seugi.local.room.entity.WorkspaceEntity
import com.seugi.network.workspace.response.WorkspaceResponse
import kotlinx.collections.immutable.toImmutableList

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import com.seugi.data.workspace.model.CheckWorkspaceModel
import com.seugi.data.workspace.model.WaitWorkspaceModel
import com.seugi.data.workspace.model.WorkspaceModel
import com.seugi.local.room.dao.WorkspaceDao
import com.seugi.local.room.dao.WorkspaceNotificationDao
import com.seugi.local.room.entity.WorkspaceNotificationEntity
import com.seugi.network.core.response.safeResponse
import com.seugi.network.workspace.WorkspaceDataSource
import javax.inject.Inject
Expand All @@ -28,6 +30,7 @@ class WorkspaceRepositoryImpl @Inject constructor(
@SeugiDispatcher(DispatcherType.IO) private val dispatcher: CoroutineDispatcher,
private val workspaceDatasource: WorkspaceDataSource,
private val workspaceDao: WorkspaceDao,
private val workspaceNotificationDao: WorkspaceNotificationDao,
) : WorkspaceRepository {
override suspend fun checkWorkspace(schoolCode: String): Flow<Result<CheckWorkspaceModel>> {
return flow {
Expand Down Expand Up @@ -76,10 +79,14 @@ class WorkspaceRepositoryImpl @Inject constructor(
teacher = workspaceModel.teacher,
student = workspaceModel.student,
)
if (workspaceNotificationDao.getWorkspaceByWorkspaceId(workspaceModel.workspaceId) == null) {
workspaceNotificationDao.insert(WorkspaceNotificationEntity(workspaceModel.workspaceId, true))
}
}

override suspend fun insertWorkspace(workspaceModel: WorkspaceModel) {
workspaceDao.insert(workspaceModel.toEntity())
workspaceNotificationDao.insert(WorkspaceNotificationEntity(workspaceModel.workspaceId, true))
}

override suspend fun getLocalWorkspaceId(): String {
Expand Down Expand Up @@ -161,4 +168,22 @@ class WorkspaceRepositoryImpl @Inject constructor(
}
.flowOn(dispatcher)
.asResult()

override suspend fun getIsWorkspaceReceiveFCM(workspaceId: String): Flow<Result<Boolean>> = flow {
val response = workspaceNotificationDao.getWorkspaceByWorkspaceId(workspaceId)

emit(response?.isReceiveFCM ?: true)
}
.flowOn(dispatcher)
.asResult()

override suspend fun changeIsWorkspaceReceiveFCM(isReceiveFCM: Boolean, workspaceId: String): Flow<Result<Boolean>> = flow {
workspaceNotificationDao.updateIsReceiveFCMByWorkspaceId(
isReceiveFCM = isReceiveFCM,
workspaceId = workspaceId,
)
emit(true)
}
.flowOn(dispatcher)
.asResult()
}
17 changes: 17 additions & 0 deletions feature-main/main/src/main/java/com/seugi/main/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,12 @@ import com.seugi.workspacedetail.navigation.inviteMemberScreen
import com.seugi.workspacedetail.navigation.navigateToInviteMember
import com.seugi.workspacedetail.navigation.navigateToWorkspaceDetail
import com.seugi.workspacedetail.navigation.navigateToWorkspaceMember
import com.seugi.workspacedetail.navigation.navigateToWorkspaceSettingAlarm
import com.seugi.workspacedetail.navigation.navigateToWorkspaceSettingGeneral
import com.seugi.workspacedetail.navigation.workspaceDetailScreen
import com.seugi.workspacedetail.navigation.workspaceMemberScreen
import com.seugi.workspacedetail.navigation.workspaceSettingAlarmScreen
import com.seugi.workspacedetail.navigation.workspaceSettingGeneralScreen
import kotlinx.coroutines.delay

private const val NAVIGATION_ANIM = 400
Expand Down Expand Up @@ -327,6 +331,8 @@ internal fun MainScreen(
},
navigateToInviteMember = navHostController::navigateToInviteMember,
myRole = state.profile.permission,
navigateToSettingGeneral = navHostController::navigateToWorkspaceSettingGeneral,
navigateToSettingAlarm = navHostController::navigateToWorkspaceSettingAlarm,
)
workspaceMemberScreen(
showSnackbar = showSnackbar,
Expand All @@ -345,6 +351,17 @@ internal fun MainScreen(
},
)

workspaceSettingGeneralScreen(
popBackStack = {
navHostController.popBackStack()
},
)

workspaceSettingAlarmScreen(
workspaceId = state.workspace.workspaceId,
popBackStack = navHostController::popBackStack,
)

settingScreen(
profileModel = state.profile,
navigationToOnboarding = mainToOnboarding,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.seugi.workspacedetail.feature.settingalarm

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.seugi.designsystem.animation.bounceClick
import com.seugi.designsystem.component.SeugiToggle
import com.seugi.designsystem.component.SeugiTopBar
import com.seugi.designsystem.theme.SeugiTheme

@Composable
internal fun SettingAlarmScreen(viewModel: SettingAlarmViewModel = hiltViewModel(), workspaceId: String, popBackStack: () -> Unit) {
val alarmState by viewModel.alarmState.collectAsStateWithLifecycle()

LaunchedEffect(workspaceId) {
viewModel.load(workspaceId)
}

Scaffold(
topBar = {
SeugiTopBar(
title = {
Text(
text = "알림 설정",
style = SeugiTheme.typography.subtitle1,
color = SeugiTheme.colors.black,
)
},
onNavigationIconClick = popBackStack,
)
},
containerColor = SeugiTheme.colors.white,
) {
Column(
modifier = Modifier
.padding(it)
.fillMaxWidth(),
) {
Spacer(modifier = Modifier.height(6.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.bounceClick(
onClick = {
viewModel.changeAlarmState(
alarmState = !alarmState,
workspaceId = workspaceId,
)
},
)
.padding(
horizontal = 20.dp,
vertical = 12.5.dp,
),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "전체 알림 허용",
style = SeugiTheme.typography.subtitle2,
color = SeugiTheme.colors.black,
)
Spacer(modifier = Modifier.weight(1f))
SeugiToggle(
checked = alarmState,
onCheckedChangeListener = {
viewModel.changeAlarmState(
alarmState = it,
workspaceId = workspaceId,
)
},
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.seugi.workspacedetail.feature.settingalarm

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.seugi.common.model.Result
import com.seugi.common.utiles.DispatcherType
import com.seugi.common.utiles.SeugiDispatcher
import com.seugi.data.workspace.WorkspaceRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

@HiltViewModel
class SettingAlarmViewModel @Inject constructor(
@SeugiDispatcher(DispatcherType.IO) private val dispatcher: CoroutineDispatcher,
private val workspaceRepository: WorkspaceRepository,
) : ViewModel() {

private val _alarmState = MutableStateFlow(false)
val alarmState = _alarmState.asStateFlow()

fun load(workspaceId: String) = viewModelScope.launch(dispatcher) {
workspaceRepository.getIsWorkspaceReceiveFCM(workspaceId).collect {
when (it) {
is Result.Success -> {
_alarmState.update { _ ->
it.data
}
}
is Result.Error -> {
it.throwable.printStackTrace()
}
Result.Loading -> {}
}
}
}

fun changeAlarmState(alarmState: Boolean, workspaceId: String) = viewModelScope.launch(dispatcher) {
workspaceRepository.changeIsWorkspaceReceiveFCM(alarmState, workspaceId).collect {
when (it) {
is Result.Success -> {
_alarmState.update { _ ->
alarmState
}
}
is Result.Error -> {
it.throwable.printStackTrace()
}
Result.Loading -> {}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.seugi.workspacedetail.feature.settinggeneral

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.seugi.designsystem.animation.bounceClick
import com.seugi.designsystem.component.SeugiDialog
import com.seugi.designsystem.component.SeugiTopBar
import com.seugi.designsystem.theme.SeugiTheme
import com.seugi.workspacecdetail.R

@Composable
internal fun SettingGeneralScreen(popBackStack: () -> Unit) {
var showDialog by remember { mutableStateOf(false) }

if (showDialog) {
SeugiDialog(
title = "탈퇴 실패 안내",
content = "시연 모드에서는 탈퇴가 불가능합니다.",
onDismissRequest = {
showDialog = false
},
)
}

Scaffold(
topBar = {
SeugiTopBar(
title = {
Text(
text = "일반",
style = SeugiTheme.typography.subtitle1,
color = SeugiTheme.colors.black,
)
},
onNavigationIconClick = popBackStack,
)
},
containerColor = SeugiTheme.colors.white,
) {
Column(
modifier = Modifier
.padding(it)
.fillMaxWidth(),
) {
Spacer(modifier = Modifier.height(6.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.bounceClick(
onClick = {
showDialog = true
},
)
.padding(
horizontal = 20.dp,
vertical = 16.dp,
),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "학교 나가기",
style = SeugiTheme.typography.subtitle2,
color = SeugiTheme.colors.red500,
)
Spacer(modifier = Modifier.weight(1f))
Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = com.seugi.designsystem.R.drawable.ic_expand_right_line),
contentDescription = null,
tint = SeugiTheme.colors.gray400,
)
}
}
}
}
Loading

0 comments on commit 2f40d3c

Please sign in to comment.