diff --git a/.swift-version b/.swift-version index 9ad974f..3659ea2 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -5.5 +5.8 diff --git a/App/AppDelegate.swift b/App/AppDelegate.swift new file mode 100644 index 0000000..7493693 --- /dev/null +++ b/App/AppDelegate.swift @@ -0,0 +1,25 @@ +#if os(iOS) + import UIKit + + final class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + #if DEBUG + let args = ProcessInfo.processInfo.arguments + + if args.contains("POPULATE_APPLICATION") { + populateApplication() + } + #endif + + return true + } + + func applicationDidFinishLaunching(_: UIApplication) { + UIApplication.shared.beginReceivingRemoteControlEvents() + } + + func applicationWillTerminate(_: UIApplication) {} + } +#endif diff --git a/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/App/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..3b3b7d7 --- /dev/null +++ b/App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,74 @@ +{ + "images" : [ + { + "filename" : "logo-icon-bg-white-lg.jpg", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "filename" : "mac16.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "mac32.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "mac32.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "mac64.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "mac128.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "mac256.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "mac256.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "mac512.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "mac512.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "mac1024.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg b/App/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg new file mode 100644 index 0000000..5471db8 Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac1024.png b/App/Assets.xcassets/AppIcon.appiconset/mac1024.png new file mode 100644 index 0000000..2f0310d Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac1024.png differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac128.png b/App/Assets.xcassets/AppIcon.appiconset/mac128.png new file mode 100644 index 0000000..4f5712d Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac128.png differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac16.png b/App/Assets.xcassets/AppIcon.appiconset/mac16.png new file mode 100644 index 0000000..3efe465 Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac16.png differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac256.png b/App/Assets.xcassets/AppIcon.appiconset/mac256.png new file mode 100644 index 0000000..4a302d5 Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac256.png differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac32.png b/App/Assets.xcassets/AppIcon.appiconset/mac32.png new file mode 100644 index 0000000..b557ed9 Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac32.png differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac512.png b/App/Assets.xcassets/AppIcon.appiconset/mac512.png new file mode 100644 index 0000000..127d5b0 Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac512.png differ diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac64.png b/App/Assets.xcassets/AppIcon.appiconset/mac64.png new file mode 100644 index 0000000..ed035ee Binary files /dev/null and b/App/Assets.xcassets/AppIcon.appiconset/mac64.png differ diff --git a/Shared/Assets.xcassets/Contents.json b/App/Assets.xcassets/Contents.json similarity index 100% rename from Shared/Assets.xcassets/Contents.json rename to App/Assets.xcassets/Contents.json diff --git a/App/Assets.xcassets/logo.imageset/Contents.json b/App/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..e53a255 --- /dev/null +++ b/App/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "logo-icon-black-no-bg-lg.png", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "logo-icon-white-no-bg-lg.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Shared/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png b/App/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png similarity index 100% rename from Shared/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png rename to App/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png diff --git a/Shared/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png b/App/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png similarity index 100% rename from Shared/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png rename to App/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png diff --git a/iOS/Configuration.storekit b/App/Configuration.storekit similarity index 100% rename from iOS/Configuration.storekit rename to App/Configuration.storekit diff --git a/Shared/Entity/Entry.swift b/App/Entity/Entry.swift similarity index 100% rename from Shared/Entity/Entry.swift rename to App/Entity/Entry.swift diff --git a/Shared/Entity/Podcast.swift b/App/Entity/Podcast.swift similarity index 100% rename from Shared/Entity/Podcast.swift rename to App/Entity/Podcast.swift diff --git a/Shared/Entity/Tag.swift b/App/Entity/Tag.swift similarity index 100% rename from Shared/Entity/Tag.swift rename to App/Entity/Tag.swift diff --git a/App/Extension/AppDelegateExtension.swift b/App/Extension/AppDelegateExtension.swift new file mode 100644 index 0000000..e2bda6b --- /dev/null +++ b/App/Extension/AppDelegateExtension.swift @@ -0,0 +1,58 @@ +#if os(iOS) + import CoreData + import Factory + import Foundation + import SharedLib + import UIKit + + #if DEBUG + // swiftlint:disable line_length + extension AppDelegate { + func populateApplication() { + resetApplication() + + let appState = Container.shared.appState() + appState.registred = true + WallabagUserDefaults.defaultMode = "allArticles" + WallabagUserDefaults.badgeEnabled = false + + let context = Container.shared.coreData().viewContext + + let entry = Entry(context: context) + entry.title = "Marc Zuckerberg devrait être passible d'une peine de prison pour mensonges répétés au sujet de la protection de la vie privée des utilisateurs Facebook, d'après le sénateur américain Ron Wyden" + entry.url = "https://www.developpez.com/actu/275880/Marc-Zuckerberg-devrait-etre-passible-d-une-peine-de-prison-pour-mensonges-repetes-au-sujet-de-la-protection-de-la-vie-privee-des-utilisateurs-Facebook-d-apres-le-senateur-americain-Ron-Wyden/" + entry.previewPicture = "https://www.developpez.com/images/logos/mark-zuckerberg.png" + entry.content = """ + image La société Facebook est depuis quelque temps très critiquée sur la manière avec laquelle elle manipule les données de ses utilisateurs et les nombreux scandales comme celui de cambridge analytica, n’améliorent pas l’image de l’entreprise. D’ailleurs, après l'épisode de Cambridge Analytica, la société a reconnu plusieurs autres cas de manquements à la vie privée, dont celui d'admettre qu'elle avait mal géré les mots de passe d'utilisateurs sur Instagram. Bien que l’entreprise Facebook soit déjà sous le coup d’une amende de 5 milliards de dollars, cela semble ne pas être suffisant pour certains qui estiment que les dirigeants devraient eux aussi être poursuivis en justice. +

En effet, un projet de loi présenté en 2018 par le sénateur Ron Wyden, donne à la FTC le pouvoir de sévir plus sévèrement contre les entreprises qui violent la vie privée des consommateurs. Selon le projet de loi, les dirigeants pourraient être condamnés à 20 ans de prison et à une amende de 5 millions de dollars. Et c’est dans ce sens que le sénateur Ron Wyden s’est exprimé lors d’une récente Interview qui portait sur l'article 230 de ce projet de loi, sur l'impact de cette législation et sur les conséquences néfastes, notamment le fait que Facebook utilisait cette législation à son avantage.

Au cours de cette interview, il a déclaré : « Mark Zuckerberg a menti à plusieurs reprises au peuple américain au sujet de la vie privée. Je pense qu'il devrait être tenu personnellement pour responsable, ce qui devrait entraîner des amendes financières et laissez-moi souligner également la possibilité d'une peine de prison parce qu'il a blessé beaucoup de gens ». Wyden a aussi mentionné le fait qu’il existait un précédent dans ce genre de cas : dans les services financiers, si le PDG et les dirigeants mentent au sujet des données financières, ils peuvent être tenus personnellement pour responsables.

+
image
+
Wyden n'est pas le premier législateur à proposer d'envoyer des cadres d’entreprises en prison. La sénatrice du Massachusetts, Elizabeth Warren, une candidate à la présidence de 2020 a dévoilé au début de cette année la loi sur la responsabilité des dirigeants d'entreprise, qui étend la responsabilité pénale aux dirigeants de toute société générant un chiffre d'affaires annuel supérieur à 1 milliard de dollars si cette société était reconnue coupable d'un crime ou d'une autre infraction civile. Malgré les souhaits de Wyden de voir Zuckerberg finir en prison, cela ne se produira probablement pas. C’est l’avis de Tim Gleason, un professeur de l’Université de l’Oregon, qui estime que les chances de Zuckerberg de faire face à une action criminelle sont plutôt minces. +

Pendant ce temps, plusieurs personnes pensent qu’emprisonner Zuckerberg ne réglera pas le problème, car il sera juste remplacé par quelqu'un d'autre qui fera pareil que lui. Ces personnes estiment qu’il serait peut-être plus judicieux de lui imposer une très grosse amende, qui servira à financer des œuvres sociales. Pour ces personnes, il est inutile de combattre ces milliardaires de cette façon, il faudrait plutôt utiliser leur cupidité contre eux.

+

Source : Willamette Week

+

Et vous ?

+

Qu’en pensez-vous ?
Pensez-vous que Zuckerberg sera finalement inquiété ?
Quelles mesures proposeriez-vous pour contraindre les entreprises à respecter la vie privée des utilisateurs ?

+

Voir aussi :

+

Les actionnaires de Facebook en ont assez de Marc Zuckerberg, mais ne peuvent rien faire contre lui, En voici les raisons
Mark Zuckerberg ainsi que d'autres cadres dirigeants de Facebook sont poursuivis en justice Pour les scandales liés à la vie privée
Mark Zuckerberg devrait vendre jusqu'à 13 Md$ d'actions Facebook d'ici mars 2019 Pour financer les actions philanthropiques de sa fondation CZI

