diff --git a/.changeset/dirty-olives-search.md b/.changeset/dirty-olives-search.md
new file mode 100644
index 0000000..7b916f7
--- /dev/null
+++ b/.changeset/dirty-olives-search.md
@@ -0,0 +1,5 @@
+---
+"saleor-app-invoices": minor
+---
+
+App no longer shows initial loading spinner. It renders nothing until initial required data (channels) are fetched. When this happens, AppBridge informs Dashboard (via NotifyReady action) that it can be displayed.
diff --git a/.changeset/perfect-zoos-notice.md b/.changeset/perfect-zoos-notice.md
new file mode 100644
index 0000000..b8e7cf1
--- /dev/null
+++ b/.changeset/perfect-zoos-notice.md
@@ -0,0 +1,5 @@
+---
+"saleor-app-invoices": patch
+---
+
+Removed frontend GraphQL provider, because no frontend queries are used
diff --git a/apps/invoices/src/modules/app-configuration/ui/channels-configuration.tsx b/apps/invoices/src/modules/app-configuration/ui/channels-configuration.tsx
index 49367c7..4653957 100644
--- a/apps/invoices/src/modules/app-configuration/ui/channels-configuration.tsx
+++ b/apps/invoices/src/modules/app-configuration/ui/channels-configuration.tsx
@@ -7,7 +7,6 @@ import { AddressForm } from "./address-form";
import { ChannelsList } from "./channels-list";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { AppColumnsLayout } from "../../ui/app-columns-layout";
-import { Loader } from "../../ui/loader";
const useStyles = makeStyles((theme) => {
return {
@@ -60,7 +59,7 @@ export const ChannelsConfiguration = () => {
}, [channels.data, activeChannelSlug]);
if (channels.isLoading || !channels.data) {
- return ;
+ return null;
}
if (!activeChannel) {
diff --git a/apps/invoices/src/modules/ui/loader.tsx b/apps/invoices/src/modules/ui/loader.tsx
deleted file mode 100644
index 0c8d236..0000000
--- a/apps/invoices/src/modules/ui/loader.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { CircularProgress } from "@material-ui/core";
-import { makeStyles } from "@saleor/macaw-ui";
-
-const useStyles = makeStyles({
- root: {
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- height: 300,
- },
-});
-
-export const Loader = () => {
- const styles = useStyles();
-
- return (
-
-
-
- );
-};
diff --git a/apps/invoices/src/pages/_app.tsx b/apps/invoices/src/pages/_app.tsx
index ea3af4a..08bc777 100644
--- a/apps/invoices/src/pages/_app.tsx
+++ b/apps/invoices/src/pages/_app.tsx
@@ -4,8 +4,6 @@ import { AppBridge, AppBridgeProvider } from "@saleor/app-sdk/app-bridge";
import { RoutePropagator } from "@saleor/app-sdk/app-bridge/next";
import React, { useEffect } from "react";
import { AppProps } from "next/app";
-
-import GraphQLProvider from "../providers/GraphQLProvider";
import { ThemeSynchronizer } from "../lib/theme-synchronizer";
import { NoSSRWrapper } from "../lib/no-ssr-wrapper";
import { trpcClient } from "../modules/trpc/trpc-client";
@@ -15,7 +13,8 @@ import { MacawThemeProvider } from "@saleor/apps-shared";
* Ensure instance is a singleton.
* TODO: This is React 18 issue, consider hiding this workaround inside app-sdk
*/
-export const appBridgeInstance = typeof window !== "undefined" ? new AppBridge() : undefined;
+export const appBridgeInstance =
+ typeof window !== "undefined" ? new AppBridge({ autoNotifyReady: false }) : undefined;
function NextApp({ Component, pageProps }: AppProps) {
/**
@@ -31,13 +30,11 @@ function NextApp({ Component, pageProps }: AppProps) {
return (
-
-
-
-
-
-
-
+
+
+
+
+
);
diff --git a/apps/invoices/src/pages/configuration.tsx b/apps/invoices/src/pages/configuration.tsx
index 8a5223e..0937fa5 100644
--- a/apps/invoices/src/pages/configuration.tsx
+++ b/apps/invoices/src/pages/configuration.tsx
@@ -9,16 +9,15 @@ const ConfigurationPage: NextPage = () => {
const channels = trpcClient.channels.fetch.useQuery();
const router = useRouter();
- const { appBridge } = useAppBridge();
+ const { appBridge, appBridgeState } = useAppBridge();
- const openInNewTab = (url: string) => {
- appBridge?.dispatch(
- actions.Redirect({
- to: url,
- newContext: true,
- })
- );
- };
+ useEffect(() => {
+ if (channels.isFetched && appBridge && !appBridgeState?.ready) {
+ if (appBridge && channels.isFetched) {
+ appBridge.dispatch(actions.NotifyReady());
+ }
+ }
+ }, [channels.isFetched, appBridge, appBridgeState?.ready]);
useEffect(() => {
if (channels.isSuccess && channels.data.length === 0) {
diff --git a/apps/invoices/src/pages/index.tsx b/apps/invoices/src/pages/index.tsx
index dca92e9..536b7b3 100644
--- a/apps/invoices/src/pages/index.tsx
+++ b/apps/invoices/src/pages/index.tsx
@@ -4,7 +4,6 @@ import { useEffect } from "react";
import { useIsMounted } from "usehooks-ts";
import { useRouter } from "next/router";
import { isInIframe } from "@saleor/apps-shared";
-import { Loader } from "../modules/ui/loader";
const IndexPage: NextPage = () => {
const { appBridgeState } = useAppBridge();
@@ -18,7 +17,7 @@ const IndexPage: NextPage = () => {
}, [isMounted, appBridgeState?.ready]);
if (isInIframe()) {
- return ;
+ return null;
}
return (
diff --git a/apps/invoices/src/providers/GraphQLProvider.tsx b/apps/invoices/src/providers/GraphQLProvider.tsx
deleted file mode 100644
index 39c892f..0000000
--- a/apps/invoices/src/providers/GraphQLProvider.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useAppBridge } from "@saleor/app-sdk/app-bridge";
-import { PropsWithChildren } from "react";
-import { Provider } from "urql";
-
-import { createClient } from "../lib/graphql";
-
-function GraphQLProvider(props: PropsWithChildren<{}>) {
- const { appBridgeState } = useAppBridge();
-
- if (!appBridgeState?.saleorApiUrl) {
- return ;
- }
-
- const client = createClient(appBridgeState?.saleorApiUrl, async () =>
- Promise.resolve({ token: appBridgeState?.token! })
- );
-
- return ;
-}
-
-export default GraphQLProvider;