✘✘ GRAYBYTE WORDPRESS FILE MANAGER ✘✘

​🇳​​🇦​​🇲​​🇪♯➤ premium290.web-hosting.com ​🇻​♯➤ 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP 🇾​♯➤ 2025

𝗛𝗢𝗠𝗘 𝗜𝗗 ♯➤ 63.250.38.37 ♯➤ 𝗔𝗗𝗠𝗜𝗡 𝗜𝗗 216.73.216.150
𝗢𝗣𝗧𝗜𝗢𝗡𝗦 ♯ CRL ♯➤ 𝗢𝗞 ┃ WGT ♯➤ 𝗢𝗞 ┃ SDO ♯➤ 𝗢𝗙𝗙 ┃ PKEX ♯➤ 𝗢𝗙𝗙
𝗗𝗘𝗔𝗖𝗧𝗜𝗩𝗔𝗧𝗘𝗗 ♯➤ 𝗔𝗟𝗟 𝗪𝗢𝗥𝗞𝗜𝗡𝗚....

𝗛𝗢𝗠𝗘
𝗖𝗨𝗥𝗥𝗘𝗡𝗧 𝗙𝗜𝗟𝗘 : /home/tdhomesa/tdtravelandlogistics.com/wp-content/plugins/jetpack/_inc//site-switcher.js
/**
 * Site Switcher for Command Palette
 * Adds a dynamic "Switch to Site" command that searches across all user's WordPress.com sites
 *
 * Requires WordPress 6.9+ for admin-wide command palette support
 *
 * @package
 */

import apiFetch from '@wordpress/api-fetch';
import { useCommandLoader } from '@wordpress/commands';
import { useMemo, useState, useEffect } from '@wordpress/element';
import { sprintf, __ } from '@wordpress/i18n';
import { siteLogo } from '@wordpress/icons';

const userId = window.jetpackSiteSwitcherConfig?.userId || 0;
const CACHE_KEY = `jetpack_site_switcher_sites_${ userId }`;
const CACHE_DURATION = 3600000; // 1 hour in milliseconds

/**
 * Get cached sites from localStorage
 */
function getCachedSites() {
	try {
		const cached = localStorage.getItem( CACHE_KEY );
		if ( ! cached ) {
			return null;
		}

		const { sites, timestamp } = JSON.parse( cached );

		// Check if cache is still valid
		if ( Date.now() - timestamp < CACHE_DURATION ) {
			return sites;
		}

		// Cache expired, remove it
		localStorage.removeItem( CACHE_KEY );
		return null;
	} catch {
		// If localStorage is not available or JSON parsing fails, return null
		return null;
	}
}

/**
 * Save sites to localStorage cache
 */
function setCachedSites( sites ) {
	try {
		localStorage.setItem(
			CACHE_KEY,
			JSON.stringify( {
				sites,
				timestamp: Date.now(),
			} )
		);
	} catch {
		// Silently fail if localStorage is not available (e.g., private browsing)
	}
}

/**
 * Fetch compact sites list from WordPress.com API
 */
async function fetchSitesFromWordPressCom() {
	// Check localStorage cache first
	const cachedSites = getCachedSites();
	if ( cachedSites ) {
		return cachedSites;
	}

	const apiPath = window.jetpackSiteSwitcherConfig?.apiPath;

	try {
		const data = await apiFetch( {
			path: apiPath,
			method: 'GET',
			global: true,
		} );

		const sites = data.sites || [];

		setCachedSites( sites );

		return sites;
	} catch {
		return [];
	}
}

/**
 * Safely extract hostname from a URL string
 *
 * @param {string} urlString - The URL to parse
 * @return {string} The hostname, or empty string if invalid
 */
function getHostnameFromURL( urlString ) {
	if ( ! urlString ) {
		return '';
	}
	try {
		return new URL( urlString ).hostname;
	} catch {
		return '';
	}
}

/**
 * Remove trailing slash from a URL string
 *
 * @param {string} url - The URL to process
 * @return {string} URL without trailing slash
 */
function untrailingslashit( url ) {
	return url ? url.replace( /\/+$/, '' ) : url;
}

/**
 * Escape special regex characters in a string
 *
 * @param {string} str - String to escape
 * @return {string} Escaped string safe for use in RegExp
 */
function escapeRegex( str ) {
	return str.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
}

/**
 * Custom hook to load site-switching commands based on search term
 *
 * @param {Object} props        - Hook properties
 * @param {string} props.search - Search term to filter sites
 * @return {Object} Object containing commands array and loading state
 */
