From cf97b1cd43a91725e0419a953815287fde0bf70f Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 17 Sep 2020 00:46:27 +0300 Subject: SwiftUI WIP --- Juick/Views/ActivityIndicator.swift | 28 +++++++++ Juick/Views/AttributedLabelView.swift | 107 ++++++++++++++++++++++++++++++++++ Juick/Views/ContentView.swift | 47 +++++++++++++++ Juick/Views/FeedView.swift | 66 +++++++++++++++++++++ Juick/Views/LoadableImageView.swift | 35 +++++++++++ Juick/Views/MessageView.swift | 51 ++++++++++++++++ 6 files changed, 334 insertions(+) create mode 100644 Juick/Views/ActivityIndicator.swift create mode 100644 Juick/Views/AttributedLabelView.swift create mode 100644 Juick/Views/ContentView.swift create mode 100644 Juick/Views/FeedView.swift create mode 100644 Juick/Views/LoadableImageView.swift create mode 100644 Juick/Views/MessageView.swift (limited to 'Juick/Views') diff --git a/Juick/Views/ActivityIndicator.swift b/Juick/Views/ActivityIndicator.swift new file mode 100644 index 0000000..5b160fd --- /dev/null +++ b/Juick/Views/ActivityIndicator.swift @@ -0,0 +1,28 @@ +// +// ActivityIndicator.swift +// tst +// +// Created by Vitaly Takmazov on 10.12.2019. +// Copyright © 2019 com.juick. All rights reserved. +// + +import Foundation +import SwiftUI + +struct ActivityIndicator: UIViewRepresentable { + let style: UIActivityIndicatorView.Style + + func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView { + return UIActivityIndicatorView(style: style) + } + + func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) { + uiView.startAnimating() + } +} + +struct ActivityIndicator_Previews: PreviewProvider { + static var previews: some View { + /*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/ + } +} diff --git a/Juick/Views/AttributedLabelView.swift b/Juick/Views/AttributedLabelView.swift new file mode 100644 index 0000000..08051a9 --- /dev/null +++ b/Juick/Views/AttributedLabelView.swift @@ -0,0 +1,107 @@ +// +// AttributedLabelView.swift +// Demo +// +// Created by Ernesto Rivera on 5/14/20. +// Copyright © 2020 Atributika. All rights reserved. +// +import SwiftUI +import Atributika + +@available(iOS 13.0, *) +struct AttributedLabelView: UIViewRepresentable +{ + var attributedText: AttributedText? + var configureLabel: ((AttributedLabel) -> Void)? = nil + + @State var maxWidth: CGFloat = 300 + + typealias UIViewType = MaxWidthAttributedLabel + + func makeUIView(context: Context) -> MaxWidthAttributedLabel + { + let view = MaxWidthAttributedLabel() + configureLabel?(view) + return view + } + + func updateUIView(_ uiView: MaxWidthAttributedLabel, context: Context) + { + uiView.attributedText = attributedText + uiView.maxWidth = maxWidth + } + + class MaxWidthAttributedLabel: AttributedLabel + { + var maxWidth: CGFloat! + + open override var intrinsicContentSize: CGSize + { + sizeThatFits(CGSize(width: maxWidth, height: .infinity)) + } + } +} + +@available(iOS 13.0, *) +struct AttributtedLabelView_Previews: PreviewProvider +{ + static var previews: some View + { + let all = Style.font(UIFont.preferredFont(forTextStyle: .body)) + let link = Style("a") + .foregroundColor(Color(named: "Title") ?? .blue, .normal) + .foregroundColor(.brown, .highlighted) + let configureLabel: ((AttributedLabel) -> Void) = { label in + label.numberOfLines = 0 + label.textColor = .label + } + + return GeometryReader { geometry in + List { + AttributedLabelView(attributedText: """ +Denny JA: Dengan RT ini, anda ikut memenangkan Jokowi-JK. Pilih hghghg + hghfghfgh + fghfgh + fgh + gfh + fgh + dipercaya (Jokowi) dan pengalaman (JK). #DJoJK +""" + .style(tags: link) + .styleHashtags(link) + .styleMentions(link) + .styleLinks(link) + .styleAll(all), configureLabel: configureLabel, maxWidth: geometry.size.width) + .fixedSize(horizontal: true, vertical: true) + .padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 24)) + .listRowInsets(EdgeInsets()) + AttributedLabelView(attributedText: "@e2F If only Bradley's arm was longer. Best ever. 😊 #oscars https://m/p
Check this link" + .style(tags: link) + .styleHashtags(link) + .styleMentions(link) + .styleLinks(link) + .styleAll(all), configureLabel: configureLabel) + .fixedSize(horizontal: true, vertical: true) + .padding() + .listRowInsets(EdgeInsets()) + AttributedLabelView(attributedText: """ + # A big message + - With *mentions* [Ernesto Test Account](user://91010061) + - **Bold** text + ## Also + > Quotes + 1. Some `code` + 2. And data detectors (801) 917 4444, email@dot.com and http://apple.com + """ + .style(tags: link) + .styleHashtags(link) + .styleMentions(link) + .styleLinks(link) + .styleAll(all), configureLabel: configureLabel) + .fixedSize(horizontal: true, vertical: true) + .listRowInsets(EdgeInsets()) + .padding() + }.listRowInsets(EdgeInsets()) + } + } +} diff --git a/Juick/Views/ContentView.swift b/Juick/Views/ContentView.swift new file mode 100644 index 0000000..9a9f45b --- /dev/null +++ b/Juick/Views/ContentView.swift @@ -0,0 +1,47 @@ +// +// ContentView.swift +// tst +// +// Created by Vitaly Takmazov on 10.12.2019. +// Copyright © 2019 com.juick. All rights reserved. +// + +import SwiftUI +import Combine + +struct ContentView: View { + @State var selectedView = 0 + var body: some View { + NavigationView { + TabView(selection: $selectedView) { + FeedView(url: "https://api.juick.com/messages?popular=1", type: .messages) + .tabItem { + Image("ei-clock") + Text("Today") + }.tag(0) + FeedView(url: "https://api.juick.com/messages/discussions", type: .messages) + .tabItem { + Image("ei-bell") + Text("Discussions") + }.tag(1) + FeedView(url: "https://api.juick.com/messages", type: .messages) + .tabItem { + Image("ei-envelope") + Text("Chats") + }.tag(2) + FeedView(url: "https://api.juick.com/messages", type: .messages) + .tabItem { + Image("ei-search") + Text("Discover") + }.tag(3) + } + .navigationBarTitle("Juick", displayMode: .inline) + } + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/Juick/Views/FeedView.swift b/Juick/Views/FeedView.swift new file mode 100644 index 0000000..fe3aaed --- /dev/null +++ b/Juick/Views/FeedView.swift @@ -0,0 +1,66 @@ +// +// FeedView.swift +// tst +// +// Created by Vitaly Takmazov on 10.12.2019. +// Copyright © 2019 com.juick. All rights reserved. +// + +import SwiftUI + +enum FeedType { + case messages + case thread +} + +struct FeedView: View { + @ObservedObject var messageFetcher : MessageFetcher + + let feedType : FeedType + + init(url: String, type: FeedType) { + feedType = type + messageFetcher = MessageFetcher(url: url) + } + + private var stateContent: AnyView { + switch messageFetcher.state { + case .loading: + return AnyView( + ActivityIndicator(style: .medium) + ) + case .fetched(let result): + switch result { + case .failure(let error): + return AnyView( + Text(error.localizedDescription) + ) + case .success(let root): + return AnyView( + List(root) { (message: MessageFetcher.MessageData) in + let destination = feedType == .thread ? AnyView(Text("YO")) : AnyView(FeedView(url: "https://api.juick.com/thread?mid=\(message.message.mid.stringValue)", type: .thread)) + ZStack { + MessageView(message: message.message).listRowInsets(.none) + NavigationLink( + destination: destination) { + EmptyView() + } + } + } + .listRowInsets(.none) + ) + } + } + } + + var body: some View { + stateContent + .navigationBarTitle(Text("Messages"), displayMode: .inline) + } +} + +struct FeedView_Previews: PreviewProvider { + static var previews: some View { + FeedView(url: "https://api.juick.com/messages", type: .messages) + } +} diff --git a/Juick/Views/LoadableImageView.swift b/Juick/Views/LoadableImageView.swift new file mode 100644 index 0000000..e639602 --- /dev/null +++ b/Juick/Views/LoadableImageView.swift @@ -0,0 +1,35 @@ +// +// LoadableImageView.swift +// tst +// +// Created by Vitaly Takmazov on 10.12.2019. +// Copyright © 2019 com.juick. All rights reserved. +// + +import SwiftUI + +struct LoadableImageView: View { + @ObservedObject var imageFetcher: ImageFetcher + + init(with urlString: String) { + imageFetcher = ImageFetcher(url: urlString) + } + + var body: some View { + if let image = UIImage(data: imageFetcher.data) { + return AnyView( + Image(uiImage: image).resizable() + ) + } else { + return AnyView( + ActivityIndicator(style: .medium) + ) + } + } +} + +struct LoadableImageView_Previews: PreviewProvider { + static var previews: some View { + LoadableImageView(with: "https://i.juick.com/a/1.png") + } +} diff --git a/Juick/Views/MessageView.swift b/Juick/Views/MessageView.swift new file mode 100644 index 0000000..ffd0f19 --- /dev/null +++ b/Juick/Views/MessageView.swift @@ -0,0 +1,51 @@ +// +// MessageView.swift +// tst +// +// Created by Vitaly Takmazov on 10.12.2019. +// Copyright © 2019 com.juick. All rights reserved. +// + +import SwiftUI +import Atributika + +struct MessageView: View { + var message: Message + let all = Style.font(UIFont.preferredFont(forTextStyle: .body)) + let link = Style("a") + .foregroundColor(.blue, .normal) + .foregroundColor(.brown, .highlighted) + let configureLabel: ((AttributedLabel) -> Void) = { label in + label.numberOfLines = 0 + label.textColor = .label + } + var body: some View { + VStack(alignment: .leading) { + HStack { + LoadableImageView(with: message.user.avatar ?? "") + .frame(width: 48, height: 48, alignment: .center) + Text(message.user.uname) + .font(.headline) + .foregroundColor(.accentColor) + .fixedSize(horizontal: true, vertical: false) + } + AttributedLabelView(attributedText: (message.text ?? "") + .style(tags: link) + .styleHashtags(link) + .styleMentions(link) + .styleLinks(link) + .styleAll(all), configureLabel: configureLabel) + .fixedSize(horizontal: true, vertical: true) + message.attachment.map { + LoadableImageView(with: $0.url).scaledToFit() + } + } + } +} + +struct MessageView_Previews: PreviewProvider { + static let msg = Message() + static var previews: some View { + MessageView(message: msg) + } +} -- cgit v1.2.3