From e0fa802b10493ed191d3fc4bb4209980d47c216c Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Tue, 31 Mar 2026 11:02:59 -0700 Subject: [PATCH 1/6] Fix fan club ui --- packages/common/src/hooks/content/types.ts | 2 +- .../src/hooks/content/useIsTrackUnlockable.ts | 4 +- .../content/useTrackLockedStatusVariant.ts | 4 ++ .../src/components/core/AccessTypeLabel.tsx | 12 +--- .../lineup-tile/LineupTileAccessStatus.tsx | 4 +- .../track-details-tile/TrackDetailsTile.tsx | 37 ++++------ packages/web/src/app/web-player/WebPlayer.tsx | 2 +- .../access-type-label/AccessTypeLabel.tsx | 14 +--- .../components/track/GatedConditionsPill.tsx | 4 +- .../track/TrackLockedStatusBadge.tsx | 16 +++++ .../UnsavedChangesDialog.tsx | 2 +- .../FanClubDetailContent.tsx | 4 +- .../components/FanClubInfoSection.tsx | 72 +++++++++++++++++-- 13 files changed, 116 insertions(+), 61 deletions(-) diff --git a/packages/common/src/hooks/content/types.ts b/packages/common/src/hooks/content/types.ts index b613e3fc232..d4e620f5690 100644 --- a/packages/common/src/hooks/content/types.ts +++ b/packages/common/src/hooks/content/types.ts @@ -1 +1 @@ -export type LockedStatusVariant = 'premium' | 'gated' +export type LockedStatusVariant = 'premium' | 'gated' | 'tokenGated' diff --git a/packages/common/src/hooks/content/useIsTrackUnlockable.ts b/packages/common/src/hooks/content/useIsTrackUnlockable.ts index dfc46ff2879..fffefa150b3 100644 --- a/packages/common/src/hooks/content/useIsTrackUnlockable.ts +++ b/packages/common/src/hooks/content/useIsTrackUnlockable.ts @@ -1,6 +1,7 @@ import { useTrack } from '~/api' import { isContentSpecialAccess, + isContentTokenGated, isContentUSDCPurchaseGated, ID } from '~/models' @@ -14,6 +15,7 @@ export const useIsTrackUnlockable = (trackId: ID) => { const isPurchaseable = isContentUSDCPurchaseGated(streamConditions) const isSpecialAccess = isContentSpecialAccess(streamConditions) + const isTokenGated = isContentTokenGated(streamConditions) - return isPurchaseable || isSpecialAccess + return isPurchaseable || isSpecialAccess || isTokenGated } diff --git a/packages/common/src/hooks/content/useTrackLockedStatusVariant.ts b/packages/common/src/hooks/content/useTrackLockedStatusVariant.ts index 8e87a6e499c..2260b190a53 100644 --- a/packages/common/src/hooks/content/useTrackLockedStatusVariant.ts +++ b/packages/common/src/hooks/content/useTrackLockedStatusVariant.ts @@ -2,6 +2,7 @@ import { useTrack } from '~/api' import { ID, isContentSpecialAccess, + isContentTokenGated, isContentUSDCPurchaseGated } from '~/models' import { Nullable } from '~/utils' @@ -15,12 +16,15 @@ export const useTrackLockedStatusVariant = (trackId: ID) => { const isPurchaseable = isContentUSDCPurchaseGated(streamConditions) const isSpecialAccess = isContentSpecialAccess(streamConditions) + const isTokenGated = isContentTokenGated(streamConditions) let variant: Nullable = null if (isPurchaseable) { variant = 'premium' } else if (isSpecialAccess) { variant = 'gated' + } else if (isTokenGated) { + variant = 'tokenGated' } return variant diff --git a/packages/mobile/src/components/core/AccessTypeLabel.tsx b/packages/mobile/src/components/core/AccessTypeLabel.tsx index 3fd4c3dcef1..9e107315841 100644 --- a/packages/mobile/src/components/core/AccessTypeLabel.tsx +++ b/packages/mobile/src/components/core/AccessTypeLabel.tsx @@ -13,8 +13,6 @@ import { IconArtistCoin } from '@audius/harmony-native' -import { CoinGatedLabelSvg } from './CoinGatedLabelSvg' - type AccessTypeLabelProps = { type?: AccessType scheduledReleaseDate?: string @@ -59,7 +57,7 @@ const ACCESS_TYPE_CONFIG: Record = { }, [AccessType.TOKEN_GATED]: { icon: IconArtistCoin, - label: 'Coin Gated', + label: 'Fan Club', color: 'artistCoin' }, [AccessType.EXTRAS]: { @@ -79,14 +77,6 @@ export const AccessTypeLabel = (props: AccessTypeLabelProps) => { ? config.label(scheduledReleaseDate) : config.label - if (type === AccessType.TOKEN_GATED) { - return ( - - - - ) - } - return ( {config.icon ? ( diff --git a/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx b/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx index 442f1626a49..d5c59582a19 100644 --- a/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx +++ b/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx @@ -47,7 +47,7 @@ const { setLockedContentId } = gatedContentActions const messages = { unlocking: 'Unlocking', locked: 'Locked', - buyArtistCoin: 'Buy Fan Club Token', + unlock: 'Unlock', price: (price: string) => `$${price}` } @@ -148,7 +148,7 @@ export const LineupTileAccessStatus = ({ USDC(streamConditions.usdc_purchase.price / 100).toLocaleString() ) : isTokenGated - ? messages.buyArtistCoin + ? messages.unlock : isUnlocking ? messages.unlocking : messages.locked diff --git a/packages/mobile/src/components/track-details-tile/TrackDetailsTile.tsx b/packages/mobile/src/components/track-details-tile/TrackDetailsTile.tsx index 5f1bfaf8e5c..f3569c9fe4c 100644 --- a/packages/mobile/src/components/track-details-tile/TrackDetailsTile.tsx +++ b/packages/mobile/src/components/track-details-tile/TrackDetailsTile.tsx @@ -26,14 +26,13 @@ import { makeStyles, flexRowCentered, typography } from 'app/styles' import { spacing } from 'app/styles/spacing' import { useThemeColors } from 'app/utils/theme' -import { CoinGatedLabelSvg } from '../core/CoinGatedLabelSvg' import { TrackImage } from '../image/TrackImage' import { TrackDogEar } from '../track/TrackDogEar' const messages = { specialAccess: 'SPECIAL ACCESS', premiumTrack: 'PREMIUM TRACK', - coinGated: 'COIN GATED', + coinGated: 'FAN CLUB', earn: (amount: string) => `Earn ${amount} $AUDIO for this purchase!` } @@ -142,26 +141,20 @@ export const TrackDetailsTile = ({ {showLabel ? ( - {isTokenGated ? ( - - ) : ( - <> - - - {title} - - - )} + + + {title} + ) : null} { useEffect(() => { const client = getClient() - if (client === Client.ELECTRON) { + if (client === Client.ELECTRON && typeof window.require === 'function') { // eslint-disable-next-line @typescript-eslint/no-var-requires ipcRef.current = window.require('electron').ipcRenderer diff --git a/packages/web/src/components/access-type-label/AccessTypeLabel.tsx b/packages/web/src/components/access-type-label/AccessTypeLabel.tsx index ee695d76bb0..6d9fb44fba8 100644 --- a/packages/web/src/components/access-type-label/AccessTypeLabel.tsx +++ b/packages/web/src/components/access-type-label/AccessTypeLabel.tsx @@ -9,8 +9,7 @@ import { IconColors, Flex, Text, - IconArtistCoin, - IconCoinGatedLabel + IconArtistCoin } from '@audius/harmony' type AccessTypeLabelProps = { @@ -57,7 +56,7 @@ const ACCESS_TYPE_CONFIG: Record = { }, [AccessType.TOKEN_GATED]: { icon: IconArtistCoin, - label: 'Coin Gated', + label: 'Fan Club', color: 'artistCoin' }, [AccessType.EXTRAS]: { @@ -77,15 +76,6 @@ export const AccessTypeLabel = (props: AccessTypeLabelProps) => { ? config.label(scheduledReleaseDate) : config.label - // Use coin gated label svg instead of icon and text for token gated - if (type === AccessType.TOKEN_GATED) { - return ( - - - - ) - } - return ( {config.icon ? ( diff --git a/packages/web/src/components/track/GatedConditionsPill.tsx b/packages/web/src/components/track/GatedConditionsPill.tsx index c6417488125..f201c9acafb 100644 --- a/packages/web/src/components/track/GatedConditionsPill.tsx +++ b/packages/web/src/components/track/GatedConditionsPill.tsx @@ -17,7 +17,7 @@ import { make, track } from 'services/analytics' const messages = { unlocking: 'Unlocking', locked: 'Locked', - buyArtistCoin: 'Buy Artist Coin' + unlock: 'Unlock' } export const GatedConditionsPill = ({ @@ -50,7 +50,7 @@ export const GatedConditionsPill = ({ message = isPurchase ? USDC(streamConditions.usdc_purchase.price / 100).toLocaleString() : isTokenGated - ? messages.buyArtistCoin + ? messages.unlock : messages.locked } diff --git a/packages/web/src/components/track/TrackLockedStatusBadge.tsx b/packages/web/src/components/track/TrackLockedStatusBadge.tsx index 800a0b594c6..f020ce47b71 100644 --- a/packages/web/src/components/track/TrackLockedStatusBadge.tsx +++ b/packages/web/src/components/track/TrackLockedStatusBadge.tsx @@ -3,9 +3,14 @@ import { useTrackLockedStatusVariant } from '@audius/common/hooks' import { ID } from '@audius/common/models' +import { Flex, IconLock, Text } from '@audius/harmony' import { LockedStatusBadge } from 'components/locked-status-badge' +const messages = { + membersOnly: 'Members Only' +} + type TrackLockedStatusBadgeProps = { trackId: ID } @@ -18,5 +23,16 @@ export const TrackLockedStatusBadge = (props: TrackLockedStatusBadgeProps) => { if (!variant) return null + if (variant === 'tokenGated' && !hasStreamAccess) { + return ( + + + + {messages.membersOnly} + + + ) + } + return } diff --git a/packages/web/src/components/unsaved-changes-dialog/UnsavedChangesDialog.tsx b/packages/web/src/components/unsaved-changes-dialog/UnsavedChangesDialog.tsx index d857679ce5a..359732d92c2 100644 --- a/packages/web/src/components/unsaved-changes-dialog/UnsavedChangesDialog.tsx +++ b/packages/web/src/components/unsaved-changes-dialog/UnsavedChangesDialog.tsx @@ -41,7 +41,7 @@ export const UnsavedChangesDialog = () => { const hotkeyHookRef = useRef<(e: KeyboardEvent) => void | undefined>(undefined) - const addElectronListener = isElectron() + const addElectronListener = isElectron() && typeof window.require === 'function' const ipcRef = useRef(null) useEffect(() => { diff --git a/packages/web/src/pages/fan-club-detail-page/FanClubDetailContent.tsx b/packages/web/src/pages/fan-club-detail-page/FanClubDetailContent.tsx index 0a66642dbe4..56bd268ae3f 100644 --- a/packages/web/src/pages/fan-club-detail-page/FanClubDetailContent.tsx +++ b/packages/web/src/pages/fan-club-detail-page/FanClubDetailContent.tsx @@ -29,7 +29,7 @@ const useStyles = makeResponsiveStyles(({ media, theme }) => { /** Primary column: fan club story + exclusive tracks (desktop left). */ mainColumn: { base: { - order: hasEnoughSpaceForTwoColumns ? 1 : 2, + order: 1, width: hasEnoughSpaceForTwoColumns ? MAIN_SECTION_WIDTH : '100%', maxWidth: hasEnoughSpaceForTwoColumns ? MAIN_SECTION_WIDTH : '100%', minWidth: 0, @@ -42,7 +42,7 @@ const useStyles = makeResponsiveStyles(({ media, theme }) => { /** Sidebar: balance, leaderboard, insights, on-chain details (desktop right). */ sidebarColumn: { base: { - order: hasEnoughSpaceForTwoColumns ? 2 : 1, + order: 2, width: hasEnoughSpaceForTwoColumns ? SIDEBAR_SECTION_WIDTH : '100%', maxWidth: hasEnoughSpaceForTwoColumns ? SIDEBAR_SECTION_WIDTH : '100%', minWidth: 0, diff --git a/packages/web/src/pages/fan-club-detail-page/components/FanClubInfoSection.tsx b/packages/web/src/pages/fan-club-detail-page/components/FanClubInfoSection.tsx index 94af566c50d..0c347593339 100644 --- a/packages/web/src/pages/fan-club-detail-page/components/FanClubInfoSection.tsx +++ b/packages/web/src/pages/fan-club-detail-page/components/FanClubInfoSection.tsx @@ -78,6 +78,9 @@ const toastMessages = coinDetailsMessages.toasts const BANNER_HEIGHT = 160 const DISCOVERY_COVER_HEIGHT = 96 +/** Matches FanClubDetailContent two-column breakpoint; hero stacks coin header before artist row. */ +const HERO_STACKED_ORDER_RESET = '@media (min-width: 1440px)' + const fanClubCardMessages = walletMessages.artistCoins // Minimum claimable fee amount (0.01 $AUDIO = 10^6 in smallest denomination with 8 decimals) @@ -197,7 +200,15 @@ const FanClubInfoHeroSkeleton = () => { alignSelf='stretch' css={{ marginTop: -theme.spacing.unit9 }} > - + @@ -212,6 +223,10 @@ const FanClubInfoHeroSkeleton = () => { gap='m' backgroundColor='surface1' w='100%' + css={{ + order: 1, + [HERO_STACKED_ORDER_RESET]: { order: 0 } + }} > @@ -221,7 +236,15 @@ const FanClubInfoHeroSkeleton = () => { - + @@ -991,9 +1014,21 @@ export const FanClubInfoSection = ({ pb='l' pt='l' alignSelf='stretch' - css={{ marginTop: -theme.spacing.unit9 }} + css={{ + marginTop: -theme.spacing.unit9 + // Below 1440px: coin header + description first, then artist + social (flex order on children). + }} > - + @@ -1008,7 +1043,16 @@ export const FanClubInfoSection = ({ - {hasSocialLinks ? : null} + {hasSocialLinks ? ( + + + + ) : null} @@ -1034,7 +1082,15 @@ export const FanClubInfoSection = ({ {hasDescriptionText ? ( - + {descriptionParagraphs.map((paragraph) => { if (paragraph.trim() === '') { return null @@ -1060,6 +1116,10 @@ export const FanClubInfoSection = ({ fullWidth iconLeft={IconCloudUpload} onClick={handleUploadExclusiveTrack} + css={{ + order: 5, + [HERO_STACKED_ORDER_RESET]: { order: 0 } + }} > {messages.uploadExclusiveTrack} From 6613bfb5a65a8f04b8df84f6170984442b41c7f4 Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Tue, 31 Mar 2026 14:48:24 -0700 Subject: [PATCH 2/6] Revert "Revert fmt versions" This reverts commit 29cdb024e31d3acbb44054d6acc65c6778d19fb8. --- package-lock.json | 2 +- packages/mobile/ios/Podfile | 50 +++++++++++++++++++ packages/mobile/ios/Podfile.lock | 6 +-- .../mobile/ios/podspecs/fmt-11.0.2.podspec | 31 ++++++++++++ .../mobile/ios/podspecs/fmt-12.1.0.podspec | 31 ++++++++++++ packages/mobile/package.json | 2 +- scripts/postinstall.sh | 25 ++++++++-- 7 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 packages/mobile/ios/podspecs/fmt-11.0.2.podspec create mode 100644 packages/mobile/ios/podspecs/fmt-12.1.0.podspec diff --git a/package-lock.json b/package-lock.json index b48c1f5e1d9..5f77ae7c3c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -146305,7 +146305,7 @@ }, "packages/mobile": { "name": "@audius/mobile", - "version": "1.5.174", + "version": "1.5.173", "dependencies": { "@amplitude/analytics-react-native": "1.4.11", "@audius/common": "*", diff --git a/packages/mobile/ios/Podfile b/packages/mobile/ios/Podfile index cff6c13dbf0..ee53fc184b2 100644 --- a/packages/mobile/ios/Podfile +++ b/packages/mobile/ios/Podfile @@ -1,3 +1,5 @@ +require 'fileutils' + def node_require(script) # Resolve script with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', @@ -30,6 +32,51 @@ project 'AudiusReactNative', 'Prod.Debug' => :debug, 'Prod.Release' => :release +# fmt must stay on 11.0.2 for older Xcode / committed Podfile.lock; Xcode 16+ needs fmt 12.1.0. +# React Native pins fmt in fmt.podspec and many *.podspec dependencies — align all before resolution. +# AUDIUS_FMT_LEGACY=1 → 11.0.2; AUDIUS_FMT_12=1 → 12.1.0 (ignores Xcode). Default: 12 iff Xcode >= 16. +FMT_VERSION_LEGACY = '11.0.2' +FMT_VERSION_NEW = '12.1.0' + +def audius_xcode_major_version + out = `xcodebuild -version 2>/dev/null` + (out =~ /Xcode (\d+)/) ? Regexp.last_match(1).to_i : 0 +end + +def audius_prepare_react_native_fmt!(react_native_root_abs) + dest = File.join(react_native_root_abs, 'third-party-podspecs', 'fmt.podspec') + unless File.file?(dest) + Pod::UI.warn "Audius: fmt.podspec missing at #{dest}, skipping fmt sync" + return + end + + force_legacy = ENV['AUDIUS_FMT_LEGACY'] == '1' + force_12 = ENV['AUDIUS_FMT_12'] == '1' + major = audius_xcode_major_version + use_fmt_12 = !force_legacy && (force_12 || major >= 16) + version = use_fmt_12 ? FMT_VERSION_NEW : FMT_VERSION_LEGACY + + src_name = use_fmt_12 ? 'fmt-12.1.0.podspec' : 'fmt-11.0.2.podspec' + src = File.join(__dir__, 'podspecs', src_name) + unless File.file?(src) + Pod::UI.warn "Audius: #{src} missing, skipping fmt sync" + return + end + + FileUtils.cp(src, dest) + + fmt_dep = /dependency "fmt", "[\d.]+"/ + Dir.glob(File.join(react_native_root_abs, '**/*.podspec')).each do |podspec_path| + contents = File.read(podspec_path) + next unless contents.match?(fmt_dep) + + updated = contents.gsub(fmt_dep, "dependency \"fmt\", \"#{version}\"") + File.write(podspec_path, updated) if updated != contents + end + + Pod::UI.puts "Audius: fmt #{version} (xcode major #{major}, AUDIUS_FMT_LEGACY=#{ENV['AUDIUS_FMT_LEGACY']}, AUDIUS_FMT_12=#{ENV['AUDIUS_FMT_12']})" +end + target 'AudiusReactNative' do pod 'SRSRadialGradient', :path => '../../../node_modules/react-native-radial-gradient/ios' pod 'ffmpeg-kit-ios-full-gpl', :podspec => './ffmpeg-kit-ios-full-gpl.podspec' @@ -39,6 +86,9 @@ target 'AudiusReactNative' do config = use_native_modules! + rn_root = File.expand_path(config[:reactNativePath], Pod::Config.instance.installation_root) + audius_prepare_react_native_fmt!(rn_root) + use_react_native!( :path => config[:reactNativePath], # An absolute path to your application root. diff --git a/packages/mobile/ios/Podfile.lock b/packages/mobile/ios/Podfile.lock index 2f788cd6add..23641c1cf41 100644 --- a/packages/mobile/ios/Podfile.lock +++ b/packages/mobile/ios/Podfile.lock @@ -1337,7 +1337,7 @@ PODS: - React - react-native-google-cast/NoBluetoothArm (= 4.6.2) - react-native-google-cast/NoBluetoothArm (4.6.2): - - google-cast-sdk-dynamic-xcframework-no-bluetooth (= 4.7.1) + - google-cast-sdk-dynamic-xcframework-no-bluetooth - React - react-native-google-cast/RNGoogleCast - react-native-google-cast/RNGoogleCast (4.6.2): @@ -2548,7 +2548,7 @@ SPEC CHECKSUMS: react-native-document-picker: 4f90a074d1eb269e32d5563c53b70d469180cece react-native-fast-crypto: b30594570dab23aca7e74e206b2c03e28a006216 react-native-get-random-values: 384787fd76976f5aec9465aff6fa9e9129af1e74 - react-native-google-cast: 0a82cf63114470403e41e04ffa2b13d6448b6112 + react-native-google-cast: 18b9b2fc518caabfa65d309409e160b3fc6d1733 react-native-image-picker: f104798044ef2c9211c42a48025d0693b5f34981 react-native-in-app-review: db8bb167a5f238e7ceca5c242d6b36ce8c4404a4 react-native-keyboard-controller: 7c1271a9fe703b7ee588b75d6c486eda79e5081b @@ -2621,6 +2621,6 @@ SPEC CHECKSUMS: TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 Yoga: eca8dd841b7cd47d82d66be58af8e3aeb819012f -PODFILE CHECKSUM: b77c7dc423273b965d32a03d73fe6277c67877b7 +PODFILE CHECKSUM: c2e67d2a2a2154693b58e3aff84723ed0f577413 COCOAPODS: 1.15.2 diff --git a/packages/mobile/ios/podspecs/fmt-11.0.2.podspec b/packages/mobile/ios/podspecs/fmt-11.0.2.podspec new file mode 100644 index 00000000000..bc0847728a1 --- /dev/null +++ b/packages/mobile/ios/podspecs/fmt-11.0.2.podspec @@ -0,0 +1,31 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# +# Vendored from react-native@0.78.3 — used when Xcode < 16 (e.g. CI) so Podfile.lock stays on fmt 11.0.2. + +fmt_config = get_fmt_config() +fmt_git_url = fmt_config[:git] + +Pod::Spec.new do |spec| + spec.name = "fmt" + spec.version = "11.0.2" + spec.license = { :type => "MIT" } + spec.homepage = "https://github.com/fmtlib/fmt" + spec.summary = "{fmt} is an open-source formatting library for C++. It can be used as a safe and fast alternative to (s)printf and iostreams." + spec.authors = "The fmt contributors" + spec.source = { + :git => fmt_git_url, + :tag => "11.0.2" + } + spec.pod_target_xcconfig = { + "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(), + "GCC_WARN_INHIBIT_ALL_WARNINGS" => "YES" # Disable warnings because we don't control this library + } + spec.platforms = min_supported_versions + spec.libraries = "c++" + spec.public_header_files = "include/fmt/*.h" + spec.header_mappings_dir = "include" + spec.source_files = ["include/fmt/*.h", "src/format.cc"] +end diff --git a/packages/mobile/ios/podspecs/fmt-12.1.0.podspec b/packages/mobile/ios/podspecs/fmt-12.1.0.podspec new file mode 100644 index 00000000000..629b511a6b6 --- /dev/null +++ b/packages/mobile/ios/podspecs/fmt-12.1.0.podspec @@ -0,0 +1,31 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# +# fmt 12.x — required for recent Xcode / LLVM; synced into react-native when Xcode >= 16. + +fmt_config = get_fmt_config() +fmt_git_url = fmt_config[:git] + +Pod::Spec.new do |spec| + spec.name = "fmt" + spec.version = "12.1.0" + spec.license = { :type => "MIT" } + spec.homepage = "https://github.com/fmtlib/fmt" + spec.summary = "{fmt} is an open-source formatting library for C++. It can be used as a safe and fast alternative to (s)printf and iostreams." + spec.authors = "The fmt contributors" + spec.source = { + :git => fmt_git_url, + :tag => "12.1.0" + } + spec.pod_target_xcconfig = { + "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(), + "GCC_WARN_INHIBIT_ALL_WARNINGS" => "YES" # Disable warnings because we don't control this library + } + spec.platforms = min_supported_versions + spec.libraries = "c++" + spec.public_header_files = "include/fmt/*.h" + spec.header_mappings_dir = "include" + spec.source_files = ["include/fmt/*.h", "src/format.cc"] +end diff --git a/packages/mobile/package.json b/packages/mobile/package.json index 6c3f2369827..cddceaeeaab 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@audius/mobile", - "version": "1.5.174", + "version": "1.5.173", "private": true, "scripts": { "android:dev": "ENVFILE=.env.dev turbo run android -- --mode=prodDebug", diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh index f40de93e8dd..c8e9e3a8bfb 100755 --- a/scripts/postinstall.sh +++ b/scripts/postinstall.sh @@ -35,17 +35,36 @@ fi if [[ -z "${SKIP_POD_INSTALL}" ]]; then printf "${GREEN}Installing cocoapods...\n${NC}" - { + ( cd ./packages/mobile/ios if command -v bundle >/dev/null; then bundle check || bundle install fi if command -v pod >/dev/null; then - RCT_NEW_ARCH_ENABLED=0 bundle exec pod install + # Podfile.lock stays on fmt 11 for older Xcode; CI may use Xcode 16+ which would otherwise + # select fmt 12 in the Podfile and disagree with the lock. Default AUDIUS_FMT_LEGACY on CI + # unless the workflow already set it (e.g. when you intentionally move the lock to fmt 12). + if [[ -n "${CI}" ]] && [[ -z "${AUDIUS_FMT_LEGACY+x}" ]]; then + export AUDIUS_FMT_LEGACY=1 + fi + # Avoid stale fmt (and other local podspec) JSON conflicting with the current podspec on disk. + rm -rf Pods/Local\ Podspecs 2>/dev/null || true + export RCT_NEW_ARCH_ENABLED=0 + if [[ -n "${CI}" ]]; then + bundle exec pod install + else + # Xcode 16+ uses fmt 12 in the Podfile while Podfile.lock may still pin fmt 11 — first install + # can fail until the lock catches up. Refresh fmt, then install (may dirty Podfile.lock locally). + if ! bundle exec pod install; then + printf "${YELLOW}pod install failed; running pod update fmt then retrying...${NC}\n" >&2 + bundle exec pod update fmt --no-repo-update + bundle exec pod install + fi + fi fi cd ../../.. - } > /dev/null + ) > /dev/null fi if [[ -z "${SKIP_ANDROID_INSTALL}" ]]; then From 3d400c07b04642e35fdb495b2d61398c7bd89293 Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Tue, 31 Mar 2026 15:51:46 -0700 Subject: [PATCH 3/6] Artist coin UI fixes --- .../src/components/button/Button/Button.tsx | 3 +- .../src/components/button/Button/types.ts | 5 + packages/mobile/ios/Podfile.lock | 128 +++++++++--------- .../src/components/core/AccessTypeLabel.tsx | 2 +- .../lineup-tile/LineupTileAccessStatus.tsx | 19 ++- .../NavigationContainer.tsx | 3 - .../track/TrackLockedStatusBadge.tsx | 24 ++++ .../components/Button/Button/Button.tsx | 3 +- .../components/Button/Button/types.ts | 5 + .../src/screens/app-screen/AppTabScreen.tsx | 8 +- .../ExclusiveTracksScreen.tsx | 79 ----------- .../components/ExclusiveTracksCard.tsx | 106 --------------- .../components/ExclusiveTracksSection.tsx | 99 -------------- .../components/FanClubTab.tsx | 6 +- .../src/screens/coin-details-screen/index.ts | 1 - packages/web/src/app/web-player/WebPlayer.tsx | 41 ++---- .../access-type-label/AccessTypeLabel.tsx | 2 +- .../components/track/GatedConditionsPill.tsx | 18 ++- .../track/TrackLockedStatusBadge.tsx | 2 +- .../UnsavedChangesDialog.tsx | 3 +- .../FanClubDetailContent.tsx | 6 +- .../components/ExclusiveTracksPage.tsx | 76 ----------- ...acksSection.tsx => FanClubFeedSection.tsx} | 12 +- .../mobile/ExclusiveTracksPage.module.css | 15 -- .../components/mobile/ExclusiveTracksPage.tsx | 79 ----------- 25 files changed, 166 insertions(+), 579 deletions(-) delete mode 100644 packages/mobile/src/screens/coin-details-screen/ExclusiveTracksScreen.tsx delete mode 100644 packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksCard.tsx delete mode 100644 packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksSection.tsx delete mode 100644 packages/web/src/pages/fan-club-detail-page/components/ExclusiveTracksPage.tsx rename packages/web/src/pages/fan-club-detail-page/components/{ExclusiveTracksSection.tsx => FanClubFeedSection.tsx} (88%) delete mode 100644 packages/web/src/pages/fan-club-detail-page/components/mobile/ExclusiveTracksPage.module.css delete mode 100644 packages/web/src/pages/fan-club-detail-page/components/mobile/ExclusiveTracksPage.tsx diff --git a/packages/harmony/src/components/button/Button/Button.tsx b/packages/harmony/src/components/button/Button/Button.tsx index 7b7d4008850..4747730d764 100644 --- a/packages/harmony/src/components/button/Button/Button.tsx +++ b/packages/harmony/src/components/button/Button/Button.tsx @@ -25,6 +25,7 @@ export const Button = forwardRef( hoverColor, variant = 'primary', size = 'default', + rounded, disabled, ...baseProps } = props @@ -176,7 +177,7 @@ export const Button = forwardRef( color: themeColors.static.white, boxSizing: 'border-box', border: 'none', - borderRadius: cornerRadius.s, + borderRadius: rounded ? cornerRadius['2xl'] : cornerRadius.s, boxShadow: shadows.near, ...(isSmallOrXs diff --git a/packages/harmony/src/components/button/Button/types.ts b/packages/harmony/src/components/button/Button/types.ts index de765fda401..4e52a3f1b2b 100644 --- a/packages/harmony/src/components/button/Button/types.ts +++ b/packages/harmony/src/components/button/Button/types.ts @@ -34,4 +34,9 @@ export type ButtonProps = { * The button size */ size?: ButtonSize + + /** + * When true, uses fully rounded (pill-shaped) corners + */ + rounded?: boolean } & Omit diff --git a/packages/mobile/ios/Podfile.lock b/packages/mobile/ios/Podfile.lock index 23641c1cf41..378ca61fb2c 100644 --- a/packages/mobile/ios/Podfile.lock +++ b/packages/mobile/ios/Podfile.lock @@ -18,7 +18,7 @@ PODS: - ffmpeg-kit-ios-full-gpl (= 6.0) - React-Core - FingerprintPro (2.11.0) - - fmt (11.0.2) + - fmt (12.1.0) - glog (0.3.5) - google-cast-sdk-dynamic-xcframework-no-bluetooth (4.7.1) - hermes-engine (0.78.3): @@ -55,20 +55,20 @@ PODS: - boost - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - RCT-Folly/Default (= 2024.11.18.00) - RCT-Folly/Default (2024.11.18.00): - boost - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - RCT-Folly/Fabric (2024.11.18.00): - boost - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - RCTDeprecation (0.78.3) - RCTRequired (0.78.3) @@ -331,7 +331,7 @@ PODS: - React-CoreModules (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - RCT-Folly (= 2024.11.18.00) - RCTTypeSafety (= 0.78.3) - React-Core/CoreModulesHeaders (= 0.78.3) @@ -347,7 +347,7 @@ PODS: - boost - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -384,7 +384,7 @@ PODS: - React-Fabric (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -421,7 +421,7 @@ PODS: - React-Fabric/animations (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -442,7 +442,7 @@ PODS: - React-Fabric/attributedstring (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -463,7 +463,7 @@ PODS: - React-Fabric/componentregistry (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -484,7 +484,7 @@ PODS: - React-Fabric/componentregistrynative (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -505,7 +505,7 @@ PODS: - React-Fabric/components (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -529,7 +529,7 @@ PODS: - React-Fabric/components/legacyviewmanagerinterop (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -550,7 +550,7 @@ PODS: - React-Fabric/components/root (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -571,7 +571,7 @@ PODS: - React-Fabric/components/view (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -593,7 +593,7 @@ PODS: - React-Fabric/consistency (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -614,7 +614,7 @@ PODS: - React-Fabric/core (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -635,7 +635,7 @@ PODS: - React-Fabric/dom (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -656,7 +656,7 @@ PODS: - React-Fabric/imagemanager (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -677,7 +677,7 @@ PODS: - React-Fabric/leakchecker (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -698,7 +698,7 @@ PODS: - React-Fabric/mounting (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -719,7 +719,7 @@ PODS: - React-Fabric/observers (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -741,7 +741,7 @@ PODS: - React-Fabric/observers/events (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -762,7 +762,7 @@ PODS: - React-Fabric/scheduler (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -785,7 +785,7 @@ PODS: - React-Fabric/telemetry (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -806,7 +806,7 @@ PODS: - React-Fabric/templateprocessor (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -827,7 +827,7 @@ PODS: - React-Fabric/uimanager (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -850,7 +850,7 @@ PODS: - React-Fabric/uimanager/consistency (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -872,7 +872,7 @@ PODS: - React-FabricComponents (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -897,7 +897,7 @@ PODS: - React-FabricComponents/components (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -929,7 +929,7 @@ PODS: - React-FabricComponents/components/inputaccessory (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -952,7 +952,7 @@ PODS: - React-FabricComponents/components/iostextinput (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -975,7 +975,7 @@ PODS: - React-FabricComponents/components/modal (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -998,7 +998,7 @@ PODS: - React-FabricComponents/components/rncore (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1021,7 +1021,7 @@ PODS: - React-FabricComponents/components/safeareaview (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1044,7 +1044,7 @@ PODS: - React-FabricComponents/components/scrollview (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1067,7 +1067,7 @@ PODS: - React-FabricComponents/components/text (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1090,7 +1090,7 @@ PODS: - React-FabricComponents/components/textinput (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1113,7 +1113,7 @@ PODS: - React-FabricComponents/components/unimplementedview (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1136,7 +1136,7 @@ PODS: - React-FabricComponents/textlayoutmanager (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1159,7 +1159,7 @@ PODS: - React-FabricImage (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1189,7 +1189,7 @@ PODS: - React-graphics (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly/Fabric (= 2024.11.18.00) @@ -1199,7 +1199,7 @@ PODS: - React-hermes (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -1240,14 +1240,14 @@ PODS: - boost - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) - React-jsiexecutor (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -1567,7 +1567,7 @@ PODS: - React-RCTBlob (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - hermes-engine - RCT-Folly (= 2024.11.18.00) - React-Core/RCTBlobHeaders @@ -1657,7 +1657,7 @@ PODS: - React-rendererdebug (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - RCT-Folly (= 2024.11.18.00) - React-debug - React-rncore (0.78.3) @@ -1759,7 +1759,7 @@ PODS: - ReactCommon/turbomodule (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -1773,7 +1773,7 @@ PODS: - ReactCommon/turbomodule/bridging (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -1785,7 +1785,7 @@ PODS: - ReactCommon/turbomodule/core (0.78.3): - DoubleConversion - fast_float (= 6.1.4) - - fmt (= 11.0.2) + - fmt (= 12.1.0) - glog - hermes-engine - RCT-Folly (= 2024.11.18.00) @@ -2503,7 +2503,7 @@ SPEC CHECKSUMS: ffmpeg-kit-ios-full-gpl: 7d416729f7b3604b64cee2a752c42608a8d228e0 ffmpeg-kit-react-native: 3cea88c9c5cfad62e1465279ea7d800dfbba3b00 FingerprintPro: 2fbd0cda75fbab32055f7cb38bc5fc9d17168979 - fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd + fmt: 530618a01105dae0fa3a2f27c81ae11fa8f67eac glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 google-cast-sdk-dynamic-xcframework-no-bluetooth: 1fa9e267df3fd6f8a1c6e3345142ca5286297968 hermes-engine: b5c9cfbe6415f1b0b24759f2942c8f33e9af6347 @@ -2512,30 +2512,30 @@ SPEC CHECKSUMS: lottie-react-native: 04061d06c966a4179c9c1352aac63b699642c77e nSure: 2fc3fc973c44aa0be9a3446f84cb514adc475205 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 + RCT-Folly: d533c1d21249a85e67a4be97f4d793665de0222e RCTDeprecation: cf39863b43871c2031050605fb884019b6193910 RCTRequired: 8fdd66f4a97f352b66f38cfef13fc11b12d2c884 RCTTypeSafety: c9c9e64389bc545fc137030615b387ef1654dcee React: 14a80ea4f13387cfdaa4250b46fbfe19754c220c React-callinvoker: fed1dad5d6cf992c7b4b5fdbf1bf67fe2e8fb6c5 React-Core: f703e7a56fcedc3e959b8b7899995e57fd58539a - React-CoreModules: 6e87c904cc257058c271708eef1719b5b3039131 - React-cxxreact: 4153beeff710944832cd90ccb141e299ee16b7d3 + React-CoreModules: 945ed8a2827720af6852b97c8ddd2ac2ceb04157 + React-cxxreact: 26c744a099a29f2f995f9bb4b755d8ecbf7c5392 React-debug: aea2894f3f71697ec8724c11db9c46c1574b21e4 React-defaultsnativemodule: de00ba37b23205eca31cee5a6a8756a48f0a38f9 React-domnativemodule: b8dd2af2fcd232da5ea679e439a95a827a852a21 - React-Fabric: a63a42788096362a4840d827dab426c17a15a644 - React-FabricComponents: 8dd7bea45626350fe7bd052ea7c9fd657a1977cc - React-FabricImage: de4c10c3319b916ca4d0b6a6fd53c3ecb4da0f83 + React-Fabric: 31765f67f16bec0e85e89be0a544da0d91b8fdc2 + React-FabricComponents: ad41201e8e20a4f57d9f62ded0506ebc67e89cff + React-FabricImage: 77b5157315924901911fdaa586df5b5fbf754366 React-featureflags: c6de2182d6065b3239245820347947e2c1309feb React-featureflagsnativemodule: 47c7a5814a027eb262c2709852d1b1a597599cca - React-graphics: bf16f4f74e3bc342b58b71797674a4eafda467a9 - React-hermes: a942bebef5e9fcc31f51c6fb814e96c260a2a20d + React-graphics: f9371eec432c7cf095238eaca8d2d3deaa95989f + React-hermes: 1ee5a6b835bc939b7aba500cb716a1095b3e0959 React-idlecallbacksnativemodule: d53c466886963cc325172bc9100b21e8511bce97 React-ImageManager: 4e2d837df0bf6b4cc42238122dc4577545befed5 React-jserrorhandler: 41f26e9e5559bda0549f27410d685a8f21bdbb94 - React-jsi: b2de88284fc2cc69466a34d8b794160216d3bd2c - React-jsiexecutor: e947af1c9e42610affd9f4178cd4b649e8ac889b + React-jsi: 0810ff01e7f73a1cfba83d176e21c29302f6f3aa + React-jsiexecutor: 70f6865d195eba534f39ac9504a9aa178e5389f7 React-jsinspector: 7efabcd0a393fed8e3bd4b9c8c461c1b4d5d2b90 React-jsinspectortracing: 8cddf7d93b8aa43a14b5d92e8a83de083a1158e6 React-jsitracing: 1d636f7da6f2d4f9c2d3d7e9d50f469eb2356ddb @@ -2570,7 +2570,7 @@ SPEC CHECKSUMS: React-RCTActionSheet: a078d5008632fed31b0024c420ee02e612b317d5 React-RCTAnimation: 82e31d191af4175e0c2df5bdac2c8569a5f3ab54 React-RCTAppDelegate: 183c991d0be0b05a4e1587bb2740cf954782a56b - React-RCTBlob: c462b8b7de6ce44ddc56dd96eebe1da0a6e54c77 + React-RCTBlob: 605c283c68fee9e095206fefbfe69d0d23df1a00 React-RCTFabric: 8f6eead6e48b1126ec325964040d175c9163e35f React-RCTFBReactNativeSpec: bc4feee6ad7e6cce73d38000473fe8702a38e76a React-RCTImage: 10fad63f1bb8adbd519c4c2ef6bec3c0d95fdd32 @@ -2580,7 +2580,7 @@ SPEC CHECKSUMS: React-RCTText: d97cfb9c89b06de9530577dd43f178c47ea07853 React-RCTVibration: 2fcefee071a4f0d416e4368416bb073ea6893451 React-rendererconsistency: 259dede0b0b9b46bcc2fcdc94465a5fa01a66ef9 - React-rendererdebug: 3f7600015d8ce3a4c97149f3660fe30dba17c0fd + React-rendererdebug: 61d39f5756b6fad82d52c25e87ef71e35e4d4254 React-rncore: 93b049aef62762732c06413616b0f033d47b9a95 React-RuntimeApple: 85a29d8805ace62a2db360cc46e3100435b0dd2b React-RuntimeCore: a81ea64fb5578c0367736c91fb85d6844950b7c2 @@ -2591,7 +2591,7 @@ SPEC CHECKSUMS: React-utils: 21356bf3cdd7a337587165fea57563a077993864 ReactAppDependencyProvider: ad88c80e06f29900f2e6f9ccf1d4cb0bfc3e1bbc ReactCodegen: 8e673528b686d334cfa785515d9c9b14bcb272d8 - ReactCommon: 7ea8ee50e489e9cc75922f19a06ea45c1b59b4bd + ReactCommon: 2a8b95bef15a281871b6bae12de1624f80e3a209 RNBootSplash: c2ae3f80f6c90979ee57977672f57e74981f85a5 RNCAsyncStorage: 23e56519cc41d3bade3c8d4479f7760cb1c11996 RNCClipboard: dfeb43751adff21e588657b5b6c888c72f3aa68e diff --git a/packages/mobile/src/components/core/AccessTypeLabel.tsx b/packages/mobile/src/components/core/AccessTypeLabel.tsx index 9e107315841..ee05de41b4a 100644 --- a/packages/mobile/src/components/core/AccessTypeLabel.tsx +++ b/packages/mobile/src/components/core/AccessTypeLabel.tsx @@ -58,7 +58,7 @@ const ACCESS_TYPE_CONFIG: Record = { [AccessType.TOKEN_GATED]: { icon: IconArtistCoin, label: 'Fan Club', - color: 'artistCoin' + color: 'subdued' }, [AccessType.EXTRAS]: { icon: IconReceive, diff --git a/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx b/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx index d5c59582a19..f46ddf560b8 100644 --- a/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx +++ b/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx @@ -24,6 +24,7 @@ import { useDispatch, useSelector } from 'react-redux' import type { FlexProps } from '@audius/harmony-native' import { + Button, Flex, IconLock, IconLockUnlocked, @@ -180,6 +181,20 @@ export const LineupTileAccessStatus = ({ style: { backgroundColor } } + if (isTokenGated && !hasStreamAccess && !isUnlocking) { + return ( + + ) + } + return ( - ) : !isTokenGated ? ( + ) : ( - ) : null} + )} {showButtonText ? ( {buttonText} diff --git a/packages/mobile/src/components/navigation-container/NavigationContainer.tsx b/packages/mobile/src/components/navigation-container/NavigationContainer.tsx index d3b2101be6b..87497d194a0 100644 --- a/packages/mobile/src/components/navigation-container/NavigationContainer.tsx +++ b/packages/mobile/src/components/navigation-container/NavigationContainer.tsx @@ -186,9 +186,6 @@ const NavigationContainer = (props: NavigationContainerProps) => { }, CoinRedeemScreen: { path: 'coins/:ticker/redeem/:code?' - }, - ExclusiveTracksScreen: { - path: 'coins/:ticker/exclusive-tracks' } } }, diff --git a/packages/mobile/src/components/track/TrackLockedStatusBadge.tsx b/packages/mobile/src/components/track/TrackLockedStatusBadge.tsx index 2dc3bcc1231..99b81b7ea8c 100644 --- a/packages/mobile/src/components/track/TrackLockedStatusBadge.tsx +++ b/packages/mobile/src/components/track/TrackLockedStatusBadge.tsx @@ -4,8 +4,14 @@ import { } from '@audius/common/hooks' import type { ID } from '@audius/common/models' +import { Flex, IconLock, Text } from '@audius/harmony-native' + import { LockedStatusBadge } from '../core/LockedStatusBadge' +const messages = { + membersOnly: 'Members Only' +} + type TrackLockedStatusBadgeProps = { trackId: ID } @@ -16,5 +22,23 @@ export const TrackLockedStatusBadge = (props: TrackLockedStatusBadgeProps) => { const variant = useTrackLockedStatusVariant(trackId) if (!variant) return null + if (variant === 'tokenGated' && !hasStreamAccess) { + return ( + + + + + {messages.membersOnly} + + + + ) + } + return } diff --git a/packages/mobile/src/harmony-native/components/Button/Button/Button.tsx b/packages/mobile/src/harmony-native/components/Button/Button/Button.tsx index a0ee5e325f7..1bffe49c706 100644 --- a/packages/mobile/src/harmony-native/components/Button/Button/Button.tsx +++ b/packages/mobile/src/harmony-native/components/Button/Button/Button.tsx @@ -23,6 +23,7 @@ export const Button = (props: ButtonProps) => { hexColor, variant = 'primary', size = 'default', + rounded, disabled, style, gradient, @@ -199,7 +200,7 @@ export const Button = (props: ButtonProps) => { const buttonStyles: ViewStyle = { borderWidth: 0, - borderRadius: cornerRadius.s, + borderRadius: rounded ? cornerRadius['2xl'] : cornerRadius.s, alignItems: 'center', justifyContent: 'center', // TODO bring this back properly diff --git a/packages/mobile/src/harmony-native/components/Button/Button/types.ts b/packages/mobile/src/harmony-native/components/Button/Button/types.ts index dac6bc93261..04f97977333 100644 --- a/packages/mobile/src/harmony-native/components/Button/Button/types.ts +++ b/packages/mobile/src/harmony-native/components/Button/Button/types.ts @@ -30,5 +30,10 @@ export type ButtonProps = { */ size?: ButtonSize + /** + * When true, uses fully rounded (pill-shaped) corners + */ + rounded?: boolean + style?: StyleProp } & Omit diff --git a/packages/mobile/src/screens/app-screen/AppTabScreen.tsx b/packages/mobile/src/screens/app-screen/AppTabScreen.tsx index f7bf9825504..870c7c3e88a 100644 --- a/packages/mobile/src/screens/app-screen/AppTabScreen.tsx +++ b/packages/mobile/src/screens/app-screen/AppTabScreen.tsx @@ -32,8 +32,7 @@ import { ChatScreen } from 'app/screens/chat-screen/ChatScreen' import { ChatUserListScreen } from 'app/screens/chat-screen/ChatUserListScreen' import { CoinDetailsScreen, - EditCoinDetailsScreen, - ExclusiveTracksScreen + EditCoinDetailsScreen } from 'app/screens/coin-details-screen' import { CoinRedeemScreen } from 'app/screens/coin-redeem-screen' import { CollectionScreen } from 'app/screens/collection-screen/CollectionScreen' @@ -123,7 +122,6 @@ export type AppTabScreenParamList = { CoinDetailsScreen: { ticker: string } CoinRedeemScreen: { ticker: string; code?: string } EditCoinDetailsScreen: { ticker: string } - ExclusiveTracksScreen: { ticker: string } Upload: { initialMetadata?: Partial } @@ -246,10 +244,6 @@ export const AppTabScreen = ({ baseScreen, Stack }: AppTabScreenProps) => { name='EditCoinDetailsScreen' component={EditCoinDetailsScreen} /> - { - return ( - - - {messages.emptyTitle} - - - {messages.emptyDescription} - - - ) -} - -export const ExclusiveTracksScreen = () => { - const { ticker } = useRoute().params as { ticker: string } - const { data: coin } = useArtistCoinByTicker({ ticker }) - const ownerId = coin?.ownerId - const coinName = coin?.name ?? ticker - - const title = coinName ? `${coinName} Exclusive Tracks` : 'Exclusive Tracks' - - const lineup = useProxySelector((state) => getLineup(state), []) - - const fetchPayload = useMemo(() => ({ userId: ownerId }), [ownerId]) - - if (!ownerId) { - return ( - - - - - - ) - } - - return ( - - - } - showsVerticalScrollIndicator={false} - /> - - - ) -} diff --git a/packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksCard.tsx b/packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksCard.tsx deleted file mode 100644 index 5ba71772f39..00000000000 --- a/packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksCard.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { useCallback } from 'react' - -import { - useArtistCoin, - useExclusiveTracks, - useExclusiveTracksCount -} from '@audius/common/api' -import { exclusiveTracksPageLineupActions as exclusiveTracksActions } from '@audius/common/store' - -import { Button, Flex, Text } from '@audius/harmony-native' -import { TanQueryLineup } from 'app/components/lineup/TanQueryLineup' -import { useNavigation } from 'app/hooks/useNavigation' - -const messages = { - exclusiveTracks: 'Exclusive Tracks', - viewAll: 'View All' -} - -const MAX_PREVIEW_TRACKS = 3 - -const itemStyles = { - paddingHorizontal: 0 -} - -type ExclusiveTracksSectionProps = { - mint: string -} - -export const ExclusiveTracksSection = ({ - mint -}: ExclusiveTracksSectionProps) => { - const navigation = useNavigation() - const { data: coin } = useArtistCoin(mint) - const ownerId = coin?.ownerId - const coinName = coin?.name ?? coin?.ticker - - const { data, lineup, pageSize, isFetching, loadNextPage, isPending } = - useExclusiveTracks({ - userId: ownerId, - pageSize: MAX_PREVIEW_TRACKS - }) - - const { data: totalCount = 0 } = useExclusiveTracksCount({ - userId: ownerId - }) - - const handleViewAll = useCallback(() => { - if (coin?.ticker) { - navigation.navigate('ExclusiveTracksScreen', { ticker: coin.ticker }) - } - }, [coin?.ticker, navigation]) - - const shouldShowCard = totalCount > 0 && ownerId - - if (!shouldShowCard) return null - - const title = coinName - ? `${coinName} ${messages.exclusiveTracks}` - : messages.exclusiveTracks - - return ( - - - - - {title} - - {totalCount > 0 ? ( - - ({totalCount}) - - ) : null} - - - - - - ) -} diff --git a/packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksSection.tsx b/packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksSection.tsx deleted file mode 100644 index 0f57de69492..00000000000 --- a/packages/mobile/src/screens/coin-details-screen/components/ExclusiveTracksSection.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { useCallback } from 'react' - -import { - useArtistCoin, - useExclusiveTracks, - useExclusiveTracksCount -} from '@audius/common/api' -import { exclusiveTracksPageLineupActions as exclusiveTracksActions } from '@audius/common/store' - -import { Flex, PlainButton, Text } from '@audius/harmony-native' -import { TanQueryLineup } from 'app/components/lineup/TanQueryLineup' -import { useNavigation } from 'app/hooks/useNavigation' - -const messages = { - exclusiveTracks: 'Exclusive Tracks', - viewAll: 'View All' -} - -const MAX_PREVIEW_TRACKS = 3 - -const itemStyles = { - paddingHorizontal: 0 -} - -type ExclusiveTracksSectionProps = { - mint: string -} - -export const ExclusiveTracksSection = ({ - mint -}: ExclusiveTracksSectionProps) => { - const navigation = useNavigation() - const { data: coin } = useArtistCoin(mint) - const ownerId = coin?.ownerId - const coinName = coin?.name ?? coin?.ticker - - const { data, lineup, pageSize, isFetching, loadNextPage, isPending } = - useExclusiveTracks({ - userId: ownerId, - pageSize: MAX_PREVIEW_TRACKS - }) - - const { data: totalCount = 0 } = useExclusiveTracksCount({ - userId: ownerId - }) - - const handleViewAll = useCallback(() => { - if (coin?.ticker) { - navigation.navigate('ExclusiveTracksScreen', { ticker: coin.ticker }) - } - }, [coin?.ticker, navigation]) - - const shouldShowCard = totalCount > 0 && ownerId - - if (!shouldShowCard) return null - - const title = coinName - ? `${coinName} ${messages.exclusiveTracks}` - : messages.exclusiveTracks - - return ( - - - - - {title}{' '} - {totalCount > 0 ? ( - ({totalCount}) - ) : null} - - - - {messages.viewAll} - - - - - ) -} diff --git a/packages/mobile/src/screens/coin-details-screen/components/FanClubTab.tsx b/packages/mobile/src/screens/coin-details-screen/components/FanClubTab.tsx index f8104fff461..ff9201adf85 100644 --- a/packages/mobile/src/screens/coin-details-screen/components/FanClubTab.tsx +++ b/packages/mobile/src/screens/coin-details-screen/components/FanClubTab.tsx @@ -44,7 +44,7 @@ const messages = { uploadExclusiveTrack: coinDetailsMessages.coinInfo.uploadExclusiveTrack, becomeAMember: coinDetailsMessages.balance.becomeAMember, hintDescription: coinDetailsMessages.balance.hintDescription, - fanClubFeed: 'Fan Club Feed' + title: 'Fan Club Feed' } const MAX_PREVIEW_TRACKS = 3 @@ -260,7 +260,7 @@ const FanClubFeed = ({ - {messages.fanClubFeed} + {messages.title} @@ -280,7 +280,7 @@ const FanClubFeed = ({ - {messages.fanClubFeed} + {messages.title} {totalCount > 0 ? ( diff --git a/packages/mobile/src/screens/coin-details-screen/index.ts b/packages/mobile/src/screens/coin-details-screen/index.ts index 58fd1c13202..1b88375a13a 100644 --- a/packages/mobile/src/screens/coin-details-screen/index.ts +++ b/packages/mobile/src/screens/coin-details-screen/index.ts @@ -1,3 +1,2 @@ export { CoinDetailsScreen } from './CoinDetailsScreen' export { EditCoinDetailsScreen } from './EditCoinDetailsScreen' -export { ExclusiveTracksScreen } from './ExclusiveTracksScreen' diff --git a/packages/web/src/app/web-player/WebPlayer.tsx b/packages/web/src/app/web-player/WebPlayer.tsx index 328b9527f25..42c8c7b7c04 100644 --- a/packages/web/src/app/web-player/WebPlayer.tsx +++ b/packages/web/src/app/web-player/WebPlayer.tsx @@ -104,23 +104,11 @@ const FanClubDetailPage = lazy(() => default: m.FanClubDetailPage })) ) -const ExclusiveTracksPage = lazy(() => - import('pages/fan-club-detail-page/components/ExclusiveTracksPage').then( - (m) => ({ - default: m.ExclusiveTracksPage - }) - ) -) const ArtistFanClubDetailsPage = lazy(() => import( 'pages/fan-club-detail-page/components/mobile/ArtistFanClubDetailsPage' ).then((m) => ({ default: m.ArtistFanClubDetailsPage })) ) -const MobileExclusiveTracksPage = lazy(() => - import( - 'pages/fan-club-detail-page/components/mobile/ExclusiveTracksPage' - ).then((m) => ({ default: m.ExclusiveTracksPage })) -) const CoinRedeemPage = lazy(() => import('pages/coin-redeem-page/CoinRedeemPage').then((m) => ({ default: m.CoinRedeemPage @@ -408,10 +396,10 @@ const FanClubDetailPageRoute = ({ return } -const CoinExclusiveTracksMobileRoute = () => { +const CoinExclusiveTracksLegacyRedirect = () => { const params = useParams<{ ticker?: string }>() - const { ticker } = params - return + const ticker = (params.ticker ?? '').toUpperCase() + return } type HomePageRedirectProps = { @@ -950,20 +938,13 @@ const WebPlayer = (props: WebPlayerProps) => { } /> } /> - {!isMobile ? ( - } - /> - ) : ( - } - /> - )} + } + /> } + element={} /> { } /> } + element={} + /> + } /> = { [AccessType.TOKEN_GATED]: { icon: IconArtistCoin, label: 'Fan Club', - color: 'artistCoin' + color: 'subdued' }, [AccessType.EXTRAS]: { icon: IconReceive, diff --git a/packages/web/src/components/track/GatedConditionsPill.tsx b/packages/web/src/components/track/GatedConditionsPill.tsx index f201c9acafb..1fd32cc1f21 100644 --- a/packages/web/src/components/track/GatedConditionsPill.tsx +++ b/packages/web/src/components/track/GatedConditionsPill.tsx @@ -87,12 +87,28 @@ export const GatedConditionsPill = ({ ] ) + if (isTokenGated) { + return ( + + ) + } + return (