diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 1da458a..c52bf43 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,11 +16,11 @@ jobs: stale-issue-message: 'This issue is being marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' stale-issue-label: 'stale' - exempt-issue-labels: 'stale-exempt' # Comma seperated list of labels that should be used to exempt an issue from being marked as stale or being closed + exempt-issue-labels: 'stale-exempt' # Comma separated list of labels that should be used to exempt an issue from being marked as stale or being closed stale-pr-message: 'This Pull Request is being marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' stale-pr-label: 'stale' - exempt-pr-labels: 'stale-exempt' # Comma seperated list of labels that should be used to exempt a PR from being marked as stale or being closed + exempt-pr-labels: 'stale-exempt' # Comma separated list of labels that should be used to exempt a PR from being marked as stale or being closed days-before-stale: 30 days-before-close: 5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 7db2d2a..cd2cb6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.0] - 2023-05-01 +### Updates +- Update dependencies +- Update or remove deprecations +- Update to ViewBinding and remove Kotlinx Synthetics +- Small other cleanups + ## [1.0.0] - 2020-07-15 ### Mailchimp SDK is now out of Beta. diff --git a/Gemfile.lock b/Gemfile.lock index 519dafa..0c67cfc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,61 +1,102 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.2) - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) + CFPropertyList (3.0.6) + rexml + addressable (2.8.4) + public_suffix (>= 2.0.2, < 6.0) + artifactory (3.0.15) atomos (0.1.3) - babosa (1.0.3) - claide (1.0.3) + aws-eventstream (1.2.0) + aws-partitions (1.758.0) + aws-sdk-core (3.171.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.64.0) + aws-sdk-core (~> 3, >= 3.165.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.121.0) + aws-sdk-core (~> 3, >= 3.165.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.4) + aws-sigv4 (1.5.2) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + claide (1.1.0) colored (1.2) colored2 (3.1.2) - commander-fastlane (4.4.6) - highline (~> 1.7.2) - declarative (0.0.10) - declarative-option (0.1.0) - digest-crc (0.4.1) + commander (4.6.0) + highline (~> 2.0.0) + declarative (0.0.20) + digest-crc (0.6.4) + rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.5) - emoji_regex (1.0.1) - excon (0.71.1) - faraday (0.17.3) - multipart-post (>= 1.2, < 3) - faraday-cookie_jar (0.0.6) - faraday (>= 0.7.4) + dotenv (2.8.1) + emoji_regex (3.2.3) + excon (0.99.0) + faraday (1.10.3) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) http-cookie (~> 1.0.0) - faraday_middleware (0.13.1) - faraday (>= 0.7.4, < 1.0) - fastimage (2.1.7) - fastlane (2.139.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + fastimage (2.2.6) + fastlane (2.212.2) CFPropertyList (>= 2.3, < 4.0.0) - addressable (>= 2.3, < 3.0.0) - babosa (>= 1.0.2, < 2.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) colored - commander-fastlane (>= 4.4.6, < 5.0.0) + commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) - emoji_regex (>= 0.1, < 2.0) + emoji_regex (>= 0.1, < 4.0) excon (>= 0.71.0, < 1.0.0) - faraday (~> 0.17) + faraday (~> 1.0) faraday-cookie_jar (~> 0.0.6) - faraday_middleware (~> 0.13.1) + faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) gh_inspector (>= 1.1.2, < 2.0.0) - google-api-client (>= 0.29.2, < 0.37.0) - google-cloud-storage (>= 1.15.0, < 2.0.0) - highline (>= 1.7.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) json (< 3.0.0) - jwt (~> 2.1.0) + jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) - multi_xml (~> 0.5) multipart-post (~> 2.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) plist (>= 3.1.0, < 4.0.0) - public_suffix (~> 2.0.0) - rubyzip (>= 1.3.0, < 2.0.0) + rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) simctl (~> 1.6.3) - slack-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 2.0.0, < 3.0.0) terminal-table (>= 1.4.5, < 2.0.0) tty-screen (>= 0.6.3, < 1.0.0) @@ -65,88 +106,106 @@ GEM xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) gh_inspector (1.1.3) - google-api-client (0.36.4) + google-apis-androidpublisher_v3 (0.41.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.0) addressable (~> 2.5, >= 2.5.1) - googleauth (~> 0.9) - httpclient (>= 2.8.1, < 3.0) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) mini_mime (~> 1.0) representable (~> 3.0) - retriable (>= 2.0, < 4.0) - signet (~> 0.12) - google-cloud-core (1.4.1) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) + google-cloud-core (1.6.0) google-cloud-env (~> 1.0) - google-cloud-env (1.3.0) - faraday (~> 0.11) - google-cloud-storage (1.25.0) - addressable (~> 2.5) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) + addressable (~> 2.8) digest-crc (~> 0.4) - google-api-client (~> 0.33) - google-cloud-core (~> 1.2) - googleauth (~> 0.9) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (0.10.0) - faraday (~> 0.12) + googleauth (1.5.2) + faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) - signet (~> 0.12) - highline (1.7.10) - http-cookie (1.0.3) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) - json (2.3.0) - jwt (2.1.0) + jmespath (1.6.2) + json (2.6.3) + jwt (2.7.0) memoist (0.16.2) - mini_magick (4.10.1) - mini_mime (1.0.2) - multi_json (1.14.1) - multi_xml (0.6.0) + mini_magick (4.12.0) + mini_mime (1.1.2) + multi_json (1.15.0) multipart-post (2.0.0) - nanaimo (0.2.6) - naturally (2.2.0) - os (1.0.1) - plist (3.5.0) - public_suffix (2.0.5) - representable (3.0.4) + nanaimo (0.3.0) + naturally (2.2.1) + optparse (0.1.1) + os (1.1.4) + plist (3.7.0) + public_suffix (5.0.1) + rake (13.0.6) + representable (3.2.0) declarative (< 0.1.0) - declarative-option (< 0.2.0) + trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) + rexml (3.2.5) rouge (2.0.7) - rubyzip (1.3.0) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) security (0.1.3) - signet (0.12.0) - addressable (~> 2.3) - faraday (~> 0.9) + signet (0.17.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - simctl (1.6.7) + simctl (1.6.10) CFPropertyList naturally - slack-notifier (2.3.2) terminal-notifier (2.0.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - tty-cursor (0.7.0) - tty-screen (0.7.0) - tty-spinner (0.9.2) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.6) - unicode-display_width (1.6.0) + unf_ext (0.0.8.2) + unicode-display_width (1.8.0) + webrick (1.8.1) word_wrap (1.0.0) - xcodeproj (1.14.0) + xcodeproj (1.22.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.2.6) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) xcpretty (0.3.0) rouge (~> 2.0.7) - xcpretty-travis-formatter (1.0.0) + xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) PLATFORMS @@ -156,4 +215,4 @@ DEPENDENCIES fastlane BUNDLED WITH - 2.0.2 + 2.4.12 diff --git a/LICENSE b/LICENSE index 1ac231b..c259b68 100644 --- a/LICENSE +++ b/LICENSE @@ -25,7 +25,7 @@ b) You must cause any modified files to carry prominent notices stating that You c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. -5. Submission of Contributions. Any Contribution submitted for inclusion in the Work by You to Mailchimp shall be made under the terms and conditions of the Individual Contributor License Agreement orthe Software Grant and Corporate Contributor License Agreement, as applicable. +5. Submission of Contributions. Any Contribution submitted for inclusion in the Work by You to Mailchimp shall be made under the terms and conditions of the Individual Contributor License Agreement or the Software Grant and Corporate Contributor License Agreement, as applicable. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of Mailchimp, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. diff --git a/README.md b/README.md index 62c3d57..fb32317 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ repositories { Next add the Mailchimp SDK to your list of dependencies. Below is a gradle example ```gradle -implementation 'com.github.mailchimp:Mailchimp-SDK-Android:1.0.0' +implementation 'com.github.mailchimp:Mailchimp-SDK-Android:1.1.0' ``` ### Initializing the SDK diff --git a/build.gradle b/build.gradle index b7e8fde..d897c87 100644 --- a/build.gradle +++ b/build.gradle @@ -12,18 +12,20 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.50' - ext.kotlinx_version = '1.0.2' - ext.work_version = '2.0.1' - ext.retrofit_version = '2.3.0' - ext.nav_version = "2.1.0" + ext { + kotlin_version = '1.8.10' + work_version = '2.8.1' + retrofit_version = '2.9.0' + nav_version = '2.5.3' + } + repositories { google() - jcenter() - + mavenCentral() } + dependencies { - classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.android.tools.build:gradle:8.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -35,8 +37,7 @@ buildscript { allprojects { repositories { google() - jcenter() - + mavenCentral() } } diff --git a/fastlane/README.md b/fastlane/README.md index 4d1ed02..8ae53b9 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -1,44 +1,56 @@ fastlane documentation -================ +---- + # Installation Make sure you have the latest version of the Xcode command line tools installed: -``` +```sh xcode-select --install ``` -Install _fastlane_ using -``` -[sudo] gem install fastlane -NV -``` -or alternatively using `brew cask install fastlane` +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) # Available Actions + ## Android + ### android test + +```sh +[bundle exec] fastlane android test ``` -fastlane android test -``` + Runs all the tests + ### android publish + +```sh +[bundle exec] fastlane android publish ``` -fastlane android publish -``` + Publish a new version to our artifact repo + ### android build_and_package + +```sh +[bundle exec] fastlane android build_and_package ``` -fastlane android build_and_package -``` + Build the sdk and package the aar + ### android build_ui_tests + +```sh +[bundle exec] fastlane android build_ui_tests ``` -fastlane android build_ui_tests -``` + Build debug and android test ---- -This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. -More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). -The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. + +More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). + +The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/gradle.properties b/gradle.properties index 6a7eb1d..d555069 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,3 +30,6 @@ android.useAndroidX=true android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=true +android.nonFinalResIds=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f6b961f..7454180 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bed8464..837b390 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,17 +1,6 @@ -# -# Licensed under the Mailchimp Mobile SDK License Agreement (the "License"); -# you may not use this file except in compliance with the License. Unless -# required by applicable law or agreed to in writing, software distributed -# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, either or express or implied. -# -# See the License for the specific language governing permissions and -# limitations under the License. -# - -#Tue Aug 27 14:32:24 EDT 2019 +#Fri Apr 28 11:17:32 MDT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/gradlew b/gradlew index cccdd3d..1b6c787 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/mailchimp-sdk-api/build.gradle b/mailchimp-sdk-api/build.gradle index d349f8a..dc0438f 100644 --- a/mailchimp-sdk-api/build.gradle +++ b/mailchimp-sdk-api/build.gradle @@ -9,22 +9,19 @@ * limitations under the License. */ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +plugins { + id 'com.android.library' + id 'kotlin-android' +} android { - compileSdkVersion 28 - + compileSdkVersion 33 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } buildTypes { @@ -34,24 +31,30 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + } + testOptions { unitTests.returnDefaultValues = true } + namespace 'com.mailchimp.sdk.api' } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "com.squareup.retrofit2:retrofit:$retrofit_version" implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" - implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' - - testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:2.23.0' - testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0" -} + implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0' -repositories { - mavenCentral() + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.mockito:mockito-core:5.3.1' + testImplementation "org.mockito.kotlin:mockito-kotlin:4.1.0" } diff --git a/mailchimp-sdk-api/src/main/AndroidManifest.xml b/mailchimp-sdk-api/src/main/AndroidManifest.xml index 02ad357..44dc069 100644 --- a/mailchimp-sdk-api/src/main/AndroidManifest.xml +++ b/mailchimp-sdk-api/src/main/AndroidManifest.xml @@ -9,16 +9,4 @@ ~ limitations under the License. --> - - - + diff --git a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/di/ApiDependencies.kt b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/di/ApiDependencies.kt index 66ebdfa..5fc0b3d 100644 --- a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/di/ApiDependencies.kt +++ b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/di/ApiDependencies.kt @@ -14,26 +14,34 @@ package com.mailchimp.sdk.api.di import com.google.gson.Gson import com.google.gson.GsonBuilder import com.mailchimp.sdk.api.ApiAuthInterceptor -import com.mailchimp.sdk.api.SdkWebService import com.mailchimp.sdk.api.RetrofitBuilder +import com.mailchimp.sdk.api.SdkWebService import com.mailchimp.sdk.api.gson.BasicGsonTypeDecoder import com.mailchimp.sdk.api.gson.GsonInterfaceAdapter +import com.mailchimp.sdk.api.model.mergefields.Address +import com.mailchimp.sdk.api.model.mergefields.MergeFieldValue +import com.mailchimp.sdk.api.model.mergefields.StringMergeFieldValue import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty -import com.mailchimp.sdk.api.model.mergefields.* -import okhttp3.logging.HttpLoggingInterceptor interface ApiDependencies { val sdkWebService: SdkWebService val gson: Gson } -open class ApiImplementation(private val sdkKey: String, private val shard: String, private val isDebug: Boolean) : ApiDependencies { - override val gson: Gson by lazy { GsonBuilder().registerTypeAdapter(MergeFieldValue::class.java, mergeFieldValueTypeAdapter).create() } - override val sdkWebService by lazy { retrofit.create(SdkWebService::class.java) } +open class ApiImplementation(private val sdkKey: String, private val shard: String, private val isDebug: Boolean) : + ApiDependencies { + override val gson: Gson by lazy { + GsonBuilder().registerTypeAdapter( + MergeFieldValue::class.java, + mergeFieldValueTypeAdapter + ).create() + } + override val sdkWebService: SdkWebService by lazy { retrofit.create(SdkWebService::class.java) } // WebService Dependencies private val okHttpLoggingInterceptor by lazy { @@ -52,7 +60,13 @@ open class ApiImplementation(private val sdkKey: String, private val shard: Stri } private val gsonConverterFactory: GsonConverterFactory by lazy { GsonConverterFactory.create(gson) } - private val retrofit: Retrofit by lazy { RetrofitBuilder().createInstance(shard, gsonConverterFactory, okHttpClient) } + private val retrofit: Retrofit by lazy { + RetrofitBuilder().createInstance( + shard, + gsonConverterFactory, + okHttpClient + ) + } // Gson Dependencies private val mergeFieldValueTypeAdapter by Dependency { GsonInterfaceAdapter(mergeFieldTypeDecoder) } diff --git a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonInterfaceAdapter.kt b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonInterfaceAdapter.kt index 1d46ab7..b22b034 100644 --- a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonInterfaceAdapter.kt +++ b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonInterfaceAdapter.kt @@ -45,7 +45,7 @@ class GsonInterfaceAdapter(private val typeDecoder: GsonTypeDecoder) : if (!wrapper.has(typeEncoding)) { throw IllegalStateException( "Json object $wrapper does not contain expected $typeEncoding property. Without " + - "the $typeEncoding property, it is unknown how to deserialize this object." + "the $typeEncoding property, it is unknown how to deserialize this object." ) } diff --git a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonTypeDecoder.kt b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonTypeDecoder.kt index f20dd89..b07c5b6 100644 --- a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonTypeDecoder.kt +++ b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/gson/GsonTypeDecoder.kt @@ -17,7 +17,10 @@ interface GsonTypeDecoder { fun getEncodedName(classIn: Class<*>): String } -class BasicGsonTypeDecoder private constructor(private val encodingName: String, private val encodingMap: Map>) : GsonTypeDecoder { +class BasicGsonTypeDecoder private constructor( + private val encodingName: String, + private val encodingMap: Map> +) : GsonTypeDecoder { private val classMap = encodingMap.entries.associateBy({ it.value }) { it.key } @@ -31,7 +34,7 @@ class BasicGsonTypeDecoder private constructor(private val encodingName: String, } else { throw IllegalStateException( "Gson Mapping does not exist for type $serializedType, " + - "please make sure you registered a mapping for this type in your GsonTypeDecoder!" + "please make sure you registered a mapping for this type in your GsonTypeDecoder!" ) } } @@ -42,7 +45,7 @@ class BasicGsonTypeDecoder private constructor(private val encodingName: String, } else { throw IllegalStateException( "Gson mapping does not exist for class ${classIn.simpleName}, " + - "please make sure you registered a mapping for this class in your GsonTypeDecoder!" + "please make sure you registered a mapping for this class in your GsonTypeDecoder!" ) } } diff --git a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/Contact.kt b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/Contact.kt index 04af150..d34efa9 100644 --- a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/Contact.kt +++ b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/Contact.kt @@ -49,14 +49,17 @@ data class Contact private constructor( companion object { const val ACTIVE_TAG_STATUS = "active" const val INACTIVE_TAG_STATUS = "inactive" + /** * Tag marking the user as an Android User. */ const val ANDROID_TAG = "Android" + /** * Tag marking the user as a Phone user. */ const val PHONE_TAG = "Phone" + /** * Tag marking the user as a Tablet user. */ @@ -189,6 +192,7 @@ enum class ContactStatus { */ @SerializedName("subscribed") SUBSCRIBED, + /** * Indicated that a contact is not subscribed to marketing campaigns and will only receive * transactional information. diff --git a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/mergefields/Country.kt b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/mergefields/Country.kt index 05f677d..770f152 100644 --- a/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/mergefields/Country.kt +++ b/mailchimp-sdk-api/src/main/java/com/mailchimp/sdk/api/model/mergefields/Country.kt @@ -11,8 +11,6 @@ package com.mailchimp.sdk.api.model.mergefields -import kotlin.String - enum class Country(val countryName: String, val code: String) { USA("USA", "US"), @@ -403,9 +401,9 @@ enum class Country(val countryName: String, val code: String) { SOUTH_AFRICA("South Africa", "ZA"), SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS( - "South Georgia and the South Sandwich Islands", - "GS" -), + "South Georgia and the South Sandwich Islands", + "GS" + ), SOUTH_KOREA("South Korea", "KR"), diff --git a/mailchimp-sdk-api/src/test/java/InterfaceAdapterTest.kt b/mailchimp-sdk-api/src/test/java/InterfaceAdapterTest.kt index 6b6f9a9..4a0a4be 100644 --- a/mailchimp-sdk-api/src/test/java/InterfaceAdapterTest.kt +++ b/mailchimp-sdk-api/src/test/java/InterfaceAdapterTest.kt @@ -95,7 +95,8 @@ class InterfaceAdapterTest { val adapter = GsonInterfaceAdapter(standardTypeDecoder()) val mergeField = StringMergeFieldValue("Jabroni") - val serialized = adapter.serialize(mergeField, StringMergeFieldValue::class.java, GsonContextImpl()) as JsonObject + val serialized = + adapter.serialize(mergeField, StringMergeFieldValue::class.java, GsonContextImpl()) as JsonObject assertEquals("Jabroni", serialized.get("value").asString) assertEquals("string", serialized.get("type").asString) } diff --git a/mailchimp-sdk-audience/build.gradle b/mailchimp-sdk-audience/build.gradle index 56c3d1d..53dadf9 100644 --- a/mailchimp-sdk-audience/build.gradle +++ b/mailchimp-sdk-audience/build.gradle @@ -9,22 +9,19 @@ * limitations under the License. */ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +plugins { + id 'com.android.library' + id 'kotlin-android' +} android { - compileSdkVersion 28 - + compileSdkVersion 33 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } buildTypes { @@ -34,10 +31,20 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + } + testOptions { unitTests.returnDefaultValues = true } + namespace 'com.mailchimp.sdk.audience' } dependencies { @@ -46,20 +53,20 @@ dependencies { implementation project(':mailchimp-sdk-core') implementation project(':mailchimp-sdk-api') - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "com.squareup.retrofit2:retrofit:$retrofit_version" - implementation 'com.google.code.gson:gson:2.8.5' + implementation 'com.google.code.gson:gson:2.10.1' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation "androidx.work:work-testing:$work_version" + implementation "androidx.work:work-runtime-ktx:$work_version" + implementation 'com.jakewharton.timber:timber:5.0.1' - testImplementation 'junit:junit:4.12' - testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0" + testImplementation 'junit:junit:4.13.2' testImplementation "androidx.work:work-testing:$work_version" -} -repositories { - mavenCentral() + testImplementation "org.mockito.kotlin:mockito-kotlin:4.1.0" + + androidTestImplementation 'androidx.test:runner:1.5.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation "androidx.work:work-testing:$work_version" } diff --git a/mailchimp-sdk-audience/src/main/AndroidManifest.xml b/mailchimp-sdk-audience/src/main/AndroidManifest.xml index 9714671..44dc069 100644 --- a/mailchimp-sdk-audience/src/main/AndroidManifest.xml +++ b/mailchimp-sdk-audience/src/main/AndroidManifest.xml @@ -9,5 +9,4 @@ ~ limitations under the License. --> - + diff --git a/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/AudienceWorker.kt b/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/AudienceWorker.kt index 10af764..ac8f4be 100644 --- a/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/AudienceWorker.kt +++ b/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/AudienceWorker.kt @@ -25,6 +25,7 @@ class AudienceWorker(appContext: Context, workParams: WorkerParameters) : SdkWor companion object { const val KEY_INPUT_CONTACT = "contact" + /* * We will not retry the request if we receive the following error codes. * 400: Malformed request. @@ -44,7 +45,11 @@ class AudienceWorker(appContext: Context, workParams: WorkerParameters) : SdkWor Timber.d("Creating or updating user failed for %s, will not retry", contact.emailAddress) Response.FAILURE_CONTINUE_CHAIN } else { - Timber.d("Creating or updating user failed for %s, will retry if not attempt %s", contact.emailAddress, maxRetries) + Timber.d( + "Creating or updating user failed for %s, will retry if not attempt %s", + contact.emailAddress, + maxRetries + ) Response.RETRY } } diff --git a/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdk.kt b/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdk.kt index e03b4a8..7825d0c 100644 --- a/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdk.kt +++ b/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdk.kt @@ -19,7 +19,7 @@ import com.mailchimp.sdk.core.MailchimpSdkConfiguration import com.mailchimp.sdk.core.work.WorkProcessor import com.mailchimp.sdk.core.work.WorkStatusProvider import timber.log.Timber -import java.util.* +import java.util.UUID class WorkManagerAudienceSdk( private val workProcessor: WorkProcessor, @@ -122,7 +122,7 @@ class WorkManagerAudienceSdk( val builder = Contact.Builder(contact) builder.addTag(Contact.ANDROID_TAG) - if (sdkConfiguration.context.resources.getBoolean(R.bool.isTablet)) { + if (sdkConfiguration.context.resources.getBoolean(com.mailchimp.mailchimp_sdk_core.R.bool.isTablet)) { builder.addTag(Contact.TABLET_TAG) } else { builder.addTag(Contact.PHONE_TAG) diff --git a/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/di/AudienceDependencies.kt b/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/di/AudienceDependencies.kt index ba17a34..ec83034 100644 --- a/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/di/AudienceDependencies.kt +++ b/mailchimp-sdk-audience/src/main/java/com/mailchimp/sdk/audience/di/AudienceDependencies.kt @@ -42,7 +42,12 @@ class AudienceImplementation private constructor( private var instance: AudienceImplementation? = null /* Don't use this unless you're sure you should be */ - fun initialize(coreDependencies: CoreDependencies, apiDependencies: ApiDependencies, mailchimpSdkConfiguration: MailchimpSdkConfiguration, override: Boolean = false): AudienceImplementation { + fun initialize( + coreDependencies: CoreDependencies, + apiDependencies: ApiDependencies, + mailchimpSdkConfiguration: MailchimpSdkConfiguration, + override: Boolean = false + ): AudienceImplementation { synchronized(this) { if (instance == null || override) { instance = AudienceImplementation(coreDependencies, apiDependencies, mailchimpSdkConfiguration) diff --git a/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkRequestTest.kt b/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkRequestTest.kt index 0fc3fd8..eec38c2 100644 --- a/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkRequestTest.kt +++ b/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkRequestTest.kt @@ -14,10 +14,10 @@ package com.mailchimp.sdk.audience import com.google.gson.Gson import com.mailchimp.sdk.api.model.Contact import com.mailchimp.sdk.audience.AudienceWorker.Companion.KEY_INPUT_CONTACT -import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.whenever -import org.junit.Assert.* +import org.junit.Assert.assertEquals import org.junit.Test +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever class AudienceWorkRequestTest { diff --git a/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkerTest.kt b/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkerTest.kt index 6721391..b02886b 100644 --- a/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkerTest.kt +++ b/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/AudienceWorkerTest.kt @@ -23,10 +23,14 @@ import com.mailchimp.sdk.audience.di.AudienceImplementation import com.mailchimp.sdk.core.MailchimpSdkConfiguration import com.mailchimp.sdk.core.di.CoreDependencies import com.mailchimp.sdk.core.work.SdkWorker -import com.nhaarman.mockitokotlin2.* import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever import retrofit2.Call import retrofit2.Response @@ -34,8 +38,8 @@ class AudienceWorkerTest { private val apiDependencies = mock() private val coreDependencies = mock() private val mailchimpConfiguration = mock() - lateinit var gson: Gson - lateinit var webService: SdkWebService + private lateinit var gson: Gson + private lateinit var webService: SdkWebService @Before fun setup() { diff --git a/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdkTest.kt b/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdkTest.kt index 57dafbb..41f9c8d 100644 --- a/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdkTest.kt +++ b/mailchimp-sdk-audience/src/test/java/com/mailchimp/sdk/audience/WorkManagerAudienceSdkTest.kt @@ -21,13 +21,21 @@ import com.mailchimp.sdk.api.model.mergefields.Address import com.mailchimp.sdk.audience.AudienceWorker.Companion.KEY_INPUT_CONTACT import com.mailchimp.sdk.core.MailchimpSdkConfiguration import com.mailchimp.sdk.core.work.WorkProcessor -import com.nhaarman.mockitokotlin2.* -import org.junit.Assert.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.mockito.Mock -import org.mockito.MockitoAnnotations.initMocks -import java.util.* +import org.mockito.MockitoAnnotations.openMocks +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import java.util.UUID /** * Tests that the audience sdk work manager implementation generates the right work requests and submits it to @@ -40,16 +48,19 @@ class WorkManagerAudienceSdkTest { @Mock private lateinit var processor: WorkProcessor + @Mock private lateinit var gson: Gson + @Mock private lateinit var audienceContract: AudienceSdkContract + @Mock private lateinit var audienceSdkConfiguration: MailchimpSdkConfiguration @Before fun setup() { - initMocks(this) + openMocks(this) } @Test @@ -261,7 +272,7 @@ class WorkManagerAudienceSdkTest { whenever(processor.submitWork(any())).thenReturn(generatedUUID to mock()) whenever(mockApp.resources).thenReturn(resource) - whenever(resource.getBoolean(R.bool.isTablet)).thenReturn(true) + whenever(resource.getBoolean(com.mailchimp.mailchimp_sdk_core.R.bool.isTablet)).thenReturn(true) sdk.createOrUpdateContact(contact) @@ -301,7 +312,7 @@ class WorkManagerAudienceSdkTest { whenever(processor.submitWork(any())).thenReturn(generatedUUID to mock()) whenever(mockApp.resources).thenReturn(resource) - whenever(resource.getBoolean(R.bool.isTablet)).thenReturn(false) + whenever(resource.getBoolean(com.mailchimp.mailchimp_sdk_core.R.bool.isTablet)).thenReturn(false) sdk.createOrUpdateContact(contact) diff --git a/mailchimp-sdk-core/build.gradle b/mailchimp-sdk-core/build.gradle index 19113fa..87454e9 100644 --- a/mailchimp-sdk-core/build.gradle +++ b/mailchimp-sdk-core/build.gradle @@ -9,19 +9,17 @@ * limitations under the License. */ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +plugins { + id 'com.android.library' + id 'kotlin-android' +} android { - compileSdkVersion 28 - + compileSdkVersion 33 defaultConfig { minSdkVersion 21 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -35,9 +33,20 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + } + testOptions { unitTests.returnDefaultValues = true } + + namespace 'com.mailchimp.mailchimp_sdk_core' } dependencies { @@ -45,24 +54,20 @@ dependencies { implementation project(path: ':mailchimp-sdk-api') - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation "androidx.core:core-ktx:$kotlinx_version" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - - api "androidx.work:work-runtime-ktx:$work_version" - api 'com.jakewharton.timber:timber:4.7.1' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.core:core-ktx:1.10.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - androidTestImplementation "androidx.work:work-testing:$work_version" - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation "androidx.work:work-runtime-ktx:$work_version" + implementation 'com.jakewharton.timber:timber:5.0.1' - testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:2.23.0' - testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0" - testImplementation 'android.arch.core:core-testing:1.1.1' + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.mockito:mockito-core:5.3.1' + testImplementation "org.mockito.kotlin:mockito-kotlin:4.1.0" + testImplementation 'androidx.arch.core:core-testing:2.2.0' -} -repositories { - mavenCentral() + androidTestImplementation "androidx.work:work-testing:$work_version" + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test:runner:1.5.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } diff --git a/mailchimp-sdk-core/src/main/AndroidManifest.xml b/mailchimp-sdk-core/src/main/AndroidManifest.xml index ce698b5..44dc069 100644 --- a/mailchimp-sdk-core/src/main/AndroidManifest.xml +++ b/mailchimp-sdk-core/src/main/AndroidManifest.xml @@ -9,5 +9,4 @@ ~ limitations under the License. --> - + diff --git a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/di/CoreDependencies.kt b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/di/CoreDependencies.kt index d2e3e43..d332ef3 100644 --- a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/di/CoreDependencies.kt +++ b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/di/CoreDependencies.kt @@ -12,11 +12,10 @@ package com.mailchimp.sdk.core.di import androidx.work.WorkManager -import com.mailchimp.sdk.api.di.ApiDependencies import com.mailchimp.sdk.api.di.Dependency +import com.mailchimp.sdk.core.work.WorkManagerStatusProvider import com.mailchimp.sdk.core.work.WorkProcessor import com.mailchimp.sdk.core.work.WorkStatusProvider -import com.mailchimp.sdk.core.work.WorkManagerStatusProvider interface CoreDependencies { val workProcessor: WorkProcessor diff --git a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorkRequest.kt b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorkRequest.kt index 05dfbe5..a84195f 100644 --- a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorkRequest.kt +++ b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorkRequest.kt @@ -11,7 +11,11 @@ package com.mailchimp.sdk.core.work -import androidx.work.* +import androidx.work.BackoffPolicy +import androidx.work.Constraints +import androidx.work.Data +import androidx.work.NetworkType +import androidx.work.OneTimeWorkRequest import java.util.concurrent.TimeUnit abstract class SdkWorkRequest { diff --git a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorker.kt b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorker.kt index 8cddc35..7d12a73 100644 --- a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorker.kt +++ b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/SdkWorker.kt @@ -27,10 +27,12 @@ abstract class SdkWorker(context: Context, workParams: WorkerParameters) : Worke * Max number to retry this worker. */ protected open val maxRetries = 5 + /** * The result code that will be used when the retry limit is reached. */ protected open val onRetryLimitReachedResponse = Response.FAILURE_CONTINUE_CHAIN + /** * The result code that will be used when a unhandled exception is thrown by the worker. */ @@ -88,9 +90,10 @@ abstract class SdkWorker(context: Context, workParams: WorkerParameters) : Worke * Retry the given worker after whatever the original backoff criteria and retry count is. If the retry count is * greater than the maximum, the task will be failed as #FAILURE_CONTINUE_CHAIN. * - * See default max retry account at SdkWorker#maxRetries (which can be overriden). + * See default max retry account at SdkWorker#maxRetries (which can be overridden). */ RETRY, + /** * Indicates that work completion failed, and should not be retried. * @@ -99,6 +102,7 @@ abstract class SdkWorker(context: Context, workParams: WorkerParameters) : Worke * pruned from WorkManager. */ FAILURE_END_CHAIN, + /** * Indicates that work completion failed, and should not be retried. * @@ -106,6 +110,7 @@ abstract class SdkWorker(context: Context, workParams: WorkerParameters) : Worke * well. New workers that are submitted after this will run, regardless of this failure. */ FAILURE_CONTINUE_CHAIN, + /** * Indicates that the worker successfully completed its work. */ diff --git a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkProcessor.kt b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkProcessor.kt index 9a8bda7..fdf0355 100644 --- a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkProcessor.kt +++ b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkProcessor.kt @@ -16,7 +16,7 @@ import androidx.work.ExistingWorkPolicy import androidx.work.Operation import androidx.work.WorkInfo import androidx.work.WorkManager -import java.util.* +import java.util.UUID open class WorkProcessor(private val workManager: WorkManager) { diff --git a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkStatusProvider.kt b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkStatusProvider.kt index 21ea9d6..1d1fc96 100644 --- a/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkStatusProvider.kt +++ b/mailchimp-sdk-core/src/main/java/com/mailchimp/sdk/core/work/WorkStatusProvider.kt @@ -14,7 +14,7 @@ package com.mailchimp.sdk.core.work import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import androidx.work.WorkInfo -import java.util.* +import java.util.UUID interface WorkStatusProvider { /** @@ -66,14 +66,17 @@ enum class WorkStatus { * The Queued Status is used to indicate that the job is waiting on other jobs to complete before starting. */ QUEUED, + /** * The Running Status is used to indicate that the job is currently in progress. */ RUNNING, + /** * The Finished Status is used to indicate that the job completed and encountered no errors. */ FINISHED, + /** * The Failed Status is used to indicate that the job encountered an error and may or may not have had the intended effect. */ diff --git a/mailchimp-sdk-core/src/main/res/values-sw600dp/attr.xml b/mailchimp-sdk-core/src/main/res/values-sw600dp/attr.xml index 6bfe653..b7f4d94 100644 --- a/mailchimp-sdk-core/src/main/res/values-sw600dp/attr.xml +++ b/mailchimp-sdk-core/src/main/res/values-sw600dp/attr.xml @@ -1,5 +1,4 @@ - - + xmlns:tools="http://schemas.android.com/tools"> @@ -25,7 +24,9 @@ android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> - + diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddContactFragment.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddContactFragment.kt index acb5bb1..cabaa63 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddContactFragment.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddContactFragment.kt @@ -21,13 +21,12 @@ import androidx.activity.OnBackPressedCallback import androidx.fragment.app.Fragment import com.mailchimp.sdk.api.model.Contact import com.mailchimp.sdk.api.model.ContactStatus -import com.mailchimp.sdk.core.work.WorkStatus import com.mailchimp.sdk.main.Mailchimp +import com.mailchimp.sdkdemo.databinding.FragmentAddContactBinding import com.mailchimp.sdkdemo.ui.AddressFieldLayout import com.mailchimp.sdkdemo.ui.KeyValueLayout import com.mailchimp.sdkdemo.ui.MarketingPermissionLayout import com.mailchimp.sdkdemo.ui.NamedFieldLayout -import kotlinx.android.synthetic.main.fragment_add_contact.* class AddContactFragment : Fragment() { @@ -37,17 +36,25 @@ class AddContactFragment : Fragment() { private val stringMergeFieldCellList = mutableListOf() private val addressFieldCellList = mutableListOf() private val marketingPermissionCellList = mutableListOf() + private val noContactStatus = object { override fun toString(): String { return "DON'T SEND CONTACT STATUS" } // Placeholder object that is a stand in for a null value } + private var _binding: FragmentAddContactBinding? = null + + /** + * This property is only valid between onCreateView and onDestroyView. + */ + private val binding get() = _binding!! + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - activity!!.onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - activity!!.finish() + activity?.finish() } }) } @@ -56,38 +63,45 @@ class AddContactFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_add_contact, container, false) + ): View { + return FragmentAddContactBinding.inflate(inflater, container, false).let { + _binding = it + it.root + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // This is gross but ¯\_(ツ)_/¯ since it's the demo app - val adapter = ArrayAdapter(context!!, R.layout.spinner_demo_app) + val adapter = ArrayAdapter(requireContext(), R.layout.spinner_demo_app) adapter.setDropDownViewResource(R.layout.spinner_drop_down) ContactStatus.values().toList().forEach { adapter.add(it) } adapter.add(noContactStatus) - spnr_contact_status.adapter = adapter - - btn_create_contact.setOnClickListener { callCreateOrUpdateEndpoint() } - btn_add_tag.setOnClickListener { appendAddTagCell() } - btn_remove_tag.setOnClickListener { appendRemoveTagCell() } - btn_add_merge_field.setOnClickListener { appendMergeFieldCell() } - btn_add_address.setOnClickListener { appendAddressCell() } - btn_add_marketing_permission.setOnClickListener { appendMarketingPermissionCell() } + binding.spnrContactStatus.adapter = adapter + + binding.btnCreateContact.setOnClickListener { callCreateOrUpdateEndpoint() } + binding.btnAddTag.setOnClickListener { appendAddTagCell() } + binding.btnRemoveTag.setOnClickListener { appendRemoveTagCell() } + binding.btnAddMergeField.setOnClickListener { appendMergeFieldCell() } + binding.btnAddAddress.setOnClickListener { appendAddressCell() } + binding.btnAddMarketingPermission.setOnClickListener { appendMarketingPermissionCell() } } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } private fun callCreateOrUpdateEndpoint() { - val email = nfl_email.value + val email = binding.nflEmail.value if (email.isBlank()) { - Toast.makeText(context!!, "Please enter an Email", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Please enter an Email", Toast.LENGTH_SHORT).show() return } val contactBuilder = Contact.Builder(email) - val spnrOption = spnr_contact_status.selectedItem + val spnrOption = binding.spnrContactStatus.selectedItem if (spnrOption != noContactStatus) { contactBuilder.setContactStatus(spnrOption as ContactStatus) } @@ -125,38 +139,35 @@ class AddContactFragment : Fragment() { val uuid = audienceSdk.createOrUpdateContact(contact) val liveData = Mailchimp.sharedInstance().getStatusByIdLiveData(uuid) - liveData.observe( - this@AddContactFragment, - androidx.lifecycle.Observer { - Toast.makeText(context!!, "Work: $it", Toast.LENGTH_SHORT).show() - } - ) + liveData.observe(viewLifecycleOwner) { + Toast.makeText(requireContext(), "Work: $it", Toast.LENGTH_SHORT).show() + } clearAddedCells() } private fun appendAddTagCell() { - val newLayout = NamedFieldLayout(context!!, null) + val newLayout = NamedFieldLayout(requireContext(), null) setViewMargins(newLayout) newLayout.label = getString(R.string.add_tag) newLayout.removeButtonVisible = true newLayout.removeButton.setOnClickListener { removeView(newLayout, addTagsCellList) } addTagsCellList.add(newLayout) - ll_add_on_fields.addView(newLayout) + binding.llAddOnFields.addView(newLayout) } private fun appendRemoveTagCell() { - val newLayout = NamedFieldLayout(context!!, null) + val newLayout = NamedFieldLayout(requireContext(), null) setViewMargins(newLayout) newLayout.label = getString(R.string.remove_tag) newLayout.removeButtonVisible = true newLayout.removeButton.setOnClickListener { removeView(newLayout, removeTagsCellList) } removeTagsCellList.add(newLayout) - ll_add_on_fields.addView(newLayout) + binding.llAddOnFields.addView(newLayout) } private fun appendMergeFieldCell() { - val newLayout = KeyValueLayout(context!!, null) + val newLayout = KeyValueLayout(requireContext(), null) setViewMargins(newLayout) newLayout.label = getString(R.string.set_merge_field) newLayout.removeButtonVisible = true @@ -169,20 +180,20 @@ class AddContactFragment : Fragment() { ) } stringMergeFieldCellList.add(newLayout) - ll_add_on_fields.addView(newLayout) + binding.llAddOnFields.addView(newLayout) } private fun appendAddressCell() { - val newLayout = AddressFieldLayout(context!!, null) + val newLayout = AddressFieldLayout(requireContext(), null) setViewMargins(newLayout) newLayout.removeButtonVisible = true newLayout.removeButton.setOnClickListener { removeView(newLayout, addressFieldCellList) } addressFieldCellList.add(newLayout) - ll_add_on_fields.addView(newLayout) + binding.llAddOnFields.addView(newLayout) } private fun appendMarketingPermissionCell() { - val newLayout = MarketingPermissionLayout(context!!, null) + val newLayout = MarketingPermissionLayout(requireContext(), null) setViewMargins(newLayout) newLayout.removeButtonVisible = true newLayout.removeButton.setOnClickListener { @@ -192,7 +203,7 @@ class AddContactFragment : Fragment() { ) } marketingPermissionCellList.add(newLayout) - ll_add_on_fields.addView(newLayout) + binding.llAddOnFields.addView(newLayout) } private fun setViewMargins(view: View) { @@ -208,11 +219,11 @@ class AddContactFragment : Fragment() { removeTagsCellList.clear() addressFieldCellList.clear() marketingPermissionCellList.clear() - ll_add_on_fields.removeAllViews() + binding.llAddOnFields.removeAllViews() } private fun removeView(view: T, list: MutableList) { - ll_add_on_fields.removeView(view) + binding.llAddOnFields.removeView(view) list.remove(view) } -} \ No newline at end of file +} diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddEventFragment.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddEventFragment.kt index ad31626..a9919cd 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddEventFragment.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/AddEventFragment.kt @@ -18,8 +18,8 @@ import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.Fragment import com.mailchimp.sdk.main.Mailchimp +import com.mailchimp.sdkdemo.databinding.FragmentAddEventBinding import com.mailchimp.sdkdemo.ui.KeyValueLayout -import kotlinx.android.synthetic.main.fragment_add_event.* import timber.log.Timber class AddEventFragment : Fragment() { @@ -27,29 +27,44 @@ class AddEventFragment : Fragment() { private val mailchimpSdk = Mailchimp.sharedInstance() private val propertiesCellList = mutableListOf() + private var _binding: FragmentAddEventBinding? = null + + /** + * This property is only valid between onCreateView and onDestroyView. + */ + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_add_event, container, false) + ): View { + return FragmentAddEventBinding.inflate(inflater, container, false).let { + _binding = it + it.root + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - btn_add_pair.setOnClickListener { appendPropertyCell() } - btn_create_event.setOnClickListener { addEvent() } + binding.btnAddPair.setOnClickListener { appendPropertyCell() } + binding.btnCreateEvent.setOnClickListener { addEvent() } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } private fun addEvent() { - val email = nfl_email_FAE.value + val email = binding.nflEmailFAE.value if (email.isBlank()) { - Toast.makeText(context!!, "Please enter an Email", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Please enter an Email", Toast.LENGTH_SHORT).show() return } - val eventName = nfl_event_name_FAE.value + val eventName = binding.nflEventNameFAE.value if (eventName.isBlank()) { - Toast.makeText(context!!, "Please enter an Event Name", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Please enter an Event Name", Toast.LENGTH_SHORT).show() return } @@ -60,12 +75,11 @@ class AddEventFragment : Fragment() { val propertyValue = view.value if (propertyName.isBlank() && propertyValue.isBlank()) { Timber.i("Ignoring empty property") - } - else if (propertyName.isBlank() || propertyValue.isBlank()) { - Toast.makeText(context!!, "Property names and values cannot be empty", Toast.LENGTH_SHORT).show() + } else if (propertyName.isBlank() || propertyValue.isBlank()) { + Toast.makeText(requireContext(), "Property names and values cannot be empty", Toast.LENGTH_SHORT).show() return } else { - properties.put(view.key, view.value) + properties[view.key] = view.value } } @@ -78,7 +92,7 @@ class AddEventFragment : Fragment() { if (eventId == null) { Toast.makeText( - context!!, + requireContext(), "Malformed request: Check logs to see a more detailed error", Toast.LENGTH_SHORT ).show() @@ -86,17 +100,15 @@ class AddEventFragment : Fragment() { } val liveData = mailchimpSdk.getStatusByIdLiveData(eventId) - liveData.observe( - this@AddEventFragment, - androidx.lifecycle.Observer { - Toast.makeText(context!!, "Work: $it", Toast.LENGTH_SHORT).show() - }) + liveData.observe(viewLifecycleOwner) { + Toast.makeText(requireContext(), "Work: $it", Toast.LENGTH_SHORT).show() + } clearAddedCells() } private fun appendPropertyCell() { - val newLayout = KeyValueLayout(context!!, null) + val newLayout = KeyValueLayout(requireContext(), null) newLayout.removeButtonVisible = true newLayout.setKeyHint(getString(R.string.key)) newLayout.setValueHint(getString(R.string.value)) @@ -107,16 +119,16 @@ class AddEventFragment : Fragment() { ) } propertiesCellList.add(newLayout) - ll_add_on_fields_FAE.addView(newLayout) + binding.llAddOnFieldsFAE.addView(newLayout) } private fun clearAddedCells() { propertiesCellList.clear() - ll_add_on_fields_FAE.removeAllViews() + binding.llAddOnFieldsFAE.removeAllViews() } private fun removeView(view: T, list: MutableList) { - ll_add_on_fields_FAE.removeView(view) + binding.llAddOnFieldsFAE.removeView(view) list.remove(view) } -} \ No newline at end of file +} diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/HomeFragment.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/HomeFragment.kt index f9be764..ca09567 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/HomeFragment.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/HomeFragment.kt @@ -16,54 +16,62 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.FragmentStatePagerAdapter -import kotlinx.android.synthetic.main.fragment_home.* +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.google.android.material.tabs.TabLayoutMediator +import com.mailchimp.sdkdemo.databinding.FragmentHomeBinding class HomeFragment : Fragment() { - private lateinit var pagerAdapter: HomeFragmentPagerAdapter + private var _binding: FragmentHomeBinding? = null + + /** + * This property is only valid between onCreateView and onDestroyView. + */ + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_home, container, false) + ): View { + return FragmentHomeBinding.inflate(inflater, container, false).let { + _binding = it + it.root + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - pagerAdapter = HomeFragmentPagerAdapter(fragmentManager!!) - view_pager_FH.adapter = pagerAdapter - tab_layout_FH.setupWithViewPager(view_pager_FH) + binding.viewPagerFH.adapter = HomeFragmentPagerAdapter(this) + TabLayoutMediator(binding.tabLayoutFH, binding.viewPagerFH) { tab, position -> + tab.text = HomeFragmentPagerAdapter.HomeTabs.values()[position].tabName + }.attach() + } + override fun onDestroyView() { + super.onDestroyView() + _binding = null } -} + private class HomeFragmentPagerAdapter(fragment: Fragment) : + FragmentStateAdapter(fragment) { -class HomeFragmentPagerAdapter(fragmentManager: FragmentManager) : - FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - override fun getItem(position: Int): Fragment { - val tab = HomeTabs.values()[position] - return when (tab) { - HomeTabs.ADD_CONTACT -> AddContactFragment() - HomeTabs.ADD_EVENT -> AddEventFragment() + enum class HomeTabs(val tabName: String) { + ADD_CONTACT("Add Contact"), + ADD_EVENT("Add Event") } - } - override fun getCount(): Int { - return HomeTabs.values().size - } + override fun getItemCount(): Int { + return HomeTabs.values().size + } - override fun getPageTitle(position: Int): CharSequence { - return HomeTabs.values()[position].tabName - } + override fun createFragment(position: Int): Fragment { + return when (HomeTabs.values()[position]) { + HomeTabs.ADD_CONTACT -> AddContactFragment() + HomeTabs.ADD_EVENT -> AddEventFragment() + } + } + } } - -enum class HomeTabs(val tabName: String) { - ADD_CONTACT("Add Contact"), - ADD_EVENT("Add Event") -} \ No newline at end of file diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MailchimpSdkDemoApp.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MailchimpSdkDemoApp.kt index 92ab968..9559341 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MailchimpSdkDemoApp.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MailchimpSdkDemoApp.kt @@ -13,9 +13,4 @@ package com.mailchimp.sdkdemo import android.app.Application -class MailchimpSdkDemoApp : Application() { - - override fun onCreate() { - super.onCreate() - } -} \ No newline at end of file +class MailchimpSdkDemoApp : Application() diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MainActivity.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MainActivity.kt index 555856f..afce006 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MainActivity.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/MainActivity.kt @@ -14,14 +14,15 @@ package com.mailchimp.sdkdemo import android.graphics.drawable.ColorDrawable import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.res.ResourcesCompat -class MainActivity: AppCompatActivity() { +class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - supportActionBar!!.setBackgroundDrawable(ColorDrawable(resources.getColor(R.color.kale))) - supportActionBar!!.elevation = 0f + supportActionBar?.setBackgroundDrawable(ColorDrawable(ResourcesCompat.getColor(resources, R.color.kale, this.theme))) + supportActionBar?.elevation = 0f } } \ No newline at end of file diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/SetupFragment.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/SetupFragment.kt index 94a77b7..101d300 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/SetupFragment.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/SetupFragment.kt @@ -25,37 +25,47 @@ import com.mailchimp.sdk.audience.di.AudienceImplementation import com.mailchimp.sdk.core.MailchimpSdkConfiguration import com.mailchimp.sdk.main.Mailchimp import com.mailchimp.sdk.main.di.MailchimpInjector +import com.mailchimp.sdkdemo.databinding.FragmentSetupBinding import com.mailchimp.sdkdemo.mockapi.MockApiImplementation import com.mailchimp.sdkdemo.mockapi.MockMailchimp -import kotlinx.android.synthetic.main.fragment_setup.* -import java.util.* +import java.util.Locale class SetupFragment : Fragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_setup, container, false) + private var _binding: FragmentSetupBinding? = null + + /** + * This property is only valid between onCreateView and onDestroyView. + */ + private val binding get() = _binding!! + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return FragmentSetupBinding.inflate(inflater, container, false).let { + _binding = it + it.root + } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - cbx_autotag.isChecked = true - cbx_debug.isChecked = true - et_sdk_key.text = Editable.Factory().newEditable(BuildConfig.MAILCHIMP_SDK_DEMO_KEY) - btn_start.setOnClickListener { start() } - btn_start_mock.setOnClickListener { startMock() } + binding.cbxAutotag.isChecked = true + binding.cbxDebug.isChecked = true + binding.etSdkKey.text = Editable.Factory().newEditable(BuildConfig.MAILCHIMP_SDK_DEMO_KEY) + binding.btnStart.setOnClickListener { start() } + binding.btnStartMock.setOnClickListener { startMock() } } private fun start() { - val sdkKey = et_sdk_key.text.toString().toLowerCase(Locale.getDefault()) + val sdkKey = binding.etSdkKey.text.toString().lowercase(Locale.getDefault()) if (sdkKey.isBlank()) { - Toast.makeText(context!!, getString(R.string.invalid_sdk_key_msg), Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.invalid_sdk_key_msg), Toast.LENGTH_SHORT).show() } else { // Initialize SDK // Normally this would be done elsewhere. Typically App Start. val configuration = - MailchimpSdkConfiguration.Builder(context!!, sdkKey) - .isDebugModeEnabled(cbx_debug.isChecked) - .isAutoTaggingEnabled(cbx_autotag.isChecked) + MailchimpSdkConfiguration.Builder(requireContext(), sdkKey) + .isDebugModeEnabled(binding.cbxDebug.isChecked) + .isAutoTaggingEnabled(binding.cbxAutotag.isChecked) .build() Mailchimp.initialize(configuration) @@ -65,9 +75,9 @@ class SetupFragment : Fragment() { private fun startMock() { val configuration = - MailchimpSdkConfiguration.Builder(context!!, "sdkkey-us1") - .isDebugModeEnabled(cbx_debug.isChecked) - .isAutoTaggingEnabled(cbx_autotag.isChecked) + MailchimpSdkConfiguration.Builder(requireContext(), "sdkkey-us1") + .isDebugModeEnabled(binding.cbxDebug.isChecked) + .isAutoTaggingEnabled(binding.cbxAutotag.isChecked) .build() val apiDependencies = MockApiImplementation() val mockInjector = object : MailchimpInjector(configuration) { diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockMailchimpAudienceBackend.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockMailchimpAudienceBackend.kt index 03d6d7c..a98d912 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockMailchimpAudienceBackend.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockMailchimpAudienceBackend.kt @@ -26,7 +26,7 @@ class MockMailchimpAudienceBackend { lastCallMap[contactUpdates.emailAddress] = contactUpdates // Add to Contact Map, Merge if necessary - val currentContact: ApiContact? = contactMap.get(contactUpdates.emailAddress) + val currentContact: ApiContact? = contactMap[contactUpdates.emailAddress] if (currentContact != null) { Timber.i("Updating Contact For: ${contactUpdates.emailAddress} ") // Merge updates diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockSdkWebService.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockSdkWebService.kt index 98b819b..bd4a4fc 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockSdkWebService.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/mockapi/MockSdkWebService.kt @@ -17,11 +17,15 @@ import com.mailchimp.sdk.api.model.ContactEvent import com.mailchimp.sdk.api.model.ContactEventResponse import com.mailchimp.sdk.api.model.UpdateContactResponse import okhttp3.Request +import okio.Timeout import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class MockSdkWebService(private val audienceBackend: MockMailchimpAudienceBackend, private val mockGenericCallBackend: MockGenericCallBackend) : SdkWebService { +class MockSdkWebService( + private val audienceBackend: MockMailchimpAudienceBackend, + private val mockGenericCallBackend: MockGenericCallBackend +) : SdkWebService { companion object { const val ADD_CONTACT_EVENT_TAG = "add_contact_event" @@ -39,7 +43,7 @@ class MockSdkWebService(private val audienceBackend: MockMailchimpAudienceBacken } } -class AudienceCall(private val doWork: () -> T) : Call { +private class AudienceCall(private val doWork: () -> T) : Call { private var isCancelled = false private var isExecuted = false @@ -75,6 +79,10 @@ class AudienceCall(private val doWork: () -> T) : Call { return Request.Builder().build() } + override fun timeout(): Timeout { + TODO("Not yet implemented") + } + private fun executeUpdate(): T { return doWork() } diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/AddressFieldLayout.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/AddressFieldLayout.kt index 9a6b0e5..ffee847 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/AddressFieldLayout.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/AddressFieldLayout.kt @@ -12,7 +12,6 @@ package com.mailchimp.sdkdemo.ui import android.content.Context -import android.content.res.TypedArray import android.util.AttributeSet import android.view.LayoutInflater import android.view.View @@ -21,55 +20,54 @@ import androidx.constraintlayout.widget.ConstraintLayout import com.mailchimp.sdk.api.model.mergefields.Address import com.mailchimp.sdk.api.model.mergefields.Country import com.mailchimp.sdkdemo.R -import kotlinx.android.synthetic.main.layout_address_field.view.* +import com.mailchimp.sdkdemo.databinding.LayoutAddressFieldBinding class AddressFieldLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) { - init { - val inflater = LayoutInflater.from(context) - inflater.inflate(R.layout.layout_address_field, this, true) + private val binding = LayoutAddressFieldBinding.inflate(LayoutInflater.from(context), this) + init { val adapter = ArrayAdapter(context, R.layout.country_spinner_item) adapter.setDropDownViewResource(R.layout.spinner_drop_down) adapter.addAll(Country.values().toList()) - spnr_country.adapter = adapter + binding.spnrCountry.adapter = adapter } - val removeButton = btn_remove_field + val removeButton = binding.btnRemoveField val key: String get() { - return tiet_key_AFL.text.toString().trim() + return binding.tietKeyAFL.text.toString().trim() } val lineOne: String get() { - return tiet_line_one_AFL.text.toString().trim() + return binding.tietLineOneAFL.text.toString().trim() } val lineTwo: String get() { - return tiet_line_two_AFL.text.toString().trim() + return binding.tietLineTwoAFL.text.toString().trim() } val city: String get() { - return tiet_city_AFL.text.toString().trim() + return binding.tietCityAFL.text.toString().trim() } val state: String get() { - return tiet_state_AFL.text.toString().trim() + return binding.tietStateAFL.text.toString().trim() } val country: Country get() { - return spnr_country.selectedItem as Country + return binding.spnrCountry.selectedItem as Country } val zip: String get() { - return tiet_zip_AFL.text.toString().trim() + return binding.tietZipAFL.text.toString().trim() } val address: Address? @@ -89,10 +87,10 @@ class AddressFieldLayout(context: Context, attrs: AttributeSet?) : ConstraintLay var removeButtonVisible = false set(value) { field = value - if (value) { - btn_remove_field.visibility = View.VISIBLE + binding.btnRemoveField.visibility = if (value) { + View.VISIBLE } else { - btn_remove_field.visibility = View.GONE + View.GONE } } diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/KeyValueLayout.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/KeyValueLayout.kt index 9e27eb4..eb7264c 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/KeyValueLayout.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/KeyValueLayout.kt @@ -16,50 +16,50 @@ import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import androidx.constraintlayout.widget.ConstraintLayout -import com.mailchimp.sdkdemo.R -import kotlinx.android.synthetic.main.layout_key_value.view.* +import com.mailchimp.sdkdemo.databinding.LayoutKeyValueBinding class KeyValueLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) { - init { - val inflater = LayoutInflater.from(context) - inflater.inflate(R.layout.layout_key_value, this, true) - } + + private val binding = LayoutKeyValueBinding.inflate(LayoutInflater.from(context), this) var label: String? = null set(value) { - if (value != null && value.isNotEmpty()) { - tv_label_KVL.text = value - tv_label_KVL.visibility = View.VISIBLE + if (!value.isNullOrEmpty()) { + binding.tvLabelKVL.text = value + binding.tvLabelKVL.visibility = View.VISIBLE } else { - tv_label_KVL.visibility = View.GONE + binding.tvLabelKVL.visibility = View.GONE } field = value } - val removeButton = btn_remove_field + val removeButton = binding.btnRemoveField + val value: String get() { - return tiet_value_KVL.text.toString().trim() + return binding.tietValueKVL.text.toString().trim() } + val key: String get() { - return tiet_key_KVL.text.toString().trim() + return binding.tietKeyKVL.text.toString().trim() } + var removeButtonVisible = false set(value) { field = value if (value) { - btn_remove_field.visibility = View.VISIBLE + binding.btnRemoveField.visibility = View.VISIBLE } else { - btn_remove_field.visibility = View.GONE + binding.btnRemoveField.visibility = View.GONE } } fun setValueHint(hint: String) { - til_value_KVL.hint = hint + binding.tilValueKVL.hint = hint } fun setKeyHint(hint: String) { - til_key_KVL.hint = hint + binding.tilKeyKVL.hint = hint } } diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/MarketingPermissionLayout.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/MarketingPermissionLayout.kt index 345d613..967f01d 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/MarketingPermissionLayout.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/MarketingPermissionLayout.kt @@ -16,31 +16,31 @@ import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import androidx.constraintlayout.widget.ConstraintLayout -import com.mailchimp.sdkdemo.R -import kotlinx.android.synthetic.main.layout_marketing_permission_field.view.* +import com.mailchimp.sdkdemo.databinding.LayoutMarketingPermissionFieldBinding class MarketingPermissionLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) { - init { - val inflater = LayoutInflater.from(context) - inflater.inflate(R.layout.layout_marketing_permission_field, this, true) - } - val removeButton = btn_remove_field + private val binding = LayoutMarketingPermissionFieldBinding.inflate(LayoutInflater.from(context), this) + + val removeButton = binding.btnRemoveField + val isPermissionGranted: Boolean get() { - return sc_value.isChecked + return binding.scValue.isChecked } + val permission: String get() { - return tiet_key_MPFL.text.toString().trim() + return binding.tietKeyMPFL.text.toString().trim() } + var removeButtonVisible = false set(value) { field = value - if (value) { - btn_remove_field.visibility = View.VISIBLE + binding.btnRemoveField.visibility = if (value) { + View.VISIBLE } else { - btn_remove_field.visibility = View.GONE + View.GONE } } } diff --git a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/NamedFieldLayout.kt b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/NamedFieldLayout.kt index b4bbf23..d086fcd 100644 --- a/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/NamedFieldLayout.kt +++ b/mailchimp-sdk-demo/src/main/java/com/mailchimp/sdkdemo/ui/NamedFieldLayout.kt @@ -12,49 +12,47 @@ package com.mailchimp.sdkdemo.ui import android.content.Context -import android.content.res.TypedArray import android.util.AttributeSet import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout -import com.google.android.material.textfield.TextInputLayout +import androidx.core.content.withStyledAttributes import com.mailchimp.sdkdemo.R -import kotlinx.android.synthetic.main.layout_named_field.view.* +import com.mailchimp.sdkdemo.databinding.LayoutNamedFieldBinding class NamedFieldLayout(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { - var label: String? = null - set(value) { - til_NFL.hint = value - field = value - } + + private val binding = LayoutNamedFieldBinding.inflate(LayoutInflater.from(context), this) init { - val inflater = LayoutInflater.from(context) - inflater.inflate(R.layout.layout_named_field, this, true) layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - var typedArray: TypedArray? = null - try { - typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.NamedFieldLayout, 0, 0) - label = typedArray.getString(R.styleable.NamedFieldLayout_label) - } finally { - typedArray?.recycle() + context.withStyledAttributes(attrs, R.styleable.NamedFieldLayout) { + binding.tilNFL.hint = getString(R.styleable.NamedFieldLayout_label) } } - val removeButton = btn_remove_field + val removeButton = binding.btnRemoveField + val value: String get() { - return tiet_NFL.text.toString().trim() + return binding.tietNFL.text.toString().trim() } + var removeButtonVisible = false set(value) { field = value - if (value) { - btn_remove_field.visibility = View.VISIBLE + binding.btnRemoveField.visibility = if (value) { + View.VISIBLE } else { - btn_remove_field.visibility = View.GONE + View.GONE } } + + var label: String? + get() = binding.tilNFL.hint?.toString() + set(value) { + binding.tilNFL.hint = value + } } diff --git a/mailchimp-sdk-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/mailchimp-sdk-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml index 33dbbe5..82ec14e 100644 --- a/mailchimp-sdk-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ b/mailchimp-sdk-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -10,36 +10,36 @@ --> + xmlns:aapt="http://schemas.android.com/aapt" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + android:fillType="evenOdd" + android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" + android:strokeWidth="1" + android:strokeColor="#00000000"> + android:endX="78.5885" + android:endY="90.9159" + android:startX="48.7653" + android:startY="61.0927" + android:type="linear"> + android:color="#44000000" + android:offset="0.0" /> + android:color="#00000000" + android:offset="1.0" /> + android:fillColor="#FFFFFF" + android:fillType="nonZero" + android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" + android:strokeWidth="1" + android:strokeColor="#00000000" /> diff --git a/mailchimp-sdk-demo/src/main/res/drawable/border.xml b/mailchimp-sdk-demo/src/main/res/drawable/border.xml index 3d5cc35..4b917ac 100644 --- a/mailchimp-sdk-demo/src/main/res/drawable/border.xml +++ b/mailchimp-sdk-demo/src/main/res/drawable/border.xml @@ -1,5 +1,4 @@ - - - + - + \ No newline at end of file diff --git a/mailchimp-sdk-demo/src/main/res/drawable/ic_close_icon.xml b/mailchimp-sdk-demo/src/main/res/drawable/ic_close_icon.xml index 5cea622..0777e6b 100644 --- a/mailchimp-sdk-demo/src/main/res/drawable/ic_close_icon.xml +++ b/mailchimp-sdk-demo/src/main/res/drawable/ic_close_icon.xml @@ -9,8 +9,14 @@ ~ limitations under the License. --> - - + + diff --git a/mailchimp-sdk-demo/src/main/res/drawable/ic_launcher_background.xml b/mailchimp-sdk-demo/src/main/res/drawable/ic_launcher_background.xml index fd8e5a8..ab90ae2 100644 --- a/mailchimp-sdk-demo/src/main/res/drawable/ic_launcher_background.xml +++ b/mailchimp-sdk-demo/src/main/res/drawable/ic_launcher_background.xml @@ -1,5 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mailchimp-sdk-demo/src/main/res/layout/activity_main.xml b/mailchimp-sdk-demo/src/main/res/layout/activity_main.xml index 3b67cbf..61bfed8 100644 --- a/mailchimp-sdk-demo/src/main/res/layout/activity_main.xml +++ b/mailchimp-sdk-demo/src/main/res/layout/activity_main.xml @@ -1,5 +1,4 @@ - - - - - \ No newline at end of file diff --git a/mailchimp-sdk-demo/src/main/res/layout/country_spinner_item.xml b/mailchimp-sdk-demo/src/main/res/layout/country_spinner_item.xml index b0d032e..aca8e6e 100644 --- a/mailchimp-sdk-demo/src/main/res/layout/country_spinner_item.xml +++ b/mailchimp-sdk-demo/src/main/res/layout/country_spinner_item.xml @@ -1,5 +1,4 @@ - - - + android:textSize="16sp" /> diff --git a/mailchimp-sdk-demo/src/main/res/layout/spinner_drop_down.xml b/mailchimp-sdk-demo/src/main/res/layout/spinner_drop_down.xml index afb1981..7929ca0 100644 --- a/mailchimp-sdk-demo/src/main/res/layout/spinner_drop_down.xml +++ b/mailchimp-sdk-demo/src/main/res/layout/spinner_drop_down.xml @@ -1,5 +1,4 @@ - - - + android:textColor="@color/black" + android:textSize="16sp" /> diff --git a/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 8e20a2b..f26e3ce 100644 --- a/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,4 @@ - - - - + + \ No newline at end of file diff --git a/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 8e20a2b..f26e3ce 100644 --- a/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/mailchimp-sdk-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,4 @@ - - - - + + \ No newline at end of file diff --git a/mailchimp-sdk-demo/src/main/res/navigation/nav_graph.xml b/mailchimp-sdk-demo/src/main/res/navigation/nav_graph.xml index 996784a..5ac10bf 100644 --- a/mailchimp-sdk-demo/src/main/res/navigation/nav_graph.xml +++ b/mailchimp-sdk-demo/src/main/res/navigation/nav_graph.xml @@ -1,5 +1,4 @@ - - + android:label="SetupFragment"> diff --git a/mailchimp-sdk-demo/src/main/res/values/attrs.xml b/mailchimp-sdk-demo/src/main/res/values/attrs.xml index 7b519e6..30ec96a 100644 --- a/mailchimp-sdk-demo/src/main/res/values/attrs.xml +++ b/mailchimp-sdk-demo/src/main/res/values/attrs.xml @@ -1,5 +1,4 @@ - - - + diff --git a/mailchimp-sdk-main/src/main/java/com/mailchimp/sdk/main/Mailchimp.kt b/mailchimp-sdk-main/src/main/java/com/mailchimp/sdk/main/Mailchimp.kt index c1ab211..67bdd72 100644 --- a/mailchimp-sdk-main/src/main/java/com/mailchimp/sdk/main/Mailchimp.kt +++ b/mailchimp-sdk-main/src/main/java/com/mailchimp/sdk/main/Mailchimp.kt @@ -19,12 +19,12 @@ import timber.log.Timber /** * The Mailchimp Class manages all contact updates to your Mailchimp audience. This class operates - * as a singleton. To start and instance call the [Mailchimp.initialize] method with the desired - * configuration. To retrieve and instance of the Audience SDK call the [Mailchimp.sharedInstance] + * as a singleton. To start an instance call the [Mailchimp.initialize] method with the desired + * configuration. To retrieve an instance of the Audience SDK call the [Mailchimp.sharedInstance] * method. */ open class Mailchimp protected constructor( - internal val injector: MailchimpInjector + private val injector: MailchimpInjector ) : AudienceSdkContract by injector.audienceDependencies.audienceSdkContract { companion object { @@ -69,7 +69,7 @@ open class Mailchimp protected constructor( } protected fun setupSdk(debugModeEnabled: Boolean) { - if (debugModeEnabled && Timber.treeCount() == 0) { + if (debugModeEnabled && Timber.treeCount == 0) { Timber.plant(Timber.DebugTree()) } Timber.d("SDK initialized")