| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- import Foundation
- enum RedditLoginBridgeStyle {
- static let messageHandlerName = "reddoraLogin"
- /// Intercepts Log In and blocks Reddit's embedded auth modal, which cannot complete
- /// credential sign-in reliably in WKWebView ("Server error. Try again later.").
- static let injectionScript = """
- (function() {
- if (window.__reddoraLoginBridgeInstalled) return;
- window.__reddoraLoginBridgeInstalled = true;
- const LOGIN_PATTERN = /log\\s*in/i;
- const HEADER_SELECTORS = 'header, [role="banner"], #header, faceplate-header, nav';
- const AUTH_MODAL_SELECTORS = [
- 'auth-flow-modal',
- '[data-testid="login-modal"]',
- '#credentials-login-popup',
- 'faceplate-modal[slot="login"]',
- 'faceplate-modal[open]'
- ].join(', ');
- function nodeLabel(node) {
- if (!(node instanceof Element)) return '';
- return (
- (node.textContent || '') + ' ' +
- (node.getAttribute('aria-label') || '') + ' ' +
- (node.getAttribute('title') || '')
- ).trim();
- }
- function isHeaderLoginTrigger(node) {
- if (!(node instanceof Element)) return false;
- const clickable = node.matches('button, a, [role="button"], faceplate-tracker, faceplate-button')
- ? node
- : node.closest('button, a, [role="button"], faceplate-tracker, faceplate-button');
- if (!clickable) return false;
- if (clickable.id === 'login-button') return true;
- if (clickable.getAttribute('data-testid') === 'login-button') return true;
- const label = nodeLabel(clickable);
- if (!LOGIN_PATTERN.test(label)) return false;
- return !!clickable.closest(HEADER_SELECTORS);
- }
- function isLoginPage() {
- const host = window.location.hostname.toLowerCase();
- return (host === 'www.reddit.com' || host === 'reddit.com' || host === 'new.reddit.com')
- && /^\\/login\\/?$/i.test(window.location.pathname);
- }
- function requestInAppLogin() {
- if (isLoginPage()) return;
- if (window.__reddoraLoginPanelRequested) return;
- window.__reddoraLoginPanelRequested = true;
- setTimeout(function() {
- window.__reddoraLoginPanelRequested = false;
- }, 1000);
- if (
- window.webkit &&
- window.webkit.messageHandlers &&
- window.webkit.messageHandlers.reddoraLogin
- ) {
- window.webkit.messageHandlers.reddoraLogin.postMessage('open');
- }
- }
- function isAuthModal(element) {
- if (!(element instanceof Element)) return false;
- if (element.matches('auth-flow-modal, [data-testid="login-modal"], #credentials-login-popup')) {
- return true;
- }
- if (element.matches('faceplate-modal')) {
- const label = nodeLabel(element);
- return LOGIN_PATTERN.test(label) || !!element.querySelector('input[type="password"]');
- }
- return false;
- }
- window.__reddoraCloseRedditAuthModal = function() {
- document.querySelectorAll(AUTH_MODAL_SELECTORS).forEach(function(element) {
- if (!isAuthModal(element)) return;
- const closeButton = element.querySelector(
- '[aria-label="Close"], [aria-label="close"], button[close]'
- );
- if (closeButton) {
- closeButton.click();
- } else {
- element.remove();
- }
- });
- };
- function installAuthModalBlocker() {
- if (isLoginPage()) return;
- const STYLE_ID = 'reddora-auth-block-style';
- if (!document.getElementById(STYLE_ID)) {
- const style = document.createElement('style');
- style.id = STYLE_ID;
- style.textContent = [
- 'auth-flow-modal,',
- '[data-testid="login-modal"],',
- '#credentials-login-popup {',
- ' display: none !important;',
- ' pointer-events: none !important;',
- '}'
- ].join('\\n');
- (document.head || document.documentElement).appendChild(style);
- }
- const observer = new MutationObserver(function() {
- if (isLoginPage()) return;
- let foundAuthModal = false;
- document.querySelectorAll(AUTH_MODAL_SELECTORS).forEach(function(element) {
- if (!isAuthModal(element)) return;
- foundAuthModal = true;
- element.remove();
- });
- if (foundAuthModal) {
- requestInAppLogin();
- }
- });
- observer.observe(document.documentElement, { childList: true, subtree: true });
- }
- document.addEventListener('click', function(event) {
- if (isLoginPage()) return;
- const path = event.composedPath();
- for (let i = 0; i < path.length; i++) {
- if (!isHeaderLoginTrigger(path[i])) continue;
- event.preventDefault();
- event.stopImmediatePropagation();
- window.__reddoraCloseRedditAuthModal();
- requestInAppLogin();
- return;
- }
- }, true);
- installAuthModalBlocker();
- })();
- """
- static let closeAuthModalScript = "window.__reddoraCloseRedditAuthModal && window.__reddoraCloseRedditAuthModal();"
- }
|