Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,19 @@ public final class HomeCoordinator: BaseCoordinator {
self.delegate?.homeCoordinator(self, to: .deepLink(url: url))
}

homeForMember.vm.onSurveyButtonTapped = { [weak self] url in
guard let self else { return }
self.delegate?.homeCoordinator(self, to: .webLink(url: url))
}

// homeForMember.vm.onSurveyButtonTapped = { [weak self] url in
// guard let self else { return }
// self.delegate?.homeCoordinator(self, to: .webLink(url: url))
// }


//TODO: - DeepLink 테스트이후 제거
homeForMember.vm.onSurveyButtonTapped = { [weak self] _ in
guard let self else { return }
let testLink = "home/soptamp/entire-part-ranking/part-ranking/missions/missionDetail?part=ANDROID&nickname=안드박찬미&id=292&isMine=true"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

길긴 길다 ㅋㅋㅋㅋ

self.delegate?.homeCoordinator(self, to: .deepLink(url: testLink))
}

homeForMember.vm.onSocialLinkButtonTapped = { [weak self] url in
guard let self else { return }
self.delegate?.homeCoordinator(self, to: .webLink(url: url))
Expand Down Expand Up @@ -179,3 +187,4 @@ public final class HomeCoordinator: BaseCoordinator {
navigationController?.pushViewController(homeForVisitor.vc, animated: true)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import StampFeature

public struct SoptampDeepLink: DeepLinkExecutable {
public let name = "soptamp"
public let children: [DeepLinkExecutable] = [SoptampEntireRankingDeepLink(), SoptampCurrentGenerationRankingDeepLink()]
public let children: [DeepLinkExecutable] = [SoptampEntireRankingDeepLink(), SoptampCurrentGenerationRankingDeepLink(), SoptampEntirePartRankingDeepLink()]
public var isDestination: Bool = false

public func execute(with coordinator: Coordinator, queryItems: [URLQueryItem]?) -> Coordinator? {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// SoptampEntirePartRankingDeepLink.swift
// StampFeature
//
// Created by 성현주 on 10/20/25.
// Copyright © 2025 SOPT-iOS. All rights reserved.
//


import Foundation
import BaseFeatureDependency
import Core

public struct SoptampEntirePartRankingDeepLink: DeepLinkExecutable {
public let name = "entire-part-ranking"
public let children: [DeepLinkExecutable] = [SoptampPartRankingDeepLink()]
public var isDestination: Bool = false

public init() {}

public func execute(with coordinator: Coordinator, queryItems: [URLQueryItem]?) -> Coordinator? {
switch Config.coordinatorFlag {
case .legacy:
guard let coordinator = coordinator as? LegacyStampCoordinator else { return nil }
coordinator.runRankingFlow(rankingViewType: .partRanking)
case .new:
guard let coordinator = coordinator as? StampCoordinator else { return nil }
coordinator.runRankingFlow(rankingViewType: .partRanking)
}
return coordinator
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// SoptampMissionDetailDeepLink.swift
// StampFeature
//
// Created by 성현주 on 10/21/25.
// Copyright © 2025 SOPT-iOS. All rights reserved.
//

import Foundation
import BaseFeatureDependency
import Core

public struct SoptampMissionDetailDeepLink: DeepLinkExecutable {
public let name = "missionDetail"
public let children: [DeepLinkExecutable] = []
public var isDestination: Bool = true

public init() {}

public func execute(with coordinator: Coordinator, queryItems: [URLQueryItem]?) -> Coordinator? {
guard let idString = queryItems?.getQueryValue(key: "id"),
let missionId = Int(idString) else {
return nil
}

let nickname = queryItems?.getQueryValue(key: "nickname")

switch Config.coordinatorFlag {
case .legacy:
guard let coordinator = coordinator as? LegacyStampCoordinator else {
return nil
}

case .new:
guard let coordinator = coordinator as? StampCoordinator else {
return nil
}
coordinator.runMissionDetailById(missionId: missionId, username: nickname)
}
return coordinator
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// SoptampPartMissionListDeepLink.swift
// StampFeature
//
// Created by 성현주 on 10/21/25.
// Copyright © 2025 SOPT-iOS. All rights reserved.
//
Comment on lines +1 to +7
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

파일명 불일치

헤더 주석의 파일명이 실제 파일명과 다릅니다.

  • 주석: SoptampPartMissionListDeepLink.swift
  • 실제: SoptampMissionListDeepLink.swift
 //
-//  SoptampPartMissionListDeepLink.swift
+//  SoptampMissionListDeepLink.swift
 //  StampFeature
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//
// SoptampPartMissionListDeepLink.swift
// StampFeature
//
// Created by 성현주 on 10/21/25.
// Copyright © 2025 SOPT-iOS. All rights reserved.
//
//
// SoptampMissionListDeepLink.swift
// StampFeature
//
// Created by 성현주 on 10/21/25.
// Copyright © 2025 SOPT-iOS. All rights reserved.
//
🤖 Prompt for AI Agents
In
SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/DeepLinks/SoptampMissionListDeepLink.swift
around lines 1 to 7, the header comment's filename
(SoptampPartMissionListDeepLink.swift) does not match the actual file name
(SoptampMissionListDeepLink.swift); update the header comment to use the correct
filename so the top-of-file comment matches the real file name exactly.


import Foundation
import BaseFeatureDependency
import Core

public struct SoptampMissionListDeepLink: DeepLinkExecutable {
public let name = "missions"
public let children: [DeepLinkExecutable] = [SoptampMissionDetailDeepLink()]
public var isDestination: Bool = false

public init() {}

public func execute(with coordinator: Coordinator, queryItems: [URLQueryItem]?) -> Coordinator? {

guard let username = queryItems?.getQueryValue(key: "nickname"), !username.isEmpty else {
return nil
}

let sentence = queryItems?.getQueryValue(key: "sentence") ?? ""

switch Config.coordinatorFlag {
case .legacy:
guard let coordinator = coordinator as? LegacyStampCoordinator else { return nil }
case .new:
guard let coordinator = coordinator as? StampCoordinator else { return nil }
coordinator.runOtherMissionList(username: username, sentence: sentence)
}
return coordinator
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// SoptampPartRankingDeepLink.swift
// StampFeature
//
// Created by 성현주 on 10/20/25.
// Copyright © 2025 SOPT-iOS. All rights reserved.
//

import Foundation
import BaseFeatureDependency
import Core

public struct SoptampPartRankingDeepLink: DeepLinkExecutable {
public let name = "part-ranking"
public let children: [DeepLinkExecutable] = [SoptampMissionListDeepLink()]
public var isDestination: Bool = false

public init() {}

public func execute(with coordinator: Coordinator, queryItems: [URLQueryItem]?) -> Coordinator? {

guard let partString = queryItems?.getQueryValue(key: "part") else {
return coordinator
}

guard let part = Part.allCases.first(where: {
$0.uppercasedName() == partString.uppercased()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 디테일하네요

}) else {
print("[DeepLink][Soptamp][Error] Invalid part parameter: \(partString)")
return coordinator
}

switch Config.coordinatorFlag {
case .legacy:
guard let coordinator = coordinator as? LegacyStampCoordinator else { return nil }
coordinator.runRankingFlow(rankingViewType: .individualRankingInPart(part: part))
case .new:
guard let coordinator = coordinator as? StampCoordinator else { return nil }
coordinator.runRankingFlow(rankingViewType: .individualRankingInPart(part: part))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

분기까지 굿! 근데 이제 coordinatorFlag 들어가보면 알겠지만 legacy 쪽은 안 쓰긴 해요

}

return coordinator
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,20 @@ public final class StampCoordinator: BaseCoordinator {
// MARK: - MissionDetailFlow

extension StampCoordinator {
public func runOtherMissionList(username: String, sentence: String) {
showOtherMissionList(username, sentence)
}

public func runMissionDetailById(missionId: Int, username: String?) {
let model = MissionListModel(
id: missionId,
title: "",
level: 1,
isCompleted: true
)
showMissionDetail(model, username)
}
Comment on lines +106 to +114
Copy link

@coderabbitai coderabbitai bot Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

더미 데이터로 인한 잠재적 문제

MissionListModel을 하드코딩된 더미 값으로 생성하고 있습니다:

  • title: "" - UI에서 빈 제목이 표시될 수 있음
  • level: 1 - 실제 미션 레벨과 불일치할 수 있음 (Line 117에서 StarViewLevel 초기화에 사용됨)
  • isCompleted: true - 다른 사용자의 미션인 경우 부정확할 수 있음

PR 설명에서 언급하신 대로, 미션 레벨 정보 누락 문제에 대한 다음 해결 방안을 검토해 주세요:

  1. 서버 응답에 레벨 정보 포함하도록 API 확장
  2. 딥링크 파라미터로 레벨 전달 (예: level 쿼리 파라미터 추가)
  3. 미션 디테일 뷰에서 ID로 전체 정보를 다시 fetch
 public func runMissionDetailById(missionId: Int, username: String?) {
+    // 옵션 1: 쿼리 파라미터에서 레벨 정보를 추가로 받기
+    // public func runMissionDetailById(missionId: Int, username: String?, level: Int?)
+    
+    // 옵션 2: 미션 디테일 뷰에서 ID로 전체 정보 fetch 후 업데이트
     let model = MissionListModel(
         id: missionId,
-        title: "",
-        level: 1,
+        title: "", // TODO: Fetch from server or pass via query
+        level: 1,  // TODO: Get actual level from query parameter
         isCompleted: true
     )
     showMissionDetail(model, username)
 }

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@dlwogus0128 dlwogus0128 Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 적어주신 내용 확인했는데, 2로 가는 게 깔끔할 듯 ! 안드랑 논의하고 결정해주세요

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dlwogus0128 넵, 알겠습니다! 딥링크 파라미터로 level 정보를 전달하는 방식(옵션 2)으로 안드로이드 팀과 협의하여 결정하시면 좋을 것 같습니다. 크로스 플랫폼 간 일관성 있는 딥링크 스펙을 맞추는 것이 중요하니 논의 후 구현 방향이 정해지면 더미 데이터 부분을 실제 값으로 대체해 주시면 되겠습니다! 👍


private func showMissionDetail(_ model: MissionListModel, _ username: String?) {
guard let starLevel = StarViewLevel.init(rawValue: model.level) else { return }

Expand Down