diff --git a/android/app/build.gradle b/android/app/build.gradle index 76c99cd9..a64b7bbb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "com.compassconnections.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 107 - versionName "1.24.0" + versionCode 108 + versionName "1.25.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/backend/api/package.json b/backend/api/package.json index 14df2ec3..7790f814 100644 --- a/backend/api/package.json +++ b/backend/api/package.json @@ -1,6 +1,6 @@ { "name": "@compass/api", - "version": "1.38.2", + "version": "1.39.0", "private": true, "description": "Backend API endpoints", "main": "src/serve.ts", diff --git a/web/components/messaging/send-message-button.tsx b/web/components/messaging/send-message-button.tsx index 08f17823..d3225fb2 100644 --- a/web/components/messaging/send-message-button.tsx +++ b/web/components/messaging/send-message-button.tsx @@ -4,9 +4,9 @@ import {Profile} from 'common/profiles/profile' import {User} from 'common/user' import {findKey} from 'lodash' import {useRouter} from 'next/router' -import {useEffect, useState} from 'react' +import React, {useEffect, useState} from 'react' import {BiEnvelope} from 'react-icons/bi' -import {Button} from 'web/components/buttons/button' +import {Button, buttonClass} from 'web/components/buttons/button' import {CommentInputTextArea} from 'web/components/comments/comment-input' import {Col} from 'web/components/layout/col' import {Modal, MODAL_CLASS} from 'web/components/layout/modal' @@ -15,26 +15,41 @@ import {useTextEditor} from 'web/components/widgets/editor' import {Tooltip} from 'web/components/widgets/tooltip' import {useFirebaseUser} from 'web/hooks/use-firebase-user' import {useSortedPrivateMessageMemberships} from 'web/hooks/use-private-messages' -import {usePrivateUser} from 'web/hooks/use-user' +import {usePrivateUser, useUser} from 'web/hooks/use-user' import {api} from 'web/lib/api' import {firebaseLogin} from 'web/lib/firebase/users' import {useT} from 'web/lib/locale' export const SendMessageButton = (props: { toUser: User - currentUser: User | undefined | null profile: Profile includeLabel?: boolean circleButton?: boolean text?: string tooltipText?: string + className?: string disabled?: boolean + accentIfMessaged?: boolean + onPointerDown?: () => void + size?: string }) => { - const {toUser, currentUser, profile, includeLabel, circleButton, text, tooltipText, disabled} = - props + const { + toUser, + profile, + includeLabel, + circleButton, + text, + tooltipText, + disabled, + onPointerDown, + className, + size = 'h-6 w-6', + accentIfMessaged, + } = props const firebaseUser = useFirebaseUser() const router = useRouter() const privateUser = usePrivateUser() + const currentUser = useUser() const channelMemberships = useSortedPrivateMessageMemberships(currentUser?.id) const {memberIdsByChannelId} = channelMemberships const t = useT() @@ -43,17 +58,19 @@ export const SendMessageButton = (props: { const [error, setError] = useState('') const [submitting, setSubmitting] = useState(false) + const previousDirectMessageChannel = findKey( + memberIdsByChannelId, + (dm) => dm.includes(toUser.id) && dm.length === 1, + ) + + const previousChannelId = + previousDirectMessageChannel !== undefined ? previousDirectMessageChannel : undefined + + const putAccent = previousChannelId !== undefined && accentIfMessaged + const messageButtonClicked = async () => { if (disabled) return if (!currentUser) return firebaseLogin() - const previousDirectMessageChannel = findKey( - memberIdsByChannelId, - (dm) => dm.includes(toUser.id) && dm.length === 1, - ) - - const previousChannelId = - previousDirectMessageChannel !== undefined ? previousDirectMessageChannel : undefined - if (previousChannelId) router.push(`/messages/${previousChannelId}`) else setOpenComposeModal(true) } @@ -138,12 +155,23 @@ export const SendMessageButton = (props: { return ( <> - + {text ? ( )} diff --git a/web/components/profile-grid.tsx b/web/components/profile-grid.tsx index aa5a20d6..7f6e6bcb 100644 --- a/web/components/profile-grid.tsx +++ b/web/components/profile-grid.tsx @@ -23,12 +23,14 @@ import {PiMagnifyingGlassBold} from 'react-icons/pi' import GenderIcon from 'web/components/gender-icon' import {IconWithInfo} from 'web/components/icons' import {Row} from 'web/components/layout/row' +import {SendMessageButton} from 'web/components/messaging/send-message-button' import {ProfileLocation} from 'web/components/profile/profile-location' import {getSeekingText} from 'web/components/profile-about' import {CompatibleBadge} from 'web/components/widgets/compatible-badge' import {Content} from 'web/components/widgets/editor' import HideProfileButton from 'web/components/widgets/hide-profile-button' import {CompassLoadingIndicator} from 'web/components/widgets/loading-indicator' +import {StarButton} from 'web/components/widgets/star-button' import {LoadMoreUntilNotVisible} from 'web/components/widgets/visibility-observer' import {useChoicesContext} from 'web/hooks/use-choices' import {isDark, useTheme} from 'web/hooks/use-theme' @@ -144,7 +146,16 @@ function ProfilePreview(props: { onUndoHidden?: (userId: string) => void displayOptions?: Partial }) { - const {profile, compatibilityScore, onHide, isHidden, onUndoHidden, displayOptions} = props + const { + profile, + compatibilityScore, + onHide, + isHidden, + onUndoHidden, + displayOptions, + hasStar, + refreshStars, + } = props const { showPhotos, @@ -168,7 +179,6 @@ function ProfilePreview(props: { const {user} = profile const choicesIdsToLabels = useChoicesContext() const t = useT() - // const currentUser = useUser() const [isLoading, setIsLoading] = useState(false) const [showRing, setShowRing] = useState(false) @@ -346,18 +356,21 @@ function ProfilePreview(props: { {compatibilityScore && ( - + )} {onHide && ( { @@ -365,6 +378,32 @@ function ProfilePreview(props: { }} /> )} + {hasStar !== undefined && ( + { + hideButtonClickedRef.current = true + }} + /> + )} + {user && ( +
+ { + hideButtonClickedRef.current = true + }} + /> +
+ )}
diff --git a/web/components/profile/connect-actions.tsx b/web/components/profile/connect-actions.tsx index 29b60454..1a4152b7 100644 --- a/web/components/profile/connect-actions.tsx +++ b/web/components/profile/connect-actions.tsx @@ -89,7 +89,6 @@ export function ConnectActions(props: {profile: Profile; user: User}) { {profile.allow_direct_messaging || matches.length > 0 ? ( diff --git a/web/components/profile/profile-header.tsx b/web/components/profile/profile-header.tsx index ce7f9a98..0abda070 100644 --- a/web/components/profile/profile-header.tsx +++ b/web/components/profile/profile-header.tsx @@ -328,7 +328,6 @@ export function ProfileHeaderActions(props: { {currentUser && showMessageButton && ( diff --git a/web/components/widgets/star-button.tsx b/web/components/widgets/star-button.tsx index 88a555aa..3c2b68d9 100644 --- a/web/components/widgets/star-button.tsx +++ b/web/components/widgets/star-button.tsx @@ -14,8 +14,10 @@ export const StarButton = (props: { refresh: () => Promise hideTooltip?: boolean className?: string + size?: string + onPointerDown?: () => void }) => { - const {targetProfile, refresh, hideTooltip, className} = props + const {targetProfile, refresh, hideTooltip, className, size = 'w-6 h-6', onPointerDown} = props const targetId = targetProfile.user_id const [isStarred, setIsStarred] = useState(props.isStarred) const t = useT() @@ -41,18 +43,21 @@ export const StarButton = (props: { const button = ( ) diff --git a/web/components/widgets/tooltip.tsx b/web/components/widgets/tooltip.tsx index 140fc97b..707dce89 100644 --- a/web/components/widgets/tooltip.tsx +++ b/web/components/widgets/tooltip.tsx @@ -123,7 +123,7 @@ export function Tooltip(props: { as="div" ref={refs.setFloating as any} style={{position: strategy, top: y ?? 0, left: x ?? 0}} - className="text-ink-1000 bg-canvas-50 z-20 w-max max-w-xs whitespace-normal rounded-lg px-2 py-1 text-center text-sm font-medium border border-canvas-100 shadow shadow-canvas-100" + className="text-ink-1000 bg-primary-100 z-20 w-max max-w-xs whitespace-normal rounded-lg px-2 py-1 text-center text-sm font-medium border border-primary-300 shadow shadow-canvas-100" suppressHydrationWarning={suppressHydrationWarning} {...getFloatingProps()} > diff --git a/web/styles/globals.css b/web/styles/globals.css index 22e68557..653c0b61 100644 --- a/web/styles/globals.css +++ b/web/styles/globals.css @@ -106,6 +106,7 @@ --color-ink-600: 120 108 92; /* Green - Accents */ + --color-green-200: #f0faf3; --color-green-500: 107 143 113; /* Accent - Sage Green (#6B8F71) */ /* Canvas - Backgrounds & Surfaces */ @@ -182,7 +183,7 @@ /*--color-green-500: 34 197 94; !* standard green *!*/ --color-green-400: 74 222 128; --color-green-300: 110 231 183; /* vibrant but not neon */ - --color-green-200: 167 243 208; /* gentle mid-light tone */ + /*--color-green-200: 167 243 208; !* gentle mid-light tone *!*/ --color-green-100: 209 260 229; /* soft and airy */ --color-green-50: 240 263 245; /* subtle, barely tinted background */ @@ -222,8 +223,11 @@ --color-ink-500: 176 160 140; /* Muted Text - shifted to warm tan */ --color-ink-600: 156 140 120; - /* Green - Sage looks great on dark brown */ - --color-green-500: 125 160 131; /* Lightened Sage */ + /* Button background — barely-there dark green surface */ + --color-green-200: 32 54 38; + + /* Icon, dot, text — readable sage on that dark surface */ + --color-green-500: 125 160 131; /* High Contrast */ --color-ink-1000: 255 255 255; /* white */ @@ -298,7 +302,7 @@ /*--color-green-500: 34 197 94; !* standard green *!*/ --color-green-400: 22 163 74; --color-green-300: 21 128 61; - --color-green-200: 22 101 52; + /*--color-green-200: 22 101 52;*/ --color-green-100: 20 83 45; --color-green-50: 5 46 22; /* darkest green */