Skip to content

Commit 4b08643

Browse files
committed
Merge branch 'release/5.32.0'
2 parents 1f4a849 + a680769 commit 4b08643

Some content is hidden

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

43 files changed

+505
-286
lines changed

CONTRIBUTING.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Thank you for taking the time to contribute to DuckDuckGo! :sparkles:
44

55
We are pleased to open up the project to you - our community. How can you contribute?
66

7+
## Improve translations
8+
We are introducing support for additional languages and would like your help in improving the translations. Please see [improving translations](TRANSLATIONS.md) for how you can help us.
9+
710
## Share feedback
811
Contact us at https://duckduckgo.com/feedback if you have feedback, questions or want to chat. You can also use the feedback form embedded within our Mobile App - to do so please navigate to Settings and select "Leave Feedback".
912

@@ -26,11 +29,11 @@ We welcome pull requests aimed at fixing bugs and security issues. We have also
2629

2730
If you have a great idea you really want to implement, start by logging an issue for us and mention that you are interested in helping. If it fits with our product direction and is a good candidate for community development we may be able to bend the rules and work with you to develop it.
2831

29-
## Style Guide
32+
### Style Guide
3033

3134
We care about clean code. Refer to our [style guide](styleguide/STYLEGUIDE.md).
3235

3336

34-
## Commit Messages
37+
### Commit Messages
3538

3639
See Chris Beams' guide to writing good commit messages https://chris.beams.io/posts/git-commit/

