Skip to content

Commit e9da8de

Browse files
authored
title (#218)
1 parent 1127700 commit e9da8de

File tree

12 files changed

+1779
-575
lines changed

12 files changed

+1779
-575
lines changed

Sora/ContentView.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ struct ContentView: View {
5555
.searchable(text: $searchQuery)
5656
} else {
5757
ZStack(alignment: .bottom) {
58-
Group {
58+
ZStack {
5959
tabView(for: selectedTab)
60+
.id(selectedTab)
61+
.transition(.opacity)
62+
.animation(.easeInOut(duration: 0.3), value: selectedTab)
6063
}
6164
.onPreferenceChange(TabBarVisibilityKey.self) { shouldShowTabBar = $0 }
6265

Sora/Info.plist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<string>de</string>
2020
<string>it</string>
2121
<string>kk</string>
22+
<string>mn</string>
2223
<string>nn</string>
2324
<string>ru</string>
2425
<string>sk</string>

Sora/Localization/mn.lproj/Localizable.strings

Lines changed: 467 additions & 0 deletions
Large diffs are not rendered by default.

Sora/MediaUtils/CustomPlayer/Components/MusicProgressSlider.swift

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,8 @@ struct MusicProgressSlider<T: BinaryFloatingPoint>: View {
3333
VStack(spacing: 8) {
3434
ZStack(alignment: .center) {
3535
ZStack(alignment: .center) {
36-
// Intro Segments
37-
ForEach(introSegments, id: \.self) { segment in
38-
HStack(spacing: 0) {
39-
Spacer()
40-
.frame(width: bounds.size.width * CGFloat(segment.lowerBound))
41-
Rectangle()
42-
.fill(introColor.opacity(0.5))
43-
.frame(width: bounds.size.width * CGFloat(segment.upperBound - segment.lowerBound))
44-
Spacer()
45-
}
46-
}
47-
48-
// Outro Segments
49-
ForEach(outroSegments, id: \.self) { segment in
50-
HStack(spacing: 0) {
51-
Spacer()
52-
.frame(width: bounds.size.width * CGFloat(segment.lowerBound))
53-
Rectangle()
54-
.fill(outroColor.opacity(0.5))
55-
.frame(width: bounds.size.width * CGFloat(segment.upperBound - segment.lowerBound))
56-
Spacer()
57-
}
58-
}
59-
6036
Capsule()
61-
.fill(emptyColor)
37+
.fill(.ultraThinMaterial)
6238
}
6339
.clipShape(Capsule())
6440

@@ -77,6 +53,28 @@ struct MusicProgressSlider<T: BinaryFloatingPoint>: View {
7753
Spacer(minLength: 0)
7854
}
7955
})
56+
57+
ForEach(introSegments, id: \.self) { segment in
58+
HStack(spacing: 0) {
59+
Spacer()
60+
.frame(width: bounds.size.width * CGFloat(segment.lowerBound))
61+
Rectangle()
62+
.fill(introColor.opacity(0.5))
63+
.frame(width: bounds.size.width * CGFloat(segment.upperBound - segment.lowerBound))
64+
Spacer()
65+
}
66+
}
67+
68+
ForEach(outroSegments, id: \.self) { segment in
69+
HStack(spacing: 0) {
70+
Spacer()
71+
.frame(width: bounds.size.width * CGFloat(segment.lowerBound))
72+
Rectangle()
73+
.fill(outroColor.opacity(0.5))
74+
.frame(width: bounds.size.width * CGFloat(segment.upperBound - segment.lowerBound))
75+
Spacer()
76+
}
77+
}
8078
}
8179

8280
HStack {

Sora/MediaUtils/CustomPlayer/Components/VolumeSlider.swift

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct VolumeSlider<T: BinaryFloatingPoint>: View {
2121
@State private var localTempProgress: T = 0
2222
@State private var lastVolumeValue: T = 0
2323
@GestureState private var isActive: Bool = false
24+
@State private var isAtEnd: Bool = false
2425

2526
var body: some View {
2627
GeometryReader { bounds in
@@ -51,8 +52,9 @@ struct VolumeSlider<T: BinaryFloatingPoint>: View {
5152
handleIconTap()
5253
}
5354
}
54-
.frame(width: isActive ? bounds.size.width * 1.02 : bounds.size.width, alignment: .center)
55+
.frame(width: getStretchWidth(bounds: bounds), alignment: .center)
5556
.animation(animation, value: isActive)
57+
.animation(animation, value: isAtEnd)
5658
}
5759
.frame(width: bounds.size.width, height: bounds.size.height)
5860
.gesture(
@@ -61,16 +63,26 @@ struct VolumeSlider<T: BinaryFloatingPoint>: View {
6163
.onChanged { gesture in
6264
let delta = gesture.translation.width / bounds.size.width
6365
localTempProgress = T(delta)
66+
67+
let totalProgress = localRealProgress + localTempProgress
68+
if totalProgress <= 0.0 || totalProgress >= 1.0 {
69+
isAtEnd = true
70+
} else {
71+
isAtEnd = false
72+
}
73+
6474
value = sliderValueInRange()
6575
}
6676
.onEnded { _ in
6777
localRealProgress = max(min(localRealProgress + localTempProgress, 1), 0)
6878
localTempProgress = 0
79+
isAtEnd = false
6980
}
7081
)
7182
.onChange(of: isActive) { newValue in
7283
if !newValue {
7384
value = sliderValueInRange()
85+
isAtEnd = false
7486
}
7587
onEditingChanged(newValue)
7688
}
@@ -91,7 +103,7 @@ struct VolumeSlider<T: BinaryFloatingPoint>: View {
91103
}
92104
}
93105
}
94-
.frame(height: isActive ? height * 1.25 : height)
106+
.frame(height: getStretchHeight())
95107
}
96108

97109
private var getIconName: String {
@@ -133,9 +145,12 @@ struct VolumeSlider<T: BinaryFloatingPoint>: View {
133145
}
134146

135147
private var animation: Animation {
136-
isActive
137-
? .spring()
138-
: .spring(response: 0.5, dampingFraction: 0.5, blendDuration: 0.6)
148+
.interpolatingSpring(
149+
mass: 1.0,
150+
stiffness: 100,
151+
damping: 15,
152+
initialVelocity: 0.0
153+
)
139154
}
140155

141156
private func progress(for val: T) -> T {
@@ -150,4 +165,25 @@ struct VolumeSlider<T: BinaryFloatingPoint>: View {
150165
+ inRange.lowerBound
151166
return max(min(rawVal, inRange.upperBound), inRange.lowerBound)
152167
}
168+
169+
private func getStretchWidth(bounds: GeometryProxy) -> CGFloat {
170+
let baseWidth = bounds.size.width
171+
if isAtEnd {
172+
return baseWidth * 1.08
173+
} else if isActive {
174+
return baseWidth * 1.04
175+
} else {
176+
return baseWidth
177+
}
178+
}
179+
180+
private func getStretchHeight() -> CGFloat {
181+
if isAtEnd {
182+
return height * 1.35
183+
} else if isActive {
184+
return height * 1.25
185+
} else {
186+
return height
187+
}
188+
}
153189
}

0 commit comments

Comments
 (0)