Skip to content

Commit df0130c

Browse files
committed
fix: random pages.
1 parent b3a15fd commit df0130c

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

src/pages/RandomPage.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React, { useEffect, useRef } from 'react';
2+
import { useNavigate } from 'react-router-dom';
3+
import useSearchableData from '../hooks/useSearchableData';
4+
import Loading from '../components/Loading';
5+
import { useToast } from '../hooks/useToast';
6+
7+
// * `hasNavigated` Ref: I introduced a useRef variable called hasNavigated.
8+
// * Guard Clause: The useEffect now checks hasNavigated.current at the very beginning. If it's already true, it means a
9+
// navigation attempt has been made, and it returns early.
10+
// * Set Ref: hasNavigated.current is set to true just before calling navigate.
11+
//
12+
// This pattern effectively acts as a flag that ensures the navigation logic runs only once, even if React's Strict Mode
13+
// re-runs useEffect in development or if other factors cause multiple renders.
14+
//
15+
// Now, clicking "Random" should only redirect you once! ✅
16+
const RandomPage = () => {
17+
const { items, isLoading } = useSearchableData();
18+
const navigate = useNavigate();
19+
const { addToast } = useToast();
20+
const hasNavigated = useRef(false);
21+
22+
useEffect(() => {
23+
if (hasNavigated.current) return; // Prevent double navigation in StrictMode or on re-render
24+
25+
if (!isLoading && items.length > 0) {
26+
const allNavigableItems = items.filter(item => item.path && item.path !== '/random'); // Exclude itself
27+
28+
if (allNavigableItems.length > 0) {
29+
const randomIndex = Math.floor(Math.random() * allNavigableItems.length);
30+
const randomItem = allNavigableItems[randomIndex];
31+
hasNavigated.current = true; // Set ref before navigating
32+
navigate(randomItem.path);
33+
addToast({title: 'Random', message: `Navigating to ${randomItem.title || randomItem.path}`, duration: 2000});
34+
} else {
35+
hasNavigated.current = true; // Set ref before navigating
36+
navigate('/'); // Fallback to home if no other items exist
37+
addToast({title: 'Info', message: 'No random items found, redirecting to home.', duration: 3000});
38+
}
39+
} else if (!isLoading && items.length === 0) {
40+
hasNavigated.current = true; // Set ref before navigating
41+
navigate('/'); // Fallback to home if no items loaded
42+
addToast({title: 'Info', message: 'No searchable items loaded, redirecting to home.', duration: 3000});
43+
}
44+
}, [isLoading, items, navigate, addToast]); // Dependency array
45+
46+
return <Loading />; // Show loading spinner while redirecting
47+
};
48+
49+
export default RandomPage;

src/pages/apps/NotepadPage.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, {useState, useEffect, useRef} from 'react';
22
import {Link} from 'react-router-dom';
3-
import {ArrowLeftIcon, DownloadSimple, Trash, CloudRain, FloppyDisk, FolderOpen} from '@phosphor-icons/react';
3+
import {ArrowLeftIcon, DownloadSimple, Trash, CloudRain, FloppyDisk, FolderOpen, ArrowsOutLineHorizontal, ArrowsInLineHorizontal} from '@phosphor-icons/react';
44
import useSeo from '../../hooks/useSeo';
55
import {useToast} from '../../hooks/useToast';
66
import ConfirmationModal from '../../components/ConfirmationModal';
7+
import usePersistentState from '../../hooks/usePersistentState';
78

89
const NotepadPage = () => {
910
useSeo({
@@ -15,6 +16,7 @@ const NotepadPage = () => {
1516
const [text, setText] = useState('');
1617
const [isRainy, setIsRainy] = useState(false);
1718
const [isClearModalOpen, setIsClearModalOpen] = useState(false);
19+
const [isFixedSize, setIsFixedSize] = usePersistentState('fezcodex-notepad-fixed-size', true); // Default to true for fixed height
1820
const textareaRef = useRef(null);
1921
const fileInputRef = useRef(null);
2022
const {addToast} = useToast();
@@ -96,6 +98,15 @@ const NotepadPage = () => {
9698
});
9799
};
98100

101+
const toggleFixedSize = () => {
102+
setIsFixedSize(prev => !prev);
103+
addToast({
104+
title: isFixedSize ? 'Expanded' : 'Fixed Height',
105+
message: isFixedSize ? 'Notepad expanded to fill space.' : 'Notepad height is now fixed.',
106+
duration: 2000
107+
});
108+
};
109+
99110
return (
100111
<div
101112
className={`min-h-screen flex flex-col transition-colors duration-500 ${isRainy ? 'bg-gray-900' : 'bg-[#fdfbf7]'}`}>
@@ -153,6 +164,13 @@ const NotepadPage = () => {
153164
>
154165
<FolderOpen size={20} />
155166
</button>
167+
<button
168+
onClick={toggleFixedSize}
169+
className={`p-2 rounded-full transition-colors ${isFixedSize ? 'text-gray-500 hover:bg-gray-200' : 'text-blue-300 bg-blue-900/30 hover:bg-blue-900/50'}`}
170+
title={isFixedSize ? 'Expand Notepad' : 'Fix Notepad Height'}
171+
>
172+
{isFixedSize ? <ArrowsOutLineHorizontal size={20} /> : <ArrowsInLineHorizontal size={20} />}
173+
</button>
156174
<button
157175
onClick={toggleRain}
158176
className={`p-2 rounded-full transition-colors ${isRainy ? 'text-blue-300 bg-blue-900/30 hover:bg-blue-900/50' : 'text-gray-500 hover:bg-gray-200'}`}
@@ -179,7 +197,7 @@ const NotepadPage = () => {
179197

180198
{/* Notepad Area */}
181199
<div
182-
className={`flex-grow rounded-lg shadow-lg relative overflow-hidden transition-all duration-500 ${isRainy ? 'bg-gray-800 border border-gray-700' : 'bg-white border border-gray-200'}`}>
200+
className={`${isFixedSize ? 'h-[60vh]' : 'flex-grow'} rounded-lg shadow-lg relative overflow-hidden flex flex-col transition-all duration-500 ${isRainy ? 'bg-gray-800 border border-gray-700' : 'bg-white border border-gray-200'}`}>
183201
{/* Paper Lines Background */}
184202
<div
185203
className="absolute inset-0 pointer-events-none opacity-50"
@@ -196,7 +214,8 @@ const NotepadPage = () => {
196214

197215
<textarea
198216
ref={textareaRef}
199-
className={`w-full h-full p-8 pl-16 text-lg font-mono leading-8 bg-transparent border-none resize-none focus:ring-0 focus:outline-none relative z-10 ${isRainy ? 'text-gray-300 placeholder-gray-600' : 'text-gray-800 placeholder-gray-400'}`}
217+
rows={1}
218+
className={`w-full p-8 pl-16 text-lg font-mono leading-8 bg-transparent border-none resize-none focus:ring-0 focus:outline-none relative z-10 min-h-0 flex-1 ${isRainy ? 'text-gray-300 placeholder-gray-600' : 'text-gray-800 placeholder-gray-400'}`}
200219
placeholder="Start typing..."
201220
value={text}
202221
onChange={(e) => setText(e.target.value)}

0 commit comments

Comments
 (0)