Skip to content

Commit

Permalink
Refactor/woowacourse-teams#861 network view model 적용 (woowacourse-tea…
Browse files Browse the repository at this point in the history
…ms#873)

* feat: NetworkViewModel 구현

* refactor : 스크랩 화면 NetworkViewModel 적용

* refactor : 스크랩 화면 NetworkViewModel 적용

* refactor(ChildCommentViewModel): NetworkViewModel 적용

* feat(NetworkViewModel): command와 commandAndRefresh에 onStart와 onFinish 매개변수 추가

* feat(ChildCommentViewModel): 댓글 게시 요청의 응답을 받지 않았다면 댓글을 추가적으로 보낼 수 없도록 변경

* refactor(ChildCommentActivity): NetworkActivity 적용

* refactor(NetworkActivity): BaseActivity 분리

* feat(NetworkFragment): NetworkFragment 구현

* refactor(MyProfileViewModel): NetworkViewModel 적용

* refactor(NetworkActivity): 메서드명 오타 수정

* refactor(FeedDetailViewModel): NetworkViewModel 적용

* refactor(ChildCommentsUiState): ChildCommentsUiState 클래스 제거

* feat(activity_feed_detail.xml): SwipeRefreshLayout 아이콘 색상을 primary color로 변경

* feat(NetworkViewModel): requestNetwork 메서드 구현

* feat(NetworkViewModel): requestNetwork 메서드의 onStart와 onFinish에 기본값 설정

* feat(BaseActivity): onCreate에서 바인딩 객체의 생명주기 주인 설정

* refactor(ProfileViewModel): NetworkViewModel 적용

* feat(FeedDetailActivity): 다른 화면 갔다오면 새로고침하도록 변경

* refactor(EditMyProfileViewModel): NetworkViewModel 적용

* refactor(EditMyProfile): UiState, UiEvent, Activity 리팩터링

* refactor(MyCommentsUiState): 불필요한 MyCommentsUiState 클래스 제거

* fix(FeedDetailViewModel): 댓글 개수 로직 수정

* refactor(MemberBlockViewModel): NetworkViewModel 적용

* refactor(ScrappedEvent): UiState 제거 및 NetworkFragment 적용

* refactor(FeedListViewModel): NetworkFragment 적용

* refactor(ScrappedEventViewModel): 새로고침 로직 리팩터링

* refactor(EventRecruitmentViewModel): NetworkViewModel 적용

* refactor(RecruitmentPostDetailViewModel): NetworkViewModel 적용

* refactor(RefreshableViewModel): NetworkViewModel에서 RefreshableViewModel 분리

* refactor(RecruitmentPostWritingViewModel): NetworkViewModel 적용

* refactor(BasicTextInputWindow, SubTextInputWindow): BindingMethods를 사용하여 가독성 향상

* feat(RecruitmentPostWritingActivity): 사용성 증가

- 글이 비어있거나 아무것도 수정되지 않았다면 네트워크 요청 못하게 막음
- 수정된 게 있을 때 뒤로 가기 하면 확인 다이얼로그 띄움

* refactor(FeedWritingViewModel): NetworkViewModel 적용

* refactor(RecruitmentPostWriting): 코드 리팩터링

* feat(RecruitmentPostDetailActivity): 모집글 삭제 후 스낵바 띄우지 않도록 변경

* refactor(EventDetailViewModel): RefreshableViewModel 적용

* style: ktlint 적용

* refactor(NotificationsViewModel): RefreshableViewModel 적용

* refactor(SettingViewModel): RefreshableViewModel 적용

* refactor(NotificationConfigViewModel): RefreshableViewModel 적용

* fix(EventDetailViewModel): 행사 정보 불러올 때 로딩 바 보이도록 수정

* refactor(NotificationTagConfigViewModel): RefreshableViewModel 적용

* fix(themes.xml): 다크 모드일 때도 툴바 스타일이 적용되도록 수정

