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
1 change: 1 addition & 0 deletions DevLog/Data/DTO/TodoDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct TodoRequest: Encodable {
let isPinned: Bool
let isCompleted: Bool
let isChecked: Bool
let isDeleted: Bool
let number: Int?
let title: String
let content: String
Expand Down
1 change: 1 addition & 0 deletions DevLog/Data/DTO/WebPageDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct WebPageRequest: Encodable {
let url: String
let displayURL: String
let imageURL: String
let isDeleted: Bool
}

struct WebPageResponse {
Expand Down
1 change: 1 addition & 0 deletions DevLog/Data/Mapper/TodoMapping.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extension TodoRequest {
isPinned: entity.isPinned,
isCompleted: entity.isCompleted,
isChecked: entity.isChecked,
isDeleted: false,
number: entity.number,
title: entity.title,
content: entity.content,
Expand Down
6 changes: 4 additions & 2 deletions DevLog/Data/Repository/WebPageRepositoryImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ final class WebPageRepositoryImpl: WebPageRepository {
title: metadata.title,
url: urlString,
displayURL: metadata.displayURL,
imageURL: metadata.imageURL
imageURL: metadata.imageURL,
isDeleted: false
)
try await webPageService.upsertWebPage(request)
}
Expand Down Expand Up @@ -101,7 +102,8 @@ private extension WebPageRepositoryImpl {
title: metadata.title,
url: response.url,
displayURL: metadata.displayURL,
imageURL: metadata.imageURL
imageURL: metadata.imageURL,
isDeleted: false
)
try await webPageService.upsertWebPage(request)

Expand Down
34 changes: 21 additions & 13 deletions DevLog/Infra/Service/PushNotificationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ final class PushNotificationService {
let items = snapshot.documents.compactMap { makeResponse(from: $0) }

let nextCursor: PushNotificationCursorDTO? = snapshot.documents.last.map { document in
guard let receivedAt = document.data()[Key.receivedAt.rawValue] as? Timestamp else {
guard let receivedAt = document.data()[PushNotificationFieldKey.receivedAt.rawValue] as? Timestamp
else {
return nil
}

Expand Down Expand Up @@ -184,6 +185,7 @@ final class PushNotificationService {
let subject = PassthroughSubject<Int, Error>()
let listener = store.collection(FirestorePath.notifications(uid))
.whereField("isRead", isEqualTo: false)
.whereField(PushNotificationFieldKey.isDeleted.rawValue, isEqualTo: false)
.addSnapshotListener { snapshot, error in
if let error {
subject.send(completion: .failure(error))
Expand All @@ -192,7 +194,7 @@ final class PushNotificationService {

guard let snapshot else { return }
let unreadPushCount = snapshot.documents.filter { document in
!(document.data()[Key.deletingAt.rawValue] is Timestamp)
!(document.data()[PushNotificationFieldKey.deletingAt.rawValue] is Timestamp)
}.count
subject.send(unreadPushCount)
}
Expand Down Expand Up @@ -238,7 +240,10 @@ final class PushNotificationService {
}

let collection = store.collection(FirestorePath.notifications(uid))
let snapshot = try await collection.whereField("todoId", isEqualTo: todoId).getDocuments()
let snapshot = try await collection
.whereField("todoId", isEqualTo: todoId)
.whereField(PushNotificationFieldKey.isDeleted.rawValue, isEqualTo: false)
.getDocuments()

guard let document = snapshot.documents.first else {
logger.error("Notification not found for todoId: \(todoId)")
Expand All @@ -265,6 +270,7 @@ private extension PushNotificationService {
query: PushNotificationQuery
) -> Query {
var firestoreQuery: Query = store.collection(FirestorePath.notifications(uid))
.whereField(PushNotificationFieldKey.isDeleted.rawValue, isEqualTo: false)

if let thresholdDate = query.timeFilter.thresholdDate {
firestoreQuery = firestoreQuery.whereField(
Expand All @@ -286,7 +292,7 @@ private extension PushNotificationService {
func makeNextCursor(from document: QueryDocumentSnapshot?) -> PushNotificationCursorDTO? {
guard
let document,
let receivedAt = document.data()[Key.receivedAt.rawValue] as? Timestamp else {
let receivedAt = document.data()[PushNotificationFieldKey.receivedAt.rawValue] as? Timestamp else {
return nil
}

Expand All @@ -298,16 +304,17 @@ private extension PushNotificationService {

func makeResponse(from snapshot: QueryDocumentSnapshot) -> PushNotificationResponse? {
let data = snapshot.data()
if data[Key.deletingAt.rawValue] is Timestamp {
if data[PushNotificationFieldKey.deletingAt.rawValue] is Timestamp ||
(data[PushNotificationFieldKey.isDeleted.rawValue] as? Bool) == true {
return nil
}
guard
let title = data[Key.title.rawValue] as? String,
let body = data[Key.body.rawValue] as? String,
let receivedAt = data[Key.receivedAt.rawValue] as? Timestamp,
let isRead = data[Key.isRead.rawValue] as? Bool,
let todoId = data[Key.todoId.rawValue] as? String,
let todoCategory = data[Key.todoCategory.rawValue] as? String else {
let title = data[PushNotificationFieldKey.title.rawValue] as? String,
let body = data[PushNotificationFieldKey.body.rawValue] as? String,
let receivedAt = data[PushNotificationFieldKey.receivedAt.rawValue] as? Timestamp,
let isRead = data[PushNotificationFieldKey.isRead.rawValue] as? Bool,
let todoId = data[PushNotificationFieldKey.todoId.rawValue] as? String,
let todoCategory = data[PushNotificationFieldKey.todoCategory.rawValue] as? String else {
return nil
}

Expand All @@ -322,13 +329,14 @@ private extension PushNotificationService {
)
}

enum Key: String {
enum PushNotificationFieldKey: String {
case title
case body
case receivedAt
case isRead
case todoId
case todoCategory
case deletingAt // 삭제 요청은 되었지만, 5초 유예 후 최종 삭제되기 전 상태
case deletingAt // 삭제 요청으로 앱의 로컬 데이터에서 deletion이 된 상태
case isDeleted // 삭제 요청으로 서버에서 soft deletion이 된 상태
}
}
22 changes: 17 additions & 5 deletions DevLog/Infra/Service/TodoService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,12 @@ final class TodoService {
logger.info("Fetching todo")

do {
let docRef = store.document(FirestorePath.todo(uid, todoId: todoId))
let snapshot = try await docRef.getDocument()
guard snapshot.exists, let todo = makeResponse(from: snapshot) else {
let snapshot = try await store.collection(FirestorePath.todos(uid))
.whereField(FieldPath.documentID(), isEqualTo: todoId)
.whereField(TodoFieldKey.isDeleted.rawValue, isEqualTo: false)
.limit(to: 1)
.getDocuments()
guard let document = snapshot.documents.first, let todo = makeResponse(from: document) else {
throw FirestoreError.dataNotFound("Todo")
}

Expand All @@ -253,6 +256,7 @@ final class TodoService {
group.addTask {
let snapshot = try await collection
.whereField(TodoFieldKey.number.rawValue, in: chunk)
.whereField(TodoFieldKey.isDeleted.rawValue, isEqualTo: false)
.getDocuments()
return snapshot.documents
}
Expand All @@ -269,6 +273,7 @@ final class TodoService {
let data = document.data()
guard
!(data[TodoFieldKey.deletingAt.rawValue] is Timestamp),
(data[TodoFieldKey.isDeleted.rawValue] as? Bool) != true,
let response = makeResponse(from: document)
else {
return
Expand Down Expand Up @@ -355,6 +360,7 @@ private extension TodoService {

func makeQuery(uid: String, query: TodoQuery) -> Query {
let collection = store.collection(FirestorePath.todos(uid))
.whereField(TodoFieldKey.isDeleted.rawValue, isEqualTo: false)

switch query.sortTarget {
case .dueDate:
Expand Down Expand Up @@ -426,7 +432,8 @@ private extension TodoService {
}

func makeResponse(from snapshot: QueryDocumentSnapshot) -> TodoResponse? {
if snapshot.data()[TodoFieldKey.deletingAt.rawValue] is Timestamp {
if snapshot.data()[TodoFieldKey.deletingAt.rawValue] is Timestamp ||
(snapshot.data()[TodoFieldKey.isDeleted.rawValue] as? Bool) == true {
return nil
}
return makeResponse(documentID: snapshot.documentID, data: snapshot.data())
Expand All @@ -440,6 +447,10 @@ private extension TodoService {
}

func makeResponse(documentID: String, data: [String: Any]) -> TodoResponse? {
if data[TodoFieldKey.deletingAt.rawValue] is Timestamp ||
(data[TodoFieldKey.isDeleted.rawValue] as? Bool) == true {
return nil
}
guard
let isPinned = data[TodoFieldKey.isPinned.rawValue] as? Bool,
let isCompleted = data[TodoFieldKey.isCompleted.rawValue] as? Bool,
Expand Down Expand Up @@ -487,7 +498,8 @@ private extension TodoService {
case dueDate
case tags
case category
case deletingAt // 삭제 요청은 되었지만, 5초 유예 후 최종 삭제되기 전 상태
case deletingAt // 삭제 요청으로 앱의 로컬 데이터에서 deletion이 된 상태
case isDeleted // 삭제 요청으로 서버에서 soft deletion이 된 상태
}

enum CounterFieldKey: String {
Expand Down
5 changes: 4 additions & 1 deletion DevLog/Infra/Service/WebPageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ final class WebPageService {

do {
let collectionRef = store.collection(FirestorePath.webPages(uid))
.whereField(WebPageFieldKey.isDeleted.rawValue, isEqualTo: false)
let snapshot = try await collectionRef.getDocuments()
let items: [WebPageResponse] = snapshot.documents.compactMap { makeResponse(from: $0) }

Expand Down Expand Up @@ -128,6 +129,7 @@ private extension WebPageService {
return nil
}
guard
(data[WebPageFieldKey.isDeleted.rawValue] as? Bool) != true,
let title = data[WebPageFieldKey.title.rawValue] as? String,
let url = data[WebPageFieldKey.url.rawValue] as? String,
let displayURL = data[WebPageFieldKey.displayURL.rawValue] as? String,
Expand All @@ -149,6 +151,7 @@ private extension WebPageService {
case url
case displayURL
case imageURL
case deletingAt // 삭제 요청은 되었지만, 5초 유예 후 최종 삭제되기 전 상태
case deletingAt // 삭제 요청으로 앱의 로컬 데이터에서 deletion이 된 상태
case isDeleted // 삭제 요청으로 서버에서 soft deletion이 된 상태
}
}
3 changes: 3 additions & 0 deletions Firebase/firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
]
}
],
"firestore": {
"indexes": "firestore.index.json"
},
"emulators": {
"functions": {
"port": 5001
Expand Down
Loading