v0.5 #11

Merged
kingbri1 merged 22 commits from next into default 2022-11-19 17:51:06 +00:00
13 changed files with 158 additions and 19 deletions
Showing only changes of commit 52409099d7 - Show all commits

View file

@ -71,6 +71,10 @@
0CA148EC288903F000DE2211 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA148D4288903F000DE2211 /* ContentView.swift */; };
0CA3FB2028B91D9500FA10A8 /* IndeterminateProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */; };
0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = 0CAF1C7A286F5C8600296F86 /* SwiftSoup */; };
0CB6516328C5A57300DCA721 /* ConditionalId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6516228C5A57300DCA721 /* ConditionalId.swift */; };
0CB6516528C5A5D700DCA721 /* InlinedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6516428C5A5D700DCA721 /* InlinedList.swift */; };
0CB6516828C5A5EC00DCA721 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 0CB6516728C5A5EC00DCA721 /* Introspect */; };
0CB6516A28C5B4A600DCA721 /* InlineHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB6516928C5B4A600DCA721 /* InlineHeader.swift */; };
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 */; };
@ -137,6 +141,9 @@
0CA148D4288903F000DE2211 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndeterminateProgressView.swift; sourceTree = "<group>"; };
0CAF1C68286F5C0E00296F86 /* Ferrite.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ferrite.app; sourceTree = BUILT_PRODUCTS_DIR; };
0CB6516228C5A57300DCA721 /* ConditionalId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalId.swift; sourceTree = "<group>"; };
0CB6516428C5A5D700DCA721 /* InlinedList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlinedList.swift; sourceTree = "<group>"; };
0CB6516928C5B4A600DCA721 /* InlineHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineHeader.swift; sourceTree = "<group>"; };
0CBC76FC288D914F0054BE44 /* BatchChoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchChoiceView.swift; sourceTree = "<group>"; };
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>"; };
@ -153,6 +160,7 @@
0C64A4B4288903680079976D /* Base32 in Frameworks */,
0C4CFC462897030D00AD9FAD /* Regex in Frameworks */,
0C7376F028A97D1400D60918 /* SwiftUIX in Frameworks */,
0CB6516828C5A5EC00DCA721 /* Introspect in Frameworks */,
0C64A4B7288903880079976D /* KeychainSwift in Frameworks */,
0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */,
);
@ -241,6 +249,9 @@
0C32FB562890D1F2002BD219 /* ListRowViews.swift */,
0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */,
0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */,
0CB6516228C5A57300DCA721 /* ConditionalId.swift */,
0CB6516428C5A5D700DCA721 /* InlinedList.swift */,
0CB6516928C5B4A600DCA721 /* InlineHeader.swift */,
);
path = CommonViews;
sourceTree = "<group>";
@ -366,6 +377,7 @@
0C4CFC452897030D00AD9FAD /* Regex */,
0C7376EF28A97D1400D60918 /* SwiftUIX */,
0C7506D628B1AC9A008BEE38 /* SwiftyJSON */,
0CB6516728C5A5EC00DCA721 /* Introspect */,
);
productName = Torrenter;
productReference = 0CAF1C68286F5C0E00296F86 /* Ferrite.app */;
@ -402,6 +414,7 @@
0C4CFC442897030D00AD9FAD /* XCRemoteSwiftPackageReference "Regex" */,
0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */,
0C7506D528B1AC9A008BEE38 /* XCRemoteSwiftPackageReference "SwiftyJSON" */,
0CB6516628C5A5EC00DCA721 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
);
productRefGroup = 0CAF1C69286F5C0E00296F86 /* Products */;
projectDirPath = "";
@ -431,8 +444,10 @@
buildActionMask = 2147483647;
files = (
0C0D50E5288DFE7F0035ECC8 /* SourceModels.swift in Sources */,
0CB6516528C5A5D700DCA721 /* InlinedList.swift in Sources */,
0C60B1EF28A1A00000E3FD7E /* SearchProgressView.swift in Sources */,
0C32FB532890D19D002BD219 /* AboutView.swift in Sources */,
0CB6516328C5A57300DCA721 /* ConditionalId.swift in Sources */,
0C84F4832895BFED0074B7C9 /* Source+CoreDataProperties.swift in Sources */,
0CA148DB288903F000DE2211 /* NavView.swift in Sources */,
0C750745289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift in Sources */,
@ -454,6 +469,7 @@
0C794B69289DACC800DD1CC8 /* InstalledSourceView.swift in Sources */,
0C79DC082899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift in Sources */,
0CA148DD288903F000DE2211 /* ScrapingViewModel.swift in Sources */,
0CB6516A28C5B4A600DCA721 /* InlineHeader.swift in Sources */,
0CA148D8288903F000DE2211 /* MagnetChoiceView.swift in Sources */,
0C84F4862895BFED0074B7C9 /* SourceList+CoreDataClass.swift in Sources */,
0C68135028BC1A2D00FAD890 /* GithubWrapper.swift in Sources */,
@ -747,6 +763,14 @@
minimumVersion = 2.0.0;
};
};
0CB6516628C5A5EC00DCA721 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/siteline/SwiftUI-Introspect";
requirement = {
branch = master;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@ -780,6 +804,11 @@
package = 0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */;
productName = SwiftSoup;
};
0CB6516728C5A5EC00DCA721 /* Introspect */ = {
isa = XCSwiftPackageProductDependency;
package = 0CB6516628C5A5EC00DCA721 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
productName = Introspect;
};
/* End XCSwiftPackageProductDependency section */
/* Begin XCVersionGroup section */

