diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..01cdae74dd
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,10 @@
+### Pull Request Checklist
+
+
+
+- [ ] Changes has been tested on an Android device or Android emulator with API 16
+- [ ] UI change has been tested on both light and dark themes
+- [ ] Pull request is based on the develop branch
+- [ ] Pull request updates [CHANGES.md](https://github.com/vector-im/riotX-android/blob/develop/CHANGES.md)
+- [ ] Pull request includes screenshots or videos if containing UI changes
+- [ ] Pull request includes a [sign off](https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst#sign-off)
diff --git a/.gitignore b/.gitignore
index a668f05331..0722110715 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@
/build
/captures
.externalNativeBuild
+
+/tmp
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..a41eba004f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,58 @@
+# FTR: Configuration on https://travis-ci.org/vector-im/riot-android/settings
+#
+# - Build only if .travis.yml is present -> On
+# - Limit concurrent jobs -> Off
+# - Build pushed branches -> On (build the branch)
+# - Build pushed pull request -> On (build the PR after auto-merge)
+#
+# - Auto cancel branch builds -> On
+# - Auto cancel pull request builds -> On
+
+language: android
+jdk: oraclejdk8
+sudo: false
+
+notifications:
+ email: false
+
+android:
+ components:
+ # Uncomment the lines below if you want to
+ # use the latest revision of Android SDK Tools
+ - tools
+ - platform-tools
+
+ # The BuildTools version used by your project
+ - build-tools-27.0.3
+
+ # The SDK version used to compile your project
+ - android-27
+
+before_cache:
+ - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
+ - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+
+cache:
+ directories:
+ - $HOME/.gradle/caches/
+ - $HOME/.gradle/wrapper/
+ - $HOME/.android/build-cache
+
+# Build with the development SDK
+before_script:
+ # Not necessary for the moment
+ # - /bin/sh ./set_debug_env.sh
+
+# Just build the project for now
+script:
+ # Build app (assembleAppRelease assembleAppfdroidRelease)
+ # Build Android test (assembleAndroidTest)
+ # Code quality (lintAppRelease lintAppfdroidRelease)
+ - ./gradlew clean assembleAppgplayRelease assembleAppfdroidRelease assembleAndroidTest lintAppgplayRelease lintAppfdroidRelease --stacktrace
+ # Run unitary test (Disable for now, see https://travis-ci.org/vector-im/riot-android/builds/502504370)
+ # - ./gradlew testAppgplayReleaseUnitTest --stacktrace
+ # Other code quality check
+ - ./tools/check/check_code_quality.sh
+ - ./tools/travis/check_pr.sh
+ # Check that indonesians file are identical. Due to Android issue, the resource folder must be value-in/, and Weblate export data into value-id/.
+ - diff ./app/src/main/res/values-id/strings.xml ./app/src/main/res/values-in/strings.xml
diff --git a/AUTHORS.md b/AUTHORS.md
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
index 0000000000..ad6294c176
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,49 @@
+Changes in RiotX 0.XX (2019-XX-XX)
+===================================================
+
+Features:
+ -
+
+Improvements:
+ -
+
+Other changes:
+ -
+
+Bugfix:
+ -
+
+Translations:
+ -
+
+Build:
+ -
+
+
+
+=======================================================
++ TEMPLATE WHEN PREPARING A NEW RELEASE +
+=======================================================
+
+
+Changes in RiotX 0.XX (2019-XX-XX)
+===================================================
+
+Features:
+ -
+
+Improvements:
+ -
+
+Other changes:
+ -
+
+Bugfix:
+ -
+
+Translations:
+ -
+
+Build:
+ -
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..6aecbdc451
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,76 @@
+# Contributing code to Matrix
+
+Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst
+
+Android support can be found in this [![Riot Android Matrix room #riot-android:matrix.org](https://img.shields.io/matrix/riot-android:matrix.org.svg?label=%23riot-android:matrix.org)](https://matrix.to/#/#riot-android:matrix.org) room.
+
+Dedicated room for RiotX: [![RiotX Android Matrix room #riot-android:matrix.org](https://img.shields.io/matrix/riotx:matrix.org.svg?label=%23RiotX:matrix.org)](https://matrix.to/#/#riotx:matrix.org)
+
+# Specific rules for Matrix Android projects
+
+## Android Studio settings
+
+Please set the "hard wrap" setting of Android Studio to 160 chars, this is the setting we use internally to format the source code (Menu `Settings/Editor/Code Style` then `Hard wrap at`).
+
+## Compilation
+
+For now, the Matrix SDK and the RiotX application are in the same project. So there is no specific thing to do, this project should compile without any special action.
+
+## I want to help translating RiotX
+
+If you want to fix an issue with an English string, please submit a PR.
+If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please use [Weblate](https://translate.riot.im/projects/riot-android/).
+
+For the moment, Strings from Riot will be used, there is no dedicated project in Weblate for RiotX.
+
+## I want to submit a PR to fix an issue
+
+Please check if a corresponding issue exists. If yes, please let us know in a comment that you're working on it.
+If an issue does not exist yet, it may be relevant to open a new issue and let us know that you're implementing it.
+
+### Kotlin
+
+This project is full Kotlin. Please do not write Java classes.
+
+### CHANGES.md
+
+Please add a line to the top of the file `CHANGES.md` describing your change.
+
+### Code quality
+
+Make sure the following commands execute without any error:
+
+> ./tools/check/check_code_quality.sh
+
+> ./gradlew lintAppgplayRelease
+
+### Unit tests
+
+Make sure the following commands execute without any error:
+
+> ./gradlew testAppgplayReleaseUnitTest
+
+### Tests
+
+RiotX is currently supported on Android Jelly Bean (API 16+): please test your change on an Android device (or Android emulator) running with API 16. Many issues can happen (including crashes) on older devices.
+Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
+
+### Internationalisation
+
+When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators with a specific tool named [Weblate](https://translate.riot.im/projects/riot-android/).
+Do not hesitate to use plurals when appropriate.
+
+### Layout
+
+When adding or editing layouts, make sure the layout will render correctly if device uses a RTL (Right To Left) language.
+You can check this in the layout editor preview by selecting any RTL language (ex: Arabic).
+
+Also please check that the colors are ok for all the current themes of RiotX. Please use `?attr` instead of `@color` to reference colors in the layout. You can check this in the layout editor preview by selecting all the main themes (`AppTheme.Status`, `AppTheme.Dark`, etc.).
+
+### Authors
+
+Feel free to add an entry in file AUTHORS.md
+
+## Thanks
+
+Thanks for contributing to Matrix projects!
diff --git a/README.md b/README.md
index 69628f7a5d..60c9d30e9b 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,6 @@
RiotX is an Android Matrix Client currently in development.
It's based on a new Matrix SDK, written in Kotlin.
-Download nighly build here: https://matrix.org/jenkins/job/RiotXAndroidDevelop/
+Download nightly build here: https://matrix.org/jenkins/job/RiotXAndroidDevelop/
Matrix Room: [#riotx:matrix.org](https://matrix.to/#/#riotx:matrix.org)
diff --git a/app/build.gradle b/app/build.gradle
index 9d718815c2..4665fa25d3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,7 +15,7 @@ def versionMajor = 0
def versionMinor = 1
def versionPatch = 0
-def generateVersionCodeFromTimestamp() {
+static def generateVersionCodeFromTimestamp() {
// It's unix timestamp divided by 10: It's incremented by one every 10 seconds.
return (System.currentTimeMillis() / 1_000 / 10).toInteger()
}
@@ -24,6 +24,21 @@ def generateVersionCodeFromVersionName() {
return versionMajor * 10000 + versionMinor * 100 + versionPatch
}
+static def gitRevision() {
+ def cmd = "git rev-parse --short HEAD"
+ return cmd.execute().text.trim()
+}
+
+static def gitRevisionDate() {
+ def cmd = "git show -s --format=%ci HEAD^{commit}"
+ return cmd.execute().text.trim()
+}
+
+static def gitBranchName() {
+ def cmd = "git name-rev --name-only HEAD"
+ return cmd.execute().text.trim()
+}
+
project.android.buildTypes.all { buildType ->
buildType.javaCompileOptions.annotationProcessorOptions.arguments =
[
@@ -31,6 +46,8 @@ project.android.buildTypes.all { buildType ->
]
}
+def buildNumber = System.getenv("BUILD_NUMBER") as Integer ?: 0
+
android {
compileSdkVersion 28
defaultConfig {
@@ -40,8 +57,15 @@ android {
multiDexEnabled true
versionCode generateVersionCodeFromTimestamp()
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
+
+ resValue "string", "git_revision", "\"${gitRevision()}\""
+ resValue "string", "git_revision_date", "\"${gitRevisionDate()}\""
+ resValue "string", "git_branch_name", "\"${gitBranchName()}\""
+ resValue "string", "build_number", "\"${buildNumber}\""
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
+
buildTypes {
debug {
resValue "bool", "debug_mode", "true"
@@ -55,11 +79,61 @@ android {
}
}
+ flavorDimensions "store"
+
+ productFlavors {
+ appgplay {
+ dimension "store"
+
+ buildConfigField "boolean", "ALLOW_FCM_USE", "true"
+ buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\""
+ buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\""
+ }
+
+ appfdroid {
+ dimension "store"
+
+ buildConfigField "boolean", "ALLOW_FCM_USE", "false"
+ buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\""
+ buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\""
+ }
+ }
+
+ lintOptions {
+ warning 'MissingTranslation'
+
+ // Treat some warnings as errors
+ // Resources
+ error 'TypographyEllipsis'
+ warning 'ImpliedQuantity'
+
+ // UX
+ error 'ButtonOrder'
+
+ // Layout
+ error 'StringFormatCount'
+ error 'HardcodedText'
+ error 'SpUsage'
+ error 'ObsoleteLayoutParam'
+ error 'InefficientWeight'
+ error 'DisableBaselineAlignment'
+ error 'ScrollViewSize'
+
+ // RTL
+ error 'RtlEnabled'
+ error 'RtlHardcoded'
+ error 'RtlSymmetry'
+
+ // Code
+ error 'SetTextI18n'
+ error 'ViewConstructor'
+ error 'UseValueOf'
+ }
+
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
-
}
dependencies {
diff --git a/app/src/main/res/values/config.xml b/app/src/main/res/values/config.xml
new file mode 100755
index 0000000000..696a98f46b
--- /dev/null
+++ b/app/src/main/res/values/config.xml
@@ -0,0 +1,30 @@
+
+
+
+ Riot.im
+
+
+ https://vector.im
+ https://matrix.org
+ https://matrix.org
+ https://vector.im
+ "https://piwik.riot.im"
+
+
+ "https://scalar-staging.riot.im/scalar-web/"
+ "https://scalar-staging.riot.im/scalar/api"
+
+
+ - https://scalar-staging.riot.im/scalar/api
+ - https://scalar.vector.im/api
+
+
+
+
+
+
+
+ - matrix.org
+
+
+
diff --git a/tools/check/check_code_quality.sh b/tools/check/check_code_quality.sh
new file mode 100755
index 0000000000..2e7ef32c75
--- /dev/null
+++ b/tools/check/check_code_quality.sh
@@ -0,0 +1,141 @@
+#!/usr/bin/env bash
+
+#
+# Copyright 2019 New Vector Ltd
+#
+# 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
+#
+# http://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.
+#
+
+#######################################################################################################################
+# Check drawable quantity
+#######################################################################################################################
+
+echo "Check drawable quantity"
+
+numberOfFiles1=`ls -1U ./app/src/main/res/drawable-hdpi | wc -l | sed "s/ //g"`
+numberOfFiles2=`ls -1U ./app/src/main/res/drawable-mdpi | wc -l | sed "s/ //g"`
+numberOfFiles3=`ls -1U ./app/src/main/res/drawable-xhdpi | wc -l | sed "s/ //g"`
+numberOfFiles4=`ls -1U ./app/src/main/res/drawable-xxhdpi | wc -l | sed "s/ //g"`
+numberOfFiles5=`ls -1U ./app/src/main/res/drawable-xxxhdpi | wc -l | sed "s/ //g"`
+
+if [[ ${numberOfFiles1} -eq ${numberOfFiles5} ]] && [[ ${numberOfFiles2} -eq ${numberOfFiles5} ]] && [[ ${numberOfFiles3} -eq ${numberOfFiles5} ]] && [[ ${numberOfFiles4} -eq ${numberOfFiles5} ]]; then
+ resultNbOfDrawable=0
+ echo "OK"
+else
+ resultNbOfDrawable=1
+ echo "ERROR, missing drawable alternative."
+fi
+
+echo
+
+#######################################################################################################################
+# Search forbidden pattern
+#######################################################################################################################
+
+searchForbiddenStringsScript=./tmp/search_forbidden_strings.pl
+
+if [[ -f ${searchForbiddenStringsScript} ]]; then
+ echo "${searchForbiddenStringsScript} already there"
+else
+ mkdir tmp
+ echo "Get the script"
+ wget https://raw.githubusercontent.com/matrix-org/matrix-dev-tools/develop/bin/search_forbidden_strings.pl -O ${searchForbiddenStringsScript}
+fi
+
+if [[ -x ${searchForbiddenStringsScript} ]]; then
+ echo "${searchForbiddenStringsScript} is already executable"
+else
+ echo "Make the script executable"
+ chmod u+x ${searchForbiddenStringsScript}
+fi
+
+echo
+echo "Search for forbidden patterns in code..."
+
+${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_code.txt \
+ ./app/src/main/java
+
+resultForbiddenStringInCode=$?
+
+echo
+echo "Search for forbidden patterns in resources..."
+
+${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_resources.txt \
+ ./app/src/main/res/color \
+ ./app/src/main/res/layout \
+ ./app/src/main/res/menu \
+ ./app/src/main/res/values \
+ ./app/src/main/res/values-v21 \
+ ./app/src/main/res/xml
+
+resultForbiddenStringInResource=$?
+
+#######################################################################################################################
+# Check files with long lines
+#######################################################################################################################
+
+checkLongFilesScript=./tmp/check_long_files.pl
+
+if [[ -f ${checkLongFilesScript} ]]; then
+ echo "${checkLongFilesScript} already there"
+else
+ mkdir tmp
+ echo "Get the script"
+ wget https://raw.githubusercontent.com/matrix-org/matrix-dev-tools/develop/bin/check_long_files.pl -O ${checkLongFilesScript}
+fi
+
+if [[ -x ${checkLongFilesScript} ]]; then
+ echo "${checkLongFilesScript} is already executable"
+else
+ echo "Make the script executable"
+ chmod u+x ${checkLongFilesScript}
+fi
+
+echo
+echo "Search for long files..."
+
+${checkLongFilesScript} 1000 \
+ ./app/src/main/java \
+ ./app/src/main/res/layout \
+ ./app/src/main/res/values \
+ ./app/src/main/res/values-v21 \
+
+resultLongFiles=$?
+
+#######################################################################################################################
+# search png in drawable folder
+#######################################################################################################################
+
+echo
+echo "Search for png files in /drawable..."
+
+ls -1U ./app/src/main/res/drawable/*.png
+resultTmp=$?
+
+# Inverse the result, cause no file found is an error for ls but this is what we want!
+if [[ ${resultTmp} -eq 0 ]]; then
+ echo "ERROR, png files detected in /drawable"
+ resultPngInDrawable=1
+else
+ echo "OK"
+ resultPngInDrawable=0
+fi
+
+echo
+
+if [[ ${resultNbOfDrawable} -eq 0 ]] && [[ ${resultForbiddenStringInCode} -eq 0 ]] && [[ ${resultForbiddenStringInResource} -eq 0 ]] && [[ ${resultLongFiles} -eq 0 ]] && [[ ${resultPngInDrawable} -eq 0 ]]; then
+ echo "MAIN OK"
+else
+ echo "❌ MAIN ERROR"
+ exit 1
+fi
diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt
new file mode 100644
index 0000000000..13328c3b22
--- /dev/null
+++ b/tools/check/forbidden_strings_in_code.txt
@@ -0,0 +1,151 @@
+#
+# Copyright 2018 New Vector Ltd
+#
+# 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
+#
+# http://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.
+#
+
+# This file list String which are not allowed in source code.
+# Use Perl regex to write forbidden strings
+# Note: line cannot start with a space. Use \s instead.
+# It is possible to specify an authorized number of occurrence with === suffix. Default is 0
+# Example:
+# AuthorizedStringThreeTimes===3
+
+# Extension:java
+# Extension:kt
+
+# Use new SecureLinearLayoutManager
+# DISABLED
+#new LinearLayoutManager
+
+### No import static: use full class name
+import static
+
+### Rubbish from merge. Please delete those lines (sometimes in comment)
+<<<<<<<
+>>>>>>>
+
+### carry return before "}". Please remove empty lines.
+\n\s*\n\s*\}
+
+### typo detected.
+formated
+abtract
+Succes[^s]
+succes[^s]
+
+### Please insert line break. ex: .flatMap() not at new line
+\}\)\.[\w]
+
+### Use int instead of Integer
+protected Integer
+
+### Use the interface declaration. Example: use type "Map" instead of type "HashMap" to declare variable or parameter
+(private|public|protected| ) (static )?(final )?(HashMap|HashSet|ArrayList)<
+
+### Use int instead of short
+Short\.parseShort
+\(short\)
+private short
+final short
+
+### Line length is limited to 160 chars. Please split long lines
+.{161}
+
+### "DO NOT COMMIT" has been committed
+DO NOT COMMIT
+
+### invalid formatting
+\s{8}/\*\n \*
+[^\w]if\(
+while\(
+for\(
+
+# Add space after //
+# DISABLED To re-enable when code will be formatted globally
+#^\s*//[^\s]
+
+# Not usable with unitary test. Use StringUtils
+# DISABLED
+#TextUtils\.isEmpty\(
+
+### invalid formatting (too many space char)
+^ /\*
+
+# No ternary operator
+# DISABLED
+# \?
+
+### unnecessary parenthesis around numbers, example: " (0)"
+ \(\d+\)
+
+### Malformatted comment
+^ \*
+
+### import the package, do not use long class name with package
+android\.os\.Build\.
+
+### Tab char is forbidden. Use only spaces
+\t
+
+# Empty lines and trailing space
+# DISABLED To re-enable when code will be formatted globally
+#[ ]$
+
+### Deprecated, use retrofit2.HttpException
+import retrofit2\.adapter\.rxjava\.HttpException
+
+### This is generally not necessary, no need to reset the padding if there is no drawable
+setCompoundDrawablePadding\(0\)
+
+### Deprecated use class form SDK API 26
+ButterKnife\.findById\(
+
+# Change thread with Rx
+# DISABLED
+#runOnUiThread
+
+### Bad formatting of chain (missing new line)
+\w\.flatMap\(
+\w\.map\(
+
+### Bad formatting of Realm query chain. Insert new line
+\)\.equalTo
+\)\.findAll
+
+# Use StandardCharsets.UTF_8.name()
+# DISABLED (min API to low)
+#\"UTF-
+
+### Directly use getString() in a Fragment
+getActivity\(\)\.getString\(
+
+### In Kotlin, Void has to be null safe, i.e. use 'Void?' instead of 'Void'
+\: Void\)
+
+### Home menu click is managed in parent Activity, with one exception
+android\.R\.id\.home===2
+
+### Kotlin conversion tools introduce this, but is can be replace by trim()
+trim \{ it \<\= \' \' \}
+
+### Use AlertDialog form v7 compat lib
+android\.app\.AlertDialog
+
+### Put the operator at the beginning of next line
+&&$
+\|\|$
+ ==$
+
+### Use JsonUtils.getBasicGson()
+new Gson\(\)
diff --git a/tools/check/forbidden_strings_in_resources.txt b/tools/check/forbidden_strings_in_resources.txt
new file mode 100644
index 0000000000..26d7725591
--- /dev/null
+++ b/tools/check/forbidden_strings_in_resources.txt
@@ -0,0 +1,84 @@
+#
+# Copyright 2018 New Vector Ltd
+#
+# 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
+#
+# http://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.
+#
+
+# This file list String which are not allowed in source code.
+# Use Perl regex to write forbidden strings
+# Note: line cannot start with a space. Use \s instead.
+# It is possible to specify an authorized number of occurrence with === suffix. Default is 0
+# Example:
+# AuthorizedStringThreeTimes===3
+
+# Extension:xml
+
+
+### Rubbish from merge. Please delete those lines (sometimes in comment)
+<<<<<<<
+>>>>>>>
+
+### Hardcoded string are forbidden. Please create a string resource
+app\:emptyLabelText=\"[^@]
+android\:text=\"[^@]
+android\:hint=\"[^@]
+# (with tolerance for empty string)
+android\:title=\"[^@"]
+android\:contentDescription=\"[^@]
+# (with tolerance for summary="%s")
+android\:summary=\"[^@|\%s]
+app\:ms_floatingLabelText=\"[^@]
+app\:ms_hint=\"[^@]
+
+### "DO NOT COMMIT" has been committed
+DO NOT COMMIT
+
+### Tab char is forbidden. Use only spaces
+\t
+
+### Remove space in empty lines and trailing space
+[ ]$
+
+# Use project color
+# DISABLED
+#@android\:color\/
+
+# String in multiline
+# DISABLED
+#)
+\"><\/
+
+### Bad comment format in XML resources. Use instead of //
+^\s*\/\/
+
+### Bad RTL support, use attribute with Start and End
+layout_constraintRight_
+layout_constraintLeft_
+
+### Use Preference from v7 library (android.support.v7.preference.PreferenceScreen)
+