-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
책 수정 화면 로직 구현 #113
책 수정 화면 로직 구현 #113
Changes from all commits
d57ec45
071f402
3a59a31
b6e6d83
977d300
0e5cae0
c9a5465
b86d39d
24fc2dd
9d8fb5f
c6571b9
6627556
08e4eea
5637107
1478723
d9407a2
218cba7
e3c1865
a50363d
533a457
b13a005
84c8220
40438b5
0aa8f67
230d7bc
1ff40f2
3d43247
bd0f4b4
667b01c
56ddcf1
3bb9487
6f334c5
e98544d
acfa79f
e4f2f0e
2c6e872
2aad98f
d8ae689
2aa3cdc
fefb2e3
73cf917
165df54
09e3f66
961e538
2bc516a
43c4a1a
7cefd53
878ebf3
b63dede
4e6f1e0
6c475ec
47ead38
54358d3
340a3cf
9a136aa
d60becb
68a2b0d
ad14f84
d019cfe
bb0924c
3f66fd0
4159dc3
7a2a84a
201c1cf
61a2d60
2b6bfb6
260a00e
604cbc9
8b263d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
import MHFoundation | ||
import MHCore | ||
|
||
struct MHFileManager { | ||
private let fileManager = FileManager.default | ||
public struct MHFileManager: Sendable { | ||
private var fileManager: FileManager { FileManager.default } | ||
private let directoryType: FileManager.SearchPathDirectory | ||
|
||
init(directoryType: FileManager.SearchPathDirectory) { | ||
public init(directoryType: FileManager.SearchPathDirectory) { | ||
self.directoryType = directoryType | ||
} | ||
} | ||
|
||
extension MHFileManager: FileStorage { | ||
func create(at path: String, fileName name: String, data: Data) async -> Result<Void, MHDataError> { | ||
public func create(at path: String, fileName name: String, data: Data) async -> Result<Void, MHDataError> { | ||
guard let directory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -22,13 +22,13 @@ | |
|
||
do { | ||
try fileManager.createDirectory(at: directory, withIntermediateDirectories: true) | ||
try data.write(to: dataPath) | ||
try data.write(to: dataPath, options: .atomic) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: 해당 option은 어떤걸 뜻하는 것인가욥?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저장할 때 임시파일 만들었다가 저장이 완료되면 실제 파일로 바뀌는 옵션입니다! |
||
return .success(()) | ||
} catch { | ||
return .failure(.fileCreationFailure) | ||
} | ||
} | ||
func read(at path: String, fileName name: String) async -> Result<Data, MHDataError> { | ||
public func read(at path: String, fileName name: String) async -> Result<Data, MHDataError> { | ||
guard let directory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -47,7 +47,7 @@ | |
return .failure(.fileReadingFailure) | ||
} | ||
} | ||
func delete(at path: String, fileName name: String) async -> Result<Void, MHDataError> { | ||
public func delete(at path: String, fileName name: String) async -> Result<Void, MHDataError> { | ||
guard let directory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -63,7 +63,7 @@ | |
return .failure(.fileDeletionFailure) | ||
} | ||
} | ||
func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result<Void, MHDataError> { | ||
public func copy(at url: URL, to newPath: String, newFileName name: String) async -> Result<Void, MHDataError> { | ||
let originDataPath = url | ||
|
||
guard fileManager.fileExists(atPath: originDataPath.path) else { | ||
|
@@ -86,7 +86,7 @@ | |
return .failure(.fileMovingFailure) | ||
} | ||
} | ||
func copy(at path: String, fileName name: String, to newPath: String) async -> Result<Void, MHDataError> { | ||
public func copy(at path: String, fileName name: String, to newPath: String) async -> Result<Void, MHDataError> { | ||
guard let originDirectory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -115,7 +115,7 @@ | |
return .failure(.fileMovingFailure) | ||
} | ||
} | ||
func move(at path: String, fileName name: String, to newPath: String) async -> Result<Void, MHDataError> { | ||
public func move(at path: String, fileName name: String, to newPath: String) async -> Result<Void, MHDataError> { | ||
guard let originDirectory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -144,7 +144,7 @@ | |
return .failure(.fileMovingFailure) | ||
} | ||
} | ||
func moveAll(in path: String, to newPath: String) async -> Result<Void, MHDataError> { | ||
public func moveAll(in path: String, to newPath: String) async -> Result<Void, MHDataError> { | ||
guard let originDirectory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -174,7 +174,7 @@ | |
return .failure(.fileMovingFailure) | ||
} | ||
} | ||
func getURL(at path: String, fileName name: String) async -> Result<URL, MHDataError> { | ||
public func getURL(at path: String, fileName name: String) async -> Result<URL, MHDataError> { | ||
guard let originDirectory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
|
@@ -185,5 +185,19 @@ | |
|
||
return .success(originDataPath) | ||
} | ||
public func getFileNames(at path: String) async -> Result<[String], MHDataError> { | ||
guard let originDirectory = fileManager.urls( | ||
for: directoryType, | ||
in: .userDomainMask | ||
).first?.appending(path: path) | ||
Comment on lines
+189
to
+192
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 메서드는 어떤뜻인지 궁금합니다 ! userDomainMask는 어떤 옵션인지 궁금해요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. urls(for:in:)메스드에서 저희는 ~/Document를 사용한다고 코딩해놓은 것입니다! 문서가 더 잘 설명되어있으니 한번 보셔도 좋을 것같아요! |
||
else { return .failure(.directorySettingFailure) } | ||
|
||
do { | ||
let files = try fileManager.contentsOfDirectory(atPath: originDirectory.path) | ||
return .success(files) | ||
} catch { | ||
return .failure(.fileNotExists) | ||
} | ||
} | ||
} | ||
|
||
Check warning on line 203 in MemorialHouse/MHData/MHData/LocalStorage/FileManager/MHFileManager.swift GitHub Actions / SwiftLint
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,11 @@ | |
import MHCore | ||
import AVFoundation | ||
|
||
// TODO: nil이라면 바로 error를 return하도록 수정 | ||
Check warning on line 7 in MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift GitHub Actions / SwiftLint
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 나중에 해도 될까요...하하하....ㅠ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 당근이져.. 여기서 더 추가되는건...저도 원치 않아요...... |
||
public struct LocalMediaRepository: MediaRepository { | ||
public struct LocalMediaRepository: MediaRepository, Sendable { | ||
private let storage: FileStorage | ||
private let temporaryPath = "temp" // TODO: - 지워질 것임! | ||
Check warning on line 10 in MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift GitHub Actions / SwiftLint
|
||
private let snapshotFileName = ".snapshot" | ||
|
||
public init(storage: FileStorage) { | ||
self.storage = storage | ||
|
@@ -18,34 +20,33 @@ | |
to bookID: UUID? | ||
) async -> Result<Void, MHDataError> { | ||
let path = bookID == nil | ||
? "temp" | ||
? temporaryPath | ||
: bookID!.uuidString | ||
let fileName = mediaDescription.id.uuidString | ||
let fileName = fileName(of: mediaDescription) | ||
|
||
return await storage.create(at: path, fileName: fileName, data: data) | ||
} | ||
|
||
public func create( | ||
media mediaDescription: MediaDescription, | ||
from: URL, | ||
to bookID: UUID? | ||
) async -> Result<Void, MHDataError> { | ||
let path = bookID == nil | ||
? "temp" | ||
? temporaryPath | ||
: bookID!.uuidString | ||
let fileName = mediaDescription.id.uuidString | ||
let fileName = fileName(of: mediaDescription) | ||
|
||
return await storage.copy(at: from, to: path, newFileName: fileName) | ||
} | ||
|
||
public func read( | ||
public func fetch( | ||
media mediaDescription: MediaDescription, | ||
from bookID: UUID? | ||
) async -> Result<Data, MHDataError> { | ||
let path = bookID == nil | ||
? "temp" | ||
? temporaryPath | ||
: bookID!.uuidString | ||
let fileName = mediaDescription.id.uuidString | ||
let fileName = fileName(of: mediaDescription) | ||
|
||
return await storage.read(at: path, fileName: fileName) | ||
} | ||
|
@@ -55,9 +56,9 @@ | |
at bookID: UUID? | ||
) async -> Result<Void, MHDataError> { | ||
let path = bookID == nil | ||
? "temp" | ||
? temporaryPath | ||
: bookID!.uuidString | ||
let fileName = mediaDescription.id.uuidString | ||
let fileName = fileName(of: mediaDescription) | ||
|
||
return await storage.delete(at: path, fileName: fileName) | ||
} | ||
|
@@ -77,16 +78,49 @@ | |
from bookID: UUID? | ||
) async -> Result<URL, MHDataError> { | ||
let path = bookID == nil | ||
? "temp" | ||
? temporaryPath | ||
: bookID!.uuidString | ||
let fileName = mediaDescription.id.uuidString | ||
let fileName = fileName(of: mediaDescription) | ||
|
||
return await storage.getURL(at: path, fileName: fileName) | ||
} | ||
|
||
public func moveAllTemporaryMedia(to bookID: UUID) async -> Result<Void, MHDataError> { | ||
let path = bookID.uuidString | ||
|
||
return await storage.moveAll(in: "temp", to: path) | ||
return await storage.moveAll(in: temporaryPath, to: path) | ||
} | ||
|
||
// MARK: - Snpashot | ||
public func createSnapshot(for media: [MediaDescription], in bookID: UUID) async -> Result<Void, MHDataError> { | ||
let path = bookID.uuidString | ||
let mediaList = media.map { fileName(of: $0) } | ||
guard let snapshot = try? JSONEncoder().encode(mediaList) | ||
else { return .failure(.snapshotEncodingFailure) } | ||
|
||
return await storage.create(at: path, fileName: snapshotFileName, data: snapshot) | ||
} | ||
Comment on lines
+95
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 미디어 데이터를 저장하는 코드로 보이는데 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 편집뷰에서 수정완려/저장 버튼을 눌렀을 때 호출됩니다! |
||
public func deleteMediaBySnapshot(for bookID: UUID) async -> Result<Void, MHDataError> { | ||
let path = bookID.uuidString | ||
|
||
do { | ||
let snapshotData = try await storage.read(at: path, fileName: snapshotFileName).get() | ||
let mediaSet = Set<String>(try JSONDecoder().decode([String].self, from: snapshotData)) | ||
// snapshot 파일은 제외 | ||
let currentFiles = Set<String>(try await storage.getFileNames(at: path).get()).subtracting([snapshotFileName]) | ||
Check warning on line 110 in MemorialHouse/MHData/MHData/Repository/LocalMediaRepository.swift GitHub Actions / SwiftLint
|
||
let shouldDelete = currentFiles.subtracting(mediaSet) | ||
for fileName in shouldDelete { | ||
_ = try await storage.delete(at: path, fileName: fileName).get() | ||
} | ||
return .success(()) | ||
} catch let error as MHDataError { | ||
return .failure(error) | ||
} catch { | ||
return .failure(.generalFailure) | ||
} | ||
} | ||
// MARK: - Helper | ||
private func fileName(of media: MediaDescription) -> String { | ||
return media.id.uuidString + media.type.defaultFileExtension | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
연산 프로퍼티로 하신 이유가 있나요 ?
연산 프로퍼티는 접근할 때마다 매번 새로 호출되는 걸로 아는데, 이 경우
private let fileManager = FileManager.default
가 더 괜찮지 않은지 질문 드립니다 !!만약 테스트를 할 거면 생성자 시점에서 주입 받아도 괜찮구요