* refactor(NetworkActivity, NetworkFragment): 데이터 불러오기가 실패할 경우 보여주는 다이얼로그 메세지 변경

* refactor: 불필요한 UiState 제거

* refactor(MemberBlockActivity): 코드 리팩터링

* refactor(ChildCommentsActivity): 코드 리팩터링

* refactor(EditMyProfileActivity): 코드 리팩터링

* refactor(EventDetailActivity): 코드 리팩터링

* refactor(EventFragment): 코드 리팩터링

* refactor(FeedDetailActivity): 코드 리팩터링

* refactor(FeedListFragment): 코드 리팩터링

* refactor(MyCommentsActivity): 코드 리팩터링

* refactor(MyProfileFragment): 코드 리팩터링

* refactor(ProfileActivity): 코드 리팩터링

* refactor(RecruitmentPostDetailActivity): 코드 리팩터링

* refactor(RecruitmentsFragment): 코드 리팩터링

* refactor(FeedDetailActivity): 코드 리팩터링

* refactor(ScrappedEventFragment): 코드 리팩터링

* refactor(SettingFragment): 코드 리팩터링

* refactor(HorizontalDivider): AppCompatImageView를 상속하도록 바꾸고 클래스명 변경

- Divider -> HorizontalDivider

* refactor: 수평 구분선을 HorizontalDivider로 구현하도록 변경

* refactor: 불필요한 layout 파일 제거

* feat(FeedListFragment): 피드 사이에만 구분선이 그려지도록 변경

* feat(RecruitmentsFragment): 모집글 사이에만 구분선이 그려지도록 변경

* feat(FeedWritingActivity): 이미지 삭제 아이콘 변경, 이미지 클릭 시 크게 보기 기능 추가, 이미지 사이에만 간격이 존재하도록 변경

* feat(activity_feed_writing.xml): 레이아웃 변경

* refactor(MessageListViewModel): RefreshableViewModel 적용

* refactor(NetworkViewModel): onStart 메서드 실행을 맨 처음으로 옮김

* fix(FeedDetailViewModel, NotificationTagConfigViewModel): 요청 실패 시 화면 상태를 NONE으로 변경

* refactor(MessagesUiState): Message ui 상태를 변경하는 로직을 MessagesUiState로 옮김

* refactor(MessageListActivity): 코드 리팩터링

* feat(MessageListActivity): 아래로 스크롤 할 수 없을 때 새로운 메세지가 오면 새 메세지 알림 뷰를 보여주는 대신 자동으로 아래로 스크롤 되도록 변경

* feat(MessageListActivity): MessageListActivity가 화면에 보여질 때 다른 채팅방의 메세지가 오면 알림 띄우기 기능 추가

* fix(ic_all_close.xml): 원래대로 x 아이콘만 그리고 게시글 이미지 작성 화면에서 사용할 이미지 제거 아이콘 따로 만듦(ic_writing_image_delete.xml)

* refactor(MessageRoomViewModel): RefreshableViewModel 적용

* feat(NetworkActivity, NetworkFragment): 알 수 없는 에러 발생 시 다이얼로그를 띄우고 화면을 나가도록 변경

* refactor(NetworkViewModel, RefreshableViewModel): 모든 메서드의 모든 매개변수를 suspend 함수 타입으로 변경

* refactor(LoginViewModel): NetworkViewModel 적용

* refactor(SplashActivity): 코드 리팩터링

* fix(img_profile_image_decoration.xml): 깨지지 않은 이미지로 변경

* refactor(BaseFragment): 생성자에서 레이아웃 리소스를 받도록 변경

* refactor(OnboardingViewModel): RefreshableViewModel 적용

* refactor(FeedDetailActivity): ConcatAdapter 대신 멀티 뷰 타입을 사용하도록 변경

* feat(FeedDetailActivity): 피드 댓글 하이라이팅 기능 구현

* feat(item_all_comment.xml): 댓글 메뉴 크기 늘림

