From c1fc163a353b56c11a67766c36d5e984763468ff Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 27 Jun 2019 09:39:58 +0200 Subject: [PATCH 01/57] Build scripts refactoring (#121) * Initial buildSrc support * buildSrc: remove versioning and flavor related BuildConfig fields * Removing scripts/CliqzConfig.gradle * Cleaning up settings.gradle * Setup Sentry for crash reporting * Incremental builds * Ignoring cliqz-config.json * Kotlin support, moving all the keys/tokens to cliqz-config.json * cliqz-config.json is optional, warning if missing --- .gitignore | 1 + app/build.gradle | 53 +----- app/cliqz-config.json | 19 --- .../com/cliqz/browser/app/BrowserApp.java | 20 ++- .../purchases/trial/TrialPeriodRemoteRepo.kt | 4 +- buildSrc/build.gradle | 24 +++ .../java/com/cliqz/gradle/CliqzConfigTask.kt | 139 ++++++++++++++++ .../main/java/com/cliqz/gradle/CliqzPlugin.kt | 75 +++++++++ scripts/CliqzConfig.gradle | 155 ------------------ settings.gradle | 4 +- 10 files changed, 264 insertions(+), 230 deletions(-) delete mode 100644 app/cliqz-config.json create mode 100644 buildSrc/build.gradle create mode 100644 buildSrc/src/main/java/com/cliqz/gradle/CliqzConfigTask.kt create mode 100644 buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt delete mode 100644 scripts/CliqzConfig.gradle diff --git a/.gitignore b/.gitignore index bea9a2955..0e88695d1 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,4 @@ app/src/main/assets/jsengine.bundle.js node_modules/ yarn.lock app/google-services.json +app/cliqz-config.json diff --git a/app/build.gradle b/app/build.gradle index 60128206f..d31f0219e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,6 @@ apply plugin: 'kotlin-kapt' apply plugin: 'com.github.triplet.play' apply plugin: 'com.getkeepsafe.dexcount' -apply from: '../scripts/CliqzConfig.gradle' apply from: 'cliqz.gradle' def useGoogleServices = System.getenv("DISABLE_GOOGLE_SERVICES") == null @@ -25,22 +24,7 @@ android { buildConfigField 'String', 'LIGHTNING_VERSION_NAME', '"4.2.3.1"' buildConfigField "int", "MINIMUM_WEBVIEW_VERSION", "55" buildConfigField 'int', "VISIBLE_TOP_SITES", '4' - - def vpnApiKey = this.hasProperty("com.cliqz.lumen.vpnApiKey") ? - this.getProperty("com.cliqz.lumen.vpnApiKey") : System.getenv("VPN_API_KEY") - if (vpnApiKey) { - buildConfigField 'String', 'VPN_API_KEY', "\"${vpnApiKey}\"" - } else { - buildConfigField 'String', 'VPN_API_KEY', '""' - } - - def revenueCatApiKey = this.hasProperty("com.cliqz.lumen.revenueCatApiKey") ? - this.getProperty("com.cliqz.lumen.revenueCatApiKey") : System.getenv("REVENUECAT_API_KEY") - if (revenueCatApiKey) { - buildConfigField 'String', 'REVENUECAT_API_KEY', "\"${revenueCatApiKey}\"" - } else { - buildConfigField 'String', 'REVENUECAT_API_KEY', '""' - } + applicationId "com.cliqz.browser" testInstrumentationRunner "com.cliqz.browser.test.CustomTestRunner" vectorDrawables.useSupportLibrary = true @@ -124,15 +108,6 @@ android { universalApk true } } - - productFlavors.properties.names.each { name -> - defaultConfig { - def upperName = name.toUpperCase() - buildConfigField 'String', "FLAVOR_${upperName}", "\"${name}\"" - buildConfigField 'boolean', "IS_${upperName}", "FLAVOR.equals(FLAVOR_${upperName})" - buildConfigField 'boolean', "IS_NOT_${upperName}", "!IS_${upperName}" - } - } } dexcount { @@ -157,15 +132,10 @@ configurations.all { details.useTarget group: details.requested.group, name: 'android-jsc-intl', version: 'r236355' } } + force "com.google.code.findbugs:jsr305:3.0.0" } } -configurations.all { - resolutionStrategy { - force "com.google.code.findbugs:jsr305:3.0.0" - } -} - dependencies { // support libraries @@ -260,6 +230,8 @@ dependencies { androidTestImplementation 'com.google.dexmaker:dexmaker:1.2' androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' + // Sentry + implementation 'io.sentry:sentry-android:1.7.21' // Forcing version androidTestImplementation 'androidx.annotation:annotation:1.0.0' androidTestImplementation 'androidx.test:runner:1.1.0' @@ -271,24 +243,11 @@ dependencies { testImplementation 'org.apache.velocity:velocity:1.7' } -def abiCodes = ["armeabi-v7a": 2, "arm64-v8a": 4, "x86": 6, "x86_64": 8] -import com.android.build.OutputFile - -preBuild.doLast { - android.applicationVariants.each { variant -> - def apiVersion = variant.productFlavors.get(0).versionCode - // set the composite code - variant.outputs.each { output -> - def abiVersion = abiCodes.get(output.getFilter(OutputFile.ABI)) ?: 1 - def generatedVersionCode = android.defaultConfig.versionCode * 100 + apiVersion * 10 + abiVersion - output.versionCodeOverride = generatedVersionCode - } - } -} - play { track = 'alpha' } if (useGoogleServices) { apply plugin: 'com.google.gms.google-services' } + +apply plugin: com.cliqz.gradle.CliqzPlugin \ No newline at end of file diff --git a/app/cliqz-config.json b/app/cliqz-config.json deleted file mode 100644 index 3b5c18728..000000000 --- a/app/cliqz-config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - ".default": { - "amazonApplicationARN": "arn:aws:sns:us-east-1:141047255820:app/GCM/CLIQZ_Browser_for_Android", - "amazonSnsTopics": [ "arn:aws:sns:us-east-1:141047255820:mobile_news" ], - "amazonAccountID": "141047255820", - "amazonIdentityPoolID": "us-east-1:68bb8256-a533-4b93-b744-423518ef0f02", - "amazonUnauthRoleARN": "arn:aws:iam::141047255820:role/Cognito_CLIQZ_browser_androidUnauth_Role", - "amazonAuthRoleARN": "arn:aws:iam::141047255820:role/Cognito_CLIQZ_browser_androidAuth_Role" - }, - "debug": { - "amazonSnsTopics": [ "arn:aws:sns:us-east-1:141047255820:mobile_news_staging" ] - }, - "o2": { - "amazonSnsTopics": ["arn:aws:sns:us-east-1:141047255820:o2_android_browser"] - }, - "lookback": { - "lookbackSdkToken": "HWiD4ErSbeNy9JcRg" - } -} diff --git a/app/src/lumen/java/com/cliqz/browser/app/BrowserApp.java b/app/src/lumen/java/com/cliqz/browser/app/BrowserApp.java index c3ae68843..2da52195b 100644 --- a/app/src/lumen/java/com/cliqz/browser/app/BrowserApp.java +++ b/app/src/lumen/java/com/cliqz/browser/app/BrowserApp.java @@ -1,13 +1,15 @@ package com.cliqz.browser.app; import com.cliqz.browser.BuildConfig; +import com.cliqz.browser.CliqzConfig; import com.cliqz.browser.purchases.PurchasesManager; import com.revenuecat.purchases.Purchases; +import de.blinkt.openvpn.core.StatusListener; +import io.sentry.Sentry; +import io.sentry.android.AndroidSentryClientFactory; import javax.inject.Inject; -import de.blinkt.openvpn.core.StatusListener; - /** * @author Ravjit Uppal */ @@ -20,17 +22,25 @@ public class BrowserApp extends BaseBrowserApp { public void init() { final StatusListener mStatus = new StatusListener(); mStatus.init(getApplicationContext()); - + setupCrashReporting(); getAppComponent().inject(this); setupSubscriptionSDK(); } + private void setupCrashReporting() { + //noinspection ConstantConditions + if (!CliqzConfig.SENTRY_TOKEN.isEmpty()) { + Sentry.init(CliqzConfig.SENTRY_TOKEN, new AndroidSentryClientFactory(this)); + } + } + private void setupSubscriptionSDK() { //noinspection ConstantConditions - if (!BuildConfig.REVENUECAT_API_KEY.isEmpty()) { + if (!CliqzConfig.REVENUECAT_API_KEY.isEmpty()) { Purchases.setDebugLogsEnabled(BuildConfig.DEBUG); - Purchases.configure(this, BuildConfig.REVENUECAT_API_KEY); + Purchases.configure(this, CliqzConfig.REVENUECAT_API_KEY); purchasesManager.checkPurchases(); } } + } diff --git a/app/src/lumen/java/com/cliqz/browser/purchases/trial/TrialPeriodRemoteRepo.kt b/app/src/lumen/java/com/cliqz/browser/purchases/trial/TrialPeriodRemoteRepo.kt index f29d9b95e..43b91effa 100644 --- a/app/src/lumen/java/com/cliqz/browser/purchases/trial/TrialPeriodRemoteRepo.kt +++ b/app/src/lumen/java/com/cliqz/browser/purchases/trial/TrialPeriodRemoteRepo.kt @@ -5,8 +5,8 @@ import android.content.Context import android.net.Uri import android.os.AsyncTask import android.provider.Settings +import com.cliqz.browser.CliqzConfig import android.util.Log -import com.cliqz.browser.BuildConfig import com.cliqz.browser.utils.HttpHandler import com.revenuecat.purchases.Purchases import de.blinkt.openvpn.ConfigConverter @@ -23,7 +23,7 @@ private val TAG = TrialPeriodRemoteRepo::class.java.simpleName private const val CONTENT_TYPE_JSON = "application/json" private val LUMEN_CREDENTIAL_URL = URL("https://auth-staging.lumenbrowser.com/get_credentials") -private val HEADERS = mapOf("x-api-key" to BuildConfig.VPN_API_KEY) +private val HEADERS = mapOf("x-api-key" to CliqzConfig.VPN_API_KEY) class TrialPeriodRemoteRepo(private val context: Context) { diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 000000000..91be46e16 --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,24 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.3.31' +} +repositories { + mavenCentral() + google() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + implementation "com.android.tools.build:gradle:3.4.1" +} + +compileKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} + +compileTestKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} \ No newline at end of file diff --git a/buildSrc/src/main/java/com/cliqz/gradle/CliqzConfigTask.kt b/buildSrc/src/main/java/com/cliqz/gradle/CliqzConfigTask.kt new file mode 100644 index 000000000..b1c961289 --- /dev/null +++ b/buildSrc/src/main/java/com/cliqz/gradle/CliqzConfigTask.kt @@ -0,0 +1,139 @@ +package com.cliqz.gradle + +import com.android.build.gradle.tasks.GenerateBuildConfig +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.squareup.javawriter.JavaWriter +import org.gradle.api.DefaultTask +import org.gradle.api.logging.Logger +import org.gradle.api.tasks.* +import org.gradle.api.tasks.Optional +import java.io.File +import java.io.FileReader +import java.io.FileWriter +import java.util.* +import javax.inject.Inject +import javax.lang.model.element.Modifier +import kotlin.reflect.KMutableProperty1 +import kotlin.reflect.full.declaredMemberProperties + +open class CliqzConfigTask @Inject constructor( + val buildConfigProvider: TaskProvider, + val flavorNames: Set) : DefaultTask() { + + val inputFile: File? by lazy { + val inFile = project.file(CLIQZ_CONFIG_JSON) + if (inFile.isFile) inFile else null + } + @Optional @InputFile get + + private val buildConfigTask: GenerateBuildConfig by lazy { buildConfigProvider.get() } + private val packageName: String by lazy { buildConfigTask.buildConfigPackageName } + + val outputDirectory: File by lazy { + File(buildConfigTask.sourceOutputDir, packageName.replace('.', File.separatorChar)) + } + @OutputDirectory get + + val outputFile: File by lazy { + File(outputDirectory, "CliqzConfig.java") + } + @OutputFile get + + @TaskAction + fun generateCliqzConfig() { + // Read the json file + val type = MapTypeToken().type + val config = if (inputFile == null) { + logger.warn("Missing $CLIQZ_CONFIG_JSON") + Config() + } else FileReader(inputFile).use { + val configs = Gson().fromJson>(it, type) + val defaultConfig = configs[DEFAULT_CONFIG_KEY] ?: Config() + val mergedConfig = configs.filter { (key, _) -> + flavorNames.contains(key) + }.values.fold(Config()) { result, other -> + result.merge(other, logger) + } + defaultConfig.merge(mergedConfig) + return@use defaultConfig + } + + FileWriter(outputFile).use { writer -> + val javaWriter = JavaWriter(writer) + javaWriter.emitJavadoc("Auto generated, do not edit") + .emitPackage(packageName) + .beginType("CliqzConfig", "class", EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)) + Config::class.declaredMemberProperties.forEach { property -> + val allCapsKey = property.name.replace(Regex("([A-Z]+)"), "_\$1").toUpperCase() + val value = property.get(config) + when (value) { + is String -> javaWriter.emitField( + "String", + allCapsKey, + EnumSet.of(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC), + "\"${property.get(config)}\"") + is List<*> -> javaWriter.emitField( + "String[]", + allCapsKey, + EnumSet.of(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC), + value.joinToString(prefix = "new String[] {", postfix = "}", transform = { "\"$it\""}) + ) + } + } + javaWriter.endType() + } + } + + + companion object { + private const val CLIQZ_CONFIG_JSON = "cliqz-config.json" + private const val DEFAULT_CONFIG_KEY = ".default" + } +} +private class MapTypeToken: TypeToken>() + +// All the properties are only used via reflection, so they are "unused" +@Suppress("unused") +class Config { + var amazonAccountID = "" + var amazonAuthRoleARN = "" + var amazonUnauthRoleARN = "" + var amazonIdentityPoolID = "" + var amazonApplicationARN = "" + var amazonSnsTopics = mutableListOf() + var vpnApiKey = "" + var revenuecatApiKey = "" + var sentryToken = "" + + @Suppress("UNCHECKED_CAST") + fun merge(other: Config, logger: Logger? = null): Config { + Config::class.declaredMemberProperties.forEach { member -> + when (member.returnType.classifier) { + String::class -> mergeStringProperty(logger, other, member as KMutableProperty1) + MutableList::class -> mergeListProperty(other, member as KMutableProperty1>) + else -> logger?.error("Can't merge property ${member.name}") + } + } + return this + } + + private fun mergeListProperty(other: Config, property: KMutableProperty1>) { + val topics = property.get(this).toMutableSet() + topics.addAll(property.get(other)) + property.set(this, topics.toMutableList()) + } + + private fun mergeStringProperty(logger: Logger?, other: Config, property: KMutableProperty1) { + val v1 = property.get(this) + val v2 = property.get(other) + if (v1.isNotEmpty() && v2.isNotEmpty()) { + logger?.warn("Duplicated property ${property.name}") + } + if (v2.isNotEmpty()) { + property.set(this, v2) + } + } + +} + diff --git a/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt b/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt new file mode 100644 index 000000000..9ec1a77cc --- /dev/null +++ b/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt @@ -0,0 +1,75 @@ +package com.cliqz.gradle + +import com.android.build.OutputFile +import com.android.build.gradle.AppExtension +import com.android.build.gradle.api.ApkVariantOutput +import com.android.build.gradle.api.ApplicationVariant +import org.gradle.api.Plugin +import org.gradle.api.Project + +@Suppress("unused") +class CliqzPlugin: Plugin { + override fun apply(project: Project) { + // TODO: Can this be moved to afterEvaluate too? + val android = project.property("android") as AppExtension + android.productFlavors.names.forEach { + android.defaultConfig.apply { + val upperName = it.toUpperCase() + buildConfigField("String", "FLAVOR_$upperName", "\"$it\"") + buildConfigField("boolean", "IS_$upperName", "FLAVOR.equals(FLAVOR_$upperName)") + buildConfigField("boolean", "IS_NOT_$upperName", "!IS_$upperName") + } + } + + val defaultVersionCode = android.defaultConfig.versionCode + project.afterEvaluate { + android.applicationVariants.forEach { variant -> + setVersionCode(defaultVersionCode, variant) + createCliqzConfigTasks(project, variant) + } + } + } + + private fun createCliqzConfigTasks(project: Project, variant: ApplicationVariant) { + val buildConfigProvider = variant.generateBuildConfigProvider + val javaCompileProvider = variant.javaCompileProvider + // val sourceOutdir = buildConfig.sourceOutputDir + val taskName = "generate${variant.name.capitalize()}CliqzConfig" + // val packageName = buildConfig.buildConfigPackageName + val builtType = variant.buildType.name + // This generate possible config names to look for in the json + val flavorNames = variant.productFlavors.fold(emptySet()) { acc, productFlavor -> + acc + (listOf(productFlavor.name, "${productFlavor.name}${builtType.capitalize()}", builtType)) + } + + val taskProvider = project.tasks.register(taskName, CliqzConfigTask::class.java, buildConfigProvider, flavorNames) + taskProvider.configure { + it.dependsOn(buildConfigProvider) + } + project.tasks.named("compile${variant.name.capitalize()}Kotlin").configure { + it.dependsOn(taskProvider) + } + javaCompileProvider.configure { + it.dependsOn(taskProvider) + } + } + + private fun setVersionCode(defaultVersionCode: Int, variant: ApplicationVariant) { + val apiVersion = variant.productFlavors[0].versionCode + variant.outputs.forEach { output -> + val abi = output.filters.find { it.filterType == OutputFile.ABI } + abi?.let { + val abiVersion = ABI_CODES[it.identifier] + (output as ApkVariantOutput).versionCodeOverride = + defaultVersionCode * 100 + apiVersion * 10 + abiVersion!! + } + } + } + + + + companion object { + private val ABI_CODES = mapOf( + "armeabi-v7a" to 2, "arm64-v8a" to 4, "x86" to 6, "x86_64" to 8) + } +} \ No newline at end of file diff --git a/scripts/CliqzConfig.gradle b/scripts/CliqzConfig.gradle deleted file mode 100644 index 65c9e816b..000000000 --- a/scripts/CliqzConfig.gradle +++ /dev/null @@ -1,155 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' - } -} - - -import com.squareup.javawriter.JavaWriter -import groovy.json.JsonSlurper -import javax.lang.model.element.Modifier - -apply plugin: CliqzPlugin - -/** - * Add a custom task to generate CLIQZ specific configuration file - * Example structure for the config file:
- *
- * {
- *   ".default": {
- *     "amazonSnsTopics": [ "default_topic_arn" ],
- *     "amazonApplicationARN": "...",
- *     "amazonAccountID": "...",
- *     "amazonIdentityPoolID": "...",
- *     "amazonUnauthRoleARN": "...",
- *     "amazonAuthRoleARN": "..."
- *   },
- *   "demo": {
- *     "amazonAccountID": "...",
- *     "amazonSnsTopics": [ "demo_topic_arn" ]
- *   },
- *   "full": {
- *     "amazonSnsTopics": [ "full_topic_arn" ]
- *   },
- *   "demoDebug": {
- *     ...
- *   },
- *   "demoRelease": {
- *     ...
- *   }
- * }
- * 
- */ -class CliqzPlugin implements Plugin { - - final static String CLIQZ_CONFIG_FILENAME = "CliqzConfig.java" - final def configModifier = EnumSet.of(Modifier.FINAL, Modifier.PUBLIC,Modifier.STATIC) - final static String CLIQZ_CONFIG_JSON = "cliqz-config.json" - def logger - - void apply(Project project) { - if (!project.plugins.hasPlugin('com.android.application')) { - throw new IllegalArgumentException('Not an android app') - } - logger = project.logger - File configFile = project.file(CLIQZ_CONFIG_JSON) - if (!configFile.isFile()) { - logger.warn("Missing configuration file: ${configFile}") - return - } - - JsonSlurper slurper = new JsonSlurper(); - def config = slurper.parse(configFile) - project.afterEvaluate { - project.android.applicationVariants.each { variant -> - def buildConfig = variant.generateBuildConfigProvider.get() - def compileProvider = variant.javaCompileProvider - File sourceOutDir = buildConfig.sourceOutputDir - String packageName = buildConfig.getBuildConfigPackageName() - String taskName = buildConfig.name.replace('BuildConfig', 'CliqzConfig') - def buildType = variant.buildType.name - def flavorNames = variant.productFlavors.inject(new TreeSet()) { acc, value -> - acc += [ value.name as String, "${value.name}${buildType.capitalize()}" as String, buildType as String ] - acc - } - def variantConfig = config.findAll { flavorNames.contains(it.key) || it.key == '.default' } - - Task task = buildTask(project, taskName, variantConfig, packageName, sourceOutDir) - task.mustRunAfter(buildConfig) - compileProvider.get().dependsOn(task) - } - } - } - - - Task buildTask(Project project, String taskName, Map config, String packageName, File dstDir) { - project.task(taskName) { - doLast { - def cfg = mergeConfig(config) - File packageOutDir = new File(dstDir, packageName.replace('.' as char, File.separatorChar)) - def outFile = new File(packageOutDir, CLIQZ_CONFIG_FILENAME) - outFile.withWriter { writer -> - JavaWriter javaWriter = new JavaWriter(writer) - javaWriter.emitJavadoc('Auto generated, do not edit') - .emitPackage(packageName) - .beginType('CliqzConfig', 'class', EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)) - - cfg.each { - def ALLCAPS_KEY = it.key.replaceAll("([A-Z]+)", "_\$1").toUpperCase() - if (it.key == 'amazonSnsTopics') { - javaWriter.emitField('String[]', ALLCAPS_KEY, configModifier, "new String[] {${it.value.join(',')}}") - } else { - javaWriter.emitField('String', ALLCAPS_KEY, configModifier, it.value ? "\"${it.value}\"": 'null') - } - } - javaWriter.endType() - } - } - } - } - - Object mergeConfig(Map config) { - def result = [ - amazonAccountID:null, - amazonAuthRoleARN:null, - amazonUnauthRoleARN:null, - amazonIdentityPoolID:null, - amazonApplicationARN:null, - lookbackSdkToken:null - ] - def defaultConfig = config['.default'] - config.remove('.default') - result.each { result[it.key] = mergeKey(config, defaultConfig, it.key) } - result['amazonSnsTopics'] = mergeTopics(config, defaultConfig) - result - } - - List mergeTopics(Map config, Map defaultConfig) { - def topics = config.inject(new TreeSet()) { acc, it -> - def entries = it.value['amazonSnsTopics'] - if (entries) { - acc += entries.collect { value -> "\"${value}\""} - } - acc - } - if (defaultConfig?.get('amazonSnsTopics')) { - topics += defaultConfig?.get('amazonSnsTopics')?.collect { "\"${it}\"" } - } - topics.toList() - } - - String mergeKey(Map config, Map defaultConfig, String key) { - def result = config.inject(null) { result, val -> - if (result != null) { - logger.warn("Multiple ${key}") - } - result = val.value[key] - result - } - result ? result : defaultConfig?.get(key) - } -} diff --git a/settings.gradle b/settings.gradle index db534a493..46c7e2771 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -include ':app', ':oss', ':utils', ':android_utils', ':testdroid' +include ':app', ':utils', ':android_utils', ':testdroid' include ':react-native-fs' project(':react-native-fs').projectDir = new File(settingsDir, 'node_modules/react-native-fs/android') @@ -16,4 +16,4 @@ include ':react-native-share' project(':react-native-share').projectDir = new File(settingsDir, 'node_modules/react-native-share/android') include ':react-native-user-agent-react-native-user-agent' -project(':react-native-user-agent-react-native-user-agent').projectDir = new File(settingsDir, 'node_modules/react-native-user-agent/android') \ No newline at end of file +project(':react-native-user-agent-react-native-user-agent').projectDir = new File(settingsDir, 'node_modules/react-native-user-agent/android') From 73baef24b8ca79f077e690dc69db79b8f881cb28 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 27 Jun 2019 17:44:13 +0200 Subject: [PATCH 02/57] AP-274 lock icon in the title bar (#129) --- .../java/com/cliqz/utils/ResourcesUtils.java | 28 -------- .../cliqz/res/layout/search_bar_widget.xml | 11 +++- app/src/cliqz/res/values/colors.xml | 2 + .../res/layout/fragment_search_toolbar.xml | 4 +- .../lumen/res/layout/search_bar_widget.xml | 19 ++++-- .../com/cliqz/browser/main/TabFragment.java | 10 ++- .../com/cliqz/browser/widget/SearchBar.java | 64 +++++++++++++------ app/src/main/res/drawable/ic_lock_black.xml | 9 +++ app/src/main/res/values/dimens.xml | 2 +- 9 files changed, 94 insertions(+), 55 deletions(-) delete mode 100644 android_utils/src/main/java/com/cliqz/utils/ResourcesUtils.java create mode 100644 app/src/main/res/drawable/ic_lock_black.xml diff --git a/android_utils/src/main/java/com/cliqz/utils/ResourcesUtils.java b/android_utils/src/main/java/com/cliqz/utils/ResourcesUtils.java deleted file mode 100644 index 0772f52d9..000000000 --- a/android_utils/src/main/java/com/cliqz/utils/ResourcesUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.cliqz.utils; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.os.Build; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -/** - * @author Stefano Pacifici - * @date 2016/09/13 - */ -public final class ResourcesUtils { - - private ResourcesUtils() {} // No instances - - public static Drawable getDrawable(@NonNull Context context, @DrawableRes int drawable, - @Nullable Resources.Theme theme) { - final Resources resources = context.getResources(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - return resources.getDrawable(drawable, theme); - } else { - return resources.getDrawable(drawable); - } - } -} diff --git a/app/src/cliqz/res/layout/search_bar_widget.xml b/app/src/cliqz/res/layout/search_bar_widget.xml index 3c7e4b324..8d97de27f 100644 --- a/app/src/cliqz/res/layout/search_bar_widget.xml +++ b/app/src/cliqz/res/layout/search_bar_widget.xml @@ -5,8 +5,18 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:background="@drawable/searchbar_background" + android:gravity="center_vertical" android:orientation="horizontal"> + + diff --git a/app/src/cliqz/res/values/colors.xml b/app/src/cliqz/res/values/colors.xml index 711e25567..a9aec6a50 100644 --- a/app/src/cliqz/res/values/colors.xml +++ b/app/src/cliqz/res/values/colors.xml @@ -76,4 +76,6 @@ #CFFF #E7ECEE #2B5993 + + @color/primary_color diff --git a/app/src/lumen/res/layout/fragment_search_toolbar.xml b/app/src/lumen/res/layout/fragment_search_toolbar.xml index ae8db12c1..8c642c869 100644 --- a/app/src/lumen/res/layout/fragment_search_toolbar.xml +++ b/app/src/lumen/res/layout/fragment_search_toolbar.xml @@ -17,8 +17,8 @@ android:layout_height="wrap_content" tools:layout_height="30dp" tools:background="@color/white" - android:paddingLeft="@dimen/toolbar_padding" - android:paddingRight="@dimen/toolbar_padding" + android:layout_marginStart="@dimen/toolbar_padding" + android:layout_marginEnd="@dimen/toolbar_padding" android:layout_weight="1"/> - + tools:background="@color/gray_dark"> + + - + diff --git a/app/src/main/java/com/cliqz/browser/main/TabFragment.java b/app/src/main/java/com/cliqz/browser/main/TabFragment.java index b48b236be..8f05dca32 100644 --- a/app/src/main/java/com/cliqz/browser/main/TabFragment.java +++ b/app/src/main/java/com/cliqz/browser/main/TabFragment.java @@ -741,6 +741,7 @@ public void updateUrl(BrowserEvents.UpdateUrl event) { if (url != null && !url.isEmpty() && !url.contains(TrampolineConstants.TRAMPOLINE_COMMAND_PARAM_NAME)) { state.setUrl(url); searchBar.setTitle(url); + searchBar.setSecure(isHttpsUrl(url)); } } @@ -748,7 +749,9 @@ private void bringWebViewToFront(Animation animation) { final WebView webView = mLightningView.getWebView(); searchBar.showTitleBar(); searchBar.showProgressBar(); - searchBar.setTitle(BuildConfig.IS_LUMEN ? webView.getUrl() : webView.getTitle()); + final String url = webView.getUrl(); + searchBar.setTitle(BuildConfig.IS_LUMEN ? url : webView.getTitle()); + searchBar.setSecure(isHttpsUrl(url)); searchBar.setAntiTrackingDetailsVisibility(View.VISIBLE); webView.setAnimation(animation); webView.bringToFront(); @@ -764,6 +767,10 @@ private void bringWebViewToFront(Animation animation) { } } + private boolean isHttpsUrl(@Nullable String url) { + return url != null && url.startsWith("https://"); + } + private void updateToolbarContainer(@NonNull Context context, boolean isBackgroundEnabled) { if (mIsIncognito) { appBackgroundManager.setViewBackgroundColor(toolBarContainer, @@ -872,6 +879,7 @@ public void openLink(String eventUrl, boolean reset, boolean fromHistory, Animat final String url = builder.build().toString(); mLightningView.loadUrl(url); searchBar.setTitle(eventUrl); + searchBar.setSecure(isHttpsUrl(eventUrl)); bringWebViewToFront(animation); if (quickAccessBar != null) { quickAccessBar.hide(); diff --git a/app/src/main/java/com/cliqz/browser/widget/SearchBar.java b/app/src/main/java/com/cliqz/browser/widget/SearchBar.java index a4307ecb1..0415fd2a4 100644 --- a/app/src/main/java/com/cliqz/browser/widget/SearchBar.java +++ b/app/src/main/java/com/cliqz/browser/widget/SearchBar.java @@ -3,7 +3,6 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Handler; @@ -24,9 +23,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; import androidx.core.content.ContextCompat; -import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; +import com.cliqz.browser.BuildConfig; import com.cliqz.browser.R; import com.cliqz.browser.app.BrowserApp; import com.cliqz.browser.main.Messages; @@ -35,7 +35,6 @@ import com.cliqz.nove.Subscribe; import java.util.Locale; -import java.util.Objects; import javax.inject.Inject; @@ -49,6 +48,8 @@ */ public class SearchBar extends FrameLayout { + public static final String HTTPS_PREFIX = "HTTPS://"; + public static final String HTTP_PREFIX = "HTTP://"; private float scaleX; private float scaleY; private float pivotX; @@ -66,6 +67,9 @@ public interface Listener extends TextWatcher, OnFocusChangeListener { @Inject QueryManager queryManager; + @BindView(R.id.icon_lock) + AppCompatImageView lock; + @BindView(R.id.title_bar) TextView titleBar; @@ -97,10 +101,6 @@ public SearchBar(Context context, AttributeSet attrs, int defStyle) { bus.register(this); inflate(getContext(), R.layout.search_bar_widget, this); ButterKnife.bind(this); - final Drawable clearIcon = VectorDrawableCompat.create( - context.getResources(), R.drawable.ic_clear_black, null); - final int clearIconHeight = Objects.requireNonNull(clearIcon).getIntrinsicHeight(); - titleBar.setHeight(clearIconHeight); if (trackerCounter != null) { trackerCounter.setFocusable(false); trackerCounter.setFocusableInTouchMode(false); @@ -226,7 +226,7 @@ public void selectAllText() { searchEditText.setSelection(0,getSearchText().length()), 200); } - public void setTitle(String title) { + public void setTitle(@Nullable String title) { // Be sure to not set the trampoline as the title final String nnTitle = title == null ? "" : title; final Uri titleAsUri = Uri.parse(nnTitle); @@ -234,7 +234,20 @@ public void setTitle(String title) { .getQueryParameter(TrampolineConstants.TRAMPOLINE_COMMAND_PARAM_NAME) != null) { return; } - titleBar.setText(title); + final String upperCaseTitle = nnTitle.toUpperCase(); + final String cleanTitle; + if (upperCaseTitle.startsWith(HTTPS_PREFIX)) { + cleanTitle = nnTitle.substring(HTTPS_PREFIX.length()); + } else if (upperCaseTitle.startsWith(HTTP_PREFIX)) { + cleanTitle = nnTitle.substring(HTTP_PREFIX.length()); + } else { + cleanTitle = nnTitle; + } + titleBar.setText(cleanTitle); + } + + public void setSecure(boolean secure) { + lock.setVisibility(secure ? VISIBLE : GONE); } public void setQuery(String query) { @@ -304,16 +317,31 @@ public boolean onInterceptTouchEvent(MotionEvent event) { * @param isIncognito True if the current tab is in incognito mode */ public void setStyle(boolean isIncognito) { - if (isIncognito) { - searchEditText.setTextColor(ContextCompat.getColor(getContext(), R.color.url_bar_text_color_incognito)); - searchEditText.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.url_bar_bg_incognito)); - titleBar.setTextColor(ContextCompat.getColor(getContext(), R.color.url_bar_text_color_incognito)); - titleBar.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.url_bar_bg_incognito)); + final Context context = getContext(); + if (BuildConfig.IS_NOT_LUMEN) { + if (isIncognito) { + searchEditText.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_incognito)); + searchEditText.setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_incognito)); + titleBar.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_incognito)); + titleBar.setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_incognito)); + } else { + searchEditText.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_normal)); + searchEditText.setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_normal)); + titleBar.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_normal)); + titleBar.setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_normal)); + } } else { - searchEditText.setTextColor(ContextCompat.getColor(getContext(), R.color.url_bar_text_color_normal)); - searchEditText.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.url_bar_bg_normal)); - titleBar.setTextColor(ContextCompat.getColor(getContext(), R.color.url_bar_text_color_normal)); - titleBar.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.url_bar_bg_normal)); + if (isIncognito) { + searchEditText.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_incognito)); + searchEditText.setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_incognito)); + titleBar.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_incognito)); + setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_incognito)); + } else { + searchEditText.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_normal)); + searchEditText.setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_normal)); + titleBar.setTextColor(ContextCompat.getColor(context, R.color.url_bar_text_color_normal)); + setBackgroundColor(ContextCompat.getColor(context, R.color.url_bar_bg_normal)); + } } } diff --git a/app/src/main/res/drawable/ic_lock_black.xml b/app/src/main/res/drawable/ic_lock_black.xml new file mode 100644 index 000000000..67a7c73ab --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_black.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 8fdc819b7..433c0c538 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -13,7 +13,7 @@ 24.0dp 12.0dp 50.0dp - 32dp + 24dp 80sp 100dp 20dp From d45492f418b189abe57dbc8fe8915ce79e55fe5b Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 27 Jun 2019 17:44:31 +0200 Subject: [PATCH 03/57] AP-330 unified status bar color (#130) --- app/src/cliqz/AndroidManifest.xml | 10 ++++++ .../browser/starttab/freshtab/FreshTab.kt | 7 ++-- app/src/main/AndroidManifest.xml | 25 ++++++------- .../com/cliqz/browser/main/MainActivity.java | 36 +++++++------------ .../com/cliqz/browser/main/TabFragment.java | 32 ++++++++++++----- app/src/main/res/values-v21/styles.xml | 13 ++++++- 6 files changed, 73 insertions(+), 50 deletions(-) create mode 100644 app/src/cliqz/AndroidManifest.xml diff --git a/app/src/cliqz/AndroidManifest.xml b/app/src/cliqz/AndroidManifest.xml new file mode 100644 index 000000000..34f69a8a3 --- /dev/null +++ b/app/src/cliqz/AndroidManifest.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt b/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt index 561d5cbbe..9d7329e8b 100644 --- a/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt +++ b/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt @@ -85,6 +85,10 @@ internal class FreshTab : StartTabFragment() { } else { getTrialPeriod(Messages.OnTrialPeriodResponse()) } + + trial_period_lumen_upgrade.setOnClickListener { + bus.post(Messages.GoToPurchase(0)) + } } @Subscribe @@ -136,9 +140,6 @@ internal class FreshTab : StartTabFragment() { trial_over_lumen_upgrade.visibility = View.GONE trial_period_upgrade_description.text = resources.getQuantityString(R.plurals.trial_period_upgrade_description, daysLeft, daysLeft) - trial_period_lumen_upgrade.setOnClickListener { - bus.post(Messages.GoToPurchase(0)) - } } private fun hideAllTrialPeriodViews() { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 54acb09db..f3a85b3ab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -131,12 +131,20 @@ - - + + + + @@ -225,17 +233,6 @@ android:authorities="${applicationId}.FacebookInitProvider" android:exported="false" tools:node="remove" /> - - - diff --git a/app/src/main/java/com/cliqz/browser/main/MainActivity.java b/app/src/main/java/com/cliqz/browser/main/MainActivity.java index 670554c2f..59b1f62eb 100644 --- a/app/src/main/java/com/cliqz/browser/main/MainActivity.java +++ b/app/src/main/java/com/cliqz/browser/main/MainActivity.java @@ -10,7 +10,6 @@ import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; @@ -24,7 +23,6 @@ import android.util.Log; import android.util.Patterns; import android.view.MenuItem; -import android.view.View; import android.view.WindowManager; import android.widget.Toast; @@ -112,11 +110,9 @@ public class MainActivity extends AppCompatActivity implements ActivityComponent private CustomViewHandler mCustomViewHandler; protected String currentMode; private boolean mIsColdStart = true; - private boolean mShouldShowLookbackDialog = true; private final HashSet downloadIds = new HashSet<>(); private final FileChooserHelper fileChooserHelper = new FileChooserHelper(this); private BroadcastReceiver mDownoloadCompletedBroadcastReceiver = null; - private ProgressDialog progressDialog = null; private PurchaseFragment purchaseFragment; @@ -194,7 +190,7 @@ protected void onCreate(Bundle savedInstanceState) { isIncognito = false; url = null; query = null; - progressDialog = new ProgressDialog(this); + final ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setIndeterminate(true); progressDialog.show(); // TODO This break the news on Cliqz. Please, move the loader to the proper, flavor dependent spot @@ -232,7 +228,6 @@ protected void onCreate(Bundle savedInstanceState) { if (isNotificationClicked) { sendNotificationClickedTelemetry(intent); } - //noinspection ConstantConditions if (!isRestored || url != null || query != null) { firstTabBuilder = tabsManager.buildTab(); firstTabBuilder.setForgetMode(isIncognito); @@ -270,12 +265,10 @@ protected void onCreate(Bundle savedInstanceState) { final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.update_webview_msg) .setCancelable(false) - .setPositiveButton(R.string.update, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("market://details?id=" + WEBVIEW_PACKAGE_NAME))); - finish(); - } + .setPositiveButton(R.string.update, (dialog, id) -> { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse("market://details?id=" + WEBVIEW_PACKAGE_NAME))); + finish(); }); AlertDialog alert = builder.create(); alert.show(); @@ -477,6 +470,7 @@ private void performExitCleanUp() { WebUtils.clearWebStorage(this); final File file = new File(getApplicationInfo().dataDir+"/app_webview", "historyManager-journal"); if (file.exists()) { + //noinspection ResultOfMethodCallIgnored file.delete(); } } @@ -484,6 +478,7 @@ private void performExitCleanUp() { WebUtils.clearCookies(this); final File file = new File(getApplicationInfo().dataDir+"/app_webview", "Cookies-journal"); if (file.exists()) { + //noinspection ResultOfMethodCallIgnored file.delete(); } @@ -502,12 +497,7 @@ public void onBackPressed() { public void openLinkInNewTab(BrowserEvents.OpenUrlInNewTab event) { createTab(event.url, event.isIncognito, event.showImmediately); bus.post(new Messages.UpdateTabCounter(tabsManager.getTabCount())); - Utils.showSnackbar(this, getString(R.string.tab_created), getString(R.string.view), new View.OnClickListener() { - @Override - public void onClick(View v) { - tabsManager.showTab(tabsManager.getTabCount() - 1); - } - }); + Utils.showSnackbar(this, getString(R.string.tab_created), getString(R.string.view), v -> tabsManager.showTab(tabsManager.getTabCount() - 1)); } @Subscribe @@ -753,13 +743,11 @@ private boolean shouldUpdateWebview() { @Override public boolean onOptionsItemSelected(MenuItem item) { final int id = item.getItemId(); - switch (id) { - case android.R.id.home: - onBackPressed(); - return true; - default: - return super.onOptionsItemSelected(item); + if (id == android.R.id.home) { + onBackPressed(); + return true; } + return super.onOptionsItemSelected(item); } @Override diff --git a/app/src/main/java/com/cliqz/browser/main/TabFragment.java b/app/src/main/java/com/cliqz/browser/main/TabFragment.java index 8f05dca32..f14743a49 100644 --- a/app/src/main/java/com/cliqz/browser/main/TabFragment.java +++ b/app/src/main/java/com/cliqz/browser/main/TabFragment.java @@ -86,7 +86,13 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import javax.inject.Inject; @@ -1381,15 +1387,25 @@ private void updateUI() { final Context wrapper = new ContextThemeWrapper(activity, themeId); final Resources.Theme theme = wrapper.getTheme(); - final TypedArray typedArray = theme.obtainStyledAttributes(new int[]{ - R.attr.colorPrimary, - R.attr.colorPrimaryDark, - R.attr.textColorPrimary, - }); - final int iconColor = typedArray.getColor(2, - ContextCompat.getColor(wrapper, R.color.text_color_primary)); - final int statusBarColor = typedArray.getColor(1, + int[] attrs; + try { + final Field field = android.R.attr.class.getDeclaredField("statusBarColor"); + final int attr = field.getInt(null); + attrs = new int[] { + attr, + R.attr.textColorPrimary, + }; + } catch (Throwable e) { + attrs = new int[] { + R.attr.colorPrimaryDark, + R.attr.textColorPrimary + }; + } + final TypedArray typedArray = theme.obtainStyledAttributes(attrs); + final int statusBarColor = typedArray.getColor(typedArray.getIndex(0), ContextCompat.getColor(wrapper, R.color.primary_color_dark)); + final int iconColor = typedArray.getColor(typedArray.getIndex(1), + ContextCompat.getColor(wrapper, R.color.text_color_primary)); typedArray.recycle(); overflowMenuIcon.getDrawable().setColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP); updateToolbarContainer(activity, preferenceManager.isBackgroundImageEnabled()); diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index f49f71cce..377562362 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -30,6 +30,13 @@ --> + + + \ No newline at end of file From dfa925dd12bb1286b62351079087ddd602673d3f Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Thu, 27 Jun 2019 18:58:27 +0200 Subject: [PATCH 04/57] AP-337 re-add option menu in overview (#132) --- .../browser/overview/OverviewFragment.java | 108 +++++------------- .../browser/overview/OverviewFragment.java | 8 +- .../browser/main/MainActivityComponent.java | 4 +- .../overview/CommonOverviewFragment.java | 80 +++++++++++++ .../browser/overview/TabOverviewFragment.java | 15 ++- 5 files changed, 116 insertions(+), 99 deletions(-) create mode 100644 app/src/main/java/com/cliqz/browser/overview/CommonOverviewFragment.java diff --git a/app/src/cliqz/java/com/cliqz/browser/overview/OverviewFragment.java b/app/src/cliqz/java/com/cliqz/browser/overview/OverviewFragment.java index dfec65467..bd4e3144e 100644 --- a/app/src/cliqz/java/com/cliqz/browser/overview/OverviewFragment.java +++ b/app/src/cliqz/java/com/cliqz/browser/overview/OverviewFragment.java @@ -1,49 +1,34 @@ package com.cliqz.browser.overview; +import android.app.Activity; import android.content.res.Configuration; import android.content.res.TypedArray; import android.os.Build; import android.os.Bundle; -import androidx.annotation.NonNull; -import com.google.android.material.tabs.TabLayout; -import androidx.fragment.app.Fragment; -import androidx.core.content.ContextCompat; -import androidx.viewpager.widget.ViewPager; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; 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 androidx.annotation.NonNull; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.viewpager.widget.ViewPager; + import com.cliqz.browser.R; -import com.cliqz.browser.app.BrowserApp; -import com.cliqz.browser.main.FlavoredActivityComponent; import com.cliqz.browser.main.Messages; import com.cliqz.browser.main.TabFragment; -import com.cliqz.browser.main.TabsManager; -import com.cliqz.browser.telemetry.Telemetry; import com.cliqz.browser.telemetry.TelemetryKeys; import com.cliqz.browser.webview.CliqzMessages; -import com.cliqz.nove.Bus; import com.cliqz.nove.Subscribe; +import com.google.android.material.tabs.TabLayout; import com.readystatesoftware.systembartint.SystemBarTintManager; -import javax.inject.Inject; - -public class OverviewFragment extends Fragment { - - @Inject - Bus bus; - - @Inject - TabsManager tabsManager; +import java.util.Objects; - @Inject - Telemetry telemetry; +public class OverviewFragment extends CommonOverviewFragment { private ViewPager mViewPager; private OverviewTabsEnum mSelectedTab = OverviewTabsEnum.UNDEFINED; @@ -62,15 +47,16 @@ public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup conta final View deleteButton = view.findViewById(R.id.action_delete); deleteButton.setOnClickListener(v -> bus.post(new Messages.OnContextualBarDeletePressed())); final int themeResId = R.style.Theme_Cliqz_Overview; - final TypedArray typedArray = getActivity().getTheme() + final Activity activity = Objects.requireNonNull(getActivity()); + final TypedArray typedArray = activity.getTheme() .obtainStyledAttributes(themeResId, new int[]{R.attr.colorPrimaryDark}); final int resourceId = typedArray.getResourceId(0, R.color.normal_tab_primary_color); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - getActivity().getWindow() - .setStatusBarColor(ContextCompat.getColor(getContext(), resourceId)); + activity.getWindow() + .setStatusBarColor(ContextCompat.getColor(activity, resourceId)); typedArray.recycle(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - SystemBarTintManager tintManager = new SystemBarTintManager(getActivity()); + SystemBarTintManager tintManager = new SystemBarTintManager(activity); tintManager.setStatusBarTintEnabled(true); tintManager.setNavigationBarTintEnabled(true); tintManager.setTintColor(resourceId); @@ -81,14 +67,13 @@ public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup conta mViewPager.setOffscreenPageLimit(5); mViewPager.setAdapter(mPageAdapter); final Toolbar toolbar = view.findViewById(R.id.toolbar); - toolbar.setTitle(getContext().getString(R.string.overview)); - ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); - final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); + toolbar.setTitle(activity.getString(R.string.overview)); + ((AppCompatActivity) activity).setSupportActionBar(toolbar); + final ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setTitle(getContext().getString(R.string.overview)); + actionBar.setTitle(activity.getString(R.string.overview)); } - setHasOptionsMenu(true); TabLayout tabLayout = view.findViewById(R.id.tabs); tabLayout.setupWithViewPager(mViewPager); return view; @@ -104,43 +89,6 @@ private void sendCurrentPageHideSignal() { } } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.fragment_overview_menu, menu); - super.onCreateOptionsMenu(menu, inflater); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // All the options close the current visible page - sendCurrentPageHideSignal(); - final int id = item.getItemId(); - switch (id) { - case R.id.action_new_tab: - telemetry.sendMainMenuSignal(TelemetryKeys.NEW_TAB, false, TelemetryKeys.OVERVIEW); - tabsManager.buildTab().show(); - return true; - case R.id.action_new_forget_tab: - telemetry.sendMainMenuSignal(TelemetryKeys.NEW_FORGET_TAB, false, - TelemetryKeys.OVERVIEW); - tabsManager.buildTab().setForgetMode(true).show(); - return true; - case R.id.action_settings: - telemetry.sendMainMenuSignal(TelemetryKeys.SETTINGS, false, TelemetryKeys.OVERVIEW); - if (bus != null) { - bus.post(new Messages.GoToSettings()); - } - return true; - case R.id.action_close_all_tabs: - telemetry.sendMainMenuSignal(TelemetryKeys.CLOSE_ALL_TABS, false, - TelemetryKeys.OVERVIEW); - tabsManager.deleteAllTabs(); - return true; - default: - return false; - } - } - @SuppressWarnings("UnusedParameters") @Subscribe public void onBackPressed(Messages.BackPressed event) { @@ -176,16 +124,6 @@ public void onOrientationChanged(Configuration newConfig) { TelemetryKeys.LANDSCAPE : TelemetryKeys.PORTRAIT, TelemetryKeys.OVERVIEW); } - @Override - public void onStart() { - super.onStart(); - final FlavoredActivityComponent component = BrowserApp.getActivityComponent(getActivity()); - if (component != null) { - component.inject(this); - bus.register(this); - } - } - @Override public void onStop() { super.onStop(); @@ -270,4 +208,10 @@ public void onPageScrollStateChanged(int state) { } } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + sendCurrentPageHideSignal(); + return super.onOptionsItemSelected(item); + } } diff --git a/app/src/lumen/java/com/cliqz/browser/overview/OverviewFragment.java b/app/src/lumen/java/com/cliqz/browser/overview/OverviewFragment.java index 3a7e1ede0..1342f37c3 100644 --- a/app/src/lumen/java/com/cliqz/browser/overview/OverviewFragment.java +++ b/app/src/lumen/java/com/cliqz/browser/overview/OverviewFragment.java @@ -24,16 +24,10 @@ import javax.inject.Inject; -public class OverviewFragment extends Fragment { +public class OverviewFragment extends CommonOverviewFragment { private final static String TAB_OVERVIEW_TAG = "tab_overview_tag"; - @Inject - TabsManager tabsManager; - - @Inject - Bus bus; - public void setDisplayFavorites() { } diff --git a/app/src/main/java/com/cliqz/browser/main/MainActivityComponent.java b/app/src/main/java/com/cliqz/browser/main/MainActivityComponent.java index 3eb8de8aa..4810e3185 100644 --- a/app/src/main/java/com/cliqz/browser/main/MainActivityComponent.java +++ b/app/src/main/java/com/cliqz/browser/main/MainActivityComponent.java @@ -2,7 +2,7 @@ import com.cliqz.browser.main.search.Incognito; import com.cliqz.browser.main.search.SearchView; -import com.cliqz.browser.overview.OverviewFragment; +import com.cliqz.browser.overview.CommonOverviewFragment; import com.cliqz.browser.overview.TabOverviewFragment; import com.cliqz.browser.utils.PasswordManager; import com.cliqz.browser.webview.BaseWebView; @@ -31,7 +31,7 @@ interface MainActivityComponent { void inject(CliqzWebView cliqzWebView); - void inject(OverviewFragment overviewFragment); + void inject(CommonOverviewFragment overviewFragment); void inject(TabOverviewFragment tabOverviewFragment); diff --git a/app/src/main/java/com/cliqz/browser/overview/CommonOverviewFragment.java b/app/src/main/java/com/cliqz/browser/overview/CommonOverviewFragment.java new file mode 100644 index 000000000..6364abe71 --- /dev/null +++ b/app/src/main/java/com/cliqz/browser/overview/CommonOverviewFragment.java @@ -0,0 +1,80 @@ +package com.cliqz.browser.overview; + +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; + +import androidx.fragment.app.Fragment; + +import com.cliqz.browser.R; +import com.cliqz.browser.app.BrowserApp; +import com.cliqz.browser.main.FlavoredActivityComponent; +import com.cliqz.browser.main.Messages; +import com.cliqz.browser.main.TabsManager; +import com.cliqz.browser.telemetry.Telemetry; +import com.cliqz.browser.telemetry.TelemetryKeys; +import com.cliqz.nove.Bus; + +import javax.inject.Inject; + +public class CommonOverviewFragment extends Fragment { + + @Inject + Bus bus; + + @Inject + TabsManager tabsManager; + + @Inject + Telemetry telemetry; + + @Override + public void onStart() { + super.onStart(); + final FlavoredActivityComponent component = BrowserApp.getActivityComponent(getActivity()); + if (component != null) { + component.inject(this); + bus.register(this); + } + } + + public CommonOverviewFragment() { + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.fragment_overview_menu, menu); + super.onCreateOptionsMenu(menu, inflater); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // All the options close the current visible page + final int id = item.getItemId(); + switch (id) { + case R.id.action_new_tab: + telemetry.sendMainMenuSignal(TelemetryKeys.NEW_TAB, false, TelemetryKeys.OVERVIEW); + tabsManager.buildTab().show(); + return true; + case R.id.action_new_forget_tab: + telemetry.sendMainMenuSignal(TelemetryKeys.NEW_FORGET_TAB, false, + TelemetryKeys.OVERVIEW); + tabsManager.buildTab().setForgetMode(true).show(); + return true; + case R.id.action_settings: + telemetry.sendMainMenuSignal(TelemetryKeys.SETTINGS, false, TelemetryKeys.OVERVIEW); + if (bus != null) { + bus.post(new Messages.GoToSettings()); + } + return true; + case R.id.action_close_all_tabs: + telemetry.sendMainMenuSignal(TelemetryKeys.CLOSE_ALL_TABS, false, + TelemetryKeys.OVERVIEW); + tabsManager.deleteAllTabs(); + return true; + default: + return false; + } + } +} diff --git a/app/src/main/java/com/cliqz/browser/overview/TabOverviewFragment.java b/app/src/main/java/com/cliqz/browser/overview/TabOverviewFragment.java index 33839a092..13fb6f2cb 100644 --- a/app/src/main/java/com/cliqz/browser/overview/TabOverviewFragment.java +++ b/app/src/main/java/com/cliqz/browser/overview/TabOverviewFragment.java @@ -19,6 +19,8 @@ import com.cliqz.deckview.TabsDeckView; import com.cliqz.jsengine.Engine; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import javax.inject.Inject; @@ -55,16 +57,13 @@ public class TabOverviewFragment extends Fragment implements TabsDeckView.TabsDe @Nullable @Override - public View onCreateView(final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + public View onCreateView(@NotNull final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.tabs_overview, container, false); ButterKnife.bind(this, view); - floatingActionButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - telemetry.sendNewTabSignal(tabsManager.getTabCount()+1); - final int position = tabsManager.buildTab().create(); - tabsManager.showTab(position, R.anim.new_tab_scale_animation); - } + floatingActionButton.setOnClickListener(v -> { + telemetry.sendNewTabSignal(tabsManager.getTabCount()+1); + final int position = tabsManager.buildTab().create(); + tabsManager.showTab(position, R.anim.new_tab_scale_animation); }); deckView.setListener(this); return view; From 4b356b663d0973c9a85cfdba7e64dfef5e7189bc Mon Sep 17 00:00:00 2001 From: Jayesh Solanki Date: Fri, 28 Jun 2019 15:04:41 +0200 Subject: [PATCH 05/57] AP-349 Check and restore subscription if exists for each purchase request (#131) --- .../browser/purchases/PurchaseFragment.kt | 95 ++++++++++++------- .../browser/purchases/PurchasesManager.kt | 5 +- .../browser/starttab/freshtab/FreshTab.kt | 1 + .../lumen/res/layout/fragment_freshtab.xml | 2 +- 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt b/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt index a362c9427..aa3769fdb 100644 --- a/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt +++ b/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt @@ -118,44 +118,75 @@ class PurchaseFragment : DialogFragment(), OnBuyClickListener { } override fun onBuyClicked(position: Int) { + mAdapter.getProduct(position)?.apply { + restoreExistingPurchase({ activeSku -> + Toast.makeText(context, "You are already subscribed to one the packages", Toast.LENGTH_LONG).show() + enableFeatures(activeSku) + }, { + makePurchase(sku) + }) + } + } + + private fun restoreExistingPurchase(success: (sku: String) -> Unit, cannotRestore: () -> Unit) { + Purchases.sharedInstance.restorePurchasesWith( + { + Log.w(TAG, it.message) + cannotRestore() + }, + { + if (it.activeSubscriptions.isEmpty()) { + cannotRestore() + } else { + success(it.activeSubscriptions.first()) + } + } + ) + } + + private fun makePurchase(sku: String) { val oldSku = ArrayList() if (purchasesManager.purchase.sku.isNotEmpty()) { oldSku.add(purchasesManager.purchase.sku) } - mAdapter.getProduct(position)?.apply { - Purchases.sharedInstance.makePurchaseWith(activity as Activity, sku, - BillingClient.SkuType.SUBS, oldSku, - { error, _ -> - Log.e(TAG, error.underlyingErrorMessage) + Purchases.sharedInstance.makePurchaseWith(activity as Activity, sku, + BillingClient.SkuType.SUBS, oldSku, + { error, userCancelled -> + if (!userCancelled) { + Log.e(TAG, "${error.underlyingErrorMessage}") Toast.makeText(context, error.message, Toast.LENGTH_LONG).show() - }, - { purchase, _ -> - when (purchase.sku) { - Product.BASIC_VPN -> { - purchasesManager.purchase.isVpnEnabled = true - purchasesManager.purchase.isDashboardEnabled = true - preferenceManager.isAttrackEnabled = true - preferenceManager.adBlockEnabled = true - } - Product.BASIC -> { - purchasesManager.purchase.isVpnEnabled = false - purchasesManager.purchase.isDashboardEnabled = true - preferenceManager.isAttrackEnabled = true - preferenceManager.adBlockEnabled = true - } - Product.VPN -> { - purchasesManager.purchase.isVpnEnabled = true - purchasesManager.purchase.isDashboardEnabled = false - preferenceManager.isAttrackEnabled = false - preferenceManager.adBlockEnabled = false - } - } - purchasesManager.purchase.sku = purchase.sku - purchasesManager.purchase.isASubscriber = true - bus.post(Messages.PurchaseCompleted()) - this@PurchaseFragment.dismiss() } - ) + }, + { purchase, _ -> + enableFeatures(purchase.sku) + } + ) + } + + private fun enableFeatures(sku: String) { + when (sku) { + Product.BASIC_VPN -> { + purchasesManager.purchase.isVpnEnabled = true + purchasesManager.purchase.isDashboardEnabled = true + preferenceManager.isAttrackEnabled = true + preferenceManager.adBlockEnabled = true + } + Product.BASIC -> { + purchasesManager.purchase.isVpnEnabled = false + purchasesManager.purchase.isDashboardEnabled = true + preferenceManager.isAttrackEnabled = true + preferenceManager.adBlockEnabled = true + } + Product.VPN -> { + purchasesManager.purchase.isVpnEnabled = true + purchasesManager.purchase.isDashboardEnabled = false + preferenceManager.isAttrackEnabled = false + preferenceManager.adBlockEnabled = false + } } + purchasesManager.purchase.sku = sku + purchasesManager.purchase.isASubscriber = true + bus.post(Messages.PurchaseCompleted()) + this@PurchaseFragment.dismiss() } } diff --git a/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt b/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt index 484be83c7..addcf73e7 100644 --- a/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt +++ b/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt @@ -62,10 +62,9 @@ class PurchasesManager( isLoading = false } else { purchase.isASubscriber = false - // Check if in trial period. - this.loadTrialPeriodInfo(this@PurchasesManager) } - + // Get Trial Period data and vpn username, password. + this.loadTrialPeriodInfo(this@PurchasesManager) } override fun onError(error: PurchasesError) { diff --git a/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt b/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt index 9d7329e8b..f34ce0e90 100644 --- a/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt +++ b/app/src/lumen/java/com/cliqz/browser/starttab/freshtab/FreshTab.kt @@ -93,6 +93,7 @@ internal class FreshTab : StartTabFragment() { @Subscribe fun getTrialPeriod(onTrialPeriodResponse: Messages.OnTrialPeriodResponse) { + if (purchasesManager.purchase.isASubscriber) return if (purchasesManager.serverData != null) { purchasesManager.serverData?.apply { if (isInTrial) { diff --git a/app/src/lumen/res/layout/fragment_freshtab.xml b/app/src/lumen/res/layout/fragment_freshtab.xml index 2a000828f..c2aa1ae53 100644 --- a/app/src/lumen/res/layout/fragment_freshtab.xml +++ b/app/src/lumen/res/layout/fragment_freshtab.xml @@ -11,7 +11,7 @@ layout="@layout/fragment_freshtab_welcome_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toBottomOf="@id/trial_over_lumen_upgrade" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" From 3a4d03a63ffe7f7fa069d5570dde7073582dbe05 Mon Sep 17 00:00:00 2001 From: Jayesh Solanki Date: Fri, 28 Jun 2019 16:09:08 +0200 Subject: [PATCH 06/57] Handle null VpnProfile crash (#133) --- .../java/com/cliqz/browser/vpn/VpnPanel.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/lumen/java/com/cliqz/browser/vpn/VpnPanel.java b/app/src/lumen/java/com/cliqz/browser/vpn/VpnPanel.java index 8f180a8ce..2d92b9c8c 100644 --- a/app/src/lumen/java/com/cliqz/browser/vpn/VpnPanel.java +++ b/app/src/lumen/java/com/cliqz/browser/vpn/VpnPanel.java @@ -9,7 +9,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; -import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -36,6 +35,7 @@ import com.cliqz.nove.Subscribe; import java.util.ArrayList; +import java.util.Collection; import javax.inject.Inject; @@ -112,7 +112,11 @@ public static VpnPanel create(View source) { final Bundle arguments = new Bundle(); arguments.putInt(KEY_ANCHOR_HEIGHT, source.getHeight()); dialog.setArguments(arguments); - dialog.selectedProfile = ProfileManager.getInstance(source.getContext()).getProfiles().iterator().next(); + final Collection vpnProfiles = + ProfileManager.getInstance(source.getContext()).getProfiles(); + if (vpnProfiles != null && !vpnProfiles.isEmpty()) { + dialog.selectedProfile = vpnProfiles.iterator().next(); + } return dialog; } @@ -164,7 +168,11 @@ public void onPause() { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ButterKnife.bind(this, view); - mSelectedCountry.setText(selectedProfile.getName()); + if (selectedProfile == null) { + mSelectedCountry.setText("US"); + } else { + mSelectedCountry.setText(selectedProfile.getName()); + } mSelectedCountry.setPaintFlags(mSelectedCountry.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); vpnMsgsChangeDrawable(VpnStatus.isVPNConnected() ? R.drawable.ic_check : R.drawable.ic_cross); @@ -184,7 +192,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c @OnClick(R.id.vpn_country) void vpnCountryClicked() { - showVpnCountriesDialog(); + if (selectedProfile != null) { + showVpnCountriesDialog(); + } else { + unlockVpnDialog(); + } } @OnClick(R.id.vpn_connect_button) From c231091aff19513359b0be87348431bae24bd656 Mon Sep 17 00:00:00 2001 From: Stefano Pacifici Date: Mon, 1 Jul 2019 17:28:03 +0200 Subject: [PATCH 07/57] AP-331 removes incognito mode special message from Lumen (#137) --- .../com/cliqz/browser/main/TabFragment.java | 9 +--- .../cliqz/browser/main/search/SearchView.java | 51 ++++++++----------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/cliqz/browser/main/TabFragment.java b/app/src/main/java/com/cliqz/browser/main/TabFragment.java index f14743a49..c15ac7c67 100644 --- a/app/src/main/java/com/cliqz/browser/main/TabFragment.java +++ b/app/src/main/java/com/cliqz/browser/main/TabFragment.java @@ -88,11 +88,6 @@ import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; import javax.inject.Inject; @@ -1011,9 +1006,7 @@ public void reloadPage(Messages.ReloadPage event) { @Subscribe public void shareLink(Messages.ShareLink event) { - if (state.getMode() == Mode.SEARCH) { - searchView.requestCardUrl(); - } else { + if (state.getMode() != Mode.SEARCH) { final String url = mLightningView.getUrl(); shareText(url); telemetry.sendShareSignal(TelemetryKeys.WEB); diff --git a/app/src/main/java/com/cliqz/browser/main/search/SearchView.java b/app/src/main/java/com/cliqz/browser/main/search/SearchView.java index d88a5f9f4..708c05aa4 100644 --- a/app/src/main/java/com/cliqz/browser/main/search/SearchView.java +++ b/app/src/main/java/com/cliqz/browser/main/search/SearchView.java @@ -79,7 +79,7 @@ public SearchView(AppCompatActivity context, Engine engine) { mReactView = engine.reactRootView; startTabContainer = new StartTabContainer(this.context); startTabContainer.init(context.getSupportFragmentManager(), preferenceManager); - incognito = new Incognito(this.context); + incognito = BuildConfig.IS_NOT_LUMEN ? new Incognito(this.context) : null; // mReactView.setBackgroundColor(ContextCompat.getColor(this.context, R.color.normal_tab_primary_color)); mReactView.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); @@ -88,7 +88,10 @@ public SearchView(AppCompatActivity context, Engine engine) { parent.removeView(mReactView); } addView(mReactView); - addView(incognito); + if (incognito != null) { + incognito.setVisibility(GONE); + addView(incognito); + } addView(startTabContainer); } @@ -97,15 +100,7 @@ public void bringToFront() { super.bringToFront(); final String query = state.getQuery(); if (query.equals("")) { - if (state.isIncognito()) { - incognito.bringToFront(); - incognito.setVisibility(View.VISIBLE); - startTabContainer.setVisibility(View.GONE); - } else { - startTabContainer.bringToFront(); - startTabContainer.setVisibility(View.VISIBLE); - incognito.setVisibility(View.GONE); - } + setIncognito(state.isIncognito()); mReactView.setVisibility(View.GONE); } else { mReactView.bringToFront(); @@ -157,30 +152,28 @@ public void onResume() { public void setCurrentTabState(CliqzBrowserState state) { this.state = state; -// mReactView.setCurrentTabState(state); - if (state.isIncognito()) { - if (incognito.getVisibility() == VISIBLE) { - return; - } + setIncognito(state.isIncognito()); + } + + private void setIncognito(boolean enabled) { + final boolean shouldShowIncognitoView = enabled && incognito != null && incognito.getVisibility() != VISIBLE; + final boolean shouldShowRegularView = !enabled && startTabContainer.getVisibility() != VISIBLE; + + if (shouldShowIncognitoView) { incognito.bringToFront(); - incognito.setVisibility(View.VISIBLE); - startTabContainer.setVisibility(View.GONE); - } else { - if (startTabContainer.getVisibility() == VISIBLE) { - return; - } + incognito.setVisibility(VISIBLE); + startTabContainer.setVisibility(GONE); + } + if (shouldShowRegularView) { startTabContainer.bringToFront(); - startTabContainer.setVisibility(View.VISIBLE); - incognito.setVisibility(View.GONE); + startTabContainer.setVisibility(VISIBLE); + if (incognito != null) { + incognito.setVisibility(GONE); + } } } - public void requestCardUrl() { -// cardsView.requestCardUrl(); - } - public void updateQuery(String query, int start, int count) { - //noinspection ConstantConditions if (BuildConfig.IS_LUMEN) { return; } From bb0316b5590f602e09c88f921cc0bbc94b41f13f Mon Sep 17 00:00:00 2001 From: Jayesh Solanki Date: Tue, 2 Jul 2019 18:22:09 +0200 Subject: [PATCH 08/57] Do not change user preferences when disabling subscriptions (#136) --- .../cliqz/browser/controlcenter/ControlCenterDialog.java | 8 +++----- .../cliqz/browser/controlcenter/DashboardFragment.java | 6 ++++-- .../java/com/cliqz/browser/purchases/PurchaseFragment.kt | 9 +++++++-- .../java/com/cliqz/browser/purchases/PurchasesManager.kt | 6 ------ .../browser/lightning/preference/PreferenceManager.java | 6 ++---- .../java/acr/browser/lightning/view/LightningView.java | 8 ++++++-- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/app/src/lumen/java/com/cliqz/browser/controlcenter/ControlCenterDialog.java b/app/src/lumen/java/com/cliqz/browser/controlcenter/ControlCenterDialog.java index eadaf01c0..11e2761f4 100644 --- a/app/src/lumen/java/com/cliqz/browser/controlcenter/ControlCenterDialog.java +++ b/app/src/lumen/java/com/cliqz/browser/controlcenter/ControlCenterDialog.java @@ -145,10 +145,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c controlCenterPager.setAdapter(mControlCenterPagerAdapter); controlCenterTabLayout.setupWithViewPager(controlCenterPager); - boolean isDashboardEnabled = - preferenceManager.isAttrackEnabled() && preferenceManager.getAdBlockEnabled(); - - hideSubscribeButton(isDashboardEnabled); + hideSubscribeButton(purchasesManager.isDashboardEnabled()); ultimateProtectionSwitch.setOnCheckedChangeListener((compoundButton, isChecked) -> { mControlCenterPagerAdapter.updateViewComponent(0, isChecked); @@ -191,7 +188,8 @@ public void onConfigurationChanged(Configuration newConfig) { } private void hideSubscribeButton(boolean isDashboardEnabled) { - ultimateProtectionSwitch.setChecked(isDashboardEnabled); + ultimateProtectionSwitch.setChecked(preferenceManager.isAttrackEnabled() && + preferenceManager.getAdBlockEnabled()); subscribeUltimateProtectionView.setVisibility(isDashboardEnabled ? View.GONE : View.VISIBLE); dashboardDisableOverlay.setVisibility(isDashboardEnabled ? View.GONE : View.VISIBLE); ViewExtensionsKt.enableViewHierarchy(ultimateProtectionContainer, isDashboardEnabled); diff --git a/app/src/lumen/java/com/cliqz/browser/controlcenter/DashboardFragment.java b/app/src/lumen/java/com/cliqz/browser/controlcenter/DashboardFragment.java index 478f3b98a..561ed4bd4 100644 --- a/app/src/lumen/java/com/cliqz/browser/controlcenter/DashboardFragment.java +++ b/app/src/lumen/java/com/cliqz/browser/controlcenter/DashboardFragment.java @@ -80,7 +80,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c updateUI(); dashBoardListView.setAdapter(mDashboardAdapter); dashBoardListView.setLayoutManager(new LinearLayoutManager(getContext())); - changeDashboardState(preferenceManager.isAttrackEnabled() && preferenceManager.getAdBlockEnabled()); + changeDashboardState(purchasesManager.isDashboardEnabled() && + preferenceManager.isAttrackEnabled() && preferenceManager.getAdBlockEnabled()); return view; } @@ -135,7 +136,8 @@ public void updateViews(ReadableMap data) { final MeasurementWrapper trackersDetected; final MeasurementWrapper pagesVisited; - if (preferenceManager.getAdBlockEnabled() && preferenceManager.isAttrackEnabled()) { + if (purchasesManager.isDashboardEnabled() && + preferenceManager.getAdBlockEnabled() && preferenceManager.isAttrackEnabled()) { dataSaved = ValuesFormatterUtil.formatBytesCount(ReadableMapUtils.getSafeInt(data, "dataSaved")); adsBlocked = ValuesFormatterUtil.formatBlockCount(ReadableMapUtils.getSafeInt(data,"adsBlocked")); trackersDetected = ValuesFormatterUtil.formatBlockCount(ReadableMapUtils.getSafeInt(data, "trackersDetected")); diff --git a/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt b/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt index aa3769fdb..4856b0f17 100644 --- a/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt +++ b/app/src/lumen/java/com/cliqz/browser/purchases/PurchaseFragment.kt @@ -120,8 +120,13 @@ class PurchaseFragment : DialogFragment(), OnBuyClickListener { override fun onBuyClicked(position: Int) { mAdapter.getProduct(position)?.apply { restoreExistingPurchase({ activeSku -> - Toast.makeText(context, "You are already subscribed to one the packages", Toast.LENGTH_LONG).show() - enableFeatures(activeSku) + if (activeSku == sku) { + Toast.makeText(context, "You are already subscribed to this package", Toast.LENGTH_LONG).show() + // TODO: Can remove this line and provide a restore button. + enableFeatures(sku) + } else { + makePurchase(sku) + } }, { makePurchase(sku) }) diff --git a/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt b/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt index addcf73e7..3a54a24df 100644 --- a/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt +++ b/app/src/lumen/java/com/cliqz/browser/purchases/PurchasesManager.kt @@ -36,8 +36,6 @@ class PurchasesManager( override fun onTrialPeriodResponse(serverData: ServerData?) { this.serverData = serverData isLoading = false - preferenceManager.adBlockEnabled = serverData == null || serverData.isInTrial - preferenceManager.isAttrackEnabled = serverData == null || serverData.isInTrial bus.post(Messages.OnTrialPeriodResponse()) } @@ -54,10 +52,6 @@ class PurchasesManager( this.isDashboardEnabled = isDashboardEnabled this.sku = sku } - if (!isDashboardEnabled) { - preferenceManager.adBlockEnabled = false - preferenceManager.isAttrackEnabled = false - } } isLoading = false } else { diff --git a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java index 81d086494..9c57c5620 100644 --- a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java +++ b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java @@ -153,8 +153,7 @@ public PreferenceManager(final Context context) { * @return true if adblocking is enabled, false otherwise */ public boolean getAdBlockEnabled() { - boolean isDefaultEnabled = BuildConfig.IS_NOT_LUMEN; - return mPrefs.getBoolean(Name.BLOCK_ADS, isDefaultEnabled); + return mPrefs.getBoolean(Name.BLOCK_ADS, true); } public boolean getOptimizedAdBlockEnabled() { @@ -446,8 +445,7 @@ public boolean getFirstDevicePaired() { } public boolean isAttrackEnabled() { - boolean isDefaultEnabled = BuildConfig.IS_NOT_LUMEN; - return mPrefs.getBoolean(Name.ATTRACK_ENABLED, isDefaultEnabled); + return mPrefs.getBoolean(Name.ATTRACK_ENABLED, true); } public int getMainActivityLastState() { diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index 0d6fb223a..68035bdd8 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -27,6 +27,7 @@ import com.cliqz.browser.antiphishing.AntiPhishing; import com.cliqz.browser.app.BrowserApp; import com.cliqz.browser.main.FlavoredActivityComponent; +import com.cliqz.browser.purchases.PurchasesManager; import com.cliqz.browser.telemetry.Telemetry; import com.cliqz.browser.utils.BloomFilterUtils; import com.cliqz.browser.utils.PasswordManager; @@ -117,6 +118,9 @@ public interface LightingViewListener { @Inject PreferenceManager preferences; + @Inject + PurchasesManager purchasesManager; + @Inject LightningDialogBuilder dialogBuilder; @@ -275,8 +279,8 @@ private synchronized void initializePreferences(@Nullable WebSettings settings) // update jsengine module states. try { - attrack.setEnabled(preferences.isAttrackEnabled()); - adblocker.setEnabled(preferences.getAdBlockEnabled()); + attrack.setEnabled(purchasesManager.isDashboardEnabled() && preferences.isAttrackEnabled()); + adblocker.setEnabled(purchasesManager.isDashboardEnabled() && preferences.getAdBlockEnabled()); } catch (EngineNotYetAvailable e) { Log.w(TAG, "error updating jsengine state", e); } From 361355dcbf89ab6aa8a4e333c44d7f19e652f1e5 Mon Sep 17 00:00:00 2001 From: Sharath Date: Tue, 2 Jul 2019 18:55:39 +0200 Subject: [PATCH 09/57] Fix Docker and Setup CD (#135) --- Dockerfile | 37 +++--- Jenkinsfile.upload | 107 ++++++++++-------- app/build.gradle | 2 +- .../main/java/com/cliqz/gradle/CliqzPlugin.kt | 10 +- fastlane/Appfile | 2 +- fastlane/Fastfile | 19 +++- 6 files changed, 101 insertions(+), 76 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9269d52b7..d533dd81b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 MAINTAINER Stefano Pacifici ENV DEBIAN_FRONTEND noninteractive @@ -61,7 +61,7 @@ ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/ ENV ANDROID_HOME /home/jenkins/android_home ENV GRADLE_USER_HOME /home/jenkins/gradle_home ENV NVM_DIR /home/jenkins/nvm -ENV NODE_VERSION 8.9.3 +ENV NODE_VERSION 9.11.2 USER jenkins @@ -74,18 +74,14 @@ RUN mkdir -p $ANDROID_HOME; \ rm -r sdktools.zip; \ (while (true); do echo y; sleep 2; done) | \ tools/bin/sdkmanager \ - "build-tools;26.0.2" \ - "platforms;android-23" \ - "platforms;android-27" \ + "build-tools;28.0.3" \ + "platforms;android-28" \ "platform-tools" \ "tools" \ - "platforms;android-25" \ "extras;google;m2repository" \ "extras;android;m2repository" \ "extras;google;google_play_services"; -ENV LD_LIBRARY_PATH "/home/jenkins/android_home/emulator/lib64/qt/lib" - # Install Node.JS SHELL ["/bin/bash", "-l", "-c"] RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash && \ @@ -93,14 +89,23 @@ RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | b ENV PATH "$NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH" -#Installation of 'yarn'; 'appium' & 'wd' for Integration Tests -RUN npm install --global \ - yarn \ - appium \ - wd +#Installation of Updated 'npm' +RUN npm install --global npm #Install Ruby and Fastlane +RUN for key in 409B6B1796C275462A1703113804BB82D39DC0E3 \ + 7D2BAF1CF37B13E2069D6956105BD0E739499BDB; do \ + for server in "hkp://keys.gnupg.net" \ + "hkp://p80.pool.sks-keyservers.net:80" \ + "pgp.mit.edu" \ + "hkp://keyserver.ubuntu.com:80"; do \ + gpg2 --keyserver "${server}" --recv-keys "${key}" || echo "Trying new server..."; \ + done; \ + done +RUN curl -sSL https://get.rvm.io | bash -s stable --ruby=2.4.3 --autolibs=read-fail && \ + source /home/jenkins/.rvm/scripts/rvm \ + rvm reload && \ + gem install fastlane --version 2.126.0 -RUN gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \ - curl -sSL https://get.rvm.io | bash -s stable --ruby=2.4.1 --autolibs=read-fail -RUN gem install fastlane \ No newline at end of file +#Install AWS CLI +RUN pip install awscli --upgrade --user \ No newline at end of file diff --git a/Jenkinsfile.upload b/Jenkinsfile.upload index c2a0912e9..004aac602 100644 --- a/Jenkinsfile.upload +++ b/Jenkinsfile.upload @@ -1,66 +1,73 @@ #!/bin/env groovy - +@Library(['cliqz-shared-library@v1.2']) _ +properties([ + parameters([ + choice(choices: ['cliqz', 'lumen'], defaultValue: 'lumen', description: 'Which Product ?', name: 'product') + ]) +]) node('master'){ def imageName = 'android-browser' - def branchName = "${BRANCH_NAME}" - stage('Checkout'){ checkout scm } - stage('Build docker image') { docker.build(imageName, '--build-arg UID=`id -u` --build-arg GID=`id -g` .') } - docker.image(imageName).inside() { - stage('Extension') { - sh ''' - set -x - set -e - yarn - npm run bundle - ''' - } - - withEnv(["GRADLE_USER_HOME=${pwd()}/gradle_home","BN=${branchName}"]) { - withCredentials([ - file(credentialsId: '263e59fb-e9de-4e51-962c-0237c6ee167b', variable: 'CERT_PATH'), - string(credentialsId: '60354bba-8ed0-4df9-8f8e-5be7454c1680', variable: 'CERT_PASS'), - file(credentialsId: '2939d2e1-dd9a-4097-adc2-430e3d67157a', variable: 'PLAY_STORE_CERT')]) { - sh 'echo $BN' - if ("${BN}".contains("-re")) { - stage('Compile') { - sh './gradlew clean assembleStandardFatRelease' - } - }else { + try { + stage('Extension') { + sh '''#!/bin/bash -l + set -x + set -e + npm ci + npm run bundle + ''' + } + withEnv(["GRADLE_USER_HOME=${pwd()}/gradle_home"]) { + withCredentials([ + file(credentialsId: '263e59fb-e9de-4e51-962c-0237c6ee167b', variable: 'CERT_PATH'), + string(credentialsId: '60354bba-8ed0-4df9-8f8e-5be7454c1680', variable: 'CERT_PASS'), + file(credentialsId: '2939d2e1-dd9a-4097-adc2-430e3d67157a', variable: 'PLAY_STORE_CERT'), + file(credentialsId: '3796eb16-42cd-4551-a5a5-c4fe3a18719a', variable: 'CLIQZ_CONFIG_JSON'), + file(credentialsId: '6006a534-9f2e-4ba8-93f9-f0f27c0713df', variable: 'GOOGLE_SERVICES')]) { stage('Compile and Upload') { - sh '''#!/bin/bash -l - set -x - set -e - fastlane android alpha - ''' + sh '''#!/bin/bash -l + set -x + set -e + cp $CLIQZ_CONFIG_JSON app/cliqz-config.json + cp $GOOGLE_SERVICES app/google-services.json + ''' + if(params.product == "cliqz") { + sh '''#!/bin/bash -l + set -x + set -e + export APP_PACKAGE="com.cliqz.browser" + fastlane android internal_cliqz + ''' + } + if(params.product == "lumen") { + sh '''#!/bin/bash -l + set -x + set -e + export APP_PACKAGE="com.cliqz.lumen" + fastlane android internal_lumen + ''' + } + } } } - } - } - - } - if ("${branchName}".contains("-re")) { - def id = "Cliqz_Browser_android"+"${branchName}".substring("${branchName}".indexOf("v"), "${branchName}".indexOf("-")) - stage('Upload') { - withCredentials([ - [ - $class : 'UsernamePasswordMultiBinding', - credentialsId : 'f1732e5f-3e84-47ad-9286-a5fa6657ec43', - passwordVariable: 'AWS_SECRET_ACCESS_KEY', - usernameVariable: 'AWS_ACCESS_KEY_ID', - ] - ]) { - def s3Path = 's3://repository.cliqz.com/dist/android/release/apk' - def apkPath = "app/build/outputs/apk/standardFat/release/app-standard-fat-release.apk" - - sh "aws s3 cp --acl public-read --acl bucket-owner-full-control ${apkPath} ${s3Path}/${id}.apk" - sh "aws s3 cp --acl public-read --acl bucket-owner-full-control ${s3Path}/${id}.apk ${s3Path}/latest.apk" + } finally { + stage('Upload Artifacts and Clean Up') { + archiveArtifacts allowEmptyArchive: true, artifacts: 'app/build/**/*.apk' + sh'''#!/bin/bash -l + set -x + set -e + rm -f app/cliqz-config.json + rm -f app/google-services.json + rm -rf app/build + rm -rf jsengine/* + rm -rf gradle_home/ + ''' } } } diff --git a/app/build.gradle b/app/build.gradle index d31f0219e..a205a2c01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { } defaultConfig { - versionCode 106 + versionCode 1 versionName "1.8.4" multiDexEnabled true diff --git a/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt b/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt index 9ec1a77cc..80c2ba62a 100644 --- a/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt +++ b/buildSrc/src/main/java/com/cliqz/gradle/CliqzPlugin.kt @@ -21,10 +21,9 @@ class CliqzPlugin: Plugin { } } - val defaultVersionCode = android.defaultConfig.versionCode project.afterEvaluate { android.applicationVariants.forEach { variant -> - setVersionCode(defaultVersionCode, variant) + setVersionCode(variant) createCliqzConfigTasks(project, variant) } } @@ -54,14 +53,17 @@ class CliqzPlugin: Plugin { } } - private fun setVersionCode(defaultVersionCode: Int, variant: ApplicationVariant) { + private fun setVersionCode(variant: ApplicationVariant) { + val buildNumber = System.getenv("BUILD_NUMBER")?.toIntOrNull() + if (buildNumber == null) return; + val versionCode = 110 + buildNumber val apiVersion = variant.productFlavors[0].versionCode variant.outputs.forEach { output -> val abi = output.filters.find { it.filterType == OutputFile.ABI } abi?.let { val abiVersion = ABI_CODES[it.identifier] (output as ApkVariantOutput).versionCodeOverride = - defaultVersionCode * 100 + apiVersion * 10 + abiVersion!! + versionCode * 100 + apiVersion * 10 + abiVersion!! } } } diff --git a/fastlane/Appfile b/fastlane/Appfile index 4d0bab144..c8d9ea785 100644 --- a/fastlane/Appfile +++ b/fastlane/Appfile @@ -1,2 +1,2 @@ json_key_file(ENV["PLAY_STORE_CERT"]) # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one -package_name("com.cliqz.browser") # e.g. com.krausefx.app +package_name(ENV["APP_PACKAGE"]) # e.g. com.krausefx.app diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f0396d1e2..e7bf0d5fa 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -7,17 +7,28 @@ # # Uncomment the line if you want fastlane to automatically update itself - update_fastlane +# update_fastlane default_platform(:android) platform :android do desc "Submit a new alpha Build to the Google Play Store" - lane :alpha do - gradle(task: "clean assembleStandardArmRelease assembleStandardX6Release") + lane :internal_lumen do + gradle(task: "clean assembleLumenRelease") upload_to_play_store( apk_paths:ENV["GRADLE_ALL_APK_OUTPUT_PATHS"], - track:"alpha", + track:"internal", + skip_upload_metadata: true, + skip_upload_images: true, + skip_upload_screenshots: true, + ) + end + + lane :internal_cliqz do + gradle(task: "clean assembleCliqzRelease") + upload_to_play_store( + apk_paths:ENV["GRADLE_ALL_APK_OUTPUT_PATHS"], + track:"internal", skip_upload_metadata: true, skip_upload_images: true, skip_upload_screenshots: true, From fc553e597ea9fd5b84650fc308eeac2376e699c0 Mon Sep 17 00:00:00 2001 From: Jayesh Solanki Date: Wed, 3 Jul 2019 11:15:47 +0200 Subject: [PATCH 10/57] AP-360 Implement design changes on subscription screen (#138) * AP-360 Implement design changes on subscription screen * Tint close drawable instead of having multiple colored drawable --- .../cliqz/res/layout/activity_overview.xml | 3 +- app/src/lumen/res/drawable/ic_close_black.xml | 5 -- .../subscription_button_background.xml | 4 +- .../res/drawable/subscription_item_border.xml | 10 ++-- .../subscription_item_hollow_border.xml | 6 +-- .../lumen/res/layout/fragment_purchase.xml | 5 +- .../subscription_product_row_default.xml | 47 ++++++++++--------- .../subscription_product_row_highlighted.xml | 47 ++++++++++--------- app/src/lumen/res/values/colors.xml | 3 ++ app/src/main/res/drawable/ic_clear_white.xml | 9 ---- app/src/main/res/values/styles.xml | 7 ++- 11 files changed, 72 insertions(+), 74 deletions(-) delete mode 100644 app/src/lumen/res/drawable/ic_close_black.xml delete mode 100644 app/src/main/res/drawable/ic_clear_white.xml diff --git a/app/src/cliqz/res/layout/activity_overview.xml b/app/src/cliqz/res/layout/activity_overview.xml index c73178c0c..972b871f6 100644 --- a/app/src/cliqz/res/layout/activity_overview.xml +++ b/app/src/cliqz/res/layout/activity_overview.xml @@ -32,7 +32,8 @@ android:layout_width="@dimen/icon_width" android:layout_height="@dimen/icon_height" android:layout_gravity="center" - app:srcCompat="@drawable/ic_clear_white"/> + android:tint="@android:color/white" + app:srcCompat="@drawable/ic_clear_black"/> - - diff --git a/app/src/lumen/res/drawable/subscription_button_background.xml b/app/src/lumen/res/drawable/subscription_button_background.xml index e57dc6db5..bad8929e1 100644 --- a/app/src/lumen/res/drawable/subscription_button_background.xml +++ b/app/src/lumen/res/drawable/subscription_button_background.xml @@ -1,5 +1,5 @@ - - + + diff --git a/app/src/lumen/res/drawable/subscription_item_border.xml b/app/src/lumen/res/drawable/subscription_item_border.xml index 829163c63..165a2ca45 100644 --- a/app/src/lumen/res/drawable/subscription_item_border.xml +++ b/app/src/lumen/res/drawable/subscription_item_border.xml @@ -4,12 +4,12 @@ + android:bottom="4dp" + android:left="4dp" + android:right="4dp" + android:top="4dp"> - + diff --git a/app/src/lumen/res/drawable/subscription_item_hollow_border.xml b/app/src/lumen/res/drawable/subscription_item_hollow_border.xml index c03b2ff4e..e415ec901 100644 --- a/app/src/lumen/res/drawable/subscription_item_hollow_border.xml +++ b/app/src/lumen/res/drawable/subscription_item_hollow_border.xml @@ -3,9 +3,9 @@ diff --git a/app/src/lumen/res/layout/fragment_purchase.xml b/app/src/lumen/res/layout/fragment_purchase.xml index c07cdce7a..8aff3d6fc 100644 --- a/app/src/lumen/res/layout/fragment_purchase.xml +++ b/app/src/lumen/res/layout/fragment_purchase.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#1B1F3D" + android:background="@color/lumen_color_background" tools:context="com.cliqz.browser.purchases.PurchaseFragment"> + android:tint="@android:color/white" + app:srcCompat="@drawable/ic_clear_black" /> @@ -15,7 +14,7 @@ android:id="@+id/horizontal_row" android:layout_width="match_parent" android:layout_height="2dp" - android:layout_marginTop="45dp" + android:layout_marginTop="50dp" android:background="@drawable/subscription_item_hollow_border" app:layout_constraintEnd_toStartOf="parent" app:layout_constraintStart_toEndOf="parent" @@ -25,15 +24,15 @@ android:id="@+id/title" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="14dp" + android:layout_marginStart="18dp" android:layout_marginEnd="14dp" android:ellipsize="end" android:maxLines="1" android:textAllCaps="true" android:textColor="@color/white" - android:textSize="19sp" + android:textSize="15sp" android:textStyle="bold" - app:layout_constraintBottom_toTopOf="@+id/horizontal_row" + app:layout_constraintBottom_toBottomOf="@+id/horizontal_row" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" @@ -44,10 +43,11 @@ android:id="@+id/price" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="14dp" + android:layout_marginTop="26dp" android:textAllCaps="true" android:textColor="@color/white" - android:textSize="19sp" + android:textSize="15sp" + android:textStyle="bold" app:layout_constraintStart_toStartOf="@+id/title" app:layout_constraintTop_toBottomOf="@+id/horizontal_row" tools:text="4,99 $/MONTH" /> @@ -55,29 +55,30 @@