ui: what's new crowdfunding card opens the crowdfunding page again (#8022)

* ui: what's new crowdfunding card opens the crowdfunding page, with ask SimpleX team

* ui: what's new references with the crowdfunding card

* ui: keep the what's new card texts, only open the crowdfunding page from it
This commit is contained in:
Evgeny @ SimpleX Chat authored and GitHub committed 2026-11-04 09:09:02 +00:00
1 parent d00513ed27
commit 4ef5fdc566
4 files changed
+53 -19

No files matched your search

@@ -839,6 +839,7 @@ fileprivate struct CreateUpdateAddressShortLink: View {
fileprivate struct InvestInSimpleXChat: View {
@EnvironmentObject var theme: AppTheme
@State private var showGetStakeSheet = false
var body: some View {
VStack(alignment: .leading, spacing: 4) {
@@ -850,13 +851,16 @@ fileprivate struct InvestInSimpleXChat: View {
.cornerRadius(12)
.padding(.top, 4)
.padding(.bottom, 8)
.onTapGesture { UIApplication.shared.open(wefunderURL) }
.onTapGesture { showGetStakeSheet = true }
#endif
Text("Learn more on Wefunder.")
.foregroundColor(theme.colors.primary)
.onTapGesture { UIApplication.shared.open(wefunderURL) }
.onTapGesture { showGetStakeSheet = true }
}
.frame(maxWidth: .infinity, alignment: .leading)
.sheet(isPresented: $showGetStakeSheet) {
GetStakeView(fromSettings: false)
}
}
}
@@ -889,7 +893,11 @@ fileprivate let getStakeSlides: [(image: String, heading: String, info: String?,
let wefunderURL = URL(string: "https://wefunder.com/simplex.chat?utm_source=app_ios")!
private let simplexCrowdfundingURL = URL(string: "simplex:/a#JxGcOA1_QhlmVFzYYabloMbvMZk5Y9d9iS3ITDnhzYo?h=smp11.simplex.im")!
struct GetStakeView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@EnvironmentObject var chatModel: ChatModel
var fromSettings: Bool
var body: some View {
@@ -921,7 +929,18 @@ struct GetStakeView: View {
Text(verbatim: "Learn more on Wefunder")
}
.buttonStyle(OnboardingButtonStyle())
.padding(.bottom)
Button {
dismiss()
DispatchQueue.main.async {
ChatModel.shared.appOpenUrl = simplexCrowdfundingURL
}
} label: {
Text(verbatim: "or ask SimpleX team")
.font(.callout)
}
.disabled(chatModel.chatRunning != true)
.frame(maxWidth: .infinity)
}
.padding()
}
@@ -73,8 +73,8 @@ fun GetStakeBanner(showDismiss: Boolean, onTap: () -> Unit, onDismiss: () -> Uni
fun openGetStake(modalManager: ModalManager) {
appPrefs.getStakeBannerTapped.set(true)
modalManager.showModal(cardScreen = true) {
GetStakeView(inCenterOfWindow = modalManager === ModalManager.center)
modalManager.showModalCloseable(cardScreen = true) { close ->
GetStakeView(inCenterOfWindow = modalManager === ModalManager.center, close = close)
}
}
@@ -971,7 +971,7 @@ private val versionDescriptions: List<VersionDescription> = listOf(
VersionFeature.FeatureView(
icon = null,
titleId = MR.strings.v7_1_invest,
view = { InvestInSimpleXChatView() }
view = { modalManager -> InvestInSimpleXChatView(modalManager) }
),
VersionFeature.FeatureDescription(
icon = MR.images.ic_alternate_email,
@@ -998,7 +998,7 @@ private val versionDescriptions: List<VersionDescription> = listOf(
VersionFeature.FeatureView(
icon = null,
titleId = MR.strings.v7_1_invest,
view = { InvestInSimpleXChatView() }
view = { modalManager -> InvestInSimpleXChatView(modalManager) }
),
VersionFeature.FeatureView(
icon = null,
@@ -1083,6 +1083,8 @@ fun shouldShowWhatsNew(m: ChatModel): Boolean {
val WEFUNDER_URL = "https://wefunder.com/simplex.chat?utm_source=$APP_UTM_SOURCE"
private const val CROWDFUNDING_CONTACT_URI = "simplex:/a#JxGcOA1_QhlmVFzYYabloMbvMZk5Y9d9iS3ITDnhzYo?h=smp11.simplex.im"
// the center modal takes the remaining width of the window, so the image is limited to its design width
private val MAX_CROWDFUNDING_IMAGE_WIDTH = DEFAULT_MIN_CENTER_MODAL_WIDTH
@@ -1095,8 +1097,12 @@ private const val CROWDFUNDING_IMAGE_CORNER_RADIUS_RATIO = 0.03f
private class CrowdfundingLayout(
val maxImageWidth: Dp,
val imageShape: Shape
)
val imageShape: Shape,
// the modal manager that shows the page in the center of the window, or null when nothing does
private val centerOfWindow: ModalManager?
) {
fun inCenterOfWindow(modalManager: ModalManager) = modalManager === centerOfWindow
}
// the images are designed for the width of a phone screen, which Android always gives them. On desktop
// they are limited to their own width, and their radius is scaled with them, as they are still shown
@@ -1106,9 +1112,9 @@ private val crowdfundingLayout = if (appPlatform.isDesktop)
CrowdfundingLayout(CROWDFUNDING_PAGE_IMAGE_WIDTH, object : Shape {
override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline =
Outline.Rounded(RoundRect(size.toRect(), CornerRadius(size.width * CROWDFUNDING_IMAGE_CORNER_RADIUS_RATIO)))
})
}, ModalManager.center)
else
CrowdfundingLayout(Dp.Unspecified, RoundedCornerShape(CROWDFUNDING_IMAGE_CORNER_RADIUS))
CrowdfundingLayout(Dp.Unspecified, RoundedCornerShape(CROWDFUNDING_IMAGE_CORNER_RADIUS), null)
// Google Play policy restricts promoting investments, so Play builds only show it in the US
@Composable
@@ -1128,10 +1134,9 @@ fun isInUs(): Boolean =
|| androidPlayStoreCountry.value == null
@Composable
private fun InvestInSimpleXChatView() {
private fun InvestInSimpleXChatView(modalManager: ModalManager) {
if (!crowdfundingAvailable()) return
val uriHandler = LocalUriHandler.current
val openWefunder = { uriHandler.openUriCatching(WEFUNDER_URL) }
val showGetStake = { modalManager.showModalCloseable(cardScreen = true) { close -> GetStakeView(inCenterOfWindow = crowdfundingLayout.inCenterOfWindow(modalManager), close = close) } }
Column(modifier = Modifier.padding(bottom = 12.dp)) {
Text(
generalGetString(MR.strings.v7_1_invest),
@@ -1153,7 +1158,7 @@ private fun InvestInSimpleXChatView() {
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = openWefunder
onClick = showGetStake
)
)
}
@@ -1166,7 +1171,7 @@ private fun InvestInSimpleXChatView() {
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = openWefunder
onClick = showGetStake
)
)
}
@@ -1208,8 +1213,9 @@ private val getStakeSlides: List<CrowdfundingSlide> = listOf(
)
@Composable
fun GetStakeView(inCenterOfWindow: Boolean = false) {
fun GetStakeView(inCenterOfWindow: Boolean = false, close: () -> Unit) {
val uriHandler = LocalUriHandler.current
val stopped = chatModel.chatRunning.value == false
@Composable
fun slideImage(slide: CrowdfundingSlide) {
@@ -1259,7 +1265,7 @@ fun GetStakeView(inCenterOfWindow: Boolean = false) {
}
Column(
Modifier.fillMaxWidth().padding(vertical = DEFAULT_PADDING * 2),
Modifier.fillMaxWidth().padding(top = DEFAULT_PADDING * 2),
horizontalAlignment = Alignment.CenterHorizontally
) {
OnboardingActionButton(
@@ -1268,6 +1274,15 @@ fun GetStakeView(inCenterOfWindow: Boolean = false) {
onboarding = null,
onclick = { uriHandler.openUriCatching(WEFUNDER_URL) }
)
if (!chatModel.desktopNoUserNoRemote) {
TextButtonBelowOnboardingButton(
"or ask SimpleX team",
onClick = if (stopped) null else ({
close()
uriHandler.openVerifiedSimplexUri(CROWDFUNDING_CONTACT_URI)
})
)
}
}
}
}
@@ -143,7 +143,7 @@ fun SettingsLayout(
SettingsActionItem(
painterResource(MR.images.ic_redeem),
stringResource(MR.strings.v7_0_crowdfunding),
{ ModalManager.start.showModal(cardScreen = true) { GetStakeView() } }
{ ModalManager.start.showModalCloseable(cardScreen = true) { close -> GetStakeView(close = close) } }
)
}
}