* feat(MyCommentsViewModel): 댓글 작성 날짜 역순으로 정렬

* refactor(FeedDetailActivity): 메서드 위치 변경

- highlightComment 메서드 위치를 사용되는 곳 아래로 옮김

* refactor(EventDetailViewModel): 모집글 작성했는지 확인하는 로직 리팩터링

* refactor(FeedDetailViewModel): 댓글 수정 중일 때 댓글 배경색 변화가 유지되도록 변경

* refactor: RecruitmentPost -> Recruitment

* refactor(KerdyFirebaseMessagingService): 코드 리팩터링

* feat(FeedDetailViewModel): 하이라이팅 된 댓글을 다시 하이라이팅 할 수 있도록 변경

* chore(proguard-rules.pro): ApiResponse 클래스를 절대 축소되지 않게 하는 게 아니라 이름이 유지만 되도록 변경

* fix(MyProfileActivity): 프로필 수정하고 오면 화면이 새로고침 되도록 변경

* fix(SplashActivity): 플레이스토어가 설치되지 않았다면 플레이스토어로 이동하도록 수정

---------

Co-authored-by: chws0508 <[email protected]>
  • Loading branch information
ki960213 and chws0508 authored Dec 12, 2023
1 parent 6186249 commit fa38c87
Show file tree
Hide file tree
Showing 261 changed files with 4,822 additions and 6,283 deletions.
2 changes: 1 addition & 1 deletion android/2023-emmsale/app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

