-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWebPageRepositoryImpl.swift
More file actions
128 lines (109 loc) · 3.79 KB
/
Copy pathWebPageRepositoryImpl.swift
File metadata and controls
128 lines (109 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//
// WebPageRepositoryImpl.swift
// DevLog
//
// Created by 최윤진 on 2/8/26.
//
import Foundation
import UIKit
final class WebPageRepositoryImpl: WebPageRepository {
private let webPageService: WebPageService
private let metadataService: WebPageMetadataService
init(
webPageService: WebPageService,
metadataService: WebPageMetadataService
) {
self.webPageService = webPageService
self.metadataService = metadataService
}
func fetch(_ query: String) async throws -> [WebPage] {
let responses = try await webPageService.fetchWebPages(query)
var pages: [WebPage] = []
pages.reserveCapacity(responses.count)
for response in responses {
if await needsImageRestore(response) {
if let restored = try? await restoreWebPage(response) {
pages.append(restored)
} else if let page = try? responseWithoutImage(response).toDomain() {
pages.append(page)
}
continue
}
if let page = try? response.toDomain() {
pages.append(page)
}
}
return pages
}
func upsert(_ urlString: String) async throws {
let metadata = try await metadataService.fetchMetadata(from: urlString)
let request = WebPageRequest(
title: metadata.title,
url: urlString,
displayURL: metadata.displayURL,
imageURL: metadata.imageURL
)
try await webPageService.upsertWebPage(request)
}
func delete(_ urlString: String) async throws {
try await webPageService.deleteWebPage(urlString)
await metadataService.removeCachedImage(for: urlString)
}
func undoDelete(_ urlString: String) async throws {
try await webPageService.undoDeleteWebPage(urlString)
}
}
private extension WebPageRepositoryImpl {
func needsImageRestore(_ response: WebPageResponse) async -> Bool {
guard !response.imageURL.isEmpty,
let imageURL = URL(string: response.imageURL),
imageURL.isFileURL else {
return false
}
let expectedImageURL: URL
do {
expectedImageURL = try metadataService.cachedImageURL(for: response.url)
} catch {
return true
}
if imageURL.standardizedFileURL != expectedImageURL.standardizedFileURL {
return true
}
return await Task.detached(priority: .utility) {
guard FileManager.default.fileExists(atPath: imageURL.path) else {
return true
}
guard let imageData = try? Data(contentsOf: imageURL) else {
return true
}
return UIImage(data: imageData) == nil
}.value
}
func restoreWebPage(_ response: WebPageResponse) async throws -> WebPage? {
let metadata = try await metadataService.fetchMetadata(from: response.url)
let request = WebPageRequest(
title: metadata.title,
url: response.url,
displayURL: metadata.displayURL,
imageURL: metadata.imageURL
)
try await webPageService.upsertWebPage(request)
let newResponse = WebPageResponse(
id: response.id,
title: metadata.title,
url: response.url,
displayURL: metadata.displayURL,
imageURL: metadata.imageURL
)
return try? newResponse.toDomain()
}
func responseWithoutImage(_ response: WebPageResponse) -> WebPageResponse {
WebPageResponse(
id: response.id,
title: response.title,
url: response.url,
displayURL: response.displayURL,
imageURL: ""
)
}
}