From a12c9539a1e3d04185886d6f447dd9c2d885e217 Mon Sep 17 00:00:00 2001 From: Matte23 Date: Tue, 16 Feb 2021 20:50:14 +0100 Subject: [PATCH] Automatically resolve circular's direct URL on iOS --- .../circolapp.xcodeproj/project.pbxproj | 8 ++- .../xcshareddata/xcschemes/circolapp.xcscheme | 2 +- .../circolapp/View/ActivityIndicator.swift | 18 +++++ .../circolapp/View/AttachmentView.swift | 65 +++++++++++++++---- .../circolapp/View/CircularView.swift | 48 ++++++++++---- .../circolapp/View/NewReminderView.swift | 2 +- shared/shared.podspec | 2 +- .../server/curie/SpecificCurieServer.kt | 3 +- 8 files changed, 118 insertions(+), 30 deletions(-) create mode 100644 ios/circolapp/circolapp/View/ActivityIndicator.swift diff --git a/ios/circolapp/circolapp.xcodeproj/project.pbxproj b/ios/circolapp/circolapp.xcodeproj/project.pbxproj index 7f5d350..f76b64b 100644 --- a/ios/circolapp/circolapp.xcodeproj/project.pbxproj +++ b/ios/circolapp/circolapp.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 95CA31B2255C1EDE00AC095B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CA31B1255C1EDE00AC095B /* ContentView.swift */; }; 95CA31B7255C1EE000AC095B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95CA31B6255C1EE000AC095B /* Preview Assets.xcassets */; }; 95CA31C0255C28C300AC095B /* CircularView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CA31BF255C28C300AC095B /* CircularView.swift */; }; + 95CED73225DBFA3B00C0E661 /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CED73125DBFA3B00C0E661 /* ActivityIndicator.swift */; }; 95DB71AB258A1C1500A78033 /* CarteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95DB71AA258A1C1500A78033 /* CarteView.swift */; }; 95E58FBB2592195B00689C37 /* ShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E58FBA2592195B00689C37 /* ShareSheet.swift */; }; 95F6666E2590D712006DE74F /* URLUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6666D2590D712006DE74F /* URLUtils.swift */; }; @@ -90,6 +91,7 @@ 95CA31B6255C1EE000AC095B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 95CA31B8255C1EE000AC095B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 95CA31BF255C28C300AC095B /* CircularView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularView.swift; sourceTree = ""; }; + 95CED73125DBFA3B00C0E661 /* ActivityIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = ""; }; 95DB71AA258A1C1500A78033 /* CarteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarteView.swift; sourceTree = ""; }; 95E58FBA2592195B00689C37 /* ShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheet.swift; sourceTree = ""; }; 95F6666D2590D712006DE74F /* URLUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLUtils.swift; sourceTree = ""; }; @@ -155,6 +157,7 @@ 950C1783258E582E00B2DBFE /* PadView.swift */, 950C1785258E58AD00B2DBFE /* SidebarView.swift */, 950C1787258E5BD300B2DBFE /* PhoneView.swift */, + 95CED73125DBFA3B00C0E661 /* ActivityIndicator.swift */, ); path = View; sourceTree = ""; @@ -247,7 +250,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1210; - LastUpgradeCheck = 1210; + LastUpgradeCheck = 1240; TargetAttributes = { 95CA31AB255C1EDD00AC095B = { CreatedOnToolsVersion = 12.1; @@ -377,6 +380,7 @@ 95CA31C0255C28C300AC095B /* CircularView.swift in Sources */, 954AF8FF2588A61B00666D0C /* RemindersViewModel.swift in Sources */, 952DEDDF2576F8DC001DF85D /* SceneDelegate.swift in Sources */, + 95CED73225DBFA3B00C0E661 /* ActivityIndicator.swift in Sources */, 954AF8FA2588A5DD00666D0C /* RemindersList.swift in Sources */, 95CA31B2255C1EDE00AC095B /* ContentView.swift in Sources */, 955B7A10257D10A70091B1F9 /* ViewControllerResolver.swift in Sources */, @@ -420,6 +424,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -482,6 +487,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; diff --git a/ios/circolapp/circolapp.xcodeproj/xcshareddata/xcschemes/circolapp.xcscheme b/ios/circolapp/circolapp.xcodeproj/xcshareddata/xcschemes/circolapp.xcscheme index cacb474..ddb5299 100644 --- a/ios/circolapp/circolapp.xcodeproj/xcshareddata/xcschemes/circolapp.xcscheme +++ b/ios/circolapp/circolapp.xcodeproj/xcshareddata/xcschemes/circolapp.xcscheme @@ -1,6 +1,6 @@ ) -> UIActivityIndicatorView { + return UIActivityIndicatorView(style: style) + } + + func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) { + isAnimating ? uiView.startAnimating() : uiView.stopAnimating() + } +} diff --git a/ios/circolapp/circolapp/View/AttachmentView.swift b/ios/circolapp/circolapp/View/AttachmentView.swift index ee41fb2..89e7fa3 100644 --- a/ios/circolapp/circolapp/View/AttachmentView.swift +++ b/ios/circolapp/circolapp/View/AttachmentView.swift @@ -22,10 +22,27 @@ import Shared struct AttachmentView: View { @State private var sharingPhone: Bool = false @State private var sharingPad: Bool = false + @State private var loadingRealUrl = false - var attachmentName: String - var attachmentUrl: String + var index: Int + var circular: Circular + let attachmentName: String + let attachmentUrl: String + var realAttachmentUrl: String = "" + + init(index: Int, circular: Circular) { + self.index = index + self.circular = circular + + attachmentName = circular.attachmentsNames[index] as! String + attachmentUrl = circular.attachmentsUrls[index] as! String + + if circular.realAttachmentsUrls.count == circular.attachmentsUrls.count { + realAttachmentUrl = circular.realAttachmentsUrls[index] as! String + } + } + var body: some View { Divider() HStack { @@ -34,16 +51,21 @@ struct AttachmentView: View { .multilineTextAlignment(.leading) Spacer() - Button(action: { - URLUtils.openUrl(url: attachmentUrl) - }) { - Image(systemName: "envelope.open.fill") - .resizable() - .scaledToFit() - .frame(width: 20.0, height: 20.0) + if loadingRealUrl { + ActivityIndicator(isAnimating: .constant(true), style: .medium) .padding(8.0) + } else { + Button(action: { + runWhenUrlIsAvailable(code: {realUrl in URLUtils.openUrl(url: realUrl)}) + }) { + Image(systemName: "envelope.open.fill") + .resizable() + .scaledToFit() + .frame(width: 20.0, height: 20.0) + .padding(8.0) + } + .buttonStyle(BorderlessButtonStyle()) } - .buttonStyle(BorderlessButtonStyle()) Button(action: { if UIDevice.current.userInterfaceIdiom == .phone { @@ -68,10 +90,31 @@ struct AttachmentView: View { } } } + + func runWhenUrlIsAvailable(code: @escaping (_ url: String) -> Void) { + if realAttachmentUrl == "" { + loadingRealUrl = true + + iOSRepository.getCircularRepository().getRealUrlForAttachment(index: Int32(index), rawUrls: circular.attachmentsUrls as! [String], realUrls: circular.realAttachmentsUrls as! [String], id: circular.id, school: circular.school, completionHandler: {realUrls, _ in + + if realUrls == nil { + code(attachmentUrl) + } + + loadingRealUrl = false + code(realUrls![index]) + } ) + return + } + + code(realAttachmentUrl) + } } struct AttachmentView_Previews: PreviewProvider { + static var previewCircular = Circular(id: 1, school: 0, name: "This is a circular", url: "http://example.com", realUrl: "http://example.com", date: "19/11/2020", favourite: false, reminder: false, read: false, attachmentsNames: ["This is an attachment"], attachmentsUrls: ["http://example.com"], realAttachmentsUrls: []) + static var previews: some View { - AttachmentView(attachmentName: "This is an attachment", attachmentUrl: "http://example.com") + AttachmentView(index: 0, circular: previewCircular) } } diff --git a/ios/circolapp/circolapp/View/CircularView.swift b/ios/circolapp/circolapp/View/CircularView.swift index e437b88..054659b 100644 --- a/ios/circolapp/circolapp/View/CircularView.swift +++ b/ios/circolapp/circolapp/View/CircularView.swift @@ -24,6 +24,7 @@ struct CircularView: View { @State private var sharingPhone: Bool = false @State private var sharingPad: Bool = false @State private var showDetail = false + @State private var loadingRealUrl = false var circular: Circular @@ -52,20 +53,25 @@ struct CircularView: View { if showDetail { HStack { - Button(action: { - if !circular.read { - iOSRepository.getCircularDao().markRead(id: circular.id, school: circular.school, read: true, completionHandler: {_,_ in }) - } - - URLUtils.openUrl(url: circular.url) - }) { - Image(systemName: "envelope.open.fill") - .resizable() - .scaledToFit() - .frame(width: 20.0, height: 20.0) + if loadingRealUrl { + ActivityIndicator(isAnimating: .constant(true), style: .medium) .padding(.leading, 32.0) + } else { + Button(action: { + if !circular.read { + iOSRepository.getCircularDao().markRead(id: circular.id, school: circular.school, read: true, completionHandler: {_,_ in }) + } + + runWhenUrlIsAvailable(code: {realUrl in URLUtils.openUrl(url: realUrl)}) + }) { + Image(systemName: "envelope.open.fill") + .resizable() + .scaledToFit() + .frame(width: 20.0, height: 20.0) + .padding(.leading, 32.0) + } + .buttonStyle(BorderlessButtonStyle()) } - .buttonStyle(BorderlessButtonStyle()) Spacer() @@ -130,15 +136,29 @@ struct CircularView: View { ForEach(0.. Void) { + if circular.realUrl == nil { + loadingRealUrl = true + iOSRepository.getCircularRepository().getRealUrl(rawUrl: circular.url, id: circular.id, school: circular.school, completionHandler: + {realUrl, _ in + loadingRealUrl = false + code(realUrl!) + }) + return + } + + code(circular.realUrl!) + } } struct CircularView_Previews: PreviewProvider { - static var previewCircular = Circular(id: 1, school: 0, name: "This is a circular", url: "http://example.com", date: "19/11/2020", favourite: false, reminder: false, read: false, attachmentsNames: [], attachmentsUrls: []) + static var previewCircular = Circular(id: 1, school: 0, name: "This is a circular", url: "http://example.com", realUrl: "http://example.com", date: "19/11/2020", favourite: false, reminder: false, read: false, attachmentsNames: [], attachmentsUrls: [], realAttachmentsUrls: []) static var previews: some View { CircularView(circular: previewCircular) diff --git a/ios/circolapp/circolapp/View/NewReminderView.swift b/ios/circolapp/circolapp/View/NewReminderView.swift index e9193f6..162cb27 100644 --- a/ios/circolapp/circolapp/View/NewReminderView.swift +++ b/ios/circolapp/circolapp/View/NewReminderView.swift @@ -71,7 +71,7 @@ struct NewReminderView: View { } struct NewReminderView_Previews: PreviewProvider { - static var previewCircular = Circular(id: 1, school: 0, name: "This is a circular", url: "http://example.com", date: "19/11/2020", favourite: false, reminder: false, read: false, attachmentsNames: [], attachmentsUrls: []) + static var previewCircular = Circular(id: 1, school: 0, name: "This is a circular", url: "http://example.com", realUrl: "http://example.com", date: "19/11/2020", favourite: false, reminder: false, read: false, attachmentsNames: [], attachmentsUrls: [], realAttachmentsUrls: []) static var previews: some View { NewReminderView(circular: previewCircular) diff --git a/shared/shared.podspec b/shared/shared.podspec index 449d053..e5b97a9 100644 --- a/shared/shared.podspec +++ b/shared/shared.podspec @@ -19,7 +19,7 @@ Pod::Spec.new do |spec| spec.pod_target_xcconfig = { 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', - 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86', + 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', diff --git a/shared/src/iosMain/kotlin/net/underdesk/circolapp/shared/server/curie/SpecificCurieServer.kt b/shared/src/iosMain/kotlin/net/underdesk/circolapp/shared/server/curie/SpecificCurieServer.kt index f30fa38..ce58d58 100644 --- a/shared/src/iosMain/kotlin/net/underdesk/circolapp/shared/server/curie/SpecificCurieServer.kt +++ b/shared/src/iosMain/kotlin/net/underdesk/circolapp/shared/server/curie/SpecificCurieServer.kt @@ -49,6 +49,7 @@ actual class SpecificCurieServer actual constructor(private val curieServer: Cur } actual fun parseFileUrl(string: String): String { - TODO("Not yet implemented") + val document = HTMLParser(string).parseDocument() + return document.querySelector(".mtli_attachment")!!.attributes.objectForKey("href").toString() } }