Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import SwiftUI

public struct SidebarVisibilityKey: EnvironmentKey {
public static let defaultValue: Bool = false
}

public extension EnvironmentValues {
var isSidebarVisible: Bool {
get { self[SidebarVisibilityKey.self] }
set { self[SidebarVisibilityKey.self] = newValue }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import SwiftUI
import WebKit

final class InstagramNavigationDelegate: NSObject, WKNavigationDelegate {
var onStart: (() -> Void)?
var onFinish: (() -> Void)?
var onFail: ((Error) -> Void)?

func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation?) {
onStart?()
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation?) {
onFinish?()
}

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation?, withError error: Error) {
onFail?(error)
}

func webView(_ webView: WKWebView, didFail navigation: WKNavigation?, withError error: Error) {
onFail?(error)
}

func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
guard let url = navigationAction.request.url else {
decisionHandler(.cancel)
return
}

guard navigationAction.navigationType == .linkActivated else {
decisionHandler(.allow)
return
}

if url.host?.lowercased().contains("instagram.com") == true {
if let appURL = makeInstagramAppURL(from: url),
UIApplication.shared.canOpenURL(appURL) {
UIApplication.shared.open(appURL)
} else {
UIApplication.shared.open(url)
}
decisionHandler(.cancel)
return
}

decisionHandler(.allow)
}

private func makeInstagramAppURL(from webURL: URL) -> URL? {
var components = URLComponents(url: webURL, resolvingAgainstBaseURL: false)
components?.scheme = "instagram"
components?.host = nil
return components?.url
}
}
133 changes: 133 additions & 0 deletions MacMagazine/MacMagazine/Features/Social/InstagramPostsWebView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import MacMagazineLibrary
import SwiftUI
import UIComponentsLibrary
import WebKit
#if canImport(UIKit)
import UIKit
#endif

struct InstagramPostsWebView: View {
let url: URL
let userAgent: String
let shouldUseSidebar: Bool

private let darkMode: Bool

@Environment(\.theme) private var theme: ThemeColor

@State private var isPresenting = true
@State private var isLoading = true
@State private var loadError: String?

private let navigationDelegate = InstagramNavigationDelegate()

init(
colorSchema: ColorScheme?,
url: URL,
userAgent: String,
shouldUseSidebar: Bool
) {
self.url = url
self.userAgent = userAgent
self.shouldUseSidebar = shouldUseSidebar

self.darkMode = if colorSchema == nil {
Self.isDarkMode()
} else {
colorSchema == .dark
}
}

private var userScripts: [WKUserScript] {
[
WKUserScript(
source: """
(function() {
var style = document.createElement('style');
style.innerHTML = `
html, body {
padding-top: 50px !important;
}
`;
document.head.appendChild(style);
})();
""",
injectionTime: .atDocumentEnd,
forMainFrameOnly: true
)
]
}

var body: some View {
ZStack {
(theme.main.background.color ?? Color.secondary)
.ignoresSafeArea()

Webview(
title: nil,
url: url.absoluteString,
isPresenting: $isPresenting,
standAlone: true,
navigationDelegate: navigationDelegate,
userScripts: userScripts,
cookies: makeCookies(),
userAgent: userAgent
)
.ignoresSafeArea(.container, edges: [.top, .bottom])
.opacity(isLoading ? 0 : 1)
.animation(.easeInOut(duration: 0.25), value: isLoading)

if isLoading {
ProgressView()
.transition(.opacity)
}

if loadError != nil {
ContentUnavailableView(
"Estamos com um problema",
systemImage: "square.and.arrow.down.badge.xmark",
description: Text("No momento estamos com um problema tΓ©cnico. Tente novamente mais tarde.")
)
}
}
.onAppear {
navigationDelegate.onStart = { isLoading = true; loadError = nil }
navigationDelegate.onFinish = {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
isLoading = false
}
}
navigationDelegate.onFail = { error in
isLoading = false
loadError = error.localizedDescription
}
}
}
}

