feat: major update - Markdown Editor, CodeMirror upgrades, SEO improvements, tool cleanup
- Added new Markdown Editor with live preview, GFM support, PDF/HTML/DOCX export - Upgraded all paste fields to CodeMirror with syntax highlighting and expand/collapse - Enhanced Object Editor with advanced URL fetching and preview mode - Improved export views with syntax highlighting in Table/Object editors - Implemented SEO improvements (FAQ schema, breadcrumbs, internal linking) - Added Related Tools recommendations component - Created custom 404 page with tool suggestions - Consolidated tools: removed JSON, Serialize, CSV-JSON (merged into main editors) - Updated documentation and cleaned up redundant files - Updated release notes with user-centric improvements
This commit is contained in:
66
src/components/MobileAdBanner.js
Normal file
66
src/components/MobileAdBanner.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
/**
|
||||
* MobileAdBanner Component - Sticky bottom banner for mobile
|
||||
* Visible only on mobile/tablet, hidden on desktop
|
||||
* Includes close button for better UX
|
||||
*/
|
||||
const MobileAdBanner = ({ slot = 'REPLACE_WITH_MOBILE_SLOT' }) => {
|
||||
const [visible, setVisible] = useState(true);
|
||||
const [closed, setClosed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if user previously closed the banner (session storage)
|
||||
const wasClosed = sessionStorage.getItem('mobileAdClosed');
|
||||
if (wasClosed === 'true') {
|
||||
setClosed(true);
|
||||
setVisible(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (visible && !closed) {
|
||||
try {
|
||||
(window.adsbygoogle = window.adsbygoogle || []).push({});
|
||||
} catch (e) {
|
||||
console.error('AdSense error:', e);
|
||||
}
|
||||
}
|
||||
}, [visible, closed]);
|
||||
|
||||
const handleClose = () => {
|
||||
setVisible(false);
|
||||
setClosed(true);
|
||||
sessionStorage.setItem('mobileAdClosed', 'true');
|
||||
};
|
||||
|
||||
if (!visible || closed) return null;
|
||||
|
||||
return (
|
||||
<div className="xl:hidden fixed bottom-0 left-0 right-0 z-50 bg-white dark:bg-gray-900 shadow-lg border-t border-gray-200 dark:border-gray-700">
|
||||
<button
|
||||
onClick={handleClose}
|
||||
className="absolute top-1 right-1 p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 bg-white dark:bg-gray-800 rounded-full shadow-sm"
|
||||
aria-label="Close ad"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
<div className="flex justify-center py-2">
|
||||
<ins
|
||||
className="adsbygoogle"
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '320px',
|
||||
height: '50px'
|
||||
}}
|
||||
data-ad-client="ca-pub-8644544686212757"
|
||||
data-ad-slot={slot}
|
||||
data-ad-format="fixed"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobileAdBanner;
|
||||
Reference in New Issue
Block a user