Skip to content

Commit

Permalink
feature: 사진 추가 유즈케이스 설계 및 구현(#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
taipaise committed Nov 18, 2024
1 parent 81e95bc commit dcf4aca
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 0 deletions.
24 changes: 24 additions & 0 deletions Domain/Domain.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

/* Begin PBXBuildFile section */
003D5A2B2CEB1FF0005F3D09 /* PhotoObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 003D5A2A2CEB1FEA005F3D09 /* PhotoObject.swift */; };
003D5A2D2CEB21AA005F3D09 /* AddPhotoUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 003D5A2C2CEB217E005F3D09 /* AddPhotoUseCase.swift */; };
003D5A2F2CEB21B6005F3D09 /* AddPhotoUseCaseInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 003D5A2E2CEB21B2005F3D09 /* AddPhotoUseCaseInterface.swift */; };
004B217D2CEB2B2300A5BEB8 /* DomainError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004B217C2CEB2B2300A5BEB8 /* DomainError.swift */; };
004B217F2CEB2F6300A5BEB8 /* AirplaINImageData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004B217E2CEB2F6300A5BEB8 /* AirplaINImageData.swift */; };
00683D692CE37F2F000D28E4 /* DrawingObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00683D682CE37F2F000D28E4 /* DrawingObject.swift */; };
00683D722CE3A74A000D28E4 /* DrawObjectUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00683D712CE3A74A000D28E4 /* DrawObjectUseCase.swift */; };
0080E8BB2CE2ECD80095B958 /* WhiteboardObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0080E8BA2CE2ECC60095B958 /* WhiteboardObject.swift */; };
Expand Down Expand Up @@ -64,6 +68,10 @@

/* Begin PBXFileReference section */
003D5A2A2CEB1FEA005F3D09 /* PhotoObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoObject.swift; sourceTree = "<group>"; };
003D5A2C2CEB217E005F3D09 /* AddPhotoUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddPhotoUseCase.swift; sourceTree = "<group>"; };
003D5A2E2CEB21B2005F3D09 /* AddPhotoUseCaseInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddPhotoUseCaseInterface.swift; sourceTree = "<group>"; };
004B217C2CEB2B2300A5BEB8 /* DomainError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainError.swift; sourceTree = "<group>"; };
004B217E2CEB2F6300A5BEB8 /* AirplaINImageData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirplaINImageData.swift; sourceTree = "<group>"; };
00683D682CE37F2F000D28E4 /* DrawingObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawingObject.swift; sourceTree = "<group>"; };
00683D712CE3A74A000D28E4 /* DrawObjectUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawObjectUseCase.swift; sourceTree = "<group>"; };
0080E8BA2CE2ECC60095B958 /* WhiteboardObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhiteboardObject.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -114,6 +122,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
004B217B2CEB2B0B00A5BEB8 /* Common */ = {
isa = PBXGroup;
children = (
004B217C2CEB2B2300A5BEB8 /* DomainError.swift */,
);
path = Common;
sourceTree = "<group>";
};
00683D702CE3A72F000D28E4 /* UseCase */ = {
isa = PBXGroup;
children = (
Expand All @@ -123,13 +139,15 @@
5BDFD9392CE2EE3100DA4F5B /* WhiteboardUseCase.swift */,
00D2DD852CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift */,
00D2DD902CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift */,
003D5A2C2CEB217E005F3D09 /* AddPhotoUseCase.swift */,
);
path = UseCase;
sourceTree = "<group>";
};
0080E8592CE19EBD0095B958 /* Sources */ = {
isa = PBXGroup;
children = (
004B217B2CEB2B0B00A5BEB8 /* Common */,
00D2DD962CE8A4DB0089F0BA /* Model */,
0080E8CB2CE4461F0095B958 /* Interface */,
0080E8B92CE2ECB50095B958 /* Entity */,
Expand All @@ -156,6 +174,7 @@
0080E8BA2CE2ECC60095B958 /* WhiteboardObject.swift */,
00683D682CE37F2F000D28E4 /* DrawingObject.swift */,
003D5A2A2CEB1FEA005F3D09 /* PhotoObject.swift */,
004B217E2CEB2F6300A5BEB8 /* AirplaINImageData.swift */,
);
path = Entity;
sourceTree = "<group>";
Expand Down Expand Up @@ -188,6 +207,7 @@
5B6542472CE44631000168AD /* WhiteboardUseCaseInterface.swift */,
00D2DD832CE8864B0089F0BA /* ManageWhiteboardObjectUseCaseInterface.swift */,
00D2DD872CE88BD80089F0BA /* ManageWhiteboardToolUseCaseInterface.swift */,
003D5A2E2CEB21B2005F3D09 /* AddPhotoUseCaseInterface.swift */,
);
path = UseCase;
sourceTree = "<group>";
Expand Down Expand Up @@ -386,7 +406,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
003D5A2F2CEB21B6005F3D09 /* AddPhotoUseCaseInterface.swift in Sources */,
A8E97C052CE5E3AB00B28063 /* ProfileUseCaseInterface.swift in Sources */,
004B217D2CEB2B2300A5BEB8 /* DomainError.swift in Sources */,
A8E97BDB2CE5A6D500B28063 /* ProfileRepositoryInterface.swift in Sources */,
A8E97BD92CE5A6B800B28063 /* ProfileIcon.swift in Sources */,
A8E97C072CE5E45500B28063 /* WhiteboardObjectSendUseCase.swift in Sources */,
Expand All @@ -403,9 +425,11 @@
0080E8BB2CE2ECD80095B958 /* WhiteboardObject.swift in Sources */,
6FBC909B2CE5A6AE000FEB5A /* WhiteObjectSendUseCaseInterface.swift in Sources */,
6F21477B2CE4CEAE00B55E2C /* TextObject.swift in Sources */,
004B217F2CEB2F6300A5BEB8 /* AirplaINImageData.swift in Sources */,
00683D722CE3A74A000D28E4 /* DrawObjectUseCase.swift in Sources */,
00D2DD8F2CE88C640089F0BA /* WhiteboardTool.swift in Sources */,
0080E91A2CE4B0880095B958 /* DrawObjectUseCaseInterface.swift in Sources */,
003D5A2D2CEB21AA005F3D09 /* AddPhotoUseCase.swift in Sources */,
00D2DD912CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift in Sources */,
00D2DD862CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift in Sources */,
00683D692CE37F2F000D28E4 /* DrawingObject.swift in Sources */,
Expand Down
27 changes: 27 additions & 0 deletions Domain/Domain/Sources/Common/DomainError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// DomainError.swift
// Domain
//
// Created by 이동현 on 11/18/24.
//