# ApiResponse 클래스 축소 및 난독화 해제하여 CallAdapter에서 retrofit2.Call<ApiResponse>를 반환하는 CallAdapter 만들 수 있도록 변경
-keep class com.emmsale.data.common.retrofit.callAdapter.ApiResponse
-keepnames class com.emmsale.data.common.retrofit.callAdapter.ApiResponse
12 changes: 7 additions & 5 deletions android/2023-emmsale/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@
</activity>
<activity android:name=".presentation.ui.myRecruitmentList.MyRecruitmentActivity" />
<activity android:name=".presentation.ui.notificationTagConfig.NotificationTagConfigActivity" />
<activity android:name=".presentation.ui.notificationList.NotificationsActivity" />
<activity android:name=".presentation.ui.myCommentList.MyCommentsActivity" />
<activity android:name=".presentation.ui.blockMemberList.MemberBlockActivity" />
<activity android:name=".presentation.ui.blockMemberList.BlockedMembersActivity" />
<activity android:name=".presentation.ui.notificationConfig.NotificationConfigActivity" />
<activity android:name=".presentation.ui.recruitmentWriting.RecruitmentPostWritingActivity" />
<activity android:name=".presentation.ui.recruitmentDetail.RecruitmentPostDetailActivity" />
<activity
android:name=".presentation.ui.recruitmentWriting.RecruitmentWritingActivity"
android:windowSoftInputMode="adjustResize" />
<activity android:name=".presentation.ui.recruitmentDetail.RecruitmentDetailActivity" />
<activity android:name=".presentation.ui.editMyProfile.EditMyProfileActivity" />
<activity android:name=".presentation.ui.profile.ProfileActivity" />
<activity android:name=".presentation.ui.notificationPageList.NotificationBoxActivity" />
<activity android:name=".presentation.ui.childCommentList.ChildCommentActivity" />
<activity android:name=".presentation.ui.childCommentList.ChildCommentsActivity" />
<activity android:name=".presentation.ui.useTerm.UseTermWebViewActivity" />
<activity android:name=".presentation.ui.conferenceFilter.ConferenceFilterActivity" />
<activity android:name=".presentation.ui.competitionFilter.CompetitionFilterActivity" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class BlockedMemberResponse(
@SerialName("blockMemberId")
val id: Long,
val blockedMemberId: Long,
@SerialName("id")
val blockId: Long,
@SerialName("memberName")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class KerdyCall<T : Any>(
val apiResult = when {
!result.isSuccessful -> Failure(result.code(), result.errorBody()?.string())
responseType == Unit::class.java -> Success(Unit as T, result.headers())
result.body() == null -> Unexpected(IllegalStateException(NOT_EXIST_BODY))
result.body() == null -> Unexpected(Throwable(NOT_EXIST_BODY))
else -> Success(result.body()!!, result.headers())
}
callback.onResponse(this@KerdyCall, Response.success(apiResult))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.emmsale.data.model.BlockedMember
fun List<BlockedMemberResponse>.toData(): List<BlockedMember> = map(BlockedMemberResponse::toData)

fun BlockedMemberResponse.toData(): BlockedMember = BlockedMember(
id = id,
blockedMemberId = blockedMemberId,
memberName = memberName,
blockId = blockId,
profileImageUrl = profileImageUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,34 @@ import com.emmsale.data.apiModel.response.CommentTypeNotificationResponse
import com.emmsale.data.apiModel.response.EventTypeNotificationResponse
import com.emmsale.data.apiModel.response.NotificationResponse
import com.emmsale.data.apiModel.response.NotificationResponse.NotificationType
import com.emmsale.data.model.updatedNotification.ChildCommentNotification
import com.emmsale.data.model.updatedNotification.InterestEventNotification
import com.emmsale.data.model.updatedNotification.UpdatedNotification
import com.emmsale.data.model.Comment
import com.emmsale.data.model.Event
import com.emmsale.data.model.Feed
import com.emmsale.data.model.Member
import com.emmsale.data.model.notification.ChildCommentNotification
import com.emmsale.data.model.notification.InterestEventNotification
import com.emmsale.data.model.notification.Notification
import kotlinx.serialization.json.Json
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

@JvmName("NotificationResponse")
fun List<NotificationResponse>.toData(): List<UpdatedNotification> = map { it.toData() }
fun List<NotificationResponse>.toData(): List<Notification> = map { it.toData() }

fun NotificationResponse.toData(): UpdatedNotification = when (notificationType) {
fun NotificationResponse.toData(): Notification = when (notificationType) {
NotificationType.EVENT -> {
val eventNotificationInformation = Json.decodeFromString<EventTypeNotificationResponse>(
requireNotNull(extraNotificationInformation) { "이벤트 알림에 추가 정보가 없어요" },
)
InterestEventNotification(
id = notificationId,
receiverId = receiverId,
eventId = redirectId,
createdAt = createdAt.toLocalDateTime(),
isRead = isRead,
eventTitle = eventNotificationInformation.eventTitle,
event = Event(
id = redirectId,
name = eventNotificationInformation.eventTitle,
),
)
}

Expand All @@ -40,11 +46,13 @@ fun NotificationResponse.toData(): UpdatedNotification = when (notificationType)
receiverId = receiverId,
createdAt = createdAt.toLocalDateTime(),
isRead = isRead,
parentCommentId = commentNotificationInformation.parentId,
childCommentId = redirectId,
childCommentContent = commentNotificationInformation.content,
feedId = commentNotificationInformation.feedId,
commentProfileImageUrl = commentNotificationInformation.writerProfileImageUrl,
comment = Comment(
id = redirectId,
content = commentNotificationInformation.content,
parentCommentId = commentNotificationInformation.parentId,
feed = Feed(id = commentNotificationInformation.feedId),
writer = Member(profileImageUrl = commentNotificationInformation.writerProfileImageUrl),
),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.emmsale.data.model

data class BlockedMember(
val id: Long,
val blockedMemberId: Long,
val memberName: String,
val blockId: Long,
val profileImageUrl: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ data class Comment(
val updatedAt: LocalDateTime = LocalDateTime.MAX,
val isDeleted: Boolean = false,
val childComments: List<Comment> = emptyList(),
)
) {
val isUpdated: Boolean = createdAt != updatedAt
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.emmsale.data.model

data class Config(
val isNotificationReceive: Boolean,
val isFollowNotificationReceive: Boolean,
val isCommentNotificationReceive: Boolean,
val isInterestEventNotificationReceive: Boolean,
val isMessageNotificationReceive: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.emmsale.data.model
import java.time.LocalDateTime

data class Event(
val id: Long,
val id: Long = -1,
val name: String = "",
val informationUrl: String = "",
val organization: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ data class Feed(
val updatedAt: LocalDateTime = LocalDateTime.MAX,
) {
val titleImageUrl = imageUrls.firstOrNull()

val isUpdated = createdAt != updatedAt
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package com.emmsale.data.model
import java.time.LocalDate

data class Recruitment(
val id: Long,
val writer: Member,
val event: Event,
val content: String,
val updatedDate: LocalDate,
val id: Long = -1,
val writer: Member = Member(),
val event: Event = Event(),
val content: String = "",
val updatedDate: LocalDate = LocalDate.MAX,
)
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package com.emmsale.data.model.updatedNotification
package com.emmsale.data.model.notification

import com.emmsale.data.model.Comment
import java.time.LocalDateTime

class ChildCommentNotification(
id: Long,
receiverId: Long,
createdAt: LocalDateTime,
isRead: Boolean,
val parentCommentId: Long,
val childCommentId: Long,
val childCommentContent: String,
val feedId: Long,
val commentProfileImageUrl: String,
) : UpdatedNotification(
val comment: Comment,
) : Notification(
id = id,
receiverId = receiverId,
createdAt = createdAt,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.emmsale.data.model.updatedNotification
package com.emmsale.data.model.notification

import com.emmsale.data.model.Event
import java.time.LocalDateTime

class InterestEventNotification(
id: Long,
receiverId: Long,
createdAt: LocalDateTime,
isRead: Boolean,
val eventId: Long,
val eventTitle: String,
) : UpdatedNotification(
val event: Event,
) : Notification(
id = id,
receiverId = receiverId,
createdAt = createdAt,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.emmsale.data.model.notification

import java.time.LocalDateTime

sealed class Notification(
val id: Long,
val receiverId: Long,
val createdAt: LocalDateTime,
val isRead: Boolean,
) {

fun read(): Notification = when (this) {
is ChildCommentNotification -> ChildCommentNotification(
id = id,
receiverId = receiverId,
createdAt = createdAt,
isRead = true,
comment = comment,
)

is InterestEventNotification -> InterestEventNotification(
id = id,
receiverId = receiverId,
createdAt = createdAt,
isRead = true,
event = event,
)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ class DefaultConfigRepository @Inject constructor(
KEY_NOTIFICATION_RECEIVE,
DEFAULT_VALUE_NOTIFICATION_RECEIVE,
),
isFollowNotificationReceive = preference.getBoolean(
KEY_FOLLOW_NOTIFICATION_RECEIVE,
DEFAULT_VALUE_FOLLOW_NOTIFICATION_RECEIVE,
),
isCommentNotificationReceive = preference.getBoolean(
KEY_CHILD_COMMENT_NOTIFICATION_RECEIVE,
DEFAULT_VALUE_CHILD_COMMENT_NOTIFICATION_RECEIVE,
Expand All @@ -41,10 +37,6 @@ class DefaultConfigRepository @Inject constructor(
preferenceEditor.putBoolean(KEY_NOTIFICATION_RECEIVE, isReceive).commit()
}

override fun saveFollowNotificationReceiveConfig(isReceive: Boolean) {
preferenceEditor.putBoolean(KEY_FOLLOW_NOTIFICATION_RECEIVE, isReceive).commit()
}

override fun saveCommentNotificationReceiveConfig(isReceive: Boolean) {
preferenceEditor.putBoolean(KEY_CHILD_COMMENT_NOTIFICATION_RECEIVE, isReceive).commit()
}
Expand All @@ -68,9 +60,6 @@ class DefaultConfigRepository @Inject constructor(
private const val KEY_AUTO_LOGIN = "auto_login_key"
private const val DEFAULT_VALUE_AUTO_LOGIN = false

private const val KEY_FOLLOW_NOTIFICATION_RECEIVE = "follow_notification_receive_key"
private const val DEFAULT_VALUE_FOLLOW_NOTIFICATION_RECEIVE = true

private const val KEY_CHILD_COMMENT_NOTIFICATION_RECEIVE =
"child_comment_notification_receive_key"
private const val DEFAULT_VALUE_CHILD_COMMENT_NOTIFICATION_RECEIVE = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class DefaultEventRepository @Inject constructor(
)
}

override suspend fun deleteScrap(eventId: Long): ApiResponse<Unit> {
override suspend fun scrapOffEvent(eventId: Long): ApiResponse<Unit> {
return eventService.deleteScrap(eventId)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.emmsale.data.repository.concretes

import com.emmsale.data.apiModel.request.NotificationListDeleteRequest
import com.emmsale.data.apiModel.request.RecruitmentNotificationReportCreateRequest
import com.emmsale.data.apiModel.response.NotificationResponse
import com.emmsale.data.common.retrofit.callAdapter.ApiResponse
import com.emmsale.data.mapper.toData
import com.emmsale.data.model.updatedNotification.UpdatedNotification
import com.emmsale.data.model.notification.Notification
import com.emmsale.data.repository.interfaces.NotificationRepository
import com.emmsale.data.service.NotificationService
import com.emmsale.di.modules.other.IoDispatcher
Expand All @@ -18,45 +17,25 @@ class DefaultNotificationRepository @Inject constructor(
private val notificationService: NotificationService,
) : NotificationRepository {

override suspend fun updateNotificationReadStatus(
notificationId: Long,
): ApiResponse<Unit> = withContext(dispatcher) {
notificationService.updateRecruitmentNotificationReadStatus(notificationId)
}

override suspend fun getUpdatedNotifications(
override suspend fun getNotifications(
memberId: Long,
): ApiResponse<List<UpdatedNotification>> = withContext(dispatcher) {
): ApiResponse<List<Notification>> = withContext(dispatcher) {
notificationService
.getNotifications(memberId)
.map(List<NotificationResponse>::toData)
}

override suspend fun updateUpdatedNotificationReadStatus(
override suspend fun readNotification(
notificationId: Long,
): ApiResponse<Unit> = withContext(dispatcher) {
notificationService.updateNotificationReadStatus(notificationId)
notificationService.readNotification(notificationId)
}

override suspend fun deleteUpdatedNotifications(
override suspend fun deleteNotifications(
notificationIds: List<Long>,
): ApiResponse<Unit> = withContext(dispatcher) {
notificationService.deleteNotification(
NotificationListDeleteRequest(notificationIds),
)
}

override suspend fun reportRecruitmentNotification(
recruitmentNotificationId: Long,
senderId: Long,
reporterId: Long,
): ApiResponse<Unit> = withContext(dispatcher) {
notificationService.reportRecruitmentNotification(
RecruitmentNotificationReportCreateRequest.create(
recruitmentNotificationId = recruitmentNotificationId,
senderId = senderId,
reporterId = reporterId,
),
).map { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ interface ConfigRepository {

fun saveAutoLoginConfig(isAutoLogin: Boolean)

fun saveFollowNotificationReceiveConfig(isReceive: Boolean)

fun saveCommentNotificationReceiveConfig(isReceive: Boolean)

fun saveInterestEventNotificationReceiveConfig(isReceive: Boolean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ interface EventRepository {

suspend fun scrapEvent(eventId: Long): ApiResponse<Unit>

suspend fun deleteScrap(eventId: Long): ApiResponse<Unit>
suspend fun scrapOffEvent(eventId: Long): ApiResponse<Unit>

suspend fun isScraped(eventId: Long): ApiResponse<Boolean>
}
Loading

0 comments on commit fa38c87

Please sign in to comment.