TRANSLATIONS.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Improve Language Translations
2+
Thank you for taking the time to contribute to DuckDuckGo! :sparkles:
3+
4+
If you know any of the following languages and would like to help us improve the translations for them, please follow the instructions below.
5+
6+
## List of languages
7+
1. Bulgarian (bg)
8+
1. Croatian (hr)
9+
1. Czech (cs)
10+
1. Danish (da)
11+
1. Dutch (nl)
12+
1. Finnish (fi)
13+
1. French (fr)
14+
1. German (de)
15+
1. Greek (el)
16+
1. Hungarian (hu)
17+
1. Italian (it)
18+
1. Lithuanian (lt)
19+
1. Norwegian bokmål (nb)
20+
1. Polish (pl)
21+
1. Portuguese (pt)
22+
1. Romanian (ro)
23+
1. Russian (ru)
24+
1. Slovak (sk)
25+
1. Slovenian (sl)
26+
1. Spanish (es)
27+
1. Swedish (sv)
28+
29+
## How to help
30+
31+
There is a branch containing the current translations, called [`feature/app_translations`](https://github.com/duckduckgo/Android/tree/feature/app_translations/app/src/main/res).
32+
1. Each language has a `values` directory containing the language code, and the `strings.xml` file contains the translations. Examples:
33+
- Italian translation files are located within `values-it/strings.xml`
34+
- Spanish translation files are located within `values-es/strings.xml`
35+
1. If you notice anything which could be improved, you should create a PR containing the improved language suggestions and those changes will be merged into that branch if accepted.
36+
1. Fork the project, and clone your forked project to your machine. [Instructions](https://help.github.com/en/articles/fork-a-repo)
37+
1. Checkout the translations branch `git checkout --track origin/feature/app_translations`
38+
1. Make the changes to the relevant `strings.xml` file, and commit
39+
1. Test the app in the language you've improved, and ensure the changed strings look good
40+
1. Push the changes to your fork `git push origin`
41+
1. Create a Pull Request for your changes. [Instructions](https://help.github.com/en/articles/creating-a-pull-request-from-a-fork)
42+
- Ensure the base branch in your PR is `feature/app_translations`
43+
44+
45+
ℹ️ Please note we are not looking for help with other languages at this time; only the languages listed above. We may open up requests in future for additional languages.

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ import androidx.room.Room
2929
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
3030
import com.duckduckgo.app.InstantSchedulersRule
3131
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi
32+
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi.AutoCompleteSuggestion.AutoCompleteBookmarkSuggestion
33+
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi.AutoCompleteSuggestion.AutoCompleteSearchSuggestion
3234
import com.duckduckgo.app.bookmarks.db.BookmarkEntity
3335
import com.duckduckgo.app.bookmarks.db.BookmarksDao
3436
import com.duckduckgo.app.browser.BrowserTabViewModel.Command
35-
import com.duckduckgo.app.browser.BrowserTabViewModel.Command.DisplayMessage
3637
import com.duckduckgo.app.browser.BrowserTabViewModel.Command.Navigate
3738
import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.DownloadFile
3839
import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.OpenInNewTab
@@ -52,7 +53,6 @@ import com.duckduckgo.app.global.install.AppInstallStore
5253
import com.duckduckgo.app.global.model.SiteFactory
5354
import com.duckduckgo.app.privacy.db.NetworkLeaderboardDao
5455
import com.duckduckgo.app.privacy.model.PrivacyPractices
55-
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi.AutoCompleteSuggestion.*
5656
import com.duckduckgo.app.privacy.store.PrevalenceStore
5757
import com.duckduckgo.app.settings.db.SettingsDataStore
5858
import com.duckduckgo.app.statistics.api.StatisticsUpdater
@@ -295,11 +295,19 @@ class BrowserTabViewModelTest {
295295
}
296296

297297
@Test
298-
fun whenBookmarkAddedThenDaoIsUpdatedAndUserNotified() {
299-
testee.onBookmarkSaved(null, "A title", "www.example.com")
298+
fun whenBookmarkEditedThenDaoIsUpdated() = runBlocking<Unit> {
299+
testee.editBookmark(0, "A title", "www.example.com")
300+
verify(bookmarksDao).update(BookmarkEntity(title = "A title", url = "www.example.com"))
301+
}
302+
303+
@Test
304+
fun whenBookmarkAddedThenDaoIsUpdatedAndUserNotified() = runBlocking<Unit> {
305+
loadUrl("www.example.com", "A title")
306+
307+
testee.onBookmarkAddRequested()
300308
verify(bookmarksDao).insert(BookmarkEntity(title = "A title", url = "www.example.com"))
301309
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
302-
assertTrue(commandCaptor.lastValue is DisplayMessage)
310+
assertTrue(commandCaptor.lastValue is Command.ShowBookmarkAddedConfirmation)
303311
}
304312

305313
@Test
@@ -895,22 +903,24 @@ class BrowserTabViewModelTest {
895903
}
896904

897905
@Test
898-
fun whenSiteLoadedAndUserSelectsToAddBookmarkThenAddBookmarkCommandSentWithUrlAndTitle() {
906+
fun whenSiteLoadedAndUserSelectsToAddBookmarkThenAddBookmarkCommandSentWithUrlAndTitle() = runBlocking<Unit> {
899907
loadUrl("foo.com")
900908
testee.titleReceived("Foo Title")
901-
testee.onAddBookmarkSelected()
902-
val command = captureCommands().value as Command.AddBookmark
909+
testee.onBookmarkAddRequested()
910+
val command = captureCommands().value as Command.ShowBookmarkAddedConfirmation
903911
assertEquals("foo.com", command.url)
904912
assertEquals("Foo Title", command.title)
905913
}
906914

907915
@Test
908-
fun whenNoSiteAndUserSelectsToAddBookmarkThenAddBookmarkCommandSentWithBlankTitleAndUrl() {
909-
testee.onAddBookmarkSelected()
910-
val command = captureCommands().value as Command.AddBookmark
911-
assertNotNull(command)
912-
assertNull(command.url)
913-
assertNull(command.title)
916+
fun whenNoSiteAndUserSelectsToAddBookmarkThenBookmarkAddedWithBlankTitleAndUrl() = runBlocking<Unit> {
917+
whenever(bookmarksDao.insert(any())).thenReturn(1)
918+
testee.onBookmarkAddRequested()
919+
verify(bookmarksDao).insert(BookmarkEntity(title = "", url = ""))
920+
val command = captureCommands().value as Command.ShowBookmarkAddedConfirmation
921+
assertEquals(1, command.bookmarkId)
922+
assertEquals("", command.title)
923+
assertEquals("", command.url)
914924
}
915925

916926
@Test

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserWebViewClientTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class BrowserWebViewClientTest {
108108
val detail: RenderProcessGoneDetail = mock()
109109
whenever(detail.didCrash()).thenReturn(false)
110110
testee.onRenderProcessGone(webView, detail)
111-
verify(offlinePixelDataStore, times(1)).webRendererGoneOtherCount = 1
111+
verify(offlinePixelDataStore, times(1)).webRendererGoneKilledCount = 1
112112
}
113113

114114
private class TestWebView(context: Context) : WebView(context)

app/src/androidTest/java/com/duckduckgo/app/cta/ui/CtaViewModelTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,21 +174,21 @@ class CtaViewModelTest {
174174
fun whenCtaShownPixelIsFired() {
175175
testee.onSurveyChanged(Survey("abc", "http://example.com", 1, SCHEDULED))
176176
testee.onCtaShown()
177-
verify(mockPixel).fire(eq(SURVEY_CTA_SHOWN), any(), eq(false))
177+
verify(mockPixel).fire(eq(SURVEY_CTA_SHOWN), any())
178178
}
179179

180180
@Test
181181
fun whenCtaLaunchedPixelIsFired() {
182182
testee.onSurveyChanged(Survey("abc", "http://example.com", 1, SCHEDULED))
183183
testee.onCtaLaunched()
184-
verify(mockPixel).fire(eq(SURVEY_CTA_LAUNCHED), any(), eq(false))
184+
verify(mockPixel).fire(eq(SURVEY_CTA_LAUNCHED), any())
185185
}
186186

187187
@Test
188188
fun whenCtaDismissedPixelIsFired() {
189189
testee.onSurveyChanged(Survey("abc", "http://example.com", 1, SCHEDULED))
190190
testee.onCtaDismissed()
191-
verify(mockPixel).fire(eq(SURVEY_CTA_DISMISSED), any(), eq(false))
191+
verify(mockPixel).fire(eq(SURVEY_CTA_DISMISSED), any())
192192
}
193193

194194
@Test

app/src/androidTest/java/com/duckduckgo/app/di/StubStatisticsModule.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ class StubStatisticsModule {
5151
fun stubPixel(): Pixel {
5252
return object : Pixel {
5353

54-
override fun fire(pixel: Pixel.PixelName, parameters: Map<String, String?>, includeLocale: Boolean) {
54+
override fun fire(pixel: Pixel.PixelName, parameters: Map<String, String?>) {
5555
}
5656

57-
override fun fire(pixelName: String, parameters: Map<String, String?>, includeLocale: Boolean) {
57+
override fun fire(pixelName: String, parameters: Map<String, String?>) {
5858

5959
}
6060

app/src/androidTest/java/com/duckduckgo/app/notification/NotificationHandlerServiceTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class NotificationHandlerServiceTest {
5050
intent.type = CLEAR_DATA_LAUNCH
5151
intent.putExtra(PIXEL_SUFFIX_EXTRA, "abc")
5252
testee.onHandleIntent(intent)
53-
verify(mockPixel).fire(eq("mnot_l_abc"), any(), any())
53+
verify(mockPixel).fire(eq("mnot_l_abc"), any())
5454
}
5555

5656
@Test
@@ -59,6 +59,6 @@ class NotificationHandlerServiceTest {
5959
intent.type = CANCEL
6060
intent.putExtra(PIXEL_SUFFIX_EXTRA, "abc")
6161
testee.onHandleIntent(intent)
62-
verify(mockPixel).fire(eq("mnot_c_abc"), any(), any())
62+
verify(mockPixel).fire(eq("mnot_c_abc"), any())
6363
}
6464
}

app/src/androidTest/java/com/duckduckgo/app/notification/NotificationRegistrarTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,31 +56,31 @@ class NotificationRegistrarTest {
5656
fun whenNotificationsPreviouslyOffAndNowOnThenPixelIsFiredAndSettingsUpdated() {
5757
whenever(mockSettingsDataStore.appNotificationsEnabled).thenReturn(false)
5858
testee.updateStatus(true)
59-
verify(mockPixel).fire(eq(Pixel.PixelName.NOTIFICATIONS_ENABLED), any(), eq(false))
59+
verify(mockPixel).fire(eq(Pixel.PixelName.NOTIFICATIONS_ENABLED), any())
6060
verify(mockSettingsDataStore).appNotificationsEnabled = true
6161
}
6262

6363
@Test
6464
fun whenNotificationsPreviouslyOffAndStillOffThenNoPixelIsFiredAndSettingsUnchanged() {
6565
whenever(mockSettingsDataStore.appNotificationsEnabled).thenReturn(false)
6666
testee.updateStatus(false)
67-
verify(mockPixel, never()).fire(any<Pixel.PixelName>(), any(), eq(false))
67+
verify(mockPixel, never()).fire(any<Pixel.PixelName>(), any())
6868
verify(mockSettingsDataStore, never()).appNotificationsEnabled = true
6969
}
7070

7171
@Test
7272
fun whenNotificationsPreviouslyOnAndStillOnThenNoPixelIsFiredAndSettingsUnchanged() {
7373
whenever(mockSettingsDataStore.appNotificationsEnabled).thenReturn(true)
7474
testee.updateStatus(true)
75-
verify(mockPixel, never()).fire(any<Pixel.PixelName>(), any(), eq(false))
75+
verify(mockPixel, never()).fire(any<Pixel.PixelName>(), any())
7676
verify(mockSettingsDataStore, never()).appNotificationsEnabled = false
7777
}
7878

7979
@Test
8080
fun whenNotificationsPreviouslyOnAndNowOffPixelIsFiredAndSettingsUpdated() {
8181
whenever(mockSettingsDataStore.appNotificationsEnabled).thenReturn(true)
8282
testee.updateStatus(false)
83-
verify(mockPixel).fire(eq(Pixel.PixelName.NOTIFICATIONS_DISABLED), any(), eq(false))
83+
verify(mockPixel).fire(eq(Pixel.PixelName.NOTIFICATIONS_DISABLED), any())
8484
verify(mockSettingsDataStore).appNotificationsEnabled = false
8585
}
8686
}

app/src/androidTest/java/com/duckduckgo/app/statistics/ApiBasedPixelTest.kt

Lines changed: 14 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class ApiBasedPixelTest {
5757
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
5858
pixel.fire(PRIVACY_DASHBOARD_OPENED)
5959

60-
verify(mockPixelService).fire("mp", "phone", "atbvariant", emptyMap())
60+
verify(mockPixelService).fire(eq("mp"), eq("phone"), eq("atbvariant"), any())
6161
}
6262

6363
@Test
@@ -70,7 +70,7 @@ class ApiBasedPixelTest {
7070
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
7171
pixel.fire(FORGET_ALL_EXECUTED)
7272

73-
verify(mockPixelService).fire("mf", "phone", "atb", emptyMap())
73+
verify(mockPixelService).fire(eq("mf"), eq("phone"), eq("atb"), any())
7474
}
7575

7676
@Test
@@ -81,7 +81,7 @@ class ApiBasedPixelTest {
8181
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
8282
pixel.fire(APP_LAUNCH)
8383

84-
verify(mockPixelService).fire("ml", "tablet", "", emptyMap())
84+
verify(mockPixelService).fire(eq("ml"), eq("tablet"), eq(""), any())
8585
}
8686

8787
@Test
@@ -92,63 +92,37 @@ class ApiBasedPixelTest {
9292
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
9393
pixel.fire(APP_LAUNCH)
9494

95-
verify(mockPixelService).fire("ml", "phone", "", emptyMap())
95+
verify(mockPixelService).fire(eq("ml"), eq("phone"), eq(""), any())
9696
}
9797

9898
@Test
99-
fun whenPixelFiredWithAdditionalParametersThenPixelServiceCalledWithAdditionalParameters() {
99+
fun whenPixelFiredWithAdditionalParametersThenPixelServiceCalledWithDefaultAndAdditionalParameters() {
100100
whenever(mockPixelService.fire(any(), any(), any(), any())).thenReturn(Completable.complete())
101101
whenever(mockStatisticsDataStore.atb).thenReturn(Atb("atb"))
102102
whenever(mockVariantManager.getVariant()).thenReturn(Variant("variant"))
103103
whenever(mockDeviceInfo.formFactor()).thenReturn(DeviceInfo.FormFactor.PHONE)
104+
whenever(mockDeviceInfo.appVersion).thenReturn("1.0.0")
104105

105106
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
106107
val params = mapOf("param1" to "value1", "param2" to "value2")
107-
pixel.fire(PRIVACY_DASHBOARD_OPENED, params)
108-
verify(mockPixelService).fire("mp", "phone", "atbvariant", params)
109-
}
110-
111-
@Test
112-
fun whenPixelFiredWithoutAdditionalParametersThenPixelServiceCalledWithNoParameters() {
113-
whenever(mockPixelService.fire(any(), any(), any(), any())).thenReturn(Completable.complete())
114-
whenever(mockStatisticsDataStore.atb).thenReturn(Atb("atb"))
115-
whenever(mockVariantManager.getVariant()).thenReturn(Variant("variant"))
116-
whenever(mockDeviceInfo.formFactor()).thenReturn(DeviceInfo.FormFactor.PHONE)
108+
val expectedParams = mapOf("param1" to "value1", "param2" to "value2", "appVersion" to "1.0.0")
117109

118-
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
119-
val params = emptyMap<String, String>()
120-
pixel.fire(PRIVACY_DASHBOARD_OPENED)
121-
verify(mockPixelService).fire("mp", "phone", "atbvariant", params)
110+
pixel.fire(PRIVACY_DASHBOARD_OPENED, params)
111+
verify(mockPixelService).fire("mp", "phone", "atbvariant", expectedParams)
122112
}
123113

124114
@Test
125-
fun whenPixelFiredWithAdditionalParametersAndLocaleThenPixelServiceCalledWithBothSetsOfParameters() {
115+
fun whenPixelFiredWithoutAdditionalParametersThenPixelServiceCalledWithOnlyDefaultParameters() {
126116
whenever(mockPixelService.fire(any(), any(), any(), any())).thenReturn(Completable.complete())
127117
whenever(mockStatisticsDataStore.atb).thenReturn(Atb("atb"))
128118
whenever(mockVariantManager.getVariant()).thenReturn(Variant("variant"))
129119
whenever(mockDeviceInfo.formFactor()).thenReturn(DeviceInfo.FormFactor.PHONE)
130-
whenever(mockDeviceInfo.country).thenReturn("us")
131-
whenever(mockDeviceInfo.language).thenReturn("es")
120+
whenever(mockDeviceInfo.appVersion).thenReturn("1.0.0")
132121

133-
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
134-
val params = mapOf("param1" to "value1")
135-
val localeParams = mapOf("lg" to "es", "co" to "us")
136-
pixel.fire(PRIVACY_DASHBOARD_OPENED, params, includeLocale = true)
137-
verify(mockPixelService).fire("mp", "phone", "atbvariant", params.plus(localeParams))
138-
}
139-
140-
@Test
141-
fun whenPixelFiredWithLocaleAndNoAdditionalParametersThenPixelServiceCalledWithLocaleParameters() {
142-
whenever(mockPixelService.fire(any(), any(), any(), any())).thenReturn(Completable.complete())
143-
whenever(mockStatisticsDataStore.atb).thenReturn(Atb("atb"))
144-
whenever(mockVariantManager.getVariant()).thenReturn(Variant("variant"))
145-
whenever(mockDeviceInfo.formFactor()).thenReturn(DeviceInfo.FormFactor.PHONE)
146-
whenever(mockDeviceInfo.country).thenReturn("us")
147-
whenever(mockDeviceInfo.language).thenReturn("es")
148122

149123
val pixel = ApiBasedPixel(mockPixelService, mockStatisticsDataStore, mockVariantManager, mockDeviceInfo)
150-
val localeParams = mapOf("lg" to "es", "co" to "us")
151-
pixel.fire(PRIVACY_DASHBOARD_OPENED, includeLocale = true)
152-
verify(mockPixelService).fire("mp", "phone", "atbvariant", localeParams)
124+
pixel.fire(PRIVACY_DASHBOARD_OPENED)
125+
val expectedParams = mapOf("appVersion" to "1.0.0")
126+
verify(mockPixelService).fire("mp", "phone", "atbvariant", expectedParams)
153127
}
154128
}

0 commit comments

Comments
 (0)