From 87951bc674c03c778a7f07f822b56ce0fe8cc441 Mon Sep 17 00:00:00 2001 From: Marcin Czachurski Date: Sat, 21 Oct 2023 09:44:40 +0200 Subject: [PATCH] Add first tips --- Vernissage/VernissageApp.swift | 4 + .../ViewModifiers/NavigationMenuButtons.swift | 5 + Vernissage/Views/HomeTimelineView.swift | 6 +- Vernissage/Views/MainView.swift | 4 + Vernissage/Widgets/ImageRowItemAsync.swift | 3 + .../Sources/WidgetsKit/Localizable.xcstrings | 102 ++++++++++++++++++ .../WidgetsKit/Tips/MainNavigationTip.swift | 29 +++++ .../WidgetsKit/Tips/MenuCustomizableTip.swift | 29 +++++ .../Tips/TimelineDoubleTapTip.swift | 29 +++++ 9 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 WidgetsKit/Sources/WidgetsKit/Tips/MainNavigationTip.swift create mode 100644 WidgetsKit/Sources/WidgetsKit/Tips/MenuCustomizableTip.swift create mode 100644 WidgetsKit/Sources/WidgetsKit/Tips/TimelineDoubleTapTip.swift diff --git a/Vernissage/VernissageApp.swift b/Vernissage/VernissageApp.swift index 2ba8074..439ecd8 100644 --- a/Vernissage/VernissageApp.swift +++ b/Vernissage/VernissageApp.swift @@ -11,6 +11,7 @@ import ClientKit import EnvironmentKit import WidgetKit import SwiftData +import TipKit @main struct VernissageApp: App { @@ -108,6 +109,9 @@ struct VernissageApp: App { UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.white.withAlphaComponent(0.7) UIPageControl.appearance().pageIndicatorTintColor = UIColor.white.withAlphaComponent(0.4) + // Configure TipKit. + try? Tips.configure([.displayFrequency(.daily), .datastoreLocation(.applicationDefault)]) + // Set custom configurations for Nuke image/data loaders. self.setImagePipelines() diff --git a/Vernissage/ViewModifiers/NavigationMenuButtons.swift b/Vernissage/ViewModifiers/NavigationMenuButtons.swift index d47418f..7358db7 100644 --- a/Vernissage/ViewModifiers/NavigationMenuButtons.swift +++ b/Vernissage/ViewModifiers/NavigationMenuButtons.swift @@ -8,6 +8,8 @@ import Foundation import SwiftUI import EnvironmentKit import ServicesKit +import TipKit +import WidgetsKit @MainActor extension View { @@ -22,6 +24,7 @@ private struct NavigationMenuButtons: ViewModifier { @Environment(RouterPath.self) var routerPath @Environment(\.modelContext) private var modelContext + private let menuCustomizableTip = MenuCustomizableTip() private let onViewModeIconTap: (MainView.ViewMode) -> Void private let imageFontSize = 20.0 @@ -102,6 +105,7 @@ private struct NavigationMenuButtons: ViewModifier { .background(.ultraThinMaterial) .clipShape(Circle()) } + .popoverTip(menuCustomizableTip, arrowEdge: .bottom) } else { HStack(alignment: .center) { self.composeImageView() @@ -119,6 +123,7 @@ private struct NavigationMenuButtons: ViewModifier { .background(.ultraThinMaterial) .clipShape(Capsule()) } + .popoverTip(menuCustomizableTip, arrowEdge: .bottom) } } diff --git a/Vernissage/Views/HomeTimelineView.swift b/Vernissage/Views/HomeTimelineView.swift index 8d2c0f7..593b5d2 100644 --- a/Vernissage/Views/HomeTimelineView.swift +++ b/Vernissage/Views/HomeTimelineView.swift @@ -11,6 +11,7 @@ import ClientKit import ServicesKit import EnvironmentKit import WidgetsKit +import TipKit @MainActor struct HomeTimelineView: View { @@ -28,6 +29,7 @@ struct HomeTimelineView: View { private let defaultLimit = 80 private let imagePrefetcher = ImagePrefetcher(destination: .diskCache) + private let timelineDoubleTapTip = TimelineDoubleTapTip() var body: some View { switch state { @@ -56,6 +58,8 @@ struct HomeTimelineView: View { ZStack { ScrollView { LazyVStack(alignment: .center) { + TipView(timelineDoubleTapTip) + ForEach(self.statusViewModels, id: \.id) { item in if self.shouldUpToDateBeVisible(statusId: item.id) { self.upToDatePlaceholder() @@ -80,7 +84,7 @@ struct HomeTimelineView: View { } } } - + self.newPhotosView() .offset(y: self.offset) .opacity(self.opacity) diff --git a/Vernissage/Views/MainView.swift b/Vernissage/Views/MainView.swift index 28f773e..5ae5879 100644 --- a/Vernissage/Views/MainView.swift +++ b/Vernissage/Views/MainView.swift @@ -11,6 +11,7 @@ import PixelfedKit import ClientKit import ServicesKit import EnvironmentKit +import WidgetsKit @MainActor struct MainView: View { @@ -27,6 +28,8 @@ struct MainView: View { self.navBarTitle = viewMode.title } } + + private let mainNavigationTip = MainNavigationTip() @Query(sort: \AccountData.acct, order: .forward) var dbAccounts: [AccountData] @@ -179,6 +182,7 @@ struct MainView: View { } .frame(width: 150) .foregroundColor(.mainTextColor) + .popoverTip(self.mainNavigationTip) } } } diff --git a/Vernissage/Widgets/ImageRowItemAsync.swift b/Vernissage/Widgets/ImageRowItemAsync.swift index b27485d..5a3ebed 100644 --- a/Vernissage/Widgets/ImageRowItemAsync.swift +++ b/Vernissage/Widgets/ImageRowItemAsync.swift @@ -207,6 +207,9 @@ struct ImageRowItemAsync: View { // Run adnimation and haptic feedback. self.showThumbImage = true HapticService.shared.fireHaptic(of: .buttonPress) + + // Mark that user performed specific action. + TimelineDoubleTapTip().invalidate(reason: .actionPerformed) // Mark favourite booleans used to show star in the timeline view. self.statusViewModel.favourited = true diff --git a/WidgetsKit/Sources/WidgetsKit/Localizable.xcstrings b/WidgetsKit/Sources/WidgetsKit/Localizable.xcstrings index 26cca94..4b13baf 100644 --- a/WidgetsKit/Sources/WidgetsKit/Localizable.xcstrings +++ b/WidgetsKit/Sources/WidgetsKit/Localizable.xcstrings @@ -1621,6 +1621,108 @@ } } } + }, + "tip.mainNavigation.message" : { + "comment" : "Main navigation tip message.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You can customize the position of main naviagation menu in the app settings." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Położenie głównego menu nawigacyjnego można dostosować w ustawieniach aplikacji." + } + } + } + }, + "tip.mainNavigation.title" : { + "comment" : "Main navigation tip title.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Menu position" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pozycja menu" + } + } + } + }, + "tip.menuCustomizable.message" : { + "comment" : "Menu customizable tip message.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You can change default option in the menu by long press on the specific option." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Domyślną opcję w menu można zmienić poprzez długie naciśnięcie określonej opcji." + } + } + } + }, + "tip.menuCustomizable.title" : { + "comment" : "Menu customizable tip title.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Changing the default options" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zmiana domyślnych opcji" + } + } + } + }, + "tip.timelineDoubleTap.message" : { + "comment" : "Timeline double tip message.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Double-tapping on a photo will result in it being favourited." + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dwukrotne dotknięcie zdjęcia spowoduje jego polubienie." + } + } + } + }, + "tip.timelineDoubleTap.title" : { + "comment" : "Timeline double tip title.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mark as favorite" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Oznacz jako ulubione" + } + } + } } }, "version" : "1.0" diff --git a/WidgetsKit/Sources/WidgetsKit/Tips/MainNavigationTip.swift b/WidgetsKit/Sources/WidgetsKit/Tips/MainNavigationTip.swift new file mode 100644 index 0000000..b328945 --- /dev/null +++ b/WidgetsKit/Sources/WidgetsKit/Tips/MainNavigationTip.swift @@ -0,0 +1,29 @@ +// +// https://mczachurski.dev +// Copyright © 2023 Marcin Czachurski and the repository contributors. +// Licensed under the Apache License 2.0. +// + +import SwiftUI +import Foundation +import TipKit + +public struct MainNavigationTip: Tip { + public var options: [TipOption] { + Tips.MaxDisplayCount(2) + } + + public var title: Text { + Text("tip.mainNavigation.title", bundle: Bundle.module, comment: "Main navigation tip title.") + } + + public var message: Text? { + Text("tip.mainNavigation.message", bundle: Bundle.module, comment: "Main navigation tip message.") + } + + public var image: Image? { + Image(systemName: "info.circle") + } + + public init() { } +} diff --git a/WidgetsKit/Sources/WidgetsKit/Tips/MenuCustomizableTip.swift b/WidgetsKit/Sources/WidgetsKit/Tips/MenuCustomizableTip.swift new file mode 100644 index 0000000..bb307d3 --- /dev/null +++ b/WidgetsKit/Sources/WidgetsKit/Tips/MenuCustomizableTip.swift @@ -0,0 +1,29 @@ +// +// https://mczachurski.dev +// Copyright © 2023 Marcin Czachurski and the repository contributors. +// Licensed under the Apache License 2.0. +// + +import SwiftUI +import Foundation +import TipKit + +public struct MenuCustomizableTip: Tip { + public var options: [TipOption] { + Tips.MaxDisplayCount(2) + } + + public var title: Text { + Text("tip.menuCustomizable.title", bundle: Bundle.module, comment: "Menu customizable tip title.") + } + + public var message: Text? { + Text("tip.menuCustomizable.message", bundle: Bundle.module, comment: "Menu customizable tip message.") + } + + public var image: Image? { + Image(systemName: "hand.tap") + } + + public init() { } +} diff --git a/WidgetsKit/Sources/WidgetsKit/Tips/TimelineDoubleTapTip.swift b/WidgetsKit/Sources/WidgetsKit/Tips/TimelineDoubleTapTip.swift new file mode 100644 index 0000000..f12ce67 --- /dev/null +++ b/WidgetsKit/Sources/WidgetsKit/Tips/TimelineDoubleTapTip.swift @@ -0,0 +1,29 @@ +// +// https://mczachurski.dev +// Copyright © 2023 Marcin Czachurski and the repository contributors. +// Licensed under the Apache License 2.0. +// + +import SwiftUI +import Foundation +import TipKit + +public struct TimelineDoubleTapTip: Tip { + public var options: [TipOption] { + Tips.MaxDisplayCount(5) + } + + public var title: Text { + Text("tip.timelineDoubleTap.title", bundle: Bundle.module, comment: "Timeline double tip title.") + } + + public var message: Text? { + Text("tip.timelineDoubleTap.message", bundle: Bundle.module, comment: "Timeline double tip message.") + } + + public var image: Image? { + Image(systemName: "star") + } + + public init() { } +}