@@ -3,6 +3,7 @@ import { useRequest } from "../context/RequestContext";
33import clsx from "clsx" ;
44import { useState , useEffect } from "react" ;
55import { invoke } from "@tauri-apps/api/core" ;
6+ import { useToast } from "../hooks/useToast" ;
67
78interface ProtoSchema {
89 services : ProtoService [ ] ;
@@ -50,21 +51,15 @@ export const GrpcEditor = () => {
5051 setProtoContent,
5152 setGrpcSchema,
5253 } = useRequest ( ) ;
54+ const toast = useToast ( ) ;
5355
5456 const [ services , setServices ] = useState < ProtoService [ ] > ( [ ] ) ;
5557 const [ methods , setMethods ] = useState < ProtoMethod [ ] > ( [ ] ) ;
5658 const [ isDiscovering , setIsDiscovering ] = useState ( false ) ;
5759 const [ isParsing , setIsParsing ] = useState ( false ) ;
58- const [ parseError , setParseError ] = useState < string > ( "" ) ;
59- const [ discoveryError , setDiscoveryError ] = useState < string > ( "" ) ;
6060 const [ jsonError , setJsonError ] = useState < string > ( "" ) ;
6161 const [ testingConnection , setTestingConnection ] = useState ( false ) ;
6262 const [ isJsonValid , setIsJsonValid ] = useState ( true ) ;
63- const [ connectionStatus , setConnectionStatus ] = useState < {
64- connected : boolean ;
65- message : string ;
66- latency_ms ?: number ;
67- } | null > ( null ) ;
6863
6964 // Validate JSON in real-time
7065 useEffect ( ( ) => {
@@ -85,10 +80,10 @@ export const GrpcEditor = () => {
8580 }
8681 } , [ grpcMessage ] ) ;
8782
88- // Parse proto content when it changes
83+ // Parse proto content when it changes (silently, without toasts)
8984 useEffect ( ( ) => {
9085 if ( protoContent . trim ( ) ) {
91- parseProtoContent ( ) ;
86+ parseProtoContent ( false ) ;
9287 }
9388 } , [ protoContent ] ) ;
9489
@@ -106,9 +101,8 @@ export const GrpcEditor = () => {
106101 }
107102 } , [ grpcService , services ] ) ;
108103
109- const parseProtoContent = async ( ) => {
104+ const parseProtoContent = async ( showToast : boolean = true ) => {
110105 setIsParsing ( true ) ;
111- setParseError ( "" ) ;
112106
113107 try {
114108 const result = ( await invoke ( "grpc_parse_proto_file" , {
@@ -129,16 +123,24 @@ export const GrpcEditor = () => {
129123 messages : schema . messages || [ ] ,
130124 } ) ;
131125
132- if ( schema . services . length === 0 ) {
133- setParseError ( "No services found in proto file" ) ;
126+ if ( showToast ) {
127+ if ( schema . services . length === 0 ) {
128+ toast . warning ( "No services found in proto file" ) ;
129+ } else {
130+ toast . success ( `Found ${ schema . services . length } service${ schema . services . length !== 1 ? "s" : "" } ` ) ;
131+ }
134132 }
135133 } else {
136- setParseError ( result ?. error || "Failed to parse proto file" ) ;
134+ if ( showToast ) {
135+ toast . error ( result ?. error || "Failed to parse proto file" ) ;
136+ }
137137 }
138138 } catch ( error ) {
139139 const errorMsg =
140140 error instanceof Error ? error . message : "Failed to parse proto file" ;
141- setParseError ( errorMsg ) ;
141+ if ( showToast ) {
142+ toast . error ( errorMsg ) ;
143+ }
142144 console . error ( "Failed to parse proto file:" , error ) ;
143145 } finally {
144146 setIsParsing ( false ) ;
@@ -147,12 +149,11 @@ export const GrpcEditor = () => {
147149
148150 const discoverServices = async ( ) => {
149151 if ( ! url ) {
150- setDiscoveryError ( "Please enter a URL first" ) ;
152+ toast . warning ( "Please enter a URL first" ) ;
151153 return ;
152154 }
153155
154156 setIsDiscovering ( true ) ;
155- setDiscoveryError ( "" ) ;
156157
157158 try {
158159 const result = ( await invoke ( "grpc_discover_services" , {
@@ -172,15 +173,17 @@ export const GrpcEditor = () => {
172173 } ) ;
173174
174175 if ( schema . services . length === 0 ) {
175- setDiscoveryError ( "No services found at this URL" ) ;
176+ toast . warning ( "No services found at this URL" ) ;
177+ } else {
178+ toast . success ( `Discovered ${ schema . services . length } service${ schema . services . length !== 1 ? "s" : "" } via reflection` ) ;
176179 }
177180 } else {
178- setDiscoveryError ( result ?. error || "Failed to discover services" ) ;
181+ toast . error ( result ?. error || "Failed to discover services" ) ;
179182 }
180183 } catch ( error ) {
181184 const errorMsg =
182185 error instanceof Error ? error . message : "Failed to discover services" ;
183- setDiscoveryError ( errorMsg ) ;
186+ toast . error ( errorMsg ) ;
184187 console . error ( "Failed to discover services:" , error ) ;
185188 } finally {
186189 setIsDiscovering ( false ) ;
@@ -189,29 +192,27 @@ export const GrpcEditor = () => {
189192
190193 const testConnection = async ( ) => {
191194 if ( ! url ) {
192- setConnectionStatus ( {
193- connected : false ,
194- message : "Please enter a URL first" ,
195- } ) ;
195+ toast . warning ( "Please enter a URL first" ) ;
196196 return ;
197197 }
198198
199199 setTestingConnection ( true ) ;
200- setConnectionStatus ( null ) ;
201200
202201 try {
203202 const result = ( await invoke ( "grpc_test_connection" , {
204203 url : url ,
205204 } ) ) as { connected : boolean ; message : string ; latency_ms ?: number } ;
206205
207- setConnectionStatus ( result ) ;
206+ if ( result . connected ) {
207+ const latencyMsg = result . latency_ms ? ` (${ result . latency_ms } ms)` : "" ;
208+ toast . success ( `${ result . message } ${ latencyMsg } ` ) ;
209+ } else {
210+ toast . error ( result . message ) ;
211+ }
208212 } catch ( error ) {
209213 const errorMsg =
210214 error instanceof Error ? error . message : "Failed to test connection" ;
211- setConnectionStatus ( {
212- connected : false ,
213- message : errorMsg ,
214- } ) ;
215+ toast . error ( errorMsg ) ;
215216 } finally {
216217 setTestingConnection ( false ) ;
217218 }
@@ -224,7 +225,7 @@ export const GrpcEditor = () => {
224225 setGrpcMessage ( JSON . stringify ( parsed , null , 2 ) ) ;
225226 } catch ( error ) {
226227 console . error ( "Invalid JSON" ) ;
227- alert ( "Invalid JSON format. Please correct it before formatting." ) ;
228+ toast . error ( "Invalid JSON format. Please correct it before formatting." ) ;
228229 }
229230 } ;
230231
@@ -273,7 +274,7 @@ export const GrpcEditor = () => {
273274 < div className = "space-y-2 mb-2" >
274275 < div className = "flex gap-2 flex-wrap" >
275276 < button
276- onClick = { parseProtoContent }
277+ onClick = { ( ) => parseProtoContent ( true ) }
277278 disabled = { ! protoContent . trim ( ) || isParsing }
278279 title = "Parse proto file content to extract services and methods"
279280 className = { clsx (
@@ -312,72 +313,6 @@ export const GrpcEditor = () => {
312313 { testingConnection ? "Testing..." : "Test Connection" }
313314 </ button >
314315 </ div >
315-
316- { /* Error Messages */ }
317- { parseError && (
318- < div
319- className = { clsx (
320- "text-xs p-2 rounded border" ,
321- theme === "dark"
322- ? "bg-red-900/20 border-red-700 text-red-300"
323- : "bg-red-50 border-red-300 text-red-700"
324- ) }
325- >
326- ❌ { parseError }
327- </ div >
328- ) }
329-
330- { discoveryError && (
331- < div
332- className = { clsx (
333- "text-xs p-2 rounded border" ,
334- theme === "dark"
335- ? "bg-red-900/20 border-red-700 text-red-300"
336- : "bg-red-50 border-red-300 text-red-700"
337- ) }
338- >
339- ❌ { discoveryError }
340- </ div >
341- ) }
342-
343- { /* Success Message */ }
344- { services . length > 0 && ! parseError && ! discoveryError && (
345- < div
346- className = { clsx (
347- "text-xs p-2 rounded border" ,
348- theme === "dark"
349- ? "bg-green-900/20 border-green-700 text-green-300"
350- : "bg-green-50 border-green-300 text-green-700"
351- ) }
352- >
353- ✅ Found { services . length } service
354- { services . length !== 1 ? "s" : "" }
355- </ div >
356- ) }
357-
358- { /* Connection Status */ }
359- { connectionStatus && (
360- < div
361- className = { clsx (
362- "text-xs p-2 rounded border" ,
363- connectionStatus . connected
364- ? theme === "dark"
365- ? "bg-green-900/20 border-green-700 text-green-300"
366- : "bg-green-50 border-green-300 text-green-700"
367- : theme === "dark"
368- ? "bg-red-900/20 border-red-700 text-red-300"
369- : "bg-red-50 border-red-300 text-red-700"
370- ) }
371- >
372- { connectionStatus . connected ? "🟢" : "🔴" } { " " }
373- { connectionStatus . message }
374- { connectionStatus . latency_ms && (
375- < span className = "ml-2 font-mono" >
376- ({ connectionStatus . latency_ms } ms)
377- </ span >
378- ) }
379- </ div >
380- ) }
381316 </ div >
382317 < textarea
383318 value = { protoContent }
0 commit comments