+ """ + } + + private func resetApplication() { + do { + // MARK: CoreData + + let context = Container.shared.coreData().viewContext + let operations = NSBatchDeleteRequest(fetchRequest: Entry.fetchRequest()) + try context.execute(operations) + + let accounts = NSBatchDeleteRequest(fetchRequest: Tag.fetchRequest()) + try context.execute(accounts) + + try context.save() + } catch { + print("error resetting app") + } + } + } + #endif + +#endif diff --git a/App/Extension/SwiftUI/View+Extension.swift b/App/Extension/SwiftUI/View+Extension.swift new file mode 100644 index 0000000..bb6fb1a --- /dev/null +++ b/App/Extension/SwiftUI/View+Extension.swift @@ -0,0 +1,14 @@ +import SwiftUI + +extension View { + func addSwipeToBack(action: @escaping () -> Void) -> some View { + gesture( + DragGesture() + .onEnded { gesture in + if gesture.startLocation.x < 50, gesture.translation.width > 80 { + action() + } + } + ) + } +} diff --git a/iOS/Features/About/AboutView.swift b/App/Features/About/AboutView.swift similarity index 95% rename from iOS/Features/About/AboutView.swift rename to App/Features/About/AboutView.swift index f8f6d75..ac23cdd 100644 --- a/iOS/Features/About/AboutView.swift +++ b/App/Features/About/AboutView.swift @@ -16,6 +16,7 @@ struct AboutView: View { Spacer() Text("Made by Maxime Marinel @bourvill") } + .navigationTitle("About") } } diff --git a/iOS/Features/BugReport/BugReportView.swift b/App/Features/BugReport/BugReportView.swift similarity index 100% rename from iOS/Features/BugReport/BugReportView.swift rename to App/Features/BugReport/BugReportView.swift diff --git a/iOS/Features/Entry/AddEntryView.swift b/App/Features/Entry/AddEntryView.swift similarity index 90% rename from iOS/Features/Entry/AddEntryView.swift rename to App/Features/Entry/AddEntryView.swift index bd2cd13..1680d5f 100644 --- a/iOS/Features/Entry/AddEntryView.swift +++ b/App/Features/Entry/AddEntryView.swift @@ -1,3 +1,4 @@ +import Factory import SwiftUI struct AddEntryView: View { @@ -6,7 +7,9 @@ struct AddEntryView: View { var body: some View { Form { TextField("Url", text: $model.url) + #if os(iOS) .autocapitalization(.none) + #endif .disableAutocorrection(true) HStack { Button(model.submitting ? "Submitting..." : "Submit") { @@ -17,11 +20,12 @@ struct AddEntryView: View { Text("Great! Entry was added") } } + .navigationTitle("Add entry") } } private class AddEntryModel: ObservableObject { - @Injector var session: WallabagSession + @Injected(\.wallabagSession) private var session @Published var url: String = "" @Published var submitting: Bool = false diff --git a/App/Features/Entry/EntriesListView.swift b/App/Features/Entry/EntriesListView.swift new file mode 100644 index 0000000..2574435 --- /dev/null +++ b/App/Features/Entry/EntriesListView.swift @@ -0,0 +1,43 @@ +import CoreData +import Foundation +import SwiftUI + +struct EntriesListView: View { + @Environment(\.managedObjectContext) var context: NSManagedObjectContext + @EnvironmentObject var appSync: AppSync + @FetchRequest var entries: FetchedResults + + init(predicate: NSPredicate, entriesSortAscending: Bool) { + _entries = FetchRequest( + entity: Entry.entity(), + sortDescriptors: [NSSortDescriptor(key: "id", ascending: entriesSortAscending)], + predicate: predicate, animation: nil + ) + } + + var body: some View { + List { + ForEach(entries) { entry in + NavigationLink(value: RoutePath.entry(entry)) { + EntryRowView(entry: entry) + .contentShape(Rectangle()) + .contextMenu { + ArchiveEntryButton(entry: entry) + StarEntryButton(entry: entry) + } + } + .buttonStyle(.plain) + .swipeActions(allowsFullSwipe: false, content: { + ArchiveEntryButton(entry: entry) + .tint(.blue) + .labelStyle(.iconOnly) + StarEntryButton(entry: entry) + .tint(.orange) + .labelStyle(.iconOnly) + }) + } + } + .refreshable { appSync.requestSync() } + .listStyle(.inset) + } +} diff --git a/App/Features/Entry/EntriesView.swift b/App/Features/Entry/EntriesView.swift new file mode 100644 index 0000000..3b5befc --- /dev/null +++ b/App/Features/Entry/EntriesView.swift @@ -0,0 +1,78 @@ +import Combine +import CoreData +import SwiftUI + +struct EntriesView: View { + @EnvironmentObject var router: Router + @EnvironmentObject var appState: AppState + @StateObject var searchViewModel = SearchViewModel() + @State var entriesSortAscending = false + + var body: some View { + VStack { + #if os(iOS) + PasteBoardView() + #endif + SearchView(searchViewModel: searchViewModel) + EntriesListView(predicate: searchViewModel.predicate, entriesSortAscending: entriesSortAscending) + } + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + HStack { + Button(action: { + entriesSortAscending.toggle() + }, label: { + Image(systemName: "line.3.horizontal.decrease.circle") + .rotationEffect(.degrees(entriesSortAscending ? 180 : 0)) + }) + RefreshButton() + } + } + ToolbarItem(placement: .navigationBarLeading) { + Menu(content: { + Button(action: { + router.path.append(RoutePath.addEntry) + }, label: { + Label("Add entry", systemImage: "tray.and.arrow.down") + }) + Button(action: { + router.path.append(RoutePath.about) + }, label: { + Label("About", systemImage: "questionmark") + }) + Button(action: { + router.path.append(RoutePath.tips) + }, label: { + Label("Don", systemImage: "heart") + }) + Divider() + Button(action: { + router.path.append(RoutePath.setting) + }, label: { + Label("Setting", systemImage: "gear") + }) + Divider() + Button(role: .destructive, action: { + appState.logout() + }, label: { + Label("Logout", systemImage: "person") + }).foregroundColor(.red) + }, label: { + Label("Menu", systemImage: "list.bullet") + }) + } + } + .navigationTitle("Entries") + } +} + +#if DEBUG + struct ArticleListView_Previews: PreviewProvider { + static var previews: some View { + EntriesView() + #if os(iOS) + .environmentObject(PasteBoardViewModel()) + #endif + } + } +#endif diff --git a/iOS/Features/Entry/EntryRowView.swift b/App/Features/Entry/EntryRowView.swift similarity index 92% rename from iOS/Features/Entry/EntryRowView.swift rename to App/Features/Entry/EntryRowView.swift index 338af16..dd7673a 100644 --- a/iOS/Features/Entry/EntryRowView.swift +++ b/App/Features/Entry/EntryRowView.swift @@ -1,4 +1,6 @@ +import Factory import HTMLEntities +import SharedLib import SwiftUI struct EntryRowView: View { @@ -35,7 +37,8 @@ struct EntryRowView: View { struct ArticleRowView_Previews: PreviewProvider { static var entry: Entry { - let entry = Entry(context: CoreData.shared.viewContext) + let coreData = Container.shared.coreData() + let entry = Entry(context: coreData.viewContext) entry.title = "Marc Zuckerberg devrait être passible d'une peine de prison pour mensonges répétés au sujet de la protection de la vie privée des utilisateurs Facebook, d'après le sénateur américain Ron Wyden" return entry diff --git a/App/Features/Entry/EntryView.swift b/App/Features/Entry/EntryView.swift new file mode 100644 index 0000000..7fe5117 --- /dev/null +++ b/App/Features/Entry/EntryView.swift @@ -0,0 +1,135 @@ +import CoreData +import Factory +import HTMLEntities +import SwiftUI + +struct EntryView: View { + @Environment(\.managedObjectContext) var context: NSManagedObjectContext + @Environment(\.openURL) var openURL + @Environment(\.dismiss) private var dismiss + @EnvironmentObject var appSync: AppSync + #if os(iOS) + @EnvironmentObject var player: PlayerPublisher + #endif + @ObservedObject var entry: Entry + @State var showTag: Bool = false + @State private var showDeleteConfirm = false + @State private var progress = 0.0 + + #if os(iOS) + let toolbarPlacement: ToolbarItemPlacement = .bottomBar + #else + let toolbarPlacement: ToolbarItemPlacement = .primaryAction + #endif + + var body: some View { + VStack(alignment: .leading) { + Text(entry.title?.htmlUnescape() ?? "Entry") + .font(.title) + .fontWeight(.black) + .lineLimit(2) + .padding(.horizontal) + ProgressView(value: progress, total: 1) + WebView(entry: entry, progress: $progress) + } + .addSwipeToBack { + dismiss() + } + .toolbar { + ToolbarItem(placement: toolbarPlacement) { + HStack { + FontSizeSelectorView() + .buttonStyle(.plain) + #if os(iOS) + Spacer() + #endif + Menu(content: { + bottomBarButton + }, label: { + Label("Entry option", systemImage: "filemenu.and.selection") + .foregroundColor(.primary) + .labelStyle(.iconOnly) + }) + .accessibilityLabel("Entry option") + .frame(width: 28, height: 28) + .contentShape(Rectangle()) + } + .actionSheet(isPresented: $showDeleteConfirm) { + ActionSheet( + title: Text("Confirm delete?"), + buttons: [ + .destructive(Text("Delete")) { + context.delete(entry) + dismiss() + }, + .cancel(), + ] + ) + } + } + } + .sheet(isPresented: $showTag) { + TagListFor(tagsForEntry: TagsForEntryPublisher(entry: entry)) + .environment(\.managedObjectContext, context) + } + #if os(iOS) + .navigationBarTitleDisplayMode(.inline) + #endif + } + + @ViewBuilder + private var bottomBarButton: some View { + Button(role: .destructive, action: { + showDeleteConfirm = true + }, label: { + Label("Delete", systemImage: "trash") + }) + Divider() + Button(action: { + openURL(entry.url!.url!) + }, label: { + Label("Open in Safari", systemImage: "safari") + }) + Button(action: { + showTag.toggle() + }, label: { + Label("Tag", systemImage: showTag ? "tag.fill" : "tag") + }) + Button(action: { + appSync.refresh(entry: entry) + }, label: { + Label("Refresh", systemImage: "arrow.counterclockwise") + }) + StarEntryButton(entry: entry, showText: true) + #if os(iOS) + .hapticNotification(.success) + #endif + ArchiveEntryButton(entry: entry, showText: true) { + dismiss() + } + #if os(iOS) + .hapticNotification(.success) + #endif + #if os(iOS) + Button(action: { + player.load(entry) + }, label: { + Label("Load entry", systemImage: "music.note") + }) + .accessibilityHint("Load entry in text-to-speech player") + #endif + } +} + +#if DEBUG + struct EntryView_Previews: PreviewProvider { + static var previews: some View { + let coreData = Container.shared.coreData() + EntryView(entry: Entry(context: coreData.viewContext)) + #if os(iOS) + .environmentObject(PlayerPublisher()) + #endif + .environment(\.managedObjectContext, coreData.viewContext) + } + } +#endif diff --git a/App/Features/Entry/Picture/EntryPicture.swift b/App/Features/Entry/Picture/EntryPicture.swift new file mode 100644 index 0000000..5050d03 --- /dev/null +++ b/App/Features/Entry/Picture/EntryPicture.swift @@ -0,0 +1,54 @@ +import SwiftUI +#if os(iOS) + import Combine + import UIKit + + struct EntryPicture: View { + @StateObject var imagePublisher = ImageDownloaderPublisher() + + var url: String? + + var body: some View { + Group { + if let image = imagePublisher.image { + Image(uiImage: image) + .resizable() + .scaledToFit() + } else { + Image(systemName: "book") + .resizable() + .scaledToFit() + } + }.task { + await imagePublisher.loadImage(url: url) + } + } + } +#endif + +#if os(macOS) + struct EntryPicture: View { + var url: String? + + var body: some View { + if let url { + AsyncImage(url: URL(string: url)) { image in + image + .resizable() + .scaledToFit() + } placeholder: { + placeholder + } + + } else { + placeholder + } + } + + private var placeholder: some View { + Image(systemName: "book") + .resizable() + .scaledToFit() + } + } +#endif diff --git a/App/Features/Entry/Picture/ImageCache.swift b/App/Features/Entry/Picture/ImageCache.swift new file mode 100644 index 0000000..656e9be --- /dev/null +++ b/App/Features/Entry/Picture/ImageCache.swift @@ -0,0 +1,72 @@ +import Combine +import Foundation +#if os(iOS) + import UIKit + + actor ImageCache { + static var shared = ImageCache() + + private var memoryCache: NSCache = { + let cache = NSCache() + // set limit? + return cache + }() + + private init() {} + + private func clearMemoryCache(_: Notification?) { + memoryCache.removeAllObjects() + } + + subscript(name: String) -> UIImage? { + get { + get(name: name) + } + set { + guard let image = newValue else { return } + set(image, for: name) + } + } + + func set(_ image: UIImage, for name: String) { + memoryCache.setObject(image, forKey: name as NSString) + + let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] + let filename = url.appendingPathComponent("\(name.md5).png") + + try? image.pngData()?.write(to: filename) + } + + func get(name: String) -> UIImage? { + if let imageCacheMemory = memoryCache.object(forKey: name.NSString) { + return imageCacheMemory + } + + let dir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] + let imageCacheDir = UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent("\(name.md5).png").path) + + if imageCacheDir != nil { + memoryCache.setObject(imageCacheDir!, forKey: name.NSString) + + return imageCacheDir + } + + return nil + } + + func purge() { + clearMemoryCache(nil) + + let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] + do { + let files = try FileManager.default.contentsOfDirectory(atPath: url.path) + try files.forEach { + try FileManager.default.removeItem(atPath: url.appendingPathComponent($0).path) + } + } catch { + print("Error in cache purge") + } + } + } + +#endif diff --git a/App/Features/Entry/Picture/ImageDownloader.swift b/App/Features/Entry/Picture/ImageDownloader.swift new file mode 100644 index 0000000..b089c29 --- /dev/null +++ b/App/Features/Entry/Picture/ImageDownloader.swift @@ -0,0 +1,36 @@ +import Combine +import Foundation +#if os(iOS) + import UIKit + + final class ImageDownloader { + private var cacheStore = ImageCache.shared + + private var dispatchQueue = DispatchQueue(label: "fr.district-web.wallabag.image-downloader", qos: .background) + + func loadImage(url: URL) async -> UIImage? { + if let imageCache = await cacheStore[url.absoluteString] { + return imageCache + } + + var request = URLRequest(url: url) + request.allowsConstrainedNetworkAccess = false + + do { + let (data, _) = try await URLSession.shared.data(for: request) + guard let image = UIImage(data: data) else { return nil } + + await cacheStore.set(image, for: url.absoluteString) + + return image + } catch {} + + return nil + } + } + +#endif + +#if os(macOS) + final class ImageDownloader {} +#endif diff --git a/App/Features/Entry/Picture/ImageDownloaderPublisher.swift b/App/Features/Entry/Picture/ImageDownloaderPublisher.swift new file mode 100644 index 0000000..9520065 --- /dev/null +++ b/App/Features/Entry/Picture/ImageDownloaderPublisher.swift @@ -0,0 +1,17 @@ +#if os(iOS) + import Combine + import Factory + import Foundation + import UIKit + + final class ImageDownloaderPublisher: ObservableObject { + @Injected(\.imageDownloader) private var imageDownloader + @Published var image: UIImage? + + @MainActor + func loadImage(url: String?) async { + guard let url = url?.url else { return } + image = await imageDownloader.loadImage(url: url) + } + } +#endif diff --git a/iOS/Features/Entry/UI/ArchiveEntryButton.swift b/App/Features/Entry/UI/ArchiveEntryButton.swift similarity index 64% rename from iOS/Features/Entry/UI/ArchiveEntryButton.swift rename to App/Features/Entry/UI/ArchiveEntryButton.swift index 008214f..b6f2ddf 100644 --- a/iOS/Features/Entry/UI/ArchiveEntryButton.swift +++ b/App/Features/Entry/UI/ArchiveEntryButton.swift @@ -2,10 +2,19 @@ import SwiftUI struct ArchiveEntryButton: View { @ObservedObject var entry: Entry - var showText: Bool = true + let showText: Bool + let action: (() -> Void)? + + init(entry: Entry, showText: Bool = true, action: (() -> Void)? = nil) { + self.entry = entry + self.showText = showText + self.action = action + } + var body: some View { Button(action: { - self.entry.toggleArchive() + entry.toggleArchive() + action?() }, label: { if showText { Label( diff --git a/iOS/Features/Entry/UI/DeleteEntryButton.swift b/App/Features/Entry/UI/DeleteEntryButton.swift similarity index 90% rename from iOS/Features/Entry/UI/DeleteEntryButton.swift rename to App/Features/Entry/UI/DeleteEntryButton.swift index 699c84c..b034357 100644 --- a/iOS/Features/Entry/UI/DeleteEntryButton.swift +++ b/App/Features/Entry/UI/DeleteEntryButton.swift @@ -6,7 +6,7 @@ struct DeleteEntryButton: View { var showText: Bool = true var body: some View { Button(action: { - self.showConfirm = true + showConfirm = true }, label: { if showText { Text("Delete") diff --git a/iOS/Features/Entry/UI/EntryPictoImage.swift b/App/Features/Entry/UI/EntryPictoImage.swift similarity index 100% rename from iOS/Features/Entry/UI/EntryPictoImage.swift rename to App/Features/Entry/UI/EntryPictoImage.swift diff --git a/iOS/Features/Entry/UI/FontSizeSelectorView.swift b/App/Features/Entry/UI/FontSizeSelectorView.swift similarity index 92% rename from iOS/Features/Entry/UI/FontSizeSelectorView.swift rename to App/Features/Entry/UI/FontSizeSelectorView.swift index 999b508..94ae1fd 100644 --- a/iOS/Features/Entry/UI/FontSizeSelectorView.swift +++ b/App/Features/Entry/UI/FontSizeSelectorView.swift @@ -9,7 +9,7 @@ struct FontSizeSelectorView: View { HStack { Button(action: { withAnimation { - self.showSelector = !self.showSelector + showSelector = !showSelector } }, label: { Image(systemName: "textformat.size") diff --git a/iOS/Features/Entry/UI/StarEntryButton.swift b/App/Features/Entry/UI/StarEntryButton.swift similarity index 93% rename from iOS/Features/Entry/UI/StarEntryButton.swift rename to App/Features/Entry/UI/StarEntryButton.swift index aa9b322..9893d63 100644 --- a/iOS/Features/Entry/UI/StarEntryButton.swift +++ b/App/Features/Entry/UI/StarEntryButton.swift @@ -5,7 +5,7 @@ struct StarEntryButton: View { var showText: Bool = true var body: some View { Button(action: { - self.entry.toggleStarred() + entry.toggleStarred() }, label: { if showText { Label( diff --git a/App/Features/Entry/WebView.swift b/App/Features/Entry/WebView.swift new file mode 100644 index 0000000..22e29c2 --- /dev/null +++ b/App/Features/Entry/WebView.swift @@ -0,0 +1,191 @@ +import CoreData +import SafariServices +import SwiftUI +import WebKit + +#if os(iOS) + struct WebView: UIViewRepresentable { + var entry: Entry + private(set) var wkWebView = WKWebView(frame: .zero) + @EnvironmentObject var appSetting: AppSetting + @Binding var progress: Double + + func makeCoordinator() -> Coordinator { + Coordinator(self, appSetting: appSetting) + } + + class Coordinator: NSObject, WKNavigationDelegate, UIScrollViewDelegate { + @CoreDataViewContext var context: NSManagedObjectContext + var appSetting: AppSetting + + private var webView: WebView + + init(_ webView: WebView, appSetting: AppSetting) { + self.webView = webView + self.appSetting = appSetting + super.init() + } + + func webViewToLastPosition() { + DispatchQueue.main.async { + self.webView.wkWebView.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.webView.entry.screenPositionForWebView), animated: true) + } + } + + func webView(_ webView: WKWebView, didFinish _: WKNavigation!) { + webViewToLastPosition() + webView.fontSizePercent(appSetting.webFontSizePercent) + } + + func webView(_: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + guard let urlTarget = navigationAction.request.url else { + decisionHandler(.cancel) + return + } + + let urlAbsolute = urlTarget.absoluteString + + if urlAbsolute.hasPrefix(Bundle.main.bundleURL.absoluteString) || urlAbsolute == "about:blank" { + decisionHandler(.allow) + return + } + + if navigationAction.targetFrame?.isMainFrame == false { + decisionHandler(.allow) + return + } + + let safariController = SFSafariViewController(url: urlTarget) + safariController.modalPresentationStyle = .overFullScreen + + UIApplication.shared.open(urlTarget, options: [:], completionHandler: nil) + decisionHandler(.cancel) + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + webView.progress = scrollView.contentOffset.y / (scrollView.contentSize.height - scrollView.bounds.height) + } + + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + context.perform { + self.webView.entry.screenPosition = Float(scrollView.contentOffset.y) + try? self.context.save() + } + } + } + + func makeUIView(context: Context) -> WKWebView { + wkWebView.navigationDelegate = context.coordinator + wkWebView.scrollView.delegate = context.coordinator + wkWebView.load(content: entry.content, justify: false) + + return wkWebView + } + + func updateUIView(_ webView: WKWebView, context _: Context) { + webView.fontSizePercent(appSetting.webFontSizePercent) + } + } +#endif + +#if os(macOS) + struct WebView: NSViewRepresentable { + var entry: Entry + private(set) var wkWebView = WKWebView(frame: .zero) + @EnvironmentObject var appSetting: AppSetting + + func makeNSView(context _: Context) -> WKWebView { + wkWebView.load(content: entry.content, justify: false) + + return wkWebView + } + + func updateNSView(_ nsView: WKWebView, context _: Context) { + nsView.load(content: entry.content, justify: false) + nsView.fontSizePercent(appSetting.webFontSizePercent) + } + + func makeCoordinator() -> Coordinator { + Coordinator(self, appSetting: appSetting) + } + + class Coordinator: NSObject, WKNavigationDelegate { + @CoreDataViewContext var context: NSManagedObjectContext + var appSetting: AppSetting + + private var webView: WebView + + init(_ webView: WebView, appSetting: AppSetting) { + self.webView = webView + self.appSetting = appSetting + super.init() + } + + func webViewToLastPosition() { + /* DispatchQueue.main.async { + self.webView.wkWebView.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.webView.entry.screenPositionForWebView), animated: true) + }*/ + } + + func webView(_ webView: WKWebView, didFinish _: WKNavigation!) { + webViewToLastPosition() + webView.fontSizePercent(appSetting.webFontSizePercent) + } + + func webView(_: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + guard let urlTarget = navigationAction.request.url else { + decisionHandler(.cancel) + return + } + + let urlAbsolute = urlTarget.absoluteString + + if urlAbsolute.hasPrefix(Bundle.main.bundleURL.absoluteString) || urlAbsolute == "about:blank" { + decisionHandler(.allow) + return + } + + if navigationAction.targetFrame?.isMainFrame == false { + decisionHandler(.allow) + return + } + + /* let safariController = SFSafariViewController(url: urlTarget) + safariController.modalPresentationStyle = .overFullScreen + + UIApplication.shared.open(urlTarget, options: [:], completionHandler: nil) + */ + decisionHandler(.cancel) + } + + /* + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + context.perform { + self.webView.entry.screenPosition = Float(scrollView.contentOffset.y) + try? self.context.save() + } + }*/ + } + } + +#endif + +struct WebView_Previews: PreviewProvider { + static var entry: Entry = { + let entry = Entry() + entry.title = "Test" + entry.content = "

Nice Content

" + return entry + }() + + static var previews: some View { + Group { + WebView( + entry: entry, progress: .constant(0.5) + ).colorScheme(.light) + WebView( + entry: entry, progress: .constant(0.5) + ).colorScheme(.dark) + } + } +} diff --git a/iOS/Features/Error/ErrorView.swift b/App/Features/Error/ErrorView.swift similarity index 100% rename from iOS/Features/Error/ErrorView.swift rename to App/Features/Error/ErrorView.swift diff --git a/iOS/Features/Error/ErrorViewModel.swift b/App/Features/Error/ErrorViewModel.swift similarity index 83% rename from iOS/Features/Error/ErrorViewModel.swift rename to App/Features/Error/ErrorViewModel.swift index f67dded..55a5f9a 100644 --- a/iOS/Features/Error/ErrorViewModel.swift +++ b/App/Features/Error/ErrorViewModel.swift @@ -1,9 +1,7 @@ import Combine import Foundation -class ErrorViewModel: ObservableObject { - static var shared = ErrorViewModel() - +final class ErrorViewModel: ObservableObject { private var resetAfter: Double init(_ resetAfter: Double = 10) { diff --git a/App/Features/Haptic/ButtonStyle/HapticNotificationButtonStyle.swift b/App/Features/Haptic/ButtonStyle/HapticNotificationButtonStyle.swift new file mode 100644 index 0000000..3f6216f --- /dev/null +++ b/App/Features/Haptic/ButtonStyle/HapticNotificationButtonStyle.swift @@ -0,0 +1,14 @@ +import SwiftUI + +#if os(iOS) + struct HapticNotificationButtonStyle: ButtonStyle { + let feedbackType: UINotificationFeedbackGenerator.FeedbackType + func makeBody(configuration: Configuration) -> some View { + if configuration.isPressed { + let generator = UINotificationFeedbackGenerator() + generator.notificationOccurred(feedbackType) + } + return configuration.label + } + } +#endif diff --git a/App/Features/Haptic/Extension/View+haptic.swift b/App/Features/Haptic/Extension/View+haptic.swift new file mode 100644 index 0000000..620af06 --- /dev/null +++ b/App/Features/Haptic/Extension/View+haptic.swift @@ -0,0 +1,9 @@ +import SwiftUI + +#if os(iOS) + extension View { + func hapticNotification(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) -> some View { + buttonStyle(HapticNotificationButtonStyle(feedbackType: feedbackType)) + } + } +#endif diff --git a/App/Features/MainView.swift b/App/Features/MainView.swift new file mode 100644 index 0000000..726d1a1 --- /dev/null +++ b/App/Features/MainView.swift @@ -0,0 +1,47 @@ +import Combine +import SwiftUI + +struct MainView: View { + @EnvironmentObject var appState: AppState + @EnvironmentObject var router: Router + + var body: some View { + if appState.registred { + mainView + } else { + RegistrationView() + } + } + + #if os(iOS) + var mainView: some View { + NavigationStack(path: $router.path) { + EntriesView() + .appRouting() + } + } + #endif + + #if os(macOS) + var mainView: some View { + NavigationSplitView { + EntriesView() + .appRouting() + } detail: { + Text("Choose one entry") + }.toolbar { + ToolbarItem { + RefreshButton() + } + } + } + #endif +} + +#if DEBUG + struct MainView_Previews: PreviewProvider { + static var previews: some View { + Text("nothing") + } + } +#endif diff --git a/App/Features/PasteBoard/PasteBoardView.swift b/App/Features/PasteBoard/PasteBoardView.swift new file mode 100644 index 0000000..49d98c6 --- /dev/null +++ b/App/Features/PasteBoard/PasteBoardView.swift @@ -0,0 +1,48 @@ +import SwiftUI + +#if os(iOS) + struct PasteBoardView: View { + @StateObject var pasteBoardViewModel = PasteBoardViewModel() + + var body: some View { + if pasteBoardViewModel.showPasteBoardView { + HStack(alignment: .center) { + Image(systemName: "doc.on.clipboard") + VStack { + Text("New url in pasteboard detected") + .font(.headline) + Text(pasteBoardViewModel.pasteBoardUrl) + .lineLimit(1) + HStack { + Button(action: { + pasteBoardViewModel.addUrl() + }, label: { + Text("Add") + }) + Button(action: { + pasteBoardViewModel.hide() + }, label: { + Text("Cancel") + }) + } + } + } + } + } + } + + struct PasteBoardView_Previews: PreviewProvider { + static var publisher: PasteBoardViewModel = { + let pub = PasteBoardViewModel() + pub.pasteBoardUrl = "http://wallabag-with-a-long-url.org" + return pub + }() + + static var previews: some View { + Group { + PasteBoardView().previewLayout(.sizeThatFits).environmentObject(publisher) + PasteBoardView().previewLayout(.fixed(width: 250, height: 60)).environmentObject(publisher) + } + } + } +#endif diff --git a/App/Features/PasteBoard/PasteBoardViewModel.swift b/App/Features/PasteBoard/PasteBoardViewModel.swift new file mode 100644 index 0000000..b7f6484 --- /dev/null +++ b/App/Features/PasteBoard/PasteBoardViewModel.swift @@ -0,0 +1,51 @@ +#if os(iOS) + import Combine + import Factory + import Foundation + import SharedLib + import UIKit + + class PasteBoardViewModel: ObservableObject { + @Published var showPasteBoardView: Bool = false { + willSet { + if newValue { + if let newPasteBoardUrl = UIPasteboard.general.url { + WallabagUserDefaults.previousPasteBoardUrl = newPasteBoardUrl.absoluteString + pasteBoardUrl = newPasteBoardUrl.absoluteString + } + } + } + } + + @Published var pasteBoardUrl: String = "" + @Injected(\.wallabagSession) var session + + private var cancellableNotification: AnyCancellable? + + init() { + cancellableNotification = NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification) + .map { _ -> Bool in + guard let pasteBoardUrl = UIPasteboard.general.url, + pasteBoardUrl.absoluteString != WallabagUserDefaults.previousPasteBoardUrl + else { + return false + } + return true + } + .assign(to: \.showPasteBoardView, on: self) + } + + deinit { + cancellableNotification?.cancel() + } + + func addUrl() { + session.addEntry(url: pasteBoardUrl) {} + showPasteBoardView = false + } + + func hide() { + showPasteBoardView = false + } + } +#endif diff --git a/App/Features/Player/PlayerPublisher.swift b/App/Features/Player/PlayerPublisher.swift new file mode 100644 index 0000000..fcd3034 --- /dev/null +++ b/App/Features/Player/PlayerPublisher.swift @@ -0,0 +1,81 @@ +import AVFoundation +import Combine +import Foundation +import MediaPlayer +import SwiftUI + +#if os(iOS) + final class PlayerPublisher: ObservableObject { + static var shared = PlayerPublisher() + private var speecher = AVSpeechSynthesizer() + private var utterance: AVSpeechUtterance? + + @Published var podcast: Podcast? + @Published var showPlayer: Bool = false + @Published private(set) var isPlaying = false { + willSet { + if newValue { + play() + } else { + pause() + } + } + } + + init() { + MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = false + MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = false + MPRemoteCommandCenter.shared().playCommand.addTarget { _ in + self.play() + return .success + } + MPRemoteCommandCenter.shared().pauseCommand.addTarget { _ in + self.pause() + return .success + } + } + + func load(_ entry: Entry) { + isPlaying = false + showPlayer = true + podcast = Podcast(id: entry.id, title: entry.title ?? "Title", content: entry.content?.withoutHTML ?? "", picture: entry.previewPicture) + utterance = AVSpeechUtterance(string: podcast!.content) + MPNowPlayingInfoCenter.default().nowPlayingInfo = [ + MPMediaItemPropertyTitle: entry.title, + MPMediaItemPropertyArtist: "Wallabag", + ] + try? AVAudioSession.sharedInstance().setActive(true) + try? AVAudioSession.sharedInstance().setCategory(.playback) + } + + func togglePlaying() { + isPlaying = !isPlaying + } + + func play() { + guard let utterance else { return } + if !speecher.isSpeaking { + speecher.speak(utterance) + } else { + if speecher.isPaused { + speecher.continueSpeaking() + } else { + speecher.pauseSpeaking(at: .word) + } + } + } + + func pause() { + speecher.pauseSpeaking(at: .word) + } + + func stop() { + isPlaying = false + speecher.stopSpeaking(at: .immediate) + } + + func togglePlayer() { + showPlayer.toggle() + } + } +#endif diff --git a/App/Features/Player/PlayerView.swift b/App/Features/Player/PlayerView.swift new file mode 100644 index 0000000..64907b2 --- /dev/null +++ b/App/Features/Player/PlayerView.swift @@ -0,0 +1,76 @@ +import Factory +import SwiftUI + +#if os(iOS) + struct PlayerView: View { + @EnvironmentObject var playerPublisher: PlayerPublisher + + var body: some View { + VStack { + if playerPublisher.podcast != nil { + playerPublisher.podcast.map { podcast in + VStack { + EntryPicture(url: podcast.picture).frame(width: 100, alignment: .center) + Text(podcast.title) + .padding(4) + HStack { + Button(action: { + playerPublisher.togglePlaying() + }, label: { + Image(systemName: playerPublisher.isPlaying ? "pause.circle" : "play.circle") + }).font(.system(size: 30)) + Button(action: { + playerPublisher.stop() + }, label: { + Image(systemName: "stop.circle") + }).font(.system(size: 30)) + } + .buttonStyle(.plain) + }.padding() + } + } else { + VStack { + EntryPicture(url: nil).frame(width: 100, alignment: .center) + Text("Select one entry") + .padding(4) + HStack { + Button(action: {}, label: { + Image(systemName: "play.circle") + .font(.system(size: 30)) + }).disabled(true) + } + } + } + } + .frame(width: 200, height: 200, alignment: .center) + .background(Color.primary.colorInvert()) + .cornerRadius(6) + .shadow(radius: 10) + .gesture(DragGesture().onEnded { swipe in + if swipe.startLocation.x < swipe.location.x { + playerPublisher.showPlayer = false + } + }) + } + } + + struct PlayerView_Previews: PreviewProvider { + static var player: PlayerPublisher = { + let coreData = Container.shared.coreData() + let player = PlayerPublisher() + let entry = Entry(context: coreData.viewContext) + player.load(entry) + return player + }() + + static var previews: some View { + PlayerView() + .environmentObject(PlayerPublisher()) + .previewLayout(.sizeThatFits) + + PlayerView() + .environmentObject(player) + .previewLayout(.sizeThatFits) + } + } +#endif diff --git a/iOS/Features/Registration/ClientIdClientSecret/ClientIdClientSecretView.swift b/App/Features/Registration/ClientIdClientSecret/ClientIdClientSecretView.swift similarity index 73% rename from iOS/Features/Registration/ClientIdClientSecret/ClientIdClientSecretView.swift rename to App/Features/Registration/ClientIdClientSecret/ClientIdClientSecretView.swift index 5673a26..cafcb5f 100644 --- a/iOS/Features/Registration/ClientIdClientSecret/ClientIdClientSecretView.swift +++ b/App/Features/Registration/ClientIdClientSecret/ClientIdClientSecretView.swift @@ -9,19 +9,26 @@ struct ClientIdClientSecretView: View { Section(header: Text("Client id")) { TextField("Client id", text: $clientIdSecretViewModel.clientId) .disableAutocorrection(true) + #if os(iOS) .autocapitalization(.none) + #endif } Section(header: Text("Client secret")) { TextField("Client secret", text: $clientIdSecretViewModel.clientSecret) .disableAutocorrection(true) + #if os(iOS) .autocapitalization(.none) + #endif } NavigationLink("Next", destination: LoginView()).disabled(!clientIdSecretViewModel.isValid) - }.navigationBarTitle("Client id & secret") - .navigationBarItems(trailing: - Link(destination: Bundle.infoForKey("DOCUMENTATION_URL")!.url!) { - Text("Open documentation") - }) + } + #if os(iOS) + .navigationBarTitle("Client id & secret") + .navigationBarItems(trailing: + Link(destination: Bundle.infoForKey("DOCUMENTATION_URL")!.url!) { + Text("Open documentation") + }) + #endif } } diff --git a/iOS/Features/Registration/ClientIdClientSecret/ClientIdClientSecretViewModel.swift b/App/Features/Registration/ClientIdClientSecret/ClientIdClientSecretViewModel.swift similarity index 88% rename from iOS/Features/Registration/ClientIdClientSecret/ClientIdClientSecretViewModel.swift rename to App/Features/Registration/ClientIdClientSecret/ClientIdClientSecretViewModel.swift index c597e7d..b01d968 100644 --- a/iOS/Features/Registration/ClientIdClientSecret/ClientIdClientSecretViewModel.swift +++ b/App/Features/Registration/ClientIdClientSecret/ClientIdClientSecretViewModel.swift @@ -1,5 +1,6 @@ import Combine import Foundation +import SharedLib import SwiftUI class ClientIdSecretViewModel: ObservableObject { @@ -15,8 +16,8 @@ class ClientIdSecretViewModel: ObservableObject { clientSecret = WallabagUserDefaults.clientSecret cancellable = Publishers.CombineLatest($clientId, $clientSecret).sink { [unowned self] clientId, clientSecret in - self.isValid = !clientId.isEmpty && !clientSecret.isEmpty - if self.isValid { + isValid = !clientId.isEmpty && !clientSecret.isEmpty + if isValid { WallabagUserDefaults.clientId = clientId.trimmingCharacters(in: .whitespacesAndNewlines) WallabagUserDefaults.clientSecret = clientSecret.trimmingCharacters(in: .whitespacesAndNewlines) } diff --git a/iOS/Features/Registration/Login/LoginView.swift b/App/Features/Registration/Login/LoginView.swift similarity index 73% rename from iOS/Features/Registration/Login/LoginView.swift rename to App/Features/Registration/Login/LoginView.swift index d3d074e..13fd1ab 100644 --- a/iOS/Features/Registration/Login/LoginView.swift +++ b/App/Features/Registration/Login/LoginView.swift @@ -7,14 +7,16 @@ struct LoginView: View { Form { Section(header: Text("Login")) { TextField("Login", text: $loginViewModel.login) + #if os(iOS) .disableAutocorrection(true) .autocapitalization(.none) + #endif } Section(header: Text("Password")) { SecureField("Password", text: $loginViewModel.password) } Button("Login") { - self.loginViewModel.tryLogin() + loginViewModel.tryLogin() }.disabled(!loginViewModel.isValid) loginViewModel.error.map { error in VStack { @@ -22,11 +24,14 @@ struct LoginView: View { Link("Report issue", destination: "https://github.com/wallabag/ios-app/issues") } } - }.navigationBarTitle("Login & Password") - .navigationBarItems(trailing: - Link(destination: Bundle.infoForKey("DOCUMENTATION_URL")!.url!) { - Text("Open documentation") - }) + } + #if os(iOS) + .navigationBarTitle("Login & Password") + .navigationBarItems(trailing: + Link(destination: Bundle.infoForKey("DOCUMENTATION_URL")!.url!) { + Text("Open documentation") + }) + #endif } } diff --git a/iOS/Features/Registration/Login/LoginViewModel.swift b/App/Features/Registration/Login/LoginViewModel.swift similarity index 69% rename from iOS/Features/Registration/Login/LoginViewModel.swift rename to App/Features/Registration/Login/LoginViewModel.swift index ef5b8e4..4af5837 100644 --- a/iOS/Features/Registration/Login/LoginViewModel.swift +++ b/App/Features/Registration/Login/LoginViewModel.swift @@ -1,30 +1,32 @@ import Combine +import Factory import Foundation +import SharedLib class LoginViewModel: ObservableObject { + @Injected(\.appState) private var appState + @Injected(\.wallabagSession) private var session + @Injected(\.router) private var router + @Published var login: String = "" @Published var password: String = "" @Published var error: String? - @Injector var appState: AppState - @Injector var router: Router - private(set) var isValid: Bool = false private var cancellable = Set() init() { login = WallabagUserDefaults.login Publishers.CombineLatest($login, $password).sink { [unowned self] login, password in - self.isValid = !login.isEmpty && !password.isEmpty + isValid = !login.isEmpty && !password.isEmpty }.store(in: &cancellable) - appState.session.$state.receive(on: DispatchQueue.main).sink { [unowned self] state in + session.$state.receive(on: DispatchQueue.main).sink { [unowned self] state in switch state { case let .error(reason): - self.error = reason + error = reason case .connected: - self.appState.registred = true - self.router.load(.entries) + appState.registred = true case .unknown, .connecting, .offline: break } @@ -35,8 +37,8 @@ class LoginViewModel: ObservableObject { error = nil WallabagUserDefaults.login = login WallabagUserDefaults.password = password - appState.session.kit.host = WallabagUserDefaults.host - appState.session.requestSession( + session.kit.host = WallabagUserDefaults.host + session.requestSession( clientId: WallabagUserDefaults.clientId, clientSecret: WallabagUserDefaults.clientSecret, username: login, diff --git a/iOS/Features/Registration/RegistrationView.swift b/App/Features/Registration/RegistrationView.swift similarity index 76% rename from iOS/Features/Registration/RegistrationView.swift rename to App/Features/Registration/RegistrationView.swift index 4f831cc..deca59c 100644 --- a/iOS/Features/Registration/RegistrationView.swift +++ b/App/Features/Registration/RegistrationView.swift @@ -2,7 +2,7 @@ import SwiftUI struct RegistrationView: View { var body: some View { - NavigationView { + NavigationStack { VStack { Image("logo") .resizable() @@ -11,9 +11,11 @@ struct RegistrationView: View { .font(.title) NavigationLink("Log in", destination: ServerView()) .buttonStyle(.borderedProminent) - .buttonBorderShape(.capsule) - }.navigationBarHidden(true) - }.navigationViewStyle(StackNavigationViewStyle()) + } + #if os(iOS) + .navigationBarHidden(true) + #endif + } } } diff --git a/iOS/Features/Registration/Server/ServerView.swift b/App/Features/Registration/Server/ServerView.swift similarity index 70% rename from iOS/Features/Registration/Server/ServerView.swift rename to App/Features/Registration/Server/ServerView.swift index abbc2f6..11c242c 100644 --- a/iOS/Features/Registration/Server/ServerView.swift +++ b/App/Features/Registration/Server/ServerView.swift @@ -8,16 +8,21 @@ struct ServerView: View { Section(header: Text("Server")) { TextField("https://your-instance.domain", text: $serverViewModel.url) .disableAutocorrection(true) + #if os(iOS) .autocapitalization(.none) + #endif } NavigationLink(destination: ClientIdClientSecretView()) { Text("Next") }.disabled(!serverViewModel.isValid) - }.navigationBarTitle("Server") - .navigationBarItems(trailing: - Link(destination: Bundle.infoForKey("DOCUMENTATION_URL")!.url!) { - Text("Open documentation") - }) + } + #if os(iOS) + .navigationBarTitle("Server") + .navigationBarItems(trailing: + Link(destination: Bundle.infoForKey("DOCUMENTATION_URL")!.url!) { + Text("Open documentation") + }) + #endif } } diff --git a/iOS/Features/Registration/Server/ServerViewModel.swift b/App/Features/Registration/Server/ServerViewModel.swift similarity index 78% rename from iOS/Features/Registration/Server/ServerViewModel.swift rename to App/Features/Registration/Server/ServerViewModel.swift index 8086f0d..b0ae09c 100644 --- a/iOS/Features/Registration/Server/ServerViewModel.swift +++ b/App/Features/Registration/Server/ServerViewModel.swift @@ -1,10 +1,10 @@ import Combine import Foundation +import SharedLib import SwiftUI -class ServerViewModel: ObservableObject { +final class ServerViewModel: ObservableObject { @Published private(set) var isValid: Bool = false - @Published var url: String = "" private var cancellable: AnyCancellable? @@ -12,8 +12,8 @@ class ServerViewModel: ObservableObject { init() { url = WallabagUserDefaults.host cancellable = $url.sink { [unowned self] url in - self.isValid = self.validateServer(host: url) - if self.isValid { + isValid = validateServer(host: url) + if isValid { WallabagUserDefaults.host = url } } diff --git a/App/Features/Router/Route.swift b/App/Features/Router/Route.swift new file mode 100644 index 0000000..65f71e9 --- /dev/null +++ b/App/Features/Router/Route.swift @@ -0,0 +1,11 @@ +import Foundation +import SwiftUI + +enum RoutePath: Hashable { + case registration + case addEntry + case entry(Entry) + case tips + case about + case setting +} diff --git a/App/Features/Router/RouteSwiftUIExtension.swift b/App/Features/Router/RouteSwiftUIExtension.swift new file mode 100644 index 0000000..4994490 --- /dev/null +++ b/App/Features/Router/RouteSwiftUIExtension.swift @@ -0,0 +1,30 @@ +// +// RouteSwiftUIExtension.swift +// wallabag (iOS) +// +// Created by maxime marinel on 13/03/2023. +// + +import Foundation +import SwiftUI + +extension View { + func appRouting() -> some View { + navigationDestination(for: RoutePath.self) { route in + switch route { + case .addEntry: + AddEntryView() + case let .entry(entry): + EntryView(entry: entry) + case .about: + AboutView() + case .tips: + TipView() + case .setting: + SettingView() + default: + Text("test") + } + } + } +} diff --git a/App/Features/Router/Router.swift b/App/Features/Router/Router.swift new file mode 100644 index 0000000..05923d0 --- /dev/null +++ b/App/Features/Router/Router.swift @@ -0,0 +1,7 @@ +import Combine +import Foundation +import SwiftUI + +final class Router: ObservableObject { + @Published var path: [RoutePath] = [] +} diff --git a/iOS/Features/Search/SearchView.swift b/App/Features/Search/SearchView.swift similarity index 74% rename from iOS/Features/Search/SearchView.swift rename to App/Features/Search/SearchView.swift index 4525c7d..bd1ccb0 100644 --- a/iOS/Features/Search/SearchView.swift +++ b/App/Features/Search/SearchView.swift @@ -17,21 +17,24 @@ struct SearchView: View { HStack { if showSearchBar { TextField("Search", text: $searchViewModel.search) - .textFieldStyle(RoundedBorderTextFieldStyle()) + .textFieldStyle(.roundedBorder) .disableAutocorrection(true) + #if os(iOS) .autocapitalization(.none) + #endif .padding(.leading) } else { RetrieveModePicker(filter: $searchViewModel.retrieveMode) } Button(action: { withAnimation { - self.showSearchBar = !self.showSearchBar + showSearchBar = !showSearchBar } }, label: { - Image(systemName: self.showSearchBar ? "list.bullet.below.rectangle" : "magnifyingglass") + Image(systemName: showSearchBar ? "list.bullet.below.rectangle" : "magnifyingglass") .padding(.trailing) - }).buttonStyle(PlainButtonStyle()) + }) + .buttonStyle(.plain) } } } diff --git a/iOS/Features/Search/SearchViewModel.swift b/App/Features/Search/SearchViewModel.swift similarity index 100% rename from iOS/Features/Search/SearchViewModel.swift rename to App/Features/Search/SearchViewModel.swift diff --git a/iOS/Features/Setting/AppSetting.swift b/App/Features/Setting/AppSetting.swift similarity index 96% rename from iOS/Features/Setting/AppSetting.swift rename to App/Features/Setting/AppSetting.swift index 9a18e46..264096e 100644 --- a/iOS/Features/Setting/AppSetting.swift +++ b/App/Features/Setting/AppSetting.swift @@ -1,5 +1,6 @@ import Combine import Foundation +import SharedLib final class AppSetting: ObservableObject { @Published var webFontSizePercent: Double diff --git a/App/Features/Setting/SettingView.swift b/App/Features/Setting/SettingView.swift new file mode 100644 index 0000000..1273e5b --- /dev/null +++ b/App/Features/Setting/SettingView.swift @@ -0,0 +1,39 @@ +import SharedLib +import SwiftUI + +struct SettingView: View { + @AppStorage("showImageInList") var showImageInList: Bool = true + @AppStorage("justifyArticle") var justifyArticle: Bool = true + @AppStorage("badge") var badge: Bool = true + @AppStorage("defaultMode") var defaultMode: String = RetrieveMode.allArticles.rawValue + @AppStorage("itemPerPageDuringSync") var itemPerPageDuringSync: Int = 50 + + var body: some View { + Form { + Section("Entries list") { + Toggle("Show image in list", isOn: $showImageInList) + Picker("Default mode", selection: $defaultMode) { + ForEach(RetrieveMode.allCases, id: \.rawValue) { + Text($0.rawValue).tag($0.settingCase) + } + } + } + Section("Badge") { + Toggle("Show badge", isOn: $badge) + } + Section("Entry") { + Toggle("Justify entry", isOn: $justifyArticle) + } + Section("Sync") { + Stepper("Item per page during sync \(itemPerPageDuringSync)", value: $itemPerPageDuringSync, in: 20 ... 200) + } + } + .navigationTitle("Setting") + } +} + +struct SettingView_Previews: PreviewProvider { + static var previews: some View { + SettingView() + } +} diff --git a/iOS/Features/Sync/AppSync.swift b/App/Features/Sync/AppSync.swift similarity index 91% rename from iOS/Features/Sync/AppSync.swift rename to App/Features/Sync/AppSync.swift index e5fc110..4535f23 100644 --- a/iOS/Features/Sync/AppSync.swift +++ b/App/Features/Sync/AppSync.swift @@ -1,19 +1,21 @@ import Combine import CoreData +import Factory import Foundation +import SharedLib import WallabagKit -class AppSync: ObservableObject { - static var shared = AppSync() - @Injector var session: WallabagSession - @Injector var errorViewModel: ErrorViewModel +final class AppSync: ObservableObject { + @Injected(\.wallabagSession) private var session + @Injected(\.errorHandler) private var errorViewModel + @Injected(\.coreData) private var coreData @CoreDataViewContext var coreDataContext: NSManagedObjectContext @Published private(set) var inProgress = false @Published private(set) var progress: Float = 0.0 - private var backgroundContext: NSManagedObjectContext = { - let context = CoreData.shared.persistentContainer.newBackgroundContext() + private lazy var backgroundContext: NSManagedObjectContext = { + let context = coreData.persistentContainer.newBackgroundContext() context.mergePolicy = NSOverwriteMergePolicy return context }() diff --git a/iOS/Features/Sync/CoreDataSync.swift b/App/Features/Sync/CoreDataSync.swift similarity index 87% rename from iOS/Features/Sync/CoreDataSync.swift rename to App/Features/Sync/CoreDataSync.swift index 948bdf3..4061d4e 100644 --- a/iOS/Features/Sync/CoreDataSync.swift +++ b/App/Features/Sync/CoreDataSync.swift @@ -1,13 +1,14 @@ import Combine import CoreData +import Factory import Foundation import SharedLib class CoreDataSync { private var objectsDidChangeCancellable: AnyCancellable? - @Injector var appSync: AppSync - @Injector var wallabagSession: WallabagSession + @Injected(\.appSync) private var appSync + @Injected(\.wallabagSession) var wallabagSession init() { objectsDidChangeCancellable = NotificationCenter.default @@ -26,11 +27,9 @@ class CoreDataSync { } } - // swiftlint:disable force_cast private func deletedObjects(_ deletedObjects: Set) { deletedObjects - .filter { $0 is Entry } - .map { entry -> Entry in entry as! Entry } + .compactMap { $0 as? Entry } .forEach { entry in self.wallabagSession.delete(entry: entry) } @@ -47,7 +46,7 @@ class CoreDataSync { changedValues.removeValue(forKey: "tags") if changedValues.count > 0 { logger.debug("Push update entry \(entry.id) to remote") - self.wallabagSession.update( + wallabagSession.update( entry, parameters: [ diff --git a/App/Features/Sync/RefreshButton.swift b/App/Features/Sync/RefreshButton.swift new file mode 100644 index 0000000..ebbe3c7 --- /dev/null +++ b/App/Features/Sync/RefreshButton.swift @@ -0,0 +1,36 @@ +import SwiftUI + +struct RefreshButton: View { + @EnvironmentObject var appSync: AppSync + + var body: some View { + HStack { + if appSync.inProgress { + ProgressView(value: appSync.progress, total: 100) + #if os(iOS) + .progressViewStyle(.linear) + #else + .progressViewStyle(.circular) + #endif + } else { + Button( + action: appSync.requestSync, + label: { + Image(systemName: "arrow.counterclockwise") + .frame(width: 34, height: 34, alignment: .center) + } + ) + .buttonStyle(.plain) + .accessibilityLabel("Refresh") + .accessibilityHint("Refres entries from server") + .keyboardShortcut("r", modifiers: .command) + } + } + } +} + +struct RefreshButton_Previews: PreviewProvider { + static var previews: some View { + RefreshButton().environmentObject(AppSync()) + } +} diff --git a/iOS/Features/Tag/TagListFor.swift b/App/Features/Tag/TagListFor.swift similarity index 81% rename from iOS/Features/Tag/TagListFor.swift rename to App/Features/Tag/TagListFor.swift index f868801..bb711bf 100644 --- a/iOS/Features/Tag/TagListFor.swift +++ b/App/Features/Tag/TagListFor.swift @@ -13,12 +13,12 @@ struct TagListFor: View { HStack { TextField("New tag", text: $tagLabel) Button(action: { - self.tagsForEntry.add(tag: self.tagLabel) - self.tagLabel = "" + tagsForEntry.add(tag: tagLabel) + tagLabel = "" }, label: { Text("Add") }) }.padding(.horizontal) List(tagsForEntry.tags) { tag in - TagRow(tag: tag, tagsForEntry: self.tagsForEntry) + TagRow(tag: tag, tagsForEntry: tagsForEntry) } } } diff --git a/iOS/Features/Tag/TagRow.swift b/App/Features/Tag/TagRow.swift similarity index 78% rename from iOS/Features/Tag/TagRow.swift rename to App/Features/Tag/TagRow.swift index e6a9aa5..0596393 100644 --- a/iOS/Features/Tag/TagRow.swift +++ b/App/Features/Tag/TagRow.swift @@ -12,10 +12,10 @@ struct TagRow: View { Image(systemName: "checkmark") } }.onTapGesture { - if self.tag.isChecked { - self.tagsForEntry.delete(tag: self.tag) + if tag.isChecked { + tagsForEntry.delete(tag: tag) } else { - self.tagsForEntry.add(tag: self.tag) + tagsForEntry.add(tag: tag) } } } diff --git a/iOS/Features/Tag/TagsForEntryPublisher.swift b/App/Features/Tag/TagsForEntryPublisher.swift similarity index 70% rename from iOS/Features/Tag/TagsForEntryPublisher.swift rename to App/Features/Tag/TagsForEntryPublisher.swift index 702e2fb..513a7b0 100644 --- a/iOS/Features/Tag/TagsForEntryPublisher.swift +++ b/App/Features/Tag/TagsForEntryPublisher.swift @@ -1,20 +1,22 @@ import Combine import CoreData +import Factory import Foundation -// swiftlint:disable all +// swiftlint:disable:next all class TagsForEntryPublisher: ObservableObject { + @Injected(\.wallabagSession) private var session + var objectWillChange = PassthroughSubject() var tags: [Tag] var entry: Entry @CoreDataViewContext var coreDataContext: NSManagedObjectContext - @Injector var appState: AppState init(entry: Entry) { self.entry = entry - tags = try! CoreData.shared.viewContext.fetch(Tag.fetchRequestSorted()) + tags = (try? Container.shared.coreData().viewContext.fetch(Tag.fetchRequestSorted())) ?? [] tags.filter { tag in entry.tags.contains(tag) @@ -27,13 +29,13 @@ class TagsForEntryPublisher: ObservableObject { } func add(tag: String) { - appState.session.add(tag: tag, for: entry) + session.add(tag: tag, for: entry) objectWillChange.send() } func delete(tag: Tag) { tag.isChecked = false tag.objectWillChange.send() - appState.session.delete(tag: tag, for: entry) + session.delete(tag: tag, for: entry) } } diff --git a/iOS/Features/Tip/TipView.swift b/App/Features/Tip/TipView.swift similarity index 89% rename from iOS/Features/Tip/TipView.swift rename to App/Features/Tip/TipView.swift index a6dc805..e27d932 100644 --- a/iOS/Features/Tip/TipView.swift +++ b/App/Features/Tip/TipView.swift @@ -21,11 +21,11 @@ struct TipView: View { HStack { Spacer() if tipViewModel.canMakePayments { - if self.tipViewModel.tipProduct != nil { + if tipViewModel.tipProduct != nil { Button( action: { Task { await purchase() } }, label: { - self.tipViewModel.tipProduct.map { product in + tipViewModel.tipProduct.map { product in HStack { Text(product.displayName) Text(product.displayPrice) @@ -42,7 +42,9 @@ struct TipView: View { Spacer() } Spacer() - }.padding() + } + .padding() + .navigationTitle("Don") } @MainActor diff --git a/iOS/Features/Tip/TipViewModel.swift b/App/Features/Tip/TipViewModel.swift similarity index 96% rename from iOS/Features/Tip/TipViewModel.swift rename to App/Features/Tip/TipViewModel.swift index 655005e..9af125c 100644 --- a/iOS/Features/Tip/TipViewModel.swift +++ b/App/Features/Tip/TipViewModel.swift @@ -11,7 +11,7 @@ final class TipViewModel: ObservableObject { init() { canMakePayments = SKPaymentQueue.canMakePayments() if canMakePayments { - Task { + Task { @MainActor in let product = try? await requestProduct() tipProduct = product?.first } @@ -20,13 +20,12 @@ final class TipViewModel: ObservableObject { taskHandle = listenForTransactions() } - @MainActor private func requestProduct() async throws -> [Product] { try await Product.products(for: ["tips1"]) } func listenForTransactions() -> Task { - Task.detached { + Task { for await result in Transaction.updates { do { let transaction = try self.checkVerified(result) diff --git a/iOS/Info.plist b/App/Info.plist similarity index 93% rename from iOS/Info.plist rename to App/Info.plist index 06761bb..ef38ff6 100644 --- a/iOS/Info.plist +++ b/App/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.2.1 + 7.0.0 CFBundleVersion 319 LSRequiresIPhoneOS @@ -50,5 +50,7 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + LSApplicationCategoryType + public.app-category.utilities diff --git a/iOS/Lib/AppState.swift b/App/Lib/AppState.swift similarity index 83% rename from iOS/Lib/AppState.swift rename to App/Lib/AppState.swift index f16a609..8b0fbb9 100644 --- a/iOS/Lib/AppState.swift +++ b/App/Lib/AppState.swift @@ -1,10 +1,12 @@ import Combine +import Factory import Foundation +import SharedLib import SwiftUI import WallabagKit -class AppState: NSObject, ObservableObject { - static var shared = AppState() +final class AppState: NSObject, ObservableObject { + @Injected(\.wallabagSession) private var session @Published var registred: Bool = false { didSet { @@ -12,9 +14,6 @@ class AppState: NSObject, ObservableObject { } } - @Injector var session: WallabagSession - @Injector var router: Router - @AppStorage("readingSpeed") var readingSpeed: Double = 200 override init() { @@ -35,7 +34,6 @@ class AppState: NSObject, ObservableObject { logger.debug("Logout called") registred = false session.state = .unknown - router.load(.registration) } /// Fetch user config from server @@ -43,7 +41,7 @@ class AppState: NSObject, ObservableObject { private func fetchConfig() { logger.info("Fetch user config") session.config { [weak self] config in - guard let config = config else { return } + guard let config else { return } logger.debug("User config available") DispatchQueue.main.async { self?.readingSpeed = config.readingSpeed diff --git a/Shared/Lib/CoreData.swift b/App/Lib/CoreData.swift similarity index 95% rename from Shared/Lib/CoreData.swift rename to App/Lib/CoreData.swift index 8286020..230889a 100644 --- a/Shared/Lib/CoreData.swift +++ b/App/Lib/CoreData.swift @@ -2,10 +2,6 @@ import CoreData import Foundation final class CoreData { - static let shared = CoreData() - - private init() {} - lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "wallabagStore") diff --git a/App/Lib/DependencyInjection.swift b/App/Lib/DependencyInjection.swift new file mode 100644 index 0000000..4b8d86b --- /dev/null +++ b/App/Lib/DependencyInjection.swift @@ -0,0 +1,82 @@ +import Factory +import Foundation +import SharedLib +import WallabagKit + +extension Container { + var appState: Factory { + Factory(self) { + AppState() + }.scope(.singleton) + } + + var router: Factory { + Factory(self) { + Router() + }.scope(.singleton) + } + + var errorHandler: Factory { + Factory(self) { + ErrorViewModel() + }.scope(.singleton) + } + + #if os(iOS) + var playerPublisher: Factory { + Factory(self) { + PlayerPublisher() + }.scope(.singleton) + } + #endif + + var appSync: Factory { + Factory(self) { + AppSync() + }.scope(.singleton) + } + + var wallabagSession: Factory { + Factory(self) { + WallabagSession() + }.scope(.singleton) + } + + var imageDownloader: Factory { + Factory(self) { + ImageDownloader() + }.scope(.singleton) + } + + var coreDataSync: Factory { + Factory(self) { + CoreDataSync() + }.scope(.singleton) + } + + var appSetting: Factory { + Factory(self) { + AppSetting() + }.scope(.singleton) + } + + var coreData: Factory { + Factory(self) { + CoreData() + }.scope(.singleton) + } + + var wallabagKit: Factory { + Factory(self) { + let kit = WallabagKit(host: WallabagUserDefaults.host) + kit.clientId = WallabagUserDefaults.clientId + kit.clientSecret = WallabagUserDefaults.clientSecret + kit.username = WallabagUserDefaults.login + kit.password = WallabagUserDefaults.password + kit.accessToken = WallabagUserDefaults.accessToken + kit.refreshToken = WallabagUserDefaults.refreshToken + + return kit + }.scope(.singleton) + } +} diff --git a/iOS/Lib/WallabagError.swift b/App/Lib/WallabagError.swift similarity index 100% rename from iOS/Lib/WallabagError.swift rename to App/Lib/WallabagError.swift diff --git a/Shared/Lib/WallabagSession.swift b/App/Lib/WallabagSession.swift similarity index 95% rename from Shared/Lib/WallabagSession.swift rename to App/Lib/WallabagSession.swift index 0c3f9ae..ff29687 100644 --- a/Shared/Lib/WallabagSession.swift +++ b/App/Lib/WallabagSession.swift @@ -1,6 +1,8 @@ import Combine import CoreData +import Factory import Foundation +import SharedLib import WallabagKit class WallabagSession: ObservableObject { @@ -13,7 +15,7 @@ class WallabagSession: ObservableObject { } @Published var state: State = .unknown - @Injector var kit: WallabagKit + @Injected(\.wallabagKit) var kit @CoreDataViewContext var coreDataContext: NSManagedObjectContext private var cancellable = Set() @@ -38,7 +40,7 @@ class WallabagSession: ObservableObject { } } }, receiveValue: { token in - guard let token = token else { self.state = .unknown; return } + guard let token else { self.state = .unknown; return } WallabagUserDefaults.refreshToken = token.refreshToken WallabagUserDefaults.accessToken = token.accessToken self.kit.accessToken = token.accessToken @@ -51,7 +53,7 @@ class WallabagSession: ObservableObject { kit.send(to: WallabagEntryEndpoint.add(url: url)) .catch { _ in Empty() } .sink { [unowned self] (wallabagEntry: WallabagEntry) in - let entry = Entry(context: self.coreDataContext) + let entry = Entry(context: coreDataContext) entry.hydrate(from: wallabagEntry) completion() } diff --git a/iOS/PropertyWrapper/BundleKey.swift b/App/PropertyWrapper/BundleKey.swift similarity index 100% rename from iOS/PropertyWrapper/BundleKey.swift rename to App/PropertyWrapper/BundleKey.swift diff --git a/Shared/PropertyWrapper/CoreDataViewContext.swift b/App/PropertyWrapper/CoreDataViewContext.swift similarity index 57% rename from Shared/PropertyWrapper/CoreDataViewContext.swift rename to App/PropertyWrapper/CoreDataViewContext.swift index e8c03ba..d52110a 100644 --- a/Shared/PropertyWrapper/CoreDataViewContext.swift +++ b/App/PropertyWrapper/CoreDataViewContext.swift @@ -1,9 +1,12 @@ import CoreData +import Factory import Foundation @propertyWrapper struct CoreDataViewContext { + @Injected(\Container.coreData) private var coreData + var wrappedValue: NSManagedObjectContext { - CoreData.shared.viewContext + coreData.viewContext } } diff --git a/App/WallabagApp.swift b/App/WallabagApp.swift new file mode 100644 index 0000000..e046f21 --- /dev/null +++ b/App/WallabagApp.swift @@ -0,0 +1,90 @@ +import Factory +import Foundation +import os +import SharedLib +import SwiftUI + +let logger = Logger(subsystem: "fr.district-web.wallabag", category: "main") + +@main +struct WallabagApp: App { + @Environment(\.scenePhase) var scenePhase + #if os(iOS) + @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate + #endif + + @Injected(\.appState) private var appState + @Injected(\.router) private var router + #if os(iOS) + @Injected(\.playerPublisher) private var playerPublisher + #endif + @Injected(\.errorHandler) private var errorHandler + @Injected(\.appSync) private var appSync + @Injected(\.coreDataSync) private var coreDataSync + @Injected(\.appSetting) private var appSetting + @Injected(\.coreData) private var coreData + + var body: some Scene { + WindowGroup { + MainView() + .environmentObject(appState) + #if os(iOS) + .environmentObject(playerPublisher) + #endif + .environmentObject(router) + .environmentObject(errorHandler) + .environmentObject(appSync) + .environmentObject(appSetting) + .environment(\.managedObjectContext, coreData.viewContext) + }.onChange(of: scenePhase) { state in + if state == .active { + appState.initSession() + #if os(iOS) + requestNotificationAuthorization() + #endif + } + + if state == .background { + coreData.saveContext() + updateBadge() + } + } + .commands { + CommandGroup(after: .newItem) { + Button("Refresh entries") { + appSync.requestSync() + } + .keyboardShortcut("r", modifiers: .command) + } + } + } + + private func updateBadge() { + if !WallabagUserDefaults.badgeEnabled { + setBadgeNumber(0) + return + } + + do { + let fetchRequest = Entry.fetchRequestSorted() + fetchRequest.predicate = RetrieveMode(fromCase: WallabagUserDefaults.defaultMode).predicate() + let entries = try coreData.viewContext.fetch(fetchRequest) + setBadgeNumber(entries.count) + } catch { + fatalError(error.localizedDescription) + } + } + + private func setBadgeNumber(_ number: Int) { + #if os(iOS) + UIApplication.shared.applicationIconBadgeNumber = number + #endif + } + + #if os(iOS) + private func requestNotificationAuthorization() { + let center = UNUserNotificationCenter.current() + center.requestAuthorization(options: [.badge]) { _, _ in } + } + #endif +} diff --git a/iOS/ar.lproj/Localizable.strings b/App/ar.lproj/Localizable.strings similarity index 100% rename from iOS/ar.lproj/Localizable.strings rename to App/ar.lproj/Localizable.strings diff --git a/iOS/cs.lproj/Localizable.strings b/App/cs.lproj/Localizable.strings similarity index 100% rename from iOS/cs.lproj/Localizable.strings rename to App/cs.lproj/Localizable.strings diff --git a/iOS/da.lproj/Localizable.strings b/App/da.lproj/Localizable.strings similarity index 100% rename from iOS/da.lproj/Localizable.strings rename to App/da.lproj/Localizable.strings diff --git a/iOS/de.lproj/Localizable.strings b/App/de.lproj/Localizable.strings similarity index 100% rename from iOS/de.lproj/Localizable.strings rename to App/de.lproj/Localizable.strings diff --git a/iOS/en.lproj/Localizable.strings b/App/en.lproj/Localizable.strings similarity index 100% rename from iOS/en.lproj/Localizable.strings rename to App/en.lproj/Localizable.strings diff --git a/iOS/es.lproj/Localizable.strings b/App/es.lproj/Localizable.strings similarity index 100% rename from iOS/es.lproj/Localizable.strings rename to App/es.lproj/Localizable.strings diff --git a/iOS/fa.lproj/Localizable.strings b/App/fa.lproj/Localizable.strings similarity index 100% rename from iOS/fa.lproj/Localizable.strings rename to App/fa.lproj/Localizable.strings diff --git a/iOS/fr.lproj/Localizable.strings b/App/fr.lproj/Localizable.strings similarity index 100% rename from iOS/fr.lproj/Localizable.strings rename to App/fr.lproj/Localizable.strings diff --git a/iOS/gl.lproj/Localizable.strings b/App/gl.lproj/Localizable.strings similarity index 100% rename from iOS/gl.lproj/Localizable.strings rename to App/gl.lproj/Localizable.strings diff --git a/iOS/hi.lproj/Localizable.strings b/App/hi.lproj/Localizable.strings similarity index 100% rename from iOS/hi.lproj/Localizable.strings rename to App/hi.lproj/Localizable.strings diff --git a/iOS/hr.lproj/Localizable.strings b/App/hr.lproj/Localizable.strings similarity index 100% rename from iOS/hr.lproj/Localizable.strings rename to App/hr.lproj/Localizable.strings diff --git a/iOS/html-ressources/article.html b/App/html-ressources/article.html similarity index 100% rename from iOS/html-ressources/article.html rename to App/html-ressources/article.html diff --git a/iOS/html-ressources/justify.css b/App/html-ressources/justify.css similarity index 100% rename from iOS/html-ressources/justify.css rename to App/html-ressources/justify.css diff --git a/iOS/html-ressources/main.css b/App/html-ressources/main.css similarity index 100% rename from iOS/html-ressources/main.css rename to App/html-ressources/main.css diff --git a/iOS/html-ressources/ratatouille.css b/App/html-ressources/ratatouille.css similarity index 100% rename from iOS/html-ressources/ratatouille.css rename to App/html-ressources/ratatouille.css diff --git a/iOS/hu.lproj/Localizable.strings b/App/hu.lproj/Localizable.strings similarity index 100% rename from iOS/hu.lproj/Localizable.strings rename to App/hu.lproj/Localizable.strings diff --git a/iOS/it.lproj/Localizable.strings b/App/it.lproj/Localizable.strings similarity index 100% rename from iOS/it.lproj/Localizable.strings rename to App/it.lproj/Localizable.strings diff --git a/iOS/ja.lproj/Localizable.strings b/App/ja.lproj/Localizable.strings similarity index 100% rename from iOS/ja.lproj/Localizable.strings rename to App/ja.lproj/Localizable.strings diff --git a/iOS/ko.lproj/Localizable.strings b/App/ko.lproj/Localizable.strings similarity index 100% rename from iOS/ko.lproj/Localizable.strings rename to App/ko.lproj/Localizable.strings diff --git a/iOS/nb-NO.lproj/Localizable.strings b/App/nb-NO.lproj/Localizable.strings similarity index 100% rename from iOS/nb-NO.lproj/Localizable.strings rename to App/nb-NO.lproj/Localizable.strings diff --git a/iOS/nl.lproj/Localizable.strings b/App/nl.lproj/Localizable.strings similarity index 100% rename from iOS/nl.lproj/Localizable.strings rename to App/nl.lproj/Localizable.strings diff --git a/iOS/oc.lproj/Localizable.strings b/App/oc.lproj/Localizable.strings similarity index 100% rename from iOS/oc.lproj/Localizable.strings rename to App/oc.lproj/Localizable.strings diff --git a/iOS/pl.lproj/Localizable.strings b/App/pl.lproj/Localizable.strings similarity index 100% rename from iOS/pl.lproj/Localizable.strings rename to App/pl.lproj/Localizable.strings diff --git a/iOS/pt.lproj/Localizable.strings b/App/pt.lproj/Localizable.strings similarity index 100% rename from iOS/pt.lproj/Localizable.strings rename to App/pt.lproj/Localizable.strings diff --git a/iOS/ro.lproj/Localizable.strings b/App/ro.lproj/Localizable.strings similarity index 100% rename from iOS/ro.lproj/Localizable.strings rename to App/ro.lproj/Localizable.strings diff --git a/iOS/ru.lproj/Localizable.strings b/App/ru.lproj/Localizable.strings similarity index 100% rename from iOS/ru.lproj/Localizable.strings rename to App/ru.lproj/Localizable.strings diff --git a/iOS/sv.lproj/Localizable.strings b/App/sv.lproj/Localizable.strings similarity index 100% rename from iOS/sv.lproj/Localizable.strings rename to App/sv.lproj/Localizable.strings diff --git a/iOS/th.lproj/Localizable.strings b/App/th.lproj/Localizable.strings similarity index 100% rename from iOS/th.lproj/Localizable.strings rename to App/th.lproj/Localizable.strings diff --git a/iOS/tr.lproj/Localizable.strings b/App/tr.lproj/Localizable.strings similarity index 100% rename from iOS/tr.lproj/Localizable.strings rename to App/tr.lproj/Localizable.strings diff --git a/iOS/uk.lproj/Localizable.strings b/App/uk.lproj/Localizable.strings similarity index 100% rename from iOS/uk.lproj/Localizable.strings rename to App/uk.lproj/Localizable.strings diff --git a/Shared/wallabag.xcdatamodeld/.xccurrentversion b/App/wallabag.xcdatamodeld/.xccurrentversion similarity index 66% rename from Shared/wallabag.xcdatamodeld/.xccurrentversion rename to App/wallabag.xcdatamodeld/.xccurrentversion index 775cb51..0c67376 100644 --- a/Shared/wallabag.xcdatamodeld/.xccurrentversion +++ b/App/wallabag.xcdatamodeld/.xccurrentversion @@ -1,8 +1,5 @@ - - _XCCurrentVersionName - Shared.xcdatamodel - + diff --git a/Shared/wallabag.xcdatamodeld/Shared.xcdatamodel/contents b/App/wallabag.xcdatamodeld/Shared.xcdatamodel/contents similarity index 53% rename from Shared/wallabag.xcdatamodeld/Shared.xcdatamodel/contents rename to App/wallabag.xcdatamodeld/Shared.xcdatamodel/contents index 9ed2921..0d4feb9 100644 --- a/Shared/wallabag.xcdatamodeld/Shared.xcdatamodel/contents +++ b/App/wallabag.xcdatamodeld/Shared.xcdatamodel/contents @@ -1,9 +1,6 @@ - + - - - \ No newline at end of file diff --git a/iOS/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents b/App/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents similarity index 100% rename from iOS/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents rename to App/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents diff --git a/iOS/zh-Hans.lproj/Localizable.strings b/App/zh-Hans.lproj/Localizable.strings similarity index 100% rename from iOS/zh-Hans.lproj/Localizable.strings rename to App/zh-Hans.lproj/Localizable.strings diff --git a/iOS/zh-Hant.lproj/Localizable.strings b/App/zh-Hant.lproj/Localizable.strings similarity index 100% rename from iOS/zh-Hant.lproj/Localizable.strings rename to App/zh-Hant.lproj/Localizable.strings diff --git a/Gemfile.lock b/Gemfile.lock index e21c026..ce41060 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,27 +1,27 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.5) + CFPropertyList (3.0.6) rexml - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.607.0) - aws-sdk-core (3.131.2) + aws-partitions (1.719.0) + aws-sdk-core (3.170.0) aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.525.0) - aws-sigv4 (~> 1.1) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.57.0) - aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-kms (1.63.0) + aws-sdk-core (~> 3, >= 3.165.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.114.0) - aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-s3 (1.119.1) + aws-sdk-core (~> 3, >= 3.165.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) - aws-sigv4 (1.5.0) + aws-sigv4 (1.5.2) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) claide (1.1.0) @@ -34,10 +34,10 @@ GEM rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.6) + dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.92.3) - faraday (1.10.0) + excon (0.99.0) + faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -66,7 +66,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.207.0) + fastlane (2.212.1) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -106,9 +106,9 @@ GEM xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.25.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-core (0.7.0) + google-apis-androidpublisher_v3 (0.34.0) + google-apis-core (>= 0.9.1, < 2.a) + google-apis-core (0.11.0) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -117,27 +117,27 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-iamcredentials_v1 (0.13.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-playcustomapp_v1 (0.10.0) - google-apis-core (>= 0.7, < 2.a) - google-apis-storage_v1 (0.18.0) - google-apis-core (>= 0.7, < 2.a) + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.2.0) - google-cloud-storage (1.37.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.2.0) + googleauth (1.3.0) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -148,11 +148,11 @@ GEM http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) - jmespath (1.6.1) - json (2.6.2) - jwt (2.4.1) + jmespath (1.6.2) + json (2.6.3) + jwt (2.7.0) memoist (0.16.2) - mini_magick (4.11.0) + mini_magick (4.12.0) mini_mime (1.1.2) multi_json (1.15.0) multipart-post (2.0.0) @@ -160,8 +160,8 @@ GEM naturally (2.2.1) optparse (0.1.1) os (1.1.4) - plist (3.6.0) - public_suffix (4.0.7) + plist (3.7.0) + public_suffix (5.0.1) rake (13.0.6) representable (3.2.0) declarative (< 0.1.0) @@ -178,7 +178,7 @@ GEM faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - simctl (1.6.8) + simctl (1.6.10) CFPropertyList naturally terminal-notifier (2.0.0) @@ -194,7 +194,7 @@ GEM unf_ext unf_ext (0.0.8.2) unicode-display_width (1.8.0) - webrick (1.7.0) + webrick (1.8.1) word_wrap (1.0.0) xcodeproj (1.22.0) CFPropertyList (>= 2.3.3, < 4.0) @@ -209,8 +209,7 @@ GEM xcpretty (~> 0.2, >= 0.0.7) PLATFORMS - universal-darwin-20 - universal-darwin-21 + universal-darwin-22 DEPENDENCIES fastlane diff --git a/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/Shared/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb87897..0000000 --- a/Shared/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json b/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 39167fb..0000000 --- a/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "images" : [ - { - "filename" : "Icon-Notification@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "Icon-Notification@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "Icon-Small@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "Icon-Small@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "Icon-Small-40@2x-1.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "Icon-Small-40@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "Icon-60@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "Icon-60@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "Icon-Notification.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "Icon-Notification@2x-1.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "Icon-Small.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "Icon-Small@2x-1.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "Icon-Small-40.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "Icon-Small-40@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "Icon-76.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "Icon-76@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "Icon-83.5@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "logo-icon-bg-white.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "16x16" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "16x16" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "32x32" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "32x32" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "128x128" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "128x128" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "256x256" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "256x256" - }, - { - "idiom" : "mac", - "scale" : "1x", - "size" : "512x512" - }, - { - "idiom" : "mac", - "scale" : "2x", - "size" : "512x512" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png deleted file mode 100644 index 2fffe34..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png deleted file mode 100644 index 19dcc58..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-76.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-76.png deleted file mode 100644 index 7d8ca8b..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-76.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png deleted file mode 100644 index 1660dc8..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png deleted file mode 100644 index 517aea3..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification.png deleted file mode 100644 index a264831..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x-1.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x-1.png deleted file mode 100644 index 0d2a131..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x-1.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x.png deleted file mode 100644 index 0d2a131..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@3x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@3x.png deleted file mode 100644 index e817b4c..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Notification@3x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png deleted file mode 100644 index 0d2a131..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png deleted file mode 100644 index e9f6e7d..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png deleted file mode 100644 index e9f6e7d..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png deleted file mode 100644 index 2fffe34..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small.png deleted file mode 100644 index 47aced1..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png deleted file mode 100644 index d54945b..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png deleted file mode 100644 index d54945b..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png deleted file mode 100644 index 94317ce..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png and /dev/null differ diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white.png b/Shared/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white.png deleted file mode 100644 index 5f03e3e..0000000 Binary files a/Shared/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white.png and /dev/null differ diff --git a/Shared/Assets.xcassets/logo.imageset/Contents.json b/Shared/Assets.xcassets/logo.imageset/Contents.json deleted file mode 100644 index 8a5a44b..0000000 --- a/Shared/Assets.xcassets/logo.imageset/Contents.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "images" : [ - { - "filename" : "logo-icon-black-no-bg-lg.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "logo-icon-white-no-bg-lg.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Shared/Features/Router/RouterView.swift b/Shared/Features/Router/RouterView.swift deleted file mode 100644 index ec77b2c..0000000 --- a/Shared/Features/Router/RouterView.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation -import SwiftUI - -struct RouterView: View { - @EnvironmentObject var router: Router - - var body: some View { - router.route.view - } -} diff --git a/Shared/PropertyWrapper/Injector.swift b/Shared/PropertyWrapper/Injector.swift deleted file mode 100644 index 1aa8ace..0000000 --- a/Shared/PropertyWrapper/Injector.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Swinject - -@propertyWrapper -struct Injector { - var service: Service? - var container: Resolver? - - var wrappedValue: Service { - mutating get { - if service == nil { - service = DependencyInjection.container.resolve(Service.self) - } - - return service! - } - } -} diff --git a/SharedLib/Package.swift b/SharedLib/Package.swift index c56e65e..05d6046 100644 --- a/SharedLib/Package.swift +++ b/SharedLib/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.7 import PackageDescription diff --git a/SharedLib/SharedLib.xcodeproj/SharedLibTests_Info.plist b/SharedLib/SharedLib.xcodeproj/SharedLibTests_Info.plist deleted file mode 100644 index 7c23420..0000000 --- a/SharedLib/SharedLib.xcodeproj/SharedLibTests_Info.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/SharedLib/SharedLib.xcodeproj/SharedLib_Info.plist b/SharedLib/SharedLib.xcodeproj/SharedLib_Info.plist deleted file mode 100644 index 57ada9f..0000000 --- a/SharedLib/SharedLib.xcodeproj/SharedLib_Info.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/SharedLib/SharedLib.xcodeproj/project.pbxproj b/SharedLib/SharedLib.xcodeproj/project.pbxproj deleted file mode 100644 index 1ab793a..0000000 --- a/SharedLib/SharedLib.xcodeproj/project.pbxproj +++ /dev/null @@ -1,667 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - "SharedLib::SharedLibPackageTests::ProductTarget" /* SharedLibPackageTests */ = { - isa = PBXAggregateTarget; - buildConfigurationList = OBJ_63 /* Build configuration list for PBXAggregateTarget "SharedLibPackageTests" */; - buildPhases = ( - ); - dependencies = ( - OBJ_66 /* PBXTargetDependency */, - ); - name = SharedLibPackageTests; - productName = SharedLibPackageTests; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 091CB01A283BEC760077779D /* Double.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091CB019283BEC760077779D /* Double.swift */; }; - OBJ_44 /* Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* Bool.swift */; }; - OBJ_45 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* Bundle.swift */; }; - OBJ_46 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* Date.swift */; }; - OBJ_47 /* Int.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* Int.swift */; }; - OBJ_48 /* SKProduct.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* SKProduct.swift */; }; - OBJ_49 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* String.swift */; }; - OBJ_50 /* UISearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* UISearchBar.swift */; }; - OBJ_51 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* URL.swift */; }; - OBJ_52 /* WKWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* WKWebView.swift */; }; - OBJ_53 /* RetrieveMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* RetrieveMode.swift */; }; - OBJ_54 /* RetrieveModePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_22 /* RetrieveModePicker.swift */; }; - OBJ_61 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; - OBJ_72 /* BoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_26 /* BoolTests.swift */; }; - OBJ_73 /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_27 /* DateTests.swift */; }; - OBJ_74 /* IntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* IntTests.swift */; }; - OBJ_75 /* SharedLibTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_29 /* SharedLibTests.swift */; }; - OBJ_76 /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_30 /* StringTests.swift */; }; - OBJ_77 /* URLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_31 /* URLTests.swift */; }; - OBJ_78 /* RetrieveModeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_34 /* RetrieveModeTests.swift */; }; - OBJ_80 /* SharedLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "SharedLib::SharedLib::Product" /* SharedLib.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 0952BED527A88A63008EE6F2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = "SharedLib::SharedLib"; - remoteInfo = SharedLib; - }; - 0952BED627A88A63008EE6F2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = "SharedLib::SharedLibTests"; - remoteInfo = SharedLibTests; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 091CB019283BEC760077779D /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = ""; }; - OBJ_10 /* Bool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bool.swift; sourceTree = ""; }; - OBJ_11 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; - OBJ_12 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = ""; }; - OBJ_13 /* Int.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Int.swift; sourceTree = ""; }; - OBJ_14 /* SKProduct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SKProduct.swift; sourceTree = ""; }; - OBJ_15 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; - OBJ_16 /* UISearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UISearchBar.swift; sourceTree = ""; }; - OBJ_17 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = ""; }; - OBJ_18 /* WKWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKWebView.swift; sourceTree = ""; }; - OBJ_21 /* RetrieveMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetrieveMode.swift; sourceTree = ""; }; - OBJ_22 /* RetrieveModePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetrieveModePicker.swift; sourceTree = ""; }; - OBJ_26 /* BoolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoolTests.swift; sourceTree = ""; }; - OBJ_27 /* DateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTests.swift; sourceTree = ""; }; - OBJ_28 /* IntTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntTests.swift; sourceTree = ""; }; - OBJ_29 /* SharedLibTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedLibTests.swift; sourceTree = ""; }; - OBJ_30 /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = ""; }; - OBJ_31 /* URLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLTests.swift; sourceTree = ""; }; - OBJ_34 /* RetrieveModeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetrieveModeTests.swift; sourceTree = ""; }; - OBJ_38 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; - "SharedLib::SharedLib::Product" /* SharedLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SharedLib.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - "SharedLib::SharedLibTests::Product" /* SharedLibTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = SharedLibTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - OBJ_55 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_79 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 0; - files = ( - OBJ_80 /* SharedLib.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - OBJ_19 /* Features */ = { - isa = PBXGroup; - children = ( - OBJ_20 /* RetrieveMode */, - ); - path = Features; - sourceTree = ""; - }; - OBJ_20 /* RetrieveMode */ = { - isa = PBXGroup; - children = ( - OBJ_21 /* RetrieveMode.swift */, - OBJ_22 /* RetrieveModePicker.swift */, - ); - path = RetrieveMode; - sourceTree = ""; - }; - OBJ_23 /* Tests */ = { - isa = PBXGroup; - children = ( - OBJ_24 /* SharedLibTests */, - ); - name = Tests; - sourceTree = SOURCE_ROOT; - }; - OBJ_24 /* SharedLibTests */ = { - isa = PBXGroup; - children = ( - OBJ_25 /* Extension */, - OBJ_32 /* Features */, - ); - name = SharedLibTests; - path = Tests/SharedLibTests; - sourceTree = SOURCE_ROOT; - }; - OBJ_25 /* Extension */ = { - isa = PBXGroup; - children = ( - OBJ_26 /* BoolTests.swift */, - OBJ_27 /* DateTests.swift */, - OBJ_28 /* IntTests.swift */, - OBJ_29 /* SharedLibTests.swift */, - OBJ_30 /* StringTests.swift */, - OBJ_31 /* URLTests.swift */, - ); - path = Extension; - sourceTree = ""; - }; - OBJ_32 /* Features */ = { - isa = PBXGroup; - children = ( - OBJ_33 /* RetrieveMode */, - ); - path = Features; - sourceTree = ""; - }; - OBJ_33 /* RetrieveMode */ = { - isa = PBXGroup; - children = ( - OBJ_34 /* RetrieveModeTests.swift */, - ); - path = RetrieveMode; - sourceTree = ""; - }; - OBJ_35 /* Products */ = { - isa = PBXGroup; - children = ( - "SharedLib::SharedLib::Product" /* SharedLib.framework */, - "SharedLib::SharedLibTests::Product" /* SharedLibTests.xctest */, - ); - name = Products; - sourceTree = BUILT_PRODUCTS_DIR; - }; - OBJ_5 = { - isa = PBXGroup; - children = ( - OBJ_6 /* Package.swift */, - OBJ_7 /* Sources */, - OBJ_23 /* Tests */, - OBJ_35 /* Products */, - OBJ_38 /* README.md */, - ); - sourceTree = ""; - }; - OBJ_7 /* Sources */ = { - isa = PBXGroup; - children = ( - OBJ_8 /* SharedLib */, - ); - name = Sources; - sourceTree = SOURCE_ROOT; - }; - OBJ_8 /* SharedLib */ = { - isa = PBXGroup; - children = ( - OBJ_9 /* Extension */, - OBJ_19 /* Features */, - ); - name = SharedLib; - path = Sources/SharedLib; - sourceTree = SOURCE_ROOT; - }; - OBJ_9 /* Extension */ = { - isa = PBXGroup; - children = ( - OBJ_10 /* Bool.swift */, - OBJ_11 /* Bundle.swift */, - OBJ_12 /* Date.swift */, - OBJ_13 /* Int.swift */, - OBJ_14 /* SKProduct.swift */, - OBJ_15 /* String.swift */, - OBJ_16 /* UISearchBar.swift */, - OBJ_17 /* URL.swift */, - OBJ_18 /* WKWebView.swift */, - 091CB019283BEC760077779D /* Double.swift */, - ); - path = Extension; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - "SharedLib::SharedLib" /* SharedLib */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_40 /* Build configuration list for PBXNativeTarget "SharedLib" */; - buildPhases = ( - OBJ_43 /* Sources */, - OBJ_55 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SharedLib; - productName = SharedLib; - productReference = "SharedLib::SharedLib::Product" /* SharedLib.framework */; - productType = "com.apple.product-type.framework"; - }; - "SharedLib::SharedLibTests" /* SharedLibTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_68 /* Build configuration list for PBXNativeTarget "SharedLibTests" */; - buildPhases = ( - OBJ_71 /* Sources */, - OBJ_79 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - OBJ_81 /* PBXTargetDependency */, - ); - name = SharedLibTests; - productName = SharedLibTests; - productReference = "SharedLib::SharedLibTests::Product" /* SharedLibTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - "SharedLib::SwiftPMPackageDescription" /* SharedLibPackageDescription */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_57 /* Build configuration list for PBXNativeTarget "SharedLibPackageDescription" */; - buildPhases = ( - OBJ_60 /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SharedLibPackageDescription; - productName = SharedLibPackageDescription; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - OBJ_1 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftMigration = 9999; - LastUpgradeCheck = 1320; - }; - buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "SharedLib" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = OBJ_5; - productRefGroup = OBJ_35 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - "SharedLib::SharedLib" /* SharedLib */, - "SharedLib::SwiftPMPackageDescription" /* SharedLibPackageDescription */, - "SharedLib::SharedLibPackageTests::ProductTarget" /* SharedLibPackageTests */, - "SharedLib::SharedLibTests" /* SharedLibTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - OBJ_43 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_44 /* Bool.swift in Sources */, - OBJ_45 /* Bundle.swift in Sources */, - OBJ_46 /* Date.swift in Sources */, - OBJ_47 /* Int.swift in Sources */, - OBJ_48 /* SKProduct.swift in Sources */, - OBJ_49 /* String.swift in Sources */, - OBJ_50 /* UISearchBar.swift in Sources */, - OBJ_51 /* URL.swift in Sources */, - OBJ_52 /* WKWebView.swift in Sources */, - OBJ_53 /* RetrieveMode.swift in Sources */, - 091CB01A283BEC760077779D /* Double.swift in Sources */, - OBJ_54 /* RetrieveModePicker.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_60 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_61 /* Package.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_71 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_72 /* BoolTests.swift in Sources */, - OBJ_73 /* DateTests.swift in Sources */, - OBJ_74 /* IntTests.swift in Sources */, - OBJ_75 /* SharedLibTests.swift in Sources */, - OBJ_76 /* StringTests.swift in Sources */, - OBJ_77 /* URLTests.swift in Sources */, - OBJ_78 /* RetrieveModeTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - OBJ_66 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = "SharedLib::SharedLibTests" /* SharedLibTests */; - targetProxy = 0952BED627A88A63008EE6F2 /* PBXContainerItemProxy */; - }; - OBJ_81 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = "SharedLib::SharedLib" /* SharedLib */; - targetProxy = 0952BED527A88A63008EE6F2 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - OBJ_3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "SWIFT_PACKAGE=1", - "DEBUG=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - ONLY_ACTIVE_ARCH = YES; - OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "$(AVAILABLE_PLATFORMS)"; - SUPPORTS_MACCATALYST = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE DEBUG"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - USE_HEADERMAP = NO; - }; - name = Debug; - }; - OBJ_4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = s; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "SWIFT_PACKAGE=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "$(AVAILABLE_PLATFORMS)"; - SUPPORTS_MACCATALYST = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE"; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - USE_HEADERMAP = NO; - }; - name = Release; - }; - OBJ_41 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = SharedLib.xcodeproj/SharedLib_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = SharedLib; - PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = SharedLib; - TVOS_DEPLOYMENT_TARGET = 12.0; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Debug; - }; - OBJ_42 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = SharedLib.xcodeproj/SharedLib_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = SharedLib; - PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = SharedLib; - TVOS_DEPLOYMENT_TARGET = 12.0; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Release; - }; - OBJ_58 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - LD = /usr/bin/true; - OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/ManifestAPI -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -package-description-version 5.5.0"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - OBJ_59 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - LD = /usr/bin/true; - OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/ManifestAPI -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -package-description-version 5.5.0"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - OBJ_64 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = Debug; - }; - OBJ_65 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = Release; - }; - OBJ_69 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = SharedLib.xcodeproj/SharedLibTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = SharedLibTests; - TVOS_DEPLOYMENT_TARGET = 14.0; - WATCHOS_DEPLOYMENT_TARGET = 7.0; - }; - name = Debug; - }; - OBJ_70 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = SharedLib.xcodeproj/SharedLibTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = SharedLibTests; - TVOS_DEPLOYMENT_TARGET = 14.0; - WATCHOS_DEPLOYMENT_TARGET = 7.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - OBJ_2 /* Build configuration list for PBXProject "SharedLib" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_3 /* Debug */, - OBJ_4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_40 /* Build configuration list for PBXNativeTarget "SharedLib" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_41 /* Debug */, - OBJ_42 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_57 /* Build configuration list for PBXNativeTarget "SharedLibPackageDescription" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_58 /* Debug */, - OBJ_59 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_63 /* Build configuration list for PBXAggregateTarget "SharedLibPackageTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_64 /* Debug */, - OBJ_65 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_68 /* Build configuration list for PBXNativeTarget "SharedLibTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_69 /* Debug */, - OBJ_70 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = OBJ_1 /* Project object */; -} diff --git a/SharedLib/SharedLib.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SharedLib/SharedLib.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index fe1aa71..0000000 --- a/SharedLib/SharedLib.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/SharedLib/SharedLib.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/SharedLib/SharedLib.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index a72dc2b..0000000 --- a/SharedLib/SharedLib.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded - - - \ No newline at end of file diff --git a/SharedLib/SharedLib.xcodeproj/xcshareddata/xcschemes/SharedLib-Package.xcscheme b/SharedLib/SharedLib.xcodeproj/xcshareddata/xcschemes/SharedLib-Package.xcscheme deleted file mode 100644 index 08fdef9..0000000 --- a/SharedLib/SharedLib.xcodeproj/xcshareddata/xcschemes/SharedLib-Package.xcscheme +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SharedLib/SharedLib.xcodeproj/xcuserdata/maxime.xcuserdatad/xcschemes/xcschememanagement.plist b/SharedLib/SharedLib.xcodeproj/xcuserdata/maxime.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index feb8daf..0000000 --- a/SharedLib/SharedLib.xcodeproj/xcuserdata/maxime.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - SchemeUserState - - SharedLib-Package.xcscheme_^#shared#^_ - - orderHint - 5 - - SharedLibPackageDescription.xcscheme_^#shared#^_ - - orderHint - 11 - - SharedLibPackageTests.xcscheme_^#shared#^_ - - orderHint - 6 - - - - diff --git a/SharedLib/Sources/SharedLib/Extension/String.swift b/SharedLib/Sources/SharedLib/Extension/String.swift index a9573e9..72ac122 100644 --- a/SharedLib/Sources/SharedLib/Extension/String.swift +++ b/SharedLib/Sources/SharedLib/Extension/String.swift @@ -37,7 +37,6 @@ public extension String { URL(string: self) } - @available(iOS 13.0, macOS 10.15, *) var md5: String { Insecure.MD5.hash(data: data(using: .utf8)!).map { String(format: "%02hhx", $0) diff --git a/SharedLib/Sources/SharedLib/Extension/WKWebView.swift b/SharedLib/Sources/SharedLib/Extension/WKWebView.swift index da60b6b..9dfef42 100644 --- a/SharedLib/Sources/SharedLib/Extension/WKWebView.swift +++ b/SharedLib/Sources/SharedLib/Extension/WKWebView.swift @@ -1,5 +1,4 @@ import Foundation -// import UIKit import WebKit public extension WKWebView { @@ -12,7 +11,7 @@ public extension WKWebView { func contentForWebView(_ content: String?, justify: Bool) -> String? { do { - guard let content = content else { return nil } + guard let content else { return nil } let html = try String(contentsOfFile: Bundle.main.path(forResource: "article", ofType: "html")!) let justify = justify ? "justify.css" : "" diff --git a/SharedLib/Sources/SharedLib/Features/RetrieveMode/RetrieveModePicker.swift b/SharedLib/Sources/SharedLib/Features/RetrieveMode/RetrieveModePicker.swift index 02e5d5e..395d086 100644 --- a/SharedLib/Sources/SharedLib/Features/RetrieveMode/RetrieveModePicker.swift +++ b/SharedLib/Sources/SharedLib/Features/RetrieveMode/RetrieveModePicker.swift @@ -1,6 +1,5 @@ import SwiftUI -@available(iOS 13.0, macOS 10.15, *) public struct RetrieveModePicker: View { @Binding var filter: RetrieveMode @@ -14,11 +13,12 @@ public struct RetrieveModePicker: View { Text(LocalizedStringKey(RetrieveMode.starredArticles.rawValue)).tag(RetrieveMode.starredArticles) Text(LocalizedStringKey(RetrieveMode.unarchivedArticles.rawValue)).tag(RetrieveMode.unarchivedArticles) Text(LocalizedStringKey(RetrieveMode.archivedArticles.rawValue)).tag(RetrieveMode.archivedArticles) - }).pickerStyle(SegmentedPickerStyle()) + }) + .pickerStyle(.segmented) + .labelsHidden() } } -@available(iOS 13.0, macOS 10.15, *) struct RetrieveModePicker_Previews: PreviewProvider { static var previews: some View { RetrieveModePicker(filter: .constant(.archivedArticles)).previewLayout(.fixed(width: 300, height: 70)) diff --git a/Shared/Lib/KeychainPasswordItem.swift b/SharedLib/Sources/SharedLib/Lib/KeychainPasswordItem.swift similarity index 98% rename from Shared/Lib/KeychainPasswordItem.swift rename to SharedLib/Sources/SharedLib/Lib/KeychainPasswordItem.swift index c90ddd2..9647f78 100644 --- a/Shared/Lib/KeychainPasswordItem.swift +++ b/SharedLib/Sources/SharedLib/Lib/KeychainPasswordItem.swift @@ -125,11 +125,11 @@ public struct KeychainPasswordItem { query[kSecClass as String] = kSecClassGenericPassword query[kSecAttrService as String] = service as AnyObject? - if let account = account { + if let account { query[kSecAttrAccount as String] = account as AnyObject? } - if let accessGroup = accessGroup { + if let accessGroup { query[kSecAttrAccessGroup as String] = accessGroup as AnyObject? } diff --git a/Shared/Lib/WallabagUserDefaults.swift b/SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift similarity index 53% rename from Shared/Lib/WallabagUserDefaults.swift rename to SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift index 74f925c..5140d6b 100644 --- a/Shared/Lib/WallabagUserDefaults.swift +++ b/SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift @@ -1,51 +1,51 @@ import Foundation -struct WallabagUserDefaults { +public enum WallabagUserDefaults { @Setting("host", defaultValue: "") - static var host: String + public static var host: String @Setting("clientId", defaultValue: "") - static var clientId: String + public static var clientId: String @Setting("clientSecret", defaultValue: "") - static var clientSecret: String + public static var clientSecret: String @Setting("username", defaultValue: "") - static var login: String + public static var login: String @Password() - static var password: String + public static var password: String @Setting("registred", defaultValue: false) - static var registred: Bool + public static var registred: Bool @Setting("accessToken", defaultValue: nil) - static var accessToken: String? + public static var accessToken: String? @Setting("refreshToken", defaultValue: nil) - static var refreshToken: String? + public static var refreshToken: String? @Setting("expiresIn", defaultValue: nil) - static var expiresIn: Int? + public static var expiresIn: Int? @Setting("previousPasteBoardUrl", defaultValue: "") - static var previousPasteBoardUrl: String + public static var previousPasteBoardUrl: String @GeneralSetting("justifyArticle", defaultValue: true) - static var justifyArticle: Bool + public static var justifyArticle: Bool @GeneralSetting("badge", defaultValue: true) - static var badgeEnabled: Bool + public static var badgeEnabled: Bool @GeneralSetting("defaultMode", defaultValue: "allArticles") - static var defaultMode: String + public static var defaultMode: String @Setting("webFontSizePercent", defaultValue: 100) - static var webFontSizePercent: Double + public static var webFontSizePercent: Double @GeneralSetting("showImageInList", defaultValue: true) - static var showImageInList: Bool + public static var showImageInList: Bool @GeneralSetting("itemPerPageDuringSync", defaultValue: 50) - static var itemPerPageDuringSync: Int + public static var itemPerPageDuringSync: Int } diff --git a/Shared/PropertyWrapper/GeneralSetting.swift b/SharedLib/Sources/SharedLib/PropertyWrapper/GeneralSetting.swift similarity index 74% rename from Shared/PropertyWrapper/GeneralSetting.swift rename to SharedLib/Sources/SharedLib/PropertyWrapper/GeneralSetting.swift index dc8574a..fb17730 100644 --- a/Shared/PropertyWrapper/GeneralSetting.swift +++ b/SharedLib/Sources/SharedLib/PropertyWrapper/GeneralSetting.swift @@ -1,16 +1,16 @@ import Foundation @propertyWrapper -struct GeneralSetting { +public struct GeneralSetting { let key: String let defaultValue: T - init(_ key: String, defaultValue: T) { + public init(_ key: String, defaultValue: T) { self.key = key self.defaultValue = defaultValue } - var wrappedValue: T { + public var wrappedValue: T { get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue } diff --git a/Shared/PropertyWrapper/Password.swift b/SharedLib/Sources/SharedLib/PropertyWrapper/Password.swift similarity index 79% rename from Shared/PropertyWrapper/Password.swift rename to SharedLib/Sources/SharedLib/PropertyWrapper/Password.swift index 282a85f..c22d278 100644 --- a/Shared/PropertyWrapper/Password.swift +++ b/SharedLib/Sources/SharedLib/PropertyWrapper/Password.swift @@ -1,15 +1,15 @@ import Foundation @propertyWrapper -struct Password { +public struct Password { private var keychain: KeychainPasswordItem - var wrappedValue: String { + public init() { + keychain = KeychainPasswordItem(service: "wallabag", account: "main", accessGroup: "group.wallabag.share_extension") + } + + public var wrappedValue: String { get { (try? keychain.readPassword()) ?? "" } set { try? keychain.savePassword(newValue) } } - - init() { - keychain = KeychainPasswordItem(service: "wallabag", account: "main", accessGroup: "group.wallabag.share_extension") - } } diff --git a/Shared/PropertyWrapper/Setting.swift b/SharedLib/Sources/SharedLib/PropertyWrapper/Setting.swift similarity index 88% rename from Shared/PropertyWrapper/Setting.swift rename to SharedLib/Sources/SharedLib/PropertyWrapper/Setting.swift index 0be7c3b..72d05b2 100644 --- a/Shared/PropertyWrapper/Setting.swift +++ b/SharedLib/Sources/SharedLib/PropertyWrapper/Setting.swift @@ -1,7 +1,7 @@ import Foundation @propertyWrapper -struct Setting { +public struct Setting { let key: String let defaultValue: T let userDefaults = UserDefaults(suiteName: "group.wallabag.share_extension")! @@ -11,7 +11,7 @@ struct Setting { self.defaultValue = defaultValue } - var wrappedValue: T { + public var wrappedValue: T { get { userDefaults.object(forKey: key) as? T ?? defaultValue } diff --git a/Shortcuts/AddEntryIntentHandler.swift b/Shortcuts/AddEntryIntentHandler.swift index 055e06f..980cb66 100644 --- a/Shortcuts/AddEntryIntentHandler.swift +++ b/Shortcuts/AddEntryIntentHandler.swift @@ -1,6 +1,7 @@ import Combine import Foundation import Intents +import SharedLib import WallabagKit class AddEntryIntentHandler: NSObject, AddEntryIntentHandling { diff --git a/Shortcuts/Info.plist b/Shortcuts/Info.plist index e3acbc2..2b172f2 100644 --- a/Shortcuts/Info.plist +++ b/Shortcuts/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.2.1 + 7.0.0 CFBundleVersion 319 NSExtension diff --git a/Tests iOS/Info.plist b/Tests iOS/Info.plist index a71e404..8b13789 100644 --- a/Tests iOS/Info.plist +++ b/Tests iOS/Info.plist @@ -1,22 +1 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 6.2.1 - CFBundleVersion - 319 - - + diff --git a/Tests iOS/Tests_iOS.swift b/Tests iOS/Tests_iOS.swift deleted file mode 100644 index b432921..0000000 --- a/Tests iOS/Tests_iOS.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Tests_iOS.swift -// Tests iOS -// -// Created by maxime marinel on 01/02/2021. -// - -import XCTest - -class TestsIOS: XCTestCase { - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() - - // Use recording to get started writing UI tests. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func atestLaunchPerformance() throws { - if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } - } -} diff --git a/Tests macOS/Info.plist b/Tests macOS/Info.plist index a71e404..8b13789 100644 --- a/Tests macOS/Info.plist +++ b/Tests macOS/Info.plist @@ -1,22 +1 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 6.2.1 - CFBundleVersion - 319 - - + diff --git a/Tests macOS/Tests_macOS.swift b/Tests macOS/Tests_macOS.swift deleted file mode 100644 index 8942d5e..0000000 --- a/Tests macOS/Tests_macOS.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Tests_macOS.swift -// Tests macOS -// -// Created by maxime marinel on 01/02/2021. -// - -import XCTest - -class TestsMacOS: XCTestCase { - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false - - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() - - // Use recording to get started writing UI tests. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testLaunchPerformance() throws { - if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } - } -} diff --git a/WallabagKit/Package.swift b/WallabagKit/Package.swift index 3aa983f..dc669a2 100644 --- a/WallabagKit/Package.swift +++ b/WallabagKit/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.7 import PackageDescription diff --git a/WallabagKit/Sources/WallabagKit/Endpoint/WallabagEntryEndpoint.swift b/WallabagKit/Sources/WallabagKit/Endpoint/WallabagEntryEndpoint.swift index 54a46ab..9d95d0b 100644 --- a/WallabagKit/Sources/WallabagKit/Endpoint/WallabagEntryEndpoint.swift +++ b/WallabagKit/Sources/WallabagKit/Endpoint/WallabagEntryEndpoint.swift @@ -50,14 +50,16 @@ public enum WallabagEntryEndpoint: WallabagKitEndpoint { } } - // swiftlint:disable force_try public func getBody() -> Data { switch self { case let .add(url): + // swiftlint:disable:next force_try return try! JSONSerialization.data(withJSONObject: ["url": url], options: .prettyPrinted) case let .update(_, parameters): + // swiftlint:disable:next force_try return try! JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted) case let .addTag(tag, _): + // swiftlint:disable:next force_try return try! JSONSerialization.data(withJSONObject: ["tags": tag], options: .prettyPrinted) default: return "".data(using: .utf8)! diff --git a/WallabagKit/Sources/WallabagKit/Endpoint/WallabagOAuth.swift b/WallabagKit/Sources/WallabagKit/Endpoint/WallabagOAuth.swift index 549c148..05fd694 100644 --- a/WallabagKit/Sources/WallabagKit/Endpoint/WallabagOAuth.swift +++ b/WallabagKit/Sources/WallabagKit/Endpoint/WallabagOAuth.swift @@ -12,10 +12,10 @@ enum WallabagOauth: WallabagKitEndpoint { } } - // swiftlint:disable force_try func getBody() -> Data { switch self { case let .request(clientId, clientSecret, username, password): + // swiftlint:disable:next force_try return try! JSONSerialization.data(withJSONObject: [ "grant_type": "password", "client_id": clientId, diff --git a/WallabagKit/Tests/WallabagKitTests/WallabagKitTests.swift b/WallabagKit/Tests/WallabagKitTests/WallabagKitTests.swift index d9a4ca6..2987dba 100644 --- a/WallabagKit/Tests/WallabagKitTests/WallabagKitTests.swift +++ b/WallabagKit/Tests/WallabagKitTests/WallabagKitTests.swift @@ -1,11 +1,4 @@ @testable import WallabagKit import XCTest -final class WallabagKitTests: XCTestCase { - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - XCTAssertEqual(WallabagKit().text, "Hello, World!") - } -} +final class WallabagKitTests: XCTestCase {} diff --git a/WallabagKit/WallabagKit.xcodeproj/WallabagKitTests_Info.plist b/WallabagKit/WallabagKit.xcodeproj/WallabagKitTests_Info.plist deleted file mode 100644 index 7c23420..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/WallabagKitTests_Info.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/WallabagKit/WallabagKit.xcodeproj/WallabagKit_Info.plist b/WallabagKit/WallabagKit.xcodeproj/WallabagKit_Info.plist deleted file mode 100644 index 57ada9f..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/WallabagKit_Info.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - diff --git a/WallabagKit/WallabagKit.xcodeproj/project.pbxproj b/WallabagKit/WallabagKit.xcodeproj/project.pbxproj deleted file mode 100644 index 2c16e72..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/project.pbxproj +++ /dev/null @@ -1,639 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - "WallabagKit::WallabagKitPackageTests::ProductTarget" /* WallabagKitPackageTests */ = { - isa = PBXAggregateTarget; - buildConfigurationList = OBJ_59 /* Build configuration list for PBXAggregateTarget "WallabagKitPackageTests" */; - buildPhases = ( - ); - dependencies = ( - OBJ_62 /* PBXTargetDependency */, - ); - name = WallabagKitPackageTests; - productName = WallabagKitPackageTests; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 09A5DDCF283BA1E400494B1E /* WallabagConfigEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A5DDCE283BA1E400494B1E /* WallabagConfigEndpoint.swift */; }; - 09A5DDD1283BA23F00494B1E /* WallabagConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A5DDD0283BA23F00494B1E /* WallabagConfig.swift */; }; - OBJ_38 /* WallabagEntryEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* WallabagEntryEndpoint.swift */; }; - OBJ_39 /* WallabagKitEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* WallabagKitEndpoint.swift */; }; - OBJ_40 /* WallabagOAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* WallabagOAuth.swift */; }; - OBJ_41 /* WallabagTagEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* WallabagTagEndpoint.swift */; }; - OBJ_42 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* Publisher.swift */; }; - OBJ_43 /* HttpMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* HttpMethod.swift */; }; - OBJ_44 /* WallabagCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* WallabagCollection.swift */; }; - OBJ_45 /* WallabagEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* WallabagEntry.swift */; }; - OBJ_46 /* WallabagTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* WallabagTag.swift */; }; - OBJ_47 /* WallabagToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* WallabagToken.swift */; }; - OBJ_48 /* EntriesFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_23 /* EntriesFetcher.swift */; }; - OBJ_49 /* WallabagKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_24 /* WallabagKit.swift */; }; - OBJ_50 /* WallabagKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_25 /* WallabagKitError.swift */; }; - OBJ_57 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; - OBJ_68 /* WallabagKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* WallabagKitTests.swift */; }; - OBJ_70 /* WallabagKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "WallabagKit::WallabagKit::Product" /* WallabagKit.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 09918FC22731EB9F005F3CE7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = "WallabagKit::WallabagKit"; - remoteInfo = WallabagKit; - }; - 09918FC32731EB9F005F3CE7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = "WallabagKit::WallabagKitTests"; - remoteInfo = WallabagKitTests; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 09A5DDCE283BA1E400494B1E /* WallabagConfigEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagConfigEndpoint.swift; sourceTree = ""; }; - 09A5DDD0283BA23F00494B1E /* WallabagConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagConfig.swift; sourceTree = ""; }; - OBJ_10 /* WallabagEntryEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagEntryEndpoint.swift; sourceTree = ""; }; - OBJ_11 /* WallabagKitEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagKitEndpoint.swift; sourceTree = ""; }; - OBJ_12 /* WallabagOAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagOAuth.swift; sourceTree = ""; }; - OBJ_13 /* WallabagTagEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagTagEndpoint.swift; sourceTree = ""; }; - OBJ_15 /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = ""; }; - OBJ_16 /* HttpMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpMethod.swift; sourceTree = ""; }; - OBJ_18 /* WallabagCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagCollection.swift; sourceTree = ""; }; - OBJ_19 /* WallabagEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagEntry.swift; sourceTree = ""; }; - OBJ_20 /* WallabagTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagTag.swift; sourceTree = ""; }; - OBJ_21 /* WallabagToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagToken.swift; sourceTree = ""; }; - OBJ_23 /* EntriesFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntriesFetcher.swift; sourceTree = ""; }; - OBJ_24 /* WallabagKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagKit.swift; sourceTree = ""; }; - OBJ_25 /* WallabagKitError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagKitError.swift; sourceTree = ""; }; - OBJ_28 /* WallabagKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagKitTests.swift; sourceTree = ""; }; - OBJ_32 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; - "WallabagKit::WallabagKit::Product" /* WallabagKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = WallabagKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - "WallabagKit::WallabagKitTests::Product" /* WallabagKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = WallabagKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - OBJ_51 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_69 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 0; - files = ( - OBJ_70 /* WallabagKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - OBJ_14 /* Extension */ = { - isa = PBXGroup; - children = ( - OBJ_15 /* Publisher.swift */, - ); - path = Extension; - sourceTree = ""; - }; - OBJ_17 /* Model */ = { - isa = PBXGroup; - children = ( - OBJ_18 /* WallabagCollection.swift */, - OBJ_19 /* WallabagEntry.swift */, - OBJ_20 /* WallabagTag.swift */, - OBJ_21 /* WallabagToken.swift */, - 09A5DDD0283BA23F00494B1E /* WallabagConfig.swift */, - ); - path = Model; - sourceTree = ""; - }; - OBJ_22 /* Util */ = { - isa = PBXGroup; - children = ( - OBJ_23 /* EntriesFetcher.swift */, - ); - path = Util; - sourceTree = ""; - }; - OBJ_26 /* Tests */ = { - isa = PBXGroup; - children = ( - OBJ_27 /* WallabagKitTests */, - ); - name = Tests; - sourceTree = SOURCE_ROOT; - }; - OBJ_27 /* WallabagKitTests */ = { - isa = PBXGroup; - children = ( - OBJ_28 /* WallabagKitTests.swift */, - ); - name = WallabagKitTests; - path = Tests/WallabagKitTests; - sourceTree = SOURCE_ROOT; - }; - OBJ_29 /* Products */ = { - isa = PBXGroup; - children = ( - "WallabagKit::WallabagKit::Product" /* WallabagKit.framework */, - "WallabagKit::WallabagKitTests::Product" /* WallabagKitTests.xctest */, - ); - name = Products; - sourceTree = BUILT_PRODUCTS_DIR; - }; - OBJ_5 = { - isa = PBXGroup; - children = ( - OBJ_6 /* Package.swift */, - OBJ_7 /* Sources */, - OBJ_26 /* Tests */, - OBJ_29 /* Products */, - OBJ_32 /* README.md */, - ); - sourceTree = ""; - }; - OBJ_7 /* Sources */ = { - isa = PBXGroup; - children = ( - OBJ_8 /* WallabagKit */, - ); - name = Sources; - sourceTree = SOURCE_ROOT; - }; - OBJ_8 /* WallabagKit */ = { - isa = PBXGroup; - children = ( - OBJ_9 /* Endpoint */, - OBJ_14 /* Extension */, - OBJ_16 /* HttpMethod.swift */, - OBJ_17 /* Model */, - OBJ_22 /* Util */, - OBJ_24 /* WallabagKit.swift */, - OBJ_25 /* WallabagKitError.swift */, - ); - name = WallabagKit; - path = Sources/WallabagKit; - sourceTree = SOURCE_ROOT; - }; - OBJ_9 /* Endpoint */ = { - isa = PBXGroup; - children = ( - OBJ_10 /* WallabagEntryEndpoint.swift */, - OBJ_11 /* WallabagKitEndpoint.swift */, - OBJ_12 /* WallabagOAuth.swift */, - OBJ_13 /* WallabagTagEndpoint.swift */, - 09A5DDCE283BA1E400494B1E /* WallabagConfigEndpoint.swift */, - ); - path = Endpoint; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - "WallabagKit::SwiftPMPackageDescription" /* WallabagKitPackageDescription */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_53 /* Build configuration list for PBXNativeTarget "WallabagKitPackageDescription" */; - buildPhases = ( - OBJ_56 /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = WallabagKitPackageDescription; - productName = WallabagKitPackageDescription; - productType = "com.apple.product-type.framework"; - }; - "WallabagKit::WallabagKit" /* WallabagKit */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_34 /* Build configuration list for PBXNativeTarget "WallabagKit" */; - buildPhases = ( - OBJ_37 /* Sources */, - OBJ_51 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = WallabagKit; - productName = WallabagKit; - productReference = "WallabagKit::WallabagKit::Product" /* WallabagKit.framework */; - productType = "com.apple.product-type.framework"; - }; - "WallabagKit::WallabagKitTests" /* WallabagKitTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = OBJ_64 /* Build configuration list for PBXNativeTarget "WallabagKitTests" */; - buildPhases = ( - OBJ_67 /* Sources */, - OBJ_69 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - OBJ_71 /* PBXTargetDependency */, - ); - name = WallabagKitTests; - productName = WallabagKitTests; - productReference = "WallabagKit::WallabagKitTests::Product" /* WallabagKitTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - OBJ_1 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftMigration = 9999; - LastUpgradeCheck = 1310; - }; - buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "WallabagKit" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = OBJ_5; - productRefGroup = OBJ_29 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - "WallabagKit::WallabagKit" /* WallabagKit */, - "WallabagKit::SwiftPMPackageDescription" /* WallabagKitPackageDescription */, - "WallabagKit::WallabagKitPackageTests::ProductTarget" /* WallabagKitPackageTests */, - "WallabagKit::WallabagKitTests" /* WallabagKitTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - OBJ_37 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_38 /* WallabagEntryEndpoint.swift in Sources */, - OBJ_39 /* WallabagKitEndpoint.swift in Sources */, - OBJ_40 /* WallabagOAuth.swift in Sources */, - OBJ_41 /* WallabagTagEndpoint.swift in Sources */, - OBJ_42 /* Publisher.swift in Sources */, - OBJ_43 /* HttpMethod.swift in Sources */, - OBJ_44 /* WallabagCollection.swift in Sources */, - OBJ_45 /* WallabagEntry.swift in Sources */, - OBJ_46 /* WallabagTag.swift in Sources */, - OBJ_47 /* WallabagToken.swift in Sources */, - OBJ_48 /* EntriesFetcher.swift in Sources */, - OBJ_49 /* WallabagKit.swift in Sources */, - OBJ_50 /* WallabagKitError.swift in Sources */, - 09A5DDD1283BA23F00494B1E /* WallabagConfig.swift in Sources */, - 09A5DDCF283BA1E400494B1E /* WallabagConfigEndpoint.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_56 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_57 /* Package.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - OBJ_67 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 0; - files = ( - OBJ_68 /* WallabagKitTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - OBJ_62 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = "WallabagKit::WallabagKitTests" /* WallabagKitTests */; - targetProxy = 09918FC32731EB9F005F3CE7 /* PBXContainerItemProxy */; - }; - OBJ_71 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = "WallabagKit::WallabagKit" /* WallabagKit */; - targetProxy = 09918FC22731EB9F005F3CE7 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - OBJ_3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "SWIFT_PACKAGE=1", - "DEBUG=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - ONLY_ACTIVE_ARCH = YES; - OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "$(AVAILABLE_PLATFORMS)"; - SUPPORTS_MACCATALYST = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE DEBUG"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - USE_HEADERMAP = NO; - }; - name = Debug; - }; - OBJ_35 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = WallabagKit.xcodeproj/WallabagKit_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = WallabagKit; - PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = WallabagKit; - TVOS_DEPLOYMENT_TARGET = 12.0; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Debug; - }; - OBJ_36 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = WallabagKit.xcodeproj/WallabagKit_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = WallabagKit; - PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = WallabagKit; - TVOS_DEPLOYMENT_TARGET = 12.0; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Release; - }; - OBJ_4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = s; - GCC_PREPROCESSOR_DEFINITIONS = ( - "$(inherited)", - "SWIFT_PACKAGE=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "$(AVAILABLE_PLATFORMS)"; - SUPPORTS_MACCATALYST = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE"; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - USE_HEADERMAP = NO; - }; - name = Release; - }; - OBJ_54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - LD = /usr/bin/true; - OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/ManifestAPI -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -package-description-version 5.5.0"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - OBJ_55 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - LD = /usr/bin/true; - OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/ManifestAPI -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -package-description-version 5.5.0"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - OBJ_60 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = Debug; - }; - OBJ_61 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = Release; - }; - OBJ_65 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = WallabagKit.xcodeproj/WallabagKitTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = WallabagKitTests; - TVOS_DEPLOYMENT_TARGET = 14.0; - WATCHOS_DEPLOYMENT_TARGET = 7.0; - }; - name = Debug; - }; - OBJ_66 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 1; - DRIVERKIT_DEPLOYMENT_TARGET = 19.0; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PLATFORM_DIR)/Developer/Library/Frameworks", - ); - HEADER_SEARCH_PATHS = "$(inherited)"; - INFOPLIST_FILE = WallabagKit.xcodeproj/WallabagKitTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; - SWIFT_VERSION = 5.0; - TARGET_NAME = WallabagKitTests; - TVOS_DEPLOYMENT_TARGET = 14.0; - WATCHOS_DEPLOYMENT_TARGET = 7.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - OBJ_2 /* Build configuration list for PBXProject "WallabagKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_3 /* Debug */, - OBJ_4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_34 /* Build configuration list for PBXNativeTarget "WallabagKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_35 /* Debug */, - OBJ_36 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_53 /* Build configuration list for PBXNativeTarget "WallabagKitPackageDescription" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_54 /* Debug */, - OBJ_55 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_59 /* Build configuration list for PBXAggregateTarget "WallabagKitPackageTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_60 /* Debug */, - OBJ_61 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_64 /* Build configuration list for PBXNativeTarget "WallabagKitTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_65 /* Debug */, - OBJ_66 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = OBJ_1 /* Project object */; -} diff --git a/WallabagKit/WallabagKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/WallabagKit/WallabagKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index fe1aa71..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/WallabagKit/WallabagKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/WallabagKit/WallabagKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index a72dc2b..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded - - - \ No newline at end of file diff --git a/WallabagKit/WallabagKit.xcodeproj/xcshareddata/xcschemes/WallabagKit-Package.xcscheme b/WallabagKit/WallabagKit.xcodeproj/xcshareddata/xcschemes/WallabagKit-Package.xcscheme deleted file mode 100644 index 29fab3c..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/xcshareddata/xcschemes/WallabagKit-Package.xcscheme +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WallabagKit/WallabagKit.xcodeproj/xcuserdata/maxime.xcuserdatad/xcschemes/xcschememanagement.plist b/WallabagKit/WallabagKit.xcodeproj/xcuserdata/maxime.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index d75910a..0000000 --- a/WallabagKit/WallabagKit.xcodeproj/xcuserdata/maxime.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - SchemeUserState - - WallabagKit-Package.xcscheme_^#shared#^_ - - orderHint - 4 - - WallabagKitPackageDescription.xcscheme_^#shared#^_ - - orderHint - 7 - - WallabagKitPackageTests.xcscheme_^#shared#^_ - - orderHint - 9 - - - - diff --git a/bagit/Info.plist b/bagit/Info.plist index 848beff..08e7373 100644 --- a/bagit/Info.plist +++ b/bagit/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 6.2.1 + 7.0.0 CFBundleVersion 319 ITSEncryptionExportComplianceCode diff --git a/bagit/ShareViewController.swift b/bagit/ShareViewController.swift index 767e92b..17e113a 100644 --- a/bagit/ShareViewController.swift +++ b/bagit/ShareViewController.swift @@ -1,5 +1,6 @@ import Combine import MobileCoreServices +import SharedLib import Social import UIKit import UniformTypeIdentifiers @@ -37,7 +38,7 @@ class ShareViewController: UIViewController { view.addSubview(backView) view.addSubview(notificationView) UIView.animate(withDuration: 0.3) { [unowned self] in - self.backView.alpha = 0.6 + backView.alpha = 0.6 } } @@ -51,7 +52,7 @@ class ShareViewController: UIViewController { kit.password = WallabagUserDefaults.password getUrl { shareURL in - guard let shareURL = shareURL else { + guard let shareURL else { self.clearView(withError: .retrievingURL) return } diff --git a/fastlane/SnapshotHelper.swift b/fastlane/SnapshotHelper.swift index 03f85dd..2d3505b 100644 --- a/fastlane/SnapshotHelper.swift +++ b/fastlane/SnapshotHelper.swift @@ -76,7 +76,7 @@ open class Snapshot: NSObject { } class func setLanguage(_ app: XCUIApplication) { - guard let cacheDirectory = cacheDirectory else { + guard let cacheDirectory else { NSLog("CacheDirectory is not set - probably running on a physical device?") return } @@ -93,7 +93,7 @@ open class Snapshot: NSObject { } class func setLocale(_ app: XCUIApplication) { - guard let cacheDirectory = cacheDirectory else { + guard let cacheDirectory else { NSLog("CacheDirectory is not set - probably running on a physical device?") return } @@ -117,7 +117,7 @@ open class Snapshot: NSObject { } class func setLaunchArguments(_ app: XCUIApplication) { - guard let cacheDirectory = cacheDirectory else { + guard let cacheDirectory else { NSLog("CacheDirectory is not set - probably running on a physical device?") return } @@ -150,7 +150,7 @@ open class Snapshot: NSObject { } #if os(OSX) - guard let app = app else { + guard let app else { NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") return } @@ -209,7 +209,7 @@ open class Snapshot: NSObject { return #endif - guard let app = app else { + guard let app else { NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().") return } diff --git a/iOS/AppDelegate.swift b/iOS/AppDelegate.swift deleted file mode 100644 index 5eb22fe..0000000 --- a/iOS/AppDelegate.swift +++ /dev/null @@ -1,23 +0,0 @@ -import UIKit - -final class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - - func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - #if DEBUG - let args = ProcessInfo.processInfo.arguments - - if args.contains("POPULATE_APPLICATION") { - populateApplication() - } - #endif - - return true - } - - func applicationDidFinishLaunching(_: UIApplication) { - UIApplication.shared.beginReceivingRemoteControlEvents() - } - - func applicationWillTerminate(_: UIApplication) {} -} diff --git a/iOS/Extension/AppDelegateExtension.swift b/iOS/Extension/AppDelegateExtension.swift deleted file mode 100644 index ff1dfea..0000000 --- a/iOS/Extension/AppDelegateExtension.swift +++ /dev/null @@ -1,54 +0,0 @@ -import CoreData -import Foundation -import UIKit - -#if DEBUG - // swiftlint:disable line_length - extension AppDelegate { - func populateApplication() { - resetApplication() - - let appState = DependencyInjection.container.resolve(AppState.self)! - appState.registred = true - appState.router.load(.entries) - WallabagUserDefaults.defaultMode = "allArticles" - WallabagUserDefaults.badgeEnabled = false - - let context = CoreData.shared.viewContext - - let entry = Entry(context: context) - entry.title = "Marc Zuckerberg devrait être passible d'une peine de prison pour mensonges répétés au sujet de la protection de la vie privée des utilisateurs Facebook, d'après le sénateur américain Ron Wyden" - entry.url = "https://www.developpez.com/actu/275880/Marc-Zuckerberg-devrait-etre-passible-d-une-peine-de-prison-pour-mensonges-repetes-au-sujet-de-la-protection-de-la-vie-privee-des-utilisateurs-Facebook-d-apres-le-senateur-americain-Ron-Wyden/" - entry.previewPicture = "https://www.developpez.com/images/logos/mark-zuckerberg.png" - entry.content = """ - image La société Facebook est depuis quelque temps très critiquée sur la manière avec laquelle elle manipule les données de ses utilisateurs et les nombreux scandales comme celui de cambridge analytica, n’améliorent pas l’image de l’entreprise. D’ailleurs, après l'épisode de Cambridge Analytica, la société a reconnu plusieurs autres cas de manquements à la vie privée, dont celui d'admettre qu'elle avait mal géré les mots de passe d'utilisateurs sur Instagram. Bien que l’entreprise Facebook soit déjà sous le coup d’une amende de 5 milliards de dollars, cela semble ne pas être suffisant pour certains qui estiment que les dirigeants devraient eux aussi être poursuivis en justice. -

