mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +00:00
Fixes (#170)
* Fixed episodecells getting stuck sliding
* Enabled device scaling for ipad
not good enough yet, not applied everywhere cuz idk where to apply exactly 💯
* Fixed blur in continue watching cells
* Keyboard controls player
* fixed downloadview buttons
* Reduced tab bar outline opacity
* Increased module selector hitbox
* Fixed module add view
* Fixed mediainfoview issues (description) + changed settingsviewdata footer
medainfoview:
1: no swipe to go back
2: image shadows were fucked
* Fixes
This commit is contained in:
parent
75c9d6bf07
commit
eaa6a6d9e0
8 changed files with 211 additions and 126 deletions
|
|
@ -318,6 +318,9 @@
|
|||
},
|
||||
"Open in AniList" : {
|
||||
|
||||
},
|
||||
"Original Poster" : {
|
||||
|
||||
},
|
||||
"Play" : {
|
||||
|
||||
|
|
@ -339,9 +342,6 @@
|
|||
},
|
||||
"Remove" : {
|
||||
|
||||
},
|
||||
"Remove All Caches" : {
|
||||
|
||||
},
|
||||
"Remove Documents" : {
|
||||
|
||||
|
|
@ -366,9 +366,6 @@
|
|||
},
|
||||
"Reset Progress" : {
|
||||
|
||||
},
|
||||
"Revert Module Poster" : {
|
||||
|
||||
},
|
||||
"Running Sora %@ - cranci1" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,20 +22,20 @@ struct ModuleAdditionSettingsView: View {
|
|||
ZStack {
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
colorScheme == .light ? Color.black : Color.white,
|
||||
Color.accentColor.opacity(0.08)
|
||||
colorScheme == .dark ? Color.black : Color.white,
|
||||
Color.accentColor.opacity(0.05)
|
||||
]),
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
.ignoresSafeArea()
|
||||
.ignoresSafeArea()
|
||||
|
||||
VStack(spacing: 0) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Capsule()
|
||||
.frame(width: 40, height: 5)
|
||||
.foregroundColor(Color(.systemGray4))
|
||||
.foregroundColor(Color(.systemGray3))
|
||||
.padding(.top, 10)
|
||||
Spacer()
|
||||
}
|
||||
|
|
@ -57,17 +57,22 @@ struct ModuleAdditionSettingsView: View {
|
|||
}
|
||||
.frame(width: 90, height: 90)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 22, style: .continuous))
|
||||
.shadow(color: Color.accentColor.opacity(0.18), radius: 10, x: 0, y: 6)
|
||||
.shadow(
|
||||
color: colorScheme == .dark
|
||||
? Color.black.opacity(0.3)
|
||||
: Color.accentColor.opacity(0.15),
|
||||
radius: 10, x: 0, y: 6
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 22)
|
||||
.stroke(Color.accentColor, lineWidth: 2)
|
||||
.stroke(Color.accentColor.opacity(0.8), lineWidth: 2)
|
||||
)
|
||||
.padding(.top, 10)
|
||||
|
||||
VStack(spacing: 6) {
|
||||
Text(metadata.sourceName)
|
||||
.font(.system(size: 28, weight: .bold, design: .rounded))
|
||||
.foregroundColor(.primary)
|
||||
.foregroundColor(colorScheme == .dark ? .white : .black)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.top, 6)
|
||||
|
||||
|
|
@ -84,14 +89,19 @@ struct ModuleAdditionSettingsView: View {
|
|||
}
|
||||
.frame(width: 32, height: 32)
|
||||
.clipShape(Circle())
|
||||
.shadow(radius: 2)
|
||||
.shadow(
|
||||
color: colorScheme == .dark
|
||||
? Color.black.opacity(0.4)
|
||||
: Color.gray.opacity(0.3),
|
||||
radius: 2
|
||||
)
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text(metadata.author.name)
|
||||
.font(.headline)
|
||||
.foregroundColor(.primary)
|
||||
.foregroundColor(colorScheme == .dark ? .white : .black)
|
||||
Text("Author")
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
.foregroundColor(colorScheme == .dark ? Color.white.opacity(0.7) : Color.black.opacity(0.6))
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
|
|
@ -99,7 +109,11 @@ struct ModuleAdditionSettingsView: View {
|
|||
.padding(.vertical, 8)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(Color.accentColor.opacity(colorScheme == .dark ? 0.13 : 0.08))
|
||||
.fill(
|
||||
colorScheme == .dark
|
||||
? Color.accentColor.opacity(0.15)
|
||||
: Color.accentColor.opacity(0.08)
|
||||
)
|
||||
)
|
||||
.padding(.top, 2)
|
||||
}
|
||||
|
|
@ -125,7 +139,7 @@ struct ModuleAdditionSettingsView: View {
|
|||
}
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 22)
|
||||
.fill(Color(.systemGray6).opacity(colorScheme == .dark ? 0.18 : 0.8))
|
||||
.fill(colorScheme == .dark ? Color.white.opacity(0.1) : Color.black.opacity(0.05))
|
||||
)
|
||||
.padding(.top, 18)
|
||||
.padding(.horizontal, 2)
|
||||
|
|
@ -142,7 +156,7 @@ struct ModuleAdditionSettingsView: View {
|
|||
.padding(16)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 18)
|
||||
.fill(Color(.systemGray6).opacity(colorScheme == .dark ? 0.13 : 0.85))
|
||||
.fill(colorScheme == .dark ? Color.white.opacity(0.08) : Color.black.opacity(0.04))
|
||||
)
|
||||
.padding(.top, 18)
|
||||
}
|
||||
|
|
@ -152,8 +166,10 @@ struct ModuleAdditionSettingsView: View {
|
|||
VStack(spacing: 20) {
|
||||
ProgressView()
|
||||
.scaleEffect(1.5)
|
||||
.tint(.accentColor)
|
||||
Text("Loading module information...")
|
||||
.foregroundColor(.secondary)
|
||||
.foregroundColor(colorScheme == .dark ? Color.white.opacity(0.7) : Color.black.opacity(0.6))
|
||||
.font(.body)
|
||||
}
|
||||
.frame(maxHeight: .infinity)
|
||||
.padding(.top, 100)
|
||||
|
|
@ -165,6 +181,7 @@ struct ModuleAdditionSettingsView: View {
|
|||
Text(errorMessage)
|
||||
.foregroundColor(.red)
|
||||
.multilineTextAlignment(.center)
|
||||
.font(.body)
|
||||
}
|
||||
.frame(maxHeight: .infinity)
|
||||
.padding(.top, 100)
|
||||
|
|
@ -180,21 +197,26 @@ struct ModuleAdditionSettingsView: View {
|
|||
Text("Add Module")
|
||||
}
|
||||
.font(.headline)
|
||||
.foregroundColor(colorScheme == .light ? .black : .white)
|
||||
.foregroundColor(Color.accentColor)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 14)
|
||||
.background(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color.accentColor.opacity(0.95),
|
||||
Color.accentColor.opacity(0.7)
|
||||
colorScheme == .dark ? Color.white : Color.black,
|
||||
colorScheme == .dark ? Color.white.opacity(0.9) : Color.black.opacity(0.9)
|
||||
]),
|
||||
startPoint: .leading,
|
||||
endPoint: .trailing
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 18))
|
||||
)
|
||||
.shadow(color: Color.accentColor.opacity(0.18), radius: 8, x: 0, y: 4)
|
||||
.shadow(
|
||||
color: colorScheme == .dark
|
||||
? Color.black.opacity(0.3)
|
||||
: Color.accentColor.opacity(0.25),
|
||||
radius: 8, x: 0, y: 4
|
||||
)
|
||||
.padding(.horizontal, 20)
|
||||
}
|
||||
.disabled(isLoading || moduleMetadata == nil)
|
||||
|
|
@ -203,7 +225,7 @@ struct ModuleAdditionSettingsView: View {
|
|||
Button(action: { presentationMode.wrappedValue.dismiss() }) {
|
||||
Text("Cancel")
|
||||
.font(.body)
|
||||
.foregroundColor(.secondary)
|
||||
.foregroundColor(colorScheme == .dark ? Color.white.opacity(0.7) : Color.black.opacity(0.6))
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
|
|
@ -271,18 +293,19 @@ struct FancyInfoTile: View {
|
|||
let icon: String
|
||||
let label: String
|
||||
let value: String
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 4) {
|
||||
Image(systemName: icon)
|
||||
.font(.system(size: 18, weight: .semibold))
|
||||
.foregroundColor(.accentColor)
|
||||
.foregroundColor(colorScheme == .dark ? .white : .black)
|
||||
Text(label)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
.foregroundColor(colorScheme == .dark ? Color.white.opacity(0.6) : Color.black.opacity(0.5))
|
||||
Text(value)
|
||||
.font(.system(size: 15, weight: .semibold, design: .rounded))
|
||||
.foregroundColor(.primary)
|
||||
.foregroundColor(colorScheme == .dark ? .white : .black)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.7)
|
||||
}
|
||||
|
|
@ -294,16 +317,17 @@ struct FancyInfoTile: View {
|
|||
struct FancyUrlRow: View {
|
||||
let title: String
|
||||
let value: String
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 8) {
|
||||
Text(title)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.foregroundColor(colorScheme == .dark ? Color.white.opacity(0.7) : Color.black.opacity(0.6))
|
||||
Spacer()
|
||||
Text(value)
|
||||
.font(.footnote.monospaced())
|
||||
.foregroundColor(.accentColor)
|
||||
.foregroundColor(colorScheme == .dark ? .white : .black)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.onLongPressGesture {
|
||||
|
|
@ -311,7 +335,7 @@ struct FancyUrlRow: View {
|
|||
DropManager.shared.showDrop(title: "Copied to Clipboard", subtitle: "", duration: 1.0, icon: UIImage(systemName: "doc.on.clipboard.fill"))
|
||||
}
|
||||
Image(systemName: "doc.on.clipboard")
|
||||
.foregroundColor(.accentColor)
|
||||
.foregroundColor(colorScheme == .dark ? .white : .black)
|
||||
.font(.system(size: 14))
|
||||
.onTapGesture {
|
||||
UIPasteboard.general.string = value
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ struct EpisodeCell: View {
|
|||
@State private var lastLoggedStatus: EpisodeDownloadStatus?
|
||||
@State private var downloadAnimationScale: CGFloat = 1.0
|
||||
|
||||
@State private var isActionsVisible = false
|
||||
@State private var panGesture = UIPanGestureRecognizer()
|
||||
|
||||
@State private var swipeOffset: CGFloat = 0
|
||||
@State private var isShowingActions: Bool = false
|
||||
@State private var actionButtonWidth: CGFloat = 60
|
||||
@State private var dragState: DragState = .inactive
|
||||
|
||||
@State private var retryAttempts: Int = 0
|
||||
private let maxRetryAttempts: Int = 3
|
||||
|
|
@ -186,28 +188,73 @@ struct EpisodeCell: View {
|
|||
)
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 15))
|
||||
.offset(x: swipeOffset + dragState.translation.width)
|
||||
.offset(x: swipeOffset)
|
||||
.zIndex(1)
|
||||
.scaleEffect(dragState.isActive ? 0.98 : 1.0)
|
||||
.animation(.spring(response: 0.4, dampingFraction: 0.8), value: swipeOffset)
|
||||
.animation(.spring(response: 0.3, dampingFraction: 0.6), value: dragState.isActive)
|
||||
.animation(.spring(response: 0.3, dampingFraction: 0.8), value: swipeOffset)
|
||||
.contextMenu {
|
||||
contextMenuContent
|
||||
}
|
||||
.simultaneousGesture(
|
||||
DragGesture(coordinateSpace: .local)
|
||||
.highPriorityGesture(
|
||||
DragGesture(minimumDistance: 10)
|
||||
.onChanged { value in
|
||||
handleDragChanged(value)
|
||||
let horizontalTranslation = value.translation.width
|
||||
let verticalTranslation = value.translation.height
|
||||
|
||||
// Only handle if it's a clear horizontal swipe
|
||||
if abs(horizontalTranslation) > abs(verticalTranslation) * 1.5 {
|
||||
if horizontalTranslation < 0 {
|
||||
let maxSwipe = calculateMaxSwipeDistance()
|
||||
swipeOffset = max(horizontalTranslation, -maxSwipe)
|
||||
} else if isShowingActions {
|
||||
let maxSwipe = calculateMaxSwipeDistance()
|
||||
swipeOffset = max(horizontalTranslation - maxSwipe, -maxSwipe)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onEnded { value in
|
||||
handleDragEnded(value)
|
||||
let horizontalTranslation = value.translation.width
|
||||
let verticalTranslation = value.translation.height
|
||||
|
||||
// Only handle if it was a clear horizontal swipe
|
||||
if abs(horizontalTranslation) > abs(verticalTranslation) * 1.5 {
|
||||
let maxSwipe = calculateMaxSwipeDistance()
|
||||
let threshold = maxSwipe * 0.2
|
||||
|
||||
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
|
||||
if horizontalTranslation < -threshold && !isShowingActions {
|
||||
swipeOffset = -maxSwipe
|
||||
isShowingActions = true
|
||||
} else if horizontalTranslation > threshold && isShowingActions {
|
||||
swipeOffset = 0
|
||||
isShowingActions = false
|
||||
} else {
|
||||
swipeOffset = isShowingActions ? -maxSwipe : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
.onTapGesture {
|
||||
handleTap()
|
||||
if isShowingActions {
|
||||
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
|
||||
swipeOffset = 0
|
||||
isShowingActions = false
|
||||
}
|
||||
} else if isMultiSelectMode {
|
||||
onSelectionChanged?(!isSelected)
|
||||
} else {
|
||||
let imageUrl = episodeImageUrl.isEmpty ? defaultBannerImage : episodeImageUrl
|
||||
onTap(imageUrl)
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
// Configure the pan gesture
|
||||
panGesture.delegate = nil
|
||||
panGesture.cancelsTouchesInView = false
|
||||
panGesture.delaysTouchesBegan = false
|
||||
panGesture.delaysTouchesEnded = false
|
||||
|
||||
updateProgress()
|
||||
updateDownloadStatus()
|
||||
if UserDefaults.standard.string(forKey: "metadataProviders") ?? "TMDB" == "TMDB" {
|
||||
|
|
@ -968,72 +1015,10 @@ struct EpisodeCell: View {
|
|||
.padding(.horizontal, 8)
|
||||
}
|
||||
|
||||
private func handleDragChanged(_ value: DragGesture.Value) {
|
||||
let translation = value.translation
|
||||
let velocity = value.velocity
|
||||
|
||||
let isHorizontalGesture = abs(translation.width) > abs(translation.height)
|
||||
let hasSignificantHorizontalMovement = abs(translation.width) > 10
|
||||
|
||||
if isHorizontalGesture && hasSignificantHorizontalMovement {
|
||||
dragState = .dragging(translation: .zero)
|
||||
|
||||
let proposedOffset = swipeOffset + translation.width
|
||||
let maxSwipe = calculateMaxSwipeDistance()
|
||||
|
||||
if translation.width < 0 {
|
||||
let newOffset = max(proposedOffset, -maxSwipe)
|
||||
if proposedOffset < -maxSwipe {
|
||||
let resistance = abs(proposedOffset + maxSwipe) * 0.15
|
||||
swipeOffset = -maxSwipe - resistance
|
||||
} else {
|
||||
swipeOffset = newOffset
|
||||
}
|
||||
} else if isShowingActions {
|
||||
swipeOffset = max(proposedOffset, -maxSwipe)
|
||||
}
|
||||
} else if !hasSignificantHorizontalMovement {
|
||||
dragState = .inactive
|
||||
}
|
||||
}
|
||||
|
||||
private func handleDragEnded(_ value: DragGesture.Value) {
|
||||
let translation = value.translation
|
||||
let velocity = value.velocity
|
||||
|
||||
dragState = .inactive
|
||||
|
||||
let isHorizontalGesture = abs(translation.width) > abs(translation.height)
|
||||
let hasSignificantHorizontalMovement = abs(translation.width) > 10
|
||||
|
||||
if isHorizontalGesture && hasSignificantHorizontalMovement {
|
||||
let maxSwipe = calculateMaxSwipeDistance()
|
||||
let threshold = maxSwipe * 0.3
|
||||
let velocityThreshold: CGFloat = 500
|
||||
|
||||
withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
|
||||
if translation.width < -threshold || velocity.width < -velocityThreshold {
|
||||
swipeOffset = -maxSwipe
|
||||
isShowingActions = true
|
||||
} else if translation.width > threshold || velocity.width > velocityThreshold {
|
||||
swipeOffset = 0
|
||||
isShowingActions = false
|
||||
} else {
|
||||
swipeOffset = isShowingActions ? -maxSwipe : 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
|
||||
swipeOffset = isShowingActions ? -calculateMaxSwipeDistance() : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handleTap() {
|
||||
if isShowingActions {
|
||||
if isActionsVisible {
|
||||
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
|
||||
swipeOffset = 0
|
||||
isShowingActions = false
|
||||
isActionsVisible = false
|
||||
}
|
||||
} else if isMultiSelectMode {
|
||||
onSelectionChanged?(!isSelected)
|
||||
|
|
@ -1044,18 +1029,16 @@ struct EpisodeCell: View {
|
|||
}
|
||||
|
||||
private func closeActionsIfNeeded() {
|
||||
if isShowingActions {
|
||||
if isActionsVisible {
|
||||
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
|
||||
swipeOffset = 0
|
||||
isShowingActions = false
|
||||
isActionsVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func closeActionsAndPerform(action: @escaping () -> Void) {
|
||||
withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
|
||||
swipeOffset = 0
|
||||
isShowingActions = false
|
||||
isActionsVisible = false
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
|
||||
|
|
@ -1063,3 +1046,69 @@ struct EpisodeCell: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct UIViewWrapper: UIViewRepresentable {
|
||||
let panGesture: UIPanGestureRecognizer
|
||||
let onSwipe: (SwipeDirection) -> Void
|
||||
|
||||
enum SwipeDirection {
|
||||
case left, right, none
|
||||
}
|
||||
|
||||
func makeUIView(context: Context) -> UIView {
|
||||
let view = UIView()
|
||||
view.isUserInteractionEnabled = true
|
||||
view.backgroundColor = .clear
|
||||
|
||||
// Remove any existing gesture recognizers
|
||||
if let existingGestures = view.gestureRecognizers {
|
||||
for gesture in existingGestures {
|
||||
view.removeGestureRecognizer(gesture)
|
||||
}
|
||||
}
|
||||
|
||||
// Add the pan gesture
|
||||
panGesture.addTarget(context.coordinator, action: #selector(Coordinator.handlePan(_:)))
|
||||
view.addGestureRecognizer(panGesture)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIView, context: Context) {
|
||||
// Ensure the view is user interaction enabled
|
||||
uiView.isUserInteractionEnabled = true
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(onSwipe: onSwipe)
|
||||
}
|
||||
|
||||
class Coordinator: NSObject {
|
||||
let onSwipe: (SwipeDirection) -> Void
|
||||
|
||||
init(onSwipe: @escaping (SwipeDirection) -> Void) {
|
||||
self.onSwipe = onSwipe
|
||||
}
|
||||
|
||||
@objc func handlePan(_ gesture: UIPanGestureRecognizer) {
|
||||
let translation = gesture.translation(in: gesture.view)
|
||||
let velocity = gesture.velocity(in: gesture.view)
|
||||
|
||||
if gesture.state == .ended {
|
||||
if abs(velocity.x) > abs(velocity.y) && abs(velocity.x) > 500 {
|
||||
if velocity.x < 0 {
|
||||
onSwipe(.left)
|
||||
} else {
|
||||
onSwipe(.right)
|
||||
}
|
||||
} else if abs(translation.x) > abs(translation.y) && abs(translation.x) > 50 {
|
||||
if translation.x < 0 {
|
||||
onSwipe(.left)
|
||||
} else {
|
||||
onSwipe(.right)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,6 +124,13 @@ struct MediaInfoView: View {
|
|||
.onAppear {
|
||||
buttonRefreshTrigger.toggle()
|
||||
tabBarController.hideTabBar()
|
||||
|
||||
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||
let window = windowScene.windows.first,
|
||||
let navigationController = window.rootViewController?.children.first as? UINavigationController {
|
||||
navigationController.interactivePopGestureRecognizer?.isEnabled = true
|
||||
navigationController.interactivePopGestureRecognizer?.delegate = nil
|
||||
}
|
||||
}
|
||||
.onChange(of: selectedRange) { newValue in
|
||||
UserDefaults.standard.set(newValue.lowerBound, forKey: selectedRangeKey)
|
||||
|
|
@ -224,16 +231,8 @@ struct MediaInfoView: View {
|
|||
Rectangle()
|
||||
.fill(Color.clear)
|
||||
.frame(height: 400)
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
headerSection
|
||||
if !episodeLinks.isEmpty {
|
||||
episodesSection
|
||||
} else {
|
||||
noEpisodesSection
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(
|
||||
|
||||
ZStack(alignment: .top) {
|
||||
LinearGradient(
|
||||
gradient: Gradient(stops: [
|
||||
.init(color: (colorScheme == .dark ? Color.black : Color.white).opacity(0.0), location: 0.0),
|
||||
|
|
@ -244,9 +243,20 @@ struct MediaInfoView: View {
|
|||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 0))
|
||||
.shadow(color: (colorScheme == .dark ? Color.black : Color.white).opacity(1), radius: 10, x: 0, y: 10)
|
||||
)
|
||||
.frame(height: 300)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 0))
|
||||
.shadow(color: (colorScheme == .dark ? Color.black : Color.white).opacity(1), radius: 10, x: 0, y: 10)
|
||||
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
headerSection
|
||||
if !episodeLinks.isEmpty {
|
||||
episodesSection
|
||||
} else {
|
||||
noEpisodesSection
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,10 @@ struct ModuleSelectorMenu: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(.systemGray6).opacity(0))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ struct SettingsViewData: View {
|
|||
VStack(spacing: 24) {
|
||||
SettingsSection(
|
||||
title: "App Storage",
|
||||
footer: "The app cache allow the app to sho immages faster.\n\nClearing the documents folder will remove all the modules.\n\nThe App Data should never be erased if you don't know what that will cause."
|
||||
footer: "The app cache helps the app load images faster.\n\nClearing the Documents folder will delete all downloaded modules.\n\nDo not erase App Data unless you understand the consequences — it may cause the app to malfunction."
|
||||
) {
|
||||
VStack(spacing: 0) {
|
||||
SettingsButtonRow(
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ struct SettingsViewTrackers: View {
|
|||
|
||||
SettingsSection(
|
||||
title: "Info",
|
||||
footer: "Sora and cranci1 are not affiliated with AniList nor Trakt in any way.\n\nAlso note that progresses update may not be 100% accurate."
|
||||
footer: "Sora and Cranci1 are not affiliated with AniList or Trakt in any way.\n\nAlso note that progress updates may not be 100% accurate."
|
||||
) {}
|
||||
}
|
||||
.padding(.vertical, 20)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"originHash" : "e12f82ce5205016ea66a114308acd41450cfe950ccb1aacfe0e26181d2036fa4",
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "drops",
|
||||
|
|
@ -28,5 +29,5 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
"version" : 3
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue