Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
310 changes: 187 additions & 123 deletions src/components/features/settings/Settings.tsx

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions src/components/layout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {
setExplorerCollapsed,
sidebarWidth,
setSidebarWidth,
sidebarPosition,
} = useAppStore();

const isResizingRef = useRef(false);
Expand All @@ -32,8 +33,12 @@ export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {

// Calculate width relative to sidebar start
const sidebarRect = sidebarRef.current.getBoundingClientRect();
const sidebarLeft = sidebarRect.left;
const newWidthPx = e.clientX - sidebarLeft;
const sidebarLeft =
sidebarPosition === 'right' ? sidebarRect.right : sidebarRect.left;
const newWidthPx =
sidebarPosition === 'right'
? sidebarRect.right - e.clientX
: e.clientX - sidebarLeft;

const windowWidth = window.innerWidth;
const computedWidth = (newWidthPx / windowWidth) * 100;
Expand Down Expand Up @@ -63,7 +68,7 @@ export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
},
[setSidebarWidth, setExplorerCollapsed]
[setSidebarWidth, setExplorerCollapsed, sidebarPosition]
);

const toggleSidebar = () => {
Expand All @@ -79,7 +84,12 @@ export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {
}}
>
{/* Main Content Area */}
<div className="flex-1 flex min-h-0 relative">
<div
className="flex-1 flex min-h-0 relative"
style={{
flexDirection: sidebarPosition === 'right' ? 'row-reverse' : 'row',
}}
>
{/* <ActivityBar /> */}

{/* Sidebar Area */}
Expand Down
4 changes: 2 additions & 2 deletions src/components/layout/editor/EditorPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { useAppStore } from '../../../store/useAppStore';
import type { EditorView } from '@codemirror/view';

export function EditorPane() {
const [isPreview, setIsPreview] = useState(false);
const { activeFileId } = useAppStore();
const { activeFileId, defaultView } = useAppStore();
const [isPreview, setIsPreview] = useState(defaultView === 'preview');
const editorViewRef = useRef<EditorView | null>(null);
const [cursorLine, setCursorLine] = useState(1);
const [cursorCol, setCursorCol] = useState(1);
Expand Down
13 changes: 8 additions & 5 deletions src/components/layout/editor/EditorStatusBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EditorStatusBarItem } from './EditorStatusBarItem';
import { useAppStore } from '../../../store/useAppStore';
import { getTranslation } from '../../../utils/i18n';

