added download button, downlaod handler and necessary utility functions (#85)
Co-authored-by: Patanjali Kumar <patanjali@oddup.com>
This commit is contained in:
		
							parent
							
								
									d30471f5a9
								
							
						
					
					
						commit
						a1a8ac42a6
					
				|  | @ -1,6 +1,8 @@ | |||
| import {FC, useState} from "react"; | ||||
| import {Prism as SyntaxHighlighter} from "react-syntax-highlighter"; | ||||
| import {oneDark, oneLight} from "react-syntax-highlighter/dist/cjs/styles/prism"; | ||||
| import {IconDownload} from '@tabler/icons-react'; | ||||
| import {generateRandomString, programmingLanguages} from '@/utils/app/data'; | ||||
| 
 | ||||
| interface Props { | ||||
|     language: string; | ||||
|  | @ -20,22 +22,50 @@ export const CodeBlock: FC<Props> = ({ language, value, lightMode }) => { | |||
|             }, 2000); | ||||
|         }); | ||||
|     }; | ||||
|     const downloadAsFile = () => { | ||||
|         const fileExtension = programmingLanguages[language] || '.file'; | ||||
|         const suggestedFileName = `file-${generateRandomString(3, true)}${fileExtension}`; | ||||
|         const fileName = window.prompt('Enter file name', suggestedFileName); | ||||
| 
 | ||||
|         if(!fileName){ | ||||
|             // user pressed cancel on prompt
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const blob = new Blob([value], { type: "text/plain" }); | ||||
|         const url = URL.createObjectURL(blob); | ||||
|         const link = document.createElement("a"); | ||||
|         link.download = fileName; | ||||
|         link.href = url; | ||||
|         link.style.display = "none"; | ||||
|         document.body.appendChild(link); | ||||
|         link.click(); | ||||
|         document.body.removeChild(link); | ||||
|         URL.revokeObjectURL(url); | ||||
|     }; | ||||
|     return ( | ||||
|     <div className="relative text-[16px] pt-2"> | ||||
|         <div className="relative text-[16px]"> | ||||
|             <div className="flex items-center justify-end"> | ||||
|                 <button | ||||
|                     className="text-white bg-none py-0.5 px-2 rounded focus:outline-none hover:bg-blue-700 text-xs" | ||||
|                     onClick={copyToClipboard} | ||||
|                 > | ||||
|                     {buttonText} | ||||
|                 </button> | ||||
|                 <button | ||||
|                     className="text-white bg-none py-0.5 px-2 rounded focus:outline-none hover:bg-blue-700 text-xs" | ||||
|                     onClick={downloadAsFile} | ||||
|                 > | ||||
|                     <IconDownload size={16}/> | ||||
|                 </button> | ||||
|             </div> | ||||
| 
 | ||||
|             <SyntaxHighlighter | ||||
|                 language={language} | ||||
|                 style={lightMode === "light" ? oneLight : oneDark} | ||||
|             > | ||||
|                 {value} | ||||
|             </SyntaxHighlighter> | ||||
| 
 | ||||
|       <button | ||||
|         className="absolute top-[-8px] right-[0px] text-white bg-none py-0.5 px-2 rounded focus:outline-none hover:bg-blue-700 text-xs" | ||||
|         onClick={copyToClipboard} | ||||
|       > | ||||
|         {buttonText} | ||||
|       </button> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
|  |  | |||
|  | @ -21,3 +21,44 @@ export const importConversations = (conversations: Conversation[]) => { | |||
|   localStorage.setItem("conversationHistory", JSON.stringify(conversations)); | ||||
|   localStorage.setItem("selectedConversation", JSON.stringify(conversations[conversations.length - 1])); | ||||
| }; | ||||
| 
 | ||||
| interface languageMap { | ||||
|   [key: string]: string | undefined | ||||
| } | ||||
| 
 | ||||
| export const programmingLanguages: languageMap = { | ||||
|   'javascript': '.js', | ||||
|   'python': '.py', | ||||
|   'java': '.java', | ||||
|   'c': '.c', | ||||
|   'cpp': '.cpp', | ||||
|   'c++': '.cpp', | ||||
|   'c#': '.cs', | ||||
|   'ruby': '.rb', | ||||
|   'php': '.php', | ||||
|   'swift': '.swift', | ||||
|   'objective-c': '.m', | ||||
|   'kotlin': '.kt', | ||||
|   'typescript': '.ts', | ||||
|   'go': '.go', | ||||
|   'perl': '.pl', | ||||
|   'rust': '.rs', | ||||
|   'scala': '.scala', | ||||
|   'haskell': '.hs', | ||||
|   'lua': '.lua', | ||||
|   'shell': '.sh', | ||||
|   'sql': '.sql', | ||||
|   'html': '.html', | ||||
|   'css': '.css' | ||||
|   // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| export const generateRandomString = (length: Number, lowercase=false) => { | ||||
|   const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789"; // excluding similar looking characters like Z, 2, I, 1, O, 0
 | ||||
|   let result = ""; | ||||
|   for (let i = 0; i < length; i++) { | ||||
|     result += chars.charAt(Math.floor(Math.random() * chars.length)); | ||||
|   } | ||||
|   return lowercase ? result.toLowerCase() : result; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue