Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 28a86dcbff | ||
| 7cd826b052 | |||
|   | da20e34dc9 | ||
|   | a43b5a96bb | ||
|   | 48aaa262c1 | ||
| 660839d854 | |||
|   | 6d23d601a8 | ||
|   | 7405f2cb88 | 
| @@ -42,8 +42,8 @@ jobs: | |||||||
|           push: true |           push: true | ||||||
|           tags: ${{ steps.meta.outputs.tags }} |           tags: ${{ steps.meta.outputs.tags }} | ||||||
|           labels: ${{ steps.meta.outputs.labels }} |           labels: ${{ steps.meta.outputs.labels }} | ||||||
|           cache-from: type=local,src=/cache |           cache-from: type=registry,ref=${{ secrets.REGISTRY_ENDPOINT }}/${{ github.repository_owner }}/litek:buildcache | ||||||
|           cache-to: type=local,dest=/cache,mode=max |           cache-to: type=registry,ref=${{ secrets.REGISTRY_ENDPOINT }}/${{ github.repository_owner }}/litek:buildcache,mode=max | ||||||
|           # platforms: linux/amd64,linux/arm64 |           # platforms: linux/amd64,linux/arm64 | ||||||
|           platforms: linux/amd64 |           platforms: linux/amd64 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,8 @@ WORKDIR /app | |||||||
| COPY package.json pnpm-lock.yaml ./ | COPY package.json pnpm-lock.yaml ./ | ||||||
|  |  | ||||||
| # 安装依赖 | # 安装依赖 | ||||||
| RUN pnpm install --frozen-lockfile | RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ | ||||||
|  |     pnpm install --frozen-lockfile | ||||||
|  |  | ||||||
| # 复制源代码 | # 复制源代码 | ||||||
| COPY . . | COPY . . | ||||||
|   | |||||||
| @@ -1,13 +1,16 @@ | |||||||
| { | { | ||||||
|   "name": "litek", |   "name": "litek", | ||||||
|   "private": true, |   "private": true, | ||||||
|   "version": "0.0.3", |   "version": "0.0.7", | ||||||
|   "type": "module", |   "type": "module", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "dev": "vite", |     "dev": "vite", | ||||||
|     "build": "tsc -b && vite build", |     "build": "tsc -b && vite build", | ||||||
|     "lint": "eslint .", |     "lint": "eslint .", | ||||||
|     "preview": "vite preview" |     "preview": "vite preview", | ||||||
|  |     "release:patch": "npm version patch && git push --follow-tags", | ||||||
|  |     "release:minor": "npm version minor && git push --follow-tags", | ||||||
|  |     "release:major": "npm version major && git push --follow-tags" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@radix-ui/react-dialog": "^1.1.15", |     "@radix-ui/react-dialog": "^1.1.15", | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								src/components/tool/base64.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/components/tool/base64.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | import { useState, type FC } from "react"; | ||||||
|  | import { Textarea } from "@/components/ui/textarea"; | ||||||
|  | import { Button } from "@/components/ui/button"; | ||||||
|  | import { toast } from "sonner"; | ||||||
|  | import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"; | ||||||
|  |  | ||||||
|  | const Tool: FC = () => { | ||||||
|  |   const [decoded, setDecoded] = useState<string>(""); | ||||||
|  |   const [encoded, setEncoded] = useState<string>(""); | ||||||
|  |  | ||||||
|  |   const encode = () => { | ||||||
|  |     try { | ||||||
|  |       const encoded64 = btoa(decoded); | ||||||
|  |       setEncoded(encoded64); | ||||||
|  |       setDecoded(""); | ||||||
|  |       toast.success("encoded successfully"); | ||||||
|  |     } catch (error: unknown) { | ||||||
|  |       if (error instanceof Error) { | ||||||
|  |         toast.error(error.message); | ||||||
|  |       } else { | ||||||
|  |         toast.error("encoding failed"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const decode = () => { | ||||||
|  |     try { | ||||||
|  |       const decoded64 = atob(encoded); | ||||||
|  |       setDecoded(decoded64); | ||||||
|  |       setEncoded(""); | ||||||
|  |       toast.success("decoded successfully"); | ||||||
|  |     } catch (error: unknown) { | ||||||
|  |       if (error instanceof Error) { | ||||||
|  |         toast.error(error.message); | ||||||
|  |       } else { | ||||||
|  |         toast.error("decoding failed"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <div className="h-[50vh] flex flex-row gap-4 pt-[20vh]"> | ||||||
|  |       <Textarea | ||||||
|  |         className="flex-1 resize-none" | ||||||
|  |         placeholder="Enter the original text" | ||||||
|  |         value={decoded} | ||||||
|  |         onChange={(e) => setDecoded(e.target.value)} | ||||||
|  |       /> | ||||||
|  |       <div className="flex flex-col gap-2 justify-center"> | ||||||
|  |         <Button onClick={encode}> | ||||||
|  |           <ArrowRightIcon className="size-4" /> | ||||||
|  |           Encode | ||||||
|  |         </Button> | ||||||
|  |         <Button onClick={decode}> | ||||||
|  |           <ArrowLeftIcon className="size-4" /> | ||||||
|  |           Decode | ||||||
|  |         </Button> | ||||||
|  |       </div> | ||||||
|  |       <Textarea | ||||||
|  |         className="flex-1 resize-none" | ||||||
|  |         placeholder="Enter the Base64 encoded text" | ||||||
|  |         value={encoded} | ||||||
|  |         onChange={(e) => setEncoded(e.target.value)} | ||||||
|  |       /> | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default Tool; | ||||||
|  |  | ||||||
| @@ -1,8 +1,9 @@ | |||||||
| import type { ReactNode } from 'react'; | import type { ReactNode } from 'react'; | ||||||
| import { FileJson, Hash } from 'lucide-react' | import { FileJson, Hash, Binary } from 'lucide-react' | ||||||
|  |  | ||||||
| import UUID from './uuid' | import UUID from './uuid' | ||||||
| import JSON from './json' | import JSON from './json' | ||||||
|  | import Base64 from './base64' | ||||||
|  |  | ||||||
| export interface Tool { | export interface Tool { | ||||||
|   path: string; |   path: string; | ||||||
| @@ -26,5 +27,12 @@ export const tools: Tool[] = [ | |||||||
|     description: "Format and validate JSON", |     description: "Format and validate JSON", | ||||||
|     icon: <FileJson />, |     icon: <FileJson />, | ||||||
|     component: <JSON />, |     component: <JSON />, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     path: "base64", | ||||||
|  |     name: "Base64 Encoder/Decoder", | ||||||
|  |     description: "Encode and decode Base64", | ||||||
|  |     icon: <Binary />, | ||||||
|  |     component: <Base64 />, | ||||||
|   } |   } | ||||||
| ]; | ]; | ||||||
| @@ -7,12 +7,12 @@ import { AppSidebar } from "@/components/sidebar"; | |||||||
| export const Layout: FC = () => ( | export const Layout: FC = () => ( | ||||||
|   <SidebarProvider> |   <SidebarProvider> | ||||||
|     <AppSidebar /> |     <AppSidebar /> | ||||||
|     <div className="p-4 flex flex-col w-full h-[100vh]"> |     <div className="p-4 flex flex-col w-full h-[100vh] overflow-hidden"> | ||||||
|       <nav className="flex items-center justify-between"> |       <nav className="flex items-center justify-between"> | ||||||
|         <SidebarTrigger className="size-10" /> |         <SidebarTrigger className="size-10" /> | ||||||
|         <div role="actions" /> |         <div role="actions" /> | ||||||
|       </nav> |       </nav> | ||||||
|       <main className="flex-1 overflow-auto p-4"> |       <main className="flex-1 overflow-auto p-4 overflow-hidden"> | ||||||
|         <Outlet /> |         <Outlet /> | ||||||
|       </main> |       </main> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user