diff --git a/ios/LibNovel/LibNovel/Views/Auth/AuthView.swift b/ios/LibNovel/LibNovel/Views/Auth/AuthView.swift index 7f1230c..e0c2d3d 100644 --- a/ios/LibNovel/LibNovel/Views/Auth/AuthView.swift +++ b/ios/LibNovel/LibNovel/Views/Auth/AuthView.swift @@ -96,7 +96,7 @@ struct AuthView: View { Spacer() } - .navigationBarHidden(true) + .toolbar(.hidden, for: .navigationBar) } .onChange(of: mode) { _, _ in authStore.error = nil diff --git a/ios/LibNovel/LibNovel/Views/Browse/BrowseView.swift b/ios/LibNovel/LibNovel/Views/Browse/BrowseView.swift index 3728df3..c2b150b 100644 --- a/ios/LibNovel/LibNovel/Views/Browse/BrowseView.swift +++ b/ios/LibNovel/LibNovel/Views/Browse/BrowseView.swift @@ -29,13 +29,13 @@ struct BrowseView: View { // Filter chips row ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 8) { - FilterChip(label: "Sort: \(vm.sort.capitalized)", isActive: vm.sort != "popular") { + ChipButton(label: "Sort: \(vm.sort.capitalized)", isSelected: vm.sort != "popular", style: .outlined) { showFilters = true } - FilterChip(label: "Genre: \(vm.genre == "all" ? "All" : vm.genre.capitalized)", isActive: vm.genre != "all") { + ChipButton(label: "Genre: \(vm.genre == "all" ? "All" : vm.genre.capitalized)", isSelected: vm.genre != "all", style: .outlined) { showFilters = true } - FilterChip(label: "Status: \(vm.status == "all" ? "All" : vm.status.capitalized)", isActive: vm.status != "all") { + ChipButton(label: "Status: \(vm.status == "all" ? "All" : vm.status.capitalized)", isSelected: vm.status != "all", style: .outlined) { showFilters = true } } @@ -103,25 +103,6 @@ struct BrowseView: View { } } -// MARK: - Filter chip - -private struct FilterChip: View { - let label: String - let isActive: Bool - let action: () -> Void - var body: some View { - Button(action: action) { - Text(label) - .font(.caption.bold()) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background(isActive ? Color.amber.opacity(0.15) : Color(.systemGray6), in: Capsule()) - .foregroundStyle(isActive ? .amber : .primary) - .overlay(Capsule().strokeBorder(isActive ? Color.amber : .clear, lineWidth: 1)) - } - } -} - // MARK: - Browse card private struct BrowseCard: View { diff --git a/ios/LibNovel/LibNovel/Views/Home/HomeView.swift b/ios/LibNovel/LibNovel/Views/Home/HomeView.swift index 8a1a914..96c0e07 100644 --- a/ios/LibNovel/LibNovel/Views/Home/HomeView.swift +++ b/ios/LibNovel/LibNovel/Views/Home/HomeView.swift @@ -1,5 +1,4 @@ import SwiftUI -import Kingfisher struct HomeView: View { @StateObject private var vm = HomeViewModel() @@ -100,9 +99,7 @@ private struct HeroContinueCard: View { NavigationLink(value: NavDestination.chapter(item.book.slug, item.chapter)) { ZStack(alignment: .bottomLeading) { // Blurred background - KFImage(URL(string: item.book.cover)) - .resizable() - .scaledToFill() + AsyncCoverImage(url: item.book.cover, isBackground: true) .frame(maxWidth: .infinity) .frame(height: 220) .blur(radius: 22) @@ -122,13 +119,7 @@ private struct HeroContinueCard: View { // Content: cover on left, info stacked on right HStack(alignment: .bottom, spacing: 14) { - KFImage(URL(string: item.book.cover)) - .resizable() - .placeholder { - RoundedRectangle(cornerRadius: 10) - .fill(Color(.systemGray5)) - } - .scaledToFill() + AsyncCoverImage(url: item.book.cover) .frame(width: 96, height: 138) .clipShape(RoundedRectangle(cornerRadius: 10)) .shadow(color: .black.opacity(0.55), radius: 12, y: 6) @@ -215,14 +206,7 @@ private struct ContinueReadingCard: View { var body: some View { VStack(alignment: .leading, spacing: 6) { ZStack(alignment: .bottomTrailing) { - KFImage(URL(string: item.book.cover)) - .resizable() - .placeholder { - RoundedRectangle(cornerRadius: 8) - .fill(Color(.systemGray5)) - .overlay(Image(systemName: "book.closed").foregroundStyle(.secondary)) - } - .scaledToFill() + AsyncCoverImage(url: item.book.cover) .frame(width: 110, height: 158) .clipShape(RoundedRectangle(cornerRadius: 8)) @@ -258,14 +242,7 @@ private struct ShelfBookCard: View { var body: some View { VStack(alignment: .leading, spacing: 6) { - KFImage(URL(string: book.cover)) - .resizable() - .placeholder { - RoundedRectangle(cornerRadius: 8) - .fill(Color(.systemGray5)) - .overlay(Image(systemName: "book.closed").foregroundStyle(.secondary)) - } - .scaledToFill() + AsyncCoverImage(url: book.cover) .frame(width: 110, height: 158) .clipShape(RoundedRectangle(cornerRadius: 8)) .shadow(color: .black.opacity(0.12), radius: 4, y: 2) diff --git a/ios/LibNovel/LibNovel/Views/Library/LibraryView.swift b/ios/LibNovel/LibNovel/Views/Library/LibraryView.swift index 77fdc04..123d8d7 100644 --- a/ios/LibNovel/LibNovel/Views/Library/LibraryView.swift +++ b/ios/LibNovel/LibNovel/Views/Library/LibraryView.swift @@ -235,56 +235,6 @@ struct LibraryView: View { } } -// MARK: - Genre filter chip - -private struct FilterChipView: View { - let label: String - let isSelected: Bool - let action: () -> Void - - var body: some View { - Button(action: action) { - Text(label) - .font(.caption.weight(isSelected ? .semibold : .regular)) - .padding(.horizontal, 12) - .padding(.vertical, 6) - .background( - Capsule() - .fill(isSelected ? Color.amber : Color(.systemGray5)) - ) - .foregroundStyle(isSelected ? .white : .primary) - } - .buttonStyle(.plain) - } -} - -// MARK: - Sort chip - -private struct SortChip: View { - let label: String - let isSelected: Bool - let action: () -> Void - - var body: some View { - Button(action: action) { - Text(label) - .font(.subheadline.weight(isSelected ? .semibold : .regular)) - .padding(.horizontal, 14) - .padding(.vertical, 6) - .background( - Capsule() - .fill(isSelected ? Color.amber.opacity(0.15) : Color(.systemGray6)) - .overlay( - Capsule() - .stroke(isSelected ? Color.amber : .clear, lineWidth: 1.5) - ) - ) - .foregroundStyle(isSelected ? .amber : .primary) - } - .buttonStyle(.plain) - } -} - // MARK: - Library book card (3-column) private struct LibraryBookCard: View { diff --git a/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift b/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift index e433efb..d03f6a0 100644 --- a/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift +++ b/ios/LibNovel/LibNovel/Views/Player/PlayerViews.swift @@ -47,7 +47,7 @@ struct MiniPlayerView: View { // Previous chapter button if audioPlayer.status == .ready { Button { - if let prev = audioPlayer.absolutePrevChapter { + if let prev = audioPlayer.prevChapter { NotificationCenter.default.post( name: .skipToPrevChapter, object: nil, @@ -62,8 +62,8 @@ struct MiniPlayerView: View { .contentShape(Rectangle()) } .buttonStyle(.plain) - .disabled(audioPlayer.absolutePrevChapter == nil) - .opacity(audioPlayer.absolutePrevChapter == nil ? 0.4 : 1.0) + .disabled(audioPlayer.prevChapter == nil) + .opacity(audioPlayer.prevChapter == nil ? 0.4 : 1.0) } // Status indicator or play/pause control @@ -92,7 +92,7 @@ struct MiniPlayerView: View { // Next chapter button if audioPlayer.status == .ready { Button { - if let next = audioPlayer.absoluteNextChapter { + if let next = audioPlayer.nextChapter { NotificationCenter.default.post( name: .skipToNextChapter, object: nil, @@ -124,8 +124,8 @@ struct MiniPlayerView: View { .contentShape(Rectangle()) } .buttonStyle(.plain) - .disabled(audioPlayer.absoluteNextChapter == nil) - .opacity(audioPlayer.absoluteNextChapter == nil ? 0.4 : 1.0) + .disabled(audioPlayer.nextChapter == nil) + .opacity(audioPlayer.nextChapter == nil ? 0.4 : 1.0) } } } @@ -342,9 +342,9 @@ struct FullPlayerView: View { PlayerChapterSkipButton( systemName: "backward.end.fill", size: 30, - disabled: audioPlayer.absolutePrevChapter == nil + disabled: audioPlayer.prevChapter == nil ) { - if let prev = audioPlayer.absolutePrevChapter { + if let prev = audioPlayer.prevChapter { onDismiss() NotificationCenter.default.post( name: .skipToPrevChapter, object: nil, @@ -364,10 +364,10 @@ struct FullPlayerView: View { PlayerChapterSkipButton( systemName: "forward.end.fill", size: 30, - disabled: audioPlayer.absoluteNextChapter == nil, + disabled: audioPlayer.nextChapter == nil, prefetching: audioPlayer.nextPrefetchStatus == .prefetching ) { - if let next = audioPlayer.absoluteNextChapter { + if let next = audioPlayer.nextChapter { onDismiss() NotificationCenter.default.post( name: .skipToNextChapter, object: nil, diff --git a/scripts/.runner b/scripts/.runner new file mode 100644 index 0000000..54c7fc4 --- /dev/null +++ b/scripts/.runner @@ -0,0 +1,13 @@ +{ + "WARNING": "This file is automatically generated by act-runner. Do not edit it manually unless you know what you are doing. Removing this file will cause act runner to re-register as a new runner.", + "id": 11, + "uuid": "d5d04e0a-572c-46c0-83be-405508948391", + "name": "runner-mac-1", + "token": "ddf214ce148b4673a186f29cb684b407cb8c2ecc", + "address": "https://gitea.kalekber.cc/", + "labels": [ + "macos-latest:host", + "macos-14:host" + ], + "ephemeral": false +}