v0.5 #11
12 changed files with 102 additions and 77 deletions
|
|
@ -78,6 +78,7 @@
|
|||
0CBC76FD288D914F0054BE44 /* BatchChoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBC76FC288D914F0054BE44 /* BatchChoiceView.swift */; };
|
||||
0CBC76FF288DAAD00054BE44 /* NavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBC76FE288DAAD00054BE44 /* NavigationViewModel.swift */; };
|
||||
0CBC7705288DE7F40054BE44 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CBC7704288DE7F40054BE44 /* PersistenceController.swift */; };
|
||||
0CDCB91828C662640098B513 /* EmptyInstructionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CDCB91728C662640098B513 /* EmptyInstructionView.swift */; };
|
||||
0CFEFCFD288A006200B3F490 /* GroupBoxStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
|
@ -148,6 +149,7 @@
|
|||
0CBC76FE288DAAD00054BE44 /* NavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewModel.swift; sourceTree = "<group>"; };
|
||||
0CBC7704288DE7F40054BE44 /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = "<group>"; };
|
||||
0CC6E4D428A45BA000AF2BCC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
0CDCB91728C662640098B513 /* EmptyInstructionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyInstructionView.swift; sourceTree = "<group>"; };
|
||||
0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupBoxStyle.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
|
@ -252,6 +254,7 @@
|
|||
0CB6516228C5A57300DCA721 /* ConditionalId.swift */,
|
||||
0CB6516428C5A5D700DCA721 /* InlinedList.swift */,
|
||||
0CB6516928C5B4A600DCA721 /* InlineHeader.swift */,
|
||||
0CDCB91728C662640098B513 /* EmptyInstructionView.swift */,
|
||||
);
|
||||
path = CommonViews;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -482,6 +485,7 @@
|
|||
0C794B67289DACB600DD1CC8 /* SourceUpdateButtonView.swift in Sources */,
|
||||
0CA148E6288903F000DE2211 /* WebView.swift in Sources */,
|
||||
0C4CFC4E28970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift in Sources */,
|
||||
0CDCB91828C662640098B513 /* EmptyInstructionView.swift in Sources */,
|
||||
0CA148E2288903F000DE2211 /* Data.swift in Sources */,
|
||||
0C57D4CC289032ED008534E8 /* SearchResultRDView.swift in Sources */,
|
||||
0C7D11FC28AA01E900ED92DB /* DynamicAccentColor.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@
|
|||
// Created by Brian Dashore on 8/15/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Introspect
|
||||
import SwiftUI
|
||||
|
||||
extension View {
|
||||
// MARK: Custom introspect functions
|
||||
|
||||
func introspectCollectionView(customize: @escaping (UICollectionView) -> ()) -> some View {
|
||||
return inject(UIKitIntrospectionView(
|
||||
func introspectCollectionView(customize: @escaping (UICollectionView) -> Void) -> some View {
|
||||
inject(UIKitIntrospectionView(
|
||||
selector: { introspectionView in
|
||||
guard let viewHost = Introspect.findViewHost(from: introspectionView) else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ struct AboutView: View {
|
|||
Image("AppImage")
|
||||
.resizable()
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 100*0.225, style: .continuous))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 100 * 0.225, style: .continuous))
|
||||
.padding(.top, 24)
|
||||
|
||||
Text("Ferrite is a free and open source application developed by kingbri under the GNU-GPLv3 license.")
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ struct BatchChoiceView: View {
|
|||
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
.dynamicAccentColor(.primary)
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
|
|
|
|||
27
Ferrite/Views/CommonViews/EmptyInstructionView.swift
Normal file
27
Ferrite/Views/CommonViews/EmptyInstructionView.swift
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// EmptyInstructionView.swift
|
||||
// Ferrite
|
||||
//
|
||||
// Created by Brian Dashore on 9/5/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct EmptyInstructionView: View {
|
||||
let title: String
|
||||
let message: String
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 5) {
|
||||
Text(title)
|
||||
.font(.system(size: 25, weight: .semibold))
|
||||
|
||||
Text(message)
|
||||
.padding(.horizontal, 50)
|
||||
}
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.secondaryLabel)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
//
|
||||
// Created by Brian Dashore on 9/5/22.
|
||||
//
|
||||
// For iOS 15's weird defaults regarding sectioned list padding
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
|
|
@ -15,16 +17,13 @@ struct InlineHeader: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if #available(iOS 16, *) {
|
||||
Text(title)
|
||||
.padding(.vertical, 5)
|
||||
} else {
|
||||
Text(title)
|
||||
.padding(.vertical, 10)
|
||||
}
|
||||
if #available(iOS 16, *) {
|
||||
Text(title)
|
||||
} else if #available(iOS 15, *) {
|
||||
Text(title)
|
||||
.listRowInsets(EdgeInsets(top: 10, leading: 15, bottom: 0, trailing: 0))
|
||||
} else {
|
||||
Text(title)
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.listRowInsets(EdgeInsets())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
// Use UITableView.appearance().contentInset.top = -20 for iOS 15 and below in the App file
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Introspect
|
||||
import SwiftUI
|
||||
|
||||
struct InlinedList: ViewModifier {
|
||||
func body(content: Content) -> some View {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
// Created by Brian Dashore on 7/11/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Introspect
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@EnvironmentObject var debridManager: DebridManager
|
||||
|
|
@ -41,11 +41,11 @@ struct SettingsView: View {
|
|||
}
|
||||
}
|
||||
|
||||
Section(header: InlineHeader("Source management")) {
|
||||
Section(header: Text("Source management")) {
|
||||
NavigationLink("Source lists", destination: SettingsSourceListView())
|
||||
}
|
||||
|
||||
Section(header: InlineHeader("Default actions")) {
|
||||
Section(header: Text("Default actions")) {
|
||||
if debridManager.realDebridEnabled {
|
||||
NavigationLink(
|
||||
destination: DebridActionPickerView(),
|
||||
|
|
@ -95,14 +95,14 @@ struct SettingsView: View {
|
|||
)
|
||||
}
|
||||
|
||||
Section(header: InlineHeader("Updates")) {
|
||||
Section(header: Text("Updates")) {
|
||||
Toggle(isOn: $autoUpdateNotifs) {
|
||||
Text("Show update alerts")
|
||||
}
|
||||
NavigationLink("Version history", destination: SettingsAppVersionView())
|
||||
}
|
||||
|
||||
Section(header: InlineHeader("Information")) {
|
||||
Section(header: Text("Information")) {
|
||||
ListRowLinkView(text: "Donate", link: "https://ko-fi.com/kingbri")
|
||||
ListRowLinkView(text: "Report issues", link: "https://github.com/bdashore3/Ferrite/issues")
|
||||
NavigationLink("About", destination: AboutView())
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ struct SettingsAppVersionView: View {
|
|||
} catch {
|
||||
toastModel.updateToastDescription("Github error: \(error)")
|
||||
}
|
||||
|
||||
withAnimation {
|
||||
loadedReleases = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,58 +21,60 @@ struct SettingsSourceListView: View {
|
|||
@State private var selectedSourceList: SourceList?
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
ZStack {
|
||||
if sourceLists.isEmpty {
|
||||
Text("No source lists")
|
||||
EmptyInstructionView(title: "No Lists", message: "Add a source list using the + button in the top-right")
|
||||
} else {
|
||||
ForEach(sourceLists, id: \.self) { sourceList in
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text(sourceList.name)
|
||||
List {
|
||||
ForEach(sourceLists, id: \.self) { sourceList in
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text(sourceList.name)
|
||||
|
||||
Text(sourceList.author)
|
||||
.foregroundColor(.gray)
|
||||
Text(sourceList.author)
|
||||
.foregroundColor(.gray)
|
||||
|
||||
Text("ID: \(sourceList.id)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.padding(.vertical, 2)
|
||||
.contextMenu {
|
||||
Button {
|
||||
navModel.selectedSourceList = sourceList
|
||||
presentSourceSheet.toggle()
|
||||
} label: {
|
||||
Text("Edit")
|
||||
Image(systemName: "pencil")
|
||||
Text("ID: \(sourceList.id)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
|
||||
if #available(iOS 15.0, *) {
|
||||
Button(role: .destructive) {
|
||||
PersistenceController.shared.delete(sourceList, context: backgroundContext)
|
||||
} label: {
|
||||
Text("Remove")
|
||||
Image(systemName: "trash")
|
||||
}
|
||||
} else {
|
||||
.padding(.vertical, 2)
|
||||
.contextMenu {
|
||||
Button {
|
||||
PersistenceController.shared.delete(sourceList, context: backgroundContext)
|
||||
navModel.selectedSourceList = sourceList
|
||||
presentSourceSheet.toggle()
|
||||
} label: {
|
||||
Text("Remove")
|
||||
Image(systemName: "trash")
|
||||
Text("Edit")
|
||||
Image(systemName: "pencil")
|
||||
}
|
||||
|
||||
if #available(iOS 15.0, *) {
|
||||
Button(role: .destructive) {
|
||||
PersistenceController.shared.delete(sourceList, context: backgroundContext)
|
||||
} label: {
|
||||
Text("Remove")
|
||||
Image(systemName: "trash")
|
||||
}
|
||||
} else {
|
||||
Button {
|
||||
PersistenceController.shared.delete(sourceList, context: backgroundContext)
|
||||
} label: {
|
||||
Text("Remove")
|
||||
Image(systemName: "trash")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.inlinedList()
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.inlinedList()
|
||||
.sheet(isPresented: $presentSourceSheet) {
|
||||
if #available(iOS 16, *) {
|
||||
SourceListEditorView(sourceUrl: navModel.selectedSourceList?.urlString ?? "")
|
||||
SourceListEditorView()
|
||||
.presentationDetents([.medium])
|
||||
} else {
|
||||
SourceListEditorView(sourceUrl: navModel.selectedSourceList?.urlString ?? "")
|
||||
SourceListEditorView()
|
||||
}
|
||||
}
|
||||
.navigationTitle("Source Lists")
|
||||
|
|
|
|||
|
|
@ -15,11 +15,9 @@ struct SourceListEditorView: View {
|
|||
|
||||
let backgroundContext = PersistenceController.shared.backgroundContext
|
||||
|
||||
@State private var sourceUrl: String
|
||||
@State private var sourceUrlSet = false
|
||||
|
||||
init(sourceUrl: String = "") {
|
||||
_sourceUrl = State(initialValue: sourceUrl)
|
||||
}
|
||||
@State private var sourceUrl: String = ""
|
||||
|
||||
var body: some View {
|
||||
NavView {
|
||||
|
|
@ -28,9 +26,11 @@ struct SourceListEditorView: View {
|
|||
.disableAutocorrection(true)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.conditionalId(sourceUrlSet)
|
||||
}
|
||||
.onAppear {
|
||||
sourceUrl = navModel.selectedSourceList?.urlString ?? ""
|
||||
sourceUrlSet = true
|
||||
}
|
||||
.alert(isPresented: $sourceManager.showUrlErrorAlert) {
|
||||
Alert(
|
||||
|
|
|
|||
|
|
@ -5,13 +5,11 @@
|
|||
// Created by Brian Dashore on 7/24/22.
|
||||
//
|
||||
|
||||
import Introspect
|
||||
import SwiftUI
|
||||
import SwiftUIX
|
||||
import Introspect
|
||||
|
||||
struct SourcesView: View {
|
||||
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
|
||||
|
||||
@EnvironmentObject var sourceManager: SourceManager
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
|
||||
|
|
@ -53,15 +51,8 @@ struct SourcesView: View {
|
|||
ZStack {
|
||||
if !checkedForSources {
|
||||
ProgressView()
|
||||
} else if sources.isEmpty && sourceManager.availableSources.isEmpty {
|
||||
VStack {
|
||||
Text("No Sources")
|
||||
.font(.system(size: 25, weight: .semibold))
|
||||
.foregroundColor(.secondaryLabel)
|
||||
Text("Add a source list in Settings")
|
||||
.foregroundColor(.secondaryLabel)
|
||||
}
|
||||
.padding(.top, verticalSizeClass == .regular ? -50 : 0)
|
||||
} else if sources.isEmpty, sourceManager.availableSources.isEmpty {
|
||||
EmptyInstructionView(title: "No Sources", message: "Add a source list in Settings")
|
||||
} else {
|
||||
List {
|
||||
if !filteredUpdatedSources.isEmpty {
|
||||
|
|
@ -80,12 +71,12 @@ struct SourcesView: View {
|
|||
}
|
||||
}
|
||||
|
||||
if !filteredAvailableSources.isEmpty && sourceManager.availableSources.contains(where: { availableSource in
|
||||
if !filteredAvailableSources.isEmpty, sourceManager.availableSources.contains(where: { availableSource in
|
||||
!sources.contains(
|
||||
where: {
|
||||
availableSource.name == $0.name &&
|
||||
availableSource.listId == $0.listId &&
|
||||
availableSource.author == $0.author
|
||||
availableSource.listId == $0.listId &&
|
||||
availableSource.author == $0.author
|
||||
}
|
||||
)
|
||||
}) {
|
||||
|
|
@ -94,8 +85,8 @@ struct SourcesView: View {
|
|||
if !sources.contains(
|
||||
where: {
|
||||
availableSource.name == $0.name &&
|
||||
availableSource.listId == $0.listId &&
|
||||
availableSource.author == $0.author
|
||||
availableSource.listId == $0.listId &&
|
||||
availableSource.author == $0.author
|
||||
}
|
||||
) {
|
||||
SourceCatalogButtonView(availableSource: availableSource)
|
||||
|
|
@ -131,7 +122,7 @@ struct SourcesView: View {
|
|||
searchText = ""
|
||||
}
|
||||
}
|
||||
.onChange(of: searchText) { newValue in
|
||||
.onChange(of: searchText) { _ in
|
||||
filteredAvailableSources = sourceManager.availableSources.filter { searchText.isEmpty ? true : $0.name.contains(searchText) }
|
||||
filteredUpdatedSources = updatedSources.filter { searchText.isEmpty ? true : $0.name.contains(searchText) }
|
||||
if #available(iOS 15.0, *) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue