Skip to content

Commit

Permalink
Merge pull request #257 from APP-iOS5th/Feature/OptionOverlayGuide
Browse files Browse the repository at this point in the history
Feature/option overlay guide
  • Loading branch information
the-hye authored Dec 5, 2024
2 parents f12ba04 + ef1577b commit ad3eb91
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 59 deletions.
4 changes: 4 additions & 0 deletions Kabinett.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
7F6CE9E62C6E28400074568E /* CameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F6CE9E52C6E28400074568E /* CameraView.swift */; };
7F78684C2C78B41A0083D204 /* ImagePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F78684B2C78B41A0083D204 /* ImagePickerView.swift */; };
7F7868562C7B14220083D204 /* HorizontalPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F7868552C7B14220083D204 /* HorizontalPadding.swift */; };
7F8B50A02CE612780048A07D /* OptionOverlayGuide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8B509F2CE612780048A07D /* OptionOverlayGuide.swift */; };
7F9890822C7EF5C30035CB0D /* CustomTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F9890812C7EF5C30035CB0D /* CustomTabBar.swift */; };
7FCAE2B12C73080000228FA7 /* ImagePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCAE2B02C73080000228FA7 /* ImagePreview.swift */; };
7FCAE2B82C730E1700228FA7 /* OverlappingImagesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCAE2B72C730E1700228FA7 /* OverlappingImagesView.swift */; };
Expand Down Expand Up @@ -231,6 +232,7 @@
7F6CE9E52C6E28400074568E /* CameraView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = "<group>"; };
7F78684B2C78B41A0083D204 /* ImagePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePickerView.swift; sourceTree = "<group>"; };
7F7868552C7B14220083D204 /* HorizontalPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalPadding.swift; sourceTree = "<group>"; };
7F8B509F2CE612780048A07D /* OptionOverlayGuide.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionOverlayGuide.swift; sourceTree = "<group>"; };
7F9890812C7EF5C30035CB0D /* CustomTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTabBar.swift; sourceTree = "<group>"; };
7FCAE2B02C73080000228FA7 /* ImagePreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePreview.swift; sourceTree = "<group>"; };
7FCAE2B72C730E1700228FA7 /* OverlappingImagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlappingImagesView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -391,6 +393,7 @@
7F9890812C7EF5C30035CB0D /* CustomTabBar.swift */,
7F6CE9C12C6B33DD0074568E /* OptionOverlay.swift */,
7F397C542C7DF20C00388645 /* ImportDialog.swift */,
7F8B509F2CE612780048A07D /* OptionOverlayGuide.swift */,
);
path = CustomTabView;
sourceTree = "<group>";
Expand Down Expand Up @@ -1053,6 +1056,7 @@
577C86732C8B8D5700EAB1BE /* Extension+View.swift in Sources */,
53A99EA72C8190B600896AAC /* SearchBarView.swift in Sources */,
577157012C75D73700E21162 /* Extension+UIApplication.swift in Sources */,
7F8B50A02CE612780048A07D /* OptionOverlayGuide.swift in Sources */,
83D9C8E52C830C7600EF2684 /* DefaultSignUpUseCase.swift in Sources */,
832C72672C71CF7B0071E8D0 /* SignUpUseCase.swift in Sources */,
04DEC0EB2C6C87B500D289EA /* AccountSettingsView.swift in Sources */,
Expand Down
22 changes: 21 additions & 1 deletion Kabinett/Presentation/Commons/CustomTabView/OptionOverlay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct OptionOverlay: View {
var body: some View {
NavigationStack {
ZStack {
Color.black.opacity(0.5)
Color.black.opacity(0.8)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
withAnimation {
Expand All @@ -26,6 +26,25 @@ struct OptionOverlay: View {

VStack {
Spacer()
HStack(spacing: 0) {
OptionOverlayGuide(
text: "간직하고 있던 편지를 촬영해 보관해요.",
boldText: "촬영",
position: .left,
isVisible: true
)
.frame(width: UIScreen.main.bounds.width/2)

OptionOverlayGuide(
text: "카비넷 사용자라면 \n이름이나 번호를 검색해 \n편지를 보낼 수 있어요.",
boldText: "이름이나 번호",
position: .right,
isVisible: true
)
.frame(width: UIScreen.main.bounds.width/2)
}
.padding(.bottom, 16)

HStack(spacing: 2) {
Button(action: {
customTabViewModel.showImportDialogAndHideOptions()
Expand All @@ -40,6 +59,7 @@ struct OptionOverlay: View {
.background(Color.primary100)
.foregroundColor(.contentPrimary)
}

NavigationLink("편지 쓰기") {
StationerySelectionView(
letterContent: $letterContent,
Expand Down
182 changes: 182 additions & 0 deletions Kabinett/Presentation/Commons/CustomTabView/OptionOverlayGuide.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
//
// OptionOverlayGuide.swift
// Kabinett
//
// Created by 김정우 on 11/14/24.
//

import SwiftUI

struct OptionOverlayGuide: View {
let text: String
let boldText: String
let position: GuidePosition
let isVisible: Bool

enum GuidePosition {
case left
case right
}

var attributedText: AttributedString {
var text = AttributedString(text)
if let range = text.range(of: boldText) {
text[range].font = .system(size: 15, weight: .bold)
}
return text
}

var body: some View {
VStack {
if isVisible {
HStack {
if position == .right {
Spacer()
}

Text(attributedText)
.font(.system(size: 15))
.foregroundStyle(.primary100)
.lineLimit(3)
.multilineTextAlignment(position == .left ? .leading : .trailing)
.frame(width: 180)
.padding(.horizontal, 20)
.padding(.vertical, 16)
.background(
ZStack {
GuideShape(position: position)
.fill(.primary600)
GuideTailShape(position: position)
.fill(.primary600)
}
.frame(width: 180)
.frame(height: position == .right ? 85 : 85)
)
.offset(y: position == .right ? 0 : 0)
.shadow( color: .black.opacity(0.15), radius: 8, x: 0, y: 2)

if position == .left {
Spacer()
}

}
}
}
}
}

struct GuideShape: Shape {
let position: OptionOverlayGuide.GuidePosition

func path(in rect: CGRect) -> Path {
var path = Path()

let bodyHeight: CGFloat = 85
let cornerRadius: CGFloat = 25

// top left corner
path.move(to: CGPoint(x: cornerRadius, y: 0))
path.addLine(to: CGPoint(x: rect.width - cornerRadius, y: 0))

path.addQuadCurve(
to: CGPoint(x: rect.width, y: cornerRadius),
control: CGPoint(x: rect.width, y: 0)
)

path.addLine(to: CGPoint(x: rect.width, y: bodyHeight - cornerRadius))

// bottom right corner
path.addQuadCurve(
to: CGPoint(x: rect.width - cornerRadius, y: bodyHeight),
control: CGPoint(x: rect.width, y: bodyHeight)
)

path.addLine(to: CGPoint(x: cornerRadius, y: bodyHeight))

// bottom left corner
path.addQuadCurve(
to: CGPoint(x: 0, y: bodyHeight - cornerRadius),
control: CGPoint(x: 0, y: bodyHeight)
)

path.addLine(to: CGPoint(x: 0, y: cornerRadius))

// top left corner
path.addQuadCurve(
to: CGPoint(x: cornerRadius, y: 0),
control: CGPoint(x: 0, y: 0)
)

return path
}
}

struct GuideTailShape: Shape {
let position: OptionOverlayGuide.GuidePosition

func path(in rect: CGRect) -> Path {
var path = Path()

let bodyHeight: CGFloat = 85
let cornerRadius: CGFloat = 24

if position == .left {
path.move(to: CGPoint(x: cornerRadius, y: bodyHeight))
path.addQuadCurve(
to: CGPoint(x: 18, y: bodyHeight + 10),
control: CGPoint(x: cornerRadius - 1, y: bodyHeight)
)
path.addQuadCurve(
to: CGPoint(x: 0, y: bodyHeight - cornerRadius),
control: CGPoint(x: 10, y: bodyHeight)
)
} else {
path.move(to: CGPoint(x: rect.width - cornerRadius, y: bodyHeight))
path.addQuadCurve(
to: CGPoint(x: rect.width - 18, y: bodyHeight + 10),
control: CGPoint(x: rect.width - (cornerRadius - 1), y: bodyHeight)
)
path.addQuadCurve(
to: CGPoint(x: rect.width, y: bodyHeight - cornerRadius),
control: CGPoint(x: rect.width - 10, y: bodyHeight)
)
}

return path
}
}

extension View {
func optionOverlayGuide(text: String, boldText: String, position: OptionOverlayGuide.GuidePosition, isVisible: Bool = true) -> some View {
self.overlay(
OptionOverlayGuide(
text: text,
boldText: boldText,
position: position,
isVisible: isVisible
)
.offset(y: -100),
alignment: .top
)
}
}

#Preview {
HStack(spacing: 0) {
OptionOverlayGuide(
text: "간직하고 있던 편지를 촬영해 보관해요.",
boldText: "촬영",
position: .left,
isVisible: true
)

OptionOverlayGuide(
text: "카비넷 사용자라면 이름이나 번호를 검색해 편지를 보낼 수 있어요.",
boldText: "이름이나 번호",
position: .right,
isVisible: true
)
}
.padding(.leading, 50)

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ final class CustomTabViewModel: ObservableObject {
func handleTabSelection(_ tab: Int) {
if tab == selectedTab {
if tab == 2 {
NotificationCenter.default.post(name: CustomTabViewModel.resetProfileNavigationNotification, object: nil)
NotificationCenter.default.post(name: CustomTabViewModel.profileTabTappedNotification, object: nil)
}
if tab == 0 {
letterBoxNavigationPath.removeLast(letterBoxNavigationPath.count)
Expand All @@ -63,11 +63,17 @@ final class CustomTabViewModel: ObservableObject {
}
} else {
selectedTab = tab
if tab == 0 {
letterBoxNavigationPath.removeLast(letterBoxNavigationPath.count)
} else if tab == 2 {
profileNavigationPath.removeLast(profileNavigationPath.count)
}
}
}

private func resetNavigationForTab(_ tab: Int) {
switch tab {
case 0:
letterBoxNavigationPath.removeLast(letterBoxNavigationPath.count)
case 2:
profileNavigationPath.removeLast(profileNavigationPath.count)
default:
break
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,9 @@ struct ImageDetailView: View {
}
.padding()
}
.navigationBarItems(leading: Button(action: { showDetailView = false }) {
Image(systemName: "chevron.left")
.foregroundStyle(Color.contentPrimary)
})
.background(Color.background.edgesIgnoringSafeArea(.all))
}
.slideToDismiss {
showDetailView = false
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,26 @@ struct ImagePreview: View {
.padding(.horizontal, UIScreen.main.bounds.width * 0.06)
}
}
.navigationBarItems(leading: Button(action: {
imageViewModel.resetSelections()
dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if customViewModel.isLetterWrite == false {
customViewModel.showImportDialog = true
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(
leading: Button(action: {
imageViewModel.resetSelections()
customViewModel.showImagePreview = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
customViewModel.showPhotoLibrary = true
}
}) {
Image(systemName: "chevron.left")
.foregroundColor(.contentPrimary)
}
}) {
Image(systemName: "chevron.left")
.font(.system(size: 18, weight: .semibold))
.foregroundColor(.primary900)
})
.fullScreenCover(isPresented: $showDetailView) {
ImageDetailView(images: imageViewModel.photoContents, showDetailView: $showDetailView)
)
.background(Color.background.edgesIgnoringSafeArea(.all))
.navigationDestination(isPresented: $showDetailView) {
ImageDetailView(
images: imageViewModel.photoContents,
showDetailView: $showDetailView
)
}
.sheet(isPresented: $showLetterWritingView) {
LetterWritingView(
Expand All @@ -77,7 +82,6 @@ struct ImagePreview: View {
showEnvelopeStamp: $navigateToEnvelopeStamp
)
}
.background(Color.background.edgesIgnoringSafeArea(.all))
.navigationDestination(isPresented: $navigateToEnvelopeStamp) {
EnvelopeStampSelectionView(
letterContent: $letterContent,
Expand All @@ -86,11 +90,10 @@ struct ImagePreview: View {
)
}
}
.slideToDismiss {
.onDisappear {
imageViewModel.resetSelections()
dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if customViewModel.isLetterWrite == false {
if !customViewModel.isLetterWrite && !customViewModel.letterBoxNavigationPath.isEmpty {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
customViewModel.showImportDialog = true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,13 @@ struct LetterCompletionView: View {
}
}
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: backButton)
.onAppear {
Task {
await viewModel.loadAndUpdateEnvelopeAndStamp()
envelopeURL = viewModel.envelopeURL ?? letterContent.envelopeImageUrlString
stampURL = viewModel.stampURL ?? letterContent.stampImageUrlString
}
}
.slideToDismiss {
dismiss()
}
}

private var backButton: some View {
Button(action: {
dismiss()
}) {
Image(systemName: "chevron.left")
.font(.system(size: 18, weight: .semibold))
.foregroundColor(.primary900)
}
}

private var letterPreviewView: some View {
Expand Down
Loading

0 comments on commit ad3eb91

Please sign in to comment.