View file

@ -6,11 +6,34 @@
//
import SwiftUI
import Introspect
extension View {
// MARK: Custom introspect functions
func introspectCollectionView(customize: @escaping (UICollectionView) -> ()) -> some View {
return inject(UIKitIntrospectionView(
selector: { introspectionView in
guard let viewHost = Introspect.findViewHost(from: introspectionView) else {
return nil
}
return Introspect.previousSibling(containing: UICollectionView.self, from: viewHost)
},
customize: customize
))
}
// MARK: Modifiers
func dynamicAccentColor(_ color: Color) -> some View {
modifier(DynamicAccentColor(color: color))
}
func conditionalId<ID: Hashable>(_ id: ID) -> some View {
modifier(ConditionalId(id: id))
}
func inlinedList() -> some View {
modifier(InlinedList())
}
}

View file

@ -0,0 +1,24 @@
//
// ConditionalId.swift
// Ferrite
//
// Created by Brian Dashore on 9/4/22.
//
// Only applies an ID for below iOS 16
// This is due to ID workarounds making iOS 16 apps crash
//
import SwiftUI
struct ConditionalId<ID: Hashable>: ViewModifier {
let id: ID
func body(content: Content) -> some View {
if #available(iOS 16, *) {
content
} else {
content
.id(id)
}
}
}

View file

@ -0,0 +1,30 @@
//
// InlineHeader.swift
// Ferrite
//
// Created by Brian Dashore on 9/5/22.
//
import SwiftUI
struct InlineHeader: View {
let title: String
init(_ title: String) {
self.title = title
}
var body: some View {
Group {
if #available(iOS 16, *) {
Text(title)
.padding(.vertical, 5)
} else {
Text(title)
.padding(.vertical, 10)
}
}
.padding(.horizontal, 20)
.listRowInsets(EdgeInsets())
}
}

View file

@ -0,0 +1,28 @@
//
// InlinedList.swift
// Ferrite
//
// Created by Brian Dashore on 9/4/22.
//
// Removes the top padding on lists for iOS 16
// Use UITableView.appearance().contentInset.top = -20 for iOS 15 and below in the App file
//
import SwiftUI
import Introspect
struct InlinedList: ViewModifier {
func body(content: Content) -> some View {
if #available(iOS 16, *) {
content
.introspectCollectionView { collectionView in
collectionView.contentInset.top = -20
}
} else {
content
.introspectTableView { tableView in
tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 20))
}
}
}
}

View file

