Merge 05c51e5f60 into 5732483fc2
				
					
				
			This commit is contained in:
		
						commit
						a434bbcd8d
					
				
							
								
								
									
										5
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -128,12 +128,11 @@ declare module '@vue/runtime-core' { | |||||||
|     MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default'] |     MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default'] | ||||||
|     MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] |     MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] | ||||||
|     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] |     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] | ||||||
|  |     MicTester: typeof import('./src/tools/mic-tester/mic-tester.vue')['default'] | ||||||
|     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] |     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] | ||||||
|     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] |     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] | ||||||
|     NCheckbox: typeof import('naive-ui')['NCheckbox'] |  | ||||||
|     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] |     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] | ||||||
|     NConfigProvider: typeof import('naive-ui')['NConfigProvider'] |     NConfigProvider: typeof import('naive-ui')['NConfigProvider'] | ||||||
|     NDivider: typeof import('naive-ui')['NDivider'] |  | ||||||
|     NEllipsis: typeof import('naive-ui')['NEllipsis'] |     NEllipsis: typeof import('naive-ui')['NEllipsis'] | ||||||
|     NH1: typeof import('naive-ui')['NH1'] |     NH1: typeof import('naive-ui')['NH1'] | ||||||
|     NH3: typeof import('naive-ui')['NH3'] |     NH3: typeof import('naive-ui')['NH3'] | ||||||
| @ -141,8 +140,6 @@ declare module '@vue/runtime-core' { | |||||||
|     NLayout: typeof import('naive-ui')['NLayout'] |     NLayout: typeof import('naive-ui')['NLayout'] | ||||||
|     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] |     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] | ||||||
|     NMenu: typeof import('naive-ui')['NMenu'] |     NMenu: typeof import('naive-ui')['NMenu'] | ||||||
|     NSpace: typeof import('naive-ui')['NSpace'] |  | ||||||
|     NTable: typeof import('naive-ui')['NTable'] |  | ||||||
|     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] |     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] | ||||||
|     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] |     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] | ||||||
|     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] |     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] | ||||||
|  | |||||||
| @ -281,6 +281,11 @@ tools: | |||||||
|   mime-types: |   mime-types: | ||||||
|     title: MIME-Typen |     title: MIME-Typen | ||||||
|     description: Konvertiere MIME-Typen in Erweiterungen und umgekehrt. |     description: Konvertiere MIME-Typen in Erweiterungen und umgekehrt. | ||||||
|  |   mic-tester: | ||||||
|  |     title: Mikrofonprufung | ||||||
|  |     description: Wiedergabe und Visualisierung des Tons von Ihrem Mikrofon, mit einer Sekunde Verzögerung hinzugefügt | ||||||
|  |     start-button-text: Mikrofon-Wiedergabe Starten | ||||||
|  |     stop-button-text: Mikrofon-Wiedergabe Stoppen | ||||||
|   toml-to-json: |   toml-to-json: | ||||||
|     title: TOML zu JSON |     title: TOML zu JSON | ||||||
|     description: Parse und konvertiere TOML zu JSON. |     description: Parse und konvertiere TOML zu JSON. | ||||||
|  | |||||||
| @ -240,6 +240,12 @@ tools: | |||||||
|     title: MIME types |     title: MIME types | ||||||
|     description: Convert MIME types to file extensions and vice-versa. |     description: Convert MIME types to file extensions and vice-versa. | ||||||
| 
 | 
 | ||||||
|  |   mic-tester: | ||||||
|  |     title: Microphone Tester | ||||||
|  |     description: Replay and Visualize sound from Your microphone, with added one second of delay | ||||||
|  |     start-button-text: Start replaying microphone | ||||||
|  |     stop-button-text: Stop replaying microphone | ||||||
|  | 
 | ||||||
|   toml-to-json: |   toml-to-json: | ||||||
|     title: TOML to JSON |     title: TOML to JSON | ||||||
|     description: Parse and convert TOML to JSON. |     description: Parse and convert TOML to JSON. | ||||||
|  | |||||||
							
								
								
									
										87
									
								
								locales/pl.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								locales/pl.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | |||||||
