Compare commits
1 Commits
preferred-
...
fixes
| Author | SHA1 | Date | |
|---|---|---|---|
|
488ec8e009
|
@@ -31,6 +31,7 @@
|
||||
3AAA95CA298DF87B00F3D526 /* TranslationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA95C9298DF87B00F3D526 /* TranslationService.swift */; };
|
||||
3AAA95CC298E07E900F3D526 /* DeepLPlan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA95CB298E07E900F3D526 /* DeepLPlan.swift */; };
|
||||
3AAC7A022A60FE72002B50DF /* LocalizationUtilTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC7A012A60FE72002B50DF /* LocalizationUtilTests.swift */; };
|
||||
3AAC7A042A626A75002B50DF /* CarouselDotsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC7A032A626A75002B50DF /* CarouselDotsView.swift */; };
|
||||
3AB72AB9298ECF30004BB58C /* Translator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB72AB8298ECF30004BB58C /* Translator.swift */; };
|
||||
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685A297633BC00C46468 /* InfoPlist.strings */; };
|
||||
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685D297633BC00C46468 /* Localizable.strings */; };
|
||||
@@ -441,6 +442,7 @@
|
||||
3AAA95C9298DF87B00F3D526 /* TranslationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationService.swift; sourceTree = "<group>"; };
|
||||
3AAA95CB298E07E900F3D526 /* DeepLPlan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLPlan.swift; sourceTree = "<group>"; };
|
||||
3AAC7A012A60FE72002B50DF /* LocalizationUtilTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationUtilTests.swift; sourceTree = "<group>"; };
|
||||
3AAC7A032A626A75002B50DF /* CarouselDotsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselDotsView.swift; sourceTree = "<group>"; };
|
||||
3AB5B86A2986D8A3006599D2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
3AB5B86B2986D8A3006599D2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
3AB5B86C2986D8A3006599D2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
@@ -1435,6 +1437,7 @@
|
||||
4C8D00C929DF80350036AF10 /* TruncatedText.swift */,
|
||||
4C28595F2A12A2BE004746F7 /* SupporterBadge.swift */,
|
||||
5C6E1DAC2A193EC2008FC15A /* GradientButtonStyle.swift */,
|
||||
3AAC7A032A626A75002B50DF /* CarouselDotsView.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
@@ -1876,6 +1879,7 @@
|
||||
4CB883B6297730E400DC99E7 /* LNUrls.swift in Sources */,
|
||||
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */,
|
||||
4C633350283D40E500B1C9C3 /* HomeModel.swift in Sources */,
|
||||
3AAC7A042A626A75002B50DF /* CarouselDotsView.swift in Sources */,
|
||||
4C987B57283FD07F0042CE38 /* FollowersModel.swift in Sources */,
|
||||
3AB72AB9298ECF30004BB58C /* Translator.swift in Sources */,
|
||||
4C363A9028247A1D006E126D /* NostrLink.swift in Sources */,
|
||||
|
||||
65
damus/Components/CarouselDotsView.swift
Normal file
65
damus/Components/CarouselDotsView.swift
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// CarouselDotsView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by Terry Yiu on 7/15/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CarouselDotsView: View {
|
||||
let maxCount: Int
|
||||
let maxVisibleCount: Int
|
||||
@Binding var selectedIndex: Int
|
||||
|
||||
var body: some View {
|
||||
if maxCount > 1 {
|
||||
HStack {
|
||||
let visibleRange = visibleRange()
|
||||
ForEach(0 ..< maxCount, id: \.self) { index in
|
||||
if visibleRange.contains(index) {
|
||||
Circle()
|
||||
.fill(index == selectedIndex ? Color("DamusPurple") : Color("DamusLightGrey"))
|
||||
.frame(width: 10, height: 10)
|
||||
.onTapGesture {
|
||||
selectedIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, CGFloat(8))
|
||||
.id(UUID())
|
||||
}
|
||||
}
|
||||
|
||||
private func visibleRange() -> ClosedRange<Int> {
|
||||
let visibleCount = min(maxCount, maxVisibleCount)
|
||||
|
||||
let half = Int(visibleCount / 2)
|
||||
|
||||
// Keep the selected dot in the middle of the visible dots when possible.
|
||||
var minVisibleIndex: Int
|
||||
var maxVisibleIndex: Int
|
||||
|
||||
if visibleCount % 2 == 0 {
|
||||
minVisibleIndex = max(0, selectedIndex - half)
|
||||
maxVisibleIndex = min(maxCount - 1, selectedIndex + half - 1)
|
||||
} else {
|
||||
minVisibleIndex = max(0, selectedIndex - half)
|
||||
maxVisibleIndex = min(maxCount - 1, selectedIndex + half)
|
||||
}
|
||||
|
||||
// Adjust min and max to be within the bounds of what is visibly allowed.
|
||||
if (maxVisibleIndex - minVisibleIndex + 1) < visibleCount {
|
||||
if minVisibleIndex == 0 {
|
||||
maxVisibleIndex = visibleCount - 1
|
||||
} else if maxVisibleIndex == maxCount - 1 {
|
||||
minVisibleIndex = maxVisibleIndex - visibleCount + 1
|
||||
}
|
||||
} else if (maxVisibleIndex - minVisibleIndex + 1) > visibleCount {
|
||||
minVisibleIndex = maxVisibleIndex - maxVisibleCount + 1
|
||||
}
|
||||
|
||||
return minVisibleIndex...maxVisibleIndex
|
||||
}
|
||||
}
|
||||
@@ -209,30 +209,9 @@ struct ImageCarousel: View {
|
||||
.onTapGesture { }
|
||||
|
||||
// This is our custom carousel image indicator
|
||||
CarouselDotsView(urls: urls, selectedIndex: $selectedIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Custom Carousel
|
||||
struct CarouselDotsView<T>: View {
|
||||
let urls: [T]
|
||||
@Binding var selectedIndex: Int
|
||||
|
||||
var body: some View {
|
||||
if urls.count > 1 {
|
||||
HStack {
|
||||
ForEach(urls.indices, id: \.self) { index in
|
||||
Circle()
|
||||
.fill(index == selectedIndex ? Color("DamusPurple") : Color("DamusLightGrey"))
|
||||
.frame(width: 10, height: 10)
|
||||
.onTapGesture {
|
||||
selectedIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.top, CGFloat(8))
|
||||
.id(UUID())
|
||||
// A maximum of 18 should be visible. Any more than that and it starts to push the frame of the parent view
|
||||
// causing adjacent views to disort in dimensions.
|
||||
CarouselDotsView(maxCount: urls.count, maxVisibleCount: 18, selectedIndex: $selectedIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +18,6 @@ struct ImageView: View {
|
||||
|
||||
let disable_animation: Bool
|
||||
|
||||
var tabViewIndicator: some View {
|
||||
HStack(spacing: 10) {
|
||||
ForEach(urls.indices, id: \.self) { index in
|
||||
Capsule()
|
||||
.fill(index == selectedIndex ? Color(UIColor.label) : Color.secondary)
|
||||
.frame(width: 7, height: 7)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(.regularMaterial)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color(.systemBackground)
|
||||
@@ -66,7 +53,7 @@ struct ImageView: View {
|
||||
Spacer()
|
||||
|
||||
if (urls.count > 1) {
|
||||
tabViewIndicator
|
||||
CarouselDotsView(maxCount: urls.count, maxVisibleCount: 18, selectedIndex: $selectedIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user