Skip to content

Commit

Permalink
Merge pull request #86 from boostcampwm-2024/feature/manageWhiteboard
Browse files Browse the repository at this point in the history
[Feature] 화이트 보드 오브젝트/도구 관리 유즈케이스 추가
  • Loading branch information
taipaise authored Nov 16, 2024
2 parents 8ff0218 + 18aa284 commit dd7976b
Show file tree
Hide file tree
Showing 17 changed files with 515 additions and 44 deletions.
36 changes: 36 additions & 0 deletions Domain/Domain.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
0080E91A2CE4B0880095B958 /* DrawObjectUseCaseInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0080E9182CE4B0880095B958 /* DrawObjectUseCaseInterface.swift */; };
0080E9502CE4D8700095B958 /* Domain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B7C6E262CDB6A010024704A /* Domain.framework */; platformFilter = ios; };
0080E9582CE4D8760095B958 /* DrawObjectUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0080E9562CE4D8760095B958 /* DrawObjectUseCaseTests.swift */; };
00D2DD842CE8864B0089F0BA /* ManageWhiteboardObjectUseCaseInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD832CE8864B0089F0BA /* ManageWhiteboardObjectUseCaseInterface.swift */; };
00D2DD862CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD852CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift */; };
00D2DD882CE88BD80089F0BA /* ManageWhiteboardToolUseCaseInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD872CE88BD80089F0BA /* ManageWhiteboardToolUseCaseInterface.swift */; };
00D2DD8F2CE88C640089F0BA /* WhiteboardTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD8E2CE88C640089F0BA /* WhiteboardTool.swift */; };
00D2DD912CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD902CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift */; };
00D2DD932CE88EC70089F0BA /* ManageWhiteboardToolUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD922CE88EC70089F0BA /* ManageWhiteboardToolUseCaseTests.swift */; };
00D2DD952CE88EDA0089F0BA /* ManageWhiteboardObjectsUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D2DD942CE88EDA0089F0BA /* ManageWhiteboardObjectsUseCaseTests.swift */; };
5B6542482CE44631000168AD /* WhiteboardUseCaseInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6542472CE44631000168AD /* WhiteboardUseCaseInterface.swift */; };
5B7C6EB02CDB6C040024704A /* AirplaINFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B7C6EAF2CDB6C040024704A /* AirplaINFoundation.framework */; };
5B7C6EB12CDB6C040024704A /* AirplaINFoundation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5B7C6EAF2CDB6C040024704A /* AirplaINFoundation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -62,6 +69,13 @@
0080E9182CE4B0880095B958 /* DrawObjectUseCaseInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawObjectUseCaseInterface.swift; sourceTree = "<group>"; };
0080E94C2CE4D8700095B958 /* DomainTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DomainTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0080E9562CE4D8760095B958 /* DrawObjectUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DrawObjectUseCaseTests.swift; sourceTree = "<group>"; };
00D2DD832CE8864B0089F0BA /* ManageWhiteboardObjectUseCaseInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageWhiteboardObjectUseCaseInterface.swift; sourceTree = "<group>"; };
00D2DD852CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageWhiteboardObjectUseCase.swift; sourceTree = "<group>"; };
00D2DD872CE88BD80089F0BA /* ManageWhiteboardToolUseCaseInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageWhiteboardToolUseCaseInterface.swift; sourceTree = "<group>"; };
00D2DD8E2CE88C640089F0BA /* WhiteboardTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WhiteboardTool.swift; path = Domain/Sources/Model/WhiteboardTool.swift; sourceTree = SOURCE_ROOT; };
00D2DD902CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageWhiteboardToolUseCase.swift; sourceTree = "<group>"; };
00D2DD922CE88EC70089F0BA /* ManageWhiteboardToolUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageWhiteboardToolUseCaseTests.swift; sourceTree = "<group>"; };
00D2DD942CE88EDA0089F0BA /* ManageWhiteboardObjectsUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageWhiteboardObjectsUseCaseTests.swift; sourceTree = "<group>"; };
5B6542472CE44631000168AD /* WhiteboardUseCaseInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhiteboardUseCaseInterface.swift; sourceTree = "<group>"; };
5B7C6E262CDB6A010024704A /* Domain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Domain.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5B7C6EAF2CDB6C040024704A /* AirplaINFoundation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AirplaINFoundation.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -105,13 +119,16 @@
A8E97C062CE5E45500B28063 /* WhiteboardObjectSendUseCase.swift */,
A85260222CE343B20089DA5E /* ProfileUseCase.swift */,
5BDFD9392CE2EE3100DA4F5B /* WhiteboardUseCase.swift */,
00D2DD852CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift */,
00D2DD902CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift */,
);
path = UseCase;
sourceTree = "<group>";
};
0080E8592CE19EBD0095B958 /* Sources */ = {
isa = PBXGroup;
children = (
00D2DD962CE8A4DB0089F0BA /* Model */,
0080E8CB2CE4461F0095B958 /* Interface */,
0080E8B92CE2ECB50095B958 /* Entity */,
00683D702CE3A72F000D28E4 /* UseCase */,
Expand Down Expand Up @@ -166,6 +183,8 @@
A8E97C042CE5E3AB00B28063 /* ProfileUseCaseInterface.swift */,
6FBC909A2CE5A52B000FEB5A /* WhiteObjectSendUseCaseInterface.swift */,
5B6542472CE44631000168AD /* WhiteboardUseCaseInterface.swift */,
00D2DD832CE8864B0089F0BA /* ManageWhiteboardObjectUseCaseInterface.swift */,
00D2DD872CE88BD80089F0BA /* ManageWhiteboardToolUseCaseInterface.swift */,
);
path = UseCase;
sourceTree = "<group>";
Expand All @@ -174,10 +193,20 @@
isa = PBXGroup;
children = (
0080E9562CE4D8760095B958 /* DrawObjectUseCaseTests.swift */,
00D2DD922CE88EC70089F0BA /* ManageWhiteboardToolUseCaseTests.swift */,
00D2DD942CE88EDA0089F0BA /* ManageWhiteboardObjectsUseCaseTests.swift */,
);
path = DomainTests;
sourceTree = "<group>";
};
00D2DD962CE8A4DB0089F0BA /* Model */ = {
isa = PBXGroup;
children = (
00D2DD8E2CE88C640089F0BA /* WhiteboardTool.swift */,
);
path = Model;
sourceTree = "<group>";
};
5B7C6E1C2CDB6A010024704A = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -344,7 +373,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
00D2DD952CE88EDA0089F0BA /* ManageWhiteboardObjectsUseCaseTests.swift in Sources */,
0080E9582CE4D8760095B958 /* DrawObjectUseCaseTests.swift in Sources */,
00D2DD932CE88EC70089F0BA /* ManageWhiteboardToolUseCaseTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -362,12 +393,17 @@
5BDFD9342CE1F7DB00DA4F5B /* Whiteboard.swift in Sources */,
5BDFD9372CE2E6BC00DA4F5B /* WhiteboardRepositoryInterface.swift in Sources */,
5B6542482CE44631000168AD /* WhiteboardUseCaseInterface.swift in Sources */,
00D2DD842CE8864B0089F0BA /* ManageWhiteboardObjectUseCaseInterface.swift in Sources */,
00D2DD882CE88BD80089F0BA /* ManageWhiteboardToolUseCaseInterface.swift in Sources */,
0080E8CE2CE4463B0095B958 /* WhiteboardObjectRepositoryInterface.swift in Sources */,
0080E8BB2CE2ECD80095B958 /* WhiteboardObject.swift in Sources */,
6FBC909B2CE5A6AE000FEB5A /* WhiteObjectSendUseCaseInterface.swift in Sources */,
6F21477B2CE4CEAE00B55E2C /* TextObject.swift in Sources */,
00683D722CE3A74A000D28E4 /* DrawObjectUseCase.swift in Sources */,
00D2DD8F2CE88C640089F0BA /* WhiteboardTool.swift in Sources */,
0080E91A2CE4B0880095B958 /* DrawObjectUseCaseInterface.swift in Sources */,
00D2DD912CE88D260089F0BA /* ManageWhiteboardToolUseCase.swift in Sources */,
00D2DD862CE887540089F0BA /* ManageWhiteboardObjectUseCase.swift in Sources */,
00683D692CE37F2F000D28E4 /* DrawingObject.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,32 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5B25A3E32CDB68E500CB7B34"
BuildableName = "AirplaIN.app"
BlueprintName = "AirplaIN"
ReferencedContainer = "container:../AirplaIN/AirplaIN.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5B25A3E32CDB68E500CB7B34"
BuildableName = "AirplaIN.app"
BlueprintName = "AirplaIN"
ReferencedContainer = "container:../AirplaIN/AirplaIN.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
Expand Down
6 changes: 5 additions & 1 deletion Domain/Domain/Sources/Entity/WhiteboardObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//
import Foundation

public class WhiteboardObject {
public class WhiteboardObject: Equatable {
public let id: UUID
public var position: CGPoint
public var size: CGSize
Expand All @@ -20,4 +20,8 @@ public class WhiteboardObject {
self.position = position
self.size = size
}

public static func == (lhs: WhiteboardObject, rhs: WhiteboardObject) -> Bool {
return lhs.id == rhs.id
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// ManageWhiteboardObjectUseCaseInterface.swift
// Domain
//
// Created by 이동현 on 11/16/24.
//

import Combine

public protocol ManageWhiteboardObjectUseCaseInterface {
/// 화이트보드 객체가 추가될 때 이벤트를 방출합니다.
var addedObjectPublisher: AnyPublisher<WhiteboardObject, Never> { get }

/// 화이트보드 객체가 수정될 때 이벤트를 방출합니다.
var updatedObjectPublisher: AnyPublisher<WhiteboardObject, Never> { get }

/// 화이트보드 객체가 제거될 때 이벤트를 방출합니다.
var removedObjectPublisher: AnyPublisher<WhiteboardObject, Never> { get }

/// 화이트보드 객체를 추가하는 메서드
/// - Parameter whiteboardObject: 추가할 화이트보드 객체
/// - Returns: 추가 성공 여부
func addObject(whiteboardObject: WhiteboardObject) -> Bool

/// 화이트보드 객체를 수정하는 메서드
/// - Parameter whiteboardObject: 수정할 화이트보드 객체
/// - Returns: 추가 성공 여부
func updateObject(whiteboardObject: WhiteboardObject) -> Bool

/// 화이트보드를 제거하는 메서드
/// - Returns: 추가 성공 여부
func removeObject(whiteboardObject: WhiteboardObject) -> Bool
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// ManageWhiteboardToolUseCaseInterface.swift
// Domain
//
// Created by 이동현 on 11/16/24.
//

import Combine

public protocol ManageWhiteboardToolUseCaseInterface {
/// 화이트보드 도구 선택/선택 해제 시 이벤트를 방출합니다.
var currentToolPublisher: AnyPublisher<WhiteboardTool?, Never> { get }

/// 현재 사용중인 화이트보드 도구를 반환합니다.
/// - Returns: 사용중인 화이트보드 도구
func currentTool() -> WhiteboardTool?

/// 화이트보드 도구를 선택합니다.
/// - Parameter tool: 선택할 화이트보드 도구
func selectTool(tool: WhiteboardTool)

/// 화이트보드 도구 사용을 완료합니다.
func finishUsingTool()
}
15 changes: 15 additions & 0 deletions Domain/Domain/Sources/Model/WhiteboardTool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// WhiteboardTool.swift
// Domain
//
// Created by 이동현 on 11/16/24.
//

@frozen
public enum WhiteboardTool: CaseIterable {
case drawing
case text
case photo
case game
case chat
}
2 changes: 1 addition & 1 deletion Domain/Domain/Sources/UseCase/DrawObjectUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public final class DrawObjectUseCase: DrawObjectUseCaseInterface {
public private(set) var points: [CGPoint]
public private(set) var origin: CGPoint?

public init(repository: WhiteboardObjectRepositoryInterface) {
public init() {
points = []
}

Expand Down
52 changes: 52 additions & 0 deletions Domain/Domain/Sources/UseCase/ManageWhiteboardObjectUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// ManageWhiteboardObjectUseCase.swift
// Domain
//
// Created by 이동현 on 11/16/24.
//

import Combine

public final class ManageWhiteboardObjectUseCase: ManageWhiteboardObjectUseCaseInterface {
public var addedObjectPublisher: AnyPublisher<WhiteboardObject, Never>
public var updatedObjectPublisher: AnyPublisher<WhiteboardObject, Never>
public var removedObjectPublisher: AnyPublisher<WhiteboardObject, Never>
private var whiteboardObjects: [WhiteboardObject]

private let addedWhiteboardSubject: PassthroughSubject<WhiteboardObject, Never>
private let updatedWhiteboardSubject: PassthroughSubject<WhiteboardObject, Never>
private let removedWhiteboardSubject: PassthroughSubject<WhiteboardObject, Never>

public init() {
addedWhiteboardSubject = PassthroughSubject<WhiteboardObject, Never>()
updatedWhiteboardSubject = PassthroughSubject<WhiteboardObject, Never>()
removedWhiteboardSubject = PassthroughSubject<WhiteboardObject, Never>()

whiteboardObjects = []

addedObjectPublisher = addedWhiteboardSubject.eraseToAnyPublisher()
updatedObjectPublisher = updatedWhiteboardSubject.eraseToAnyPublisher()
removedObjectPublisher = removedWhiteboardSubject.eraseToAnyPublisher()
}

public func addObject(whiteboardObject: WhiteboardObject) -> Bool {
guard !whiteboardObjects.contains(whiteboardObject) else { return false }
whiteboardObjects.append(whiteboardObject)
addedWhiteboardSubject.send(whiteboardObject)
return true
}

public func updateObject(whiteboardObject: WhiteboardObject) -> Bool {
guard let index = whiteboardObjects.firstIndex(where: { $0 == whiteboardObject }) else { return false }
whiteboardObjects[index] = whiteboardObject
updatedWhiteboardSubject.send(whiteboardObject)
return true
}

public func removeObject(whiteboardObject: WhiteboardObject) -> Bool {
guard whiteboardObjects.contains(whiteboardObject) else { return false }
whiteboardObjects.removeAll { $0 == whiteboardObject }
removedWhiteboardSubject.send(whiteboardObject)
return true
}
}
30 changes: 30 additions & 0 deletions Domain/Domain/Sources/UseCase/ManageWhiteboardToolUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ManageWhiteboardToolUseCase.swift
// Domain
//
// Created by 이동현 on 11/16/24.
//

import Combine

public final class ManageWhiteboardToolUseCase: ManageWhiteboardToolUseCaseInterface {
public var currentToolPublisher: AnyPublisher<WhiteboardTool?, Never>
private let currentToolSubject: CurrentValueSubject<WhiteboardTool?, Never>

public init() {
currentToolSubject = CurrentValueSubject<WhiteboardTool?, Never>(nil)
currentToolPublisher = currentToolSubject.eraseToAnyPublisher()
}

public func currentTool() -> WhiteboardTool? {
return currentToolSubject.value
}

public func selectTool(tool: WhiteboardTool) {
currentToolSubject.send(tool)
}

public func finishUsingTool() {
currentToolSubject.send(nil)
}
}
5 changes: 1 addition & 4 deletions Domain/DomainTests/DrawObjectUseCaseTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ import XCTest

final class DrawObjectUseCaseTests: XCTestCase {
var useCase: DrawObjectUseCaseInterface!
var mockRepository: WhiteboardObjectRepositoryInterface!

override func setUpWithError() throws {
mockRepository = MockWhiteboardObjectRepository()
useCase = DrawObjectUseCase(repository: mockRepository)
useCase = DrawObjectUseCase()
}

override func tearDownWithError() throws {
mockRepository = nil
useCase = nil
}

Expand Down
Loading

0 comments on commit dd7976b

Please sign in to comment.