Skip to content

Commit

Permalink
Merge pull request #77 from mash-up-kr/feature/#76-registerMeme-hyerjang
Browse files Browse the repository at this point in the history
Feat: 밈 등록하기 디자인 및 api 연결
  • Loading branch information
hryeong66 authored Sep 30, 2024
2 parents 40ba248 + f349cd7 commit f7025a5
Show file tree
Hide file tree
Showing 48 changed files with 1,667 additions and 141 deletions.
2 changes: 2 additions & 0 deletions Projects/App/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ let project = Project.configure(
"CFBundleVersion": "1",
"UILaunchStoryboardName": "launch",
"NSUserTrackingUsageDescription": "이 앱은 사용자 맞춤형 광고 제공 및 분석을 위해 사용자 추적 정보를 수집합니다.",
"NSPhotoLibraryUsageDescription": "밈 이미지 등록을 위해 앨범 접근 권한이 필요합니다.",
"UIUserInterfaceStyle": "Light", // 다크모드 방지
"NSAllowArbitraryLoads": true,
"NSAppTransportSecurity": [
Expand Down Expand Up @@ -75,6 +76,7 @@ let project = Project.configure(
"UILaunchStoryboardName": "launch",
"NSUserTrackingUsageDescription": "이 앱은 사용자 맞춤형 광고 제공 및 분석을 위해 사용자 추적 정보를 수집합니다.",
"UIUserInterfaceStyle": "Light", // 다크모드 방지
"NSPhotoLibraryUsageDescription": "밈 이미지 등록을 위해 앨범 접근 권한이 필요합니다.",
"NSAppTransportSecurity": [
"NSAllowsArbitraryLoads": true
]
Expand Down
27 changes: 27 additions & 0 deletions Projects/Core/DesignSystem/Sources/Extension/View+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ public extension View {
) -> some View {
clipShape(RoundedCorners(radius: radius, corners: corners))
}

// MARK: - Keyboard
func endTextEditing() {
UIApplication.shared.sendAction(
#selector(UIResponder.resignFirstResponder),
to: nil,
from: nil,
for: nil
)
}

func onKeyboardChange(_ action: @escaping (Bool) -> Void) -> some View {
self.onAppear {
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { _ in
action(true)
}
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { _ in
action(false)
}
}
.onDisappear {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
}
}

public extension View {
Expand All @@ -29,3 +54,5 @@ public extension View {
)
}
}


93 changes: 0 additions & 93 deletions Projects/Core/DesignSystem/Sources/KeywordsTagView.swift

This file was deleted.

75 changes: 75 additions & 0 deletions Projects/Core/DesignSystem/Sources/View/FarmemeAlertView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// FarmemeAlertView.swift
// DesignSystem
//
// Created by 장혜령 on 9/29/24.
//

import SwiftUI

import ResourceKit

public struct FarmemeAlertView: View {
private let title: String
private let description: String
private var dismiss: (() -> Void)

public init(title: String,
description: String,
dismiss: @escaping (() -> Void)
) {
self.title = title
self.description = description
self.dismiss = dismiss
}

public var body: some View {
VStack(spacing: 0) {
titleView

descriptionView
.padding(.top, 8)

confirmButton
.padding(.top, 14)
}
.padding(.horizontal, 30)
.padding(.vertical, 20)
.background(Color.Background.white)
.cornerRadius(20)
}


private var titleView: some View {
HStack {
Text(title)
.font(Font.Heading.Medium.semiBold)
.foregroundColor(Color.Text.primary)
.foregroundColor(.black)
Spacer()
}
}

private var descriptionView: some View {
HStack {
Text(description)
.font(Font.Body.Large.medium)
.foregroundColor(Color.Text.secondary)
.multilineTextAlignment(.leading)
Spacer()
}
}

private var confirmButton: some View {
HStack{
Spacer()
Button {
dismiss()
} label: {
Text("확인")
.font(Font.Body.Large.medium)
.foregroundColor(Color.Text.brand)
}
}
}
}
20 changes: 20 additions & 0 deletions Projects/Core/DesignSystem/Sources/View/Keyword/KeywordTag.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// KeywordTag.swift
// DesignSystem
//
// Created by 장혜령 on 9/24/24.
//

import Foundation

public struct KeywordTag: Hashable, Identifiable {
public let id: String
public let name: String
public let isSelected: Bool

public init(id: String, name: String, isSelected: Bool = false) {
self.id = id
self.name = name
self.isSelected = isSelected
}
}
141 changes: 141 additions & 0 deletions Projects/Core/DesignSystem/Sources/View/Keyword/KeywordsTagView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//
// KeywordsTagView.swift
// DesignSystem
//
// Created by 리나 on 2024/06/29.
//

import SwiftUI
import ResourceKit

// thanks to NamS
public struct KeywordsTagView: View {
let keywordTags: [KeywordTag]
var onTapHandler: ((String) -> ())?

public init(keywordTags: [KeywordTag], onTapHandler: ((String) -> ())?) {
self.keywordTags = keywordTags
self.onTapHandler = onTapHandler
}

public var body: some View {
ScrollView {
FlowLayout(spacing: 8, lineSpacing: 8) {
ForEach(keywordTags, id: \.self) { keywordTag in
Text(keywordTag.name)
.font(Font.Body.Medium.medium)
.foregroundColor(
keywordTag.isSelected
? Color.Text.brand
: Color.Text.primary
)
.padding(.horizontal, 16)
.padding(.vertical, 9.5)
.background(
Capsule().foregroundStyle(
keywordTag.isSelected
? Color.Background.brandassistive
: Color.Background.assistive
)
)
.onTapGesture {
onTapHandler?(keywordTag.name)
}
}
}
}
}
}

struct FlowLayout: Layout {
var spacing: CGFloat?
var lineSpacing: CGFloat

init(spacing: CGFloat? = nil, lineSpacing: CGFloat) {
self.spacing = spacing
self.lineSpacing = lineSpacing
}

struct Cache {
var sizes: [CGSize] = []
var spacing: [CGFloat] = []
}

func makeCache(subviews: Subviews) -> Cache {
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
let spacing: [CGFloat] = subviews.indices.map { index in
guard index != subviews.count - 1 else {
return 0
}

return subviews[index].spacing.distance(
to: subviews[index+1].spacing,
along: .horizontal
)
}

return Cache(sizes: sizes, spacing: spacing)
}

func sizeThatFits(
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Cache
) -> CGSize {
var totalHeight = 0.0
var totalWidth = 0.0

var lineWidth = 0.0
var lineHeight = 0.0

for index in subviews.indices {
if lineWidth + cache.sizes[index].width > proposal.width ?? 0 {
totalHeight += lineHeight + lineSpacing // 줄 간격 추가
lineWidth = cache.sizes[index].width
lineHeight = cache.sizes[index].height
} else {
lineWidth += cache.sizes[index].width + (spacing ?? cache.spacing[index])
lineHeight = max(lineHeight, cache.sizes[index].height)
}

totalWidth = max(totalWidth, lineWidth)
}

totalHeight += lineHeight

return .init(width: totalWidth, height: totalHeight)
}

func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Cache
) {
var lineX = bounds.minX
var lineY = bounds.minY
var lineHeight: CGFloat = 0

for index in subviews.indices {
if lineX + cache.sizes[index].width > (proposal.width ?? 0) {
lineY += lineHeight + lineSpacing // 줄 간격 추가
lineHeight = 0
lineX = bounds.minX
}

let position = CGPoint(
x: lineX + cache.sizes[index].width / 2,
y: lineY + cache.sizes[index].height / 2
)

lineHeight = max(lineHeight, cache.sizes[index].height)
lineX += cache.sizes[index].width + (spacing ?? cache.spacing[index])

subviews[index].place(
at: position,
anchor: .center,
proposal: ProposedViewSize(cache.sizes[index])
)
}
}
}
Loading

0 comments on commit f7025a5

Please sign in to comment.