Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] 앱 업데이트 기능 연결, 스켈레톤 적용 #70

Merged
merged 6 commits into from
Aug 22, 2024
Merged
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
6 changes: 4 additions & 2 deletions Projects/App/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ let project = Project.configure(
"CFBundleDevelopmentRegion": "ko_KR",
"CFBundleShortVersionString": "1.1.1",
"CFBundleVersion": "1",
"UILaunchStoryboardName": "launch"
"UILaunchStoryboardName": "launch",
"UIUserInterfaceStyle": "Light" // 다크모드 방지
]),
sources: "Sources/**",
resources: "Resources/**",
Expand Down Expand Up @@ -54,7 +55,8 @@ let project = Project.configure(
product: .app,
bundleId: "ppac.farmeme.App",
infoPlist: .extendingDefault(with: [
"UILaunchStoryboardName": "launch"
"UILaunchStoryboardName": "launch",
"UIUserInterfaceStyle": "Light" // 다크모드 방지
]),
sources: "Sources/**",
resources: "Resources/**",
Expand Down
9 changes: 5 additions & 4 deletions Projects/Core/DesignSystem/Sources/MainTab/MainTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ public struct TabItemView: View {
.padding(40)
}

var needPlayLottieView: Bool {
return !isAnimationFinished && isSelected
}
// var needPlayLottieView: Bool {
// return !isAnimationFinished && isSelected
// }

var tabItemImageView: some View {
needPlayLottieView ? tabLottieView : tabImageView
//needPlayLottieView ? tabLottieView : tabImageView
tabImageView
}

var tabLottieView: AnyView {
Expand Down
17 changes: 7 additions & 10 deletions Projects/Core/DesignSystem/Sources/View/CircleButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ public struct CircleButton: View {
let width: CGFloat
let height: CGFloat
let image: SwiftUI.Image
let shadowColor: SwiftUI.Color
let action: () -> Void

public init(
width: CGFloat,
height: CGFloat,
image: SwiftUI.Image,
shadowColor: SwiftUI.Color = Color.Shadow.primary,
action: @escaping () -> Void
) {
self.width = width
self.height = height
self.image = image
self.shadowColor = shadowColor
self.action = action
}

Expand All @@ -38,15 +41,8 @@ public struct CircleButton: View {
.scaledToFill()
.frame(width: 20, height: 20, alignment: .center)
}
.frame(
width: self.width,
height: self.height,
alignment: .center
)
.shadow(
color: Color.Background.primary.opacity(0.05),
radius: 20
)
.frame(width: self.width, height: self.height,alignment: .center)
.shadow(color: shadowColor, radius: 20)
}
}
}
Expand All @@ -55,7 +51,8 @@ public struct CircleButton: View {
CircleButton(
width: 42,
height: 42,
image: ResourceKitAsset.Icon.copy.swiftUIImage
image: ResourceKitAsset.Icon.copy.swiftUIImage,
shadowColor: Color.Shadow.orange
) {
print("Copy~~")
}
Expand Down
27 changes: 26 additions & 1 deletion Projects/Core/DesignSystem/Sources/View/Meme/MemeImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
//

import SwiftUI
import ResourceKit
import Kingfisher
import SkeletonUI

public struct MemeImageView: View {

// MARK: - Properties

private let imageUrlString: String

@State private var isImageLoaded: Bool = false
// MARK: - Initializers

public init(imageUrlString: String) {
Expand All @@ -24,6 +26,14 @@ public struct MemeImageView: View {

public var body: some View {
KFImage(URL(string: imageUrlString))
.placeholder {
skeletonView
}
.onSuccess { _ in
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
isImageLoaded = true
}
}
.resizable()
.loadDiskFileSynchronously()
.cacheMemoryOnly()
Expand All @@ -32,4 +42,19 @@ public struct MemeImageView: View {
.aspectRatio(0.9375, contentMode: .fit)
.cornerRadius(10)
}

var skeletonView: some View {
EmptyView()
.skeleton(
with: !isImageLoaded,
animation: .linear(duration: 2, delay: 0, speed: 1),
appearance: .gradient(
.linear,
color: Color.Skeleton.secondary,
background: Color.Skeleton.primary,
radius: 1
),
shape: .rounded(.radius(12))
)
}
}
31 changes: 30 additions & 1 deletion Projects/Core/DesignSystem/Sources/View/Meme/MemeItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SwiftUI
import ResourceKit
import PPACModels
import Kingfisher
import SkeletonUI

public struct MemeItemView: View {
private let memeDetail: MemeDetail
Expand All @@ -31,6 +32,7 @@ public struct MemeItemView: View {
.onTapGesture {
memeClickHandler?(memeDetail)
}

MemeItemInfoView(memeName: memeDetail.title, reaction: memeDetail.reaction)
}
}
Expand All @@ -40,6 +42,7 @@ struct MemeItemViewWithButton: View {
@State private var imageHeight: CGFloat = .zero
private let memeCopyHandler: ((MemeDetail) -> ())?
private let memeDetail: MemeDetail
@State private var isImageLoaded: Bool = false

init(memeDetail: MemeDetail, memeCopyHandler: ((MemeDetail) -> ())?) {
self.memeDetail = memeDetail
Expand Down Expand Up @@ -74,15 +77,17 @@ struct MemeItemViewWithButton: View {
struct ResizableMemeImageView: View {
let imageUrlString: String
@Binding var imageHeight: CGFloat
@State private var isImageLoaded: Bool = false

var body: some View {
GeometryReader { geometry in
VStack {
ZStack {
KFImage(URL(string: imageUrlString))
.resizable()
.loadDiskFileSynchronously()
.cacheMemoryOnly()
.onSuccess { result in
guard result.image.size.width > 0 else { return }
let ratio = geometry.size.width / result.image.size.width
let newHeight = result.image.size.height * ratio
if newHeight < 80 {
Expand All @@ -92,12 +97,36 @@ struct ResizableMemeImageView: View {
} else {
imageHeight = newHeight
}
isImageLoaded = true
}
.cornerRadius(12)
.frame(height: imageHeight)
.opacity(isImageLoaded ? 1 : 0) // 이미지 로드 완료 전에 투명하게 처리

if !isImageLoaded {
skeletonView
.onAppear {
imageHeight = geometry.size.width
}
}
}
}
}

var skeletonView: some View {
EmptyView()
.skeleton(
with: !isImageLoaded,
animation: .linear(duration: 2, delay: 0, speed: 1),
appearance: .gradient(
.linear,
color: Color.Skeleton.secondary,
background: Color.Skeleton.primary,
radius: 1
),
shape: .rounded(.radius(12))
)
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct SplashView: View {
.foregroundStyle(Color.Text.primary)
}
.opacity(viewModel.state.isVisible ? 1 : 0)
.animation(.easeInOut(duration: 3.0), value: viewModel.state.isVisible)
.animation(.easeInOut(duration: 0.7), value: viewModel.state.isVisible)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ final class SplashViewModel: ViewModelType, ObservableObject {
let userDetail = try await self.checkUserInfoUseCase.execute()
self.updateMemeLevel(to: userDetail.level)
self.state = State(isVisible: false)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) { [weak self] in
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.7) { [weak self] in
self?.router?.showMainTabView(userDetail: userDetail)
}
} catch(let error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,48 @@ extension MemeDetail: HorizontalMemeItemProtocol {}
struct MemeSimpleItemView: View, HorizontalMemeItemViewProtocol {
typealias Item = MemeDetail
let memeDetail: MemeDetail
@State private var isImageLoaded: Bool = false

init(item memeDetail: MemeDetail) {
self.memeDetail = memeDetail
}

var body: some View {
MemeImageView(imageUrlString: memeDetail.imageUrlString)
public var body: some View {
ZStack {
KFImage(URL(string: memeDetail.imageUrlString))
.resizable()
.loadDiskFileSynchronously()
.cacheMemoryOnly()
.onSuccess { _ in
isImageLoaded = true
}
.aspectRatio(contentMode: .fill)
.frame(width: 120, height: 120, alignment: .center)
.cornerRadius(12)
.opacity(isImageLoaded ? 1 : 0) // 이미지 로드 완료 전에 투명하게 처리

if !isImageLoaded {
skeletonView
}
}
}

var skeletonView: some View {
EmptyView()
.skeleton(
with: !isImageLoaded,
animation: .linear(duration: 2, delay: 0, speed: 1),
appearance: .gradient(
.linear,
color: Color.Skeleton.secondary,
background: Color.Skeleton.primary,
radius: 1
),
shape: .rounded(.radius(12))
)
.frame(width: 120, height: 120, alignment: .center)
}

}

//#Preview {
Expand Down
1 change: 1 addition & 0 deletions Projects/Features/Recommend/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ let project = Project(
.ThirdParty.Kingfisher,
.ThirdParty.PopupView,
.ThirdParty.Lottie,
.ThirdParty.SkeletonUI,
.ResourceKit,
.Core.DesignSystem,
.Core.PPACModels,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,16 @@ struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) { }
}

extension View {
func recommendSkeleton(
isShow: Bool,
radius: CGFloat,
width: CGFloat? = nil,
height: CGFloat? = nil
) -> some View {
self.modifier(
SkeletonModifier(isShow: isShow, radius: radius, width: width, height: height)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// SkeletonModifier.swift
// Recommend
//
// Created by 김종윤 on 8/8/24.
//

import SwiftUI
import SkeletonUI

import ResourceKit

struct SkeletonModifier: ViewModifier {
let isShow: Bool
let radius: CGFloat
let width: CGFloat?
let height: CGFloat?

func body(content: Content) -> some View {
content
.skeleton(
with: isShow,
animation: .linear(duration: 2, delay: 0, speed: 1),
appearance: .gradient(
.linear,
color: Color.Skeleton.beige,
background: Color.Skeleton.orange,
radius: 1
),
shape: .rounded(.radius(radius))
)
.frame(width: width, height: height)
}
}
Loading