Skip to content

Commit

Permalink
bump version
Browse files Browse the repository at this point in the history
Signed-off-by: 82Flex <[email protected]>
  • Loading branch information
Lessica committed Jul 23, 2024
1 parent b1a4e7d commit 3798437
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 53 deletions.
4 changes: 2 additions & 2 deletions TrollFools.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = GXZ23M5TP2;
ENABLE_PREVIEWS = NO;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -481,7 +481,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = GXZ23M5TP2;
ENABLE_PREVIEWS = NO;
GENERATE_INFOPLIST_FILE = YES;
Expand Down
4 changes: 2 additions & 2 deletions TrollFools/AppListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ final class AppListModel: ObservableObject {
filter.$searchKeyword
.combineLatest(filter.$showPatchedOnly)
.throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true)
.sink { _ in
.sink { [weak self] _ in
withAnimation {
self.performFilter()
self?.performFilter()
}
}
.store(in: &cancellables)
Expand Down
109 changes: 61 additions & 48 deletions TrollFools/EjectListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import CocoaLumberjackSwift
import Combine
import SwiftUI

private let gDateFormatter: DateFormatter = {
Expand All @@ -30,13 +31,13 @@ struct InjectedPlugIn: Identifiable {
struct PlugInCell: View {
let plugIn: InjectedPlugIn

@EnvironmentObject var searchOptions: FilterOptions
@EnvironmentObject var filter: FilterOptions

@available(iOS 15.0, *)
var highlightedName: AttributedString {
let name = plugIn.url.lastPathComponent
var attributedString = AttributedString(name)
if let range = attributedString.range(of: searchOptions.searchKeyword, options: [.caseInsensitive, .diacriticInsensitive]) {
if let range = attributedString.range(of: filter.searchKeyword, options: [.caseInsensitive, .diacriticInsensitive]) {
attributedString[range].foregroundColor = .accentColor
}
return attributedString
Expand Down Expand Up @@ -80,31 +81,61 @@ struct PlugInCell: View {
}
}

struct EjectListView: View {
final class EjectListModel: ObservableObject {
let app: App
private var _injectedPlugIns: [InjectedPlugIn] = []

@Published var filter = FilterOptions()
@Published var filteredPlugIns: [InjectedPlugIn] = []

private var cancellables = Set<AnyCancellable>()

init(_ app: App) {
self.app = app
reload()

filter.$searchKeyword
.throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true)
.sink { [weak self] _ in
withAnimation {
self?.performFilter()
}
}
.store(in: &cancellables)
}

@State var injectedPlugIns: [InjectedPlugIn] = []
@State var isErrorOccurred: Bool = false
@State var errorMessage: String = ""
func reload() {
self._injectedPlugIns = Injector.injectedPlugInURLs(app.url)
.map { InjectedPlugIn(url: $0) }
performFilter()
}

@State var searchResults: [InjectedPlugIn] = []
@StateObject var searchOptions = FilterOptions()
func performFilter() {
var filteredPlugIns = _injectedPlugIns

@State var isDeletingAll = false
@StateObject var viewControllerHost = ViewControllerHost()
if !filter.searchKeyword.isEmpty {
filteredPlugIns = filteredPlugIns.filter {
$0.url.lastPathComponent.localizedCaseInsensitiveContains(filter.searchKeyword)
}
}

var isSearching: Bool {
return !searchOptions.searchKeyword.isEmpty
self.filteredPlugIns = filteredPlugIns
}
}

struct EjectListView: View {
@StateObject var vm: EjectListModel

var filteredPlugIns: [InjectedPlugIn] {
isSearching ? searchResults : injectedPlugIns
init(_ app: App) {
_vm = StateObject(wrappedValue: EjectListModel(app))
}

@State var isErrorOccurred: Bool = false
@State var errorMessage: String = ""

@State var isDeletingAll = false
@StateObject var viewControllerHost = ViewControllerHost()

var deleteAllButtonLabel: some View {
HStack {
Label(NSLocalizedString("Eject All", comment: ""), systemImage: "eject")
Expand Down Expand Up @@ -135,31 +166,31 @@ struct EjectListView: View {
var ejectList: some View {
List {
Section {
ForEach(filteredPlugIns) { plugin in
ForEach(vm.filteredPlugIns) { plugin in
if #available(iOS 16.0, *) {
PlugInCell(plugIn: plugin)
.environmentObject(searchOptions)
.environmentObject(vm.filter)
} else {
PlugInCell(plugIn: plugin)
.environmentObject(searchOptions)
.environmentObject(vm.filter)
.padding(.vertical, 4)
}
}
.onDelete(perform: delete)
} header: {
Text(filteredPlugIns.isEmpty
Text(vm.filteredPlugIns.isEmpty
? NSLocalizedString("No Injected Plug-Ins", comment: "")
: NSLocalizedString("Injected Plug-Ins", comment: ""))
.font(.footnote)
}

if !isSearching && !filteredPlugIns.isEmpty {
if !vm.filter.isSearching && !vm.filteredPlugIns.isEmpty {
Section {
deleteAllButton
.disabled(isDeletingAll)
.foregroundColor(isDeletingAll ? .secondary : .red)
} footer: {
if app.isFromTroll {
if vm.app.isFromTroll {
Text(NSLocalizedString("Some plug-ins were not injected by TrollFools, please eject them with caution.", comment: ""))
.font(.footnote)
}
Expand All @@ -173,53 +204,41 @@ struct EjectListView: View {
}
.listStyle(.insetGrouped)
.navigationTitle(NSLocalizedString("Plug-Ins", comment: ""))
.navigationBarTitleDisplayMode(.inline)
.animation(.easeOut, value: vm.filter.isSearching)
.onViewWillAppear { viewController in
viewControllerHost.viewController = viewController
}
.onAppear {
reloadPlugIns()
}
}

var body: some View {
if #available(iOS 15.0, *) {
ejectList
.refreshable {
withAnimation {
reloadPlugIns()
vm.reload()
}
}
.searchable(
text: $searchOptions.searchKeyword,
text: $vm.filter.searchKeyword,
placement: .automatic,
prompt: NSLocalizedString("Search…", comment: "")
)
.textInputAutocapitalization(.never)
.onChange(of: searchOptions.searchKeyword) { keyword in
fetchSearchResults(for: keyword)
}
} else {
// Fallback on earlier versions
ejectList
}
}

func reloadPlugIns() {
searchOptions.reset()
injectedPlugIns = Injector.injectedPlugInURLs(app.url)
.map { InjectedPlugIn(url: $0) }
}

func delete(at offsets: IndexSet) {
do {
let plugInsToRemove = offsets.map { filteredPlugIns[$0] }
let plugInsToRemove = offsets.map { vm.filteredPlugIns[$0] }
let plugInURLsToRemove = plugInsToRemove.map { $0.url }
let injector = try Injector(bundleURL: app.url, teamID: app.teamID)
let injector = try Injector(bundleURL: vm.app.url, teamID: vm.app.teamID)
try injector.eject(plugInURLsToRemove)

app.reloadInjectedStatus()
reloadPlugIns()
vm.app.reloadInjectedStatus()
vm.reload()
} catch {
DDLogError("\(error)")

Expand All @@ -230,7 +249,7 @@ struct EjectListView: View {

func deleteAll() {
do {
let injector = try Injector(bundleURL: app.url, teamID: app.teamID)
let injector = try Injector(bundleURL: vm.app.url, teamID: vm.app.teamID)

let view = viewControllerHost.viewController?
.navigationController?.view
Expand All @@ -245,8 +264,8 @@ struct EjectListView: View {
defer {
DispatchQueue.main.async {
withAnimation {
app.reloadInjectedStatus()
reloadPlugIns()
vm.app.reloadInjectedStatus()
vm.reload()
isDeletingAll = false
}

Expand Down Expand Up @@ -274,10 +293,4 @@ struct EjectListView: View {
isErrorOccurred = true
}
}

func fetchSearchResults(for query: String) {
searchResults = injectedPlugIns.filter { plugin in
plugin.url.lastPathComponent.localizedCaseInsensitiveContains(query)
}
}
}
1 change: 0 additions & 1 deletion TrollFools/OptionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ struct OptionView: View {
}
.padding()
.navigationTitle(app.name)
.navigationBarTitleDisplayMode(.inline)
.fileImporter(
isPresented: $isImporterPresented,
allowedContentTypes: [
Expand Down

0 comments on commit 3798437

Please sign in to comment.