Skip to content

Commit e31732b

Browse files
committed
Merge remote-tracking branch 'origin/trunk' into merge/24.4-rc-2-to-trunk
2 parents 53f18ab + f6a8606 commit e31732b

File tree

74 files changed

+4768
-512
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+4768
-512
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Fixes #
3232

3333
-----
3434

35-
## Testing Checklist:
35+
## Testing Checklist (strike-out the not-applying and unnecessary ones):
3636

3737
- [ ] WordPress.com sites and self-hosted Jetpack sites.
3838
- [ ] Portrait and landscape orientations.

RELEASE-NOTES.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
24.5
44
-----
5-
5+
* [*] [internal] Block editor: Remove code associated to Story block [https://github.com/wordpress-mobile/WordPress-Android/pull/20400]
6+
* [*] [Jetpack-only] Fixes broken links on some notifications [https://github.com/wordpress-mobile/WordPress-Android/pull/20417]
7+
* [**] [internal] Block editor: Upgrade React Native to version 0.73.3 [#20167]
68

79
24.4
810
-----

WordPress/build.gradle

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import se.bjurr.violations.lib.model.SEVERITY
44
plugins {
55
id "com.android.application"
66
id "org.jetbrains.kotlin.android"
7-
id "org.jetbrains.kotlin.kapt"
87
id "org.jetbrains.kotlin.plugin.parcelize"
98
id "org.jetbrains.kotlin.plugin.allopen"
109
id "io.sentry.android.gradle"
1110
id "se.bjurr.violations.violation-comments-to-github-gradle-plugin"
1211
id "com.google.gms.google-services"
1312
id "com.google.dagger.hilt.android"
1413
id "org.jetbrains.kotlinx.kover"
14+
id "com.google.devtools.ksp"
1515
}
1616

1717
sentry {
@@ -141,9 +141,9 @@ android {
141141
buildConfigField "boolean", "PLANS_IN_SITE_CREATION", "false"
142142
buildConfigField "boolean", "READER_IMPROVEMENTS", "false"
143143
buildConfigField "boolean", "BLOGANUARY_DASHBOARD_NUDGE", "false"
144-
buildConfigField "boolean", "IN_APP_REVIEWS", "false"
145144
buildConfigField "boolean", "DYNAMIC_DASHBOARD_CARDS", "false"
146145
buildConfigField "boolean", "STATS_TRAFFIC_TAB", "false"
146+
buildConfigField "boolean", "READER_DISCOVER_NEW_ENDPOINT", "false"
147147

148148
// Override these constants in jetpack product flavor to enable/ disable features
149149
buildConfigField "boolean", "ENABLE_SITE_CREATION", "true"
@@ -158,6 +158,7 @@ android {
158158
buildConfigField "boolean", "BLAZE_MANAGE_CAMPAIGNS", "false"
159159
buildConfigField "boolean", "DASHBOARD_PERSONALIZATION", "false"
160160
buildConfigField "boolean", "ENABLE_SITE_MONITORING", "false"
161+
buildConfigField "boolean", "SYNC_PUBLISHING", "false"
161162

162163
manifestPlaceholders = [magicLinkScheme:"wordpress"]
163164
}
@@ -335,16 +336,12 @@ static def addBuildConfigFieldsFromPrefixedProperties(variant, properties, prefi
335336
variant.buildConfigField "String", it.key.toUpperCase(), "\"${it.value}\""
336337
}
337338
}
338-
kapt {
339-
// Enable to infer error types in stubs (see: https://kotlinlang.org/docs/kapt.html#non-existent-type-correction)
340-
correctErrorTypes true
341-
}
342339

343340
dependencies {
344341
implementation 'androidx.webkit:webkit:1.10.0'
345342
implementation "androidx.navigation:navigation-compose:$androidxComposeNavigationVersion"
346343
compileOnly project(path: ':libs:annotations')
347-
kapt project(':libs:processors')
344+
ksp project(':libs:processors')
348345
implementation (project(path:':libs:networking')) {
349346
exclude group: "com.android.volley"
350347
exclude group: 'org.wordpress', module: 'utils'
@@ -446,7 +443,7 @@ dependencies {
446443
exclude group: 'androidx.appcompat', module: 'appcompat'
447444
}
448445
implementation "com.github.bumptech.glide:glide:$glideVersion"
449-
kapt "com.github.bumptech.glide:compiler:$glideVersion"
446+
ksp "com.github.bumptech.glide:ksp:$glideVersion"
450447
implementation "com.github.bumptech.glide:volley-integration:$glideVersion"
451448
implementation "com.github.indexos.media-for-mobile:domain:$indexosMediaForMobileVersion"
452449
implementation "com.github.indexos.media-for-mobile:android:$indexosMediaForMobileVersion"
@@ -460,9 +457,9 @@ dependencies {
460457
exclude group: 'com.android.support', module: 'support-annotations'
461458
}
462459
implementation "com.google.dagger:dagger-android-support:$gradle.ext.daggerVersion"
463-
kapt "com.google.dagger:dagger-android-processor:$gradle.ext.daggerVersion"
460+
ksp "com.google.dagger:dagger-android-processor:$gradle.ext.daggerVersion"
464461
implementation "com.google.dagger:hilt-android:$gradle.ext.daggerVersion"
465-
kapt "com.google.dagger:hilt-compiler:$gradle.ext.daggerVersion"
462+
ksp "com.google.dagger:hilt-compiler:$gradle.ext.daggerVersion"
466463

467464
testImplementation("androidx.arch.core:core-testing:$androidxArchCoreVersion", {
468465
exclude group: 'com.android.support', module: 'support-compat'
@@ -517,7 +514,7 @@ dependencies {
517514
androidTestImplementation (name:'cloudtestingscreenshotter_lib', ext:'aar') // Screenshots on Firebase Cloud Testing
518515
androidTestImplementation "androidx.work:work-testing:$androidxWorkManagerVersion"
519516
androidTestImplementation "com.google.dagger:hilt-android-testing:$gradle.ext.daggerVersion"
520-
kaptAndroidTest "com.google.dagger:hilt-android-compiler:$gradle.ext.daggerVersion"
517+
kspAndroidTest "com.google.dagger:hilt-android-compiler:$gradle.ext.daggerVersion"
521518
// Enables Java 8+ API desugaring support
522519
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:$androidDesugarVersion"
523520
lintChecks "org.wordpress:lint:$wordPressLintVersion"

WordPress/src/androidTest/java/org/wordpress/android/ui/notifications/NotificationsUtilsTest.java

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package org.wordpress.android.ui.notifications
2+
3+
import android.text.SpannableStringBuilder
4+
import android.text.style.ClickableSpan
5+
import android.widget.TextView
6+
import androidx.test.platform.app.InstrumentationRegistry
7+
import dagger.hilt.android.testing.HiltAndroidTest
8+
import junit.framework.TestCase.assertEquals
9+
import junit.framework.TestCase.assertFalse
10+
import junit.framework.TestCase.assertNotNull
11+
import junit.framework.TestCase.assertTrue
12+
import org.junit.Test
13+
import org.wordpress.android.fluxc.tools.FormattableContent
14+
import org.wordpress.android.fluxc.tools.FormattableRange
15+
import org.wordpress.android.ui.notifications.blocks.NoteBlockClickableSpan
16+
import org.wordpress.android.ui.notifications.utils.NotificationsUtils
17+
18+
@HiltAndroidTest
19+
class NotificationsUtilsTest {
20+
@Test
21+
fun testSpannableHasCharacterAtIndex() {
22+
val spannableStringBuilder = SpannableStringBuilder("This is only a test.")
23+
24+
assertTrue(NotificationsUtils.spannableHasCharacterAtIndex(spannableStringBuilder, 's', 3))
25+
assertFalse(NotificationsUtils.spannableHasCharacterAtIndex(spannableStringBuilder, 's', 4))
26+
27+
// Test with bogus params
28+
assertFalse(NotificationsUtils.spannableHasCharacterAtIndex(null, 'b', -1))
29+
}
30+
31+
@Test
32+
fun testGetSpannableContentForRangesAndSkipInvalidUrls() {
33+
// Create a FormattableContent object
34+
val range1 = FormattableRange(indices = listOf(10, 14), url = "https://example.com", type = "a")
35+
val range2 = FormattableRange(indices = listOf(5, 20), url = "", type = "a") // invalid url to skip
36+
val formattableContent = FormattableContent(
37+
text = "This is a test content with a link",
38+
ranges = listOf(range1, range2)
39+
)
40+
41+
// Create a TextView object
42+
val textView = TextView(InstrumentationRegistry.getInstrumentation().context)
43+
44+
// Call the method with the created objects
45+
val result = NotificationsUtils.getSpannableContentForRanges(formattableContent, textView, false) {}
46+
47+
// Check the result
48+
assertNotNull(result)
49+
assertEquals("This is a test content with a link", result.toString())
50+
51+
// Check if the link is correctly set
52+
val spans = result.getSpans(10, 14, ClickableSpan::class.java)
53+
assertTrue(spans.size == 1)
54+
assertEquals("https://example.com", (spans[0] as NoteBlockClickableSpan).formattableRange.url)
55+
}
56+
57+
@Test
58+
fun testGetSpannableContentForRangesWithNoRanges() {
59+
// Create a FormattableContent object with no ranges
60+
val formattableContent = FormattableContent(text = "This is a test content with no link")
61+
62+
// Create a TextView object
63+
val textView = TextView(InstrumentationRegistry.getInstrumentation().context)
64+
65+
// Call the method with the created objects
66+
val result = NotificationsUtils.getSpannableContentForRanges(formattableContent, textView, false) {}
67+
68+
// Check the result
69+
assertNotNull(result)
70+
assertEquals("This is a test content with no link", result.toString())
71+
72+
// Check if no ClickableSpan is set
73+
val spans = result.getSpans(0, result.length, ClickableSpan::class.java)
74+
assertTrue(spans.isEmpty())
75+
}
76+
77+
@Test
78+
fun testGetSpannableContentForRangesWithInvalidIndex() {
79+
// Create a FormattableContent object with a range with an invalid index
80+
val range = FormattableRange(indices = listOf(50, 54), url = "https://example.com", type = "a")
81+
val formattableContent = FormattableContent(text = "This is a test content", ranges = listOf(range))
82+
83+
// Create a TextView object
84+
val textView = TextView(InstrumentationRegistry.getInstrumentation().context)
85+
86+
// Call the method with the created objects
87+
val result = NotificationsUtils.getSpannableContentForRanges(formattableContent, textView, false) {}
88+
89+
// Check the result
90+
assertNotNull(result)
91+
assertEquals("This is a test content", result.toString())
92+
93+
// Check if no ClickableSpan is set
94+
val spans = result.getSpans(0, result.length, ClickableSpan::class.java)
95+
assertTrue(spans.isEmpty())
96+
}
97+
98+
@Test
99+
fun testGetSpannableContentForRangesWithNullUrl() {
100+
// Create a FormattableContent object with a range with a null URL
101+
val range = FormattableRange(indices = listOf(10, 14), url = null, type = "a")
102+
val formattableContent = FormattableContent(text = "This is a test content with a link", ranges = listOf(range))
103+
104+
// Create a TextView object
105+
val textView = TextView(InstrumentationRegistry.getInstrumentation().context)
106+
107+
// Call the method with the created objects
108+
val result = NotificationsUtils.getSpannableContentForRanges(formattableContent, textView, false) {}
109+
110+
// Check the result
111+
assertNotNull(result)
112+
assertEquals("This is a test content with a link", result.toString())
113+
114+
// Check if no ClickableSpan is set for the range with the null URL
115+
val spans = result.getSpans(10, 14, ClickableSpan::class.java)
116+
assertTrue(spans.isEmpty())
117+
}
118+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.wordpress.android.modules
2+
3+
import dagger.Module
4+
import dagger.Provides
5+
import dagger.hilt.InstallIn
6+
import dagger.hilt.components.SingletonComponent
7+
import org.wordpress.android.ui.posts.IPostFreshnessChecker
8+
import org.wordpress.android.ui.posts.PostFreshnessCheckerImpl
9+
import javax.inject.Singleton
10+
11+
@InstallIn(SingletonComponent::class)
12+
@Module
13+
class PostModule {
14+
@Singleton
15+
@Provides
16+
fun providePostFreshnessChecker(): IPostFreshnessChecker = PostFreshnessCheckerImpl()
17+
}

WordPress/src/main/java/org/wordpress/android/ui/ActivityNavigator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class ActivityNavigator @Inject constructor() {
4949

5050
fun navigateToCampaignDetailPage(
5151
context: Context,
52-
campaignId: Int,
52+
campaignId: String,
5353
campaignDetailPageSource: CampaignDetailPageSource
5454
) {
5555
context.startActivity(

WordPress/src/main/java/org/wordpress/android/ui/blaze/blazecampaigns/BlazeCampaignPage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ import org.wordpress.android.ui.blaze.blazecampaigns.campaignlisting.CampaignLis
1010
@SuppressLint("ParcelCreator")
1111
sealed class BlazeCampaignPage : Parcelable {
1212
data class CampaignListingPage(val source: CampaignListingPageSource) : BlazeCampaignPage()
13-
data class CampaignDetailsPage(val campaignId: Int, val source: CampaignDetailPageSource) : BlazeCampaignPage()
13+
data class CampaignDetailsPage(val campaignId: String, val source: CampaignDetailPageSource) : BlazeCampaignPage()
1414
object Done: BlazeCampaignPage()
1515
}

WordPress/src/main/java/org/wordpress/android/ui/blaze/blazecampaigns/campaigndetail/CampaignDetailFragment.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ private const val CAMPAIGN_DETAIL_CAMPAIGN_ID = "campaign_detail_campaign_id"
5454
@AndroidEntryPoint
5555
class CampaignDetailFragment : Fragment(), CampaignDetailWebViewClient.CampaignDetailWebViewClientListener {
5656
companion object {
57-
fun newInstance(campaignId: Int, source: CampaignDetailPageSource) = CampaignDetailFragment().apply {
57+
fun newInstance(campaignId: String, source: CampaignDetailPageSource) = CampaignDetailFragment().apply {
5858
arguments = Bundle().apply {
5959
putSerializable(CAMPAIGN_DETAIL_PAGE_SOURCE, source)
60-
putInt(CAMPAIGN_DETAIL_CAMPAIGN_ID, campaignId)
60+
putString(CAMPAIGN_DETAIL_CAMPAIGN_ID, campaignId)
6161
}
6262
}
6363
}
@@ -110,7 +110,7 @@ class CampaignDetailFragment : Fragment(), CampaignDetailWebViewClient.CampaignD
110110
?: CampaignDetailPageSource.UNKNOWN
111111
}
112112

113-
private fun getCampaignId() = requireArguments().getInt(CAMPAIGN_DETAIL_CAMPAIGN_ID)
113+
private fun getCampaignId() = requireArguments().getString(CAMPAIGN_DETAIL_CAMPAIGN_ID) ?: ""
114114

115115
override fun onRedirectToExternalBrowser(url: String) = viewModel.onRedirectToExternalBrowser(url)
116116

WordPress/src/main/java/org/wordpress/android/ui/blaze/blazecampaigns/campaigndetail/CampaignDetailViewModel.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ class CampaignDetailViewModel @Inject constructor(
3030
@Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher
3131
) : ScopedViewModel(bgDispatcher) {
3232
private lateinit var pageSource: CampaignDetailPageSource
33-
private var campaignId: Int = 0
33+
private var campaignId: String = ""
3434

3535
private val _actionEvents = Channel<BlazeActionEvent>(Channel.BUFFERED)
3636
val actionEvents = _actionEvents.receiveAsFlow()
3737

3838
private val _uiState = MutableStateFlow<CampaignDetailUiState>(CampaignDetailUiState.Preparing)
3939
val uiState = _uiState as StateFlow<CampaignDetailUiState>
4040

41-
fun start(campaignId: Int, campaignDetailPageSource: CampaignDetailPageSource) {
41+
fun start(campaignId: String, campaignDetailPageSource: CampaignDetailPageSource) {
4242
this.campaignId = campaignId
4343
this.pageSource = campaignDetailPageSource
4444

@@ -76,7 +76,7 @@ class CampaignDetailViewModel @Inject constructor(
7676
pathComponents = arrayOf(
7777
ADVERTISING_PATH,
7878
CAMPAIGNS_PATH,
79-
campaignId.toString(),
79+
campaignId,
8080
extractAndSanitizeSiteUrl()
8181
),
8282
source = pageSource.trackingName

0 commit comments

Comments
 (0)