diff --git a/apps/mobile/app.json b/apps/mobile/app.json index 4b3774eb9..b91912e29 100644 --- a/apps/mobile/app.json +++ b/apps/mobile/app.json @@ -37,13 +37,18 @@ "android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.INTERNET", "android.permission.RECORD_AUDIO", - "android.permission.CAMERA" + "android.permission.CAMERA", + "NOTIFICATIONS" ] }, "web": { "favicon": "./assets/favicon.png", - "deepLinking": true, - "bundler": "metro" + "bundler": "metro", + "fonts": [ + { + "asset": "./assets/fonts/PublicPixel-z84yD.ttf" + } + ] }, "plugins": [ [ @@ -88,6 +93,14 @@ "merchantIdentifier": "", "enableGooglePay": true } + ], + [ + "expo-notifications", + { + "icon": "./assets/notification-icon.png", + "color": "#ffffff", + "sounds": ["./assets/notification-sound.wav"] + } ] ], "sdkVersion": "51.0.0", diff --git a/apps/mobile/index.js b/apps/mobile/index.js index 4480d8fba..c86437ebc 100644 --- a/apps/mobile/index.js +++ b/apps/mobile/index.js @@ -9,5 +9,4 @@ import registerRootComponent from 'expo/build/launch/registerRootComponent'; import {Wrapper} from './src/app/Wrapper'; registerRootComponent(Wrapper); - -AppRegistry.registerComponent(appName, () => App); \ No newline at end of file +AppRegistry.registerComponent(appName, () => App); diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 6dd4f1177..ef688c3df 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -35,7 +35,7 @@ "@dynamic-labs/client": "4.0.0-alpha.8", "@dynamic-labs/react-hooks": "4.0.0-alpha.8", "@dynamic-labs/react-native-extension": "4.0.0-alpha.8", - "@dynamic-labs/utils": "^3.3.0", + "@dynamic-labs/utils": "4.0.0-alpha.8", "@dynamic-labs/viem-extension": "4.0.0-alpha.8", "@expo/metro-runtime": "~3.2.1", "@getalby/bitcoin-connect-react": "^3.5.3", @@ -45,7 +45,7 @@ "@nostr-dev-kit/ndk": "2.10.1", "@nostr-dev-kit/ndk-wallet": "^0.2.0", "@rainbow-me/rainbowkit": "^2.1.5", - "@react-native-async-storage/async-storage": "^1.24.0", + "@react-native-async-storage/async-storage": "1.23.1", "@react-native-community/netinfo": "11.3.1", "@react-native-picker/picker": "2.7.5", "@react-navigation/bottom-tabs": "^6.5.20", @@ -72,7 +72,7 @@ "common": "workspace:*", "crypto-es": "^2.1.0", "events": "^3.3.0", - "expo": "~51.0.28", + "expo": "~51.0.38", "expo-application": "^5.9.1", "expo-auth-session": "^5.5.2", "expo-av": "~14.0.7", @@ -127,7 +127,7 @@ "viem": "2.x", "wagmi": "^2.12.8", "zustand": "^4.5.2", - "@stripe/stripe-react-native":"0.38.6" + "@stripe/stripe-react-native": "0.37.2" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/apps/mobile/src/app/App.tsx b/apps/mobile/src/app/App.tsx index b7f12378f..07c98ba57 100644 --- a/apps/mobile/src/app/App.tsx +++ b/apps/mobile/src/app/App.tsx @@ -1,11 +1,10 @@ import '@walletconnect/react-native-compat'; - import {starknetChainId, useAccount} from '@starknet-react/core'; import * as Font from 'expo-font'; import * as SplashScreen from 'expo-splash-screen'; import {useCallback, useEffect, useState} from 'react'; -import {View} from 'react-native'; - +import {Platform, View} from 'react-native'; +import {registerForPushNotificationsAsync} from '../services/notifications'; import {useTips} from '../hooks'; import {useDialog, useToast} from '../hooks/modals'; import {Router} from './Router'; @@ -15,7 +14,6 @@ SplashScreen.preventAutoHideAsync(); export default function App() { const [appIsReady, setAppIsReady] = useState(false); const [sentTipNotification, setSentTipNotification] = useState(false); - const tips = useTips(); const {showToast} = useToast(); @@ -38,48 +36,17 @@ export default function App() { })(); }, []); - const {showDialog, hideDialog} = useDialog(); - - const account = useAccount(); - useEffect(() => { - const chainId = account.chainId ? starknetChainId(account.chainId) : undefined; - - if (chainId) { - // if (chainId !== CHAIN_ID) { - // showDialog({ - // title: 'Wrong Network', - // description: - // 'AFK currently only supports the Starknet Sepolia network. Please switch to the Sepolia network to continue.', - // buttons: [], - // }); - // } else { - // hideDialog(); - // } + if (Platform.OS !== 'web') { + registerForPushNotificationsAsync() + .then((token: string | null) => { + if (token) { + console.log('Push token:', token); + } + }) + .catch((error: Error) => console.error('Failed to get push token:', error)); } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [account.chainId]); - - useEffect(() => { - const interval = setInterval(() => tips.refetch(), 2 * 60 * 1_000); - return () => clearInterval(interval); - }, [tips]); - - useEffect(() => { - if (sentTipNotification) return; - - const hasUnclaimedTip = (tips.data ?? []).some((tip) => !tip.claimed && tip.depositId); - if (hasUnclaimedTip) { - setSentTipNotification(true); - showToast({ - type: 'info', - title: 'You have unclaimed tips', - }); - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [tips.data]); + }, []); const onLayoutRootView = useCallback(async () => { if (appIsReady) { diff --git a/apps/mobile/src/components/PrivateMessages/Chat/index.tsx b/apps/mobile/src/components/PrivateMessages/Chat/index.tsx index 4ea346486..1d0ee7bb9 100644 --- a/apps/mobile/src/components/PrivateMessages/Chat/index.tsx +++ b/apps/mobile/src/components/PrivateMessages/Chat/index.tsx @@ -5,6 +5,7 @@ import {FlatList, Image, Text, View} from 'react-native'; import {useStyles} from '../../../hooks'; import {useToast} from '../../../hooks/modals'; +import {sendNotificationForEvent} from '../../../utils/notifications'; import {IconButton} from '../../IconButton'; import {MessageInput} from '../PrivateMessageInput'; import stylesheet from './styles'; @@ -51,11 +52,20 @@ export const Chat: React.FC = ({item, handleGoBack, user}) => { receiverPublicKeyProps: receiverPublicKey, }, { - onSuccess: () => { - // showToast({title: 'Message sent', type: 'success'}); + onSuccess: async () => { queryClient.invalidateQueries({ queryKey: ['messagesSent'], }); + + try { + await sendNotificationForEvent(receiverPublicKey, 'privateMessage', { + senderName: user?.name || 'Someone', + conversationId: item.id.toString(), + authorName: message.substring(0, 50) + (message.length > 50 ? '...' : ''), + }); + } catch (error) { + console.error('Failed to send notification:', error); + } }, onError() { showToast({title: 'Error sending message', type: 'error'}); diff --git a/apps/mobile/src/components/TabSelector/index.tsx b/apps/mobile/src/components/TabSelector/index.tsx index 55eed5f48..863173eef 100644 --- a/apps/mobile/src/components/TabSelector/index.tsx +++ b/apps/mobile/src/components/TabSelector/index.tsx @@ -43,7 +43,7 @@ const TabSelector: React.FC = ({ key={i} style={[ tabStyle ?? styles.tab, - activeTab === b?.tab ? activeTabStyle ?? styles.active : null, + activeTab === b?.tab ? (activeTabStyle ?? styles.active) : null, ]} onPress={() => handlePress(b?.tab, b?.screen)} > diff --git a/apps/mobile/src/hooks/launchpad/useCreateToken.ts b/apps/mobile/src/hooks/launchpad/useCreateToken.ts index 512810b22..f43c2181c 100644 --- a/apps/mobile/src/hooks/launchpad/useCreateToken.ts +++ b/apps/mobile/src/hooks/launchpad/useCreateToken.ts @@ -15,8 +15,8 @@ export type DeployTokenFormValues = { export const useCreateToken = () => { const deployToken = async (account: AccountInterface, data: DeployTokenFormValues) => { const CONTRACT_ADDRESS_SALT_DEFAULT = - data?.contract_address_salt ?? - (await account?.getChainId()) == constants.StarknetChainId.SN_MAIN + (data?.contract_address_salt ?? + (await account?.getChainId()) == constants.StarknetChainId.SN_MAIN) ? '0x36d8be2991d685af817ef9d127ffb00fbb98a88d910195b04ec4559289a99f6' : '0x36d8be2991d685af817ef9d127ffb00fbb98a88d910195b04ec4559289a99f6'; @@ -51,8 +51,8 @@ export const useCreateToken = () => { const deployTokenAndLaunch = async (account: AccountInterface, data: DeployTokenFormValues) => { const CONTRACT_ADDRESS_SALT_DEFAULT = - data?.contract_address_salt ?? - (await account?.getChainId()) == constants.StarknetChainId.SN_MAIN + (data?.contract_address_salt ?? + (await account?.getChainId()) == constants.StarknetChainId.SN_MAIN) ? '0x36d8be2991d685af817ef9d127ffb00fbb98a88d910195b04ec4559289a99f6' : '0x36d8be2991d685af817ef9d127ffb00fbb98a88d910195b04ec4559289a99f6'; diff --git a/apps/mobile/src/modules/Lightning/index.tsx b/apps/mobile/src/modules/Lightning/index.tsx index 192c2a129..d31ef2e69 100644 --- a/apps/mobile/src/modules/Lightning/index.tsx +++ b/apps/mobile/src/modules/Lightning/index.tsx @@ -241,8 +241,8 @@ export const LightningNetworkWallet = () => { {isLoading ? 'Connecting...' : isExtensionAvailable - ? 'Connect with Alby Extension' - : 'Connect with Alby NWC'} + ? 'Connect with Alby Extension' + : 'Connect with Alby NWC'} diff --git a/apps/mobile/src/modules/PostCard/index.tsx b/apps/mobile/src/modules/PostCard/index.tsx index b5388a195..e67a91a74 100644 --- a/apps/mobile/src/modules/PostCard/index.tsx +++ b/apps/mobile/src/modules/PostCard/index.tsx @@ -20,7 +20,7 @@ export const PostCard: React.FC = ({event, isRepostProps, isBookm let repostedEvent = undefined; const [isRepost, setIsRepost] = useState( - isRepostProps ?? event?.kind == NDKKind.Repost ? true : false, + (isRepostProps ?? event?.kind == NDKKind.Repost) ? true : false, ); if (event?.kind == NDKKind.Repost) { diff --git a/apps/mobile/src/modules/VideoPostCard/index.tsx b/apps/mobile/src/modules/VideoPostCard/index.tsx index b503bfdeb..832166dcb 100644 --- a/apps/mobile/src/modules/VideoPostCard/index.tsx +++ b/apps/mobile/src/modules/VideoPostCard/index.tsx @@ -20,7 +20,7 @@ export const VideoPostCard: React.FC = ({event, isRepostProps, is let repostedEvent = undefined; const [isRepost, setIsRepost] = useState( - isRepostProps ?? event?.kind == NDKKind.Repost ? true : false, + (isRepostProps ?? event?.kind == NDKKind.Repost) ? true : false, ); if (event?.kind == NDKKind.Repost) { diff --git a/apps/mobile/src/modules/WalletModal/walletUtil.ts b/apps/mobile/src/modules/WalletModal/walletUtil.ts index 59d3780fd..53285c9a4 100644 --- a/apps/mobile/src/modules/WalletModal/walletUtil.ts +++ b/apps/mobile/src/modules/WalletModal/walletUtil.ts @@ -79,8 +79,8 @@ export function injectedWithFallback() { return !window.ethereum ? 'Install MetaMask' : window.ethereum?.isMetaMask - ? 'MetaMask' - : 'Browser Wallet'; + ? 'MetaMask' + : 'Browser Wallet'; }, }; }); diff --git a/apps/mobile/src/serviceWorker.js b/apps/mobile/src/serviceWorker.js new file mode 100644 index 000000000..567b7371c --- /dev/null +++ b/apps/mobile/src/serviceWorker.js @@ -0,0 +1,19 @@ +self.addEventListener('push', event => { + const options = { + body: event.data.text(), + icon: '/notification-icon.png', + badge: '/badge-icon.png', + vibrate: [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification('AFK Community', options) + ); +}); + +self.addEventListener('notificationclick', event => { + event.notification.close(); + event.waitUntil( + clients.openWindow('/') + ); +}); \ No newline at end of file diff --git a/apps/mobile/src/services/notifications.ts b/apps/mobile/src/services/notifications.ts new file mode 100644 index 000000000..a8d936ec9 --- /dev/null +++ b/apps/mobile/src/services/notifications.ts @@ -0,0 +1,21 @@ +export type NotificationData = { + type: 'tip' | 'privateMessage' | 'tokenLaunch' | 'note' | 'tokenLiquidity'; + data: { + amount?: string; + token?: string; + senderName?: string; + tokenName?: string; + action?: string; + authorName?: string; + conversationId?: string; + coinAddress?: string; + noteId?: string; + liquidityAmount?: string; + message?: string; + }; +}; + +export const registerForPushNotificationsAsync = async () => { + // Implementation here + return null; +}; diff --git a/apps/mobile/src/services/notifications/handler.ts b/apps/mobile/src/services/notifications/handler.ts new file mode 100644 index 000000000..9e1644a1b --- /dev/null +++ b/apps/mobile/src/services/notifications/handler.ts @@ -0,0 +1,2 @@ +// Add your handler-related code here +export {}; \ No newline at end of file diff --git a/apps/mobile/src/services/notifications/index.ts b/apps/mobile/src/services/notifications/index.ts new file mode 100644 index 000000000..90f41aeb8 --- /dev/null +++ b/apps/mobile/src/services/notifications/index.ts @@ -0,0 +1,5 @@ + +export * from './pushNotification'; +export * from './registration'; +export * from './types'; +export * from './webNotifications'; diff --git a/apps/mobile/src/services/notifications/pushNotification.ts b/apps/mobile/src/services/notifications/pushNotification.ts new file mode 100644 index 000000000..006a5bf4e --- /dev/null +++ b/apps/mobile/src/services/notifications/pushNotification.ts @@ -0,0 +1,24 @@ +import {NotificationData} from './types'; + +export async function sendPushNotification( + expoPushToken: string, + title: string, + body: string, + data?: NotificationData, +) { + const message = { + to: expoPushToken, + sound: 'default', + title, + body, + data: data || {}, + }; + + await fetch('https://exp.host/--/api/v2/push/send', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(message), + }); +} diff --git a/apps/mobile/src/services/notifications/registration.ts b/apps/mobile/src/services/notifications/registration.ts new file mode 100644 index 000000000..7e974efcd --- /dev/null +++ b/apps/mobile/src/services/notifications/registration.ts @@ -0,0 +1,35 @@ +import Constants from 'expo-constants'; +import * as Device from 'expo-device'; +import * as Notifications from 'expo-notifications'; +import {Platform} from 'react-native'; + +export async function registerForPushNotificationsAsync() { + if (Platform.OS === 'web') return null; + + if (!Device.isDevice) return null; + + const {status: existingStatus} = await Notifications.getPermissionsAsync(); + let finalStatus = existingStatus; + + if (existingStatus !== 'granted') { + const {status} = await Notifications.requestPermissionsAsync(); + finalStatus = status; + } + + if (finalStatus !== 'granted') return null; + + const token = await Notifications.getExpoPushTokenAsync({ + projectId: Constants.expoConfig?.extra?.eas?.projectId, + }); + + if (Platform.OS === 'android') { + await Notifications.setNotificationChannelAsync('default', { + name: 'default', + importance: Notifications.AndroidImportance.MAX, + vibrationPattern: [0, 250, 250, 250], + lightColor: '#FF231F7C', + }); + } + + return token.data; +} diff --git a/apps/mobile/src/services/notifications/types.ts b/apps/mobile/src/services/notifications/types.ts new file mode 100644 index 000000000..ed2d3dc6f --- /dev/null +++ b/apps/mobile/src/services/notifications/types.ts @@ -0,0 +1,15 @@ +export type NotificationData = { + type: 'tip' | 'privateMessage' | 'tokenLaunch' | 'note' | 'tokenLiquidity'; + data: { + amount?: string; + token?: string; + senderName?: string; + tokenName?: string; + action?: string; + authorName?: string; + conversationId?: string; + coinAddress?: string; + noteId?: string; + liquidityAmount?: string; + }; +}; diff --git a/apps/mobile/src/services/notifications/webNotifications.ts b/apps/mobile/src/services/notifications/webNotifications.ts new file mode 100644 index 000000000..ade26ae9a --- /dev/null +++ b/apps/mobile/src/services/notifications/webNotifications.ts @@ -0,0 +1,16 @@ +import { Platform } from "react-native"; + +export const setupWebNotifications = async () => { + if (Platform.OS !== 'web') return; + + if (!('Notification' in window)) return; + + try { + const permission = await Notification.requestPermission(); + if (permission === 'granted') { + console.log('Notification permission granted'); + } + } catch (error) { + console.error('Error requesting notification permission:', error); + } +}; \ No newline at end of file diff --git a/apps/mobile/src/services/notifications/webPushNotification.ts b/apps/mobile/src/services/notifications/webPushNotification.ts new file mode 100644 index 000000000..692873aed --- /dev/null +++ b/apps/mobile/src/services/notifications/webPushNotification.ts @@ -0,0 +1,26 @@ +export interface WebPushSubscription { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; +} + +export async function subscribeToWebPush(): Promise { + if (!('serviceWorker' in navigator) || !('PushManager' in window)) { + return null; + } + + try { + const registration = await navigator.serviceWorker.ready; + const subscription = await registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: process.env.EXPO_PUBLIC_VAPID_KEY + }); + + return subscription.toJSON() as WebPushSubscription; + } catch (error) { + console.error('Failed to subscribe to web push:', error); + return null; + } +} \ No newline at end of file diff --git a/apps/mobile/src/utils/notifications.ts b/apps/mobile/src/utils/notifications.ts new file mode 100644 index 000000000..509e11fd1 --- /dev/null +++ b/apps/mobile/src/utils/notifications.ts @@ -0,0 +1,27 @@ +import {NotificationData} from '../services/notifications/types'; + +export const sendNotificationForEvent = async ( + receiverPublicKey: string, + type: NotificationData['type'], + data: NotificationData['data'], +) => { + try { + // Implementation for sending notifications + // This is a placeholder - actual implementation would depend on your notification service + console.log('Sending notification:', {receiverPublicKey, type, data}); + } catch (error) { + console.error('Error sending notification:', error); + throw error; + } +}; + +export async function requestNotificationPermission() { + if ('Notification' in window) { + const permission = await Notification.requestPermission(); + if (permission === 'granted') { + // Subscribe to push notifications here + const registration = await navigator.serviceWorker.ready; + // You'll need to implement your push subscription logic here + } + } +} diff --git a/apps/pwa/.expo/README.md b/apps/pwa/.expo/README.md new file mode 100644 index 000000000..f7eb5fe7e --- /dev/null +++ b/apps/pwa/.expo/README.md @@ -0,0 +1,8 @@ +> Why do I have a folder named ".expo" in my project? +The ".expo" folder is created when an Expo project is started using "expo start" command. +> What do the files contain? +- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds. +- "settings.json": contains the server configuration that is used to serve the application manifest. +> Should I commit the ".expo" folder? +No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine. +Upon project creation, the ".expo" folder is already added to your ".gitignore" file. diff --git a/apps/pwa/.expo/devices.json b/apps/pwa/.expo/devices.json new file mode 100644 index 000000000..5efff6c8c --- /dev/null +++ b/apps/pwa/.expo/devices.json @@ -0,0 +1,3 @@ +{ + "devices": [] +} diff --git a/apps/pwa/package.json b/apps/pwa/package.json index 2da2e66d2..114be0dee 100644 --- a/apps/pwa/package.json +++ b/apps/pwa/package.json @@ -15,6 +15,7 @@ "ts:check": "tsc --noEmit" }, "dependencies": { + "@argent/x-sessions": "^6.7.4", "@avnu/avnu-sdk": "^2.0.0", "@chakra-ui/next-js": "^2.2.0", "@chakra-ui/react": "^2.8.2", @@ -45,13 +46,11 @@ "react-transition-group": "^4.4.5", "react-use-websocket": "^4.8.1", "starknet": "6.9.0", + "starknetkit-next": "npm:starknetkit@2.3.0", "viem": "~2.21.2", "wagmi": "^2.12.8", "zod": "^3.23.8", - "zustand": "^4.5.2", - "starknetkit-next": "npm:starknetkit@2.3.0", - "@argent/x-sessions": "^6.7.4" - + "zustand": "^4.5.2" }, "devDependencies": { "@types/node": "^20", @@ -62,6 +61,7 @@ "eslint": "^8.57.0", "eslint-config-next": "^14.2.4", "framer-motion": "^11.2.4", + "pino-pretty": "^11.3.0", "postcss": "^8.4.38", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/apps/pwa/public/service-worker.js b/apps/pwa/public/service-worker.js new file mode 100644 index 000000000..793b7f07f --- /dev/null +++ b/apps/pwa/public/service-worker.js @@ -0,0 +1,19 @@ +self.addEventListener('push', event => { + const options = { + body: event.data?.text() || 'New notification', + icon: '/notification-icon.png', + badge: '/badge-icon.png', + vibrate: [200, 100, 200] + }; + + event.waitUntil( + self.registration.showNotification('AFK Community', options) + ); +}); + +self.addEventListener('notificationclick', event => { + event.notification.close(); + event.waitUntil( + clients.openWindow('/') + ); +}); \ No newline at end of file diff --git a/apps/pwa/src/app/components/MenuNav.tsx b/apps/pwa/src/app/components/MenuNav.tsx index 2004c05df..6e3943b9b 100644 --- a/apps/pwa/src/app/components/MenuNav.tsx +++ b/apps/pwa/src/app/components/MenuNav.tsx @@ -1,34 +1,57 @@ import {Button, Menu, MenuButton, MenuItem, MenuList} from '@chakra-ui/react'; - +import Link from 'next/link'; +import {useRouter} from 'next/navigation'; import {CustomConnectButtonWallet} from './button/CustomConnectButtonWallet'; interface IMenuParent { children?: React.ReactNode; } + const MenuNav: React.FC = () => { + const router = useRouter(); + + const handleSettingsClick = () => { + router.push('/settings'); + }; + return ( - - {({isOpen}) => ( - <> - } - /> - } - > - {isOpen ? 'Close' : 'Profile'} - - - - - - - - )} - +
+ + + + {({isOpen}) => ( + <> + + {isOpen ? 'Close' : 'Profile'} + + + + + + + + )} + +
); }; diff --git a/apps/pwa/src/app/components/NavigationLinks.tsx b/apps/pwa/src/app/components/NavigationLinks.tsx index dc1a94bb9..9f7ddf3d8 100644 --- a/apps/pwa/src/app/components/NavigationLinks.tsx +++ b/apps/pwa/src/app/components/NavigationLinks.tsx @@ -1,20 +1,15 @@ 'use client'; +import Link from 'next/link'; + export function NavigationLinks() { return (
    - {/*
  • - Features -
  • - Pixel -
  • */} - {/*
  • - -
  • */} - {/* */} + + Settings + +
); } diff --git a/apps/pwa/src/app/layout.tsx b/apps/pwa/src/app/layout.tsx index bd83f564f..b4c7f1dad 100644 --- a/apps/pwa/src/app/layout.tsx +++ b/apps/pwa/src/app/layout.tsx @@ -4,6 +4,8 @@ import '@rainbow-me/rainbowkit/styles.css'; import type {Metadata} from 'next'; import Providers from './providers'; +import {NotificationProvider} from './providers/NotificationProvider'; + export const metadata: Metadata = { title: 'afk community portal', description: 'afk community portal', @@ -13,7 +15,11 @@ export default function RootLayout({children}: {children: React.ReactNode}) { return ( - {children} + + + {children} + + ); diff --git a/apps/pwa/src/app/page.tsx b/apps/pwa/src/app/page.tsx index d96be5646..6864791f9 100644 --- a/apps/pwa/src/app/page.tsx +++ b/apps/pwa/src/app/page.tsx @@ -1,6 +1,5 @@ 'use client'; import {AppRender} from 'pixel_ui'; - import {Navbar} from './components/Navbar'; export default function App() { @@ -12,9 +11,8 @@ export default function App() { artPeaceAddress={process.env.NEXT_PUBLIC_CANVAS_STARKNET_CONTRACT_ADDRESS} nftCanvasAddress={process.env.NEXT_PUBLIC_CANVAS_NFT_CONTRACT_ADDRESS} usernameAddress={process.env.NEXT_PUBLIC_USERNAME_STORE_CONTRACT_ADDRESS} - > + /> )} - {/*