Small notifications ux improvements
This commit is contained in:
parent
1ca73ecd4d
commit
a6cbb6b759
|
@ -69,3 +69,6 @@ export type PortfolioMetrics = {
|
||||||
timestamp: number
|
timestamp: number
|
||||||
userId: string
|
userId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const MANIFOLD_USERNAME = 'ManifoldMarkets'
|
||||||
|
export const MANIFOLD_AVATAR_URL = 'https://manifold.markets/logo-bg-white.png'
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import {
|
import {
|
||||||
|
MANIFOLD_AVATAR_URL,
|
||||||
|
MANIFOLD_USERNAME,
|
||||||
PrivateUser,
|
PrivateUser,
|
||||||
STARTING_BALANCE,
|
STARTING_BALANCE,
|
||||||
SUS_STARTING_BALANCE,
|
SUS_STARTING_BALANCE,
|
||||||
|
@ -160,8 +162,8 @@ const addUserToDefaultGroups = async (user: User) => {
|
||||||
text: `Welcome, ${user.name} (@${user.username})!`,
|
text: `Welcome, ${user.name} (@${user.username})!`,
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
userName: 'Manifold Markets',
|
userName: 'Manifold Markets',
|
||||||
userUsername: 'ManifoldMarkets',
|
userUsername: MANIFOLD_USERNAME,
|
||||||
userAvatarUrl: 'https://manifold.markets/logo-bg-white.png',
|
userAvatarUrl: MANIFOLD_AVATAR_URL,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,12 @@ import { Title } from 'web/components/title'
|
||||||
import { doc, updateDoc } from 'firebase/firestore'
|
import { doc, updateDoc } from 'firebase/firestore'
|
||||||
import { db } from 'web/lib/firebase/init'
|
import { db } from 'web/lib/firebase/init'
|
||||||
import { UserLink } from 'web/components/user-page'
|
import { UserLink } from 'web/components/user-page'
|
||||||
import { notification_subscribe_types, PrivateUser } from 'common/user'
|
import {
|
||||||
|
MANIFOLD_AVATAR_URL,
|
||||||
|
MANIFOLD_USERNAME,
|
||||||
|
notification_subscribe_types,
|
||||||
|
PrivateUser,
|
||||||
|
} from 'common/user'
|
||||||
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
||||||
import { listenForPrivateUser, updatePrivateUser } from 'web/lib/firebase/users'
|
import { listenForPrivateUser, updatePrivateUser } from 'web/lib/firebase/users'
|
||||||
import { LoadingIndicator } from 'web/components/loading-indicator'
|
import { LoadingIndicator } from 'web/components/loading-indicator'
|
||||||
|
@ -37,6 +42,7 @@ import Custom404 from 'web/pages/404'
|
||||||
import { track } from '@amplitude/analytics-browser'
|
import { track } from '@amplitude/analytics-browser'
|
||||||
import { Pagination } from 'web/components/pagination'
|
import { Pagination } from 'web/components/pagination'
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||||
|
import Router from 'next/router'
|
||||||
|
|
||||||
export const NOTIFICATIONS_PER_PAGE = 30
|
export const NOTIFICATIONS_PER_PAGE = 30
|
||||||
const MULTIPLE_USERS_KEY = 'multipleUsers'
|
const MULTIPLE_USERS_KEY = 'multipleUsers'
|
||||||
|
@ -550,6 +556,8 @@ function NotificationItem(props: {
|
||||||
setNotificationsAsSeen([notification])
|
setNotificationsAsSeen([notification])
|
||||||
}, [notification])
|
}, [notification])
|
||||||
|
|
||||||
|
const questionNeedsResolution = sourceUpdateType == 'closed'
|
||||||
|
|
||||||
if (justSummary) {
|
if (justSummary) {
|
||||||
return (
|
return (
|
||||||
<Row className={'items-center text-sm text-gray-500 sm:justify-start'}>
|
<Row className={'items-center text-sm text-gray-500 sm:justify-start'}>
|
||||||
|
@ -565,7 +573,7 @@ function NotificationItem(props: {
|
||||||
<span className={'flex-shrink-0'}>
|
<span className={'flex-shrink-0'}>
|
||||||
{sourceType &&
|
{sourceType &&
|
||||||
reason &&
|
reason &&
|
||||||
getReasonForShowingNotification(notification, true, true)}
|
getReasonForShowingNotification(notification, true)}
|
||||||
</span>
|
</span>
|
||||||
<div className={'ml-1 text-black'}>
|
<div className={'ml-1 text-black'}>
|
||||||
<NotificationTextLabel
|
<NotificationTextLabel
|
||||||
|
@ -588,9 +596,11 @@ function NotificationItem(props: {
|
||||||
highlighted && 'bg-indigo-200 hover:bg-indigo-100'
|
highlighted && 'bg-indigo-200 hover:bg-indigo-100'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<a
|
<div
|
||||||
href={getSourceUrl(notification)}
|
className={'cursor-pointer'}
|
||||||
onClick={() =>
|
onClick={(event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
Router.push(getSourceUrl(notification) ?? '')
|
||||||
track('Notification Clicked', {
|
track('Notification Clicked', {
|
||||||
type: 'notification item',
|
type: 'notification item',
|
||||||
sourceType,
|
sourceType,
|
||||||
|
@ -602,14 +612,20 @@ function NotificationItem(props: {
|
||||||
sourceUserUsername,
|
sourceUserUsername,
|
||||||
sourceText,
|
sourceText,
|
||||||
})
|
})
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<Row className={'items-center text-gray-500 sm:justify-start'}>
|
<Row className={'items-center text-gray-500 sm:justify-start'}>
|
||||||
<Avatar
|
<Avatar
|
||||||
avatarUrl={sourceUserAvatarUrl}
|
avatarUrl={
|
||||||
|
questionNeedsResolution
|
||||||
|
? MANIFOLD_AVATAR_URL
|
||||||
|
: sourceUserAvatarUrl
|
||||||
|
}
|
||||||
size={'sm'}
|
size={'sm'}
|
||||||
className={'mr-2'}
|
className={'mr-2'}
|
||||||
username={sourceUserName}
|
username={
|
||||||
|
questionNeedsResolution ? MANIFOLD_USERNAME : sourceUserUsername
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<div className={'flex w-full flex-row pl-1 sm:pl-0'}>
|
<div className={'flex w-full flex-row pl-1 sm:pl-0'}>
|
||||||
<div
|
<div
|
||||||
|
@ -618,7 +634,7 @@ function NotificationItem(props: {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{sourceUpdateType != 'closed' && (
|
{!questionNeedsResolution && (
|
||||||
<UserLink
|
<UserLink
|
||||||
name={sourceUserName || ''}
|
name={sourceUserName || ''}
|
||||||
username={sourceUserUsername || ''}
|
username={sourceUserUsername || ''}
|
||||||
|
@ -628,8 +644,7 @@ function NotificationItem(props: {
|
||||||
)}
|
)}
|
||||||
{getReasonForShowingNotification(
|
{getReasonForShowingNotification(
|
||||||
notification,
|
notification,
|
||||||
false,
|
isChildOfGroup ?? false
|
||||||
isChildOfGroup
|
|
||||||
)}
|
)}
|
||||||
{isChildOfGroup ? (
|
{isChildOfGroup ? (
|
||||||
<RelativeTimestamp time={notification.createdTime} />
|
<RelativeTimestamp time={notification.createdTime} />
|
||||||
|
@ -650,7 +665,7 @@ function NotificationItem(props: {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'mt-6 border-b border-gray-300'} />
|
<div className={'mt-6 border-b border-gray-300'} />
|
||||||
</a>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -769,17 +784,10 @@ function NotificationTextLabel(props: {
|
||||||
justSummary?: boolean
|
justSummary?: boolean
|
||||||
}) {
|
}) {
|
||||||
const { className, notification, justSummary } = props
|
const { className, notification, justSummary } = props
|
||||||
const {
|
const { sourceUpdateType, sourceType, sourceText, reasonText } = notification
|
||||||
sourceUpdateType,
|
|
||||||
sourceType,
|
|
||||||
sourceText,
|
|
||||||
sourceContractTitle,
|
|
||||||
reasonText,
|
|
||||||
} = notification
|
|
||||||
const defaultText = sourceText ?? reasonText ?? ''
|
const defaultText = sourceText ?? reasonText ?? ''
|
||||||
if (sourceType === 'contract') {
|
if (sourceType === 'contract') {
|
||||||
if (justSummary) return <span>{sourceContractTitle}</span>
|
if (justSummary || !sourceText) return <div />
|
||||||
if (!sourceText) return <div />
|
|
||||||
// Resolved contracts
|
// Resolved contracts
|
||||||
if (sourceType === 'contract' && sourceUpdateType === 'resolved') {
|
if (sourceType === 'contract' && sourceUpdateType === 'resolved') {
|
||||||
{
|
{
|
||||||
|
@ -857,27 +865,27 @@ function NotificationTextLabel(props: {
|
||||||
|
|
||||||
function getReasonForShowingNotification(
|
function getReasonForShowingNotification(
|
||||||
notification: Notification,
|
notification: Notification,
|
||||||
simple?: boolean,
|
justSummary: boolean
|
||||||
replaceOn?: boolean
|
|
||||||
) {
|
) {
|
||||||
const { sourceType, sourceUpdateType, reason, sourceSlug } = notification
|
const { sourceType, sourceUpdateType, reason, sourceSlug } = notification
|
||||||
let reasonText: string
|
let reasonText: string
|
||||||
switch (sourceType) {
|
switch (sourceType) {
|
||||||
case 'comment':
|
case 'comment':
|
||||||
if (reason === 'reply_to_users_answer')
|
if (reason === 'reply_to_users_answer')
|
||||||
reasonText = !simple ? 'replied to you on' : 'replied'
|
reasonText = justSummary ? 'replied' : 'replied to you on'
|
||||||
else if (reason === 'tagged_user')
|
else if (reason === 'tagged_user')
|
||||||
reasonText = !simple ? 'tagged you on' : 'tagged you'
|
reasonText = justSummary ? 'tagged you' : 'tagged you on'
|
||||||
else if (reason === 'reply_to_users_comment')
|
else if (reason === 'reply_to_users_comment')
|
||||||
reasonText = !simple ? 'replied to you on' : 'replied'
|
reasonText = justSummary ? 'replied' : 'replied to you on'
|
||||||
else reasonText = `commented on`
|
else reasonText = justSummary ? `commented` : `commented on`
|
||||||
break
|
break
|
||||||
case 'contract':
|
case 'contract':
|
||||||
if (reason === 'you_follow_user') reasonText = 'asked'
|
if (reason === 'you_follow_user')
|
||||||
else if (sourceUpdateType === 'resolved') reasonText = `resolved`
|
reasonText = justSummary ? 'asked the question' : 'asked'
|
||||||
else if (sourceUpdateType === 'closed')
|
else if (sourceUpdateType === 'resolved')
|
||||||
reasonText = `Please resolve your question`
|
reasonText = justSummary ? `resolved the question` : `resolved`
|
||||||
else reasonText = `updated`
|
else if (sourceUpdateType === 'closed') reasonText = `Please resolve`
|
||||||
|
else reasonText = justSummary ? 'updated the question' : `updated`
|
||||||
break
|
break
|
||||||
case 'answer':
|
case 'answer':
|
||||||
if (reason === 'on_users_contract') reasonText = `answered your question `
|
if (reason === 'on_users_contract') reasonText = `answered your question `
|
||||||
|
@ -904,7 +912,7 @@ function getReasonForShowingNotification(
|
||||||
default:
|
default:
|
||||||
reasonText = ''
|
reasonText = ''
|
||||||
}
|
}
|
||||||
return replaceOn ? reasonText.replace(' on', '') : reasonText
|
return reasonText
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: where should we put referral bonus notifications?
|
// TODO: where should we put referral bonus notifications?
|
||||||
|
|
Loading…
Reference in New Issue
Block a user