function useSiteSwitcherCommandLoader( { search } ) {
	const [ sites, setSites ] = useState( [] );
	const [ isLoading, setIsLoading ] = useState( true );

	// Fetch sites on mount
	useEffect( () => {
		fetchSitesFromWordPressCom()
			.then( fetchedSites => {
				setSites( fetchedSites );
				setIsLoading( false );
			} )
			.catch( () => {
				setIsLoading( false );
			} );
	}, [] );

	// Generate and filter commands based on search term
	const commands = useMemo( () => {
		if ( ! sites || sites.length === 0 ) {
			return [];
		}

		const searchLower = search ? search.toLowerCase() : '';

		// Strip generic keywords from search to allow queries like "site dean" to find sites with "dean"
		const genericKeywords = [
			__( 'site', 'jetpack' ).toLowerCase(),
			__( 'switch', 'jetpack' ).toLowerCase(),
			__( 'switch site', 'jetpack' ).toLowerCase(),
		];

		let cleanedSearch = searchLower;
		genericKeywords.forEach( keyword => {
			cleanedSearch = cleanedSearch.replace(
				new RegExp( `\\b${ escapeRegex( keyword ) }\\b`, 'g' ),
				' '
			);
		} );
		cleanedSearch = cleanedSearch.trim().replace( /\s+/g, ' ' );

		// Check if the search is a prefix of any generic keyword (e.g., "swit" matches "switch")
		// If so, treat it as a generic search and show all sites
		const isGenericKeywordPrefix =
			cleanedSearch && genericKeywords.some( keyword => keyword.startsWith( cleanedSearch ) );

		// If search is empty after stripping generic keywords, or is a prefix of a generic keyword, show all sites
		const filteredSites =
			! cleanedSearch || isGenericKeywordPrefix
				? sites
				: sites.filter( site => {
						const domain = getHostnameFromURL( site.URL );
						return (
							( site.name && site.name.toLowerCase().includes( cleanedSearch ) ) ||
							domain.toLowerCase().includes( cleanedSearch )
						);
				  } );

		// Filter out sites with invalid URLs (can't navigate to them anyway)
		const validSites = filteredSites.filter( site => {
			return site.URL && getHostnameFromURL( site.URL ) !== '';
		} );

		// Exclude the current site from the list
		const currentURL = untrailingslashit( window.location.href.toLowerCase() );
		const otherSites = validSites.filter( site => {
			// Normalize site URL for comparison
			const siteURL = untrailingslashit( site.URL.toLowerCase() );
			// Check if current URL starts with site URL (handles multisite subdirectory installs)
			// e.g., current: example.com/site1/wp-admin matches site: example.com/site1
			return ! currentURL.startsWith( siteURL );
		} );

		return otherSites.map( site => {
			// Extract domain from URL for display - don't want to display the protocol.
			const domain = getHostnameFromURL( site.URL );

			const iconElement = site.icon?.img ? <img src={ site.icon.img } alt="" /> : siteLogo;

			// Use site name if available, otherwise just show domain
			const label = site.name
				? sprintf(
						/* translators: %1$s: site name, %2$s: site domain */
						__( 'Switch to %1$s (%2$s)', 'jetpack' ),
						site.name,
						domain
				  )
				: sprintf(
						/* translators: %s: site domain */
						__( 'Switch to %s', 'jetpack' ),
						domain
				  );

			return {
				name: `jetpack/switch-to-site-${ domain }`,
				label,
				icon: iconElement,
				callback: ( { close } ) => {
					try {
						window.location.href = new URL( '/wp-admin', site.URL ).href;
					} catch {
						// If URL is malformed, don't navigate
					}
					close();
				},
				keywords: [
					site.name,
					domain,
					__( 'site', 'jetpack' ),
					__( 'switch site', 'jetpack' ),
				].filter( Boolean ),
			};
		} );
	}, [ sites, search ] );

	return {
		commands,
		isLoading,
	};
}

/**
 * Component that registers the site switcher command loader
 */
function JetpackSiteSwitcher() {
	useCommandLoader( {
		name: 'jetpack/site-switcher',
		hook: useSiteSwitcherCommandLoader,
	} );

	return null;
}