interface EditorStatusBarProps {
isPreview: boolean;
Expand All @@ -12,7 +13,8 @@ export function EditorStatusBar({
cursorLine,
cursorCol,
}: EditorStatusBarProps) {
const { activeFileContent, isAutoSave } = useAppStore();
const { activeFileContent, isAutoSave, language } = useAppStore();
const t = (key: string) => getTranslation(language, key);

// Calculate lines and words
const lines = activeFileContent ? activeFileContent.split('\n').length : 0;
Expand All @@ -24,10 +26,11 @@ export function EditorStatusBar({
: 0;

// Determine mode
const mode = isPreview ? 'Preview' : 'Editing';
// Determine mode
const mode = isPreview ? t('preview') : t('editing');

// Save mode text
const saveMode = isAutoSave ? 'Auto Save' : 'Manual';
const saveMode = isAutoSave ? t('autoSave') : t('manual');

return (
<div
Expand Down Expand Up @@ -85,15 +88,15 @@ export function EditorStatusBar({
style={{ color: 'var(--text-secondary)' }}
className="font-normal opacity-50"
>
{lines} lines
{lines} {t('lines')}
</span>
</EditorStatusBarItem>
<EditorStatusBarItem>
<span
style={{ color: 'var(--text-secondary)' }}
className="font-normal opacity-50"
>
{words} words
{words} {t('words')}
</span>
</EditorStatusBarItem>
</div>
Expand Down
9 changes: 6 additions & 3 deletions src/components/layout/explorer/FileExplorer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState, useMemo } from 'react';
import { useAppStore } from '../../../store/useAppStore';
import { getTranslation } from '../../../utils/i18n';
import type { FileNode } from '../../../types/fileSystem';
import { FileTreeItem } from './FileTreeItem';
import { showExplorerContextMenu } from '../../../util/contextMenu';
Expand Down Expand Up @@ -50,7 +51,9 @@ export function FileExplorer() {
closeOtherFiles,
closeAllFiles,
findFile,
language,
} = useAppStore();
const t = (key: string) => getTranslation(language, key);
const [searchQuery, setSearchQuery] = useState('');

// Extract folder name from workspace path
Expand Down Expand Up @@ -113,7 +116,7 @@ export function FileExplorer() {
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Search..."
placeholder={t('searchPlaceholder')}
className="flex-1 bg-transparent border-none outline-none text-[12px] placeholder:text-[var(--text-tertiary)] min-w-0"
style={{ color: 'var(--text-primary)' }}
/>
Expand All @@ -123,7 +126,7 @@ export function FileExplorer() {
onClick={() => createFile()}
className="h-[28px] w-[28px] flex items-center justify-center rounded-md transition-colors hover:bg-[var(--bg-hover)]"
style={{ color: 'var(--text-secondary)' }}
title="New Note"
title={t('newNote')}
>
<SquarePen size={15} strokeWidth={2.5} />
</button>
Expand Down Expand Up @@ -162,7 +165,7 @@ export function FileExplorer() {
>
{filteredFiles.length === 0 ? (
<div className="px-4 py-4 text-center text-[12px] opacity-50 select-none">
No matches found
{t('noMatches')}
</div>
) : (
<div>
Expand Down
28 changes: 28 additions & 0 deletions src/store/useAppStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ interface AppState {
expandedFolderIds: string[]; // List of folder IDs that are expanded
pendingFileId: string | null;
isAutoSave: boolean;
defaultView: 'editor' | 'preview';
sidebarPosition: 'left' | 'right';
language: string;

// Search State
isSearchOpen: boolean;
Expand Down Expand Up @@ -70,6 +73,9 @@ interface AppState {
) => void;
toggleAutoSave: () => void;
openSystemTab: (tabId: string) => void;
setDefaultView: (view: 'editor' | 'preview') => void;
setSidebarPosition: (position: 'left' | 'right') => void;
setLanguage: (lang: string) => void;

// Context Menu Actions
deleteFile: (fileId: string) => void;
Expand All @@ -95,6 +101,13 @@ export const useAppStore = create<AppState>((set, get) => ({
lastSidebarWidth: 20,
expandedFolderIds: [],
isAutoSave: true,
defaultView:
(localStorage.getItem('cinder-default-view') as 'editor' | 'preview') ||
'editor',
sidebarPosition:
(localStorage.getItem('cinder-sidebar-position') as 'left' | 'right') ||
'left',
language: localStorage.getItem('cinder-language') || 'English',

isSearchOpen: false,
searchQuery: '',
Expand Down Expand Up @@ -911,6 +924,21 @@ export const useAppStore = create<AppState>((set, get) => ({
set((state) => ({ isAutoSave: !state.isAutoSave }));
},

setDefaultView: (view: 'editor' | 'preview') => {
localStorage.setItem('cinder-default-view', view);
set({ defaultView: view });
},

setSidebarPosition: (position: 'left' | 'right') => {
localStorage.setItem('cinder-sidebar-position', position);
set({ sidebarPosition: position });
},

setLanguage: (lang: string) => {
localStorage.setItem('cinder-language', lang);
set({ language: lang });
},

// --- Context Menu Actions ---

deleteFile: (fileId: string) => {
Expand Down
167 changes: 167 additions & 0 deletions src/utils/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
export const TRANSLATIONS: Record<string, Record<string, string>> = {
English: {
settings: 'Settings',
general: 'General',
generalDesc: 'Customize your editor experience',
appearance: 'Appearance',
editor: 'Editor',
system: 'System',
autoSave: 'Auto-save',
autoSaveDesc: 'Automatically save changes while typing',
defaultView: 'Default View',
defaultViewDesc: 'Choose default view for new files',
sidebarPosition: 'Sidebar Position',
sidebarPositionDesc: 'Change the location of the sidebar',
language: 'Language',
languageDesc: 'Change interface language',
notifications: 'Notifications',
notificationsDesc: 'Configure desktop notifications',
themes: 'Themes',
themesDesc: 'Manage app appearance and customization',
colorMode: 'Color Mode',
mainThemes: 'Main Themes',
preview: 'Preview',
editing: 'Editing',
lines: 'lines',
words: 'words',
manual: 'Manual',
searchPlaceholder: 'Search...',
newNote: 'New Note',
noMatches: 'No matches found',
lightMode: 'Light mode',
darkMode: 'Dark mode',
},
Spanish: {
settings: 'Ajustes',
general: 'General',
generalDesc: 'Personaliza tu experiencia con el editor',
appearance: 'Apariencia',
editor: 'Editor',
system: 'Sistema',
autoSave: 'Guardado automático',
autoSaveDesc: 'Guardar cambios automáticamente al escribir',
defaultView: 'Vista predeterminada',
defaultViewDesc: 'Elegir vista predeterminada para archivos nuevos',
sidebarPosition: 'Posición de la barra lateral',
sidebarPositionDesc: 'Cambiar la ubicación de la barra lateral',
language: 'Idioma',
languageDesc: 'Cambiar el idioma de la interfaz',
notifications: 'Notificaciones',
notificationsDesc: 'Configurar notificaciones de escritorio',
themes: 'Temas',
themesDesc: 'Gestionar la aparência y personalización de la aplicación',
colorMode: 'Modo de color',
mainThemes: 'Temas principales',
preview: 'Vista previa',
editing: 'Editando',
lines: 'líneas',
words: 'palabras',
manual: 'Manual',
searchPlaceholder: 'Buscar...',
newNote: 'Nueva nota',
noMatches: 'No se encontraron coincidencias',
lightMode: 'Modo claro',
darkMode: 'Modo oscuro',
},
French: {
settings: 'Paramètres',
general: 'Général',
generalDesc: "Personnalisez votre expérience d'édition",
appearance: 'Apparence',
editor: 'Éditeur',
system: 'Système',
autoSave: 'Enregistrement automatique',
autoSaveDesc:
'Enregistrer automatiquement les modifications lors de la saisie',
defaultView: 'Vue par défaut',
defaultViewDesc: 'Choisir la vue par défaut pour les nouveaux fichiers',
sidebarPosition: 'Position de la barre latérale',
sidebarPositionDesc: "Changer l'emplacement de la barre latérale",
language: 'Langue',
languageDesc: "Changer la langue de l'interface",
notifications: 'Notifications',
notificationsDesc: 'Configurer les notifications de bureau',
themes: 'Thèmes',
themesDesc: "Gérer l'apparence et la personnalisation de l'application",
colorMode: 'Mode de couleur',
mainThemes: 'Thèmes principaux',
preview: 'Aperçu',
editing: 'Édition',
lines: 'lignes',
words: 'mots',
manual: 'Manuel',
searchPlaceholder: 'Rechercher...',
newNote: 'Nouvelle note',
noMatches: 'Aucune correspondance trouvée',
lightMode: 'Mode clair',
darkMode: 'Mode sombre',
},
German: {
settings: 'Einstellungen',
general: 'Allgemein',
generalDesc: 'Passen Sie Ihr Editor-Erlebnis an',
appearance: 'Aussehen',
editor: 'Editor',
system: 'System',
autoSave: 'Automatisch speichern',
autoSaveDesc: 'Änderungen beim Tippen automatisch speichern',
defaultView: 'Standardansicht',
defaultViewDesc: 'Standardansicht für neue Dateien wählen',
sidebarPosition: 'Position der Seitenleiste',
sidebarPositionDesc: 'Position der Seitenleiste ändern',
language: 'Sprache',
languageDesc: 'Oberflächensprache ändern',
notifications: 'Benachrichtigungen',
notificationsDesc: 'Desktop-Benachrichtigungen konfigurieren',
themes: 'Themes',
themesDesc: 'App-Erscheinungsbild und Anpassung verwalten',
colorMode: 'Farbmodus',
mainThemes: 'Haupt-Themes',
preview: 'Vorschau',
editing: 'Bearbeiten',
lines: 'Zeilen',
words: 'Wörter',
manual: 'Manuell',
searchPlaceholder: 'Suchen...',
newNote: 'Neue Notiz',
noMatches: 'Keine Treffer gefunden',
lightMode: 'Heller Modus',
darkMode: 'Dunkler Modus',
},
Japanese: {
settings: '設定',
general: '一般',
generalDesc: 'エディタのエクスペリエンスをカスタマイズします',
appearance: '外観',
editor: 'エディタ',
system: 'システム',
autoSave: '自動保存',
autoSaveDesc: '入力中に変更を自動的に保存します',
defaultView: 'デフォルトビュー',
defaultViewDesc: '新しいファイルのデフォルトビューを選択します',
sidebarPosition: 'サイドバーの位置',
sidebarPositionDesc: 'サイドバーの場所を変更します',
language: '言語',
languageDesc: 'インターフェース言語を変更します',
notifications: '通知',
notificationsDesc: 'デスクトップ通知を設定します',
themes: 'テーマ',
themesDesc: 'アプリの外観とカスタマイズを管理します',
colorMode: 'カラーモード',
mainThemes: 'メインテーマ',
preview: 'プレビュー',
editing: '編集中',
lines: '行',
words: '単語',
manual: '手動',
searchPlaceholder: '検索...',
newNote: '新しいノート',
noMatches: '一致する項目が見つかりません',
lightMode: 'ライトモード',
darkMode: 'ダークモード',
},
};

export const getTranslation = (lang: string, key: string) => {
return TRANSLATIONS[lang]?.[key] || TRANSLATIONS['English'][key] || key;
};
Loading