|  | home: | ||||||
|  |   categories: | ||||||
|  |     newestTools: 'Najnowsze narzędzia' | ||||||
|  |     favoriteTools: 'Twoje ulubione narzędzia' | ||||||
|  |     allTools: 'Wszystkie narzędzia' | ||||||
|  |   subtitle: 'Narzędzia dla programistów' | ||||||
|  |   toggleMenu: 'Menu' | ||||||
|  |   home: Strona główna | ||||||
|  |   uiLib: 'UI Lib' | ||||||
|  |   buyMeACoffee: 'Wesprzyj IT-Tools' | ||||||
|  |   follow: | ||||||
|  |     title: 'Podoba Ci się it-tools?' | ||||||
|  |     p1: 'Wesprzyj nas gwiazdką na' | ||||||
|  |     githubRepository: "repozytorium GitHub IT-Tools" | ||||||
|  |     p2: 'lub śledź nas na' | ||||||
|  |     twitterAccount: "koncie Twitter IT-Tools" | ||||||
|  |     thankYou: 'Dziękujemy!' | ||||||
|  |   nav: | ||||||
|  |     github: 'Repozytorium GitHub' | ||||||
|  |     githubRepository: "Repozytorium GitHub IT-Tools" | ||||||
|  |     twitter: 'Konto Twitter' | ||||||
|  |     twitterAccount: "Konto Twitter IT-Tools" | ||||||
|  |     about: "O IT-Tools" | ||||||
|  |     aboutLabel: 'O nas' | ||||||
|  |     darkMode: 'Tryb ciemny' | ||||||
|  |     lightMode: 'Tryb jasny' | ||||||
|  |     mode: 'Przełącz tryb ciemny/jasny' | ||||||
|  | about: | ||||||
|  |   content: > | ||||||
|  |     # O IT-Tools | ||||||
|  | 
 | ||||||