// Render the site switcher into wp-admin
// This works with WordPress 6.9+ admin-wide command palette
if ( typeof window !== 'undefined' && window.wp && window.wp.element && window.wp.commands ) {
	const { createRoot, createElement } = window.wp.element;

	// Create a container for our site switcher
	const container = document.createElement( 'div' );
	container.id = 'jetpack-site-switcher';
	container.style.display = 'none'; // Hidden, as we only need the hooks to run

	// Wait for DOM to be ready
	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', () => {
			document.body.appendChild( container );
			createRoot( container ).render( createElement( JetpackSiteSwitcher ) );
		} );
	} else {
		document.body.appendChild( container );
		createRoot( container ).render( createElement( JetpackSiteSwitcher ) );
	}
}


Current_dir [ 𝗪𝗥𝗜𝗧𝗘𝗔𝗕𝗟𝗘 ] Document_root [ 𝗪𝗥𝗜𝗧𝗘𝗔𝗕𝗟𝗘 ]


[ Back ]
𝗡𝗔𝗠𝗘
𝗦𝗜𝗭𝗘
𝗟𝗔𝗦𝗧 𝗧𝗢𝗨𝗖𝗛
𝗨𝗦𝗘𝗥
𝗦𝗧𝗔𝗧𝗨𝗦
𝗙𝗨𝗡𝗖𝗧𝗜𝗢𝗡𝗦
..
--
22 Jun 2026 6.38 AM
tdhomesa / tdhomesa
0755
blocks
--
11 Jun 2026 10.18 AM
tdhomesa / tdhomesa
0755
build
--
11 Jun 2026 10.18 AM
tdhomesa / tdhomesa
0755
fonts
--
11 Jun 2026 10.18 AM
tdhomesa / tdhomesa
0755
genericons
--
11 Jun 2026 10.18 AM
tdhomesa / tdhomesa
0755
lib
--
11 Jun 2026 10.18 AM
tdhomesa / tdhomesa
0755
accessible-focus.js
0.605 KB
28 Jul 2020 9.06 PM
tdhomesa / tdhomesa
0644
blogging-prompts.php
8.972 KB
25 May 2026 6.51 PM
tdhomesa / tdhomesa
0644
class.jetpack-provision.php
9.564 KB
8 Dec 2025 7.41 PM
tdhomesa / tdhomesa
0644
crowdsignal-shortcode.js
0.634 KB
16 Dec 2024 7.21 PM
tdhomesa / tdhomesa
0644
crowdsignal-survey.js
0.271 KB
28 Jul 2020 9.06 PM
tdhomesa / tdhomesa
0644
deprecate.js
2.263 KB
24 Nov 2025 10.00 PM
tdhomesa / tdhomesa
0644
facebook-embed.js
1.004 KB
11 Jan 2022 10.52 PM
tdhomesa / tdhomesa
0644
gallery-settings.js
1 KB
28 Jul 2020 9.06 PM
tdhomesa / tdhomesa
0644
genericons.php
0.496 KB
30 Sep 2024 9.15 PM
tdhomesa / tdhomesa
0644
jetpack-admin.js
1.557 KB
3 May 2023 12.08 AM
tdhomesa / tdhomesa
0644
jetpack-deactivate-dialog.js
2.901 KB
16 Dec 2024 7.21 PM
tdhomesa / tdhomesa
0644
jetpack-modules.js
2.373 KB
16 Dec 2024 7.21 PM
tdhomesa / tdhomesa
0644
jetpack-modules.models.js
2.15 KB
24 Nov 2025 10.00 PM
tdhomesa / tdhomesa
0644
jetpack-modules.views.js
1.686 KB
24 Nov 2025 10.00 PM
tdhomesa / tdhomesa
0644
polldaddy-shortcode.js
2.645 KB
23 Mar 2026 7.45 PM
tdhomesa / tdhomesa
0644
site-switcher-endpoint.php
2.331 KB
19 Jan 2026 9.00 PM
tdhomesa / tdhomesa
0644
site-switcher.js
7.613 KB
2 Feb 2026 6.45 PM
tdhomesa / tdhomesa
0644
site-switcher.php
1.902 KB
2 Feb 2026 6.45 PM
tdhomesa / tdhomesa
0644
social-logos.php
0.82 KB
30 Mar 2026 9.02 PM
tdhomesa / tdhomesa
0644
twitter-timeline.js
0.346 KB
8 Jun 2026 8.52 PM
tdhomesa / tdhomesa
0644

✘✘ GRAYBYTE WORDPRESS FILE MANAGER @ 2026 CONTACT ME ✘✘
Static GIF Static GIF