diff --git a/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx b/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx
index 52d2e673..325a633a 100644
--- a/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx
+++ b/src/routes/safe/components/Apps/components/AddAppForm/AppUrl.tsx
@@ -28,22 +28,34 @@ export const appUrlResolver = createDecorator({
},
})
-export const AppInfoUpdater = ({ onAppInfo }: { onAppInfo: (appInfo: SafeApp) => void }): null => {
+type AppInfoUpdaterProps = {
+ onAppInfo: (appInfo: SafeApp) => void
+ onLoading: (isLoading: boolean) => void
+}
+
+export const AppInfoUpdater = ({ onAppInfo, onLoading }: AppInfoUpdaterProps): null => {
const {
input: { value: appUrl },
} = useField('appUrl', { subscription: { value: true } })
+
const debouncedValue = useDebounce(appUrl, 500)
React.useEffect(() => {
const updateAppInfo = async () => {
- const appInfo = await getAppInfoFromUrl(debouncedValue)
- onAppInfo({ ...appInfo })
+ try {
+ onLoading(true)
+ const appInfo = await getAppInfoFromUrl(debouncedValue)
+ onAppInfo({ ...appInfo })
+ onLoading(false)
+ } catch (error) {
+ onLoading(false)
+ }
}
if (isValidURL(debouncedValue)) {
updateAppInfo()
}
- }, [debouncedValue, onAppInfo])
+ }, [debouncedValue, onAppInfo, onLoading])
return null
}
@@ -55,7 +67,15 @@ const AppUrl = ({ appList }: { appList: SafeApp[] }): React.ReactElement => {
const validate = !visited?.appUrl ? undefined : composeValidators(required, validateUrl, uniqueApp(appList))
return (
-
+
)
}
diff --git a/src/routes/safe/components/Apps/components/AddAppForm/index.tsx b/src/routes/safe/components/Apps/components/AddAppForm/index.tsx
index 76827a62..5a728bb6 100644
--- a/src/routes/safe/components/Apps/components/AddAppForm/index.tsx
+++ b/src/routes/safe/components/Apps/components/AddAppForm/index.tsx
@@ -1,4 +1,4 @@
-import { TextField } from '@gnosis.pm/safe-react-components'
+import { TextField, Loader } from '@gnosis.pm/safe-react-components'
import React, { useState, ReactElement } from 'react'
import styled from 'styled-components'
@@ -24,6 +24,7 @@ const StyledTextFileAppName = styled(TextField)`
`
const AppInfo = styled.div`
+ display: flex;
margin: 36px 0 24px 0;
img {
@@ -41,6 +42,18 @@ const AppDocsInfo = styled.div`
}
`
+const WrapperLoader = styled.div`
+ height: 55px;
+ width: 65px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`
+
+const StyledLoader = styled(Loader)`
+ margin-right: 15px;
+`
+
interface AddAppFormValues {
appUrl: string
agreementAccepted: boolean
@@ -62,6 +75,7 @@ const AddApp = ({ appList, closeModal }: AddAppProps): ReactElement => {
const [appInfo, setAppInfo] = useState(APP_INFO)
const history = useHistory()
const matchSafeWithAddress = useRouteMatch<{ safeAddress: string }>({ path: `${SAFELIST_ADDRESS}/:safeAddress` })
+ const [isLoading, setIsLoading] = useState(false)
const handleSubmit = () => {
const newAppList = [
@@ -93,14 +107,26 @@ const AddApp = ({ appList, closeModal }: AddAppProps): ReactElement => {
+
{/* Fetch app from url and return a SafeApp */}
-
+
-
- {}} />
+ {isLoading ? (
+
+
+
+ ) : (
+
+ )}
+ {}}
+ />