Add animation to showing favourite star image on timeline
This commit is contained in:
parent
dca985dcf8
commit
2fcd7bcd3c
|
@ -158,7 +158,6 @@
|
|||
F89D6C4629718193001DA3D4 /* GeneralSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C4529718193001DA3D4 /* GeneralSectionView.swift */; };
|
||||
F89D6C4A297196FF001DA3D4 /* ImageViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C49297196FF001DA3D4 /* ImageViewer.swift */; };
|
||||
F89F57B029D1C11200001EE3 /* RelationshipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89F57AF29D1C11200001EE3 /* RelationshipModel.swift */; };
|
||||
F8A4A88329E3FD1C00267E36 /* ImageAvatar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A4A88229E3FD1C00267E36 /* ImageAvatar.swift */; };
|
||||
F8A93D7E2965FD89001D8331 /* UserProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A93D7D2965FD89001D8331 /* UserProfileView.swift */; };
|
||||
F8AFF7C129B259150087D083 /* HashtagsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8AFF7C029B259150087D083 /* HashtagsView.swift */; };
|
||||
F8AFF7C429B25EF40087D083 /* ImagesGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8AFF7C329B25EF40087D083 /* ImagesGrid.swift */; };
|
||||
|
@ -176,7 +175,6 @@
|
|||
F8F6E44D29BCC1F90004795E /* MediumWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44829BCC0F00004795E /* MediumWidgetView.swift */; };
|
||||
F8F6E44E29BCC1FB0004795E /* LargeWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44A29BCC0FF0004795E /* LargeWidgetView.swift */; };
|
||||
F8F6E45129BCE9190004795E /* UIImage+Resize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E45029BCE9190004795E /* UIImage+Resize.swift */; };
|
||||
F8FFBD4829E9901E0047EE80 /* ImageFavourite.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8FFBD4729E9901E0047EE80 /* ImageFavourite.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -330,7 +328,6 @@
|
|||
F89D6C49297196FF001DA3D4 /* ImageViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewer.swift; sourceTree = "<group>"; };
|
||||
F89F0605299139F6003DC875 /* Vernissage-002.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-002.xcdatamodel"; sourceTree = "<group>"; };
|
||||
F89F57AF29D1C11200001EE3 /* RelationshipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipModel.swift; sourceTree = "<group>"; };
|
||||
F8A4A88229E3FD1C00267E36 /* ImageAvatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageAvatar.swift; sourceTree = "<group>"; };
|
||||
F8A4A88429E4099900267E36 /* Vernissage-008.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-008.xcdatamodel"; sourceTree = "<group>"; };
|
||||
F8A93D7D2965FD89001D8331 /* UserProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileView.swift; sourceTree = "<group>"; };
|
||||
F8AFF7C029B259150087D083 /* HashtagsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagsView.swift; sourceTree = "<group>"; };
|
||||
|
@ -358,7 +355,6 @@
|
|||
F8F6E44829BCC0F00004795E /* MediumWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediumWidgetView.swift; sourceTree = "<group>"; };
|
||||
F8F6E44A29BCC0FF0004795E /* LargeWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeWidgetView.swift; sourceTree = "<group>"; };
|
||||
F8F6E45029BCE9190004795E /* UIImage+Resize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Resize.swift"; sourceTree = "<group>"; };
|
||||
F8FFBD4729E9901E0047EE80 /* ImageFavourite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageFavourite.swift; sourceTree = "<group>"; };
|
||||
F8FFBD4929E99BEE0047EE80 /* Vernissage-009.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-009.xcdatamodel"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -638,8 +634,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
F88BC53A29E06A5100CE6141 /* ImageContextMenu.swift */,
|
||||
F8A4A88229E3FD1C00267E36 /* ImageAvatar.swift */,
|
||||
F8FFBD4729E9901E0047EE80 /* ImageFavourite.swift */,
|
||||
);
|
||||
path = ViewModifiers;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1080,9 +1074,7 @@
|
|||
F86B7221296C49A300EE59EC /* EmptyButtonStyle.swift in Sources */,
|
||||
F80048042961850500E6868A /* AttachmentData+CoreDataProperties.swift in Sources */,
|
||||
F88E4D4A297EA0490057491A /* RouterPath.swift in Sources */,
|
||||
F8FFBD4829E9901E0047EE80 /* ImageFavourite.swift in Sources */,
|
||||
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */,
|
||||
F8A4A88329E3FD1C00267E36 /* ImageAvatar.swift in Sources */,
|
||||
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */,
|
||||
F80048032961850500E6868A /* AttachmentData+CoreDataClass.swift in Sources */,
|
||||
F891E7D029C368750022C449 /* ImageRowItemAsync.swift in Sources */,
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the Apache License 2.0.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import NukeUI
|
||||
import ClientKit
|
||||
import ServicesKit
|
||||
import EnvironmentKit
|
||||
|
||||
public extension View {
|
||||
func imageAvatar(displayName: String?, avatarUrl: URL?) -> some View {
|
||||
modifier(ImageAvatar(displayName: displayName, avatarUrl: avatarUrl))
|
||||
}
|
||||
}
|
||||
|
||||
private struct ImageAvatar: ViewModifier {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
private let displayName: String?
|
||||
private let avatarUrl: URL?
|
||||
|
||||
init(displayName: String?, avatarUrl: URL?) {
|
||||
self.displayName = displayName
|
||||
self.avatarUrl = avatarUrl
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if self.applicationState.showAvatarsOnTimeline {
|
||||
ZStack {
|
||||
// Image.
|
||||
content
|
||||
|
||||
// Avatar.
|
||||
VStack(alignment: .leading) {
|
||||
|
||||
HStack(alignment: .center) {
|
||||
LazyImage(url: avatarUrl) { state in
|
||||
if let image = state.image {
|
||||
self.buildAvatar(image: image)
|
||||
} else if state.isLoading {
|
||||
self.buildAvatar()
|
||||
} else {
|
||||
self.buildAvatar()
|
||||
}
|
||||
}
|
||||
|
||||
Text(displayName ?? "")
|
||||
.font(.system(size: 15))
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
.fontWeight(.semibold)
|
||||
.shadow(color: .black, radius: 2)
|
||||
Spacer()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, 8)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func buildAvatar(image: Image? = nil) -> some View {
|
||||
(image ?? Image("Avatar"))
|
||||
.resizable()
|
||||
.clipShape(applicationState.avatarShape.shape())
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 24, height: 24)
|
||||
.overlay(
|
||||
applicationState.avatarShape.shape()
|
||||
.stroke(Color.white.opacity(0.6), lineWidth: 1)
|
||||
.frame(width: 24, height: 24)
|
||||
)
|
||||
.shadow(color: .black, radius: 2)
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the Apache License 2.0.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import NukeUI
|
||||
import ClientKit
|
||||
import ServicesKit
|
||||
import EnvironmentKit
|
||||
|
||||
public extension View {
|
||||
func imageFavourite(isFavourited: Binding<Bool>) -> some View {
|
||||
modifier(ImageFavourite(isFavourited: isFavourited))
|
||||
}
|
||||
}
|
||||
|
||||
private struct ImageFavourite: ViewModifier {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@Binding private var isFavourited: Bool
|
||||
|
||||
init(isFavourited: Binding<Bool>) {
|
||||
self._isFavourited = isFavourited
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if self.applicationState.showFavouritesOnTimeline && self.isFavourited {
|
||||
ZStack {
|
||||
// Image.
|
||||
content
|
||||
|
||||
// Avatar.
|
||||
VStack(alignment: .leading) {
|
||||
Spacer()
|
||||
|
||||
HStack(alignment: .center) {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.system(size: 12))
|
||||
.shadow(color: .black, radius: 4)
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding(.leading, 12)
|
||||
.padding(.bottom, 14)
|
||||
}
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,20 +42,15 @@ struct ImageRowItem: View {
|
|||
if self.status.sensitive && !self.applicationState.showSensitive {
|
||||
ZStack {
|
||||
ContentWarning(spoilerText: self.status.spoilerText) {
|
||||
self.imageView(uiImage: uiImage)
|
||||
|
||||
if showThumbImage {
|
||||
FavouriteTouch {
|
||||
self.showThumbImage = false
|
||||
}
|
||||
}
|
||||
self.imageContainerView(uiImage: uiImage)
|
||||
} blurred: {
|
||||
BlurredImage(blurhash: attachmentData.blurhash)
|
||||
.imageAvatar(displayName: self.status.accountDisplayName,
|
||||
avatarUrl: self.status.accountAvatar)
|
||||
.onTapGesture {
|
||||
self.navigateToStatus()
|
||||
}
|
||||
ZStack {
|
||||
BlurredImage(blurhash: attachmentData.blurhash)
|
||||
ImageAvatar(displayName: self.status.accountDisplayName, avatarUrl: self.status.accountAvatar)
|
||||
}
|
||||
.onTapGesture {
|
||||
self.navigateToStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
.opacity(self.opacity)
|
||||
|
@ -66,13 +61,7 @@ struct ImageRowItem: View {
|
|||
}
|
||||
} else {
|
||||
ZStack {
|
||||
self.imageView(uiImage: uiImage)
|
||||
|
||||
if showThumbImage {
|
||||
FavouriteTouch {
|
||||
self.showThumbImage = false
|
||||
}
|
||||
}
|
||||
self.imageContainerView(uiImage: uiImage)
|
||||
}
|
||||
.opacity(self.opacity)
|
||||
.onAppear {
|
||||
|
@ -108,6 +97,15 @@ struct ImageRowItem: View {
|
|||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func imageContainerView(uiImage: UIImage) -> some View {
|
||||
self.imageView(uiImage: uiImage)
|
||||
|
||||
ImageAvatar(displayName: self.status.accountDisplayName, avatarUrl: self.status.accountAvatar)
|
||||
ImageFavourite(isFavourited: $isFavourited)
|
||||
FavouriteTouch(showFavouriteAnimation: $showThumbImage)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func imageView(uiImage: UIImage) -> some View {
|
||||
Image(uiImage: uiImage)
|
||||
|
@ -129,14 +127,13 @@ struct ImageRowItem: View {
|
|||
HapticService.shared.fireHaptic(of: .buttonPress)
|
||||
|
||||
// Mark favourite booleans used to show star in the timeline view.
|
||||
self.isFavourited = true
|
||||
withAnimation(.default.delay(2.0)) {
|
||||
self.isFavourited = true
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
self.navigateToStatus()
|
||||
}
|
||||
.imageAvatar(displayName: self.status.accountDisplayName,
|
||||
avatarUrl: self.status.accountAvatar)
|
||||
.imageFavourite(isFavourited: $isFavourited)
|
||||
.imageContextMenu(statusData: self.status)
|
||||
.onAppear {
|
||||
self.isFavourited = self.status.favourited
|
||||
|
|
|
@ -42,21 +42,15 @@ struct ImageRowItemAsync: View {
|
|||
if self.statusViewModel.sensitive && !self.applicationState.showSensitive {
|
||||
ZStack {
|
||||
ContentWarning(spoilerText: self.statusViewModel.spoilerText) {
|
||||
self.imageView(image: image)
|
||||
self.imageContainerView(image: image)
|
||||
} blurred: {
|
||||
BlurredImage(blurhash: attachment.blurhash)
|
||||
.if(self.showAvatar) {
|
||||
$0.imageAvatar(displayName: self.statusViewModel.account.displayNameWithoutEmojis,
|
||||
avatarUrl: self.statusViewModel.account.avatar)
|
||||
}
|
||||
.onTapGesture {
|
||||
self.navigateToStatus()
|
||||
}
|
||||
}
|
||||
|
||||
if showThumbImage {
|
||||
FavouriteTouch {
|
||||
self.showThumbImage = false
|
||||
ZStack {
|
||||
BlurredImage(blurhash: attachment.blurhash)
|
||||
ImageAvatar(displayName: self.statusViewModel.account.displayNameWithoutEmojis,
|
||||
avatarUrl: self.statusViewModel.account.avatar)
|
||||
}
|
||||
.onTapGesture {
|
||||
self.navigateToStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,13 +66,7 @@ struct ImageRowItemAsync: View {
|
|||
}
|
||||
} else {
|
||||
ZStack {
|
||||
self.imageView(image: image)
|
||||
|
||||
if showThumbImage {
|
||||
FavouriteTouch {
|
||||
self.showThumbImage = false
|
||||
}
|
||||
}
|
||||
self.imageContainerView(image: image)
|
||||
}
|
||||
.opacity(self.opacity)
|
||||
.onAppear {
|
||||
|
@ -116,6 +104,19 @@ struct ImageRowItemAsync: View {
|
|||
.priority(.high)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func imageContainerView(image: Image) -> some View {
|
||||
self.imageView(image: image)
|
||||
|
||||
if self.showAvatar {
|
||||
ImageAvatar(displayName: self.statusViewModel.account.displayNameWithoutEmojis,
|
||||
avatarUrl: self.statusViewModel.account.avatar)
|
||||
}
|
||||
|
||||
ImageFavourite(isFavourited: $isFavourited)
|
||||
FavouriteTouch(showFavouriteAnimation: $showThumbImage)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func imageView(image: Image) -> some View {
|
||||
image
|
||||
|
@ -133,16 +134,13 @@ struct ImageRowItemAsync: View {
|
|||
|
||||
// Mark favourite booleans used to show star in the timeline view.
|
||||
self.statusViewModel.favourited = true
|
||||
self.isFavourited = true
|
||||
withAnimation(.default.delay(2.0)) {
|
||||
self.isFavourited = true
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
self.navigateToStatus()
|
||||
}
|
||||
.if(self.showAvatar) {
|
||||
$0.imageAvatar(displayName: self.statusViewModel.account.displayNameWithoutEmojis,
|
||||
avatarUrl: self.statusViewModel.account.avatar)
|
||||
}
|
||||
.imageFavourite(isFavourited: $isFavourited)
|
||||
.imageContextMenu(statusModel: self.statusViewModel)
|
||||
.onAppear {
|
||||
self.isFavourited = self.statusViewModel.favourited
|
||||
|
|
|
@ -11,41 +11,43 @@ public struct FavouriteTouch: View {
|
|||
@State private var showCircle = 0
|
||||
@State private var opacity = 1.0
|
||||
|
||||
private let finished: () -> Void
|
||||
@Binding private var showFavouriteAnimation: Bool
|
||||
|
||||
public init(finished: @escaping () -> Void) {
|
||||
self.finished = finished
|
||||
public init(showFavouriteAnimation: Binding<Bool>) {
|
||||
self._showFavouriteAnimation = showFavouriteAnimation
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
ZStack {
|
||||
Circle()
|
||||
.frame(width: 55, height: 55, alignment: .center)
|
||||
.foregroundColor(.white.opacity(0.75))
|
||||
.scaleEffect(CGFloat(showCircle))
|
||||
if self.showFavouriteAnimation {
|
||||
ZStack {
|
||||
Circle()
|
||||
.frame(width: 55, height: 55, alignment: .center)
|
||||
.foregroundColor(.white.opacity(0.75))
|
||||
.scaleEffect(CGFloat(showCircle))
|
||||
|
||||
Image(systemName: "star.fill")
|
||||
.font(.system(size: 26))
|
||||
.foregroundColor(.black.opacity(0.4))
|
||||
.clipShape(Rectangle().offset(y: CGFloat(showThumb)))
|
||||
}
|
||||
.opacity(opacity)
|
||||
.onAppear {
|
||||
withAnimation(Animation.interpolatingSpring(stiffness: 170, damping: 15)) {
|
||||
showCircle = 1
|
||||
Image(systemName: "star.fill")
|
||||
.font(.system(size: 26))
|
||||
.foregroundColor(.black.opacity(0.4))
|
||||
.clipShape(Rectangle().offset(y: CGFloat(showThumb)))
|
||||
}
|
||||
.opacity(opacity)
|
||||
.onAppear {
|
||||
withAnimation(Animation.interpolatingSpring(stiffness: 170, damping: 15)) {
|
||||
showCircle = 1
|
||||
}
|
||||
|
||||
withAnimation(Animation.easeInOut(duration: 0.5).delay(0.25)) {
|
||||
showThumb = 0
|
||||
}
|
||||
withAnimation(Animation.easeInOut(duration: 0.5).delay(0.25)) {
|
||||
showThumb = 0
|
||||
}
|
||||
|
||||
withAnimation(Animation.easeInOut(duration: 0.5).delay(1.75)) {
|
||||
opacity = 0
|
||||
withAnimation(Animation.easeInOut(duration: 0.5).delay(1.75)) {
|
||||
opacity = 0
|
||||
}
|
||||
}
|
||||
.task {
|
||||
try? await Task.sleep(nanoseconds: 2_500_000_000)
|
||||
self.showFavouriteAnimation = false
|
||||
}
|
||||
}
|
||||
.task {
|
||||
try? await Task.sleep(nanoseconds: 2_500_000_000)
|
||||
self.finished()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the Apache License 2.0.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import NukeUI
|
||||
import EnvironmentKit
|
||||
|
||||
public struct ImageAvatar: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
private let displayName: String?
|
||||
private let avatarUrl: URL?
|
||||
|
||||
public init(displayName: String?, avatarUrl: URL?) {
|
||||
self.displayName = displayName
|
||||
self.avatarUrl = avatarUrl
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
if self.applicationState.showAvatarsOnTimeline {
|
||||
VStack(alignment: .leading) {
|
||||
HStack(alignment: .center) {
|
||||
LazyImage(url: avatarUrl) { state in
|
||||
if let image = state.image {
|
||||
self.buildAvatar(image: image)
|
||||
} else if state.isLoading {
|
||||
self.buildAvatar()
|
||||
} else {
|
||||
self.buildAvatar()
|
||||
}
|
||||
}
|
||||
|
||||
Text(displayName ?? "")
|
||||
.font(.system(size: 15))
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
.fontWeight(.semibold)
|
||||
.shadow(color: .black, radius: 2)
|
||||
Spacer()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, 8)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func buildAvatar(image: Image? = nil) -> some View {
|
||||
(image ?? Image("Avatar"))
|
||||
.resizable()
|
||||
.clipShape(applicationState.avatarShape.shape())
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 24, height: 24)
|
||||
.overlay(
|
||||
applicationState.avatarShape.shape()
|
||||
.stroke(Color.white.opacity(0.6), lineWidth: 1)
|
||||
.frame(width: 24, height: 24)
|
||||
)
|
||||
.shadow(color: .black, radius: 2)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the Apache License 2.0.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import EnvironmentKit
|
||||
|
||||
public struct ImageFavourite: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@Binding private var isFavourited: Bool
|
||||
|
||||
public init(isFavourited: Binding<Bool>) {
|
||||
self._isFavourited = isFavourited
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
if self.applicationState.showFavouritesOnTimeline && self.isFavourited {
|
||||
VStack(alignment: .leading) {
|
||||
Spacer()
|
||||
|
||||
HStack(alignment: .center) {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.system(size: 12))
|
||||
.shadow(color: .black, radius: 4)
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding(.leading, 12)
|
||||
.padding(.bottom, 14)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue