-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fcb73b6
commit 6ebb7a6
Showing
11 changed files
with
265 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// | ||
// SpotifyAuthCookie.swift | ||
// Spwifiy | ||
// | ||
// Created by Peter Duanmu on 12/4/24. | ||
// | ||
|
||
import Foundation | ||
|
||
struct SpotifyAuthCookie: Codable { | ||
let name: String | ||
let value: String | ||
let expiresDate: Date | ||
let domain: String | ||
|
||
var httpCookie: HTTPCookie? { | ||
let properties: [HTTPCookiePropertyKey: Any] = [ | ||
.domain: domain, | ||
.path: "/", | ||
.name: name, | ||
.value: value, | ||
.secure: true, | ||
.expires: expiresDate | ||
] | ||
|
||
return HTTPCookie(properties: properties) | ||
} | ||
|
||
init(cookie: HTTPCookie) { | ||
self.name = cookie.name | ||
self.value = cookie.value | ||
self.expiresDate = cookie.expiresDate ?? Date.now | ||
self.domain = cookie.domain | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// SpotifyAuthResponse.swift | ||
// Spwifiy | ||
// | ||
// Created by Peter Duanmu on 12/4/24. | ||
// | ||
|
||
struct SpotifyAuthResponse: Decodable { | ||
let clientId: String | ||
let accessToken: String | ||
let accessTokenExpirationTimestampMs: Double | ||
let isAnonymous: Bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// | ||
// SpotifyCustomLogin.swift | ||
// Spwifiy | ||
// | ||
// Created by Peter Duanmu on 12/4/24. | ||
// | ||
|
||
import SwiftUI | ||
import WebKit | ||
import KeychainAccess | ||
|
||
class SpotifyAuthManager: NSObject, WKHTTPCookieStoreObserver { | ||
|
||
public enum AuthStatus { | ||
case success, failed, inProcess, cookieSet | ||
} | ||
|
||
public static let spDcCookieKey = "sp_dc_cookie" | ||
public static let spTCookieKey = "sp_t_cookie" | ||
|
||
@Binding var authStatus: AuthStatus | ||
|
||
let keychain: Keychain | ||
let webStore: WKWebsiteDataStore | ||
|
||
init(webStore: WKWebsiteDataStore, authStatus: Binding<AuthStatus>) { | ||
self._authStatus = authStatus | ||
self.keychain = Keychain(service: SpwifiyApp.service) | ||
self.webStore = webStore | ||
|
||
super.init() | ||
|
||
self.webStore.httpCookieStore.add(self) | ||
} | ||
|
||
func cookiesDidChange(in cookieStore: WKHTTPCookieStore) { | ||
cookieStore.getAllCookies { cookies in | ||
if let spDcCookie = cookies.filter({ $0.name == "sp_dc" }).first, | ||
let spTCookie = cookies.filter({ $0.name == "sp_t" }).first { | ||
let encoder = JSONEncoder() | ||
|
||
do { | ||
self.keychain[ | ||
data: SpotifyAuthManager.spDcCookieKey | ||
] = try encoder.encode(SpotifyAuthCookie(cookie: spDcCookie)) | ||
|
||
self.keychain[ | ||
data: SpotifyAuthManager.spTCookieKey | ||
] = try encoder.encode(SpotifyAuthCookie(cookie: spTCookie)) | ||
|
||
self.authStatus = .cookieSet | ||
} catch { | ||
print("unable to store cookie data in keychain: \(error)") | ||
|
||
self.authStatus = .failed | ||
} | ||
|
||
cookies.forEach { | ||
self.webStore.httpCookieStore.delete($0) | ||
} | ||
|
||
self.webStore.httpCookieStore.remove(self) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
struct SpotifyWebView: NSViewRepresentable { | ||
|
||
let webStore: WKWebsiteDataStore | ||
|
||
let spotifyAuthManager: SpotifyAuthManager | ||
var webView: WKWebView | ||
|
||
init(authStatus: Binding<SpotifyAuthManager.AuthStatus>) { | ||
self.webStore = .default() | ||
|
||
let config = WKWebViewConfiguration() | ||
config.websiteDataStore = webStore | ||
config.limitsNavigationsToAppBoundDomains = false | ||
|
||
self.webView = WKWebView(frame: .zero, configuration: config) | ||
|
||
self.spotifyAuthManager = SpotifyAuthManager( | ||
webStore: self.webStore, | ||
authStatus: authStatus | ||
) | ||
|
||
self.webView.load(URLRequest(url: URL(string: "https://accounts.spotify.com/login")!)) | ||
} | ||
|
||
func makeNSView(context: Context) -> some NSView { | ||
return webView | ||
} | ||
|
||
func updateNSView(_ nsView: NSViewType, context: Context) { | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.