diff --git a/.github/workflows/build-contributor-pr.yml b/.github/workflows/build-contributor-pr.yml index 54aff826e35..d6ed3d869a1 100644 --- a/.github/workflows/build-contributor-pr.yml +++ b/.github/workflows/build-contributor-pr.yml @@ -10,7 +10,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: "Clean & Assemble Debug" uses: eskatos/gradle-command-action@v1 with: @@ -29,7 +29,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: "Test Debug Unit Tests" uses: eskatos/gradle-command-action@v1 with: @@ -48,7 +48,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: "Detekt" uses: eskatos/gradle-command-action@v1 with: @@ -72,7 +72,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: "Ktlint" uses: eskatos/gradle-command-action@v1 with: @@ -91,7 +91,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v1 with: - java-version: 1.8 + java-version: 11 - name: "Lint Debug" uses: eskatos/gradle-command-action@v1 with: @@ -125,7 +125,7 @@ jobs: arch: x86_64 profile: pixel_2 script: - "./gradlew connectedFocusDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=\ + "JAVA_HOME=$JAVA_HOME_11_X64 && ./gradlew connectedFocusDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=\ org.mozilla.focus.activity.ThreeDotMainMenuTest#browserMenuItemsTest" - name: Upload Test Artifacts uses: actions/upload-artifact@v2 diff --git a/.taskcluster.yml b/.taskcluster.yml index b01b1ed6771..8ede2a68eae 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -22,7 +22,7 @@ tasks: routes: [] payload: maxRunTime: 7200 - image: mozillamobile/focus-android:1.6 + image: mozillamobile/focus-android:1.7 command: - /bin/bash - --login @@ -81,7 +81,7 @@ tasks: - 'assume:repo:github.com/mozilla-mobile/focus-android:branch:${short_head_branch}' payload: maxRunTime: 7200 - image: mozillamobile/focus-android:1.6 + image: mozillamobile/focus-android:1.7 features: taskclusterProxy: true env: @@ -143,7 +143,7 @@ tasks: - statuses # Automatically added by taskcluster-github. It must be explicit because of Chain of Trust payload: maxRunTime: 600 # Decision should remain fast enough to schedule a handful of tasks - image: mozillamobile/focus-android:1.6 + image: mozillamobile/focus-android:1.7 features: taskclusterProxy: true chainOfTrust: true @@ -218,7 +218,7 @@ tasks: - statuses # Automatically added by taskcluster-github. It must be explicit because of Chain of Trust payload: maxRunTime: 600 # Decision should remain fast enough to schedule a handful of tasks - image: mozillamobile/focus-android:1.6 + image: mozillamobile/focus-android:1.7 features: taskclusterProxy: true chainOfTrust: true diff --git a/app/build.gradle b/app/build.gradle index 5d884348c6a..5d1c8045f19 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,11 +11,11 @@ apply from: "$project.rootDir/tools/gradle/versionCode.gradle" import com.android.build.OutputFile android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { applicationId "org.mozilla" minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 11 // This versionCode is "frozen" for local builds. For "release" builds we // override this with a generated versionCode at build time. versionName "8.13.1" @@ -30,10 +30,6 @@ android { targetCompatibility JavaVersion.VERSION_1_8 } - dexOptions { - preDexLibraries true - } - lintOptions { lintConfig file("lint.xml") } @@ -66,6 +62,14 @@ android { } } + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose_version + } + flavorDimensions "product" productFlavors { @@ -156,6 +160,10 @@ dependencies { implementation Dependencies.androidx_appcompat implementation Dependencies.androidx_browser implementation Dependencies.androidx_cardview + implementation Dependencies.androidx_compose_ui + implementation Dependencies.androidx_compose_ui_tooling + implementation Dependencies.androidx_compose_foundation + implementation Dependencies.androidx_compose_material implementation Dependencies.androidx_core_ktx implementation Dependencies.androidx_lifecycle_extensions implementation Dependencies.androidx_palette @@ -199,8 +207,8 @@ dependencies { implementation project(':service-telemetry') - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${coroutines_version}" + implementation Dependencies.kotlin_stdlib + implementation Dependencies.kotlin_coroutines focusImplementation 'com.adjust.sdk:adjust-android:4.11.4' focusImplementation 'com.android.installreferrer:installreferrer:1.1' // Required by Adjust @@ -214,8 +222,8 @@ dependencies { testImplementation "org.junit.jupiter:junit-jupiter-params:5.3.1" testImplementation "junit:junit:4.12" testRuntimeOnly "org.junit.vintage:junit-vintage-engine:5.3.1" - testImplementation "org.robolectric:robolectric:4.4" // required to support api level 28 - testImplementation "org.mockito:mockito-core:3.11.0" + testImplementation Dependencies.testing_robolectric + testImplementation Dependencies.testing_mockito testImplementation Dependencies.androidx_arch_core_testing androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version", { @@ -256,7 +264,7 @@ android.applicationVariants.all { variant -> println("----------------------------------------------") println("Variant name: " + variant.name) - println("Application ID: " + [variant.mergedFlavor.applicationId, variant.buildType.applicationIdSuffix].findAll().join()) + println("Application ID: " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join()) println("Build type: " + variant.buildType.name) println("Flavor: " + variant.flavorName) diff --git a/app/src/main/java/org/mozilla/focus/Components.kt b/app/src/main/java/org/mozilla/focus/Components.kt index 5fd17bdb830..7ec796dba84 100644 --- a/app/src/main/java/org/mozilla/focus/Components.kt +++ b/app/src/main/java/org/mozilla/focus/Components.kt @@ -7,6 +7,8 @@ package org.mozilla.focus import android.app.PendingIntent import android.content.Context import android.content.Intent +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext import mozilla.components.browser.state.engine.EngineMiddleware import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.DefaultSettings @@ -43,6 +45,7 @@ import org.mozilla.focus.engine.ClientWrapper import org.mozilla.focus.engine.LocalizedContentInterceptor import org.mozilla.focus.engine.SanityCheckMiddleware import org.mozilla.focus.exceptions.ExceptionMigrationMiddleware +import org.mozilla.focus.ext.components import org.mozilla.focus.locale.LocaleManager import org.mozilla.focus.notification.PrivateNotificationMiddleware import org.mozilla.focus.search.SearchFilterMiddleware @@ -225,3 +228,10 @@ private fun getLocaleTag(context: Context): String { Locale.getDefault().toLanguageTag() } } + +/** + * Returns the [Components] object from within a [Composable]. + */ +val components: Components + @Composable + get() = LocalContext.current.components diff --git a/app/src/main/java/org/mozilla/focus/activity/CustomTabActivity.kt b/app/src/main/java/org/mozilla/focus/activity/CustomTabActivity.kt index 06a711f8ddd..939d084b22b 100644 --- a/app/src/main/java/org/mozilla/focus/activity/CustomTabActivity.kt +++ b/app/src/main/java/org/mozilla/focus/activity/CustomTabActivity.kt @@ -38,6 +38,7 @@ class CustomTabActivity : LocaleAwareAppCompatActivity() { this.customTabId = customTabId + @Suppress("DEPRECATION") // https://github.com/mozilla-mobile/focus-android/issues/5016 window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN setContentView(R.layout.activity_customtab) diff --git a/app/src/main/java/org/mozilla/focus/activity/MainActivity.kt b/app/src/main/java/org/mozilla/focus/activity/MainActivity.kt index 728163ba1e4..ed9524b6513 100644 --- a/app/src/main/java/org/mozilla/focus/activity/MainActivity.kt +++ b/app/src/main/java/org/mozilla/focus/activity/MainActivity.kt @@ -55,6 +55,7 @@ open class MainActivity : LocaleAwareAppCompatActivity() { } } + @Suppress("DEPRECATION") // https://github.com/mozilla-mobile/focus-android/issues/5016 window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN setContentView(R.layout.activity_main) diff --git a/app/src/main/java/org/mozilla/focus/autocomplete/AutocompleteAddFragment.kt b/app/src/main/java/org/mozilla/focus/autocomplete/AutocompleteAddFragment.kt index 20787c72600..59fd80dd994 100644 --- a/app/src/main/java/org/mozilla/focus/autocomplete/AutocompleteAddFragment.kt +++ b/app/src/main/java/org/mozilla/focus/autocomplete/AutocompleteAddFragment.kt @@ -74,7 +74,7 @@ class AutocompleteAddFragment : BaseSettingsLikeFragment(), CoroutineScope { val domain = domainView.text.toString() .trim() - .toLowerCase() + .lowercase() launch(IO) { val domains = CustomDomains.load(requireActivity()) diff --git a/app/src/main/java/org/mozilla/focus/browser/integration/FullScreenIntegration.kt b/app/src/main/java/org/mozilla/focus/browser/integration/FullScreenIntegration.kt index 595ef70139a..d5e25545917 100644 --- a/app/src/main/java/org/mozilla/focus/browser/integration/FullScreenIntegration.kt +++ b/app/src/main/java/org/mozilla/focus/browser/integration/FullScreenIntegration.kt @@ -71,6 +71,7 @@ class FullScreenIntegration( private fun switchToImmersiveMode() { val window = activity.window window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + @Suppress("DEPRECATION") // https://github.com/mozilla-mobile/focus-android/issues/5016 window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN @@ -90,6 +91,7 @@ class FullScreenIntegration( val window = activity.window window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + @Suppress("DEPRECATION") // https://github.com/mozilla-mobile/focus-android/issues/5016 window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } } diff --git a/app/src/main/java/org/mozilla/focus/ext/String.kt b/app/src/main/java/org/mozilla/focus/ext/String.kt index 71a360bff41..530036b9669 100644 --- a/app/src/main/java/org/mozilla/focus/ext/String.kt +++ b/app/src/main/java/org/mozilla/focus/ext/String.kt @@ -64,10 +64,10 @@ fun String.beautifyUrl(): String { */ fun String.removePrefixesIgnoreCase(vararg prefixes: String): String { var value = this - var lower = this.toLowerCase() + var lower = this.lowercase() prefixes.forEach { - if (lower.startsWith(it.toLowerCase())) { + if (lower.startsWith(it.lowercase())) { value = value.substring(it.length) lower = lower.substring(it.length) } diff --git a/app/src/main/java/org/mozilla/focus/firstrun/FirstrunPagerAdapter.kt b/app/src/main/java/org/mozilla/focus/firstrun/FirstrunPagerAdapter.kt index 39f47eecdb9..b7f86c3c16e 100644 --- a/app/src/main/java/org/mozilla/focus/firstrun/FirstrunPagerAdapter.kt +++ b/app/src/main/java/org/mozilla/focus/firstrun/FirstrunPagerAdapter.kt @@ -68,7 +68,7 @@ class FirstrunPagerAdapter( if (position == pages.size - 1) { buttonView.setText(R.string.firstrun_close_button) buttonView.id = R.id.finish - buttonView.contentDescription = buttonView.text.toString().toLowerCase() + buttonView.contentDescription = buttonView.text.toString().lowercase() } else { buttonView.setText(R.string.firstrun_next_button) buttonView.id = R.id.next diff --git a/app/src/main/java/org/mozilla/focus/settings/ManualAddSearchEngineSettingsFragment.kt b/app/src/main/java/org/mozilla/focus/settings/ManualAddSearchEngineSettingsFragment.kt index f9ba6712339..b472a315ff4 100644 --- a/app/src/main/java/org/mozilla/focus/settings/ManualAddSearchEngineSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/focus/settings/ManualAddSearchEngineSettingsFragment.kt @@ -5,17 +5,25 @@ package org.mozilla.focus.settings import android.net.Uri -import android.os.AsyncTask import android.os.Bundle -import android.os.Handler import android.util.Log +import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater import android.view.MenuItem +import android.view.View import android.view.ViewGroup import android.widget.EditText import androidx.annotation.WorkerThread import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import mozilla.components.concept.fetch.Client import mozilla.components.concept.fetch.Request import mozilla.components.concept.fetch.Request.Redirect.FOLLOW @@ -31,11 +39,11 @@ import org.mozilla.focus.utils.SupportUtils import org.mozilla.focus.utils.UrlUtils import org.mozilla.focus.utils.ViewUtils import java.io.IOException -import java.lang.ref.WeakReference import java.net.MalformedURLException import java.net.URL import java.util.concurrent.TimeUnit +@Suppress("TooManyFunctions") class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { override fun onCreatePreferences(p0: Bundle?, p1: String?) { setHasOptionsMenu(true) @@ -43,13 +51,9 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { addPreferencesFromResource(R.xml.manual_add_search_engine) } - /** - * A reference to an active async task, if applicable, used to manage the task for lifecycle changes. - * See {@link #onPause()} for details. - */ - private var activeAsyncTask: AsyncTask? = null + private var scope: CoroutineScope? = null private var menuItemForActiveAsyncTask: MenuItem? = null - private val handler = Handler() + private var job: Job? = null override fun onResume() { super.onResume() @@ -59,20 +63,7 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { override fun onPause() { super.onPause() - // This is a last minute change and we want to keep the async task management simple: onPause is the - // first required callback for various lifecycle changes: a dialog is shown, the user - // leaves the app, the app rotates, etc. To keep things simple, we do our AsyncTask management here, - // before it gets more complex (e.g. reattaching the AsyncTask to a new fragment). - // - // We cancel the AsyncTask also to keep things simple: if the task is cancelled, it will: - // - Likely end immediately and we don't need to handle it returning after the lifecycle changes - // - Get onPostExecute scheduled on the UI thread, which must run after onPause (since it also runs on - // the UI thread), and we check if the AsyncTask is cancelled there before we perform any other actions. - if (activeAsyncTask == null) return - activeAsyncTask?.cancel(true) setUiIsValidatingAsync(false, menuItemForActiveAsyncTask) - - activeAsyncTask = null menuItemForActiveAsyncTask = null } @@ -105,13 +96,11 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { if (isPartialSuccess) { ViewUtils.hideKeyboard(view) setUiIsValidatingAsync(true, item) - activeAsyncTask = ValidateSearchEngineAsyncTask( - this, - engineName, - searchQuery, - requireComponents.client - ).execute() + menuItemForActiveAsyncTask = item + scope?.launch { + validateSearchEngine(engineName, searchQuery, requireComponents.client) + } } else { TelemetryWrapper.saveCustomSearchEngineEvent(false) } @@ -126,7 +115,17 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { return true } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + scope = CoroutineScope(Dispatchers.IO) + return super.onCreateView(inflater, container, savedInstanceState) + } + override fun onDestroyView() { + scope?.cancel() super.onDestroyView() if (view != null) ViewUtils.hideKeyboard(view) } @@ -137,12 +136,13 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { if (isValidating) { view?.alpha = DISABLED_ALPHA // Delay showing the loading indicator to prevent it flashing on the screen - handler.postDelayed({ + job = scope?.launch { + delay(LOADING_INDICATOR_DELAY) pref?.setProgressViewShown(isValidating) - }, LOADING_INDICATOR_DELAY) + } } else { view?.alpha = 1f - handler.removeCallbacksAndMessages(null) + job?.cancel() pref?.setProgressViewShown(isValidating) } @@ -150,7 +150,7 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { val viewGroup = view as ViewGroup enableAllSubviews(!isValidating, viewGroup) - saveMenuItem!!.isEnabled = !isValidating + saveMenuItem?.isEnabled = !isValidating } private fun enableAllSubviews(shouldEnable: Boolean, viewGroup: ViewGroup) { @@ -207,65 +207,42 @@ class ManualAddSearchEngineSettingsFragment : BaseSettingsFragment() { } } - private class ValidateSearchEngineAsyncTask - constructor ( - fragment: ManualAddSearchEngineSettingsFragment, - private val engineName: String, - private val query: String, - private val client: Client - ) : AsyncTask() { - - private val fragmentWeakReference = WeakReference(fragment) - - override fun doInBackground(vararg p0: Void?): Boolean { - val isValidSearchQuery = isValidSearchQueryURL(client, query) - TelemetryWrapper.saveCustomSearchEngineEvent(isValidSearchQuery) + private suspend fun validateSearchEngine(engineName: String, query: String, client: Client) { + val isValidSearchQuery = isValidSearchQueryURL(client, query) + TelemetryWrapper.saveCustomSearchEngineEvent(isValidSearchQuery) - return isValidSearchQuery - } - - override fun onPostExecute(isValidSearchQuery: Boolean) { - super.onPostExecute(isValidSearchQuery) - if (isCancelled) { - Log.d(LOGTAG, "ValidateSearchEngineAsyncTask has been cancelled") - return - } - - val fragment = fragmentWeakReference.get() - if (fragment == null) { - Log.d(LOGTAG, "Fragment or menu item no longer exists when search query " + - "validation async task returned.") - return + withContext(Dispatchers.Main) { + if (!isActive) { + return@withContext } if (isValidSearchQuery) { - fragment.requireComponents.searchUseCases.addSearchEngine( + requireComponents.searchUseCases.addSearchEngine( createSearchEngine( engineName, query.toSearchUrl(), - IconGenerator.generateSearchEngineIcon(fragment.requireContext()) + IconGenerator.generateSearchEngineIcon(requireContext()) ) ) - Snackbar.make(fragment.requireView(), R.string.search_add_confirmation, Snackbar.LENGTH_SHORT).show() - Settings.getInstance(fragment.requireActivity()).setDefaultSearchEngineByName(engineName) + Snackbar.make(requireView(), R.string.search_add_confirmation, Snackbar.LENGTH_SHORT).show() + Settings.getInstance(requireActivity()).setDefaultSearchEngineByName(engineName) - fragment.requireComponents.appStore.dispatch( - AppAction.NavigateUp(fragment.requireComponents.store.state.selectedTabId) + requireComponents.appStore.dispatch( + AppAction.NavigateUp(requireComponents.store.state.selectedTabId) ) } else { - showServerError(fragment) + showServerError() } - fragment.setUiIsValidatingAsync(false, fragment.menuItemForActiveAsyncTask) - fragment.activeAsyncTask = null - fragment.menuItemForActiveAsyncTask = null + setUiIsValidatingAsync(false, menuItemForActiveAsyncTask) + menuItemForActiveAsyncTask = null } + } - private fun showServerError(that: ManualAddSearchEngineSettingsFragment) { - val pref = that.findManualAddSearchEnginePreference(R.string.pref_key_manual_add_search_engine) - pref?.setSearchQueryErrorText(that.getString(R.string.error_hostLookup_title)) - } + private fun showServerError() { + val pref = findManualAddSearchEnginePreference(R.string.pref_key_manual_add_search_engine) + pref?.setSearchQueryErrorText(getString(R.string.error_hostLookup_title)) } } diff --git a/app/src/main/java/org/mozilla/focus/shortcut/IconGenerator.kt b/app/src/main/java/org/mozilla/focus/shortcut/IconGenerator.kt index 20b73fcef89..e7548373c80 100644 --- a/app/src/main/java/org/mozilla/focus/shortcut/IconGenerator.kt +++ b/app/src/main/java/org/mozilla/focus/shortcut/IconGenerator.kt @@ -126,7 +126,7 @@ class IconGenerator { */ @JvmStatic fun getRepresentativeCharacter(url: String?): Char { - val firstChar = getRepresentativeSnippet(url)?.find { it.isLetterOrDigit() }?.toUpperCase() + val firstChar = getRepresentativeSnippet(url)?.find { it.isLetterOrDigit() }?.uppercaseChar() return (firstChar ?: DEFAULT_ICON_CHAR) } diff --git a/app/src/test/java/org/mozilla/focus/searchsuggestions/SearchSuggestionsViewModelTest.kt b/app/src/test/java/org/mozilla/focus/searchsuggestions/SearchSuggestionsViewModelTest.kt index 5d4f52c86ad..46fdea59c90 100644 --- a/app/src/test/java/org/mozilla/focus/searchsuggestions/SearchSuggestionsViewModelTest.kt +++ b/app/src/test/java/org/mozilla/focus/searchsuggestions/SearchSuggestionsViewModelTest.kt @@ -33,7 +33,7 @@ class SearchSuggestionsViewModelTest { fun setup() { lifecycle = LifecycleRegistry(mock(LifecycleOwner::class.java)) lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) - MockitoAnnotations.openMocks(this) + MockitoAnnotations.initMocks(this) viewModel = SearchSuggestionsViewModel(ApplicationProvider.getApplicationContext()) } diff --git a/build.gradle b/build.gradle index 92f3b841b08..9fb84ada5a1 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,6 @@ buildscript { ext.espresso_version = '3.1.0-alpha4' - ext.kotlin_version = '1.4.30' ext.coroutines_version = '1.4.2' ext.jna_version = "5.6.0" // Pinning the last working version of the service-telemetry component until we decide @@ -22,8 +21,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath Dependencies.android_gradle_plugin + classpath Dependencies.kotlin_gradle_plugin classpath "org.mozilla.components:tooling-glean-gradle:${AndroidComponents.VERSION}" // NOTE: Do not place your application dependencies here; they belong diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 029b690452d..0827c9c8a79 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ plugins { - id "org.gradle.kotlin.kotlin-dsl" version "1.3.6" + id "org.gradle.kotlin.kotlin-dsl" version "2.1.4" } repositories { diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 7c015a65f0b..9be8bb62d73 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -3,12 +3,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ object Versions { + const val compose_version = "1.0.0-rc02" + object AndroidX { + const val activity_compose = "1.3.0-rc02" const val annotation = "1.1.0" const val appcompat = "1.3.0" const val arch = "2.1.0" const val browser = "1.3.0" const val core = "1.3.2" + const val compose = compose_version const val cardview = "1.0.0" const val recyclerview = "1.2.0" const val palette = "1.0.0" @@ -19,6 +23,21 @@ object Versions { object Google { const val material = "1.2.1" } + + object Kotlin { + const val version = "1.5.10" + const val coroutines = "1.5.0" + } + + object Gradle { + const val kotlin_plugin = Kotlin.version + const val android_plugin = "7.0.0-rc01" + } + + object Test { + const val robolectric = "4.6.1" + const val mockito = "2.24.5" + } } object Dependencies { @@ -27,6 +46,12 @@ object Dependencies { const val androidx_appcompat = "androidx.appcompat:appcompat:${Versions.AndroidX.appcompat}" const val androidx_browser = "androidx.browser:browser:${Versions.AndroidX.browser}" const val androidx_cardview = "androidx.cardview:cardview:${Versions.AndroidX.cardview}" + const val androidx_compose_ui = "androidx.compose.ui:ui:${Versions.AndroidX.compose}" + const val androidx_compose_ui_test = "androidx.compose.ui:ui-test-junit4:${Versions.AndroidX.compose}" + const val androidx_compose_ui_test_manifest = "androidx.compose.ui:ui-test-manifest:${Versions.AndroidX.compose}" + const val androidx_compose_ui_tooling = "androidx.compose.ui:ui-tooling:${Versions.AndroidX.compose}" + const val androidx_compose_foundation = "androidx.compose.foundation:foundation:${Versions.AndroidX.compose}" + const val androidx_compose_material = "androidx.compose.material:material:${Versions.AndroidX.compose}" const val androidx_core_ktx = "androidx.core:core-ktx:${Versions.AndroidX.core}" const val androidx_palette = "androidx.palette:palette-ktx:${Versions.AndroidX.palette}" const val androidx_preferences = "androidx.preference:preference-ktx:${Versions.AndroidX.preferences}" @@ -34,4 +59,14 @@ object Dependencies { const val androidx_lifecycle_extensions = "androidx.lifecycle:lifecycle-extensions:${Versions.AndroidX.lifecycle}" const val google_material = "com.google.android.material:material:${Versions.Google.material}" + + const val kotlin_gradle_plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Gradle.kotlin_plugin}" + const val android_gradle_plugin = "com.android.tools.build:gradle:${Versions.Gradle.android_plugin}" + + const val kotlin_stdlib = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.Kotlin.version}" + const val kotlin_coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Kotlin.coroutines}" + const val kotlin_coroutines_android = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.Kotlin.coroutines}" + + const val testing_robolectric = "org.robolectric:robolectric:${Versions.Test.robolectric}" + const val testing_mockito = "org.mockito:mockito-core:${Versions.Test.mockito}" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2ef9ac8a461..65beeeea69e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip diff --git a/service-telemetry/build.gradle b/service-telemetry/build.gradle index 78f4226e31a..b40eb734696 100644 --- a/service-telemetry/build.gradle +++ b/service-telemetry/build.gradle @@ -6,11 +6,11 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 29 + compileSdkVersion 30 defaultConfig { minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 30 } buildTypes { @@ -34,11 +34,11 @@ dependencies { implementation Dependencies.androidx_annotation - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation Dependencies.kotlin_stdlib testImplementation "junit:junit:4.12" - testImplementation "org.robolectric:robolectric:4.4" // required to support api level 28 - testImplementation 'org.mockito:mockito-core:2.24.5' + testImplementation Dependencies.testing_robolectric + testImplementation Dependencies.testing_mockito testImplementation 'com.squareup.okhttp3:mockwebserver:3.11.0' diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 44a02de26f9..6fcaed0eb76 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -13,13 +13,15 @@ MAINTAINER Sebastian Kaspari "skaspari@mozilla.com" ENV GRADLE_OPTS='-Xmx4096m -Dorg.gradle.daemon=false' \ LANG='en_US.UTF-8' \ - TERM='dumb' + TERM='dumb' \ + JAVA8PATH="/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/:$PATH" RUN apt-get update -qq \ # We need to install tzdata before all of the other packages. Otherwise it will show an interactive dialog # which we cannot navigate while building the Docker image. && apt-get install -y tzdata \ && apt-get install -y openjdk-8-jdk \ + openjdk-11-jdk \ expect \ git \ curl \ @@ -46,7 +48,7 @@ RUN cd /opt && curl --location --retry 5 --output android-sdk.zip https://dl.goo ENV ANDROID_SDK_HOME /opt/android-sdk-linux ENV ANDROID_HOME /opt/android-sdk-linux -RUN yes | "${ANDROID_SDK_HOME}/tools/bin/sdkmanager" --licenses +RUN yes | PATH=$JAVA8PATH "${ANDROID_SDK_HOME}/tools/bin/sdkmanager" --licenses # -- Project setup ---------------------------------------------------------------------- diff --git a/tools/taskcluster/lib/tasks.py b/tools/taskcluster/lib/tasks.py index 3cc4f7cbd6a..641f611492e 100644 --- a/tools/taskcluster/lib/tasks.py +++ b/tools/taskcluster/lib/tasks.py @@ -45,7 +45,7 @@ def build_task(self, name, description, command, dependencies = [], artifacts = "payload": { "features": features, "maxRunTime": 7200, - "image": "mozillamobile/focus-android:1.6", + "image": "mozillamobile/focus-android:1.7", "command": [ "/bin/bash", "--login", diff --git a/tools/taskcluster/schedule-main-build.py b/tools/taskcluster/schedule-main-build.py index 8fe8450044e..93a77d60c0d 100644 --- a/tools/taskcluster/schedule-main-build.py +++ b/tools/taskcluster/schedule-main-build.py @@ -113,7 +113,7 @@ def generate_task(name, description, command, dependencies=[], artifacts={}, sco "taskclusterProxy": True }, "maxRunTime": 7200, - "image": "mozillamobile/focus-android:1.6", + "image": "mozillamobile/focus-android:1.7", "command": [ "/bin/bash", "--login",