private extension InstagramPostsWebView {
func makeCookies() -> [HTTPCookie]? {
var cookies = [HTTPCookie]()
if let darkMode = Cookies.createDarkMode(darkMode ? "true" : "false") {
cookies.append(darkMode)
}
return cookies
}
}

#if canImport(UIKit)
private extension InstagramPostsWebView {
static func isDarkMode() -> Bool {
(UIApplication.shared.connectedScenes.first as? UIWindowScene)?
.windows.first?
.rootViewController?
.traitCollection.userInterfaceStyle == .dark
}
}
#else
private extension InstagramPostsWebView {
static func isDarkMode() -> Bool {
false
}
}
#endif
26 changes: 20 additions & 6 deletions MacMagazine/MacMagazine/Features/Social/SocialView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ struct SocialView: View {
content
}
.contentMargins(.top, 20, for: .scrollContent)
.navigation(shouldUseSidebar: shouldUseSidebar, title: viewModel.social.rawValue)
.navigation(shouldUseSidebar: shouldUseSidebar,
title: viewModel.social.rawValue)
.toolbar {
ToolbarItem(placement: .primaryAction) {
menuView
Expand Down Expand Up @@ -75,11 +76,24 @@ private extension SocialView {
scrollPosition: $scrollPosition
).transition(.opacity)
case .instagram:
ContentUnavailableView(
"PΓ‘gina em construΓ§Γ£o",
systemImage: "square.and.arrow.down.badge.xmark",
description: Text("ConteΓΊdo ainda em desenvolvimento e estarΓ‘ disponΓ­vel em breve.")
)
if let url = URL(string: "https://macmagazine.com.br/posts-instagram-app/") {
InstagramPostsWebView(
colorSchema: viewModel.settingsViewModel.colorSchema,
url: url,
userAgent: "MacMagazine",
shouldUseSidebar: shouldUseSidebar
)
.transition(.opacity)
} else {
ContentUnavailableView(
"Estamos com um problema",
systemImage: "square.and.arrow.down.badge.xmark",
description: Text(
"No momento estamos com um problema tΓ©cnico. Tente novamente mais tarde."
)
)
.transition(.opacity)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions MacMagazine/MacMagazine/MainApp/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct MainView: View {
@Environment(MainViewModel.self) var viewModel

@State var searchText: String = ""
@State var splitViewVisibility: NavigationSplitViewVisibility = .all

@State private var currentlayout: LayoutType = .tabbar

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import SwiftUI

extension MainView {
var sideBarContentView: some View {
NavigationSplitView {
let isSidebarVisible =
splitViewVisibility == .all || splitViewVisibility == .doubleColumn

return NavigationSplitView(columnVisibility: $splitViewVisibility) {
sidebar
.searchable(text: $searchText, prompt: "Search items")
} detail: {
animateContentStackView(for: navigationState.selectedItem)
.environment(\.isSidebarVisible, isSidebarVisible)
.podcastMiniPlayer()
}
.navigationSplitViewStyle(.balanced)
Expand Down
8 changes: 7 additions & 1 deletion MacMagazine/MacMagazine/Modifiers/NavigationModifier.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import SwiftUI

extension View {
func navigation(shouldUseSidebar: Bool, title: String? = nil) -> some View {
func navigation(
shouldUseSidebar: Bool,
title: String? = nil
) -> some View {
modifier(NavigationModifier(
shouldUseSidebar: shouldUseSidebar,
title: title
Expand All @@ -13,11 +16,14 @@ private struct NavigationModifier: ViewModifier {
let shouldUseSidebar: Bool
let title: String?

@Environment(\.isSidebarVisible) private var isSidebarVisible

func body(content: Content) -> some View {
if shouldUseSidebar {
if let title {
content
.navigationTitle(title)
.navigationBarTitleDisplayMode(isSidebarVisible ? .inline : .large )
} else {
content
}
Expand Down
4 changes: 4 additions & 0 deletions MacMagazine/MacMagazine/Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
<string>audio</string>
<string>fetch</string>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>instagram</string>
</array>
</dict>
</plist>