@ -54,6 +54,7 @@ struct SearchResultsView: View {
}
}
.listStyle(.insetGrouped)
.inlinedList()
.overlay {
if scrapingModel.searchResults.isEmpty {
if navModel.showSearchProgress {

View file

@ -6,6 +6,7 @@
//
import SwiftUI
import Introspect
struct SettingsView: View {
@EnvironmentObject var debridManager: DebridManager
@ -21,7 +22,7 @@ struct SettingsView: View {
var body: some View {
NavView {
Form {
Section(header: "Debrid services") {
Section(header: InlineHeader("Debrid Services")) {
HStack {
Text("Real Debrid")
Spacer()
@ -40,11 +41,11 @@ struct SettingsView: View {
}
}
Section(header: "Source management") {
Section(header: InlineHeader("Source management")) {
NavigationLink("Source lists", destination: SettingsSourceListView())
}
Section(header: "Default actions") {
Section(header: InlineHeader("Default actions")) {
if debridManager.realDebridEnabled {
NavigationLink(
destination: DebridActionPickerView(),
@ -94,14 +95,14 @@ struct SettingsView: View {
)
}
Section(header: Text("Updates")) {
Section(header: InlineHeader("Updates")) {
Toggle(isOn: $autoUpdateNotifs) {
Text("Show update alerts")
}
NavigationLink("Version history", destination: SettingsAppVersionView())
}
Section(header: Text("Information")) {
Section(header: InlineHeader("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())

View file

@ -29,6 +29,7 @@ struct MagnetActionPickerView: View {
}
}
.listStyle(.insetGrouped)
.inlinedList()
.navigationTitle("Default magnet action")
.navigationBarTitleDisplayMode(.inline)
}
@ -67,6 +68,7 @@ struct DebridActionPickerView: View {
}
}
.listStyle(.insetGrouped)
.inlinedList()
.navigationTitle("Default debrid action")
.navigationBarTitleDisplayMode(.inline)
}

View file

@ -21,7 +21,7 @@ struct SettingsAppVersionView: View {
ProgressView()
} else if !releases.isEmpty {
List {
Section(header: Text("GitHub links")) {
Section(header: InlineHeader("GitHub links")) {
ForEach(releases, id: \.self) { release in
ListRowLinkView(text: release.tagName, link: release.htmlUrl)
}

View file

@ -66,6 +66,7 @@ struct SettingsSourceListView: View {
}
}
.listStyle(.insetGrouped)
.inlinedList()
.sheet(isPresented: $presentSourceSheet) {
if #available(iOS 16, *) {
SourceListEditorView(sourceUrl: navModel.selectedSourceList?.urlString ?? "")

View file

@ -24,12 +24,10 @@ struct SourceListEditorView: View {
var body: some View {
NavView {
Form {
Section {
TextField("Enter URL", text: $sourceUrl)
.disableAutocorrection(true)
.keyboardType(.URL)
.autocapitalization(.none)
}
TextField("Enter URL", text: $sourceUrl)
.disableAutocorrection(true)
.keyboardType(.URL)
.autocapitalization(.none)
}
.onAppear {
sourceUrl = navModel.selectedSourceList?.urlString ?? ""

View file

@ -16,7 +16,7 @@ struct SourceSettingsView: View {
NavView {
List {
if let selectedSource = navModel.selectedSource {
Section(header: "Info") {
Section(header: InlineHeader("Info")) {
VStack(alignment: .leading, spacing: 5) {
HStack {
Text(selectedSource.name)
@ -78,7 +78,7 @@ struct SourceSettingsBaseUrlView: View {
@State private var tempBaseUrl: String = ""
var body: some View {
Section(
header: Text("Base URL"),
header: InlineHeader("Base URL"),
footer: Text("Enter the base URL of your server.")
) {
TextField("https://...", text: $tempBaseUrl, onEditingChanged: { isFocused in
@ -110,7 +110,7 @@ struct SourceSettingsApiView: View {
var body: some View {
Section(
header: Text("API credentials"),
header: InlineHeader("API credentials"),
footer: Text("Grab the required API credentials from the website. A client secret can be an API token.")
) {
if let clientId = selectedSourceApi.clientId, clientId.dynamic {
@ -146,7 +146,7 @@ struct SourceSettingsMethodView: View {
@ObservedObject var selectedSource: Source
var body: some View {
Section(header: Text("Fetch method")) {
Section(header: InlineHeader("Fetch method")) {
if selectedSource.api != nil, selectedSource.jsonParser != nil {
Button {
selectedSource.preferredParser = SourcePreferredParser.siteApi.rawValue

View file

@ -7,6 +7,7 @@
import SwiftUI
import SwiftUIX
import Introspect
struct SourcesView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@ -65,7 +66,7 @@ struct SourcesView: View {
} else {
List {
if !filteredUpdatedSources.isEmpty {
Section(header: "Updates") {
Section(header: InlineHeader("Updates")) {
ForEach(filteredUpdatedSources, id: \.self) { source in
SourceUpdateButtonView(updatedSource: source)
}
@ -73,7 +74,7 @@ struct SourcesView: View {
}
if !sources.isEmpty {
Section(header: "Installed") {
Section(header: InlineHeader("Installed")) {
ForEach(sources, id: \.self) { source in
InstalledSourceView(installedSource: source)
}
@ -89,7 +90,7 @@ struct SourcesView: View {
}
)
}) {
Section(header: "Catalog") {
Section(header: InlineHeader("Catalog")) {
ForEach(filteredAvailableSources, id: \.self) { availableSource in
if !sources.contains(
where: {
@ -104,6 +105,7 @@ struct SourcesView: View {
}
}
}
.conditionalId(UUID())
.listStyle(.insetGrouped)
}
}