|  |     Ta wspaniała strona, stworzona z ❤ przez [Corentina Thomasseta](https://corentin.tech?utm_source=it-tools&utm_medium=about), zbiera przydatne narzędzia dla programistów i osób pracujących w IT. Jeśli uznasz ją za pomocną, nie zapomnij się nią podzielić i dodać do ulubionych! | ||||||
|  | 
 | ||||||
|  |     IT Tools jest open-source (na licencji MIT) i darmowe, i takie pozostanie, ale koszty związane z jego hostingiem i odnawianiem domeny spoczywają na mnie. Jeśli chcesz wesprzeć moją pracę i zmotywować mnie do dodania kolejnych narzędzi, zachęcam do [wsparcia](https://www.buymeacoffee.com/cthmsst). | ||||||
|  | 
 | ||||||
|  |     ## Technologie | ||||||
|  | 
 | ||||||
|  |     IT Tools zostało stworzone w Vue.js (Vue 3) z wykorzystaniem biblioteki komponentów Naive UI i jest hostowane oraz ciągle wdrażane przez Vercel. Niektóre narzędzia korzystają z zewnętrznych bibliotek open-source, pełną listę znajdziesz w pliku [package.json](https://github.com/CorentinTh/it-tools/blob/main/package.json) repozytorium. | ||||||
|  | 
 | ||||||
|  |     ## Znalazłeś błąd? Brakuje jakiegoś narzędzia? | ||||||
|  | 
 | ||||||
|  |     Jeśli potrzebujesz narzędzia, które nie jest jeszcze dostępne, a uważasz, że mogłoby być przydatne, zapraszam do zgłoszenia propozycji funkcji w [sekcji issue](https://github.com/CorentinTh/it-tools/issues/new/choose) repozytorium GitHub. | ||||||
|  | 
 | ||||||
|  | 404: | ||||||
|  |   notFound: '404 Nie znaleziono' | ||||||
|  |   sorry: "Przepraszamy, ta strona nie istnieje" | ||||||
|  |   maybe: 'Może to problem z cachem, spróbuj wymusić odświeżenie?' | ||||||
|  |   backHome: "Powrót na stronę główną" | ||||||
|  | toolCard: | ||||||
|  |   new: Nowe | ||||||
|  | search: | ||||||
|  |   label: Szukaj | ||||||
|  | tools: | ||||||
|  |   categories: | ||||||
|  |     favorite-tools: 'Twoje ulubione narzędzia' | ||||||
|  |     crypto: Kryptografia | ||||||
|  |     converter: Konwerter | ||||||
|  |     web: Web | ||||||
|  |     images and videos: 'Obrazy i wideo' | ||||||
|  |     development: Programowanie | ||||||
|  |     network: Sieć | ||||||
|  |     math: Matematyka | ||||||
|  |     measurement: Pomiary | ||||||
|  |     text: Tekst | ||||||
|  |     data: Dane | ||||||
|  | 
 | ||||||
|  |   token-generator: | ||||||
|  |     title: Generator tokenów | ||||||
|  |     description: >- | ||||||
|  |       Generuje losowy ciąg znaków z wybranych przez Ciebie znaków: wielkie | ||||||
|  |       lub małe litery, cyfry i/lub symbole. | ||||||
|  |     uppercase: Wielkie litery (ABC...) | ||||||
|  |     lowercase: Małe litery (abc...) | ||||||
|  |     numbers: Cyfry (123...) | ||||||
|  |     symbols: Symbole (!-;...) | ||||||
|  |     button: | ||||||
|  |       copy: Kopiuj | ||||||
|  |       refresh: Odśwież | ||||||
|  |     copied: Token został skopiowany | ||||||
|  |     length: Długość | ||||||
|  |     tokenPlaceholder: Token... | ||||||
|  | 
 | ||||||
|  |   mic-tester: | ||||||
|  |     title: Tester mikrofonu | ||||||
|  |     description: Odtwórz i wizualizuj dźwięk z Twojego mikrofonu, z dodaną jedną sekundą opóźnienia | ||||||
|  |     start-button-text: Odtwarzaj mikrofonu | ||||||
|  |     stop-button-text: Zatrzymaj odtwarzanie mikrofonu | ||||||
| @ -6,6 +6,7 @@ const localesLong: Record<string, string> = { | |||||||
|   de: 'Deutsch', |   de: 'Deutsch', | ||||||
|   es: 'Español', |   es: 'Español', | ||||||
|   fr: 'Français', |   fr: 'Français', | ||||||
|  |   pl: 'Polski', | ||||||
|   pt: 'Português', |   pt: 'Português', | ||||||
|   ru: 'Русский', |   ru: 'Русский', | ||||||
|   uk: 'Українська', |   uk: 'Українська', | ||||||
|  | |||||||
| @ -87,6 +87,7 @@ import { tool as uuidGenerator } from './uuid-generator'; | |||||||
| import { tool as macAddressLookup } from './mac-address-lookup'; | import { tool as macAddressLookup } from './mac-address-lookup'; | ||||||
| import { tool as xmlFormatter } from './xml-formatter'; | import { tool as xmlFormatter } from './xml-formatter'; | ||||||
| import { tool as yamlViewer } from './yaml-viewer'; | import { tool as yamlViewer } from './yaml-viewer'; | ||||||
|  | import { tool as micTester } from './mic-tester'; | ||||||
| 
 | 
 | ||||||
| export const toolsByCategory: ToolCategory[] = [ | export const toolsByCategory: ToolCategory[] = [ | ||||||
|   { |   { | ||||||
| @ -137,6 +138,7 @@ export const toolsByCategory: ToolCategory[] = [ | |||||||
|       httpStatusCodes, |       httpStatusCodes, | ||||||
|       jsonDiff, |       jsonDiff, | ||||||
|       safelinkDecoder, |       safelinkDecoder, | ||||||
|  |       micTester, | ||||||
|     ], |     ], | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/tools/mic-tester/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/mic-tester/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | import { Microphone } from '@vicons/tabler'; | ||||||
|  | import { defineTool } from '../tool'; | ||||||
|  | import { translate } from '@/plugins/i18n.plugin'; | ||||||
|  | 
 | ||||||
|  | export const tool = defineTool({ | ||||||
|  |   name: translate('tools.mic-tester.title'), | ||||||
|  |   path: '/mic-tester', | ||||||
|  |   description: translate('tools.mic-tester.description'), | ||||||
|  |   keywords: ['mic', 'microphone', 'test', 'check', 'troubleshoot', 'sound'], | ||||||
|  |   component: () => import('./mic-tester.vue'), | ||||||
|  |   icon: Microphone, | ||||||
|  | }); | ||||||
							
								
								
									
										91
									
								
								src/tools/mic-tester/mic-tester.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/tools/mic-tester/mic-tester.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | import { onBeforeUnmount, ref } from 'vue'; | ||||||
|  | 
 | ||||||
|  | interface IMessageSender { | ||||||
|  |   error: (...messages: any[]) => void | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function useMicrophoneService(messageSender: IMessageSender) { | ||||||
|  |   let audioContext: AudioContext | null = null; | ||||||
|  |   let delayNode: DelayNode | null = null; | ||||||
|  |   let sourceNode: MediaStreamAudioSourceNode | null = null; | ||||||
|  |   let analyserNode: AnalyserNode | null = null; | ||||||
|  |   let stream: MediaStream | null = null; | ||||||
|  | 
 | ||||||
|  |   const isPlaying = ref(false); | ||||||
|  |   const loudnessLevel = ref(0); // Observable for loudness
 | ||||||
|  | 
 | ||||||
|  |   // Measure loudness and update loudness bar
 | ||||||
|  |   function measureLoudness() { | ||||||
|  |     const dataArray = new Uint8Array(analyserNode!.frequencyBinCount); | ||||||
|  | 
 | ||||||
|  |     const updateLoudness = () => { | ||||||
|  |       analyserNode!.getByteFrequencyData(dataArray); | ||||||
|  | 
 | ||||||
|  |       // Calculate average loudness
 | ||||||
|  |       let sum = 0; | ||||||
|  |       dataArray.forEach(value => sum += value); | ||||||
|  |       const average = sum / dataArray.length; | ||||||
|  | 
 | ||||||
|  |       // Update the observable loudness level
 | ||||||
|  |       loudnessLevel.value = average; | ||||||
|  | 
 | ||||||
|  |       if (isPlaying.value) { | ||||||
|  |         requestAnimationFrame(updateLoudness); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |     updateLoudness(); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const startMicReplay = async () => { | ||||||
|  |     if (!audioContext) { | ||||||
|  |       audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |       stream = await navigator.mediaDevices.getUserMedia({ audio: true }); | ||||||
|  |     } | ||||||
|  |     catch (err) { | ||||||
|  |       console.error('Microphone access denied:', err); | ||||||
|  |       messageSender.error('Microphone access denied (the error is also in the console):', err); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     sourceNode = audioContext.createMediaStreamSource(stream); | ||||||
|  |     delayNode = audioContext.createDelay(1.0); | ||||||
|  |     delayNode.delayTime.value = 1.0; | ||||||
|  | 
 | ||||||
|  |     analyserNode = audioContext.createAnalyser(); | ||||||
|  |     analyserNode.fftSize = 256; | ||||||
|  | 
 | ||||||
|  |     // Connect nodes: mic -> delay -> speakers
 | ||||||
|  |     sourceNode.connect(delayNode); | ||||||
|  |     delayNode.connect(audioContext.destination); | ||||||
|  |     sourceNode.connect(analyserNode); | ||||||
|  | 
 | ||||||
|  |     isPlaying.value = true; | ||||||
|  |     measureLoudness(); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   function stopMicReplay() { | ||||||
|  |     if (audioContext && stream) { | ||||||
|  |       const tracks = stream.getTracks(); | ||||||
|  |       tracks.forEach(track => track.stop()); | ||||||
|  |       audioContext.close(); | ||||||
|  |       audioContext = null; | ||||||
|  |       isPlaying.value = false; | ||||||
|  |       loudnessLevel.value = 0; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Cleanup on service destruction
 | ||||||
|  |   onBeforeUnmount(() => { | ||||||
|  |     stopMicReplay(); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     startMicReplay, | ||||||
|  |     stopMicReplay, | ||||||
|  |     loudnessLevel, | ||||||
|  |     isPlaying, | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								src/tools/mic-tester/mic-tester.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/tools/mic-tester/mic-tester.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | <script setup lang="ts"> | ||||||
|  | import { useI18n } from 'vue-i18n'; | ||||||
|  | import { useMessage } from 'naive-ui'; | ||||||
|  | import { useMicrophoneService } from './mic-tester.service'; | ||||||
|  | 
 | ||||||
|  | const message = useMessage(); | ||||||
|  | 
 | ||||||
|  | const { t } = useI18n(); | ||||||
|  | const { startMicReplay, stopMicReplay, loudnessLevel, isPlaying } = useMicrophoneService(message); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <c-card> | ||||||
|  |       <div class="control-buttons"> | ||||||
|  |         <c-button :disabled="isPlaying" @click="startMicReplay"> | ||||||
|  |           {{ t('tools.mic-tester.start-button-text') }} | ||||||
|  |         </c-button> | ||||||
|  |         <c-button :disabled="!isPlaying" @click="stopMicReplay"> | ||||||
|  |           {{ t('tools.mic-tester.stop-button-text') }} | ||||||
|  |         </c-button> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <!-- Loudness Meter --> | ||||||
|  |       <div id="loudnessMeter"> | ||||||
|  |         <div id="loudnessBar" :style="{ width: `${loudnessLevel}%` }" /> | ||||||
|  |       </div> | ||||||
|  |     </c-card> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped> | ||||||
|  | #loudnessMeter { | ||||||
|  | width: 100%; | ||||||
|  | height: 30px; | ||||||
|  | background-color: rgba(46, 51, 56, 0.05); | ||||||
|  | margin-top: 20px; | ||||||
|  | position: relative; | ||||||
|  | } | ||||||
|  | #loudnessBar { | ||||||
|  | height: 100%; | ||||||
|  | background: linear-gradient(48deg, rgba(37, 99, 108, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(20, 160, 88, 1) 100%); | ||||||
|  | } | ||||||
|  | .control-buttons { | ||||||
|  | display: flex; | ||||||
|  | gap: 10px; | ||||||
|  | margin-bottom: 20px; | ||||||
|  | justify-content: space-between; | ||||||
|  | } | ||||||
|  | </style> | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user