diff --git a/public/click.wav b/public/click.wav new file mode 100644 index 0000000..91ba195 Binary files /dev/null and b/public/click.wav differ diff --git a/src/lib/components/EditorTitle.svelte b/src/lib/components/EditorTitle.svelte index f01b764..b18c3d2 100644 --- a/src/lib/components/EditorTitle.svelte +++ b/src/lib/components/EditorTitle.svelte @@ -6,7 +6,7 @@ import * as Tooltip from '@/components/ui/tooltip'; import CloseIcon from '@/components/icons/Close.svelte'; import Button from '@/components/ui/button/button.svelte'; - import type { EditorType } from '@/types/EditorTypes'; + import type { EditorType } from '@/src/lib/types/EditorType'; import { cn } from '@/utils'; import { resizeInputOnDynamicContent } from '@/actions/input-auto-width'; diff --git a/src/lib/components/editor/Editor.svelte b/src/lib/components/editor/Editor.svelte index 1baf0d6..848e0d1 100644 --- a/src/lib/components/editor/Editor.svelte +++ b/src/lib/components/editor/Editor.svelte @@ -1,15 +1,13 @@ + + diff --git a/src/lib/components/font-dialog/FontDialog.svelte b/src/lib/components/font-dialog/FontDialog.svelte index 20b9b4e..9eaa0e8 100644 --- a/src/lib/components/font-dialog/FontDialog.svelte +++ b/src/lib/components/font-dialog/FontDialog.svelte @@ -7,7 +7,7 @@ import FontSizeCombobox from './FontSizeCombobox.svelte'; import { Label } from '@/components/ui/label'; import * as Card from '@/components/ui/card'; - import { FontFamily, FontSize } from '@/types/SettingsTypes'; + import { FontFamily, FontSize } from '@/src/lib/types/SettingsType'; import { get } from 'svelte/store'; const currentSettings = get(settings); diff --git a/src/lib/components/font-dialog/FontFamilyCombobox.svelte b/src/lib/components/font-dialog/FontFamilyCombobox.svelte index 65413ce..fd53fd4 100644 --- a/src/lib/components/font-dialog/FontFamilyCombobox.svelte +++ b/src/lib/components/font-dialog/FontFamilyCombobox.svelte @@ -9,7 +9,7 @@ import { get } from 'svelte/store'; import CheckIcon from '@/components/icons/Check.svelte'; import ChevronsUpDownIcon from '@/components/icons/ChevronsUpDown.svelte'; - import { FontFamily } from '@/types/SettingsTypes'; + import { FontFamily } from '@/src/lib/types/SettingsType'; interface Props { value: FontFamily; diff --git a/src/lib/components/font-dialog/FontSizeCombobox.svelte b/src/lib/components/font-dialog/FontSizeCombobox.svelte index 9ea2483..18b62be 100644 --- a/src/lib/components/font-dialog/FontSizeCombobox.svelte +++ b/src/lib/components/font-dialog/FontSizeCombobox.svelte @@ -9,7 +9,7 @@ import { cn } from '@/utils'; import { settings } from '@/store/store'; import { get } from 'svelte/store'; - import { FontSize } from '@/types/SettingsTypes'; + import { FontSize } from '@/src/lib/types/SettingsType'; interface Props { value: FontSize; diff --git a/src/lib/components/menubar/SettingsMenu.svelte b/src/lib/components/menubar/SettingsMenu.svelte index 7d06760..3d95b2f 100644 --- a/src/lib/components/menubar/SettingsMenu.svelte +++ b/src/lib/components/menubar/SettingsMenu.svelte @@ -6,6 +6,8 @@ import GithubOultineIcon from '@/components/icons/GithubOultine.svelte'; import ALargeSmallIcon from '@/components/icons/ALargeSmall.svelte'; import { Notpad } from '@/helpers/notpad'; + import { CaretAnimation, CaretStyle } from '@/types/SettingsType'; + import { settings } from '@/store/store'; @@ -30,21 +32,69 @@ Sound - None - Click - Pop - Typewriter + + Effect + + None + Click + Pop + Typewriter + + + + + Volume + + 100% + 75% + 50% + 25% + + + + + Vibration + + None + Low + Medium + High + Strong + + - Vibration + Caret - None - Low - Medium - High - Strong + + Style + + {#each Object.values(CaretStyle) as caretStyle} + Notpad.settings.updateCaret({ style: caretStyle })} + > + {caretStyle} + + {/each} + + + + + Animation + + {#each Object.values(CaretAnimation) as caretAnimation} + Notpad.settings.updateCaret({ animation: caretAnimation })} + > + {caretAnimation} + + {/each} + + diff --git a/src/lib/helpers/github-api.ts b/src/lib/helpers/github-api.ts index cf4632d..5c6331a 100644 --- a/src/lib/helpers/github-api.ts +++ b/src/lib/helpers/github-api.ts @@ -1,4 +1,4 @@ -import type { ContributorType, ReleasesType } from '@/types/GithubApiTypes'; +import type { ContributorType, ReleasesType } from '@/src/lib/types/GithubApiType'; export class GithubApi { public async getAppLicense(): Promise { diff --git a/src/lib/helpers/menubar/view-options.ts b/src/lib/helpers/menubar/view-options.ts index df1f4b1..fcc019f 100644 --- a/src/lib/helpers/menubar/view-options.ts +++ b/src/lib/helpers/menubar/view-options.ts @@ -1,7 +1,7 @@ import { get } from 'svelte/store'; import { settings } from '@/store/store'; import { Notpad } from '@/helpers/notpad'; -import type { SettingsType } from '@/types/SettingsTypes'; +import type { SettingsType } from '@/src/lib/types/SettingsType'; export class ViewOptions { public toggleStatusBar() { diff --git a/src/lib/helpers/settings.ts b/src/lib/helpers/settings.ts index eb010da..02bb7c7 100644 --- a/src/lib/helpers/settings.ts +++ b/src/lib/helpers/settings.ts @@ -1,5 +1,11 @@ import { settings } from '@/store/store'; -import { FontFamily, FontSize, type SettingsType } from '@/types/SettingsTypes'; +import { + CaretAnimation, + CaretStyle, + FontFamily, + FontSize, + type SettingsType +} from '@/types/SettingsType'; export class Settings { static defaultSettings: SettingsType = { @@ -8,7 +14,11 @@ export class Settings { fontFamily: FontFamily.SUSE, fontSize: FontSize.Size16, lineNumbers: false, - wrapLines: true + wrapLines: true, + caret: { + animation: CaretAnimation.Medium, + style: CaretStyle.VerticalBar + } }; setFontFamily(fontFamily: FontFamily) { @@ -18,4 +28,11 @@ export class Settings { setFontSize(fontSize: FontSize) { settings.update((value) => ({ ...value, fontSize })); } + + updateCaret(caret: Partial) { + settings.update((value) => ({ + ...value, + caret: { ...value.caret, ...caret } + })); + } } diff --git a/src/lib/helpers/type-sound-player.ts b/src/lib/helpers/type-sound-player.ts new file mode 100644 index 0000000..8af992a --- /dev/null +++ b/src/lib/helpers/type-sound-player.ts @@ -0,0 +1,75 @@ +class TypeSoundPlayer { + private audioContext: AudioContext; + private audioUrl: string; + private audioBuffer: AudioBuffer | null = null; + private audioReady: Promise; + + constructor(audioUrl: string) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); + this.audioUrl = audioUrl; + this.audioReady = this.loadAudio(); + } + + private async loadAudio(): Promise { + try { + const response = await fetch(this.audioUrl); + const arrayBuffer = await response.arrayBuffer(); + this.audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer); + console.log('Audio loaded successfully!'); + } catch (error) { + console.error('Error loading audio:', error); + } + } + + private calculatePan(key: string): number { + // Map the keyboard layout to a pan value + const leftKeys = 'qwertasdfgzxcvb'; // Example keys for the left side + const rightKeys = 'yuiophjkl;nm'; // Example keys for the right side + + if (leftKeys.includes(key.toLowerCase())) { + return -1; // Full left + } else if (rightKeys.includes(key.toLowerCase())) { + return 1; // Full right + } else { + return 0; // Center for unsupported keys + } + } + + public async play(key: string): Promise { + await this.audioReady; // Ensure audio is loaded + if (!this.audioBuffer) { + console.warn('Audio not loaded yet!'); + return; + } + + // Create a buffer source for each play + const source = this.audioContext.createBufferSource(); + source.buffer = this.audioBuffer; + + // Create a stereo panner + const panner = this.audioContext.createStereoPanner(); + panner.pan.value = this.calculatePan(key); + + // Connect the source to the panner and the destination + source.connect(panner).connect(this.audioContext.destination); + + // Start the sound + source.start(0); + } + + public resumeAudioContext(): void { + if (this.audioContext.state === 'suspended') { + this.audioContext.resume(); + } + } +} + +// Instantiate TypeSoundPlayer once and use it globally +const soundPlayer = new TypeSoundPlayer('http://localhost:5173/Notpad/click.wav'); + +// Event Listener +window.addEventListener('keydown', (event: KeyboardEvent): void => { + soundPlayer.resumeAudioContext(); + soundPlayer.play(event.key); +}); diff --git a/src/lib/store/storage.ts b/src/lib/store/storage.ts index c40cf98..92eceb7 100644 --- a/src/lib/store/storage.ts +++ b/src/lib/store/storage.ts @@ -1,7 +1,7 @@ import localforage from 'localforage'; import { activeTabId, editors, settings } from '@/store/store'; import type { EditorType } from '@/types/EditorTypes'; -import type { SettingsType } from '@/types/SettingsTypes'; +import type { SettingsType } from '@/src/lib/types/SettingsType'; import { Editors } from '@/helpers/editors'; import { Settings } from '@/helpers/settings'; import merge from 'lodash.merge'; diff --git a/src/lib/store/store.ts b/src/lib/store/store.ts index df92f0e..b5c864e 100644 --- a/src/lib/store/store.ts +++ b/src/lib/store/store.ts @@ -1,6 +1,6 @@ import { get, writable } from 'svelte/store'; import type { EditorType } from '@/types/EditorTypes'; -import { type SettingsType } from '@/types/SettingsTypes'; +import { type SettingsType } from '@/src/lib/types/SettingsType'; import { Settings } from '@/helpers/settings'; import { Editors } from '@/helpers/editors'; diff --git a/src/lib/types/EditorTypes.ts b/src/lib/types/EditorType.ts similarity index 100% rename from src/lib/types/EditorTypes.ts rename to src/lib/types/EditorType.ts diff --git a/src/lib/types/GithubApiTypes.ts b/src/lib/types/GithubApiType.ts similarity index 100% rename from src/lib/types/GithubApiTypes.ts rename to src/lib/types/GithubApiType.ts diff --git a/src/lib/types/SettingsTypes.ts b/src/lib/types/SettingsType.ts similarity index 73% rename from src/lib/types/SettingsTypes.ts rename to src/lib/types/SettingsType.ts index 891d8ad..a6dca72 100644 --- a/src/lib/types/SettingsTypes.ts +++ b/src/lib/types/SettingsType.ts @@ -32,6 +32,20 @@ export enum FontSize { Size72 = 72 } +export enum CaretAnimation { + Slow = 'Slow', + Medium = 'Medium', + Fast = 'Fast', + Off = 'Off' +} + +export enum CaretStyle { + VerticalBar = 'Vertical Bar ( | )', + Block = 'Block ( ▮ )', + HollowBlock = 'Hollow Block ( ▯ )', + Underline = 'Underline ( _ )' +} + /** * Interface representing the settings for the application. */ @@ -60,4 +74,11 @@ export interface SettingsType { * Should wrap long lines. */ wrapLines: boolean; + /** + * Caret's specific configs. Style and Animation. + */ + caret: { + style: CaretStyle; + animation: CaretAnimation; + }; }