refactor(client): Move banner orchestration to `BannerRegion` effects (#28414)
parent
b9e4b18d10
commit
0d286a5597
File diff suppressed because one or more lines are too long
@ -1,40 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
|
||||
import * as banners from '../../../client/lib/banners'; |
||||
|
||||
Meteor.startup(function () { |
||||
Tracker.autorun(() => { |
||||
const user = Meteor.user(); |
||||
|
||||
if (user && Object.keys(user.banners || {}).length > 0) { |
||||
const firstBanner = Object.values(user.banners) |
||||
.filter((b) => b.read !== true) |
||||
.sort((a, b) => b.priority - a.priority)[0]; |
||||
|
||||
if (!firstBanner) { |
||||
return; |
||||
} |
||||
|
||||
firstBanner.textArguments = firstBanner.textArguments || []; |
||||
|
||||
banners.open({ |
||||
id: firstBanner.id, |
||||
title: TAPi18n.__(firstBanner.title), |
||||
text: TAPi18n.__(firstBanner.text, ...firstBanner.textArguments), |
||||
modifiers: firstBanner.modifiers, |
||||
action() { |
||||
if (firstBanner.link) { |
||||
window.open(firstBanner.link, '_system'); |
||||
} |
||||
}, |
||||
onClose() { |
||||
Meteor.call('banner/dismiss', { |
||||
id: firstBanner.id, |
||||
}); |
||||
}, |
||||
}); |
||||
} |
||||
}); |
||||
}); |
||||
@ -1,73 +0,0 @@ |
||||
import { BannerPlatform } from '@rocket.chat/core-typings'; |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import { Notifications } from '../../app/notifications/client'; |
||||
import { APIClient } from '../../app/utils/client'; |
||||
import * as banners from '../lib/banners'; |
||||
|
||||
const fetchInitialBanners = async (): Promise<void> => { |
||||
const response = await APIClient.get('/v1/banners', { |
||||
platform: BannerPlatform.Web, |
||||
}); |
||||
|
||||
for (const banner of response.banners) { |
||||
banners.open({ |
||||
...banner.view, |
||||
viewId: banner.view.viewId || banner._id, |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
const handleBanner = async (event: { bannerId: string }): Promise<void> => { |
||||
const response = await APIClient.get(`/v1/banners/${event.bannerId}`, { |
||||
platform: BannerPlatform.Web, |
||||
}); |
||||
|
||||
if (!response.banners.length) { |
||||
return banners.closeById(event.bannerId); |
||||
} |
||||
|
||||
for (const banner of response.banners) { |
||||
banners.open({ |
||||
...banner.view, |
||||
viewId: banner.view.viewId || banner._id, |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
const watchBanners = (): (() => void) => { |
||||
fetchInitialBanners(); |
||||
|
||||
Notifications.onLogged('banner-changed', handleBanner); |
||||
|
||||
return (): void => { |
||||
Notifications.unLogged(handleBanner); |
||||
banners.clear(); |
||||
}; |
||||
}; |
||||
|
||||
Meteor.startup(() => { |
||||
let unwatchBanners: () => void | undefined; |
||||
|
||||
Tracker.autorun(() => { |
||||
unwatchBanners?.(); |
||||
|
||||
if (!Meteor.userId()) { |
||||
return; |
||||
} |
||||
|
||||
if (Tracker.nonreactive(() => FlowRouter.getRouteName()) === 'setup-wizard') { |
||||
Tracker.autorun((c) => { |
||||
if (FlowRouter.getRouteName() !== 'setup-wizard') { |
||||
unwatchBanners = Tracker.nonreactive(watchBanners); |
||||
c.stop(); |
||||
} |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
unwatchBanners = Tracker.nonreactive(watchBanners); |
||||
}); |
||||
}); |
||||
@ -0,0 +1,14 @@ |
||||
import { useMethod, useToastMessageDispatch } from '@rocket.chat/ui-contexts'; |
||||
import { useMutation } from '@tanstack/react-query'; |
||||
|
||||
export const useDismissUserBannerMutation = () => { |
||||
const dismissBanner = useMethod('banner/dismiss'); |
||||
|
||||
const dispatchToastMessage = useToastMessageDispatch(); |
||||
|
||||
return useMutation(dismissBanner, { |
||||
onError: (error) => { |
||||
dispatchToastMessage({ type: 'error', message: error }); |
||||
}, |
||||
}); |
||||
}; |
||||
@ -0,0 +1,75 @@ |
||||
import { BannerPlatform } from '@rocket.chat/core-typings'; |
||||
import type { IBanner, Serialized, UiKitBannerPayload } from '@rocket.chat/core-typings'; |
||||
import { useEndpoint, useStream, useUserId, ServerContext } from '@rocket.chat/ui-contexts'; |
||||
import { useContext, useEffect } from 'react'; |
||||
|
||||
import * as banners from '../../../lib/banners'; |
||||
|
||||
export const useRemoteBanners = () => { |
||||
const uid = useUserId(); |
||||
|
||||
const serverContext = useContext(ServerContext); |
||||
const getBanners = useEndpoint('GET', '/v1/banners'); |
||||
const subscribeToNotifyLoggedIn = useStream('notify-logged'); |
||||
|
||||
useEffect(() => { |
||||
if (!uid) { |
||||
return; |
||||
} |
||||
|
||||
const controller = new AbortController(); |
||||
|
||||
const { signal } = controller; |
||||
|
||||
const mapBanner = (banner: Serialized<IBanner>): UiKitBannerPayload => ({ |
||||
...banner.view, |
||||
viewId: banner.view.viewId || banner._id, |
||||
}); |
||||
|
||||
const fetchInitialBanners = async (): Promise<void> => { |
||||
const response = await getBanners({ |
||||
platform: BannerPlatform.Web, |
||||
}); |
||||
|
||||
if (signal?.aborted) { |
||||
return; |
||||
} |
||||
|
||||
response.banners.forEach((banner) => { |
||||
banners.open(mapBanner(banner)); |
||||
}); |
||||
}; |
||||
|
||||
const handleBannerChange = async (event: { bannerId: string }): Promise<void> => { |
||||
const response = await serverContext.callEndpoint({ |
||||
method: 'GET', |
||||
pathPattern: '/v1/banners/:id', |
||||
keys: { id: event.bannerId }, |
||||
params: { platform: BannerPlatform.Web }, |
||||
}); |
||||
|
||||
if (signal?.aborted) { |
||||
return; |
||||
} |
||||
|
||||
if (!response.banners.length) { |
||||
return banners.closeById(event.bannerId); |
||||
} |
||||
|
||||
response.banners.forEach((banner) => { |
||||
banners.open(mapBanner(banner)); |
||||
}); |
||||
}; |
||||
|
||||
fetchInitialBanners(); |
||||
|
||||
const unsubscribeFromBannerChanged = subscribeToNotifyLoggedIn('banner-changed', handleBannerChange); |
||||
|
||||
return () => { |
||||
controller.abort(); |
||||
|
||||
unsubscribeFromBannerChanged(); |
||||
banners.clear(); |
||||
}; |
||||
}, [getBanners, serverContext, subscribeToNotifyLoggedIn, uid]); |
||||
}; |
||||
@ -0,0 +1,44 @@ |
||||
import { useUser } from '@rocket.chat/ui-contexts'; |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
import { useEffect } from 'react'; |
||||
|
||||
import * as banners from '../../../lib/banners'; |
||||
import { useDismissUserBannerMutation } from './useDismissUserBannerMutation'; |
||||
|
||||
export const useUserBanners = () => { |
||||
const user = useUser(); |
||||
|
||||
const dismissBannerMutation = useDismissUserBannerMutation(); |
||||
|
||||
useEffect(() => { |
||||
if (!user?.banners || Object.keys(user.banners).length === 0) { |
||||
return; |
||||
} |
||||
|
||||
const firstBanner = Object.values(user.banners) |
||||
.filter((b) => b.read !== true) |
||||
.sort((a, b) => b.priority - a.priority)[0]; |
||||
|
||||
if (!firstBanner) { |
||||
return; |
||||
} |
||||
|
||||
banners.open({ |
||||
id: firstBanner.id, |
||||
title: TAPi18n.__(firstBanner.title), |
||||
text: TAPi18n.__(firstBanner.text, { |
||||
postProcess: 'sprintf', |
||||
sprintf: firstBanner.textArguments ?? [], |
||||
}), |
||||
modifiers: firstBanner.modifiers, |
||||
action() { |
||||
if (firstBanner.link) { |
||||
window.open(firstBanner.link, '_system'); |
||||
} |
||||
}, |
||||
onClose() { |
||||
dismissBannerMutation.mutate({ id: firstBanner.id }); |
||||
}, |
||||
}); |
||||
}, [dismissBannerMutation, user]); |
||||
}; |
||||
Loading…
Reference in new issue