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

Feature/improvement profile/view UI #70

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: 5 additions & 1 deletion dg-muscle-ios/sources/App/DI/MyAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ public struct MyAssembly: Assembly {
}

container.register(MyProfileView.self) { (resolver, shows: Binding<Bool>) in
return MyProfileView(shows: shows)
let userRepository = resolver.resolve(UserRepository.self)!
return MyProfileView(
shows: shows,
userRepository: userRepository
)
}

container.register(DeleteAccountConfirmView.self) { resolver in
Expand Down
5 changes: 4 additions & 1 deletion dg-muscle-ios/sources/Presentation/Main/View/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ public struct HomeView: View {
)
},
myProfileViewFactory: {_ in
MyProfileView(shows: .constant(false))
MyProfileView(
shows: .constant(false),
userRepository: userRepository
)
}
)
.preferredColorScheme(.dark)
Expand Down
17 changes: 13 additions & 4 deletions dg-muscle-ios/sources/Presentation/My/My/View/MyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,41 @@ public struct MyView: View {

Section {
VStack(spacing: 20) {

Button {
presentProfileViewAction?()
} label: {
ListItemView(systemName: "person", text: "Profile", color: Color(uiColor: .secondaryLabel))
}
.buttonStyle(.borderless)


Button {
URLManager.shared.open(url: "dgmuscle://friend")
} label: {
ListItemView(systemName: "person", text: "Friend", color: .green)
ListItemView(systemName: "link", text: "Friend", color: Color(uiColor: .secondaryLabel))
}
.buttonStyle(.borderless)

Button {
URLManager.shared.open(url: "dgmuscle://exercisemanage")
} label: {
ListItemView(systemName: "dumbbell", text: "Exercise", color: .blue)
ListItemView(systemName: "dumbbell", text: "Exercise", color: Color(uiColor: .secondaryLabel))
}
.buttonStyle(.borderless)

Button {
URLManager.shared.open(url: "dgmuscle://rapidsearchtype")
} label: {
ListItemView(systemName: "doc", text: "Exercise DB", color: .blue)
ListItemView(systemName: "doc", text: "Exercise DB", color: Color(uiColor: .secondaryLabel))
}
.buttonStyle(.borderless)

if viewModel.user?.developer == true {
Button {
URLManager.shared.open(url: "dgmuscle://logs")
} label: {
ListItemView(systemName: "doc", text: "Logs", color: .purple)
ListItemView(systemName: "doc", text: "Logs", color: Color(uiColor: .secondaryLabel))
}
.buttonStyle(.borderless)
.overlay {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,44 @@ import SwiftUI
import Domain
import MockData
import Common
import Kingfisher

public struct MyProfileView: View {

struct IdentifiableURL: Identifiable {
let id = UUID().uuidString
let url: URL
}

@Binding var shows: Bool

@State private var viewOffset: CGFloat = 0
@State private var selectedImageURL: IdentifiableURL? = nil

@StateObject var viewModel: MyProfileViewModel

public init(
shows: Binding<Bool>
shows: Binding<Bool>,
userRepository: UserRepository
) {
_shows = shows
_viewModel = .init(wrappedValue: .init(userRepository: userRepository))
}

public var body: some View {
ZStack {
Rectangle()
.fill(Color(uiColor: .systemBackground))

Text("MyProfileView")
backgroundView
VStack {
xButton
Spacer()
profileView
Text(viewModel.user?.displayName ?? "null")
.foregroundStyle(.white)
whiteLine
.padding(.top, 30)
bottomSection
.padding(.top)
}
}
.offset(y: viewOffset)
.gesture (
Expand All @@ -41,24 +60,168 @@ public struct MyProfileView: View {
let dismissableLocation = gesture.translation.height > 150
let dismissableVolocity = gesture.velocity.height > 150
if dismissableLocation || dismissableVolocity {
withAnimation {
viewOffset = 1000
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
shows = false
}
}
dismiss()
} else {
withAnimation {
viewOffset = 0
}
dragViewUp()
}
}
)

.fullScreenCover(item: $selectedImageURL) { url in
selectedURLImageView(url: url)
}
}

private func dismiss() {
withAnimation {
viewOffset = 1000
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
shows = false
}
}
}

private func dragViewUp() {
withAnimation {
viewOffset = 0
}
}

private func selectedURLImageView(url: IdentifiableURL) -> some View {
ZStack {

Rectangle()
.fill(.black)
.ignoresSafeArea()

Rectangle()
.fill(.clear)
.background {
KFImage(url.url)
.resizable()
.scaledToFill()
}

VStack {
HStack {
Button {
selectedImageURL = nil
} label: {
Image(systemName: "xmark")
.foregroundStyle(.white)
.font(.title)
}
Spacer()
}
.padding(.top)
.padding(.horizontal)

Spacer()
}
}
}

var xButton: some View {
HStack {
Button {
dismiss()
} label: {
Image(systemName: "xmark")
.foregroundStyle(.white)
.font(.title)
}

Spacer()
}
.padding(.horizontal)
}

var backgroundView: some View {
Rectangle()
.fill(.clear)
.background {
ZStack {
Rectangle()
.fill(.gray)

if let url = viewModel.user?.backgroundImageURL {
KFImage(url)
.resizable()
.scaledToFill()
.onTapGesture {
selectedImageURL = .init(url: url)
}
}
}
}
.ignoresSafeArea()
}

var profileView: some View {
RoundedRectangle(cornerRadius: 25.0, style: .continuous)
.stroke(.white.opacity(0.6))
.fill(.clear)
.frame(width: 100, height: 100)
.background {
ZStack {
RoundedRectangle(cornerRadius: 25.0, style: .continuous)
.fill(.gray)

Image(systemName: "person")
.font(.title)
.foregroundStyle(.white)

if let url = viewModel.user?.photoURL {
KFImage(url)
.resizable()
.scaledToFill()
.frame(width: 100, height: 100)
.clipShape(RoundedRectangle(cornerRadius: 25.0))
.onTapGesture {
selectedImageURL = .init(url: url)
}
}
}
}
}

var whiteLine: some View {
Rectangle()
.fill(.white.opacity(0.7))
.frame(height: 1)
}

var bottomSection: some View {
HStack(spacing: 40) {

if let link = viewModel.user?.link {
Button {
URLManager.shared.open(url: link)
} label: {
VStack(spacing: 12) {
Image(systemName: "link")
Text("Link")
}
}
.foregroundStyle(.white)
}

Button {
print("tap edit")
} label: {
VStack(spacing: 12) {
Image(systemName: "pencil")
Text("Edit")
}
}
.foregroundStyle(.white)
}
}
}

#Preview {
return MyProfileView(shows: .constant(true))
return MyProfileView(
shows: .constant(true),
userRepository: UserRepositoryMock()
)
.preferredColorScheme(.dark)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,28 @@

import Foundation
import Combine
import Common
import Domain

final class MyProfileViewModel: ObservableObject {
init() { }

@Published var user: Common.User?

private let subscribeUserUsecase: SubscribeUserUsecase

init(
userRepository: UserRepository
) {
subscribeUserUsecase = .init(userRepository: userRepository)
bind()
}

private func bind() {
subscribeUserUsecase
.implement()
.compactMap({ $0 })
.map({ Common.User(domain: $0) })
.receive(on: DispatchQueue.main)
.assign(to: &$user)
}
}