En effet, un projet de loi présenté en 2018 par le sénateur Ron Wyden, donne à la FTC le pouvoir de sévir plus sévèrement contre les entreprises qui violent la vie privée des consommateurs. Selon le projet de loi, les dirigeants pourraient être condamnés à 20 ans de prison et à une amende de 5 millions de dollars. Et c’est dans ce sens que le sénateur Ron Wyden s’est exprimé lors d’une récente Interview qui portait sur l'article 230 de ce projet de loi, sur l'impact de cette législation et sur les conséquences néfastes, notamment le fait que Facebook utilisait cette législation à son avantage.

Au cours de cette interview, il a déclaré : « Mark Zuckerberg a menti à plusieurs reprises au peuple américain au sujet de la vie privée. Je pense qu'il devrait être tenu personnellement pour responsable, ce qui devrait entraîner des amendes financières et laissez-moi souligner également la possibilité d'une peine de prison parce qu'il a blessé beaucoup de gens ». Wyden a aussi mentionné le fait qu’il existait un précédent dans ce genre de cas : dans les services financiers, si le PDG et les dirigeants mentent au sujet des données financières, ils peuvent être tenus personnellement pour responsables.

-
image
-
Wyden n'est pas le premier législateur à proposer d'envoyer des cadres d’entreprises en prison. La sénatrice du Massachusetts, Elizabeth Warren, une candidate à la présidence de 2020 a dévoilé au début de cette année la loi sur la responsabilité des dirigeants d'entreprise, qui étend la responsabilité pénale aux dirigeants de toute société générant un chiffre d'affaires annuel supérieur à 1 milliard de dollars si cette société était reconnue coupable d'un crime ou d'une autre infraction civile. Malgré les souhaits de Wyden de voir Zuckerberg finir en prison, cela ne se produira probablement pas. C’est l’avis de Tim Gleason, un professeur de l’Université de l’Oregon, qui estime que les chances de Zuckerberg de faire face à une action criminelle sont plutôt minces. -