import Foundation

public enum DomainError {
case cannotWriteFile
case cannotCreateDirectory
case cannotFindDirectory
}

extension DomainError: LocalizedError {
public var errorDescription: String? {
switch self {
case .cannotWriteFile:
return "파일을 쓸 수 없습니다."
case .cannotCreateDirectory:
return "디렉터리를 생성할 수 없습니다."
case .cannotFindDirectory:
return "디렉터리를 찾을 수 없습니다."
}
}
}
24 changes: 24 additions & 0 deletions Domain/Domain/Sources/Entity/AirplaINImageData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// AirplaINImageData.swift
// Domain
//
// Created by 이동현 on 11/18/24.
//

import Foundation

public struct AirplaINImageData {
let width: CGFloat
let height: CGFloat
let imageData: Data

public init(
width: CGFloat,
height: CGFloat,
imageData: Data
) {
self.width = width
self.height = height
self.imageData = imageData
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// AddPhotoUseCaseInterface.swift
// Domain
//
// Created by 이동현 on 11/18/24.
//

import Foundation

public protocol AddPhotoUseCaseInterface {

/// 사진 오브젝트를 추가합니다.
/// - Parameters:
/// - imageData: 추가할 사진의 데이터
/// - position: 사진을 추가할 위치 (origin)
/// - size: 사진 객체
/// - Returns:
func addPhoto(
airplainImageData: AirplaINImageData,
position: CGPoint
) throws -> PhotoObject
}
55 changes: 55 additions & 0 deletions Domain/Domain/Sources/UseCase/AddPhotoUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// AddPhotoUseCase.swift
// Domain
//
// Created by 이동현 on 11/18/24.
//

import Foundation

public final class AddPhotoUseCase: AddPhotoUseCaseInterface {
private let fileManager: FileManager
private let photoDirectory: URL

public init(fileManager: FileManager) throws {
self.fileManager = fileManager
guard
let documentDirectory = fileManager
.urls(for: .documentDirectory, in: .userDomainMask)
.first
else { throw DomainError.cannotCreateDirectory }
photoDirectory = documentDirectory.appending(path: "photos")

if !fileManager.fileExists(atPath: photoDirectory.path()) {
do {
try fileManager.createDirectory(at: photoDirectory, withIntermediateDirectories: true)
} catch {
throw DomainError.cannotCreateDirectory
}
}
}

public func addPhoto(
airplainImageData: AirplaINImageData,
position: CGPoint
) throws -> PhotoObject {
let uuid = UUID()
let photoname = "\(uuid.uuidString).jpg"
let photoURL = photoDirectory.appending(path: photoname)
let imageSize = CGSize(width: airplainImageData.width, height: airplainImageData.height)

do {
try airplainImageData.imageData.write(to: photoURL)
} catch {
throw DomainError.cannotWriteFile
}

let photoObject = PhotoObject(
id: uuid,
position: position,
size: imageSize,
photoURL: photoURL)

return photoObject
}
}

0 comments on commit dcf4aca

Please sign in to comment.