From f391e05f4a644eb8fd23afc582e69c78837416ab Mon Sep 17 00:00:00 2001 From: Sever Abibula <5903809+SeverS@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:00:37 +0200 Subject: [PATCH] chore(): fix calls and add more error handlers (#906) * chore(): fix calls and add more error handlers * chore(): add error handlers to trending widget, minor other fixes * chore(): fixes --- apps/akasha/src/bootstrap.tsx | 2 +- apps/akasha/src/components/app-routes.tsx | 8 +- .../src/components/feed-page/feed-page.tsx | 45 +++++---- .../src/components/post-page/post-page.tsx | 52 +++++----- .../trending-widget/trending-widget-card.tsx | 95 +++++++++++------- sdk-packages/app-loader/src/404.ts | 2 +- sdk-packages/app-loader/src/index.ts | 44 +++++---- sdk-packages/common/package-lock.json | 2 +- .../src/components/Errors/error-card.tsx | 6 +- ui/hooks/src/use-entry-bookmark.ts | 25 ++--- ui/hooks/src/use-global-login.ts | 4 +- ui/hooks/src/use-login-state.ts | 2 +- ui/hooks/src/use-notifications.ts | 65 +++++------- .../src/components/bookmarks-page.tsx | 14 ++- .../trending-widget/trending-widget-card.tsx | 93 +++++++++++------- .../src/components/notifications-page.tsx | 98 +++++++++++++------ .../trending-widget/trending-widget-card.tsx | 95 +++++++++++------- .../search/src/components/routes/index.tsx | 3 +- .../src/components/routes/search-page.tsx | 52 +++++----- .../trending-widget/trending-widget-card.tsx | 93 +++++++++++------- ui/widgets/feed/src/components/entry-feed.tsx | 20 +++- .../src/components/topbar-component.tsx | 25 +++-- .../top-bar/src/components/topbar-widget.tsx | 8 -- 23 files changed, 492 insertions(+), 361 deletions(-) diff --git a/apps/akasha/src/bootstrap.tsx b/apps/akasha/src/bootstrap.tsx index babe1bd270..2c00c8d583 100644 --- a/apps/akasha/src/bootstrap.tsx +++ b/apps/akasha/src/bootstrap.tsx @@ -35,7 +35,7 @@ export const application: Application = { logo: { type: LogoTypeSource.ICON, value: 'appAkasha' }, widgets: { [userPostsRoute]: [ProfileCardWidget], - [fullPostRoute]: [ProfileCardWidget], + [fullPostRoute]: [TrendingWidget, ProfileCardWidget], [routes[FEED]]: [TrendingWidget], }, }; diff --git a/apps/akasha/src/components/app-routes.tsx b/apps/akasha/src/components/app-routes.tsx index 93bc361d8a..6362b5dbd3 100644 --- a/apps/akasha/src/components/app-routes.tsx +++ b/apps/akasha/src/components/app-routes.tsx @@ -76,9 +76,7 @@ const AppRoutes: React.FC = props => { = props => { void; - ethAddress: string | null; - currentUserCalled: boolean; - pubKey: string | null; + loginState: UseLoginState; flagged: string; reportModalOpen: boolean; setFlagged: React.Dispatch>; @@ -53,9 +52,7 @@ const FeedPage: React.FC = props => { setFlagged, setReportModalOpen, showLoginModal, - ethAddress, - currentUserCalled, - pubKey, + loginState, onError, sdkModules, logger, @@ -70,17 +67,20 @@ const FeedPage: React.FC = props => { }); React.useEffect(() => { - if (pubKey) { - loginProfileActions.getProfileData({ pubKey }); + if (loginState.pubKey) { + loginProfileActions.getProfileData({ pubKey: loginState.pubKey }); } - }, [pubKey]); + }, [loginState.pubKey]); React.useEffect(() => { - if (currentUserCalled) { + if (loginState.currentUserCalled) { postsActions.resetPostIds(); postsActions.getPosts({ limit: 5 }); + if (loginState.ethAddress) { + bookmarkActions.getBookmarks(); + } } - }, [currentUserCalled]); + }, [loginState.currentUserCalled, loginState.ethAddress]); const { size, @@ -91,14 +91,13 @@ const FeedPage: React.FC = props => { const locale = (i18n.languages[0] || 'en') as ILocale; const [bookmarkState, bookmarkActions] = useBookmarks({ - pubKey, onError, dbService: sdkModules.db, }); const [, errorActions] = useErrors({ logger }); const [postsState, postsActions] = usePosts({ - user: ethAddress, + user: loginState.ethAddress, postsService: sdkModules.posts, ipfsService: sdkModules.commons.ipfsService, onError: errorActions.createError, @@ -108,7 +107,7 @@ const FeedPage: React.FC = props => { const req: { limit: number; offset?: string } = { limit: payload.limit, }; - if (!postsState.isFetchingPosts && currentUserCalled) { + if (!postsState.isFetchingPosts && loginState.currentUserCalled) { postsActions.getPosts(req); } }; @@ -125,7 +124,7 @@ const FeedPage: React.FC = props => { props.singleSpa.navigateToUrl(`/profile/${profilePubKey}`); }; const handleEntryBookmark = (entryId: string) => { - if (!pubKey) { + if (!loginState.pubKey) { return showLoginModal(); } if (bookmarkState.bookmarks.findIndex(bm => bm.entryId === entryId) >= 0) { @@ -134,7 +133,7 @@ const FeedPage: React.FC = props => { return bookmarkActions.bookmarkPost(entryId); }; const handleEntryRepost = (_withComment: boolean, entryData: any) => { - if (!pubKey) { + if (!loginState.pubKey) { showLoginModal(); } else { setCurrentEmbedEntry(entryData); @@ -191,7 +190,7 @@ const FeedPage: React.FC = props => { const handleNavigateToPost = redirectToPost(props.singleSpa.navigateToUrl); const handleEntryPublish = async (data: PublishPostData) => { - if (!ethAddress && !pubKey) { + if (!loginState.ethAddress && !loginState.pubKey) { showLoginModal(); return; } @@ -244,7 +243,7 @@ const FeedPage: React.FC = props => { reportLabel={t('Report')} blockLabel={t('Block User')} closeLabel={t('Close')} - user={ethAddress ? ethAddress : ''} + user={loginState.ethAddress ? loginState.ethAddress : ''} contentId={flagged} contentType="post" baseUrl={constants.BASE_FLAG_URL} @@ -262,7 +261,7 @@ const FeedPage: React.FC = props => { slotId={props.layout.app.modalSlotId} avatar={loginProfile.avatar} showModal={showEditor} - ethAddress={ethAddress as any} + ethAddress={loginState.ethAddress as any} postLabel={t('Publish')} placeholderLabel={t('Write something')} discardPostLabel={t('Discard Post')} @@ -288,9 +287,9 @@ const FeedPage: React.FC = props => { hasMoreItems={!!postsState.nextPostIndex} usePlaceholders={true} listHeader={ - ethAddress ? ( + loginState.ethAddress ? ( = props => { logger={logger} globalChannel={globalChannel} bookmarkState={bookmarkState} - ethAddress={ethAddress} + ethAddress={loginState.ethAddress} locale={locale} onBookmark={handleEntryBookmark} onNavigate={handleNavigateToPost} @@ -338,7 +337,7 @@ const FeedPage: React.FC = props => { globalChannel, isMobile, feedItems: postsState.postIds, - loggedEthAddress: ethAddress, + loggedEthAddress: loginState.ethAddress, pendingEntries: postsState.pendingPosts, })} /> diff --git a/apps/akasha/src/components/post-page/post-page.tsx b/apps/akasha/src/components/post-page/post-page.tsx index 3324bae6b3..d418e4771e 100644 --- a/apps/akasha/src/components/post-page/post-page.tsx +++ b/apps/akasha/src/components/post-page/post-page.tsx @@ -18,6 +18,7 @@ import PostRenderer from './post-renderer'; import { getPendingComments } from './post-page-pending-comments'; import routes, { POST } from '../../routes'; import { IAkashaError, RootComponentProps } from '@akashaproject/ui-awf-typings'; +import { UseLoginState } from '@akashaproject/ui-awf-hooks/lib/use-login-state'; const { Box, @@ -38,9 +39,7 @@ const { } = DS; interface IPostPage { - ethAddress: string | null; - currentUserCalled: boolean; - pubKey: string | null; + loginState: UseLoginState; flagged: string; reportModalOpen: boolean; setFlagged: React.Dispatch>; @@ -57,13 +56,12 @@ const PostPage: React.FC = props => { globalChannel, flagged, reportModalOpen, - currentUserCalled, setFlagged, setReportModalOpen, showLoginModal, logger, navigateToUrl, - ethAddress, + loginState, isMobile, } = props; @@ -72,7 +70,7 @@ const PostPage: React.FC = props => { const [, errorActions] = useErrors({ logger }); const [postsState, postsActions] = usePosts({ - user: ethAddress, + user: loginState.ethAddress, postsService: sdkModules.posts, ipfsService: sdkModules.commons.ipfsService, onError: errorActions.createError, @@ -99,14 +97,13 @@ const PostPage: React.FC = props => { }); React.useEffect(() => { - if (props.pubKey) { - loginProfileActions.getProfileData({ pubKey: props.pubKey }); + if (loginState.pubKey) { + loginProfileActions.getProfileData({ pubKey: loginState.pubKey }); } - }, [props.pubKey]); + }, [loginState.pubKey]); const [bookmarkState, bookmarkActions] = useBookmarks({ dbService: sdkModules.db, - pubKey: props.pubKey, onError: errorActions.createError, }); @@ -117,10 +114,10 @@ const PostPage: React.FC = props => { }); React.useEffect(() => { - if (ethAddress && entryData?.author.ethAddress) { - followActions.isFollowing(ethAddress, entryData.author.ethAddress); + if (loginState.ethAddress && entryData?.author.ethAddress) { + followActions.isFollowing(loginState.ethAddress, entryData.author.ethAddress); } - }, [ethAddress, entryData?.author.ethAddress]); + }, [loginState.ethAddress, entryData?.author.ethAddress]); const handleFollow = () => { if (entryData?.author.ethAddress) { @@ -152,11 +149,14 @@ const PostPage: React.FC = props => { React.useEffect(() => { // this is used to initialise comments when navigating to other post ids - if (postId && currentUserCalled) { + if (postId && loginState.currentUserCalled) { postsActions.getPost(postId); handleLoadMore({ limit: 5, postID: postId }); + if (loginState.ethAddress) { + bookmarkActions.getBookmarks(); + } } - }, [postId, currentUserCalled]); + }, [postId, loginState.currentUserCalled, loginState.ethAddress]); const bookmarked = React.useMemo(() => { if ( @@ -178,7 +178,7 @@ const PostPage: React.FC = props => { }; const handleEntryBookmark = (entryId: string) => { - if (!ethAddress) { + if (!loginState.ethAddress) { return showLoginModal(); } if (bookmarkState.bookmarks.findIndex(bm => bm.entryId === entryId) >= 0) { @@ -188,7 +188,7 @@ const PostPage: React.FC = props => { }; const handleCommentBookmark = (commentId: string) => { - if (!ethAddress) { + if (!loginState.ethAddress) { return showLoginModal(); } if (bookmarkState.bookmarks.findIndex(bm => bm.entryId === commentId) >= 0) { @@ -222,7 +222,7 @@ const PostPage: React.FC = props => { content: any; textContent: any; }) => { - if (!ethAddress) { + if (!loginState.ethAddress) { showLoginModal(); return; } @@ -335,7 +335,7 @@ const PostPage: React.FC = props => { reportLabel={t('Report')} blockLabel={t('Block User')} closeLabel={t('Close')} - user={ethAddress ? ethAddress : ''} + user={loginState.ethAddress ? loginState.ethAddress : ''} contentId={flagged} contentType="post" baseUrl={constants.BASE_FLAG_URL} @@ -394,14 +394,14 @@ const PostPage: React.FC = props => { shareLabel={t('Share')} copyLinkLabel={t('Copy Link')} flagAsLabel={t('Report Post')} - loggedProfileEthAddress={ethAddress} + loggedProfileEthAddress={loginState.ethAddress} locale={locale} bookmarkLabel={t('Save')} bookmarkedLabel={t('Saved')} onRepost={() => { return; }} - onEntryFlag={handleEntryFlag(entryData.entryId, ethAddress)} + onEntryFlag={handleEntryFlag(entryData.entryId, loginState.ethAddress)} handleFollowAuthor={handleFollow} handleUnfollowAuthor={handleUnfollow} isFollowingAuthor={isFollowing} @@ -422,16 +422,16 @@ const PostPage: React.FC = props => { )} - {!ethAddress && ( + {!loginState.ethAddress && ( )} - {ethAddress && ( + {loginState.ethAddress && ( = props => { logger={logger} globalChannel={globalChannel} bookmarkState={bookmarkState} - ethAddress={ethAddress} + ethAddress={loginState.ethAddress} locale={locale} onBookmark={handleCommentBookmark} onNavigate={handleNavigateToPost} @@ -492,7 +492,7 @@ const PostPage: React.FC = props => { isMobile, sdkModules, feedItems: postsState.postIds, - loggedEthAddress: ethAddress, + loggedEthAddress: loginState.ethAddress, pendingComments: postsState.pendingComments, })} /> diff --git a/apps/akasha/src/widgets/trending-widget/trending-widget-card.tsx b/apps/akasha/src/widgets/trending-widget/trending-widget-card.tsx index 202e93f076..8e6239a554 100644 --- a/apps/akasha/src/widgets/trending-widget/trending-widget-card.tsx +++ b/apps/akasha/src/widgets/trending-widget/trending-widget-card.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import DS from '@akashaproject/design-system'; -import { RootComponentProps, IAkashaError } from '@akashaproject/ui-awf-typings'; +import { RootComponentProps } from '@akashaproject/ui-awf-typings'; import { useTranslation } from 'react-i18next'; import { useTrendingData, @@ -8,28 +8,25 @@ import { useFollow, useTagSubscribe, } from '@akashaproject/ui-awf-hooks'; +import useErrorState from '@akashaproject/ui-awf-hooks/lib/use-error-state'; -const { TrendingWidgetCard } = DS; - -// export interface TrendingWidgetCardProps {} +const { TrendingWidgetCard, ErrorInfoCard, ErrorLoader } = DS; const TrendingWidget: React.FC = props => { const { globalChannel, sdkModules, logger, singleSpa } = props; const { t } = useTranslation(); + const [errorState, errorActions] = useErrorState({ logger }); + const [trendingData] = useTrendingData({ sdkModules: sdkModules, - onError: (err: IAkashaError) => { - logger.error('useTrendingData error %j', err); - }, + onError: errorActions.createError, }); const [loginState] = useLoginState({ globalChannel: globalChannel, - onError: (err: IAkashaError) => { - logger.error('useLoginState error %j', err); - }, + onError: errorActions.createError, authService: sdkModules.auth.authService, ipfsService: sdkModules.commons.ipfsService, profileService: sdkModules.profiles.profileService, @@ -38,17 +35,13 @@ const TrendingWidget: React.FC = props => { const [followedProfiles, followActions] = useFollow({ globalChannel, profileService: sdkModules.profiles.profileService, - onError: (errorInfo: IAkashaError) => { - logger.error(errorInfo.error.message, errorInfo.errorKey); - }, + onError: errorActions.createError, }); const [tagSubscriptionState, tagSubscriptionActions] = useTagSubscribe({ globalChannel, profileService: sdkModules.profiles.profileService, - onError: (errorInfo: IAkashaError) => { - logger.error(errorInfo.error.message, errorInfo.errorKey); - }, + onError: errorActions.createError, }); React.useEffect(() => { @@ -58,10 +51,18 @@ const TrendingWidget: React.FC = props => { followActions.isFollowing(loginState.ethAddress, profile.ethAddress); } }); - tagSubscriptionActions.getTagSubscriptions(); } }, [trendingData, loginState.ethAddress]); + React.useEffect(() => { + if (loginState.waitForAuth && !loginState.ready) { + return; + } + if ((loginState.waitForAuth && loginState.ready) || loginState.currentUserCalled) { + tagSubscriptionActions.getTagSubscriptions(); + } + }, [JSON.stringify(loginState)]); + const handleTagClick = () => { // todo }; @@ -83,26 +84,46 @@ const TrendingWidget: React.FC = props => { }; return ( - + + {(errMessages, hasCriticalErrors) => ( + <> + {(hasCriticalErrors || errMessages) && ( + + )} + {!hasCriticalErrors && !errMessages && ( + + )} + + )} + ); }; diff --git a/sdk-packages/app-loader/src/404.ts b/sdk-packages/app-loader/src/404.ts index 529231e205..22d5b4b751 100644 --- a/sdk-packages/app-loader/src/404.ts +++ b/sdk-packages/app-loader/src/404.ts @@ -1,7 +1,7 @@ import createTemplateElement from './create-template-element'; export default createTemplateElement(` -
+

404

The page you are looking for does not exist.

diff --git a/sdk-packages/app-loader/src/index.ts b/sdk-packages/app-loader/src/index.ts index 0639c9aae8..f330134d9c 100644 --- a/sdk-packages/app-loader/src/index.ts +++ b/sdk-packages/app-loader/src/index.ts @@ -66,6 +66,7 @@ export default class AppLoader implements IAppLoader { integrationId: string; menuItemType?: MenuItemType; }[]; + private fourOhFourTimeout: NodeJS.Timeout | null; private isRegisteringLayout: boolean; private apps: IAppEntry[]; private widgets: { @@ -102,6 +103,8 @@ export default class AppLoader implements IAppLoader { this.channels = channels; this.isMobile = detectMobile().phone || detectMobile().tablet; + this.fourOhFourTimeout = null; + this.events = new BehaviorSubject(EventTypes.Instantiated); this.menuItems = { nextIndex: 1, items: [] }; @@ -420,24 +423,31 @@ export default class AppLoader implements IAppLoader { if (fourOhFourElem) { fourOhFourElem.parentElement.removeChild(fourOhFourElem); } - if (!currentPlugins.length) { - const pluginsNode = document.getElementById(this.config.layout.app.pluginSlotId); - // create a 404 page and return it instead of a plugin - const FourOhFourNode: ChildNode = fourOhFour; - if (pluginsNode) { - pluginsNode.appendChild(FourOhFourNode); - } - return; + if (this.fourOhFourTimeout) { + clearTimeout(this.fourOhFourTimeout); + this.fourOhFourTimeout = null; } - this.appLogger.info(`active plugin %j`, currentPlugins); - const firstPlugin = currentPlugins.find(plugin => this.registeredIntegrations.has(plugin)); - if (firstPlugin) { - setPageTitle(this.registeredIntegrations.get(firstPlugin).title); - } else { - this.appLogger.warn( - `could not find a registered active app from active plugins list %j`, - currentPlugins, - ); + this.fourOhFourTimeout = setTimeout(() => { + if (!currentPlugins.length) { + const pluginsNode = document.getElementById(this.config.layout.app.pluginSlotId); + // create a 404 page and return it instead of a plugin + const FourOhFourNode: ChildNode = fourOhFour; + if (pluginsNode) { + pluginsNode.appendChild(FourOhFourNode); + } + } + }, 1500); + if (currentPlugins.length) { + this.appLogger.info(`active plugin %j`, currentPlugins); + const firstPlugin = currentPlugins.find(plugin => this.registeredIntegrations.has(plugin)); + if (firstPlugin) { + setPageTitle(this.registeredIntegrations.get(firstPlugin).title); + } else { + this.appLogger.warn( + `could not find a registered active app from active plugins list %j`, + currentPlugins, + ); + } } } private getAppEntries(appNames) { diff --git a/sdk-packages/common/package-lock.json b/sdk-packages/common/package-lock.json index c11a1a21dd..0fd9635510 100644 --- a/sdk-packages/common/package-lock.json +++ b/sdk-packages/common/package-lock.json @@ -1328,7 +1328,7 @@ } }, "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1a27c59c15ab1e95ee8e5c4ed6ad814c49cc439e", + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#1cfbb13862f90f0b391d8a699544d5fe4dfb8c7b", "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { "bn.js": "^4.11.8", diff --git a/ui/design/src/components/Errors/error-card.tsx b/ui/design/src/components/Errors/error-card.tsx index 65ba270cd9..82bc244f67 100644 --- a/ui/design/src/components/Errors/error-card.tsx +++ b/ui/design/src/components/Errors/error-card.tsx @@ -16,7 +16,7 @@ interface ErrorRendererProps { const ErrorRenderer: React.FC = props => { return (
- Expand to see error details + Expand to see error details
= props => { {props.title} - + {message} diff --git a/ui/hooks/src/use-entry-bookmark.ts b/ui/hooks/src/use-entry-bookmark.ts index af970ac0a3..e7f4c9476f 100644 --- a/ui/hooks/src/use-entry-bookmark.ts +++ b/ui/hooks/src/use-entry-bookmark.ts @@ -1,6 +1,5 @@ import { IAkashaError } from '@akashaproject/ui-awf-typings'; import * as React from 'react'; -import { Subscription } from 'rxjs'; import { createErrorHandler } from './utils/error-handler'; export enum BookmarkTypes { @@ -12,7 +11,6 @@ const BOOKMARKED_ENTRIES_KEY = 'AKASHA_APP_BOOKMARK_ENTRIES'; const entriesBookmarks = 'entries-bookmarks'; export interface UseEntryBookmarkProps { - pubKey: string | null; bmKey?: string; dbService: { [key: string]: any }; onError: (err: IAkashaError) => void; @@ -23,25 +21,25 @@ export interface IBookmarkState { isFetching: boolean; } export interface IBookmarkActions { + getBookmarks: () => void; bookmarkPost: (entryId: string) => void; bookmarkComment: (entryId: string) => void; removeBookmark: (entryId: string) => void; } const useEntryBookmark = (props: UseEntryBookmarkProps): [IBookmarkState, IBookmarkActions] => { - const { pubKey, dbService, bmKey = BOOKMARKED_ENTRIES_KEY, onError } = props; + const { dbService, bmKey = BOOKMARKED_ENTRIES_KEY, onError } = props; const [bookmarkState, setBookmarkState] = React.useState({ bookmarks: [], isFetching: true, }); - React.useEffect(() => { - let subs: Subscription | undefined; - if (pubKey) { + const actions: IBookmarkActions = { + getBookmarks() { const call = dbService.settingsAttachment.get({ moduleName: bmKey, }); - subs = call.subscribe((resp: any) => { + call.subscribe((resp: any) => { const { data } = resp; if (!data) { return setBookmarkState({ @@ -60,17 +58,8 @@ const useEntryBookmark = (props: UseEntryBookmarkProps): [IBookmarkState, IBookm }); } } - }, createErrorHandler('useEntryBookmark.useEffect', false, onError)); - } - - return () => { - if (subs) { - subs.unsubscribe(); - } - }; - }, [pubKey]); - - const actions: IBookmarkActions = { + }, createErrorHandler('useEntryBookmark.getBookmarks')); + }, bookmarkPost(entryId) { const newBmks = bookmarkState.bookmarks.slice(); newBmks.unshift({ entryId, type: BookmarkTypes.POST }); diff --git a/ui/hooks/src/use-global-login.ts b/ui/hooks/src/use-global-login.ts index 4cfcef7bbe..6dbc8d3f01 100644 --- a/ui/hooks/src/use-global-login.ts +++ b/ui/hooks/src/use-global-login.ts @@ -15,7 +15,7 @@ export interface UseGlobalLoginProps { onLogout: OnLogoutSuccessHandler; onError?: OnErrorHandler; waitForAuth?: (data: boolean) => void; - onReady?: (data: boolean) => void; + onReady?: (data: { ethAddress: string; pubKey: string }) => void; } const useGlobalLogin = (props: UseGlobalLoginProps): void => { @@ -70,7 +70,7 @@ const useGlobalLogin = (props: UseGlobalLoginProps): void => { }), ); - readyCall.subscribe((payload: { data: boolean }) => { + readyCall.subscribe((payload: { data: { ethAddress: string; pubKey: string } }) => { const { data } = payload; if (props.onReady) { props.onReady(data); diff --git a/ui/hooks/src/use-login-state.ts b/ui/hooks/src/use-login-state.ts index 781121a629..1409bc9490 100644 --- a/ui/hooks/src/use-login-state.ts +++ b/ui/hooks/src/use-login-state.ts @@ -31,7 +31,7 @@ export interface UseLoginState { * defaults to false */ currentUserCalled: boolean; - ready: boolean | null; + ready: { ethAddress: string; pubKey: string } | null; waitForAuth: boolean | null; } export interface UseLoginActions { diff --git a/ui/hooks/src/use-notifications.ts b/ui/hooks/src/use-notifications.ts index f15adad354..3c76a5331f 100644 --- a/ui/hooks/src/use-notifications.ts +++ b/ui/hooks/src/use-notifications.ts @@ -29,28 +29,15 @@ export const useNotifications = ( }, UseNotificationsActions, ] => { - const { - onError, - globalChannel, - authService, - ipfsService, - profileService, - loggedEthAddress, - } = props; + const { onError, globalChannel, authService, ipfsService, profileService } = props; const [notificationsState, setNotificationsState] = React.useState<{ notifications: any[]; isFetching: boolean; }>({ notifications: [], - isFetching: false, + isFetching: true, }); - React.useEffect(() => { - if (loggedEthAddress) { - actions.getMessages(); - } - }, [loggedEthAddress]); - const handleSubscribe = (payload: any) => { const { data, channelInfo } = payload; if (data) { @@ -85,12 +72,6 @@ export const useNotifications = ( const actions: UseNotificationsActions = { async getMessages() { try { - setNotificationsState(prev => { - return { - ...prev, - isFetching: true, - }; - }); const getMessagesCall = authService.getMessages(null); const ipfsGatewayCall = ipfsService.getSettings(null); const initialResp: any = await forkJoin([ipfsGatewayCall, getMessagesCall]).toPromise(); @@ -105,29 +86,31 @@ export const useNotifications = ( const [gatewayResp, messagesResp] = initialResp; let completeMessages: any = []; - profilesResp?.map((profileResp: any) => { - const { avatar, coverImage, ...other } = profileResp.data?.resolveProfile; - const images: { avatar: string | null; coverImage: string | null } = { - avatar: null, - coverImage: null, - }; - if (avatar) { - images.avatar = getMediaUrl(gatewayResp.data, avatar); - } - if (coverImage) { - images.coverImage = getMediaUrl(gatewayResp.data, coverImage); - } - const profileData = { ...images, ...other }; - completeMessages = messagesResp.data?.map((message: any) => { - if (message.body.value.author === profileData.pubKey) { - message.body.value.author = profileData; + profilesResp + ?.filter((res: any) => res.data) + .map((profileResp: any) => { + const { avatar, coverImage, ...other } = profileResp.data?.resolveProfile; + const images: { avatar: string | null; coverImage: string | null } = { + avatar: null, + coverImage: null, + }; + if (avatar) { + images.avatar = getMediaUrl(gatewayResp.data, avatar); } - if (message.body.value.follower === profileData.pubKey) { - message.body.value.follower = profileData; + if (coverImage) { + images.coverImage = getMediaUrl(gatewayResp.data, coverImage); } - return message; + const profileData = { ...images, ...other }; + completeMessages = messagesResp.data?.map((message: any) => { + if (message.body.value.author === profileData.pubKey) { + message.body.value.author = profileData; + } + if (message.body.value.follower === profileData.pubKey) { + message.body.value.follower = profileData; + } + return message; + }); }); - }); setNotificationsState({ isFetching: false, notifications: completeMessages }); } catch (ex) { if (onError) { diff --git a/ui/plugins/bookmarks/src/components/bookmarks-page.tsx b/ui/plugins/bookmarks/src/components/bookmarks-page.tsx index aa0514a8c7..8c249e1523 100644 --- a/ui/plugins/bookmarks/src/components/bookmarks-page.tsx +++ b/ui/plugins/bookmarks/src/components/bookmarks-page.tsx @@ -29,7 +29,6 @@ const BookmarksPage = (props: RootComponentProps) => { onLogout: () => props.singleSpa.navigateToUrl('/'), }); const [bookmarkState, bookmarkActions] = useBookmarks({ - pubKey: loginState.pubKey, dbService: sdkModules.db, onError: errorActions.createError, }); @@ -41,6 +40,18 @@ const BookmarksPage = (props: RootComponentProps) => { ipfsService: sdkModules.commons.ipfsService, onError: errorActions.createError, }); + React.useEffect(() => { + if (loginState.waitForAuth && !loginState.ready) { + return; + } + if (loginState.waitForAuth && loginState.ready) { + return bookmarkActions.getBookmarks(); + } + if (loginState.currentUserCalled) { + return bookmarkActions.getBookmarks(); + } + }, [JSON.stringify(loginState)]); + React.useEffect(() => { if (bookmarkState.bookmarks.length) { bookmarkState.bookmarks.forEach(bookmark => { @@ -99,7 +110,6 @@ const BookmarksPage = (props: RootComponentProps) => { const modifiedEntry = { ...entry, reported: false }; postActions.updatePostsState(modifiedEntry); }; - return ( <> diff --git a/ui/plugins/bookmarks/src/trending-widget/trending-widget-card.tsx b/ui/plugins/bookmarks/src/trending-widget/trending-widget-card.tsx index 202e93f076..c133c2f66f 100644 --- a/ui/plugins/bookmarks/src/trending-widget/trending-widget-card.tsx +++ b/ui/plugins/bookmarks/src/trending-widget/trending-widget-card.tsx @@ -1,15 +1,16 @@ import * as React from 'react'; import DS from '@akashaproject/design-system'; -import { RootComponentProps, IAkashaError } from '@akashaproject/ui-awf-typings'; +import { RootComponentProps } from '@akashaproject/ui-awf-typings'; import { useTranslation } from 'react-i18next'; import { useTrendingData, useLoginState, useFollow, useTagSubscribe, + useErrors, } from '@akashaproject/ui-awf-hooks'; -const { TrendingWidgetCard } = DS; +const { TrendingWidgetCard, ErrorInfoCard, ErrorLoader } = DS; // export interface TrendingWidgetCardProps {} @@ -18,18 +19,16 @@ const TrendingWidget: React.FC = props => { const { t } = useTranslation(); + const [errorState, errorActions] = useErrors({ logger }); + const [trendingData] = useTrendingData({ sdkModules: sdkModules, - onError: (err: IAkashaError) => { - logger.error('useTrendingData error %j', err); - }, + onError: errorActions.createError, }); const [loginState] = useLoginState({ globalChannel: globalChannel, - onError: (err: IAkashaError) => { - logger.error('useLoginState error %j', err); - }, + onError: errorActions.createError, authService: sdkModules.auth.authService, ipfsService: sdkModules.commons.ipfsService, profileService: sdkModules.profiles.profileService, @@ -38,17 +37,13 @@ const TrendingWidget: React.FC = props => { const [followedProfiles, followActions] = useFollow({ globalChannel, profileService: sdkModules.profiles.profileService, - onError: (errorInfo: IAkashaError) => { - logger.error(errorInfo.error.message, errorInfo.errorKey); - }, + onError: errorActions.createError, }); const [tagSubscriptionState, tagSubscriptionActions] = useTagSubscribe({ globalChannel, profileService: sdkModules.profiles.profileService, - onError: (errorInfo: IAkashaError) => { - logger.error(errorInfo.error.message, errorInfo.errorKey); - }, + onError: errorActions.createError, }); React.useEffect(() => { @@ -58,10 +53,18 @@ const TrendingWidget: React.FC = props => { followActions.isFollowing(loginState.ethAddress, profile.ethAddress); } }); - tagSubscriptionActions.getTagSubscriptions(); } }, [trendingData, loginState.ethAddress]); + React.useEffect(() => { + if (loginState.waitForAuth && !loginState.ready) { + return; + } + if ((loginState.waitForAuth && loginState.ready) || loginState.currentUserCalled) { + tagSubscriptionActions.getTagSubscriptions(); + } + }, [JSON.stringify(loginState)]); + const handleTagClick = () => { // todo }; @@ -83,26 +86,46 @@ const TrendingWidget: React.FC = props => { }; return ( - + + {(errMessages, hasCriticalErrors) => ( + <> + {(hasCriticalErrors || errMessages) && ( + + )} + {!hasCriticalErrors && !errMessages && ( + + )} + + )} + ); }; diff --git a/ui/plugins/notifications/src/components/notifications-page.tsx b/ui/plugins/notifications/src/components/notifications-page.tsx index df815157c0..028f505b9d 100644 --- a/ui/plugins/notifications/src/components/notifications-page.tsx +++ b/ui/plugins/notifications/src/components/notifications-page.tsx @@ -3,6 +3,7 @@ import DS from '@akashaproject/design-system'; import { IAkashaError } from '@akashaproject/ui-awf-typings'; import { useTranslation } from 'react-i18next'; import { useLoginState, useNotifications } from '@akashaproject/ui-awf-hooks'; +import useErrorState from '@akashaproject/ui-awf-hooks/lib/use-error-state'; const { Helmet, @@ -14,6 +15,7 @@ const { ProfileAvatarButton, formatRelativeTime, ErrorLoader, + ErrorInfoCard, Spinner, } = DS; @@ -40,10 +42,10 @@ const NotificationsPage: React.FC = props => { profileService: sdkModules.profiles.profileService, }); + const [notifErrors, notifErrorActions] = useErrorState({ logger }); + const [notificationsState, notificationsActions] = useNotifications({ - onError: (err: IAkashaError) => { - logger.error('useNotifications error %j', err); - }, + onError: notifErrorActions.createError, globalChannel: globalChannel, authService: sdkModules.auth.authService, ipfsService: sdkModules.commons.ipfsService, @@ -51,6 +53,15 @@ const NotificationsPage: React.FC = props => { loggedEthAddress: loginState.ethAddress, }); + React.useEffect(() => { + if (loginState.waitForAuth && !loginState.ready) { + return; + } + if ((loginState.waitForAuth && loginState.ready) || loginState.currentUserCalled) { + return notificationsActions.getMessages(); + } + }, [JSON.stringify(loginState)]); + const handleMarkAllAsRead = () => { notificationsState.notifications.forEach((notif: any) => { notificationsActions.markMessageAsRead(notif.id); @@ -121,35 +132,64 @@ const NotificationsPage: React.FC = props => { return ( - Notifications + {t('My notifications')} - - {notificationsState.isFetching && ( - - - - )} - {!notificationsState.isFetching && notificationsState.notifications.length === 0 && ( - - )} - {!notificationsState.isFetching && notificationsState.notifications.length !== 0 && ( - - - - {t('Notifications')} - -