fix: handle extension oauth callback on ios

This commit is contained in:
zarzet 2026-04-13 15:55:47 +07:00
parent ed020c9303
commit 7405855e01
2 changed files with 23 additions and 17 deletions

View file

@ -70,21 +70,22 @@ import Gobackend // Import Go framework
GeneratedPluginRegistrant.register(with: self)
if let url = launchOptions?[.url] as? URL {
handleExtensionOAuthRedirect(url: url)
_ = handleExtensionOAuthRedirect(url: url)
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
/// PKCE OAuth return URL: spotiflac://callback?code=...&state=<extension_id>
private func handleExtensionOAuthRedirect(url: URL) {
guard let scheme = url.scheme?.lowercased(), scheme == "spotiflac" else { return }
@discardableResult
private func handleExtensionOAuthRedirect(url: URL) -> Bool {
guard let scheme = url.scheme?.lowercased(), scheme == "spotiflac" else { return false }
let host = (url.host ?? "").lowercased()
let path = url.path.lowercased()
let ok =
host == "callback" || host == "spotify-callback" || path.contains("callback")
guard ok else { return }
guard ok else { return false }
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return
return false
}
let q = components.queryItems ?? []
let code =
@ -93,10 +94,10 @@ import Gobackend // Import Go framework
let state =
q.first { $0.name == "state" }?.value?.trimmingCharacters(
in: .whitespacesAndNewlines) ?? ""
if code.isEmpty { return }
if code.isEmpty { return false }
if state.isEmpty {
NSLog("SpotiFLAC: Extension OAuth redirect missing state (extension id)")
return
return false
}
streamQueue.async {
var err: NSError?
@ -107,6 +108,7 @@ import Gobackend // Import Go framework
"SpotiFLAC: Extension OAuth complete failed: \(err.localizedDescription)")
}
}
return true
}
override func application(
@ -114,7 +116,9 @@ import Gobackend // Import Go framework
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
handleExtensionOAuthRedirect(url: url)
if handleExtensionOAuthRedirect(url: url) {
return true
}
return super.application(app, open: url, options: options)
}

View file

@ -443,7 +443,9 @@ class _ExtensionDetailPageState extends ConsumerState<ExtensionDetailPage> {
}
/// Extensions may return `setting_updates` from button actions (e.g. OAuth URL field).
Future<void> _handleExtensionActionPayload(Map<String, dynamic> payload) async {
Future<void> _handleExtensionActionPayload(
Map<String, dynamic> payload,
) async {
final raw = payload['setting_updates'];
if (raw is! Map) return;
final partial = <String, dynamic>{};
@ -511,19 +513,19 @@ class _OauthLoginLinkPreview extends StatelessWidget {
return Text(
'Tap Connect to Spotify to fill this field.',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: colorScheme.onSurfaceVariant,
fontStyle: FontStyle.italic,
),
color: colorScheme.onSurfaceVariant,
fontStyle: FontStyle.italic,
),
);
}
return SelectionArea(
child: Text(
text,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: colorScheme.primary,
fontFamily: 'monospace',
fontSize: 11,
),
color: colorScheme.primary,
fontFamily: 'monospace',
fontSize: 11,
),
),
);
}
@ -878,7 +880,7 @@ class _SettingItemState extends State<_SettingItem> {
Map<String, dynamic> payload = result;
final nested = result['result'];
if (nested is Map) {
payload = Map<String, dynamic>.from(nested as Map);
payload = Map<String, dynamic>.from(nested);
}
final success = payload['success'] as bool? ?? false;