-
-
Save fabiogiolito/67c0fe45972685b5101594e75bb7f35b to your computer and use it in GitHub Desktop.
// | |
// InstaStories.swift | |
// SwiftUITests | |
// | |
// Created by Fabio Giolito on 23/06/2019. | |
// Copyright © 2019 Fabio Giolito. All rights reserved. | |
// | |
import Combine | |
import SwiftUI | |
struct Story: Identifiable { | |
var id: Int | |
var user: String | |
var videos: [Int] | |
} | |
struct InstaStories : View { | |
var stories = [ | |
Story(id: 0, user: "cat", videos: [0, 1, 2]), | |
Story(id: 1, user: "hand", videos: [0, 1, 2, 3]), | |
Story(id: 2, user: "man", videos: [0, 1]) | |
] | |
@State var currentStory: Int = 0 | |
@State var currentVideo: Int = 0 | |
var body: some View { | |
ZStack { | |
ForEach(stories.reversed()) { story in | |
ZStack { | |
ForEach(story.videos.identified(by: \.self)) { video in | |
Image("Story\(story.id)Video\(video)").resizable() | |
.opacity(self.isVisible(story: story.id, video: video) ? 1 : 0) | |
} | |
// Overlay UI | |
VStack { | |
HStack { | |
ForEach(story.videos.identified(by: \.self)) { video in | |
ZStack(alignment: .leading) { | |
if (self.isVisible(story: story.id, video: video)) { | |
Rectangle() | |
} | |
Rectangle().opacity(0.3) | |
}.frame(height: 4).cornerRadius(2) | |
} | |
} | |
AvatarBar(userAvatar: story.user, userName: story.user) | |
Spacer() | |
CommentsBar() | |
} | |
.foregroundColor(.white) | |
.padding() | |
}.offset(x: CGFloat(story.id - self.currentStory) * UIScreen.main.bounds.width) | |
.animation(.fluidSpring()) | |
} | |
// Navigation buttons | |
HStack { | |
Rectangle().opacity(0).tapAction { self.prevVideo() } | |
Rectangle().opacity(0).tapAction { self.nextVideo() } | |
} | |
}.cornerRadius(20).clipped() | |
} | |
func isVisible(story: Int, video: Int) -> Bool { | |
if (video == 0) { return true } | |
if (story < currentStory || (story == currentStory && video <= currentVideo)) { return true } | |
return false | |
} | |
func prevVideo() { | |
if (currentVideo > 0) { | |
currentVideo -= 1 | |
} else if (currentStory > 0) { | |
currentStory -= 1 | |
currentVideo = stories[currentStory].videos.count - 1 | |
print("prev story") | |
} else { | |
print("at lower limit") | |
} | |
} | |
func nextVideo() { | |
if (currentVideo < stories[currentStory].videos.count - 1) { | |
currentVideo += 1 | |
} else if (currentStory < stories.count - 1) { | |
currentStory += 1 | |
currentVideo = 0 | |
print("next story") | |
} else { | |
print("at top limit") | |
} | |
} | |
} | |
struct AvatarBar : View { | |
var userAvatar: String | |
var userName: String | |
var body: some View { | |
HStack { | |
Image(userAvatar).resizable().frame(width: 40, height: 40) | |
Text(userName) | |
Spacer() | |
Image(systemName: "xmark") | |
} | |
} | |
} | |
struct CommentsBar : View { | |
var body: some View { | |
HStack { | |
HStack { | |
Image(systemName: "camera.fill") | |
} | |
.frame(width: 40, height: 40) | |
.border(Color.white, width: 1, cornerRadius: 20) | |
HStack { | |
Text("Send message") | |
Spacer() | |
Image(systemName: "ellipsis") | |
} | |
.padding(.horizontal) | |
.frame(height: 40) | |
.border(Color.white, width: 1, cornerRadius: 20) | |
Image(systemName: "paperplane").imageScale(.large) | |
} | |
} | |
} | |
#if DEBUG | |
struct InstaStories_Previews : PreviewProvider { | |
static var previews: some View { | |
InstaStories() | |
} | |
} | |
#endif |
Try using .onAppear { }
.onAppear {
Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { (timer) in
self.nextVideo()
}
}
Put at the end of the main body
Try using .onAppear { }
@davidahouse Thank you. Can't use it on body, but works as expected when added to the first child.
Still some ways to go, I need to move it to a variable so I can restart it when user taps to move forward/backwards. And call .fire()
from that .onAppear
method. I'll get back to this later and update the gist.
Thanks again!
Yeah I'm still working on how to describe where to put stuff in SwiftUI. I should have said added to the last child of body, that would have been more clear. And yeah those updates sound good so you have more control over the timer. Then you could put a button or something to toggle the timer on/off too. Good work!
Also check you Facebook reactions in SwiftUI: https://gist.github.com/fabiogiolito/424e1d68766fc054ad4bf6fd3506e9c3
Two things I wasn't able to do yet:
For Timer I tried
But this keeps setting multiple timers.
For progress animation I tried replacing lines 45 to 47 with:
But bars on next stories keep growing shrinking and doesn't work correctly when you go back one step.