Pendant ce temps, plusieurs personnes pensent qu’emprisonner Zuckerberg ne réglera pas le problème, car il sera juste remplacé par quelqu'un d'autre qui fera pareil que lui. Ces personnes estiment qu’il serait peut-être plus judicieux de lui imposer une très grosse amende, qui servira à financer des œuvres sociales. Pour ces personnes, il est inutile de combattre ces milliardaires de cette façon, il faudrait plutôt utiliser leur cupidité contre eux.

-

Source : Willamette Week

-

Et vous ?

-

Qu’en pensez-vous ?
Pensez-vous que Zuckerberg sera finalement inquiété ?
Quelles mesures proposeriez-vous pour contraindre les entreprises à respecter la vie privée des utilisateurs ?

-

Voir aussi :

-

Les actionnaires de Facebook en ont assez de Marc Zuckerberg, mais ne peuvent rien faire contre lui, En voici les raisons
Mark Zuckerberg ainsi que d'autres cadres dirigeants de Facebook sont poursuivis en justice Pour les scandales liés à la vie privée
Mark Zuckerberg devrait vendre jusqu'à 13 Md$ d'actions Facebook d'ici mars 2019 Pour financer les actions philanthropiques de sa fondation CZI

- """ - } - - private func resetApplication() { - do { - // MARK: CoreData - - let context = CoreData.shared.viewContext - let operations = NSBatchDeleteRequest(fetchRequest: Entry.fetchRequest()) - try context.execute(operations) - - let accounts = NSBatchDeleteRequest(fetchRequest: Tag.fetchRequest()) - try context.execute(accounts) - - try context.save() - } catch { - print("error resetting app") - } - } - } -#endif diff --git a/iOS/Features/Entry/EntriesListView.swift b/iOS/Features/Entry/EntriesListView.swift deleted file mode 100644 index 44c4fe8..0000000 --- a/iOS/Features/Entry/EntriesListView.swift +++ /dev/null @@ -1,38 +0,0 @@ -import CoreData -import Foundation -import SwiftUI - -struct EntriesListView: View { - @Environment(\.managedObjectContext) var context: NSManagedObjectContext - @EnvironmentObject var appSync: AppSync - @FetchRequest var entries: FetchedResults - @EnvironmentObject var router: Router - - init(predicate: NSPredicate) { - _entries = FetchRequest(entity: Entry.entity(), sortDescriptors: [NSSortDescriptor(key: "id", ascending: false)], predicate: predicate, animation: nil) - } - - var body: some View { - List(entries, id: \.id) { entry in - Button(action: { - self.router.load(.entry(entry)) - }, label: { - EntryRowView(entry: entry) - .contentShape(Rectangle()) - .contextMenu { - ArchiveEntryButton(entry: entry) - StarEntryButton(entry: entry) - } - }).buttonStyle(PlainButtonStyle()) - .swipeActions(allowsFullSwipe: false, content: { - ArchiveEntryButton(entry: entry) - .tint(.blue) - .labelStyle(.iconOnly) - StarEntryButton(entry: entry) - .tint(.orange) - .labelStyle(.iconOnly) - }) - }.refreshable { appSync.requestSync() } - .listStyle(InsetListStyle()) - } -} diff --git a/iOS/Features/Entry/EntriesView.swift b/iOS/Features/Entry/EntriesView.swift deleted file mode 100644 index 997a2cb..0000000 --- a/iOS/Features/Entry/EntriesView.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Combine -import CoreData -import SwiftUI - -struct EntriesView: View { - @StateObject var pasteBoardViewModel = PasteBoardViewModel() - @StateObject var searchViewModel = SearchViewModel() - - var body: some View { - VStack { - // MARK: Pasteboard - - if pasteBoardViewModel.showPasteBoardView { - PasteBoardView().environmentObject(pasteBoardViewModel) - } - - // MARK: Picker - - SearchView(searchViewModel: searchViewModel) - EntriesListView(predicate: searchViewModel.predicate) - } - .navigationBarTitle(Text("Entry")) - .navigationBarHidden(true) - } -} - -#if DEBUG - struct ArticleListView_Previews: PreviewProvider { - static var previews: some View { - EntriesView() - .environmentObject(PasteBoardViewModel()) - } - } -#endif diff --git a/iOS/Features/Entry/EntryView.swift b/iOS/Features/Entry/EntryView.swift deleted file mode 100644 index 402c117..0000000 --- a/iOS/Features/Entry/EntryView.swift +++ /dev/null @@ -1,102 +0,0 @@ -import CoreData -import HTMLEntities -import SwiftUI - -struct EntryView: View { - @Environment(\.managedObjectContext) var context: NSManagedObjectContext - @Environment(\.openURL) var openURL - @EnvironmentObject var appSync: AppSync - @EnvironmentObject var router: Router - @EnvironmentObject var player: PlayerPublisher - @ObservedObject var entry: Entry - @State var showTag: Bool = false - @State private var showDeleteConfirm = false - - var body: some View { - VStack { - HStack { - Button(action: { - self.router.load(.entries) - }, label: { - Text("Back") - }) - Text(entry.title?.htmlUnescape() ?? "Entry") - .font(.title) - .fontWeight(.black) - .lineLimit(1) - Spacer() - }.padding() - WebView(entry: entry) - bottomBar - }.sheet(isPresented: $showTag) { - TagListFor(tagsForEntry: TagsForEntryPublisher(entry: self.entry)) - .environment(\.managedObjectContext, CoreData.shared.viewContext) - } - .actionSheet(isPresented: $showDeleteConfirm) { - ActionSheet( - title: Text("Confirm delete?"), - buttons: [ - .destructive(Text("Delete")) { - self.context.delete(entry) - self.router.load(.entries) - }, - .cancel(), - ] - ) - } - } - - private var bottomBar: some View { - HStack { - FontSizeSelectorView() - .buttonStyle(PlainButtonStyle()) - Spacer() - SwiftUI.Menu(content: { - Button(action: { - self.showDeleteConfirm = true - }, label: { - Label("Delete", systemImage: "trash") - }) - Button(action: { - openURL(self.entry.url!.url!) - }, label: { - Label("Open in Safari", systemImage: "safari") - }) - Button(action: { - self.showTag.toggle() - }, label: { - Label("Tag", systemImage: self.showTag ? "tag.fill" : "tag") - }) - Button(action: { - appSync.refresh(entry: entry) - }, label: { - Label("Refresh", systemImage: "arrow.counterclockwise") - }) - StarEntryButton(entry: entry, showText: true).hapticNotification(.success) - ArchiveEntryButton(entry: entry, showText: true).hapticNotification(.success) - Button(action: { - player.load(entry) - }, label: { - Label("Load entry", systemImage: "music.note") - }) - .accessibilityHint("Load entry in text-to-speech player") - }, label: { - Label("Entry option", systemImage: "filemenu.and.selection") - .foregroundColor(.primary) - .labelStyle(.iconOnly) - .frame(width: 28, height: 28) - }).accessibilityLabel("Entry option") - }.padding(.horizontal) - } -} - -#if DEBUG - struct EntryView_Previews: PreviewProvider { - static var previews: some View { - EntryView(entry: Entry(context: CoreData.shared.viewContext)) - .environmentObject(PlayerPublisher()) - .environmentObject(Router(defaultRoute: .entries)) - .environment(\.managedObjectContext, CoreData.shared.viewContext) - } - } -#endif diff --git a/iOS/Features/Entry/Picture/EntryPicture.swift b/iOS/Features/Entry/Picture/EntryPicture.swift deleted file mode 100644 index 48e758a..0000000 --- a/iOS/Features/Entry/Picture/EntryPicture.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Combine -import SwiftUI - -struct EntryPicture: View { - @StateObject var imagePublisher = ImageDownloaderPublisher() - - var url: String? - - var body: some View { - Group { - if let image = imagePublisher.image { - Image(uiImage: image) - .resizable() - .scaledToFit() - } else { - Image(systemName: "book") - .resizable() - .scaledToFit() - } - }.task { - await imagePublisher.loadImage(url: url) - } - } -} diff --git a/iOS/Features/Entry/Picture/ImageCache.swift b/iOS/Features/Entry/Picture/ImageCache.swift deleted file mode 100644 index 9d9f1c2..0000000 --- a/iOS/Features/Entry/Picture/ImageCache.swift +++ /dev/null @@ -1,71 +0,0 @@ -import Combine -import Foundation -#if canImport(UIKit) - import UIKit -#endif - -actor ImageCache { - static var shared = ImageCache() - - private var memoryCache: NSCache = { - let cache = NSCache() - // set limit? - return cache - }() - - private init() {} - - private func clearMemoryCache(_: Notification?) { - memoryCache.removeAllObjects() - } - - subscript(name: String) -> UIImage? { - get { - get(name: name) - } - set { - guard let image = newValue else { return } - set(image, for: name) - } - } - - func set(_ image: UIImage, for name: String) { - memoryCache.setObject(image, forKey: name as NSString) - - let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] - let filename = url.appendingPathComponent("\(name.md5).png") - - try? image.pngData()?.write(to: filename) - } - - func get(name: String) -> UIImage? { - if let imageCacheMemory = memoryCache.object(forKey: name.NSString) { - return imageCacheMemory - } - - let dir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] - let imageCacheDir = UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent("\(name.md5).png").path) - - if imageCacheDir != nil { - memoryCache.setObject(imageCacheDir!, forKey: name.NSString) - - return imageCacheDir - } - - return nil - } - - func purge() { - clearMemoryCache(nil) - - let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] - do { - let files = try FileManager.default.contentsOfDirectory(atPath: url.path) - try files.forEach { - try FileManager.default.removeItem(atPath: url.appendingPathComponent($0).path) - } - } catch { - print("Error in cache purge") - } - } -} diff --git a/iOS/Features/Entry/Picture/ImageDownloader.swift b/iOS/Features/Entry/Picture/ImageDownloader.swift deleted file mode 100644 index 64063d1..0000000 --- a/iOS/Features/Entry/Picture/ImageDownloader.swift +++ /dev/null @@ -1,35 +0,0 @@ -import Combine -import Foundation -#if canImport(UIKit) - import UIKit -#endif - -final class ImageDownloader { - static var shared = ImageDownloader() - - private var cacheStore = ImageCache.shared - - private var dispatchQueue = DispatchQueue(label: "fr.district-web.wallabag.image-downloader", qos: .background) - - private init() {} - - func loadImage(url: URL) async -> UIImage? { - if let imageCache = await cacheStore[url.absoluteString] { - return imageCache - } - - var request = URLRequest(url: url) - request.allowsConstrainedNetworkAccess = false - - do { - let (data, _) = try await URLSession.shared.data(for: request) - guard let image = UIImage(data: data) else { return nil } - - await cacheStore.set(image, for: url.absoluteString) - - return image - } catch {} - - return nil - } -} diff --git a/iOS/Features/Entry/Picture/ImageDownloaderPublisher.swift b/iOS/Features/Entry/Picture/ImageDownloaderPublisher.swift deleted file mode 100644 index dc3363f..0000000 --- a/iOS/Features/Entry/Picture/ImageDownloaderPublisher.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Combine -import Foundation -import UIKit.UIImage - -final class ImageDownloaderPublisher: ObservableObject { - @Published var image: UIImage? - - @MainActor - func loadImage(url: String?) async { - guard let url = url?.url else { return } - image = await ImageDownloader.shared.loadImage(url: url) - } -} diff --git a/iOS/Features/Entry/WebView.swift b/iOS/Features/Entry/WebView.swift deleted file mode 100644 index b72764c..0000000 --- a/iOS/Features/Entry/WebView.swift +++ /dev/null @@ -1,104 +0,0 @@ -import CoreData -import SafariServices -import SwiftUI -import WebKit - -struct WebView: UIViewRepresentable { - var entry: Entry - private(set) var wkWebView = WKWebView(frame: .zero) - @EnvironmentObject var appSetting: AppSetting - - func makeCoordinator() -> Coordinator { - Coordinator(self, appSetting: appSetting) - } - - class Coordinator: NSObject, WKNavigationDelegate, UIScrollViewDelegate { - @CoreDataViewContext var context: NSManagedObjectContext - var appSetting: AppSetting - - private var webView: WebView - - init(_ webView: WebView, appSetting: AppSetting) { - self.webView = webView - self.appSetting = appSetting - super.init() - } - - func webViewToLastPosition() { - DispatchQueue.main.async { - self.webView.wkWebView.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.webView.entry.screenPositionForWebView), animated: true) - } - } - - func webView(_ webView: WKWebView, didFinish _: WKNavigation!) { - webViewToLastPosition() - webView.fontSizePercent(appSetting.webFontSizePercent) - } - - func webView(_: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { - guard let urlTarget = navigationAction.request.url else { - decisionHandler(.cancel) - return - } - - let urlAbsolute = urlTarget.absoluteString - - if urlAbsolute.hasPrefix(Bundle.main.bundleURL.absoluteString) || urlAbsolute == "about:blank" { - decisionHandler(.allow) - return - } - - if navigationAction.targetFrame?.isMainFrame == false { - decisionHandler(.allow) - return - } - - let safariController = SFSafariViewController(url: urlTarget) - safariController.modalPresentationStyle = .overFullScreen - - UIApplication.shared.open(urlTarget, options: [:], completionHandler: nil) - decisionHandler(.cancel) - } - - func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - context.perform { - self.webView.entry.screenPosition = Float(scrollView.contentOffset.y) - try? self.context.save() - } - } - } - - func makeUIView(context: Context) -> WKWebView { - wkWebView.navigationDelegate = context.coordinator - wkWebView.scrollView.delegate = context.coordinator - wkWebView.load(content: entry.content, justify: false) - - return wkWebView - } - - func updateUIView(_ webView: WKWebView, context _: Context) { - webView.fontSizePercent(appSetting.webFontSizePercent) - } -} - -#if DEBUG - struct WebView_Previews: PreviewProvider { - static var entry: Entry = { - let entry = Entry() - entry.title = "Test" - entry.content = "

Nice Content

" - return entry - }() - - static var previews: some View { - Group { - WebView( - entry: entry - ).colorScheme(.light) - WebView( - entry: entry - ).colorScheme(.dark) - } - } - } -#endif diff --git a/iOS/Features/Haptic/ButtonStyle/HapticNotificationButtonStyle.swift b/iOS/Features/Haptic/ButtonStyle/HapticNotificationButtonStyle.swift deleted file mode 100644 index 5b25db8..0000000 --- a/iOS/Features/Haptic/ButtonStyle/HapticNotificationButtonStyle.swift +++ /dev/null @@ -1,12 +0,0 @@ -import SwiftUI - -struct HapticNotificationButtonStyle: ButtonStyle { - let feedbackType: UINotificationFeedbackGenerator.FeedbackType - func makeBody(configuration: Configuration) -> some View { - if configuration.isPressed { - let generator = UINotificationFeedbackGenerator() - generator.notificationOccurred(feedbackType) - } - return configuration.label - } -} diff --git a/iOS/Features/Haptic/Extension/View+haptic.swift b/iOS/Features/Haptic/Extension/View+haptic.swift deleted file mode 100644 index 5fbbaa0..0000000 --- a/iOS/Features/Haptic/Extension/View+haptic.swift +++ /dev/null @@ -1,7 +0,0 @@ -import SwiftUI - -extension View { - func hapticNotification(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) -> some View { - buttonStyle(HapticNotificationButtonStyle(feedbackType: feedbackType)) - } -} diff --git a/iOS/Features/MainView.swift b/iOS/Features/MainView.swift deleted file mode 100644 index b46cc0c..0000000 --- a/iOS/Features/MainView.swift +++ /dev/null @@ -1,106 +0,0 @@ -import Combine -import SwiftUI - -struct MainView: View { - @EnvironmentObject var router: Router - @EnvironmentObject var player: PlayerPublisher - @State private var showMenu: Bool = false - @State private var menuOffsetX = CGFloat(0.0) - - func getMenuCloseGesture(_ offsetClose: CGFloat) -> some Gesture { - DragGesture() - .onChanged { value in - let newOffsetX = value.location.x - value.startLocation.x - if newOffsetX < 0 { - self.menuOffsetX = newOffsetX - } - } - .onEnded { value in - withAnimation { - let finalOffsetX = value.location.x - value.startLocation.x - if finalOffsetX < -offsetClose { - self.showMenu = false - } - self.menuOffsetX = 0 - } - } - } - - var header: some View { - HStack { - if router.route.showMenuButton { - Button(action: { - withAnimation { - self.showMenu.toggle() - } - }, label: { Image(systemName: "list.bullet") }) - .buttonStyle(PlainButtonStyle()) - .accessibilityLabel("Menu") - .accessibilityHidden(showMenu) - } - Text(router.route.title) - .font(.title) - .fontWeight(.black) - Spacer() - if router.route.showTraillingButton { - router.route.traillingButton - } - Button(action: { - withAnimation { - player.togglePlayer() - } - }, label: { - Image(systemName: "music.note") - }).buttonStyle(PlainButtonStyle()) - .accessibilityLabel("Entries player") - } - } - - var body: some View { - GeometryReader { geometry in - ZStack(alignment: .leading) { - VStack { - if self.router.route.showHeader { - self.header.padding(.horizontal).padding(.top, 15) - .accessibilityHidden(showMenu) - } - ErrorView() - RouterView() - .accessibilityHidden(showMenu) - }.frame(width: geometry.size.width, height: geometry.size.height) - .blur(radius: self.showMenu ? 10 : 0) - - if self.showMenu { - Rectangle() - .opacity(0.1) - .edgesIgnoringSafeArea(.all) - .onTapGesture { - withAnimation { - self.showMenu = false - } - } - MenuView(showMenu: self.$showMenu) - .frame(width: geometry.size.width / 1.5) - .offset(x: self.menuOffsetX) - .transition(.move(edge: .leading)) - .gesture(self.getMenuCloseGesture(geometry.size.width / 4)) - .edgesIgnoringSafeArea(.all) - } - if player.showPlayer { - PlayerView() - .frame(width: geometry.size.width, height: geometry.size.height, alignment: .topTrailing) - .transition(.move(edge: .trailing)) - .offset(x: 0, y: 60) - } - } - } - } -} - -#if DEBUG - struct MainView_Previews: PreviewProvider { - static var previews: some View { - Text("nothing") - } - } -#endif diff --git a/iOS/Features/Menu/Menu.swift b/iOS/Features/Menu/Menu.swift deleted file mode 100644 index 68fd282..0000000 --- a/iOS/Features/Menu/Menu.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation -import SwiftUI - -struct Menu: Identifiable { - var id: String { - "\(route.title)" - } - - let title: LocalizedStringKey - let img: String - let route: Route -} diff --git a/iOS/Features/Menu/MenuView.swift b/iOS/Features/Menu/MenuView.swift deleted file mode 100644 index 148bc4a..0000000 --- a/iOS/Features/Menu/MenuView.swift +++ /dev/null @@ -1,78 +0,0 @@ -import SwiftUI - -struct MenuView: View { - @EnvironmentObject var appState: AppState - @Environment(\.openURL) var openURL - @EnvironmentObject var router: Router - @Binding var showMenu: Bool - - fileprivate let menus: [Menu] = [ - .init(title: "Entries", img: "tray.full", route: .entries), - .init(title: "Add entry", img: "tray.and.arrow.down", route: .addEntry), - .init(title: "About", img: "questionmark", route: .about), - .init(title: "Don", img: "heart", route: .tips), - .init(title: "Setting", img: "gear", route: .setting), - ] - - // swiftlint:disable multiple_closures_with_trailing_closure - var body: some View { - VStack(alignment: .leading) { - header - List { - Section { - ForEach(self.menus) { menu in - Button(action: { - tapButtonMenu { - router.load(menu.route) - } - }) { - Label(menu.title, systemImage: menu.img) - } - } - Button(action: { - tapButtonMenu { - router.load(.bugReport) - } - }) { - Label("Bug report", systemImage: "ant") - } - Button(role: .destructive, action: { - tapButtonMenu { - self.appState.logout() - } - }) { - Label("Logout", systemImage: "person") - }.foregroundColor(.red) - } - }.listStyle(InsetListStyle()) - } - .background(Color(UIColor.systemBackground)) - } - - private var header: some View { - Text("Menu") - .font(.title) - .fontWeight(.black) - .onTapGesture { - withAnimation { - self.showMenu = false - } - } - .padding(.top, 44) - .padding(.horizontal) - } - - private func tapButtonMenu(_ action: () -> Void) { - withAnimation { - showMenu = false - } - action() - } -} - -struct MenuView_Previews: PreviewProvider { - static var previews: some View { - MenuView(showMenu: .constant(true)) - .previewLayout(.sizeThatFits) - } -} diff --git a/iOS/Features/PasteBoard/PasteBoardView.swift b/iOS/Features/PasteBoard/PasteBoardView.swift deleted file mode 100644 index a6f1f79..0000000 --- a/iOS/Features/PasteBoard/PasteBoardView.swift +++ /dev/null @@ -1,44 +0,0 @@ -import SwiftUI - -struct PasteBoardView: View { - @EnvironmentObject var pasteBoardViewModel: PasteBoardViewModel - - var body: some View { - HStack(alignment: .center) { - Image(systemName: "doc.on.clipboard") - VStack { - Text("New url in pasteboard detected") - .font(.headline) - Text(pasteBoardViewModel.pasteBoardUrl) - .lineLimit(1) - HStack { - Button(action: { - self.pasteBoardViewModel.addUrl() - }, label: { - Text("Add") - }) - Button(action: { - self.pasteBoardViewModel.hide() - }, label: { - Text("Cancel") - }) - } - } - } - } -} - -struct PasteBoardView_Previews: PreviewProvider { - static var publisher: PasteBoardViewModel = { - let pub = PasteBoardViewModel() - pub.pasteBoardUrl = "http://wallabag-with-a-long-url.org" - return pub - }() - - static var previews: some View { - Group { - PasteBoardView().previewLayout(.sizeThatFits).environmentObject(publisher) - PasteBoardView().previewLayout(.fixed(width: 250, height: 60)).environmentObject(publisher) - } - } -} diff --git a/iOS/Features/PasteBoard/PasteBoardViewModel.swift b/iOS/Features/PasteBoard/PasteBoardViewModel.swift deleted file mode 100644 index 1f1767a..0000000 --- a/iOS/Features/PasteBoard/PasteBoardViewModel.swift +++ /dev/null @@ -1,47 +0,0 @@ -import Combine -import Foundation -import UIKit - -class PasteBoardViewModel: ObservableObject { - @Published var showPasteBoardView: Bool = false { - willSet { - if newValue { - if let pasteBoardString = UIPasteboard.general.string, let newPasteBoardUrl = URL(string: pasteBoardString) { - WallabagUserDefaults.previousPasteBoardUrl = newPasteBoardUrl.absoluteString - pasteBoardUrl = newPasteBoardUrl.absoluteString - } - } - } - } - - @Published var pasteBoardUrl: String = "" - @Injector var session: WallabagSession - - private var cancellableNotification: AnyCancellable? - - init() { - cancellableNotification = NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification) - .map { _ -> Bool in - guard let pasteBoardString = UIPasteboard.general.string, let pasteBoardUrl = URL(string: pasteBoardString), - pasteBoardUrl.absoluteString != WallabagUserDefaults.previousPasteBoardUrl - else { - return false - } - return true - } - .assign(to: \.showPasteBoardView, on: self) - } - - deinit { - cancellableNotification?.cancel() - } - - func addUrl() { - session.addEntry(url: pasteBoardUrl) {} - showPasteBoardView = false - } - - func hide() { - showPasteBoardView = false - } -} diff --git a/iOS/Features/Player/PlayerPublisher.swift b/iOS/Features/Player/PlayerPublisher.swift deleted file mode 100644 index 02f8931..0000000 --- a/iOS/Features/Player/PlayerPublisher.swift +++ /dev/null @@ -1,79 +0,0 @@ -import AVFoundation -import Combine -import Foundation -import MediaPlayer -import SwiftUI - -final class PlayerPublisher: ObservableObject { - static var shared = PlayerPublisher() - private var speecher = AVSpeechSynthesizer() - private var utterance: AVSpeechUtterance? - - @Published var podcast: Podcast? - @Published var showPlayer: Bool = false - @Published private(set) var isPlaying = false { - willSet { - if newValue { - play() - } else { - pause() - } - } - } - - init() { - MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = false - MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = false - MPRemoteCommandCenter.shared().playCommand.addTarget { _ in - self.play() - return .success - } - MPRemoteCommandCenter.shared().pauseCommand.addTarget { _ in - self.pause() - return .success - } - } - - func load(_ entry: Entry) { - isPlaying = false - showPlayer = true - podcast = Podcast(id: entry.id, title: entry.title ?? "Title", content: entry.content?.withoutHTML ?? "", picture: entry.previewPicture) - utterance = AVSpeechUtterance(string: podcast!.content) - MPNowPlayingInfoCenter.default().nowPlayingInfo = [ - MPMediaItemPropertyTitle: entry.title, - MPMediaItemPropertyArtist: "Wallabag", - ] - try? AVAudioSession.sharedInstance().setActive(true) - try? AVAudioSession.sharedInstance().setCategory(.playback) - } - - func togglePlaying() { - isPlaying = !isPlaying - } - - func play() { - guard let utterance = utterance else { return } - if !speecher.isSpeaking { - speecher.speak(utterance) - } else { - if speecher.isPaused { - speecher.continueSpeaking() - } else { - speecher.pauseSpeaking(at: .word) - } - } - } - - func pause() { - speecher.pauseSpeaking(at: .word) - } - - func stop() { - isPlaying = false - speecher.stopSpeaking(at: .immediate) - } - - func togglePlayer() { - showPlayer.toggle() - } -} diff --git a/iOS/Features/Player/PlayerView.swift b/iOS/Features/Player/PlayerView.swift deleted file mode 100644 index a46191f..0000000 --- a/iOS/Features/Player/PlayerView.swift +++ /dev/null @@ -1,71 +0,0 @@ -import SwiftUI - -struct PlayerView: View { - @EnvironmentObject var playerPublisher: PlayerPublisher - - var body: some View { - VStack { - if playerPublisher.podcast != nil { - playerPublisher.podcast.map { podcast in - VStack { - EntryPicture(url: podcast.picture).frame(width: 100, alignment: .center) - Text(podcast.title) - .padding(4) - HStack { - Button(action: { - playerPublisher.togglePlaying() - }, label: { - Image(systemName: playerPublisher.isPlaying ? "pause.circle" : "play.circle") - }).font(.system(size: 30)) - Button(action: { - playerPublisher.stop() - }, label: { - Image(systemName: "stop.circle") - }).font(.system(size: 30)) - }.buttonStyle(PlainButtonStyle()) - }.padding() - } - } else { - VStack { - EntryPicture(url: nil).frame(width: 100, alignment: .center) - Text("Select one entry") - .padding(4) - HStack { - Button(action: {}, label: { - Image(systemName: "play.circle") - .font(.system(size: 30)) - }).disabled(true) - } - } - } - } - .frame(width: 200, height: 200, alignment: .center) - .background(Color.primary.colorInvert()) - .cornerRadius(6) - .shadow(radius: 10) - .gesture(DragGesture().onEnded { swipe in - if swipe.startLocation.x < swipe.location.x { - playerPublisher.showPlayer = false - } - }) - } -} - -struct PlayerView_Previews: PreviewProvider { - static var player: PlayerPublisher = { - let player = PlayerPublisher() - let entry = Entry(context: CoreData.shared.viewContext) - player.load(entry) - return player - }() - - static var previews: some View { - PlayerView() - .environmentObject(PlayerPublisher()) - .previewLayout(.sizeThatFits) - - PlayerView() - .environmentObject(player) - .previewLayout(.sizeThatFits) - } -} diff --git a/iOS/Features/Router/Route.swift b/iOS/Features/Router/Route.swift deleted file mode 100644 index 1c4eb4c..0000000 --- a/iOS/Features/Router/Route.swift +++ /dev/null @@ -1,103 +0,0 @@ -import Foundation -import SwiftUI - -enum Route: Equatable { - case about - case addEntry - case bugReport - case entries - case entry(Entry) - case registration - case tips - case setting - - var id: String { - switch self { - case .about: - return "about" - case .addEntry: - return "addEntry" - case .bugReport: - return "bugReport" - case .entries: - return "entries" - case .entry: - return "entry" - case .registration: - return "registration" - case .tips: - return "tips" - case .setting: - return "setting" - } - } - - var title: LocalizedStringKey { - switch self { - case .addEntry: - return "Add entry" - case .entries: - return "Articles" - case .entry: - return "Article" - case .tips: - return "Tips" - case .about: - return "About" - case .registration: - return "Registration" - case .bugReport: - return "Bug report" - case .setting: - return "Setting" - } - } - - @ViewBuilder - var view: some View { - switch self { - case .about: - AboutView() - case .addEntry: - AddEntryView() - case .bugReport: - BugReportView() - case .entries: - EntriesView() - case let .entry(entry): - EntryView(entry: entry) - case .registration: - RegistrationView() - case .tips: - TipView() - case .setting: - SettingView() - } - } - - var showMenuButton: Bool { - self != .registration - } - - var showHeader: Bool { - switch self { - case .entry, .registration: - return false - default: - return true - } - } - - var showTraillingButton: Bool { - self == .entries - } - - var traillingButton: some View { - switch self { - case .entries: - return RefreshButton() - default: - fatalError("call trailling button") - } - } -} diff --git a/iOS/Features/Router/Router.swift b/iOS/Features/Router/Router.swift deleted file mode 100644 index 68f2c66..0000000 --- a/iOS/Features/Router/Router.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Combine -import Foundation - -final class Router: ObservableObject { - @Published private(set) var route: Route = .registration - - init(defaultRoute: Route) { - load(defaultRoute) - } - - func load(_ route: Route) { - logger.info("Load route \(route.id)") - self.route = route - } -} diff --git a/iOS/Features/Setting/SettingView.swift b/iOS/Features/Setting/SettingView.swift deleted file mode 100644 index 3f332ec..0000000 --- a/iOS/Features/Setting/SettingView.swift +++ /dev/null @@ -1,37 +0,0 @@ -import SharedLib -import SwiftUI - -struct SettingView: View { - @AppStorage("showImageInList") var showImageInList: Bool = true - @AppStorage("justifyArticle") var justifyArticle: Bool = true - @AppStorage("defaultMode") var defaultMode: String = RetrieveMode.allArticles.rawValue - @AppStorage("itemPerPageDuringSync") var itemPerPageDuringSync: Int = 50 - - var body: some View { - NavigationView { - Form { - Section("Entries list") { - Toggle("Show image in list", isOn: $showImageInList) - Picker("Default mode", selection: $defaultMode) { - ForEach(RetrieveMode.allCases, id: \.rawValue) { - Text($0.rawValue).tag($0.settingCase) - } - } - } - Section("Entry") { - Toggle("Justify entry", isOn: $justifyArticle) - } - Section("Sync") { - Stepper("Item per page during sync \(itemPerPageDuringSync)", value: $itemPerPageDuringSync, in: 20 ... 200) - } - }.navigationBarHidden(true) - Spacer() - }.navigationViewStyle(.stack) - } -} - -struct SettingView_Previews: PreviewProvider { - static var previews: some View { - SettingView() - } -} diff --git a/iOS/Features/Sync/RefreshButton.swift b/iOS/Features/Sync/RefreshButton.swift deleted file mode 100644 index 497577d..0000000 --- a/iOS/Features/Sync/RefreshButton.swift +++ /dev/null @@ -1,32 +0,0 @@ -import SwiftUI - -struct RefreshButton: View { - @EnvironmentObject var appSync: AppSync - - var body: some View { - HStack { - if appSync.inProgress { - ProgressView(value: appSync.progress, total: 100) - } - - Button( - action: appSync.requestSync, - label: { - Image(systemName: "arrow.counterclockwise") - .frame(width: 34, height: 34, alignment: .center) - .rotationEffect(.degrees(appSync.inProgress ? 0 : 360)) - .animation(.spring().repeatForever(autoreverses: false), value: appSync.inProgress) - } - ).disabled(appSync.inProgress) - .buttonStyle(PlainButtonStyle()) - .accessibilityLabel("Refresh") - .accessibilityHint("Refres entries from server") - } - } -} - -struct RefreshButton_Previews: PreviewProvider { - static var previews: some View { - RefreshButton().environmentObject(AppSync()) - } -} diff --git a/iOS/Lib/DependencyInjection.swift b/iOS/Lib/DependencyInjection.swift deleted file mode 100644 index c1de41f..0000000 --- a/iOS/Lib/DependencyInjection.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation -import Swinject -import WallabagKit - -final class DependencyInjection { - static let container: Container = { - let container = Container() - container.register(ErrorViewModel.self) { _ in ErrorViewModel.shared }.inObjectScope(.container) - container.register(WallabagKit.self, factory: { _ in - let kit = WallabagKit(host: WallabagUserDefaults.host) - kit.clientId = WallabagUserDefaults.clientId - kit.clientSecret = WallabagUserDefaults.clientSecret - kit.username = WallabagUserDefaults.login - kit.password = WallabagUserDefaults.password - kit.accessToken = WallabagUserDefaults.accessToken - kit.refreshToken = WallabagUserDefaults.refreshToken - - return kit - }).inObjectScope(.container) - container.register(WallabagSession.self, factory: { _ in WallabagSession() }).inObjectScope(.container) - container.register(AppSync.self, factory: { _ in AppSync.shared }).inObjectScope(.container) - container.register(ImageDownloader.self, factory: { _ in ImageDownloader.shared }).inObjectScope(.container) - container.register(AppState.self, factory: { _ in AppState.shared }).inObjectScope(.container) - container.register(Router.self, factory: { factory in - let appState: AppState = factory.resolve(AppState.self)! - let router = Router(defaultRoute: appState.registred ? .entries : .registration) - return router - }).inObjectScope(.container) - container.register(PlayerPublisher.self, factory: { _ in PlayerPublisher.shared }).inObjectScope(.container) - container.register(CoreDataSync.self, factory: { _ in CoreDataSync() }).inObjectScope(.container) - container.register(AppSetting.self, factory: { _ in AppSetting() }).inObjectScope(.container) - container.register(CoreData.self, factory: { _ in CoreData.shared }).inObjectScope(.container) - - return container - }() -} diff --git a/iOS/WallabagApp.swift b/iOS/WallabagApp.swift deleted file mode 100644 index 982fc8c..0000000 --- a/iOS/WallabagApp.swift +++ /dev/null @@ -1,59 +0,0 @@ -import Foundation -import os -import SharedLib -import SwiftUI - -let logger = Logger(subsystem: "fr.district-web.wallabag", category: "main") - -@main -struct WallabagApp: App { - @Environment(\.scenePhase) var scenePhase - @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate - - let appState: AppState = DependencyInjection.container.resolve(AppState.self)! - let router: Router = DependencyInjection.container.resolve(Router.self)! - let playerPublisher: PlayerPublisher = DependencyInjection.container.resolve(PlayerPublisher.self)! - let errorViewModel: ErrorViewModel = DependencyInjection.container.resolve(ErrorViewModel.self)! - let appSync: AppSync = DependencyInjection.container.resolve(AppSync.self)! - let coreDataSync: CoreDataSync = DependencyInjection.container.resolve(CoreDataSync.self)! - let appSetting: AppSetting = DependencyInjection.container.resolve(AppSetting.self)! - let coreData: CoreData = DependencyInjection.container.resolve(CoreData.self)! - - var body: some Scene { - WindowGroup { - MainView() - .environmentObject(appState) - .environmentObject(playerPublisher) - .environmentObject(router) - .environmentObject(errorViewModel) - .environmentObject(appSync) - .environmentObject(appSetting) - .environment(\.managedObjectContext, coreData.viewContext) - }.onChange(of: scenePhase) { state in - if state == .active { - appState.initSession() - } - - if state == .background { - coreData.saveContext() - updateBadge() - } - } - } - - private func updateBadge() { - if !WallabagUserDefaults.badgeEnabled { - UIApplication.shared.applicationIconBadgeNumber = 0 - return - } - - do { - let fetchRequest = Entry.fetchRequestSorted() - fetchRequest.predicate = RetrieveMode(fromCase: WallabagUserDefaults.defaultMode).predicate() - let entries = try coreData.viewContext.fetch(fetchRequest) - UIApplication.shared.applicationIconBadgeNumber = entries.count - } catch { - fatalError(error.localizedDescription) - } - } -} diff --git a/macOS/Features/Registration/RegistrationView.swift b/macOS/Features/Registration/RegistrationView.swift deleted file mode 100644 index 06c7e65..0000000 --- a/macOS/Features/Registration/RegistrationView.swift +++ /dev/null @@ -1,39 +0,0 @@ -import SwiftUI - -struct RegistrationView: View { - @StateObject var model = RegistrationModel() - var body: some View { - VStack(alignment: .leading) { - Text("Account").font(.title).fontWeight(.black) - TextField("Instance", text: $model.host) - TextField("Login", text: $model.login) - TextField("password", text: $model.password) - TextField("Client id", text: $model.clientId) - TextField("Client secret", text: $model.clientSecret) - Button("Submit") {} - } - .padding() - Spacer() - } -} - -final class RegistrationModel: ObservableObject { - @Published var host: String = "" - @Published var clientId: String = "" - @Published var clientSecret: String = "" - @Published var login: String = "" - @Published var password: String = "" - - init() { - host = WallabagUserDefaults.host - clientId = WallabagUserDefaults.clientId - clientSecret = WallabagUserDefaults.clientSecret - login = WallabagUserDefaults.login - } -} - -struct RegistrationView_Previews: PreviewProvider { - static var previews: some View { - RegistrationView() - } -} diff --git a/macOS/Features/Router/Route.swift b/macOS/Features/Router/Route.swift deleted file mode 100644 index fe4d3b5..0000000 --- a/macOS/Features/Router/Route.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Foundation -import SwiftUI - -enum Route { - case registration - case entry(Entry) - - var id: String { - switch self { - case .registration: - return "registration" - case .entry: - return "entry" - } - } - - @ViewBuilder - var view: some View { - switch self { - case .registration: - RegistrationView() - default: - Text("test") - } - } -} diff --git a/macOS/Features/Router/Router.swift b/macOS/Features/Router/Router.swift deleted file mode 100644 index e7885e6..0000000 --- a/macOS/Features/Router/Router.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Combine -import Foundation - -final class Router: ObservableObject { - static var shared = Router() - - @Published private(set) var route: Route = .registration - - private init() {} - - func load(_ route: Route) { - logger.info("Load route \(route.id)") - self.route = route - } -} diff --git a/macOS/Features/Sidebar/Menu.swift b/macOS/Features/Sidebar/Menu.swift deleted file mode 100644 index e53c11a..0000000 --- a/macOS/Features/Sidebar/Menu.swift +++ /dev/null @@ -1,3 +0,0 @@ -import Foundation - -enum Menu {} diff --git a/macOS/Features/Sidebar/SidebarView.swift b/macOS/Features/Sidebar/SidebarView.swift deleted file mode 100644 index 8f93577..0000000 --- a/macOS/Features/Sidebar/SidebarView.swift +++ /dev/null @@ -1,31 +0,0 @@ -import SwiftUI - -struct SidebarView: View { - var body: some View { - Section { - List { - ForEach(RetrieveMode.allCases, id: \.self) { retrieveMode in - NavigationLink(destination: EntriesListView(predicate: retrieveMode.predicate())) { - Label(LocalizedStringKey(retrieveMode.rawValue), systemImage: "tray") - } - } - }.listStyle(SidebarListStyle()) - } - Divider() - Section { - List { - Button(action: { - Router.shared.load(.registration) - }, label: { - Label("Account", systemImage: "person") - }) - }.listStyle(SidebarListStyle()) - } - } -} - -struct SidebarView_Previews: PreviewProvider { - static var previews: some View { - SidebarView() - } -} diff --git a/macOS/Info.plist b/macOS/Info.plist index 1a29f0a..8b13789 100644 --- a/macOS/Info.plist +++ b/macOS/Info.plist @@ -1,26 +1 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 6.2.1 - CFBundleVersion - 319 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - - + diff --git a/macOS/Lib/AppState.swift b/macOS/Lib/AppState.swift deleted file mode 100644 index 3e3b4c0..0000000 --- a/macOS/Lib/AppState.swift +++ /dev/null @@ -1,39 +0,0 @@ -import Combine -import Foundation - -class AppState: NSObject, ObservableObject { - static var shared = AppState() - - @Published var registred: Bool = false { - didSet { - WallabagUserDefaults.registred = registred - } - } - - @Injector var session: WallabagSession - @Injector var router: Router - - override init() { - super.init() - registred = WallabagUserDefaults.registred - } - - func initSession() { - if registred { - logger.info("App state request session") - session.requestSession( - clientId: WallabagUserDefaults.clientId, - clientSecret: WallabagUserDefaults.clientSecret, - username: WallabagUserDefaults.login, - password: WallabagUserDefaults.password - ) - } - } - - func logout() { - logger.debug("Logout called") - registred = false - session.state = .unknown - router.load(.registration) - } -} diff --git a/macOS/Lib/DependencyInjection.swift b/macOS/Lib/DependencyInjection.swift deleted file mode 100644 index 14e9f72..0000000 --- a/macOS/Lib/DependencyInjection.swift +++ /dev/null @@ -1,30 +0,0 @@ -import Foundation -import Swinject -import WallabagKit - -final class DependencyInjection { - static let container: Container = { - let container = Container() - - container.register(WallabagKit.self, factory: { _ in - let kit = WallabagKit(host: WallabagUserDefaults.host) - kit.clientId = WallabagUserDefaults.clientId - kit.clientSecret = WallabagUserDefaults.clientSecret - kit.username = WallabagUserDefaults.login - kit.password = WallabagUserDefaults.password - kit.accessToken = WallabagUserDefaults.accessToken - kit.refreshToken = WallabagUserDefaults.refreshToken - - return kit - }).inObjectScope(.container) - container.register(WallabagSession.self, factory: { _ in WallabagSession() }).inObjectScope(.container) - /* container.register(AppSync.self, factory: { _ in AppSync.shared }).inObjectScope(.container) - container.register(ArticlePlayer.self) { _ in ArticlePlayer() }.inObjectScope(.container) - container.register(ImageDownloader.self, factory: { _ in ImageDownloader.shared }).inObjectScope(.container) - container.register(AppState.self, factory: { _ in AppState.shared }).inObjectScope(.container) */ - container.register(Router.self, factory: { _ in Router.shared }).inObjectScope(.container) - // container.register(PlayerPublisher.self, factory: { _ in PlayerPublisher.shared }).inObjectScope(.container) - - return container - }() -} diff --git a/macOS/macOS.entitlements b/macOS/macOS.entitlements deleted file mode 100644 index f2ef3ae..0000000 --- a/macOS/macOS.entitlements +++ /dev/null @@ -1,10 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - - - diff --git a/macOS/wallabagMacApp.swift b/macOS/wallabagMacApp.swift deleted file mode 100644 index 52fde1c..0000000 --- a/macOS/wallabagMacApp.swift +++ /dev/null @@ -1,20 +0,0 @@ -import os -import SwiftUI - -let logger = Logger(subsystem: "fr.district-web.wallabag", category: "main") - -@main -struct WallabagMacApp: App { - @StateObject var appState = AppState.shared - - var body: some Scene { - WindowGroup { - NavigationView { - SidebarView() - List {} - RouterView() - }.environment(\.managedObjectContext, CoreData.shared.viewContext) - .environmentObject(Router.shared) - } - } -} diff --git a/wallabag.entitlements b/wallabag.entitlements index 1a278d4..7e6b603 100644 --- a/wallabag.entitlements +++ b/wallabag.entitlements @@ -2,9 +2,13 @@ + com.apple.security.app-sandbox + com.apple.security.application-groups group.wallabag.share_extension + com.apple.security.network.client + diff --git a/wallabag.xcodeproj/project.pbxproj b/wallabag.xcodeproj/project.pbxproj index 26be8be..ba92a27 100644 --- a/wallabag.xcodeproj/project.pbxproj +++ b/wallabag.xcodeproj/project.pbxproj @@ -3,55 +3,29 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 0916CD7C25F0D1F1000DC311 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0916CD7B25F0D1F1000DC311 /* Menu.swift */; }; - 0916CD8825F0D450000DC311 /* EntriesListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644C5B25C98596000FFDA1 /* EntriesListView.swift */; }; - 0916CD8E25F0D47A000DC311 /* EntryRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644C5925C98596000FFDA1 /* EntryRowView.swift */; }; - 0916CDB625F0D5D6000DC311 /* HTMLEntities in Frameworks */ = {isa = PBXBuildFile; productRef = 0916CDB525F0D5D6000DC311 /* HTMLEntities */; }; - 0916CDBC25F0E04D000DC311 /* wallabagStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 09644D1E25C98782000FFDA1 /* wallabagStore.xcdatamodeld */; }; - 0916CDE725F0E54C000DC311 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0916CDE625F0E54C000DC311 /* RegistrationView.swift */; }; - 0916CDF725F0E5BD000DC311 /* RouterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B8625C98176000FFDA1 /* RouterView.swift */; }; 093D139F26263B05008C2150 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 093D139E26263B05008C2150 /* Intents.framework */; }; 093D13A226263B05008C2150 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093D13A126263B05008C2150 /* IntentHandler.swift */; }; - 093D13B626263B05008C2150 /* Shortcuts.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 093D139D26263B05008C2150 /* Shortcuts.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 093D13B626263B05008C2150 /* Shortcuts.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 093D139D26263B05008C2150 /* Shortcuts.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 093D13D826263CC4008C2150 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 093D13D726263CC4008C2150 /* Intents.intentdefinition */; }; 093D13EC26263F81008C2150 /* AddEntryIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093D13EB26263F81008C2150 /* AddEntryIntentHandler.swift */; }; - 093D13F3262640B7008C2150 /* WallabagUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B1E25C94D9C000FFDA1 /* WallabagUserDefaults.swift */; }; - 093D13FA262640C0008C2150 /* Setting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B2625C94DD2000FFDA1 /* Setting.swift */; }; - 093D13FB262640C0008C2150 /* Password.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3225C94DEB000FFDA1 /* Password.swift */; }; - 093D13FC262640C0008C2150 /* GeneralSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B4125C94E2B000FFDA1 /* GeneralSetting.swift */; }; - 093D1403262640C9008C2150 /* KeychainPasswordItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3925C94E03000FFDA1 /* KeychainPasswordItem.swift */; }; - 093D14BA26264D62008C2150 /* SharedLib in Frameworks */ = {isa = PBXBuildFile; productRef = 093D14B926264D62008C2150 /* SharedLib */; }; - 09483CC7270498C20084CEB2 /* SharedLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09483CC6270498C20084CEB2 /* SharedLib.framework */; }; - 09483CC8270498C20084CEB2 /* SharedLib.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09483CC6270498C20084CEB2 /* SharedLib.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 09483CCD270499120084CEB2 /* WallabagKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09483CCC270499120084CEB2 /* WallabagKit.framework */; }; - 09483CCE270499120084CEB2 /* WallabagKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09483CCC270499120084CEB2 /* WallabagKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 09483CD027049B3E0084CEB2 /* WallabagKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09483CCF27049B3E0084CEB2 /* WallabagKit.framework */; }; - 09483CD427049B5F0084CEB2 /* WallabagKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09483CD327049B5F0084CEB2 /* WallabagKit.framework */; }; 094AA03E2629EB1F006E5605 /* wallabagTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094AA03D2629EB1F006E5605 /* wallabagTests.swift */; }; 094AA05A2629EB60006E5605 /* ImageCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094A9FED2629E6BB006E5605 /* ImageCacheTests.swift */; }; 094AA0692629EB98006E5605 /* ImageDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094AA00F2629E739006E5605 /* ImageDownloaderTests.swift */; }; + 0951C61829CC2EB000D8E8C6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0951C61729CC2EB000D8E8C6 /* Assets.xcassets */; }; 09564E0D2851C57200D39E95 /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09564E0C2851C57200D39E95 /* SettingView.swift */; }; 09644AD125C94825000FFDA1 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644AD025C94825000FFDA1 /* ShareViewController.swift */; }; 09644AD425C94825000FFDA1 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 09644AD225C94825000FFDA1 /* MainInterface.storyboard */; }; - 09644AD825C94825000FFDA1 /* bagit.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 09644ACE25C94825000FFDA1 /* bagit.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 09644AD825C94825000FFDA1 /* bagit.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 09644ACE25C94825000FFDA1 /* bagit.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 09644AE325C94863000FFDA1 /* ShareExtensionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644AE225C94863000FFDA1 /* ShareExtensionError.swift */; }; 09644AEA25C94879000FFDA1 /* ExtensionClass.js in Resources */ = {isa = PBXBuildFile; fileRef = 09644AE925C94879000FFDA1 /* ExtensionClass.js */; }; - 09644AF725C94982000FFDA1 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 09644AF625C94982000FFDA1 /* Media.xcassets */; }; - 09644B0725C94C14000FFDA1 /* Swinject in Frameworks */ = {isa = PBXBuildFile; productRef = 09644B0625C94C14000FFDA1 /* Swinject */; }; 09644B0F25C94C6B000FFDA1 /* HTMLEntities in Frameworks */ = {isa = PBXBuildFile; productRef = 09644B0E25C94C6B000FFDA1 /* HTMLEntities */; }; - 09644B1F25C94D9C000FFDA1 /* WallabagUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B1E25C94D9C000FFDA1 /* WallabagUserDefaults.swift */; }; - 09644B2725C94DD2000FFDA1 /* Setting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B2625C94DD2000FFDA1 /* Setting.swift */; }; - 09644B3325C94DEB000FFDA1 /* Password.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3225C94DEB000FFDA1 /* Password.swift */; }; - 09644B3A25C94E03000FFDA1 /* KeychainPasswordItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3925C94E03000FFDA1 /* KeychainPasswordItem.swift */; }; - 09644B4225C94E2B000FFDA1 /* GeneralSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B4125C94E2B000FFDA1 /* GeneralSetting.swift */; }; 09644B5725C9810A000FFDA1 /* WallabagApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B5625C9810A000FFDA1 /* WallabagApp.swift */; }; 09644B5E25C98116000FFDA1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B5D25C98116000FFDA1 /* AppDelegate.swift */; }; 09644B7E25C98152000FFDA1 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B7D25C98152000FFDA1 /* AppState.swift */; }; - 09644B8A25C98176000FFDA1 /* RouterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B8625C98176000FFDA1 /* RouterView.swift */; }; 09644B8C25C98176000FFDA1 /* Route.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B8825C98176000FFDA1 /* Route.swift */; }; 09644B9725C9819F000FFDA1 /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B9425C9819F000FFDA1 /* PlayerView.swift */; }; 09644B9825C9819F000FFDA1 /* PlayerPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B9525C9819F000FFDA1 /* PlayerPublisher.swift */; }; @@ -61,16 +35,10 @@ 09644BAE25C98213000FFDA1 /* AppSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BAB25C98213000FFDA1 /* AppSync.swift */; }; 09644BAF25C98213000FFDA1 /* RefreshButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BAC25C98213000FFDA1 /* RefreshButton.swift */; }; 09644BB725C98232000FFDA1 /* AppSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BB625C98232000FFDA1 /* AppSetting.swift */; }; - 09644BBD25C98240000FFDA1 /* WallabagUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B1E25C94D9C000FFDA1 /* WallabagUserDefaults.swift */; }; - 09644BC325C98248000FFDA1 /* GeneralSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B4125C94E2B000FFDA1 /* GeneralSetting.swift */; }; - 09644BC425C98248000FFDA1 /* Setting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B2625C94DD2000FFDA1 /* Setting.swift */; }; - 09644BC525C98248000FFDA1 /* Password.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3225C94DEB000FFDA1 /* Password.swift */; }; - 09644BCB25C98252000FFDA1 /* KeychainPasswordItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3925C94E03000FFDA1 /* KeychainPasswordItem.swift */; }; 09644BD825C9833E000FFDA1 /* DependencyInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BD125C9833D000FFDA1 /* DependencyInjection.swift */; }; 09644BDA25C9833E000FFDA1 /* WallabagError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BD325C9833D000FFDA1 /* WallabagError.swift */; }; 09644BDD25C9833E000FFDA1 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BD625C9833E000FFDA1 /* CoreData.swift */; }; 09644BDE25C9833E000FFDA1 /* WallabagSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BD725C9833E000FFDA1 /* WallabagSession.swift */; }; - 09644BE625C98350000FFDA1 /* Injector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BE525C98350000FFDA1 /* Injector.swift */; }; 09644BFA25C983F8000FFDA1 /* Podcast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BF725C983F8000FFDA1 /* Podcast.swift */; }; 09644BFB25C983F8000FFDA1 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BF825C983F8000FFDA1 /* Tag.swift */; }; 09644BFC25C983F8000FFDA1 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BF925C983F8000FFDA1 /* Entry.swift */; }; @@ -95,8 +63,6 @@ 09644C9E25C98615000FFDA1 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644C9D25C98615000FFDA1 /* MainView.swift */; }; 09644CA725C98639000FFDA1 /* View+haptic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CA625C98639000FFDA1 /* View+haptic.swift */; }; 09644CAF25C98648000FFDA1 /* HapticNotificationButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CAE25C98648000FFDA1 /* HapticNotificationButtonStyle.swift */; }; - 09644CB825C98660000FFDA1 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CB625C98660000FFDA1 /* Menu.swift */; }; - 09644CB925C98660000FFDA1 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CB725C98660000FFDA1 /* MenuView.swift */; }; 09644CC225C98674000FFDA1 /* PasteBoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CC025C98674000FFDA1 /* PasteBoardView.swift */; }; 09644CC325C98674000FFDA1 /* PasteBoardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CC125C98674000FFDA1 /* PasteBoardViewModel.swift */; }; 09644CCB25C9869D000FFDA1 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644CCA25C9869D000FFDA1 /* RegistrationView.swift */; }; @@ -116,37 +82,23 @@ 09644D1025C9872F000FFDA1 /* BundleKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644D0F25C9872F000FFDA1 /* BundleKey.swift */; }; 09644D1825C98755000FFDA1 /* AppDelegateExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644D1725C98755000FFDA1 /* AppDelegateExtension.swift */; }; 09644D2025C98782000FFDA1 /* wallabagStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 09644D1E25C98782000FFDA1 /* wallabagStore.xcdatamodeld */; }; - 097F818525CAEA79006C85F6 /* wallabagMacApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F818425CAEA79006C85F6 /* wallabagMacApp.swift */; }; - 097F819D25CAF9FE006C85F6 /* SidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F819C25CAF9FE006C85F6 /* SidebarView.swift */; }; - 097F81AA25CB1108006C85F6 /* Route.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F81A925CB1108006C85F6 /* Route.swift */; }; 097F81EB25CB18BA006C85F6 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F81DF25CB187B006C85F6 /* Router.swift */; }; - 097F81F225CB1996006C85F6 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F81F125CB1996006C85F6 /* Router.swift */; }; - 097F81FA25CB19F6006C85F6 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F81F925CB19F6006C85F6 /* AppState.swift */; }; - 097F820025CB1A04006C85F6 /* WallabagUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B1E25C94D9C000FFDA1 /* WallabagUserDefaults.swift */; }; - 097F820625CB1A0A006C85F6 /* Setting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B2625C94DD2000FFDA1 /* Setting.swift */; }; - 097F820C25CB1A0C006C85F6 /* Password.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3225C94DEB000FFDA1 /* Password.swift */; }; - 097F821225CB1A0F006C85F6 /* GeneralSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B4125C94E2B000FFDA1 /* GeneralSetting.swift */; }; - 097F821825CB1A16006C85F6 /* KeychainPasswordItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B3925C94E03000FFDA1 /* KeychainPasswordItem.swift */; }; - 097F821E25CB1A4C006C85F6 /* WallabagSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BD725C9833E000FFDA1 /* WallabagSession.swift */; }; - 097F822C25CB1A93006C85F6 /* Injector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BE525C98350000FFDA1 /* Injector.swift */; }; - 097F823325CB1A9A006C85F6 /* Swinject in Frameworks */ = {isa = PBXBuildFile; productRef = 097F823225CB1A9A006C85F6 /* Swinject */; }; - 097F823925CB1AB1006C85F6 /* CoreDataViewContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644C4E25C9850D000FFDA1 /* CoreDataViewContext.swift */; }; - 097F823F25CB1ABB006C85F6 /* CoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BD625C9833E000FFDA1 /* CoreData.swift */; }; - 097F824625CB1ADF006C85F6 /* DependencyInjection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F824525CB1ADF006C85F6 /* DependencyInjection.swift */; }; - 097F825225CB1B2E006C85F6 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BF925C983F8000FFDA1 /* Entry.swift */; }; - 097F825825CB1B33006C85F6 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644BF825C983F8000FFDA1 /* Tag.swift */; }; + 09800D8D29B9DE9E00DAB403 /* SharedLib in Frameworks */ = {isa = PBXBuildFile; productRef = 09800D8C29B9DE9E00DAB403 /* SharedLib */; }; + 09800D8F29B9DEFE00DAB403 /* SharedLib in Frameworks */ = {isa = PBXBuildFile; productRef = 09800D8E29B9DEFE00DAB403 /* SharedLib */; }; + 098BDD0829BF04E3003DF719 /* RouteSwiftUIExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098BDD0729BF04E3003DF719 /* RouteSwiftUIExtension.swift */; }; + 098CF4D629CD830E00DEAE50 /* ServerViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098CF4D529CD830E00DEAE50 /* ServerViewModelTests.swift */; }; 09AD75A12624F93D00708A1E /* article.html in Resources */ = {isa = PBXBuildFile; fileRef = 09AD759D2624F93D00708A1E /* article.html */; }; 09AD75A22624F93D00708A1E /* main.css in Resources */ = {isa = PBXBuildFile; fileRef = 09AD759E2624F93D00708A1E /* main.css */; }; 09AD75A32624F93D00708A1E /* ratatouille.css in Resources */ = {isa = PBXBuildFile; fileRef = 09AD759F2624F93D00708A1E /* ratatouille.css */; }; 09AD75A42624F93D00708A1E /* justify.css in Resources */ = {isa = PBXBuildFile; fileRef = 09AD75A02624F93D00708A1E /* justify.css */; }; 09AD75BE2624FEEE00708A1E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 09AD75C02624FEEE00708A1E /* Localizable.strings */; }; + 09AE6ECC29B13AAE0025DF93 /* WallabagKit in Frameworks */ = {isa = PBXBuildFile; productRef = 09AE6ECB29B13AAE0025DF93 /* WallabagKit */; }; + 09AE6ECE29B13ABC0025DF93 /* WallabagKit in Frameworks */ = {isa = PBXBuildFile; productRef = 09AE6ECD29B13ABC0025DF93 /* WallabagKit */; }; + 09AEBEA029B1D2C500050BBE /* Factory in Frameworks */ = {isa = PBXBuildFile; productRef = 09AEBE9F29B1D2C500050BBE /* Factory */; }; 09BCBBD4282BD46A00B234CB /* RouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BCBBD3282BD46A00B234CB /* RouterTests.swift */; }; - 09BFB29925C8348E00E12B4D /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BFB29825C8348E00E12B4D /* Tests_iOS.swift */; }; - 09BFB2A425C8348E00E12B4D /* Tests_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BFB2A325C8348E00E12B4D /* Tests_macOS.swift */; }; - 09BFB2A625C8348E00E12B4D /* wallabag.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 09BFB27A25C8348E00E12B4D /* wallabag.xcdatamodeld */; }; - 09BFB2A725C8348E00E12B4D /* wallabag.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 09BFB27A25C8348E00E12B4D /* wallabag.xcdatamodeld */; }; - 09BFB2AE25C8348E00E12B4D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 09BFB27F25C8348E00E12B4D /* Assets.xcassets */; }; - 09BFB2AF25C8348E00E12B4D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 09BFB27F25C8348E00E12B4D /* Assets.xcassets */; }; + 09BE0AF42A9F45E900193FBF /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BE0AF32A9F45E900193FBF /* View+Extension.swift */; }; + 09C34C7C29B1398B00B5C927 /* SharedLib in Frameworks */ = {isa = PBXBuildFile; productRef = 09C34C7B29B1398B00B5C927 /* SharedLib */; }; + 09C34C7E29B1399100B5C927 /* WallabagKit in Frameworks */ = {isa = PBXBuildFile; productRef = 09C34C7D29B1399100B5C927 /* WallabagKit */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -171,52 +123,24 @@ remoteGlobalIDString = 09644ACD25C94825000FFDA1; remoteInfo = bagit; }; - 09BFB29525C8348E00E12B4D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 09BFB27525C8348E00E12B4D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 09BFB28325C8348E00E12B4D; - remoteInfo = "wallabag (iOS)"; - }; - 09BFB2A025C8348E00E12B4D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 09BFB27525C8348E00E12B4D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 09BFB28B25C8348E00E12B4D; - remoteInfo = "wallabag (macOS)"; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 09483CC9270498C20084CEB2 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 09483CCE270499120084CEB2 /* WallabagKit.framework in Embed Frameworks */, - 09483CC8270498C20084CEB2 /* SharedLib.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; - 09644AD925C94825000FFDA1 /* Embed App Extensions */ = { + 09644AD925C94825000FFDA1 /* Embed Foundation Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( - 09644AD825C94825000FFDA1 /* bagit.appex in Embed App Extensions */, - 093D13B626263B05008C2150 /* Shortcuts.appex in Embed App Extensions */, + 09644AD825C94825000FFDA1 /* bagit.appex in Embed Foundation Extensions */, + 093D13B626263B05008C2150 /* Shortcuts.appex in Embed Foundation Extensions */, ); - name = "Embed App Extensions"; + name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0916CD7B25F0D1F1000DC311 /* Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = ""; }; - 0916CDE625F0E54C000DC311 /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = ""; }; 093D137226263A96008C2150 /* IntentsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IntentsUI.framework; path = Library/Frameworks/IntentsUI.framework; sourceTree = DEVELOPER_DIR; }; 093D139D26263B05008C2150 /* Shortcuts.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Shortcuts.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 093D139E26263B05008C2150 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; @@ -234,6 +158,7 @@ 094AA03B2629EB1F006E5605 /* wallabagTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = wallabagTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 094AA03D2629EB1F006E5605 /* wallabagTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = wallabagTests.swift; sourceTree = ""; }; 094AA03F2629EB1F006E5605 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0951C61729CC2EB000D8E8C6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 09564E0C2851C57200D39E95 /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = ""; }; 09644ACE25C94825000FFDA1 /* bagit.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = bagit.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 09644AD025C94825000FFDA1 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; @@ -242,16 +167,9 @@ 09644AE225C94863000FFDA1 /* ShareExtensionError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionError.swift; sourceTree = ""; }; 09644AE925C94879000FFDA1 /* ExtensionClass.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = ExtensionClass.js; sourceTree = ""; }; 09644AF025C9494D000FFDA1 /* bagit.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = bagit.entitlements; sourceTree = ""; }; - 09644AF625C94982000FFDA1 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; - 09644B1E25C94D9C000FFDA1 /* WallabagUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallabagUserDefaults.swift; sourceTree = ""; }; - 09644B2625C94DD2000FFDA1 /* Setting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Setting.swift; sourceTree = ""; }; - 09644B3225C94DEB000FFDA1 /* Password.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Password.swift; sourceTree = ""; }; - 09644B3925C94E03000FFDA1 /* KeychainPasswordItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainPasswordItem.swift; sourceTree = ""; }; - 09644B4125C94E2B000FFDA1 /* GeneralSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSetting.swift; sourceTree = ""; }; 09644B5625C9810A000FFDA1 /* WallabagApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WallabagApp.swift; sourceTree = ""; }; 09644B5D25C98116000FFDA1 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 09644B7D25C98152000FFDA1 /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; - 09644B8625C98176000FFDA1 /* RouterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouterView.swift; sourceTree = ""; }; 09644B8825C98176000FFDA1 /* Route.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Route.swift; sourceTree = ""; }; 09644B9425C9819F000FFDA1 /* PlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = ""; }; 09644B9525C9819F000FFDA1 /* PlayerPublisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerPublisher.swift; sourceTree = ""; }; @@ -265,7 +183,6 @@ 09644BD325C9833D000FFDA1 /* WallabagError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WallabagError.swift; sourceTree = ""; }; 09644BD625C9833E000FFDA1 /* CoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreData.swift; sourceTree = ""; }; 09644BD725C9833E000FFDA1 /* WallabagSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WallabagSession.swift; sourceTree = ""; }; - 09644BE525C98350000FFDA1 /* Injector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Injector.swift; sourceTree = ""; }; 09644BF725C983F8000FFDA1 /* Podcast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Podcast.swift; sourceTree = ""; }; 09644BF825C983F8000FFDA1 /* Tag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; 09644BF925C983F8000FFDA1 /* Entry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Entry.swift; sourceTree = ""; }; @@ -290,8 +207,6 @@ 09644C9D25C98615000FFDA1 /* MainView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; }; 09644CA625C98639000FFDA1 /* View+haptic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+haptic.swift"; sourceTree = ""; }; 09644CAE25C98648000FFDA1 /* HapticNotificationButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HapticNotificationButtonStyle.swift; sourceTree = ""; }; - 09644CB625C98660000FFDA1 /* Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = ""; }; - 09644CB725C98660000FFDA1 /* MenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = ""; }; 09644CC025C98674000FFDA1 /* PasteBoardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasteBoardView.swift; sourceTree = ""; }; 09644CC125C98674000FFDA1 /* PasteBoardViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasteBoardViewModel.swift; sourceTree = ""; }; 09644CCA25C9869D000FFDA1 /* RegistrationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = ""; }; @@ -311,13 +226,9 @@ 09644D0F25C9872F000FFDA1 /* BundleKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BundleKey.swift; sourceTree = ""; }; 09644D1725C98755000FFDA1 /* AppDelegateExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegateExtension.swift; sourceTree = ""; }; 09644D1F25C98782000FFDA1 /* wallabagStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = wallabagStore.xcdatamodel; sourceTree = ""; }; - 097F818425CAEA79006C85F6 /* wallabagMacApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = wallabagMacApp.swift; sourceTree = ""; }; - 097F819C25CAF9FE006C85F6 /* SidebarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarView.swift; sourceTree = ""; }; - 097F81A925CB1108006C85F6 /* Route.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Route.swift; sourceTree = ""; }; 097F81DF25CB187B006C85F6 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; - 097F81F125CB1996006C85F6 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; - 097F81F925CB19F6006C85F6 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; - 097F824525CB1ADF006C85F6 /* DependencyInjection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyInjection.swift; sourceTree = ""; }; + 098BDD0729BF04E3003DF719 /* RouteSwiftUIExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouteSwiftUIExtension.swift; sourceTree = ""; }; + 098CF4D529CD830E00DEAE50 /* ServerViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerViewModelTests.swift; sourceTree = ""; }; 09AD75962624F4E800708A1E /* wallabag.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = wallabag.entitlements; sourceTree = ""; }; 09AD759D2624F93D00708A1E /* article.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = article.html; sourceTree = ""; }; 09AD759E2624F93D00708A1E /* main.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = main.css; sourceTree = ""; }; @@ -336,19 +247,9 @@ 09AD75D42624FF5F00708A1E /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; 09AD75D52624FF6900708A1E /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; 09BCBBD3282BD46A00B234CB /* RouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterTests.swift; sourceTree = ""; }; - 09BFB27B25C8348E00E12B4D /* Shared.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Shared.xcdatamodel; sourceTree = ""; }; - 09BFB27F25C8348E00E12B4D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 09BE0AF32A9F45E900193FBF /* View+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extension.swift"; sourceTree = ""; }; 09BFB28425C8348E00E12B4D /* wallabag.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = wallabag.app; sourceTree = BUILT_PRODUCTS_DIR; }; 09BFB28725C8348E00E12B4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 09BFB28C25C8348E00E12B4D /* wallabag.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = wallabag.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 09BFB28E25C8348E00E12B4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 09BFB28F25C8348E00E12B4D /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; }; - 09BFB29425C8348E00E12B4D /* Tests iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 09BFB29825C8348E00E12B4D /* Tests_iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_iOS.swift; sourceTree = ""; }; - 09BFB29A25C8348E00E12B4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 09BFB29F25C8348E00E12B4D /* Tests macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 09BFB2A325C8348E00E12B4D /* Tests_macOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_macOS.swift; sourceTree = ""; }; - 09BFB2A525C8348E00E12B4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9C1103B626A0852F00E50F26 /* Configuration.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Configuration.storekit; sourceTree = ""; }; /* End PBXFileReference section */ @@ -357,8 +258,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 09483CD027049B3E0084CEB2 /* WallabagKit.framework in Frameworks */, + 09AE6ECE29B13ABC0025DF93 /* WallabagKit in Frameworks */, 093D139F26263B05008C2150 /* Intents.framework in Frameworks */, + 09800D8D29B9DE9E00DAB403 /* SharedLib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -373,7 +275,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 09483CD427049B5F0084CEB2 /* WallabagKit.framework in Frameworks */, + 09AE6ECC29B13AAE0025DF93 /* WallabagKit in Frameworks */, + 09800D8F29B9DEFE00DAB403 /* SharedLib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -381,56 +284,16 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 09483CCD270499120084CEB2 /* WallabagKit.framework in Frameworks */, - 09644B0725C94C14000FFDA1 /* Swinject in Frameworks */, - 09483CC7270498C20084CEB2 /* SharedLib.framework in Frameworks */, + 09AEBEA029B1D2C500050BBE /* Factory in Frameworks */, 09644B0F25C94C6B000FFDA1 /* HTMLEntities in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB28925C8348E00E12B4D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 097F823325CB1A9A006C85F6 /* Swinject in Frameworks */, - 0916CDB625F0D5D6000DC311 /* HTMLEntities in Frameworks */, - 093D14BA26264D62008C2150 /* SharedLib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB29125C8348E00E12B4D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB29C25C8348E00E12B4D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( + 09C34C7E29B1399100B5C927 /* WallabagKit in Frameworks */, + 09C34C7C29B1398B00B5C927 /* SharedLib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0916CDE525F0E524000DC311 /* Registration */ = { - isa = PBXGroup; - children = ( - 0916CDE625F0E54C000DC311 /* RegistrationView.swift */, - ); - path = Registration; - sourceTree = ""; - }; - 0916CDF625F0E5B6000DC311 /* Router */ = { - isa = PBXGroup; - children = ( - 09644B8625C98176000FFDA1 /* RouterView.swift */, - ); - path = Router; - sourceTree = ""; - }; 093D13A026263B05008C2150 /* Shortcuts */ = { isa = PBXGroup; children = ( @@ -446,6 +309,7 @@ 094A9FEC2629E6A3006E5605 /* Features */ = { isa = PBXGroup; children = ( + 098CF4D329CD82F100DEAE50 /* Registration */, 09BCBBD2282BD44100B234CB /* Router */, 094AA0012629E700006E5605 /* Entry */, ); @@ -482,7 +346,6 @@ 09644ACF25C94825000FFDA1 /* bagit */ = { isa = PBXGroup; children = ( - 09644AF625C94982000FFDA1 /* Media.xcassets */, 09644AF025C9494D000FFDA1 /* bagit.entitlements */, 09644AD025C94825000FFDA1 /* ShareViewController.swift */, 09644AD225C94825000FFDA1 /* MainInterface.storyboard */, @@ -506,32 +369,11 @@ name = Frameworks; sourceTree = ""; }; - 09644B1D25C94D71000FFDA1 /* Lib */ = { - isa = PBXGroup; - children = ( - 09644BD725C9833E000FFDA1 /* WallabagSession.swift */, - 09644B1E25C94D9C000FFDA1 /* WallabagUserDefaults.swift */, - 09644B3925C94E03000FFDA1 /* KeychainPasswordItem.swift */, - 09644BD625C9833E000FFDA1 /* CoreData.swift */, - ); - path = Lib; - sourceTree = ""; - }; - 09644B2525C94DB5000FFDA1 /* PropertyWrapper */ = { - isa = PBXGroup; - children = ( - 09644B2625C94DD2000FFDA1 /* Setting.swift */, - 09644B3225C94DEB000FFDA1 /* Password.swift */, - 09644B4125C94E2B000FFDA1 /* GeneralSetting.swift */, - 09644BE525C98350000FFDA1 /* Injector.swift */, - 09644C4E25C9850D000FFDA1 /* CoreDataViewContext.swift */, - ); - path = PropertyWrapper; - sourceTree = ""; - }; 09644B7C25C9814C000FFDA1 /* Lib */ = { isa = PBXGroup; children = ( + 09644BD725C9833E000FFDA1 /* WallabagSession.swift */, + 09644BD625C9833E000FFDA1 /* CoreData.swift */, 09644B7D25C98152000FFDA1 /* AppState.swift */, 09644BD125C9833D000FFDA1 /* DependencyInjection.swift */, 09644BD325C9833D000FFDA1 /* WallabagError.swift */, @@ -548,7 +390,6 @@ 09644C5525C9858B000FFDA1 /* Entry */, 09644B9F25C981A9000FFDA1 /* Error */, 09644CA425C98626000FFDA1 /* Haptic */, - 09644CB525C98653000FFDA1 /* Menu */, 09644CBF25C98668000FFDA1 /* PasteBoard */, 09644B9325C98191000FFDA1 /* Player */, 097F827D25CB1C12006C85F6 /* Registration */, @@ -567,6 +408,7 @@ children = ( 09644B8825C98176000FFDA1 /* Route.swift */, 097F81DF25CB187B006C85F6 /* Router.swift */, + 098BDD0729BF04E3003DF719 /* RouteSwiftUIExtension.swift */, ); path = Router; sourceTree = ""; @@ -611,6 +453,7 @@ 09644BE425C98343000FFDA1 /* PropertyWrapper */ = { isa = PBXGroup; children = ( + 09644C4E25C9850D000FFDA1 /* CoreDataViewContext.swift */, 09644D0F25C9872F000FFDA1 /* BundleKey.swift */, ); path = PropertyWrapper; @@ -695,15 +538,6 @@ path = ButtonStyle; sourceTree = ""; }; - 09644CB525C98653000FFDA1 /* Menu */ = { - isa = PBXGroup; - children = ( - 09644CB625C98660000FFDA1 /* Menu.swift */, - 09644CB725C98660000FFDA1 /* MenuView.swift */, - ); - path = Menu; - sourceTree = ""; - }; 09644CBF25C98668000FFDA1 /* PasteBoard */ = { isa = PBXGroup; children = ( @@ -771,48 +605,12 @@ 09644D1625C9874D000FFDA1 /* Extension */ = { isa = PBXGroup; children = ( + 09BE0AF22A9F45D200193FBF /* SwiftUI */, 09644D1725C98755000FFDA1 /* AppDelegateExtension.swift */, ); path = Extension; sourceTree = ""; }; - 097F819525CAEBB9006C85F6 /* Features */ = { - isa = PBXGroup; - children = ( - 0916CDE525F0E524000DC311 /* Registration */, - 097F81A825CB10F4006C85F6 /* Router */, - 097F819B25CAF9C2006C85F6 /* Sidebar */, - ); - path = Features; - sourceTree = ""; - }; - 097F819B25CAF9C2006C85F6 /* Sidebar */ = { - isa = PBXGroup; - children = ( - 097F819C25CAF9FE006C85F6 /* SidebarView.swift */, - 0916CD7B25F0D1F1000DC311 /* Menu.swift */, - ); - path = Sidebar; - sourceTree = ""; - }; - 097F81A825CB10F4006C85F6 /* Router */ = { - isa = PBXGroup; - children = ( - 097F81A925CB1108006C85F6 /* Route.swift */, - 097F81F125CB1996006C85F6 /* Router.swift */, - ); - path = Router; - sourceTree = ""; - }; - 097F81F825CB19ED006C85F6 /* Lib */ = { - isa = PBXGroup; - children = ( - 097F81F925CB19F6006C85F6 /* AppState.swift */, - 097F824525CB1ADF006C85F6 /* DependencyInjection.swift */, - ); - path = Lib; - sourceTree = ""; - }; 097F824C25CB1B17006C85F6 /* Entity */ = { isa = PBXGroup; children = ( @@ -823,14 +621,6 @@ path = Entity; sourceTree = ""; }; - 097F827C25CB1C06006C85F6 /* Features */ = { - isa = PBXGroup; - children = ( - 0916CDF625F0E5B6000DC311 /* Router */, - ); - path = Features; - sourceTree = ""; - }; 097F827D25CB1C12006C85F6 /* Registration */ = { isa = PBXGroup; children = ( @@ -842,6 +632,22 @@ path = Registration; sourceTree = ""; }; + 098CF4D329CD82F100DEAE50 /* Registration */ = { + isa = PBXGroup; + children = ( + 098CF4D429CD82FA00DEAE50 /* Server */, + ); + path = Registration; + sourceTree = ""; + }; + 098CF4D429CD82FA00DEAE50 /* Server */ = { + isa = PBXGroup; + children = ( + 098CF4D529CD830E00DEAE50 /* ServerViewModelTests.swift */, + ); + path = Server; + sourceTree = ""; + }; 09AD759C2624F93D00708A1E /* html-ressources */ = { isa = PBXGroup; children = ( @@ -861,43 +667,31 @@ path = Router; sourceTree = ""; }; + 09BE0AF22A9F45D200193FBF /* SwiftUI */ = { + isa = PBXGroup; + children = ( + 09BE0AF32A9F45E900193FBF /* View+Extension.swift */, + ); + path = SwiftUI; + sourceTree = ""; + }; 09BFB27425C8348E00E12B4D = { isa = PBXGroup; children = ( 09AD75962624F4E800708A1E /* wallabag.entitlements */, 09644ACF25C94825000FFDA1 /* bagit */, 09644B1525C94CA6000FFDA1 /* Frameworks */, - 09BFB28625C8348E00E12B4D /* iOS */, - 09BFB28D25C8348E00E12B4D /* macOS */, + 09BFB28625C8348E00E12B4D /* App */, 09BFB28525C8348E00E12B4D /* Products */, - 09BFB27925C8348E00E12B4D /* Shared */, 093D13A026263B05008C2150 /* Shortcuts */, - 09BFB29725C8348E00E12B4D /* Tests iOS */, - 09BFB2A225C8348E00E12B4D /* Tests macOS */, 094AA03C2629EB1F006E5605 /* wallabagTests */, ); sourceTree = ""; }; - 09BFB27925C8348E00E12B4D /* Shared */ = { - isa = PBXGroup; - children = ( - 097F827C25CB1C06006C85F6 /* Features */, - 09BFB27F25C8348E00E12B4D /* Assets.xcassets */, - 097F824C25CB1B17006C85F6 /* Entity */, - 09644B1D25C94D71000FFDA1 /* Lib */, - 09644B2525C94DB5000FFDA1 /* PropertyWrapper */, - 09BFB27A25C8348E00E12B4D /* wallabag.xcdatamodeld */, - ); - path = Shared; - sourceTree = ""; - }; 09BFB28525C8348E00E12B4D /* Products */ = { isa = PBXGroup; children = ( 09BFB28425C8348E00E12B4D /* wallabag.app */, - 09BFB28C25C8348E00E12B4D /* wallabag.app */, - 09BFB29425C8348E00E12B4D /* Tests iOS.xctest */, - 09BFB29F25C8348E00E12B4D /* Tests macOS.xctest */, 09644ACE25C94825000FFDA1 /* bagit.appex */, 093D139D26263B05008C2150 /* Shortcuts.appex */, 094AA03B2629EB1F006E5605 /* wallabagTests.xctest */, @@ -905,13 +699,14 @@ name = Products; sourceTree = ""; }; - 09BFB28625C8348E00E12B4D /* iOS */ = { + 09BFB28625C8348E00E12B4D /* App */ = { isa = PBXGroup; children = ( 09BFB28725C8348E00E12B4D /* Info.plist */, 9C1103B626A0852F00E50F26 /* Configuration.storekit */, 09644B5D25C98116000FFDA1 /* AppDelegate.swift */, 09644B5625C9810A000FFDA1 /* WallabagApp.swift */, + 097F824C25CB1B17006C85F6 /* Entity */, 09644D1625C9874D000FFDA1 /* Extension */, 09644B8425C98161000FFDA1 /* Features */, 09AD759C2624F93D00708A1E /* html-ressources */, @@ -919,38 +714,9 @@ 09AD75C02624FEEE00708A1E /* Localizable.strings */, 09644BE425C98343000FFDA1 /* PropertyWrapper */, 09644D1E25C98782000FFDA1 /* wallabagStore.xcdatamodeld */, + 0951C61729CC2EB000D8E8C6 /* Assets.xcassets */, ); - path = iOS; - sourceTree = ""; - }; - 09BFB28D25C8348E00E12B4D /* macOS */ = { - isa = PBXGroup; - children = ( - 097F81F825CB19ED006C85F6 /* Lib */, - 097F819525CAEBB9006C85F6 /* Features */, - 09BFB28E25C8348E00E12B4D /* Info.plist */, - 09BFB28F25C8348E00E12B4D /* macOS.entitlements */, - 097F818425CAEA79006C85F6 /* wallabagMacApp.swift */, - ); - path = macOS; - sourceTree = ""; - }; - 09BFB29725C8348E00E12B4D /* Tests iOS */ = { - isa = PBXGroup; - children = ( - 09BFB29825C8348E00E12B4D /* Tests_iOS.swift */, - 09BFB29A25C8348E00E12B4D /* Info.plist */, - ); - path = "Tests iOS"; - sourceTree = ""; - }; - 09BFB2A225C8348E00E12B4D /* Tests macOS */ = { - isa = PBXGroup; - children = ( - 09BFB2A325C8348E00E12B4D /* Tests_macOS.swift */, - 09BFB2A525C8348E00E12B4D /* Info.plist */, - ); - path = "Tests macOS"; + path = App; sourceTree = ""; }; /* End PBXGroup section */ @@ -970,6 +736,8 @@ ); name = Shortcuts; packageProductDependencies = ( + 09AE6ECD29B13ABC0025DF93 /* WallabagKit */, + 09800D8C29B9DE9E00DAB403 /* SharedLib */, ); productName = Shortcuts; productReference = 093D139D26263B05008C2150 /* Shortcuts.appex */; @@ -1007,21 +775,22 @@ ); name = bagit; packageProductDependencies = ( + 09AE6ECB29B13AAE0025DF93 /* WallabagKit */, + 09800D8E29B9DEFE00DAB403 /* SharedLib */, ); productName = bagit; productReference = 09644ACE25C94825000FFDA1 /* bagit.appex */; productType = "com.apple.product-type.app-extension"; }; - 09BFB28325C8348E00E12B4D /* wallabag (iOS) */ = { + 09BFB28325C8348E00E12B4D /* wallabag */ = { isa = PBXNativeTarget; - buildConfigurationList = 09BFB2B225C8348E00E12B4D /* Build configuration list for PBXNativeTarget "wallabag (iOS)" */; + buildConfigurationList = 09BFB2B225C8348E00E12B4D /* Build configuration list for PBXNativeTarget "wallabag" */; buildPhases = ( 09BFB28025C8348E00E12B4D /* Sources */, 09BFB28125C8348E00E12B4D /* Frameworks */, 09BFB28225C8348E00E12B4D /* Resources */, - 09644AD925C94825000FFDA1 /* Embed App Extensions */, + 09644AD925C94825000FFDA1 /* Embed Foundation Extensions */, 093D142A262643CA008C2150 /* Swiftlint */, - 09483CC9270498C20084CEB2 /* Embed Frameworks */, ); buildRules = ( ); @@ -1029,73 +798,17 @@ 09644AD725C94825000FFDA1 /* PBXTargetDependency */, 093D13B526263B05008C2150 /* PBXTargetDependency */, ); - name = "wallabag (iOS)"; + name = wallabag; packageProductDependencies = ( - 09644B0625C94C14000FFDA1 /* Swinject */, 09644B0E25C94C6B000FFDA1 /* HTMLEntities */, + 09C34C7B29B1398B00B5C927 /* SharedLib */, + 09C34C7D29B1399100B5C927 /* WallabagKit */, + 09AEBE9F29B1D2C500050BBE /* Factory */, ); productName = "wallabag (iOS)"; productReference = 09BFB28425C8348E00E12B4D /* wallabag.app */; productType = "com.apple.product-type.application"; }; - 09BFB28B25C8348E00E12B4D /* wallabag (macOS) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 09BFB2B525C8348E00E12B4D /* Build configuration list for PBXNativeTarget "wallabag (macOS)" */; - buildPhases = ( - 09BFB28825C8348E00E12B4D /* Sources */, - 09BFB28925C8348E00E12B4D /* Frameworks */, - 09BFB28A25C8348E00E12B4D /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "wallabag (macOS)"; - packageProductDependencies = ( - 097F823225CB1A9A006C85F6 /* Swinject */, - 0916CDB525F0D5D6000DC311 /* HTMLEntities */, - 093D14B926264D62008C2150 /* SharedLib */, - ); - productName = "wallabag (macOS)"; - productReference = 09BFB28C25C8348E00E12B4D /* wallabag.app */; - productType = "com.apple.product-type.application"; - }; - 09BFB29325C8348E00E12B4D /* Tests iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 09BFB2B825C8348E00E12B4D /* Build configuration list for PBXNativeTarget "Tests iOS" */; - buildPhases = ( - 09BFB29025C8348E00E12B4D /* Sources */, - 09BFB29125C8348E00E12B4D /* Frameworks */, - 09BFB29225C8348E00E12B4D /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 09BFB29625C8348E00E12B4D /* PBXTargetDependency */, - ); - name = "Tests iOS"; - productName = "Tests iOS"; - productReference = 09BFB29425C8348E00E12B4D /* Tests iOS.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; - 09BFB29E25C8348E00E12B4D /* Tests macOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 09BFB2BB25C8348E00E12B4D /* Build configuration list for PBXNativeTarget "Tests macOS" */; - buildPhases = ( - 09BFB29B25C8348E00E12B4D /* Sources */, - 09BFB29C25C8348E00E12B4D /* Frameworks */, - 09BFB29D25C8348E00E12B4D /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 09BFB2A125C8348E00E12B4D /* PBXTargetDependency */, - ); - name = "Tests macOS"; - productName = "Tests macOS"; - productReference = 09BFB29F25C8348E00E12B4D /* Tests macOS.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1103,7 +816,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1240; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1420; TargetAttributes = { 093D139C26263B05008C2150 = { CreatedOnToolsVersion = 12.4; @@ -1118,17 +831,6 @@ 09BFB28325C8348E00E12B4D = { CreatedOnToolsVersion = 12.4; }; - 09BFB28B25C8348E00E12B4D = { - CreatedOnToolsVersion = 12.4; - }; - 09BFB29325C8348E00E12B4D = { - CreatedOnToolsVersion = 12.4; - TestTargetID = 09BFB28325C8348E00E12B4D; - }; - 09BFB29E25C8348E00E12B4D = { - CreatedOnToolsVersion = 12.4; - TestTargetID = 09BFB28B25C8348E00E12B4D; - }; }; }; buildConfigurationList = 09BFB27825C8348E00E12B4D /* Build configuration list for PBXProject "wallabag" */; @@ -1152,19 +854,16 @@ ); mainGroup = 09BFB27425C8348E00E12B4D; packageReferences = ( - 09644B0525C94C14000FFDA1 /* XCRemoteSwiftPackageReference "Swinject" */, 09644B0D25C94C6B000FFDA1 /* XCRemoteSwiftPackageReference "swift-html-entities" */, + 09AEBE9E29B1D2C500050BBE /* XCRemoteSwiftPackageReference "Factory" */, ); productRefGroup = 09BFB28525C8348E00E12B4D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 09BFB28325C8348E00E12B4D /* wallabag (iOS) */, - 09BFB28B25C8348E00E12B4D /* wallabag (macOS) */, + 09BFB28325C8348E00E12B4D /* wallabag */, 09644ACD25C94825000FFDA1 /* bagit */, 093D139C26263B05008C2150 /* Shortcuts */, - 09BFB29E25C8348E00E12B4D /* Tests macOS */, - 09BFB29325C8348E00E12B4D /* Tests iOS */, 094AA03A2629EB1F006E5605 /* wallabagTests */, ); }; @@ -1190,7 +889,6 @@ buildActionMask = 2147483647; files = ( 09644AD425C94825000FFDA1 /* MainInterface.storyboard in Resources */, - 09644AF725C94982000FFDA1 /* Media.xcassets in Resources */, 09644AEA25C94879000FFDA1 /* ExtensionClass.js in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1200,41 +898,20 @@ buildActionMask = 2147483647; files = ( 09AD75A32624F93D00708A1E /* ratatouille.css in Resources */, - 09BFB2AE25C8348E00E12B4D /* Assets.xcassets in Resources */, 09AD75A12624F93D00708A1E /* article.html in Resources */, 09AD75BE2624FEEE00708A1E /* Localizable.strings in Resources */, 09AD75A42624F93D00708A1E /* justify.css in Resources */, + 0951C61829CC2EB000D8E8C6 /* Assets.xcassets in Resources */, 09AD75A22624F93D00708A1E /* main.css in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 09BFB28A25C8348E00E12B4D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 09BFB2AF25C8348E00E12B4D /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB29225C8348E00E12B4D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB29D25C8348E00E12B4D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 093D142A262643CA008C2150 /* Swiftlint */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -1258,14 +935,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 093D13FB262640C0008C2150 /* Password.swift in Sources */, - 093D13FA262640C0008C2150 /* Setting.swift in Sources */, 093D13EC26263F81008C2150 /* AddEntryIntentHandler.swift in Sources */, - 093D1403262640C9008C2150 /* KeychainPasswordItem.swift in Sources */, - 093D13FC262640C0008C2150 /* GeneralSetting.swift in Sources */, 093D13D826263CC4008C2150 /* Intents.intentdefinition in Sources */, 093D13A226263B05008C2150 /* IntentHandler.swift in Sources */, - 093D13F3262640B7008C2150 /* WallabagUserDefaults.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1275,6 +947,7 @@ files = ( 09BCBBD4282BD46A00B234CB /* RouterTests.swift in Sources */, 094AA05A2629EB60006E5605 /* ImageCacheTests.swift in Sources */, + 098CF4D629CD830E00DEAE50 /* ServerViewModelTests.swift in Sources */, 094AA03E2629EB1F006E5605 /* wallabagTests.swift in Sources */, 094AA0692629EB98006E5605 /* ImageDownloaderTests.swift in Sources */, ); @@ -1284,13 +957,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 09644B1F25C94D9C000FFDA1 /* WallabagUserDefaults.swift in Sources */, 09644AE325C94863000FFDA1 /* ShareExtensionError.swift in Sources */, - 09644B2725C94DD2000FFDA1 /* Setting.swift in Sources */, - 09644B4225C94E2B000FFDA1 /* GeneralSetting.swift in Sources */, - 09644B3325C94DEB000FFDA1 /* Password.swift in Sources */, 09644AD125C94825000FFDA1 /* ShareViewController.swift in Sources */, - 09644B3A25C94E03000FFDA1 /* KeychainPasswordItem.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1305,20 +973,16 @@ 09644B5725C9810A000FFDA1 /* WallabagApp.swift in Sources */, 09644C6F25C985A9000FFDA1 /* EntryPictoImage.swift in Sources */, 09644C9E25C98615000FFDA1 /* MainView.swift in Sources */, - 09644CB825C98660000FFDA1 /* Menu.swift in Sources */, + 098BDD0829BF04E3003DF719 /* RouteSwiftUIExtension.swift in Sources */, 09644C8F25C985E8000FFDA1 /* BugReportView.swift in Sources */, 09644BFB25C983F8000FFDA1 /* Tag.swift in Sources */, 09644CD625C986C0000FFDA1 /* ClientIdClientSecretView.swift in Sources */, 09644B9725C9819F000FFDA1 /* PlayerView.swift in Sources */, - 09644BCB25C98252000FFDA1 /* KeychainPasswordItem.swift in Sources */, 09644CF225C986EE000FFDA1 /* SearchViewModel.swift in Sources */, 09644BA325C981B4000FFDA1 /* ErrorViewModel.swift in Sources */, 09644C4F25C9850D000FFDA1 /* CoreDataViewContext.swift in Sources */, - 09644BC425C98248000FFDA1 /* Setting.swift in Sources */, 09644C5E25C98596000FFDA1 /* EntriesView.swift in Sources */, 09644CA725C98639000FFDA1 /* View+haptic.swift in Sources */, - 09644BBD25C98240000FFDA1 /* WallabagUserDefaults.swift in Sources */, - 09644BC325C98248000FFDA1 /* GeneralSetting.swift in Sources */, 09644B7E25C98152000FFDA1 /* AppState.swift in Sources */, 09644C6E25C985A9000FFDA1 /* DeleteEntryButton.swift in Sources */, 09644B8C25C98176000FFDA1 /* Route.swift in Sources */, @@ -1328,7 +992,6 @@ 09644C7D25C985B8000FFDA1 /* ImageCache.swift in Sources */, 09644CC225C98674000FFDA1 /* PasteBoardView.swift in Sources */, 09644CC325C98674000FFDA1 /* PasteBoardViewModel.swift in Sources */, - 09644BE625C98350000FFDA1 /* Injector.swift in Sources */, 09644C6D25C985A9000FFDA1 /* StarEntryButton.swift in Sources */, 09644C6125C98596000FFDA1 /* EntriesListView.swift in Sources */, 09644CF325C986EE000FFDA1 /* SearchView.swift in Sources */, @@ -1336,16 +999,13 @@ 09644C5F25C98596000FFDA1 /* EntryRowView.swift in Sources */, 09644CE925C986CC000FFDA1 /* ServerViewModel.swift in Sources */, 09644CD725C986C0000FFDA1 /* ClientIdClientSecretViewModel.swift in Sources */, - 09644CB925C98660000FFDA1 /* MenuView.swift in Sources */, 09644CCB25C9869D000FFDA1 /* RegistrationView.swift in Sources */, 09644CFE25C9870C000FFDA1 /* TagRow.swift in Sources */, 09644BFC25C983F8000FFDA1 /* Entry.swift in Sources */, 097F81EB25CB18BA006C85F6 /* Router.swift in Sources */, - 09644BC525C98248000FFDA1 /* Password.swift in Sources */, 09644BB725C98232000FFDA1 /* AppSetting.swift in Sources */, 09644C7F25C985B8000FFDA1 /* ImageDownloaderPublisher.swift in Sources */, 09644CE825C986CC000FFDA1 /* ServerView.swift in Sources */, - 09BFB2A625C8348E00E12B4D /* wallabag.xcdatamodeld in Sources */, 09644CFD25C9870C000FFDA1 /* TagListFor.swift in Sources */, 09644BFA25C983F8000FFDA1 /* Podcast.swift in Sources */, 09644BAE25C98213000FFDA1 /* AppSync.swift in Sources */, @@ -1367,86 +1027,31 @@ 09644CFF25C9870C000FFDA1 /* TagsForEntryPublisher.swift in Sources */, 09644D1025C9872F000FFDA1 /* BundleKey.swift in Sources */, 09644BAF25C98213000FFDA1 /* RefreshButton.swift in Sources */, - 09644B8A25C98176000FFDA1 /* RouterView.swift in Sources */, + 09BE0AF42A9F45E900193FBF /* View+Extension.swift in Sources */, 09644C7025C985A9000FFDA1 /* ArchiveEntryButton.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 09BFB28825C8348E00E12B4D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0916CDF725F0E5BD000DC311 /* RouterView.swift in Sources */, - 097F820C25CB1A0C006C85F6 /* Password.swift in Sources */, - 097F825225CB1B2E006C85F6 /* Entry.swift in Sources */, - 0916CDBC25F0E04D000DC311 /* wallabagStore.xcdatamodeld in Sources */, - 097F821225CB1A0F006C85F6 /* GeneralSetting.swift in Sources */, - 097F81AA25CB1108006C85F6 /* Route.swift in Sources */, - 097F821E25CB1A4C006C85F6 /* WallabagSession.swift in Sources */, - 097F823F25CB1ABB006C85F6 /* CoreData.swift in Sources */, - 097F825825CB1B33006C85F6 /* Tag.swift in Sources */, - 097F822C25CB1A93006C85F6 /* Injector.swift in Sources */, - 097F824625CB1ADF006C85F6 /* DependencyInjection.swift in Sources */, - 097F818525CAEA79006C85F6 /* wallabagMacApp.swift in Sources */, - 097F81F225CB1996006C85F6 /* Router.swift in Sources */, - 0916CDE725F0E54C000DC311 /* RegistrationView.swift in Sources */, - 097F81FA25CB19F6006C85F6 /* AppState.swift in Sources */, - 09BFB2A725C8348E00E12B4D /* wallabag.xcdatamodeld in Sources */, - 0916CD8E25F0D47A000DC311 /* EntryRowView.swift in Sources */, - 0916CD8825F0D450000DC311 /* EntriesListView.swift in Sources */, - 097F823925CB1AB1006C85F6 /* CoreDataViewContext.swift in Sources */, - 097F819D25CAF9FE006C85F6 /* SidebarView.swift in Sources */, - 097F820625CB1A0A006C85F6 /* Setting.swift in Sources */, - 097F820025CB1A04006C85F6 /* WallabagUserDefaults.swift in Sources */, - 0916CD7C25F0D1F1000DC311 /* Menu.swift in Sources */, - 097F821825CB1A16006C85F6 /* KeychainPasswordItem.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB29025C8348E00E12B4D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 09BFB29925C8348E00E12B4D /* Tests_iOS.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 09BFB29B25C8348E00E12B4D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 09BFB2A425C8348E00E12B4D /* Tests_macOS.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 093D13B526263B05008C2150 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = 093D139C26263B05008C2150 /* Shortcuts */; targetProxy = 093D13B426263B05008C2150 /* PBXContainerItemProxy */; }; 094AA0412629EB1F006E5605 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 09BFB28325C8348E00E12B4D /* wallabag (iOS) */; + target = 09BFB28325C8348E00E12B4D /* wallabag */; targetProxy = 094AA0402629EB1F006E5605 /* PBXContainerItemProxy */; }; 09644AD725C94825000FFDA1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = 09644ACD25C94825000FFDA1 /* bagit */; targetProxy = 09644AD625C94825000FFDA1 /* PBXContainerItemProxy */; }; - 09BFB29625C8348E00E12B4D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 09BFB28325C8348E00E12B4D /* wallabag (iOS) */; - targetProxy = 09BFB29525C8348E00E12B4D /* PBXContainerItemProxy */; - }; - 09BFB2A125C8348E00E12B4D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 09BFB28B25C8348E00E12B4D /* wallabag (macOS) */; - targetProxy = 09BFB2A025C8348E00E12B4D /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -1487,7 +1092,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = G97URPCGB8; INFOPLIST_FILE = Shortcuts/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1509,7 +1114,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = G97URPCGB8; INFOPLIST_FILE = Shortcuts/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1532,7 +1137,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = G97URPCGB8; INFOPLIST_FILE = wallabagTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1541,6 +1146,9 @@ PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.wallabagTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/wallabag.app/wallabag"; @@ -1554,7 +1162,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = G97URPCGB8; INFOPLIST_FILE = wallabagTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1563,6 +1171,9 @@ PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.wallabagTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/wallabag.app/wallabag"; @@ -1578,7 +1189,7 @@ CURRENT_PROJECT_VERSION = 319; DEVELOPMENT_TEAM = G97URPCGB8; INFOPLIST_FILE = bagit/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1602,7 +1213,7 @@ CURRENT_PROJECT_VERSION = 319; DEVELOPMENT_TEAM = G97URPCGB8; INFOPLIST_FILE = bagit/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1654,6 +1265,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -1671,7 +1283,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1715,6 +1327,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1726,7 +1339,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SWIFT_COMPILATION_MODE = wholemodule; @@ -1743,9 +1356,11 @@ CODE_SIGN_ENTITLEMENTS = wallabag.entitlements; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = G97URPCGB8; + ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = iOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + INFOPLIST_FILE = App/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1753,6 +1368,9 @@ PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.wallabag"; PRODUCT_NAME = wallabag; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1768,9 +1386,11 @@ CODE_SIGN_ENTITLEMENTS = wallabag.entitlements; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = G97URPCGB8; + ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = iOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + INFOPLIST_FILE = App/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1778,6 +1398,9 @@ PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.wallabag"; PRODUCT_NAME = wallabag; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1785,147 +1408,6 @@ }; name = Release; }; - 09BFB2B625C8348E00E12B4D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = G97URPCGB8; - ENABLE_HARDENED_RUNTIME = YES; - ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = macOS/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.wallabag"; - PRODUCT_NAME = wallabag; - SDKROOT = macosx; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 09BFB2B725C8348E00E12B4D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = G97URPCGB8; - ENABLE_HARDENED_RUNTIME = YES; - ENABLE_PREVIEWS = YES; - INFOPLIST_FILE = macOS/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.wallabag"; - PRODUCT_NAME = wallabag; - SDKROOT = macosx; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 09BFB2B925C8348E00E12B4D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = G97URPCGB8; - INFOPLIST_FILE = "Tests iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.Tests-iOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = iphoneos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = "wallabag (iOS)"; - }; - name = Debug; - }; - 09BFB2BA25C8348E00E12B4D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = G97URPCGB8; - INFOPLIST_FILE = "Tests iOS/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.Tests-iOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - SDKROOT = iphoneos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = "wallabag (iOS)"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 09BFB2BC25C8348E00E12B4D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = G97URPCGB8; - INFOPLIST_FILE = "Tests macOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.1; - PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.Tests-macOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SWIFT_VERSION = 5.0; - TEST_TARGET_NAME = "wallabag (macOS)"; - }; - name = Debug; - }; - 09BFB2BD25C8348E00E12B4D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = G97URPCGB8; - INFOPLIST_FILE = "Tests macOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.1; - PRODUCT_BUNDLE_IDENTIFIER = "fr.district-web.Tests-macOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SWIFT_VERSION = 5.0; - TEST_TARGET_NAME = "wallabag (macOS)"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1965,7 +1447,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 09BFB2B225C8348E00E12B4D /* Build configuration list for PBXNativeTarget "wallabag (iOS)" */ = { + 09BFB2B225C8348E00E12B4D /* Build configuration list for PBXNativeTarget "wallabag" */ = { isa = XCConfigurationList; buildConfigurations = ( 09BFB2B325C8348E00E12B4D /* Debug */, @@ -1974,44 +1456,9 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 09BFB2B525C8348E00E12B4D /* Build configuration list for PBXNativeTarget "wallabag (macOS)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 09BFB2B625C8348E00E12B4D /* Debug */, - 09BFB2B725C8348E00E12B4D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 09BFB2B825C8348E00E12B4D /* Build configuration list for PBXNativeTarget "Tests iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 09BFB2B925C8348E00E12B4D /* Debug */, - 09BFB2BA25C8348E00E12B4D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 09BFB2BB25C8348E00E12B4D /* Build configuration list for PBXNativeTarget "Tests macOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 09BFB2BC25C8348E00E12B4D /* Debug */, - 09BFB2BD25C8348E00E12B4D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 09644B0525C94C14000FFDA1 /* XCRemoteSwiftPackageReference "Swinject" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/Swinject/Swinject"; - requirement = { - kind = upToNextMinorVersion; - minimumVersion = 2.7.1; - }; - }; 09644B0D25C94C6B000FFDA1 /* XCRemoteSwiftPackageReference "swift-html-entities" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/IBM-Swift/swift-html-entities.git"; @@ -2020,32 +1467,50 @@ minimumVersion = 3.0.200; }; }; + 09AEBE9E29B1D2C500050BBE /* XCRemoteSwiftPackageReference "Factory" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "git@github.com:hmlongco/Factory.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 0916CDB525F0D5D6000DC311 /* HTMLEntities */ = { - isa = XCSwiftPackageProductDependency; - package = 09644B0D25C94C6B000FFDA1 /* XCRemoteSwiftPackageReference "swift-html-entities" */; - productName = HTMLEntities; - }; - 093D14B926264D62008C2150 /* SharedLib */ = { - isa = XCSwiftPackageProductDependency; - productName = SharedLib; - }; - 09644B0625C94C14000FFDA1 /* Swinject */ = { - isa = XCSwiftPackageProductDependency; - package = 09644B0525C94C14000FFDA1 /* XCRemoteSwiftPackageReference "Swinject" */; - productName = Swinject; - }; 09644B0E25C94C6B000FFDA1 /* HTMLEntities */ = { isa = XCSwiftPackageProductDependency; package = 09644B0D25C94C6B000FFDA1 /* XCRemoteSwiftPackageReference "swift-html-entities" */; productName = HTMLEntities; }; - 097F823225CB1A9A006C85F6 /* Swinject */ = { + 09800D8C29B9DE9E00DAB403 /* SharedLib */ = { isa = XCSwiftPackageProductDependency; - package = 09644B0525C94C14000FFDA1 /* XCRemoteSwiftPackageReference "Swinject" */; - productName = Swinject; + productName = SharedLib; + }; + 09800D8E29B9DEFE00DAB403 /* SharedLib */ = { + isa = XCSwiftPackageProductDependency; + productName = SharedLib; + }; + 09AE6ECB29B13AAE0025DF93 /* WallabagKit */ = { + isa = XCSwiftPackageProductDependency; + productName = WallabagKit; + }; + 09AE6ECD29B13ABC0025DF93 /* WallabagKit */ = { + isa = XCSwiftPackageProductDependency; + productName = WallabagKit; + }; + 09AEBE9F29B1D2C500050BBE /* Factory */ = { + isa = XCSwiftPackageProductDependency; + package = 09AEBE9E29B1D2C500050BBE /* XCRemoteSwiftPackageReference "Factory" */; + productName = Factory; + }; + 09C34C7B29B1398B00B5C927 /* SharedLib */ = { + isa = XCSwiftPackageProductDependency; + productName = SharedLib; + }; + 09C34C7D29B1399100B5C927 /* WallabagKit */ = { + isa = XCSwiftPackageProductDependency; + productName = WallabagKit; }; /* End XCSwiftPackageProductDependency section */ @@ -2060,16 +1525,6 @@ sourceTree = ""; versionGroupType = wrapper.xcdatamodel; }; - 09BFB27A25C8348E00E12B4D /* wallabag.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - 09BFB27B25C8348E00E12B4D /* Shared.xcdatamodel */, - ); - currentVersion = 09BFB27B25C8348E00E12B4D /* Shared.xcdatamodel */; - path = wallabag.xcdatamodeld; - sourceTree = ""; - versionGroupType = wrapper.xcdatamodel; - }; /* End XCVersionGroup section */ }; rootObject = 09BFB27525C8348E00E12B4D /* Project object */; diff --git a/wallabag.xcodeproj/xcshareddata/xcschemes/Shortcuts.xcscheme b/wallabag.xcodeproj/xcshareddata/xcschemes/Shortcuts.xcscheme new file mode 100644 index 0000000..e654a28 --- /dev/null +++ b/wallabag.xcodeproj/xcshareddata/xcschemes/Shortcuts.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wallabag.xcodeproj/xcshareddata/xcschemes/bagit.xcscheme b/wallabag.xcodeproj/xcshareddata/xcschemes/bagit.xcscheme index 362d9d3..b917b70 100644 --- a/wallabag.xcodeproj/xcshareddata/xcschemes/bagit.xcscheme +++ b/wallabag.xcodeproj/xcshareddata/xcschemes/bagit.xcscheme @@ -1,6 +1,6 @@ @@ -73,7 +73,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "09BFB28325C8348E00E12B4D" BuildableName = "wallabag.app" - BlueprintName = "wallabag (iOS)" + BlueprintName = "wallabag" ReferencedContainer = "container:wallabag.xcodeproj"> @@ -92,7 +92,7 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "09BFB28325C8348E00E12B4D" BuildableName = "wallabag.app" - BlueprintName = "wallabag (iOS)" + BlueprintName = "wallabag" ReferencedContainer = "container:wallabag.xcodeproj"> diff --git a/wallabag.xcodeproj/xcshareddata/xcschemes/wallabag (iOS).xcscheme b/wallabag.xcodeproj/xcshareddata/xcschemes/wallabag.xcscheme similarity index 89% rename from wallabag.xcodeproj/xcshareddata/xcschemes/wallabag (iOS).xcscheme rename to wallabag.xcodeproj/xcshareddata/xcschemes/wallabag.xcscheme index a68532e..92022da 100644 --- a/wallabag.xcodeproj/xcshareddata/xcschemes/wallabag (iOS).xcscheme +++ b/wallabag.xcodeproj/xcshareddata/xcschemes/wallabag.xcscheme @@ -1,6 +1,6 @@ @@ -28,16 +28,6 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + + + + identifier = "../App/Configuration.storekit"> diff --git a/wallabag.xcworkspace/contents.xcworkspacedata b/wallabag.xcworkspace/contents.xcworkspacedata index 5695bf2..23ae4ab 100644 --- a/wallabag.xcworkspace/contents.xcworkspacedata +++ b/wallabag.xcworkspace/contents.xcworkspacedata @@ -5,9 +5,9 @@ location = "container:wallabag.xcodeproj"> + location = "group:WallabagKit"> + location = "group:SharedLib"> diff --git a/wallabag.xcworkspace/xcshareddata/swiftpm/Package.resolved b/wallabag.xcworkspace/xcshareddata/swiftpm/Package.resolved index 79e970f..d2a17ee 100644 --- a/wallabag.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/wallabag.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,14 @@ { "pins" : [ + { + "identity" : "factory", + "kind" : "remoteSourceControl", + "location" : "git@github.com:hmlongco/Factory.git", + "state" : { + "revision" : "061b3afe0358a0da7ce568f8272c847910be3dd7", + "version" : "2.2.0" + } + }, { "identity" : "swift-html-entities", "kind" : "remoteSourceControl", @@ -8,15 +17,6 @@ "revision" : "2b14531d0c36dbb7c1c45a4d38db9c2e7898a307", "version" : "3.0.200" } - }, - { - "identity" : "swinject", - "kind" : "remoteSourceControl", - "location" : "https://github.com/Swinject/Swinject", - "state" : { - "revision" : "8a76d2c74bafbb455763487cc6a08e91bad1f78b", - "version" : "2.7.1" - } } ], "version" : 2 diff --git a/wallabagTests/Features/Entry/Picture/ImageDownloaderTests.swift b/wallabagTests/Features/Entry/Picture/ImageDownloaderTests.swift index 20e67ed..19c96be 100644 --- a/wallabagTests/Features/Entry/Picture/ImageDownloaderTests.swift +++ b/wallabagTests/Features/Entry/Picture/ImageDownloaderTests.swift @@ -5,20 +5,16 @@ import XCTest class ImageDownloaderTests: XCTestCase { var cancellable: AnyCancellable? - override func setUp() { - Task { - await ImageCache.shared.purge() - } + override func setUp() async throws { + await ImageCache.shared.purge() } - override func tearDown() { - Task { - await ImageCache.shared.purge() - } + override func tearDown() async throws { + await ImageCache.shared.purge() } func testLoadInvalidImage() async throws { - let imageDownloader = ImageDownloader.shared + let imageDownloader = ImageDownloader() let image = await imageDownloader.loadImage(url: .init(string: "https://wallabag.it/")!) @@ -26,7 +22,7 @@ class ImageDownloaderTests: XCTestCase { } func testLoadValidImage() async throws { - let imageDownloader = ImageDownloader.shared + let imageDownloader = ImageDownloader() let image = await imageDownloader.loadImage(url: .init(string: "https://www.wallabag.it/user/themes/alpha/assets/images/wallabagit.png")!) diff --git a/wallabagTests/Features/Registration/Server/ServerViewModelTests.swift b/wallabagTests/Features/Registration/Server/ServerViewModelTests.swift new file mode 100644 index 0000000..9f1a4e5 --- /dev/null +++ b/wallabagTests/Features/Registration/Server/ServerViewModelTests.swift @@ -0,0 +1,63 @@ +import Combine +import SharedLib +@testable import wallabag +import XCTest + +final class ServerViewModelTests: XCTestCase { + var cancellable = Set() + + override class func setUp() { + WallabagUserDefaults.host = "" + } + + func testInit() { + let model = ServerViewModel() + + XCTAssertEqual("", model.url) + } + + func testInvalidUrl() { + let model = ServerViewModel() + + let expectation = XCTestExpectation(description: "Invalid url") + + XCTAssertEqual("", model.url) + XCTAssertFalse(model.isValid) + + model.$isValid + .dropFirst() + .sink(receiveValue: { + XCTAssertFalse($0) + expectation.fulfill() + }) + .store(in: &cancellable) + + model.url = "azerty" + XCTAssertEqual("", WallabagUserDefaults.host) + + wait(for: [expectation], timeout: 1) + } + + func testValidUrl() { + let model = ServerViewModel() + + let expectation = XCTestExpectation(description: "Valid url") + + XCTAssertEqual("", model.url) + XCTAssertEqual("", WallabagUserDefaults.host) + XCTAssertFalse(model.isValid) + + model.$isValid + .dropFirst() + .sink(receiveValue: { + XCTAssertTrue($0) + expectation.fulfill() + }) + .store(in: &cancellable) + model.url = "https://wallabag.it" + + XCTAssertEqual("https://wallabag.it", WallabagUserDefaults.host) + + wait(for: [expectation], timeout: 1) + } +} diff --git a/wallabagTests/Features/Router/RouterTests.swift b/wallabagTests/Features/Router/RouterTests.swift index e5748a5..2ea1d95 100644 --- a/wallabagTests/Features/Router/RouterTests.swift +++ b/wallabagTests/Features/Router/RouterTests.swift @@ -3,12 +3,8 @@ import XCTest class RouterTests: XCTestCase { func testLoadRoute() throws { - let router = Router(defaultRoute: .registration) + let router = Router() - XCTAssertEqual(.registration, router.route) - - router.load(.about) - - XCTAssertEqual(.about, router.route) + XCTAssertEqual(0, router.path.count) } } diff --git a/wallabagTests/Info.plist b/wallabagTests/Info.plist index a71e404..f968cd1 100644 --- a/wallabagTests/Info.plist +++ b/wallabagTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.2.1 + 7.0.0 CFBundleVersion 319