Name fixes, more output formats, algo changes

This commit is contained in:
2024-09-10 12:50:15 -04:00
parent fdd210e13e
commit 9355fc5a12
12 changed files with 760 additions and 90 deletions

View File

@ -1,10 +1,12 @@
import React, { useState } from 'react';
import Image from 'next/image';
import { ColorScheme } from '../utils/colorSchemes';
import { generateYAML, generateJSON, generateXResources, generateTOML } from '../utils/exportFormats';
import { generateYAML, generateJSON, generateXResources, generateTOML, generateITerm2, generateWindowsTerminal, generateTerminalApp } from '../utils/exportFormats';
import { Highlight, themes } from 'prism-react-renderer';
import { motion, useAnimation } from 'framer-motion';
import ColorPalette from './ColorPalette';
import confetti from 'canvas-confetti';
import { AppSettings } from '../utils/types';
interface ColorSchemeCardProps {
scheme: ColorScheme;
@ -12,16 +14,42 @@ interface ColorSchemeCardProps {
onDislike: () => void;
index: number;
isDarkMode: boolean;
codeSample: string;
outputFormat: string;
settings: AppSettings;
}
const ColorSchemeCard: React.FC<ColorSchemeCardProps> = ({ scheme, onLike, onDislike, index, isDarkMode, codeSample, outputFormat }) => {
const ColorSchemeCard: React.FC<ColorSchemeCardProps> = ({ scheme, onLike, onDislike, index, isDarkMode, settings }) => {
const [overlayColor, setOverlayColor] = useState('rgba(0, 0, 0, 0)');
const controls = useAnimation();
const getCodeExample = () => {
// Add code samples for each language here
if (settings.juniorDevMode) {
return `
// This code is perfect, no need to review
function makeItWork() {
return true;
}
// This function does everything
function doEverything() {
// TODO: Implement
}
// Ignore this, it's probably not important
try {
somethingRisky();
} catch (e) {
// This will never happen
}
// Copy-pasted from StackOverflow
const regex = /^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/;
// I'll fix this later
while (true) {
// Infinite loop for extra performance
}
`;
}
const samples = {
c: `#include <stdio.h>
@ -149,31 +177,30 @@ func main() {
num := 7
fmt.Printf("Is %d prime? %v\n", num, isPrime(num))
}`,
javascript: `function isPrime(n) {
if (n <= 1) return false;
for (let i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) return false;
}
return true;
javascript: `/* Calculate the area and circumference of a circle */
const pi = 3.14;
function calculateArea(r) {
return pi * r ** 2; // Exponentiation, constant, operator
}
function primesUpTo(limit) {
let primes = [];
for (let i = 2; i <= limit; i++) {
if (isPrime(i)) primes.push(i);
}
return primes;
function calculateCircumference(r) {
return 2 * pi * r; // Function, return, operators
}
function fibonacci(n) {
let fib = [0, 1];
for (let i = 2; i < n; i++) {
fib.push(fib[i - 1] + fib[i - 2]);
}
return fib;
if (radius > 0) {
console.log(\`Area: $\{calculateArea(radius)\}\`); // Template string, method
console.log(\`Circumference: $\{calculateCircumference(radius)\}\`);
} else {
console.error("Invalid radius!"); // Error handling
}
let limit = 50;`,
try {
radius = -1;
if (radius < 0) throw new Error("Negative radius"); // Throw, error
} catch (e) {
console.warn(e.message); // Catch block, method
}`,
bash: `#!/bin/bash
is_prime() {
@ -219,7 +246,7 @@ fi`
return sample in samples;
};
return isValidSample(codeSample) ? samples[codeSample] : samples.javascript;
return isValidSample(settings.codeSample) ? samples[settings.codeSample] : samples.javascript;
};
const handleDownload = (e: React.MouseEvent) => {
@ -227,7 +254,7 @@ fi`
let content: string;
let fileExtension: string;
switch (outputFormat) {
switch (settings.outputFormat) {
case 'json':
content = generateJSON(scheme);
fileExtension = 'json';
@ -240,6 +267,18 @@ fi`
content = generateTOML(scheme);
fileExtension = 'toml';
break;
case 'iterm2':
content = generateITerm2(scheme);
fileExtension = 'itermcolors';
break;
case 'windows-terminal':
content = generateWindowsTerminal(scheme);
fileExtension = 'json';
break;
case 'terminal-app':
content = generateTerminalApp(scheme);
fileExtension = 'terminal';
break;
case 'yaml':
default:
content = generateYAML(scheme);
@ -259,7 +298,16 @@ fi`
const handleLike = () => {
setOverlayColor('rgba(0, 255, 0, 0.1)');
controls.start({ x: 300, opacity: 0, transition: { duration: 0.3 } }).then(onLike);
controls.start({ x: 300, opacity: 0, transition: { duration: 0.3 } }).then(() => {
if (settings.partyMode) {
confetti({
particleCount: 100,
spread: 70,
origin: { y: 0.6 }
});
}
onLike();
});
};
const handleDislike = () => {
@ -318,7 +366,7 @@ fi`
</button>
</div>
<div className="bg-gray-100 dark:bg-gray-700 rounded-md mb-2 flex-grow overflow-hidden z-10 shadow-md">
<Highlight theme={themes.dracula} code={getCodeExample()} language={codeSample}>
<Highlight theme={themes.dracula} code={getCodeExample()} language={settings.codeSample}>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={`${className} text-sm p-4 h-full overflow-auto`} style={{ ...style, backgroundColor: scheme.colors.primary.background }}>
{tokens.map((line, i) => (

View File

@ -0,0 +1,76 @@
import React from 'react';
import Image from 'next/image';
interface FormatInstructionsProps {
isOpen: boolean;
onClose: () => void;
isDarkMode: boolean;
}
const FormatInstructions: React.FC<FormatInstructionsProps> = ({ isOpen, onClose, isDarkMode }) => {
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-xl w-[90vw] max-w-2xl max-h-[90vh] overflow-y-auto">
<div className="flex justify-between items-center mb-4">
<h2 className="text-2xl font-bold">Color Scheme Installation Instructions</h2>
<button onClick={onClose} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
<Image src={isDarkMode ? "/close-icon-dark.svg" : "/close-icon-light.svg"} alt="Close" width={24} height={24} />
</button>
</div>
<div className="space-y-4">
<h3 className="text-xl font-semibold">YAML (Alacritty)</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Download the YAML file.</li>
<li>Place it in your Alacritty configuration directory (usually <code>~/.config/alacritty/</code>).</li>
<li>In your <code>alacritty.yml</code> file, add: <code>import: [/path/to/your/theme.yml]</code></li>
</ol>
<h3 className="text-xl font-semibold">JSON</h3>
<p>JSON format can be used in various terminals. Refer to your terminal's documentation for specific instructions.</p>
<h3 className="text-xl font-semibold">XResources</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Download the XResources file.</li>
<li>Add the contents to your <code>~/.Xresources</code> file.</li>
<li>Run <code>xrdb ~/.Xresources</code> to reload.</li>
</ol>
<h3 className="text-xl font-semibold">TOML (Alacritty)</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Download the TOML file.</li>
<li>Place it in your Alacritty configuration directory.</li>
<li>In your <code>alacritty.toml</code> file, add: <code>import = ["/path/to/your/theme.toml"]</code></li>
</ol>
<h3 className="text-xl font-semibold">iTerm2</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Download the iTerm2 color scheme file.</li>
<li>Open iTerm2 preferences.</li>
<li>Go to Profiles &gt; Colors.</li>
<li>Click on "Color Presets..." and choose "Import..."</li>
<li>Select the downloaded file.</li>
</ol>
<h3 className="text-xl font-semibold">Windows Terminal</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Download the JSON file.</li>
<li>Open Windows Terminal settings.</li>
<li>In the "schemes" array, add the contents of the downloaded JSON file.</li>
<li>In your profile, set "colorScheme" to the name of your new scheme.</li>
</ol>
<h3 className="text-xl font-semibold">Terminal.app (macOS)</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Download the Terminal.app color scheme file.</li>
<li>Double-click the downloaded file to import it into Terminal.app.</li>
<li>In Terminal.app preferences, select the imported profile.</li>
</ol>
</div>
</div>
</div>
);
};
export default FormatInstructions;

View File

@ -21,6 +21,7 @@ const HelpDialog: React.FC<HelpDialogProps> = ({ isOpen, onClose, isDarkMode })
</div>
<div className="space-y-4">
<p>Welcome to TerminalTinder, the dating app that actually designed to be used over and over again.</p>
<p>The more you interact with TerminalTinder, the better it becomes at suggesting color schemes and even creating new ones.</p>
<h3 className="text-xl font-semibold">How it works:</h3>
<ol className="list-decimal list-inside space-y-2">
@ -34,12 +35,12 @@ const HelpDialog: React.FC<HelpDialogProps> = ({ isOpen, onClose, isDarkMode })
<ul className="list-disc list-inside space-y-2">
<li>View a live preview of the color scheme applied to code.</li>
<li>Change the programming language of the preview in the settings.</li>
<li>Download color schemes in various formats (YAML, JSON, TOML, Xresources).</li>
<li>Download color schemes in various formats (YAML, JSON, TOML, Xresources, and more).</li>
<li>View your liked and disliked schemes in the history.</li>
</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>It&apos;s your internet, take it back.</p>
<hr className="my-4 border-t border-gray-200 w-full" />
<p>DWS - It&apos;s your internet, take it back.</p>
<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>

View File

@ -1,18 +1,15 @@
import React, { useState, useEffect } from 'react';
import Image from 'next/image';
// Import the CodeSample type
import { CodeSample } from '../utils/types';
import { CodeSample, AppSettings } from '../utils/types';
import FormatInstructions from './FormatInstructions';
interface SettingsProps {
isOpen: boolean;
onClose: () => void;
isDarkMode: boolean;
onToggleDarkMode: () => void;
outputFormat: string;
setOutputFormat: (format: string) => void;
codeSample: CodeSample;
setCodeSample: (sample: CodeSample) => void;
settings: AppSettings;
setSettings: (settings: AppSettings) => void;
saveSettings: boolean;
setSaveSettings: (save: boolean) => void;
}
@ -22,14 +19,13 @@ const Settings: React.FC<SettingsProps> = ({
onClose,
isDarkMode,
onToggleDarkMode,
outputFormat,
setOutputFormat,
codeSample,
setCodeSample,
settings,
setSettings,
saveSettings,
setSaveSettings
}) => {
const [showCookieNotice, setShowCookieNotice] = useState(false);
const [showFormatInstructions, setShowFormatInstructions] = useState(false);
useEffect(() => {
if (saveSettings && !localStorage.getItem('cookieNoticeShown')) {
@ -79,22 +75,33 @@ const Settings: React.FC<SettingsProps> = ({
</div>
<div>
<label className="block mb-2">Output Format</label>
<select
value={outputFormat}
onChange={(e) => setOutputFormat(e.target.value)}
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
>
<option value="json">JSON</option>
<option value="xresources">XResources</option>
<option value="yaml">YAML (Alacritty)</option>
<option value="toml">TOML (Alacritty)</option>
</select>
<div className="flex items-center">
<select
value={settings.outputFormat}
onChange={(e) => setSettings({ ...settings, outputFormat: e.target.value })}
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
>
<option value="yaml">YAML (Alacritty)</option>
<option value="json">JSON</option>
<option value="xresources">XResources</option>
<option value="toml">TOML (Alacritty)</option>
<option value="iterm2">iTerm2</option>
<option value="windows-terminal">Windows Terminal</option>
<option value="terminal-app">Terminal.app</option>
</select>
<button
onClick={() => setShowFormatInstructions(true)}
className="ml-2 text-blue-500 hover:text-blue-600"
>
<Image src={isDarkMode ? "/question-mark-dark.svg" : "/question-mark-light.svg"} alt="Format Instructions" width={24} height={24} />
</button>
</div>
</div>
<div>
<label className="block mb-2">Code Sample</label>
<select
value={codeSample}
onChange={(e) => setCodeSample(e.target.value as CodeSample)}
value={settings.codeSample}
onChange={(e) => setSettings({ ...settings, codeSample: e.target.value as CodeSample })}
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
>
<option value="c">C</option>
@ -116,6 +123,36 @@ const Settings: React.FC<SettingsProps> = ({
/>
<label htmlFor="saveSettings">Save settings in cookie</label>
</div>
<div className="flex items-center justify-between mt-4">
<span>Junior Dev Mode</span>
<button
onClick={() => setSettings({ ...settings, juniorDevMode: !settings.juniorDevMode })}
className={`w-12 h-6 rounded-full p-1 transition-colors duration-300 ease-in-out ${
settings.juniorDevMode ? 'bg-blue-600' : 'bg-gray-300'
}`}
>
<div
className={`w-4 h-4 rounded-full bg-white transform transition-transform duration-300 ease-in-out ${
settings.juniorDevMode ? 'translate-x-6' : ''
}`}
/>
</button>
</div>
<div className="flex items-center justify-between mt-4">
<span>Party Mode</span>
<button
onClick={() => setSettings({ ...settings, partyMode: !settings.partyMode })}
className={`w-12 h-6 rounded-full p-1 transition-colors duration-300 ease-in-out ${
settings.partyMode ? 'bg-blue-600' : 'bg-gray-300'
}`}
>
<div
className={`w-4 h-4 rounded-full bg-white transform transition-transform duration-300 ease-in-out ${
settings.partyMode ? 'translate-x-6' : ''
}`}
/>
</button>
</div>
</div>
</div>
{showCookieNotice && (
@ -126,6 +163,11 @@ const Settings: React.FC<SettingsProps> = ({
</button>
</div>
)}
<FormatInstructions
isOpen={showFormatInstructions}
onClose={() => setShowFormatInstructions(false)}
isDarkMode={isDarkMode}
/>
</div>
);
};