Build success
This commit is contained in:
parent
563845dc68
commit
771248be35
@ -212,7 +212,14 @@ else
|
|||||||
fi`
|
fi`
|
||||||
};
|
};
|
||||||
|
|
||||||
return samples[codeSample] || samples.javascript;
|
type SampleLanguage = keyof typeof samples;
|
||||||
|
|
||||||
|
// Type guard to check if codeSample is a valid key of samples
|
||||||
|
const isValidSample = (sample: string): sample is SampleLanguage => {
|
||||||
|
return sample in samples;
|
||||||
|
};
|
||||||
|
|
||||||
|
return isValidSample(codeSample) ? samples[codeSample] : samples.javascript;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDownload = (e: React.MouseEvent) => {
|
const handleDownload = (e: React.MouseEvent) => {
|
||||||
@ -289,7 +296,7 @@ fi`
|
|||||||
}}
|
}}
|
||||||
drag="x"
|
drag="x"
|
||||||
dragConstraints={{ left: -50, right: 50 }}
|
dragConstraints={{ left: -50, right: 50 }}
|
||||||
onDragEnd={(e, { offset, velocity }) => {
|
onDragEnd={(e, { offset }) => {
|
||||||
if (offset.x > 50) handleLike();
|
if (offset.x > 50) handleLike();
|
||||||
else if (offset.x < -50) handleDislike();
|
else if (offset.x < -50) handleDislike();
|
||||||
}}
|
}}
|
||||||
|
@ -24,7 +24,7 @@ const HelpDialog: React.FC<HelpDialogProps> = ({ isOpen, onClose, isDarkMode })
|
|||||||
|
|
||||||
<h3 className="text-xl font-semibold">How it works:</h3>
|
<h3 className="text-xl font-semibold">How it works:</h3>
|
||||||
<ol className="list-decimal list-inside space-y-2">
|
<ol className="list-decimal list-inside space-y-2">
|
||||||
<li>You'll be presented with color schemes one at a time.</li>
|
<li>You'll be presented with color schemes one at a time.</li>
|
||||||
<li>Swipe right or click the heart icon to like a scheme.</li>
|
<li>Swipe right or click the heart icon to like a scheme.</li>
|
||||||
<li>Swipe left or click the cross icon to dislike a scheme.</li>
|
<li>Swipe left or click the cross icon to dislike a scheme.</li>
|
||||||
<li>The app learns from your preferences and generates new schemes based on what you like.</li>
|
<li>The app learns from your preferences and generates new schemes based on what you like.</li>
|
||||||
@ -39,7 +39,7 @@ const HelpDialog: React.FC<HelpDialogProps> = ({ isOpen, onClose, isDarkMode })
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>The more you interact with TerminalTinder, the better it becomes at suggesting color schemes. All information is local, so refreshing the page refreshes learning.</p>
|
<p>The more you interact with TerminalTinder, the better it becomes at suggesting color schemes. All information is local, so refreshing the page refreshes learning.</p>
|
||||||
<p>Made with ❤️ by <a href="https://dws.rip" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:text-blue-600">DWS</a> - It's your internet, take it back.</p>
|
<p>It's your internet, take it back.</p>
|
||||||
<hr className="my-4 border-t border-gray-200 w-full" />
|
<hr className="my-4 border-t border-gray-200 w-full" />
|
||||||
<p>All credit for any non generated color schemes goes to their original creators. Color schemes are sourced from <a href="https://github.com/Mayccoll/Gogh" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:text-blue-600">Gogh</a>.</p>
|
<p>All credit for any non generated color schemes goes to their original creators. Color schemes are sourced from <a href="https://github.com/Mayccoll/Gogh" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:text-blue-600">Gogh</a>.</p>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import { ColorScheme } from '../utils/colorSchemes';
|
import { ColorScheme } from '../utils/colorSchemes';
|
||||||
import { generateYAML, generateJSON, generateXResources, generateTOML } from '../utils/exportFormats';
|
import { generateYAML, generateJSON, generateXResources, generateTOML } from '../utils/exportFormats';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
@ -13,8 +13,6 @@ interface HistoryPopupProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const HistoryPopup: React.FC<HistoryPopupProps> = ({ likedSchemes, dislikedSchemes, onClose, isDarkMode, outputFormat }) => {
|
const HistoryPopup: React.FC<HistoryPopupProps> = ({ likedSchemes, dislikedSchemes, onClose, isDarkMode, outputFormat }) => {
|
||||||
const [copiedColor, setCopiedColor] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const handleDownload = (scheme: ColorScheme) => {
|
const handleDownload = (scheme: ColorScheme) => {
|
||||||
let content: string;
|
let content: string;
|
||||||
let fileExtension: string;
|
let fileExtension: string;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
// Import the CodeSample type
|
||||||
|
import { CodeSample } from '../utils/types';
|
||||||
|
|
||||||
interface SettingsProps {
|
interface SettingsProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -8,8 +11,8 @@ interface SettingsProps {
|
|||||||
onToggleDarkMode: () => void;
|
onToggleDarkMode: () => void;
|
||||||
outputFormat: string;
|
outputFormat: string;
|
||||||
setOutputFormat: (format: string) => void;
|
setOutputFormat: (format: string) => void;
|
||||||
codeSample: string;
|
codeSample: CodeSample;
|
||||||
setCodeSample: (sample: string) => void;
|
setCodeSample: (sample: CodeSample) => void;
|
||||||
saveSettings: boolean;
|
saveSettings: boolean;
|
||||||
setSaveSettings: (save: boolean) => void;
|
setSaveSettings: (save: boolean) => void;
|
||||||
}
|
}
|
||||||
@ -91,7 +94,7 @@ const Settings: React.FC<SettingsProps> = ({
|
|||||||
<label className="block mb-2">Code Sample</label>
|
<label className="block mb-2">Code Sample</label>
|
||||||
<select
|
<select
|
||||||
value={codeSample}
|
value={codeSample}
|
||||||
onChange={(e) => setCodeSample(e.target.value)}
|
onChange={(e) => setCodeSample(e.target.value as CodeSample)}
|
||||||
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
|
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
|
||||||
>
|
>
|
||||||
<option value="c">C</option>
|
<option value="c">C</option>
|
||||||
|
44
app/page.tsx
44
app/page.tsx
@ -8,6 +8,8 @@ import Settings from "./components/Settings";
|
|||||||
import HelpDialog from "./components/HelpDialog";
|
import HelpDialog from "./components/HelpDialog";
|
||||||
import { ColorScheme, knownSchemes, generateRandomScheme, generateSchemeFromGeneticAlgorithm } from './utils/colorSchemes';
|
import { ColorScheme, knownSchemes, generateRandomScheme, generateSchemeFromGeneticAlgorithm } from './utils/colorSchemes';
|
||||||
import { AnimatePresence } from 'framer-motion';
|
import { AnimatePresence } from 'framer-motion';
|
||||||
|
import { CodeSample } from './utils/types';
|
||||||
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [schemes, setSchemes] = useState<ColorScheme[]>([]);
|
const [schemes, setSchemes] = useState<ColorScheme[]>([]);
|
||||||
@ -18,9 +20,22 @@ export default function Home() {
|
|||||||
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
|
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
|
||||||
const [isHelpOpen, setIsHelpOpen] = useState(false);
|
const [isHelpOpen, setIsHelpOpen] = useState(false);
|
||||||
const [outputFormat, setOutputFormat] = useState('yaml');
|
const [outputFormat, setOutputFormat] = useState('yaml');
|
||||||
const [codeSample, setCodeSample] = useState('javascript');
|
const [codeSample, setCodeSample] = useState<CodeSample>('javascript');
|
||||||
const [saveSettings, setSaveSettings] = useState(false);
|
const [saveSettings, setSaveSettings] = useState(false);
|
||||||
|
|
||||||
|
const generateNewSchemes = (count: number) => {
|
||||||
|
const knownCount = Math.floor(count / 2);
|
||||||
|
const generatedCount = count - knownCount;
|
||||||
|
const newSchemes = [
|
||||||
|
...knownSchemes.sort(() => 0.5 - Math.random()).slice(0, knownCount),
|
||||||
|
...Array(generatedCount).fill(null).map(() =>
|
||||||
|
likedSchemes.length > 0 ? generateSchemeFromGeneticAlgorithm(likedSchemes, dislikedSchemes) : generateRandomScheme()
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
setSchemes(prevSchemes => [...prevSchemes, ...newSchemes].sort(() => 0.5 - Math.random()));
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
generateNewSchemes(8);
|
generateNewSchemes(8);
|
||||||
setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches);
|
setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||||
@ -55,19 +70,6 @@ export default function Home() {
|
|||||||
localStorage.setItem('dislikedSchemes', JSON.stringify(dislikedSchemes));
|
localStorage.setItem('dislikedSchemes', JSON.stringify(dislikedSchemes));
|
||||||
}, [dislikedSchemes]);
|
}, [dislikedSchemes]);
|
||||||
|
|
||||||
const generateNewSchemes = (count: number) => {
|
|
||||||
const knownCount = Math.floor(count / 2);
|
|
||||||
const generatedCount = count - knownCount;
|
|
||||||
const newSchemes = [
|
|
||||||
...knownSchemes.sort(() => 0.5 - Math.random()).slice(0, knownCount),
|
|
||||||
...Array(generatedCount).fill(null).map(() =>
|
|
||||||
likedSchemes.length > 0 ? generateSchemeFromGeneticAlgorithm(likedSchemes, dislikedSchemes) : generateRandomScheme()
|
|
||||||
)
|
|
||||||
];
|
|
||||||
|
|
||||||
setSchemes(prevSchemes => [...prevSchemes, ...newSchemes].sort(() => 0.5 - Math.random()));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (saveSettings) {
|
if (saveSettings) {
|
||||||
const settings = JSON.stringify({ outputFormat, codeSample });
|
const settings = JSON.stringify({ outputFormat, codeSample });
|
||||||
@ -97,10 +99,6 @@ export default function Home() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleDarkMode = () => {
|
|
||||||
setIsDarkMode(prev => !prev);
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleHistory = () => {
|
const toggleHistory = () => {
|
||||||
setIsHistoryOpen(!isHistoryOpen);
|
setIsHistoryOpen(!isHistoryOpen);
|
||||||
};
|
};
|
||||||
@ -113,14 +111,6 @@ export default function Home() {
|
|||||||
setIsHelpOpen(!isHelpOpen);
|
setIsHelpOpen(!isHelpOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAllSchemes = () => {
|
|
||||||
const allSchemes = [...likedSchemes, ...dislikedSchemes];
|
|
||||||
const uniqueSchemes = allSchemes.filter((scheme, index, self) =>
|
|
||||||
index === self.findIndex((t) => t.name === scheme.name)
|
|
||||||
);
|
|
||||||
return uniqueSchemes.reverse(); // Most recent first
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen w-screen overflow-hidden font-[family-name:var(--font-geist-sans)] dark:bg-gray-900 dark:text-white transition-colors duration-300">
|
<div className="min-h-screen w-screen overflow-hidden font-[family-name:var(--font-geist-sans)] dark:bg-gray-900 dark:text-white transition-colors duration-300">
|
||||||
<header className="absolute top-2 left-2 right-2 flex justify-between items-start z-20">
|
<header className="absolute top-2 left-2 right-2 flex justify-between items-start z-20">
|
||||||
@ -177,7 +167,7 @@ export default function Home() {
|
|||||||
outputFormat={outputFormat}
|
outputFormat={outputFormat}
|
||||||
setOutputFormat={setOutputFormat}
|
setOutputFormat={setOutputFormat}
|
||||||
codeSample={codeSample}
|
codeSample={codeSample}
|
||||||
setCodeSample={setCodeSample}
|
setCodeSample={(sample: CodeSample) => setCodeSample(sample)}
|
||||||
saveSettings={saveSettings}
|
saveSettings={saveSettings}
|
||||||
setSaveSettings={setSaveSettings}
|
setSaveSettings={setSaveSettings}
|
||||||
/>
|
/>
|
||||||
|
@ -132,20 +132,20 @@ function generateSchemeFromGeneticAlgorithm(likedSchemes: ColorScheme[], dislike
|
|||||||
const newScheme: ColorScheme = JSON.parse(JSON.stringify(parentScheme)); // Deep copy
|
const newScheme: ColorScheme = JSON.parse(JSON.stringify(parentScheme)); // Deep copy
|
||||||
|
|
||||||
// Mutate colors
|
// Mutate colors
|
||||||
Object.keys(newScheme.colors).forEach((colorGroup: keyof typeof newScheme.colors) => {
|
(Object.keys(newScheme.colors) as Array<keyof typeof newScheme.colors>).forEach((colorGroup) => {
|
||||||
Object.keys(newScheme.colors[colorGroup]).forEach((colorName: string) => {
|
Object.keys(newScheme.colors[colorGroup]).forEach((colorName) => {
|
||||||
if (Math.random() < 0.3) { // 30% chance of mutation
|
if (Math.random() < 0.3) { // 30% chance of mutation
|
||||||
(newScheme.colors[colorGroup] as any)[colorName] = mutateColor((newScheme.colors[colorGroup] as any)[colorName]);
|
(newScheme.colors[colorGroup] as Record<string, string>)[colorName] = mutateColor((newScheme.colors[colorGroup] as Record<string, string>)[colorName]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Avoid similarities with disliked schemes
|
// Avoid similarities with disliked schemes
|
||||||
dislikedSchemes.forEach(dislikedScheme => {
|
dislikedSchemes.forEach(dislikedScheme => {
|
||||||
Object.keys(newScheme.colors).forEach((colorGroup: keyof typeof newScheme.colors) => {
|
(Object.keys(newScheme.colors) as Array<keyof typeof newScheme.colors>).forEach((colorGroup) => {
|
||||||
Object.keys(newScheme.colors[colorGroup]).forEach((colorName: string) => {
|
Object.keys(newScheme.colors[colorGroup]).forEach((colorName) => {
|
||||||
if ((newScheme.colors[colorGroup] as any)[colorName] === (dislikedScheme.colors[colorGroup] as any)[colorName]) {
|
if ((newScheme.colors[colorGroup] as Record<string, string>)[colorName] === (dislikedScheme.colors[colorGroup] as Record<string, string>)[colorName]) {
|
||||||
(newScheme.colors[colorGroup] as any)[colorName] = mutateColor((newScheme.colors[colorGroup] as any)[colorName]);
|
(newScheme.colors[colorGroup] as Record<string, string>)[colorName] = mutateColor((newScheme.colors[colorGroup] as Record<string, string>)[colorName]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
1
app/utils/types.ts
Normal file
1
app/utils/types.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type CodeSample = 'c' | 'python' | 'rust' | 'go' | 'javascript' | 'java' | 'bash';
|
Loading…
x
Reference in New Issue
Block a user