From 722f59f4c3673acc6f576e33c032bd610d10a1ae Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 25 Aug 2020 23:22:48 +0300 Subject: [PATCH 001/144] Removes libs/utils and point utils to a local directory --- WordPress/build.gradle | 9 +- libs/utils/.circleci/config.yml | 35 - libs/utils/.editorconfig | 2 - libs/utils/.gitignore | 57 -- libs/utils/.idea/checkstyle-idea.xml | 18 - libs/utils/.idea/codeStyleSettings.xml | 274 ------ libs/utils/.idea/codeStyles/Project.xml | 281 ------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - libs/utils/.idea/compiler.xml | 22 - .../.idea/copyright/profiles_settings.xml | 3 - libs/utils/.idea/encodings.xml | 6 - libs/utils/.idea/externalDependencies.xml | 6 - .../inspectionProfiles/Project_Default.xml | 16 - .../inspectionProfiles/profiles_settings.xml | 7 - libs/utils/.idea/vcs.xml | 6 - libs/utils/README.md | 40 - libs/utils/WordPressUtils/README.md | 1 - libs/utils/WordPressUtils/build.gradle | 101 -- .../WordPressUtils/gradle.properties-example | 6 - .../android/util/ImageUtilsTest.java | 89 -- .../wordpress/android/util/JSONUtilsTest.java | 37 - .../android/util/PhotonUtilsTest.java | 106 --- .../android/util/ShortcodeUtilsTest.java | 32 - .../wordpress/android/util/UrlUtilsTest.java | 131 --- .../src/main/AndroidManifest.xml | 6 - .../util/AccessibilityEventListener.java | 7 - .../android/util/AccessibilityUtils.java | 108 --- .../wordpress/android/util/ActivityUtils.java | 55 -- .../wordpress/android/util/AlertUtils.java | 100 -- .../org/wordpress/android/util/AppLog.java | 381 -------- .../android/util/AutoForeground.java | 223 ----- .../util/AutoForegroundNotification.java | 79 -- .../wordpress/android/util/DateTimeUtils.java | 251 ----- .../wordpress/android/util/DeviceUtils.java | 179 ---- .../wordpress/android/util/DisplayUtils.java | 98 -- .../wordpress/android/util/EditTextUtils.java | 88 -- .../android/util/EmoticonsUtils.java | 110 --- .../org/wordpress/android/util/FileUtils.java | 61 -- .../wordpress/android/util/FormatUtils.java | 79 -- .../wordpress/android/util/GeocoderUtils.java | 115 --- .../wordpress/android/util/GravatarUtils.java | 86 -- .../org/wordpress/android/util/HtmlUtils.java | 154 --- .../wordpress/android/util/ImageUtils.java | 898 ------------------ .../org/wordpress/android/util/JSONUtils.java | 262 ----- .../wordpress/android/util/LanguageUtils.java | 72 -- .../org/wordpress/android/util/ListUtils.java | 47 - .../org/wordpress/android/util/MapUtils.java | 115 --- .../wordpress/android/util/MediaUtils.java | 563 ----------- .../wordpress/android/util/NetworkUtils.java | 100 -- .../wordpress/android/util/PackageUtils.java | 45 - .../android/util/PermissionUtils.java | 104 -- .../wordpress/android/util/PhotonUtils.java | 143 --- .../android/util/ProfilingUtils.java | 87 -- .../wordpress/android/util/ServiceUtils.java | 16 - .../android/util/ShortcodeUtils.java | 31 - .../org/wordpress/android/util/SqlUtils.java | 146 --- .../wordpress/android/util/StringUtils.java | 363 ------- .../android/util/SystemServiceFactory.java | 14 - .../util/SystemServiceFactoryAbstract.java | 7 - .../util/SystemServiceFactoryDefault.java | 9 - .../wordpress/android/util/ToastUtils.java | 53 -- .../org/wordpress/android/util/UrlUtils.java | 318 ------- .../android/util/UserEmailUtils.java | 39 - .../wordpress/android/util/VideoUtils.java | 43 - .../org/wordpress/android/util/ViewUtils.java | 81 -- .../wordpress/android/util/WebViewUtils.java | 22 - .../android/util/helpers/Debouncer.java | 39 - .../helpers/ListScrollPositionManager.java | 58 -- .../android/util/helpers/MediaFile.java | 348 ------- .../android/util/helpers/MediaGallery.java | 86 -- .../util/helpers/MediaGalleryImageSpan.java | 21 - .../RecyclerViewScrollPositionManager.java | 39 - .../util/helpers/SwipeToRefreshHelper.java | 110 --- .../android/util/helpers/Version.java | 55 -- .../util/helpers/WPHtmlTagHandler.java | 85 -- .../android/util/helpers/WPImageSpan.java | 140 --- .../android/util/helpers/WPQuoteSpan.java | 44 - .../android/util/helpers/WPUnderlineSpan.java | 34 - .../util/helpers/WPWebChromeClient.java | 45 - .../util/helpers/logfile/LogFileCleaner.kt | 22 - .../util/helpers/logfile/LogFileProvider.kt | 42 - .../logfile/LogFileProviderInterface.kt | 12 - .../util/helpers/logfile/LogFileWriter.kt | 45 - .../util/widgets/AutoResizeTextView.java | 307 ------ .../widgets/CustomSwipeRefreshLayout.java | 34 - .../util/widgets/WPTextInputLayout.java | 49 - .../src/main/res/values/dimens.xml | 6 - .../src/main/res/values/strings.xml | 5 - .../src/main/res/values/tags.xml | 3 - .../android/util/DateTimeUtilsTest.java | 46 - .../android/util/LogFileCleanerTest.kt | 75 -- .../android/util/LogFileHelpersTest.kt | 64 -- .../android/util/LogFileWriterTest.kt | 53 -- libs/utils/build.gradle | 41 - libs/utils/config/checkstyle.xml | 276 ------ libs/utils/gradle/wrapper/gradle-wrapper.jar | Bin 54783 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - libs/utils/gradlew | 172 ---- libs/utils/gradlew.bat | 84 -- libs/utils/settings.gradle | 1 - settings.gradle | 2 +- 101 files changed, 7 insertions(+), 9490 deletions(-) delete mode 100644 libs/utils/.circleci/config.yml delete mode 100644 libs/utils/.editorconfig delete mode 100644 libs/utils/.gitignore delete mode 100644 libs/utils/.idea/checkstyle-idea.xml delete mode 100644 libs/utils/.idea/codeStyleSettings.xml delete mode 100644 libs/utils/.idea/codeStyles/Project.xml delete mode 100644 libs/utils/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 libs/utils/.idea/compiler.xml delete mode 100644 libs/utils/.idea/copyright/profiles_settings.xml delete mode 100644 libs/utils/.idea/encodings.xml delete mode 100644 libs/utils/.idea/externalDependencies.xml delete mode 100644 libs/utils/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 libs/utils/.idea/inspectionProfiles/profiles_settings.xml delete mode 100644 libs/utils/.idea/vcs.xml delete mode 100644 libs/utils/README.md delete mode 100644 libs/utils/WordPressUtils/README.md delete mode 100644 libs/utils/WordPressUtils/build.gradle delete mode 100644 libs/utils/WordPressUtils/gradle.properties-example delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/main/AndroidManifest.xml delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java delete mode 100644 libs/utils/WordPressUtils/src/main/res/values/dimens.xml delete mode 100644 libs/utils/WordPressUtils/src/main/res/values/strings.xml delete mode 100644 libs/utils/WordPressUtils/src/main/res/values/tags.xml delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt delete mode 100644 libs/utils/build.gradle delete mode 100644 libs/utils/config/checkstyle.xml delete mode 100644 libs/utils/gradle/wrapper/gradle-wrapper.jar delete mode 100644 libs/utils/gradle/wrapper/gradle-wrapper.properties delete mode 100755 libs/utils/gradlew delete mode 100644 libs/utils/gradlew.bat delete mode 100644 libs/utils/settings.gradle diff --git a/WordPress/build.gradle b/WordPress/build.gradle index f89d4da59164..1c3c52a60a7b 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -305,9 +305,12 @@ dependencies { implementation ('com.github.indexos.media-for-mobile:android:43a9026f0973a2f0a74fa813132f6a16f7499c3a') - implementation project(path:':libs:utils:WordPressUtils') - testImplementation project(path:':libs:utils:WordPressUtils') - debugImplementation project(path:':libs:utils:WordPressUtils') + implementation 'org.wordpress.android:WordPressUtils' + testImplementation 'org.wordpress.android:WordPressUtils' + debugImplementation 'org.wordpress.android:WordPressUtils' +// implementation project(path:':libs:utils:WordPressUtils') +// testImplementation project(path:':libs:utils:WordPressUtils') +// debugImplementation project(path:':libs:utils:WordPressUtils') implementation (project(path:':libs:networking:WordPressNetworking')) { exclude group: "com.android.volley" } diff --git a/libs/utils/.circleci/config.yml b/libs/utils/.circleci/config.yml deleted file mode 100644 index d2e16d4f447e..000000000000 --- a/libs/utils/.circleci/config.yml +++ /dev/null @@ -1,35 +0,0 @@ -version: 2.1 - -orbs: - android: wordpress-mobile/android@0.0.22 - -jobs: - Lint: - executor: - name: android/default - api-version: "27" - steps: - - checkout - - android/restore-gradle-cache - - run: - name: Lint & Checkstyle - command: ./gradlew --stacktrace lint checkstyle - - android/save-gradle-cache - - android/save-lint-results - Build: - executor: - name: android/default - api-version: "27" - steps: - - checkout - - android/restore-gradle-cache - - run: - name: Build - command: ./gradlew --stacktrace assembleDebug assembleRelease - - android/save-gradle-cache - -workflows: - WordPress-Utils-Android: - jobs: - - Lint - - Build diff --git a/libs/utils/.editorconfig b/libs/utils/.editorconfig deleted file mode 100644 index 590d68372e0d..000000000000 --- a/libs/utils/.editorconfig +++ /dev/null @@ -1,2 +0,0 @@ -[*.{kt,kts}] -max_line_length=120 diff --git a/libs/utils/.gitignore b/libs/utils/.gitignore deleted file mode 100644 index 3f762d543ec7..000000000000 --- a/libs/utils/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -# OS X generated file -.DS_Store - -# built application files -*.apk -*.ap_ - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ -build/ -build.log - -# Local configuration file (sdk path, etc) -local.properties - -# Eclipse project files -.settings/ -.classpath -.project - -# Intellij project files -*.iml -*.ipr -*.iws -/.idea/* - -# IntelliJ/Android Studio exceptions -!/.idea/vcs.xml -!/.idea/codeStyles/ -!/.idea/fileTemplates/ -!/.idea/inspectionProfiles/ -!/.idea/scopes/ -!/.idea/codeStyleSettings.xml -!/.idea/encodings.xml -!/.idea/copyright/ -!/.idea/compiler.xml -# Enforce plugins -!/.idea/externalDependencies.xml -# Checkstyle configuration -!/.idea/checkstyle-idea.xml - -# Gradle -.gradle/ -gradle.properties - -# Silver Searcher ignore file -.agignore - -# Windows Backup -*.bak diff --git a/libs/utils/.idea/checkstyle-idea.xml b/libs/utils/.idea/checkstyle-idea.xml deleted file mode 100644 index 0cfcc74ce7f4..000000000000 --- a/libs/utils/.idea/checkstyle-idea.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/codeStyleSettings.xml b/libs/utils/.idea/codeStyleSettings.xml deleted file mode 100644 index c3f56acf6b1c..000000000000 --- a/libs/utils/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/codeStyles/Project.xml b/libs/utils/.idea/codeStyles/Project.xml deleted file mode 100644 index a6f575ec5fc6..000000000000 --- a/libs/utils/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/codeStyles/codeStyleConfig.xml b/libs/utils/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c2b23..000000000000 --- a/libs/utils/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/utils/.idea/compiler.xml b/libs/utils/.idea/compiler.xml deleted file mode 100644 index 9a8b7e5c45ee..000000000000 --- a/libs/utils/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/copyright/profiles_settings.xml b/libs/utils/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3377d4..000000000000 --- a/libs/utils/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/libs/utils/.idea/encodings.xml b/libs/utils/.idea/encodings.xml deleted file mode 100644 index 97626ba45445..000000000000 --- a/libs/utils/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/externalDependencies.xml b/libs/utils/.idea/externalDependencies.xml deleted file mode 100644 index 687e9fd1e473..000000000000 --- a/libs/utils/.idea/externalDependencies.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/inspectionProfiles/Project_Default.xml b/libs/utils/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 4e2b427ce8a3..000000000000 --- a/libs/utils/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/utils/.idea/inspectionProfiles/profiles_settings.xml b/libs/utils/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b312839bf2e..000000000000 --- a/libs/utils/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/utils/.idea/vcs.xml b/libs/utils/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4cb4..000000000000 --- a/libs/utils/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/README.md b/libs/utils/README.md deleted file mode 100644 index 7eb92f06804b..000000000000 --- a/libs/utils/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# WordPress-Utils-Android - -Collection of utility methods for Android and WordPress. - -## Use the library in your project - -* In your build.gradle: -```groovy -dependencies { - compile 'org.wordpress:utils:1.22.0' // use version 1.22.0 -} -``` - -## Publish an updated version to your local maven repository - -You can bump the [version name in the main build file: `WordPressUtils/build.gradle`][1]. After updating the build file, you can build, and publish the library to your local maven repo. That will let you try the new version in your app for example. - -```shell -$ ./gradlew assemble test publishToMavenLocal -``` - -## Publish it to Bintray - -When a new version is ready to be published to the remote repository, use the following command to upload it to Bintray: - -```shell -$ ./gradlew assemble test bintrayUpload -PbintrayUser=FIXME -PbintrayKey=FIXME -PdryRun=false -``` - -## Apps and libraries using WordPress-Utils-Android: - -- [WordPress for Android][2] -- [FluxC][3] - -## License -Dual licensed under MIT, and GPL. - -[1]: https://github.com/wordpress-mobile/WordPress-Utils-Android/blob/a9fbe8e6597d44055ec2180dbf45aecbfc332a20/WordPressUtils/build.gradle#L37 -[2]: https://github.com/wordpress-mobile/WordPress-Android -[3]: https://github.com/wordpress-mobile/WordPress-FluxC-Android diff --git a/libs/utils/WordPressUtils/README.md b/libs/utils/WordPressUtils/README.md deleted file mode 100644 index 62a759585e63..000000000000 --- a/libs/utils/WordPressUtils/README.md +++ /dev/null @@ -1 +0,0 @@ -# org.wordpress.android.util \ No newline at end of file diff --git a/libs/utils/WordPressUtils/build.gradle b/libs/utils/WordPressUtils/build.gradle deleted file mode 100644 index d182429e1547..000000000000 --- a/libs/utils/WordPressUtils/build.gradle +++ /dev/null @@ -1,101 +0,0 @@ -buildscript { - ext.kotlinVersion = '1.3.61' - ext.kotlin_ktx_version = '1.2.0' - - repositories { - google() - jcenter() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - classpath 'com.android.tools.build:gradle:3.5.1' - classpath 'com.novoda:bintray-release:0.9.1' - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'com.novoda.bintray-release' - -repositories { - google() - jcenter() -} - -dependencies { - implementation 'org.apache.commons:commons-text:1.1' - implementation 'com.android.volley:volley:1.1.1' - implementation 'com.google.android.material:material:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.0.0' - implementation 'org.greenrobot:eventbus:3.0.0' - - implementation "androidx.core:core-ktx:$kotlin_ktx_version" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" - - testImplementation 'junit:junit:4.12' - testImplementation 'org.assertj:assertj-core:3.11.1' - testImplementation "org.robolectric:robolectric:4.3.1" - testImplementation 'androidx.test:core:1.0.0' - - lintChecks 'org.wordpress:lint:1.0.1' - androidTestImplementation 'androidx.test:runner:1.1.0' - androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2' - -} - -android { - useLibrary 'org.apache.http.legacy' - - compileSdkVersion 28 - buildToolsVersion '28.0.3' - - defaultConfig { - versionName "1.27" - minSdkVersion 18 - targetSdkVersion 26 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - testOptions { - unitTests { - includeAndroidResources = true - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } -} - -android.libraryVariants.all { variant -> - task("generate${variant.name}Javadoc", type: Javadoc) { - description "Generates Javadoc for $variant.name." - source = variant.javaCompile.source - - options { - links "http://docs.oracle.com/javase/7/docs/api/" - } - exclude '**/R.java' - doFirst { - classpath = - files(variant.javaCompile.classpath.files, - project.android.getBootClasspath()) - } - } -} - -publish { - artifactId = 'utils' - userOrg = 'wordpress-mobile' - groupId = 'org.wordpress' - uploadName = 'utils' - desc = 'Utils library for Android' - publishVersion = android.defaultConfig.versionName - licences = ['MIT', 'GPL'] - website = 'https://github.com/wordpress-mobile/WordPress-Utils-Android/' - dryRun = 'false' - autoPublish = 'true' -} diff --git a/libs/utils/WordPressUtils/gradle.properties-example b/libs/utils/WordPressUtils/gradle.properties-example deleted file mode 100644 index 5281d935c4cf..000000000000 --- a/libs/utils/WordPressUtils/gradle.properties-example +++ /dev/null @@ -1,6 +0,0 @@ -ossrhUsername=hello -ossrhPassword=world - -signing.keyId=byebye -signing.password=secret -signing.secretKeyRingFile=/home/user/secret.gpg diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java deleted file mode 100644 index 05b0af2f7ade..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.wordpress.android.util; - -import android.graphics.BitmapFactory; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ImageUtilsTest { - @Test - public void testGetScaleForResizingReturnsOneWhenMaxSizeIsZero() { - BitmapFactory.Options options = new BitmapFactory.Options(); - int scale = ImageUtils.getScaleForResizing(0, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingSameSizeReturnsOne() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 100; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingPortraitMaxHeightSameAsMaxSizeReturnsOne() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 1; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingLandscapeMaxWidthSameAsMaxSizeReturnsOne() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 1; - options.outWidth = 100; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingDoubleSizeReturnsTwo() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 200; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(2, scale); - } - - @Test - public void testGetScaleForResizingThreeTimesSizeReturnsTwo() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 300; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(2, scale); - } - - @Test - public void testGetScaleForResizingEightTimesSizeReturnsEight() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 800; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(8, scale); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java deleted file mode 100644 index e02656fe4f3f..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.wordpress.android.util; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.junit.Test; - -public class JSONUtilsTest { - @Test - public void testQueryJSONNullSource1() { - JSONUtils.queryJSON((JSONObject) null, "", ""); - } - - @Test - public void testQueryJSONNullSource2() { - JSONUtils.queryJSON((JSONArray) null, "", ""); - } - - @Test - public void testQueryJSONNullQuery1() { - JSONUtils.queryJSON(new JSONObject(), null, ""); - } - - @Test - public void testQueryJSONNullQuery2() { - JSONUtils.queryJSON(new JSONArray(), null, ""); - } - - @Test - public void testQueryJSONNullReturnValue1() { - JSONUtils.queryJSON(new JSONObject(), "", null); - } - - @Test - public void testQueryJSONNullReturnValue2() { - JSONUtils.queryJSON(new JSONArray(), "", null); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java deleted file mode 100644 index 0e2d4b301706..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Test; -import org.wordpress.android.util.PhotonUtils.Quality; - -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; - - -public class PhotonUtilsTest { - @Test - public void getPhotonImageUrlIsEmptyWhenUrlIsNull() { - String photonUrl = PhotonUtils.getPhotonImageUrl(null, 0, 1); - - assertThat(photonUrl, equalTo("")); - } - - @Test - public void getPhotonImageUrlIsEmptyWhenUrlIsEmpty() { - String photonUrl = PhotonUtils.getPhotonImageUrl("", 0, 1); - - assertThat(photonUrl, equalTo("")); - } - - @Test - public void getPhotonImageUrlReturnsImageUrlOnNoScheme() { - String imageUrl = "wordpress.com"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1); - - assertThat(photonUrl, equalTo(imageUrl)); - } - - @Test - public void getPhotonImageUrlReturnsMshots() { - String imageUrl = "http://test.wordpress.com/mshots/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1); - - assertThat(photonUrl, equalTo("http://test.wordpress.com/mshots/test.jpg?w=0&h=1")); - } - - @Test - public void getPhotonImageUrlReturnsCorrectQuality() { - Map qualities = new HashMap<>(); - qualities.put(Quality.HIGH, "100"); - qualities.put(Quality.MEDIUM, "65"); - qualities.put(Quality.LOW, "35"); - - String imageUrl = "http://test.wordpress.com/test.jpg?query=dummy"; - - for (Quality quality : qualities.keySet()) { - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1, quality); - assertThat(photonUrl, containsString("&quality=" + qualities.get(quality))); - } - } - - @Test - public void getPhotonImageUrlUsesResize() { - String imageUrl = "http://test.wordpress.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("http://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); - } - - @Test - public void getPhotonImageUrlManageSslOnPhotonUrl() { - String imageUrl = "https://i0.wp.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/test.jpg?strip=info&quality=65&resize=2,1")); - - imageUrl = "https://i0.wp.com/test.jpg?query=dummy&ssl=1"; - photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/test.jpg?strip=info&quality=65&resize=2,1&ssl=1")); - } - - @Test - public void getPhotonImageUrlDoNotUseSslOnWordPressCom() { - String imageUrl = "https://test.wordpress.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); - - imageUrl = "https://test.wordpress.com/test.jpg?query=dummy&ssl=1"; - photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); - } - - @Test - public void getPhotonImageUrlUsesSslOnHttpsImageUrl() { - String imageUrl = "http://mysite.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/mysite.com/test.jpg?strip=info&quality=65&resize=2,1")); - - imageUrl = "https://mysite.com/test.jpg?query=dummy&ssl=1"; - photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/mysite.com/test.jpg?strip=info&quality=65&resize=2,1&ssl=1")); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java deleted file mode 100644 index 32435e40e6e8..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ShortcodeUtilsTest { - @Test - public void testGetVideoPressShortcodeFromId() { - assertEquals("[wpvideo abcd1234]", ShortcodeUtils.getVideoPressShortcodeFromId("abcd1234")); - } - - @Test - public void testGetVideoPressShortcodeFromNullId() { - assertEquals("", ShortcodeUtils.getVideoPressShortcodeFromId(null)); - } - - @Test - public void testGetVideoPressIdFromCorrectShortcode() { - assertEquals("abcd1234", ShortcodeUtils.getVideoPressIdFromShortCode("[wpvideo abcd1234]")); - } - - @Test - public void testGetVideoPressIdFromInvalidShortcode() { - assertEquals("", ShortcodeUtils.getVideoPressIdFromShortCode("[other abcd1234]")); - } - - @Test - public void testGetVideoPressIdFromNullShortcode() { - assertEquals("", ShortcodeUtils.getVideoPressIdFromShortCode(null)); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java deleted file mode 100644 index 9cf88220712d..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Test; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class UrlUtilsTest { - @Test - public void testGetDomainFromUrlWithEmptyStringDoesNotReturnNull() { - assertNotNull(UrlUtils.getHost("")); - } - - @Test - public void testGetDomainFromUrlWithNoHostDoesNotReturnNull() { - assertNotNull(UrlUtils.getHost("wordpress")); - } - - @Test - public void testGetDomainFromUrlWithHostReturnsHost() { - String url = "http://www.wordpress.com"; - String host = UrlUtils.getHost(url); - - assertTrue(host.equals("www.wordpress.com")); - } - - @Test - public void testAppendUrlParameter1() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test", "preview", "true"); - assertEquals("http://wp.com/test?preview=true", url); - } - - @Test - public void testAppendUrlParameter2() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony", "preview", "true"); - assertEquals("http://wp.com/test?q=pony&preview=true", url); - } - - @Test - public void testAppendUrlParameter3() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony#unicorn", "preview", "true"); - assertEquals("http://wp.com/test?q=pony&preview=true#unicorn", url); - } - - @Test - public void testAppendUrlParameter4() { - String url = UrlUtils.appendUrlParameter("/relative/test", "preview", "true"); - assertEquals("/relative/test?preview=true", url); - } - - @Test - public void testAppendUrlParameter5() { - String url = UrlUtils.appendUrlParameter("/relative/", "preview", "true"); - assertEquals("/relative/?preview=true", url); - } - - @Test - public void testAppendUrlParameter6() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test/", "preview", "true"); - assertEquals("http://wp.com/test/?preview=true", url); - } - - @Test - public void testAppendUrlParameter7() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test/?q=pony", "preview", "true"); - assertEquals("http://wp.com/test/?q=pony&preview=true", url); - } - - @Test - public void testAppendUrlParameters1() { - Map params = new HashMap<>(); - params.put("w", "200"); - params.put("h", "300"); - String url = UrlUtils.appendUrlParameters("http://wp.com/test", params); - if (!url.equals("http://wp.com/test?h=300&w=200") && !url.equals("http://wp.com/test?w=200&h=300")) { - assertTrue("failed test on url: " + url, false); - } - } - - @Test - public void testAppendUrlParameters2() { - Map params = new HashMap<>(); - params.put("h", "300"); - params.put("w", "200"); - String url = UrlUtils.appendUrlParameters("/relative/test", params); - if (!url.equals("/relative/test?h=300&w=200") && !url.equals("/relative/test?w=200&h=300")) { - assertTrue("failed test on url: " + url, false); - } - } - - @Test - public void testHttps1() { - assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com/xmlrpc.php"))); - } - - @Test - public void testHttps2() { - assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com#.b.com/test"))); - } - - @Test - public void testHttps3() { - assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com/xmlrpc.php"))); - } - - @Test - public void testHttps4() { - assertTrue(UrlUtils.isHttps(buildURL("https://wordpress.com"))); - } - - @Test - public void testHttps5() { - assertTrue(UrlUtils.isHttps(buildURL("https://wordpress.com/test#test"))); - } - - private URL buildURL(String address) { - URL url = null; - try { - url = new URL(address); - } catch (MalformedURLException e) { - } - return url; - } -} diff --git a/libs/utils/WordPressUtils/src/main/AndroidManifest.xml b/libs/utils/WordPressUtils/src/main/AndroidManifest.xml deleted file mode 100644 index d52c0f661462..000000000000 --- a/libs/utils/WordPressUtils/src/main/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java deleted file mode 100644 index 78b9ee6d9fd6..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wordpress.android.util; - -import android.view.accessibility.AccessibilityEvent; - -public interface AccessibilityEventListener { - void onResult(AccessibilityEvent event); -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java deleted file mode 100644 index 3c6ad25eebd5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Activity; -import android.content.Context; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.view.AccessibilityDelegateCompat; -import androidx.core.view.ViewCompat; -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; - -import com.google.android.material.snackbar.Snackbar; - -import org.wordpress.android.util.AppLog.T; - -import static android.content.Context.ACCESSIBILITY_SERVICE; -import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED; - -public class AccessibilityUtils { - private static final int SNACKBAR_WITH_ACTION_DURATION_IN_MILLIS = 10000; - - public static boolean isAccessibilityEnabled(Context ctx) { - AccessibilityManager am = (AccessibilityManager) ctx.getSystemService(ACCESSIBILITY_SERVICE); - return am != null && am.isEnabled(); - } - - /** - * If the default duration is LENGTH_INDEFINITE, ignore accessibility duration and return LENGTH_INDEFINITE. - * If the accessibility is enabled, returns increased snackbar duration, otherwise returns defaultDuration. - * - * @param defaultDuration Either be one of the predefined lengths: LENGTH_SHORT, LENGTH_LONG, or a custom duration - * in milliseconds. - */ - public static int getSnackbarDuration(Context ctx, int defaultDuration) { - return defaultDuration == Snackbar.LENGTH_INDEFINITE ? Snackbar.LENGTH_INDEFINITE - : isAccessibilityEnabled(ctx) ? SNACKBAR_WITH_ACTION_DURATION_IN_MILLIS : defaultDuration; - } - - public static void setActionModeDoneButtonContentDescription(@Nullable final Activity activity, - @NonNull final String contentDescription) { - if (activity != null) { - View decorView = activity.getWindow().getDecorView(); - - decorView.post(new Runnable() { - @Override public void run() { - View doneButton = activity.findViewById(androidx.appcompat.R.id.action_mode_close_button); - - if (doneButton != null) { - doneButton.setContentDescription(contentDescription); - } - } - }); - } - } - - public static void addPopulateAccessibilityEventFocusedListener(@NonNull final View target, - @NonNull final AccessibilityEventListener - listener) { - ViewCompat.setAccessibilityDelegate(target, new AccessibilityDelegateCompat() { - @Override public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { - if (event.getEventType() == TYPE_VIEW_ACCESSIBILITY_FOCUSED) { - listener.onResult(event); - } - super.onPopulateAccessibilityEvent(host, event); - } - }); - } - - public static void disableHintAnnouncement(@NonNull TextView textView) { - setAccessibilityDelegateSafely(textView, new AccessibilityDelegateCompat() { - @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setHintText(null); - } - }); - } - - /** - * When the minsdk is 28 this can be replaced by adding android:accessibilityHeading="true" as a property to the - * view's xml declaration. - * @param view that will become a heading. - */ - public static void enableAccessibilityHeading(@NonNull View view) { - setAccessibilityDelegateSafely(view, new AccessibilityDelegateCompat() { - @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setHeading(true); - } - }); - } - - public static void setAccessibilityDelegateSafely(View view, - AccessibilityDelegateCompat accessibilityDelegateCompat) { - if (ViewCompat.hasAccessibilityDelegate(view)) { - final String errorMessage = "View already has an AccessibilityDelegate."; - if (PackageUtils.isDebugBuild()) { - throw new RuntimeException(errorMessage); - } - AppLog.e(T.UTILS, errorMessage); - } else { - ViewCompat.setAccessibilityDelegate(view, accessibilityDelegateCompat); - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java deleted file mode 100644 index 0751b0a5d977..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.view.View; -import android.view.inputmethod.InputMethodManager; - -import androidx.annotation.Nullable; - -public class ActivityUtils { - /** - * Hides the keyboard in the given {@link Activity}'s current focus using the - * {@link InputMethodManager#HIDE_NOT_ALWAYS} flag, which will hide the keyboard unless it was originally shown - * with {@link InputMethodManager#SHOW_FORCED}. - */ - public static void hideKeyboard(Activity activity) { - if (activity != null && activity.getCurrentFocus() != null) { - InputMethodManager inputManager = (InputMethodManager) activity.getSystemService( - Context.INPUT_METHOD_SERVICE); - inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), - InputMethodManager.HIDE_NOT_ALWAYS); - } - } - - /** - * Hides the keyboard for the given {@link View}. No {@link InputMethodManager} flag is used, therefore the - * keyboard is forcibly hidden regardless of the circumstances. - */ - public static void hideKeyboardForced(@Nullable final View view) { - if (view == null) { - return; - } - InputMethodManager inputMethodManager = - (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - - /** - * Shows the keyboard for the given {@link View} using the {@link InputMethodManager#SHOW_IMPLICIT} flag, - * which is an implicit request (i.e. not requested by the user) to show the keyboard. - */ - public static void showKeyboard(@Nullable final View view) { - if (view == null) { - return; - } - InputMethodManager inputMethodManager = - (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); - } - - public static boolean isDeepLinking(Intent intent) { - return Intent.ACTION_VIEW.equals(intent.getAction()); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java deleted file mode 100644 index 6a09c42f20c1..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2011 wordpress.org - * - * 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. - */ - -package org.wordpress.android.util; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; - -public class AlertUtils { - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param messageId - */ - public static void showAlert(Context context, int titleId, int messageId) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(android.R.string.ok, null) - .setMessage(messageId) - .create(); - - dlg.show(); - } - - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param message - */ - public static void showAlert(Context context, int titleId, String message) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(android.R.string.ok, null) - .setMessage(message) - .create(); - - dlg.show(); - } - - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param messageId - * @param positiveButtontxt - * @param positiveListener - * @param negativeButtontxt - * @param negativeListener - */ - public static void showAlert(Context context, int titleId, int messageId, - CharSequence positiveButtontxt, DialogInterface.OnClickListener positiveListener, - CharSequence negativeButtontxt, DialogInterface.OnClickListener negativeListener) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(positiveButtontxt, positiveListener) - .setNegativeButton(negativeButtontxt, negativeListener) - .setMessage(messageId) - .setCancelable(false) - .create(); - - dlg.show(); - } - - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param message - * @param positiveButtontxt - * @param positiveListener - */ - public static void showAlert(Context context, int titleId, String message, - CharSequence positiveButtontxt, DialogInterface.OnClickListener positiveListener) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(positiveButtontxt, positiveListener) - .setMessage(message) - .setCancelable(false) - .create(); - - dlg.show(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java deleted file mode 100644 index b0bb2a6e467a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java +++ /dev/null @@ -1,381 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.NonNull; - -import org.wordpress.android.util.helpers.logfile.LogFileCleaner; -import org.wordpress.android.util.helpers.logfile.LogFileProvider; -import org.wordpress.android.util.helpers.logfile.LogFileWriter; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.NoSuchElementException; -import java.util.TimeZone; - -import static java.lang.String.format; - -/** - * simple wrapper for Android log calls, enables recording and displaying log - */ -public class AppLog { - // T for Tag - public enum T { - READER, - EDITOR, - MEDIA, - NUX, - API, - STATS, - UTILS, - NOTIFS, - DB, - POSTS, - PAGES, - COMMENTS, - THEMES, - TESTS, - PROFILING, - SIMPERIUM, - SUGGESTION, - MAIN, - SETTINGS, - PLANS, - PEOPLE, - SHARING, - PLUGINS, - ACTIVITY_LOG, - JETPACK_REMOTE_INSTALL, - SUPPORT, - SITE_CREATION, - DOMAIN_REGISTRATION, - FEATURE_ANNOUNCEMENT - } - - public static final String TAG = "WordPress"; - public static final int HEADER_LINE_COUNT = 2; - private static boolean mEnableRecording = false; - private static List mListeners = new ArrayList<>(0); - private static TimeZone mUtcTimeZone = TimeZone.getTimeZone("UTC"); - - private AppLog() { - throw new AssertionError(); - } - - /** - * Capture log so it can be displayed by AppLogViewerActivity - * @param enable A boolean flag to capture log. Default is false, pass true to enable recording - */ - public static void enableRecording(boolean enable) { - mEnableRecording = enable; - } - - public static void addListener(@NonNull AppLogListener listener) { - mListeners.add(listener); - } - - public static void removeListeners() { - mListeners.clear(); - } - - public interface AppLogListener { - void onLog(T tag, LogLevel logLevel, String message); - } - - /** - * Add a LogFileWriter that will persist logs to disk - * @param context The current application context - * @param maxLogCount The maximum number of logs that should be stored - */ - public static void enableLogFilePersistence(Context context, int maxLogCount) { - LogFileProvider logFileProvider = LogFileProvider.fromContext(context); - new LogFileCleaner(logFileProvider, maxLogCount).clean(); - - sLogFileWriter = new LogFileWriter(logFileProvider); - sLogFileWriter.write(getAppInfoHeaderText(context) + "\n"); - sLogFileWriter.write(getDeviceInfoHeaderText(context) + "\n"); - } - - private static LogFileWriter sLogFileWriter; - - /** - * Sends a VERBOSE log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void v(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.v(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.v, message); - } - - /** - * Sends a DEBUG log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void d(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.d(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.d, message); - } - - /** - * Sends a INFO log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void i(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.i(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.i, message); - } - - /** - * Sends a WARN log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void w(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.w(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.w, message); - } - - /** - * Sends a ERROR log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void e(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.e(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.e, message); - } - - /** - * Send a ERROR log message and log the exception. - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - * @param tr An exception to log - */ - public static void e(T tag, String message, Throwable tr) { - message = StringUtils.notNullStr(message); - Log.e(TAG + "-" + tag.toString(), message, tr); - addEntry(tag, LogLevel.e, message + " - exception: " + tr.getMessage()); - addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr)); - } - - /** - * Sends a ERROR log message and the exception with StackTrace - * @param tag Used to identify the source of a log message. It usually identifies the class or activity where the - * log call occurs. - * @param tr An exception to log to get StackTrace - */ - public static void e(T tag, Throwable tr) { - Log.e(TAG + "-" + tag.toString(), tr.getMessage(), tr); - addEntry(tag, LogLevel.e, tr.getMessage()); - addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr)); - } - - /** - * Sends a ERROR log message - * @param tag Used to identify the source of a log message. It usually identifies the class or activity where the - * log call occurs. - * @param volleyErrorMsg - * @param statusCode - */ - public static void e(T tag, String volleyErrorMsg, int statusCode) { - if (TextUtils.isEmpty(volleyErrorMsg)) { - return; - } - String logText; - if (statusCode == -1) { - logText = volleyErrorMsg; - } else { - logText = volleyErrorMsg + ", status " + statusCode; - } - Log.e(TAG + "-" + tag.toString(), logText); - addEntry(tag, LogLevel.w, logText); - } - - // -------------------------------------------------------------------------------------------------------- - - private static final int MAX_ENTRIES = 99; - - public enum LogLevel { - v, d, i, w, e; - } - - private static class LogEntry { - final LogLevel mLogLevel; - final String mLogText; - final java.util.Date mDate; - final T mLogTag; - - LogEntry(LogLevel logLevel, String logText, T logTag) { - mLogLevel = logLevel; - mDate = new Date(); - if (logText == null) { - mLogText = "null"; - } else { - mLogText = logText; - } - mLogTag = logTag; - } - - private String formatLogDate() { - SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd kk:mm", Locale.US); - sdf.setTimeZone(mUtcTimeZone); - return sdf.format(mDate); - } - - private String toHtml() { - StringBuilder sb = new StringBuilder(); - sb.append("["); - sb.append(formatLogDate()).append(" "); - sb.append(mLogTag.name()).append(" "); - sb.append(mLogLevel.name()); - sb.append("] "); - sb.append(TextUtils.htmlEncode(mLogText).replace("\n", "
")); - return sb.toString(); - } - - @Override - public @NonNull String toString() { - return "[" - + formatLogDate() - + " " - + mLogTag.name() - + "] " - + mLogText - + "\n"; - } - } - - private static class LogEntryList extends ArrayList { - private synchronized boolean addEntry(LogEntry entry) { - if (size() >= MAX_ENTRIES) { - removeFirstEntry(); - } - return add(entry); - } - - private void removeFirstEntry() { - Iterator it = iterator(); - if (!it.hasNext()) { - return; - } - try { - remove(it.next()); - } catch (NoSuchElementException e) { - // ignore - } - } - } - - private static LogEntryList mLogEntries = new LogEntryList(); - - private static void addEntry(T tag, LogLevel level, String text) { - // Call our listeners if any - for (AppLogListener listener : mListeners) { - listener.onLog(tag, level, text); - } - // Record entry if enabled - if (mEnableRecording) { - LogEntry entry = new LogEntry(level, text, tag); - mLogEntries.addEntry(entry); - - if (sLogFileWriter != null) { - sLogFileWriter.write(entry.toString()); - } - } - } - - private static String getStringStackTrace(Throwable throwable) { - StringWriter errors = new StringWriter(); - throwable.printStackTrace(new PrintWriter(errors)); - return errors.toString(); - } - - - private static String getAppInfoHeaderText(Context context) { - StringBuilder sb = new StringBuilder(); - PackageManager packageManager = context.getPackageManager(); - PackageInfo pkInfo = PackageUtils.getPackageInfo(context); - - ApplicationInfo applicationInfo = pkInfo != null ? pkInfo.applicationInfo : null; - String appName; - if (applicationInfo != null && packageManager.getApplicationLabel(applicationInfo) != null) { - appName = packageManager.getApplicationLabel(applicationInfo).toString(); - } else { - appName = "Unknown"; - } - sb.append(appName).append(" - ").append(PackageUtils.getVersionName(context)) - .append(" - Version code: ").append(PackageUtils.getVersionCode(context)); - return sb.toString(); - } - - private static String getDeviceInfoHeaderText(Context context) { - return "Android device name: " + DeviceUtils.getInstance().getDeviceName(context); - } - - /** - * Returns entire log as html for display (see AppLogViewerActivity) - * @param context - * @return Arraylist of Strings containing log messages - */ - public static ArrayList toHtmlList(Context context) { - ArrayList items = new ArrayList(); - - // add version & device info - be sure to change HEADER_LINE_COUNT if additional lines are added - items.add("" + getAppInfoHeaderText(context) + ""); - items.add("" + getDeviceInfoHeaderText(context) + ""); - - Iterator it = new ArrayList<>(mLogEntries).iterator(); - while (it.hasNext()) { - items.add(it.next().toHtml()); - } - return items; - } - - /** - * Converts the entire log to plain text - * @param context - * @return The log as plain text - */ - public static synchronized String toPlainText(Context context) { - StringBuilder sb = new StringBuilder(); - - // add version & device info - sb.append(getAppInfoHeaderText(context)).append("\n") - .append(getDeviceInfoHeaderText(context)).append("\n\n"); - - Iterator it = new ArrayList<>(mLogEntries).iterator(); - int lineNum = 1; - while (it.hasNext()) { - LogEntry entry = it.next(); - sb.append(format(Locale.US, "%02d - ", lineNum)) - .append(entry.toString()); - lineNum++; - } - return sb.toString(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java deleted file mode 100644 index 4cdc2911058f..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Notification; -import android.app.Service; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Binder; -import android.os.IBinder; - -import androidx.annotation.CallSuper; -import androidx.annotation.Nullable; -import androidx.core.app.NotificationManagerCompat; - -import org.greenrobot.eventbus.EventBus; -import org.wordpress.android.util.AutoForeground.ServiceState; - -import java.util.HashMap; -import java.util.Map; - -public abstract class AutoForeground - extends Service { - public static final int NOTIFICATION_ID_PROGRESS = 1; - public static final int NOTIFICATION_ID_SUCCESS = 2; - public static final int NOTIFICATION_ID_FAILURE = 3; - - public interface ServiceState { - boolean isIdle(); - - boolean isInProgress(); - - boolean isError(); - - boolean isTerminal(); - - String getStepName(); - } - - public static class ServiceEventConnection { - private final ServiceConnection mServiceConnection; - - public ServiceEventConnection(Context context, Class clazz, Object client) { - EventBus.getDefault().register(client); - - mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - // nothing here - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - // nothing here - } - }; - - context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); - } - - public void disconnect(Context context, Object client) { - context.unbindService(mServiceConnection); - EventBus.getDefault().unregister(client); - } - } - - private class LocalBinder extends Binder { - } - - private final IBinder mBinder = new LocalBinder(); - - private final Class mStateClass; - - private boolean mIsForeground; - - protected abstract void onProgressStart(); - - protected abstract void onProgressEnd(); - - protected abstract Notification getNotification(StateClass state); - - protected abstract void trackStateUpdate(Map props); - - @SuppressWarnings("unchecked") - protected AutoForeground(StateClass initialState) { - mStateClass = (Class) initialState.getClass(); - - // initialize the sticky phase if it hasn't already - if (EventBus.getDefault().getStickyEvent(mStateClass) == null) { - notifyState(initialState); - } - } - - public boolean isForeground() { - return mIsForeground; - } - - @Nullable - private StateClass getState() { - return getState(mStateClass); - } - - @Nullable - protected static StateClass getState(Class stateClass) { - return EventBus.getDefault().getStickyEvent(stateClass); - } - - @Nullable - @CallSuper - @Override - public IBinder onBind(Intent intent) { - clearAllNotifications(); - return mBinder; - } - - @CallSuper - @Override - public void onRebind(Intent intent) { - super.onRebind(intent); - - clearAllNotifications(); - background(); - } - - @CallSuper - @Override - public boolean onUnbind(Intent intent) { - if (!hasConnectedClients()) { - final StateClass state = getState(); - if (state != null && state.isInProgress()) { - promoteForeground(state); - } - } - - return true; // call onRebind() if new clients connect - } - - protected void clearAllNotifications() { - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_SUCCESS); - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_FAILURE); - } - - private EventBus getEventBus() { - return EventBus.getDefault(); - } - - private boolean hasConnectedClients() { - return getEventBus().hasSubscriberForEvent(mStateClass); - } - - private void promoteForeground(StateClass currentState) { - startForeground(NOTIFICATION_ID_PROGRESS, getNotification(currentState)); - mIsForeground = true; - } - - private void background() { - stopForeground(true); - mIsForeground = false; - } - - @CallSuper - protected void setState(StateClass newState) { - StateClass currentState = getState(); - if ((currentState == null || !currentState.isInProgress()) && newState.isInProgress()) { - onProgressStart(); - } - - track(newState); - notifyState(newState); - - if (newState.isTerminal()) { - onProgressEnd(); - stopSelf(); - } - } - - protected void track(ServiceState state) { - Map props = new HashMap<>(); - props.put("login_phase", state == null ? "null" : state.getStepName()); - props.put("login_service_is_foreground", isForeground()); - trackStateUpdate(props); - } - - protected static void clearServiceState(Class klass) { - EventBus.getDefault().removeStickyEvent(klass); - } - - @CallSuper - protected void notifyState(StateClass state) { - // sticky emit the state. The stickiness serves as a state keeping mechanism for clients to re-read upon connect - getEventBus().postSticky(state); - - if (hasConnectedClients()) { - // there are connected clients so, nothing more to do here - return; - } - - // ok, no connected clients so, update might need to be delivered to a notification as well - - if (state.isIdle()) { - // no need to have a notification when idle - return; - } - - if (state.isInProgress()) { - // operation still is progress so, update the notification - NotificationManagerCompat.from(this).notify(NOTIFICATION_ID_PROGRESS, getNotification(state)); - return; - } - - // operation has ended so, demote the Service to a background one - background(); - - // dismiss the sticky notification - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); - - // put out a simple success/failure notification - NotificationManagerCompat.from(this).notify( - state.isError() ? NOTIFICATION_ID_FAILURE : NOTIFICATION_ID_SUCCESS, - getNotification(state)); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java deleted file mode 100644 index db8c8b32b592..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; - -import androidx.annotation.ColorRes; -import androidx.annotation.DrawableRes; -import androidx.annotation.StringRes; -import androidx.core.app.NotificationCompat; - -import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_FAILURE; -import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_PROGRESS; -import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_SUCCESS; - -public class AutoForegroundNotification { - private static Intent getResumeIntent(Context context) { - // Let's get an Intent with the sole purpose of _resuming_ the app from the background - Intent resumeIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); - - // getLaunchIntentForPackage() seems to set the Package Name but if we construct a launcher Intent manually - // the package name is not set so, let's null it out here to match the manual Intent. - resumeIntent.setSelector(null); - resumeIntent.setPackage(null); - - return resumeIntent; - } - - private static NotificationCompat.Builder getNotificationBuilder(Context context, String channelId, int requestCode, - @StringRes int title, @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); - bigTextStyle.setBigContentTitle(context.getString(title)); - bigTextStyle.bigText(context.getString(content)); - - return new NotificationCompat.Builder(context, channelId) - .setStyle(bigTextStyle) - .setContentTitle(context.getString(title)) - .setContentText(context.getString(content)) - .setSmallIcon(icon) - .setColor(context.getResources().getColor(accentColor)) - .setAutoCancel(true) - .setOnlyAlertOnce(true) - .setContentIntent(PendingIntent.getActivity( - context, - requestCode, - getResumeIntent(context), - PendingIntent.FLAG_ONE_SHOT)); - } - - public static Notification progress(Context context, String channelId, int progress, @StringRes int title, - @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_PROGRESS, title, content, icon, accentColor) - .setProgress(100, progress, false) - .build(); - } - - public static Notification progressIndeterminate(Context context, String channelId, @StringRes int title, - @StringRes int content, @DrawableRes int icon, - @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_PROGRESS, title, content, icon, accentColor) - .setProgress(0, 0, true) - .build(); - } - - public static Notification success(Context context, String channelId, @StringRes int title, @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_SUCCESS, title, content, icon, accentColor) - .build(); - } - - public static Notification failure(Context context, String channelId, @StringRes int title, @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_FAILURE, title, content, icon, accentColor) - .build(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java deleted file mode 100644 index 3f8f0fee74e4..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java +++ /dev/null @@ -1,251 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.text.TextUtils; -import android.text.format.DateUtils; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -public class DateTimeUtils { - private DateTimeUtils() { - throw new AssertionError(); - } - - // See http://drdobbs.com/java/184405382 - private static final ThreadLocal ISO8601_FORMAT = new ThreadLocal() { - @Override - protected DateFormat initialValue() { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); - } - }; - - public static String javaDateToTimeSpan(final Date date, Context context, long currentTime) { - if (date == null) { - return ""; - } - - long passedTime = date.getTime(); - - // return "now" if less than a minute has elapsed - long secondsSince = (currentTime - passedTime) / 1000; - if (secondsSince < 60) { - return context.getString(R.string.timespan_now); - } - - long daysSince = secondsSince / (60 * 60 * 24); - - // less than a year old, let `DateUtils.getRelativeTimeSpanString` do the job - if (daysSince < 365) { - return DateUtils.getRelativeTimeSpanString(passedTime, currentTime, DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_ALL).toString(); - } - - // date is older, so include year (ex: Jan 30, 2013) - return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_ABBREV_ALL); - } - - /** - * Converts a date to a localized relative time span ("Now", "8 hr. ago", "Yesterday", "3 days ago", "Jul 10, 1940") - * We're using a call to `DateUtils.getRelativeTimeSpanString` in most cases. - */ - public static String javaDateToTimeSpan(final Date date, Context context) { - return javaDateToTimeSpan(date, context, System.currentTimeMillis()); - } - - /** - * Given an ISO 8601-formatted date as a String, returns a {@link Date}. - */ - public static Date dateFromIso8601(final String strDate) { - try { - DateFormat formatter = ISO8601_FORMAT.get(); - return formatter.parse(strDate); - } catch (ParseException e) { - return null; - } - } - - /** - * Given an ISO 8601-formatted date as a String, returns a {@link Date} in UTC. - */ - public static Date dateUTCFromIso8601(String iso8601date) { - try { - iso8601date = iso8601date.replace("Z", "+0000").replace("+00:00", "+0000"); - DateFormat formatter = ISO8601_FORMAT.get(); - formatter.setTimeZone(TimeZone.getTimeZone("UTC")); - return formatter.parse(iso8601date); - } catch (ParseException e) { - return null; - } - } - - /** - * Given a {@link Date}, returns an ISO 8601-formatted String. - */ - public static String iso8601FromDate(Date date) { - if (date == null) { - return ""; - } - DateFormat formatter = ISO8601_FORMAT.get(); - return formatter.format(date); - } - - /** - * Given a {@link Date}, returns an ISO 8601-formatted String in UTC. - */ - public static String iso8601UTCFromDate(Date date) { - if (date == null) { - return ""; - } - TimeZone tz = TimeZone.getTimeZone("UTC"); - DateFormat formatter = ISO8601_FORMAT.get(); - formatter.setTimeZone(tz); - - String iso8601date = formatter.format(date); - - // Use "+00:00" notation rather than "+0000" to be consistent with the WP.COM API - return iso8601date.replace("+0000", "+00:00"); - } - - /** - * Returns the current UTC date. - * - * @deprecated This method doesn't work as expected and shouldn't be used in production code. It doesn't take - * into account that `Date` class uses TimeZone.getDefault(). It substracts the currentOffsetFromUTC, but the - * final date still uses system default timezone. - */ - @Deprecated - public static Date nowUTC() { - Date dateTimeNow = new Date(); - return localDateToUTC(dateTimeNow); - } - - /** - * - * @deprecated This method doesn't work as expected and shouldn't be used in production code. It doesn't take - * into account that `Date` class uses TimeZone.getDefault(). It substracts the currentOffsetFromUTC, but the - * final date still uses system default timezone. - */ - @Deprecated - public static Date localDateToUTC(Date dtLocal) { - if (dtLocal == null) { - return null; - } - TimeZone tz = TimeZone.getDefault(); - int currentOffsetFromUTC = tz.getRawOffset() + (tz.inDaylightTime(dtLocal) ? tz.getDSTSavings() : 0); - return new Date(dtLocal.getTime() - currentOffsetFromUTC); - } - - // Routines to return a diff between two dates - always return a positive number - - public static int daysBetween(Date dt1, Date dt2) { - long hrDiff = hoursBetween(dt1, dt2); - if (hrDiff == 0) { - return 0; - } - return (int) (hrDiff / 24); - } - - public static int hoursBetween(Date dt1, Date dt2) { - long minDiff = minutesBetween(dt1, dt2); - if (minDiff == 0) { - return 0; - } - return (int) (minDiff / 60); - } - - public static int minutesBetween(Date dt1, Date dt2) { - long msDiff = millisecondsBetween(dt1, dt2); - if (msDiff == 0) { - return 0; - } - return (int) (msDiff / 60000); - } - - public static int secondsBetween(Date dt1, Date dt2) { - long msDiff = millisecondsBetween(dt1, dt2); - if (msDiff == 0) { - return 0; - } - return (int) (msDiff / 1000); - } - - public static long millisecondsBetween(Date dt1, Date dt2) { - if (dt1 == null || dt2 == null) { - return 0; - } - return Math.abs(dt1.getTime() - dt2.getTime()); - } - - public static boolean isSameYear(Date dt1, Date dt2) { - if (dt1 == null || dt2 == null) { - return false; - } - return dt1.getYear() == dt2.getYear(); - } - - public static boolean isSameMonthAndYear(Date dt1, Date dt2) { - if (dt1 == null || dt2 == null) { - return false; - } - return dt1.getYear() == dt2.getYear() && dt1.getMonth() == dt2.getMonth(); - } - - // Routines involving Unix timestamps (GMT assumed) - - /** - * Given an ISO 8601-formatted date as a String, returns the corresponding UNIX timestamp. - */ - public static long timestampFromIso8601(final String strDate) { - return timestampFromIso8601Millis(strDate) / 1000; - } - - /** - * Given an ISO 8601-formatted date as a String, returns the corresponding timestamp in milliseconds. - * - * @return 0 if the parameter is null, empty or not a date. - */ - public static long timestampFromIso8601Millis(final String strDate) { - if (TextUtils.isEmpty(strDate)) { - return 0; - } - Date date = dateFromIso8601(strDate); - if (date == null) { - return 0; - } - return date.getTime(); - } - - /** - * Given a UNIX timestamp, returns the corresponding {@link Date}. - */ - public static Date dateFromTimestamp(long timestamp) { - return new java.util.Date(timestamp * 1000); - } - - /** - * Given a UNIX timestamp, returns an ISO 8601-formatted date as a String. - */ - public static String iso8601FromTimestamp(long timestamp) { - return iso8601FromDate(dateFromTimestamp(timestamp)); - } - - /** - * Given a UNIX timestamp, returns an ISO 8601-formatted date in UTC as a String. - */ - public static String iso8601UTCFromTimestamp(long timestamp) { - return iso8601UTCFromDate(dateFromTimestamp(timestamp)); - } - - /** - * Given a UNIX timestamp, returns a relative time span ("8h", "3d", etc.). - */ - public static String timeSpanFromTimestamp(long timestamp, Context context) { - Date dateGMT = dateFromTimestamp(timestamp); - return javaDateToTimeSpan(dateGMT, context); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java deleted file mode 100644 index dcd7d1d4ec0a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java +++ /dev/null @@ -1,179 +0,0 @@ -package org.wordpress.android.util; - -import android.app.KeyguardManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Environment; -import android.os.StatFs; - -import androidx.annotation.NonNull; - -import org.wordpress.android.util.AppLog.T; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -public class DeviceUtils { - private static final String APP_RUNTIME_ON_CHROME_FLAG = "org.chromium.arc.device_management"; - - private static DeviceUtils instance; - private boolean mIsKindleFire = false; - - public boolean isKindleFire() { - return mIsKindleFire; - } - - public static DeviceUtils getInstance() { - if (instance == null) { - instance = new DeviceUtils(); - } - return instance; - } - - private DeviceUtils() { - mIsKindleFire = android.os.Build.MODEL.equalsIgnoreCase("kindle fire") ? true : false; - } - - /** - * Checks camera availability recursively based on API level. - * - * TODO: change "android.hardware.camera.front" and "android.hardware.camera.any" to - * {@link PackageManager#FEATURE_CAMERA_FRONT} and {@link PackageManager#FEATURE_CAMERA_ANY}, - * respectively, once they become accessible or minSdk version is incremented. - * - * @param context The context. - * @return Whether camera is available. - */ - public boolean hasCamera(Context context) { - final PackageManager pm = context.getPackageManager(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) - || pm.hasSystemFeature("android.hardware.camera.front"); - } - - return pm.hasSystemFeature("android.hardware.camera.any"); - } - - public String getDeviceName(Context context) { - String manufacturer = Build.MANUFACTURER; - String undecodedModel = Build.MODEL; - String model = null; - - try { - Properties prop = new Properties(); - InputStream fileStream; - // Read the device name from a precomplied list: - // see http://making.meetup.com/post/29648976176/human-readble-android-device-names - fileStream = context.getAssets().open("android_models.properties"); - prop.load(fileStream); - fileStream.close(); - String decodedModel = prop.getProperty(undecodedModel.replaceAll(" ", "_")); - if (decodedModel != null && !decodedModel.trim().equals("")) { - model = decodedModel; - } - } catch (IOException e) { - AppLog.e(T.UTILS, "Can't read `android_models.properties` file from assets, or it's in the wrong form.", e); - AppLog.d(T.UTILS, - "If you need more info about the file, please check the reference implementation available here: " - + "https://github.com/wordpress-mobile/WordPress-Android/blob/dd989429bd701a66bcba911de08f2e8d336798ef" - + "/WordPress/src/main/assets/android_models.properties"); - } - - if (model == null) { // Device model not found in the list - if (undecodedModel.startsWith(manufacturer)) { - model = capitalize(undecodedModel); - } else { - model = capitalize(manufacturer) + " " + undecodedModel; - } - } - return model; - } - - public boolean isDeviceLocked(Context context) { - KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); - return myKM.inKeyguardRestrictedInputMode(); - } - - /** - * Checks if the current device runtime is ARC which effectively means it is a chromebook. - * - * @param context The context. - * @return Whether the device is a chromebook. - */ - public boolean isChromebook(Context context) { - return context.getPackageManager().hasSystemFeature(APP_RUNTIME_ON_CHROME_FLAG); - } - - /** - * Checks if the device has a hardware keyboard - note this will return true for emulators - */ - public boolean hasHardwareKeyboard(@NonNull Context context) { - return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS; - } - - private String capitalize(String s) { - if (s == null || s.length() == 0) { - return ""; - } - char first = s.charAt(0); - if (Character.isUpperCase(first)) { - return s; - } else { - return Character.toUpperCase(first) + s.substring(1); - } - } - - // Taken and modified from https://stackoverflow.com/a/8133437 - public static String getTotalAvailableMemorySize() { - File internalMemoryPath = Environment.getDataDirectory(); - long availableInternal = availableSpaceAtFilePath(internalMemoryPath); - long availableExternal = 0L; - if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { - File externalStoragePath = Environment.getExternalStorageDirectory(); - availableExternal = availableSpaceAtFilePath(externalStoragePath); - } - return formatSize(availableInternal + availableExternal); - } - - private static long availableSpaceAtFilePath(File path) { - StatFs stat = new StatFs(path.getPath()); - long bytesAvailable; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { - return stat.getBlockSizeLong() * stat.getAvailableBlocksLong(); - } else { - //noinspection deprecation - Deprecated calls properly handled - bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks(); - } - return bytesAvailable; - } - - private static String formatSize(long size) { - String suffix = null; - - if (size >= 1024) { - suffix = "KB"; - size /= 1024; - if (size >= 1024) { - suffix = "MB"; - size /= 1024; - } - } - - StringBuilder resultBuffer = new StringBuilder(Long.toString(size)); - - int commaOffset = resultBuffer.length() - 3; - while (commaOffset > 0) { - resultBuffer.insert(commaOffset, ','); - commaOffset -= 3; - } - - if (suffix != null) { - resultBuffer.append(suffix); - } - return resultBuffer.toString(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java deleted file mode 100644 index 1f4ab00994ca..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Point; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.Display; -import android.view.Window; -import android.view.WindowManager; - -public class DisplayUtils { - private DisplayUtils() { - throw new AssertionError(); - } - - public static boolean isLandscape(Context context) { - if (context == null) { - return false; - } - return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; - } - - public static Point getDisplayPixelSize(Context context) { - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - Point size = new Point(); - display.getSize(size); - return size; - } - - public static int getDisplayPixelWidth(Context context) { - Point size = getDisplayPixelSize(context); - return (size.x); - } - - public static int getDisplayPixelHeight(Context context) { - Point size = getDisplayPixelSize(context); - return (size.y); - } - - public static float spToPx(Context context, float sp) { - DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - final float scale = displayMetrics.scaledDensity; - return sp * scale; - } - - public static int dpToPx(Context context, int dp) { - float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, - context.getResources().getDisplayMetrics()); - return (int) px; - } - - public static int pxToDp(Context context, int px) { - DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - return (int) ((px / displayMetrics.density) + 0.5); - } - - public static boolean isXLargeTablet(Context context) { - if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) - == Configuration.SCREENLAYOUT_SIZE_XLARGE) { - return true; - } - return false; - } - - public static boolean isTablet(Context context) { - return (context.getResources().getConfiguration().screenLayout - & Configuration.SCREENLAYOUT_SIZE_MASK) - == Configuration.SCREENLAYOUT_SIZE_LARGE; - } - - /** - * returns the height of the ActionBar if one is enabled - supports both the native ActionBar - * and ActionBarSherlock - http://stackoverflow.com/a/15476793/1673548 - */ - public static int getActionBarHeight(Context context) { - if (context == null) { - return 0; - } - TypedValue tv = new TypedValue(); - if (context.getTheme() != null - && context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { - return TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); - } - - // if we get this far, it's because the device doesn't support an ActionBar, - // so return the standard ActionBar height (48dp) - return dpToPx(context, 48); - } - - /** - * detect when FEATURE_ACTION_BAR_OVERLAY has been set - */ - public static boolean hasActionBarOverlay(Window window) { - return window.hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java deleted file mode 100644 index ec4e0b69313a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Activity; -import android.content.Context; -import android.text.TextUtils; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.TextView; - -/** - * EditText utils - */ -public class EditTextUtils { - private EditTextUtils() { - throw new AssertionError(); - } - - /** - * returns non-null text string from passed TextView - */ - public static String getText(TextView textView) { - return (textView != null) ? textView.getText().toString() : ""; - } - - /** - * moves caret to end of text - */ - public static void moveToEnd(EditText edit) { - if (edit.getText() == null) { - return; - } - edit.setSelection(edit.getText().toString().length()); - } - - /** - * returns true if nothing has been entered into passed editor - */ - public static boolean isEmpty(EditText edit) { - return TextUtils.isEmpty(getText(edit)); - } - - /** - * hide the soft keyboard for the passed EditText - * - * @deprecated Use {@link ActivityUtils#hideKeyboard(Activity)} or {@link ActivityUtils#hideKeyboardForced(View)} - * instead. - */ - // TODO: Replace instances with ActivityUtils#showKeyboard(Activity) or ActivityUtils#showKeyboardForced(View) to - // consolidate similar methods and favor library version. - @Deprecated - public static void hideSoftInput(EditText edit) { - if (edit == null) { - return; - } - - InputMethodManager imm = getInputMethodManager(edit); - if (imm != null) { - imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); - } - } - - /** - * show the soft keyboard for the passed EditText - * - * @deprecated Use {@link ActivityUtils#showKeyboard(View)} instead. - */ - // TODO: Replace instances with ActivityUtils#showKeyboard(View) to consolidate similar methods and favor library - // version. - @Deprecated - public static void showSoftInput(EditText edit) { - if (edit == null) { - return; - } - - edit.requestFocus(); - - InputMethodManager imm = getInputMethodManager(edit); - if (imm != null) { - imm.showSoftInput(edit, InputMethodManager.SHOW_IMPLICIT); - } - } - - private static InputMethodManager getInputMethodManager(EditText edit) { - Context context = edit.getContext(); - return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java deleted file mode 100644 index 08d0d3417c2d..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.wordpress.android.util; - -import android.text.Html; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.style.ForegroundColorSpan; -import android.text.style.ImageSpan; -import android.util.SparseArray; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES; - -public class EmoticonsUtils { - public static final int EMOTICON_COLOR = 0xFF21759B; - private static final boolean HAS_EMOJI = SDK_INT >= VERSION_CODES.JELLY_BEAN; - private static final Map WP_SMILIES; - public static final SparseArray WP_SMILIES_CODE_POINT_TO_TEXT; - - static { - Map smilies = new HashMap(); - smilies.put("icon_mrgreen.gif", HAS_EMOJI ? "\uD83D\uDE00" : ":mrgreen:"); - smilies.put("icon_neutral.gif", HAS_EMOJI ? "\uD83D\uDE14" : ":|"); - smilies.put("icon_twisted.gif", HAS_EMOJI ? "\uD83D\uDE16" : ":twisted:"); - smilies.put("icon_arrow.gif", HAS_EMOJI ? "\u27A1" : ":arrow:"); - smilies.put("icon_eek.gif", HAS_EMOJI ? "\uD83D\uDE32" : "8-O"); - smilies.put("icon_smile.gif", HAS_EMOJI ? "\uD83D\uDE0A" : ":)"); - smilies.put("icon_confused.gif", HAS_EMOJI ? "\uD83D\uDE15" : ":?"); - smilies.put("icon_cool.gif", HAS_EMOJI ? "\uD83D\uDE0A" : "8)"); - smilies.put("icon_evil.gif", HAS_EMOJI ? "\uD83D\uDE21" : ":evil:"); - smilies.put("icon_biggrin.gif", HAS_EMOJI ? "\uD83D\uDE03" : ":D"); - smilies.put("icon_idea.gif", HAS_EMOJI ? "\uD83D\uDCA1" : ":idea:"); - smilies.put("icon_redface.gif", HAS_EMOJI ? "\uD83D\uDE33" : ":oops:"); - smilies.put("icon_razz.gif", HAS_EMOJI ? "\uD83D\uDE1D" : ":P"); - smilies.put("icon_rolleyes.gif", HAS_EMOJI ? "\uD83D\uDE0F" : ":roll:"); - smilies.put("icon_wink.gif", HAS_EMOJI ? "\uD83D\uDE09" : ";)"); - smilies.put("icon_cry.gif", HAS_EMOJI ? "\uD83D\uDE22" : ":'("); - smilies.put("icon_surprised.gif", HAS_EMOJI ? "\uD83D\uDE32" : ":o"); - smilies.put("icon_lol.gif", HAS_EMOJI ? "\uD83D\uDE03" : ":lol:"); - smilies.put("icon_mad.gif", HAS_EMOJI ? "\uD83D\uDE21" : ":x"); - smilies.put("icon_sad.gif", HAS_EMOJI ? "\uD83D\uDE1E" : ":("); - smilies.put("icon_exclaim.gif", HAS_EMOJI ? "\u2757" : ":!:"); - smilies.put("icon_question.gif", HAS_EMOJI ? "\u2753" : ":?:"); - - WP_SMILIES = Collections.unmodifiableMap(smilies); - - WP_SMILIES_CODE_POINT_TO_TEXT = new SparseArray(20); - WP_SMILIES_CODE_POINT_TO_TEXT.put(10145, ":arrow:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128161, ":idea:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128512, ":mrgreen:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128515, ":D"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128522, ":)"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128521, ";)"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128532, ":|"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128533, ":?"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128534, ":twisted:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128542, ":("); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128545, ":evil:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128546, ":'("); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128562, ":o"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128563, ":oops:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128527, ":roll:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(10071, ":!:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(10067, ":?:"); - } - - public static String lookupImageSmiley(String url) { - return lookupImageSmiley(url, ""); - } - - public static String lookupImageSmiley(String url, String ifNone) { - if (url == null) { - return ifNone; - } - String file = url.substring(url.lastIndexOf("/") + 1); - if (WP_SMILIES.containsKey(file)) { - return WP_SMILIES.get(file); - } - return ifNone; - } - - public static Spanned replaceEmoticonsWithEmoji(SpannableStringBuilder html) { - ImageSpan[] imgs = html.getSpans(0, html.length(), ImageSpan.class); - for (ImageSpan img : imgs) { - String emoticon = EmoticonsUtils.lookupImageSmiley(img.getSource()); - if (!emoticon.equals("")) { - int start = html.getSpanStart(img); - html.replace(start, html.getSpanEnd(img), emoticon); - html.setSpan(new ForegroundColorSpan(EMOTICON_COLOR), start, - start + emoticon.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - html.removeSpan(img); - } - } - return html; - } - - public static String replaceEmoticonsWithEmoji(final String text) { - if (text != null && text.contains("icon_")) { - final SpannableStringBuilder html = - (SpannableStringBuilder) replaceEmoticonsWithEmoji((SpannableStringBuilder) Html.fromHtml(text)); - // Html.toHtml() is used here rather than toString() since the latter strips html - return Html.toHtml(html); - } else { - return text; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java deleted file mode 100644 index cadee0b6906f..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -import java.io.File; - -public class FileUtils { - /** - * Returns the length of the file denoted by this abstract pathname. - * The return value is unspecified if this pathname denotes a directory. - * - * @return The length, in bytes, of the file denoted by this abstract - * pathname, or -1L if the file does not exist, or an - * exception is thrown accessing the file. - * Some operating systems may return 0L for pathnames - * denoting system-dependent entities such as devices or pipes. - */ - public static long length(String path) { - // File not found - File file = new File(path); - try { - if (!file.exists()) { - AppLog.w(AppLog.T.MEDIA, "Can't access the file. It doesn't exists anymore?"); - return -1L; - } - - return file.length(); - } catch (SecurityException e) { - AppLog.e(AppLog.T.MEDIA, "Can't access the file.", e); - return -1L; - } - } - - /** - * Given the full file path, or the filename with extension (i.e. my-picture.jpg), returns the filename part only - * (my-picture). - * - * @param filePath The path to the file or the full filename - * @return filename part only or null - */ - public static String getFileNameFromPath(String filePath) { - if (TextUtils.isEmpty(filePath)) { - return null; - } - if (filePath.contains("/")) { - if (filePath.lastIndexOf("/") + 1 >= filePath.length()) { - filePath = filePath.substring(0, filePath.length() - 1); - } - filePath = filePath.substring(filePath.lastIndexOf("/") + 1); - } - - String filename; - int dotPos = filePath.indexOf('.'); - if (dotPos > 0) { - filename = filePath.substring(0, dotPos); - } else { - filename = filePath; - } - return filename; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java deleted file mode 100644 index c2850e58d11c..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.wordpress.android.util; - -import java.text.DecimalFormat; -import java.text.NumberFormat; - -public class FormatUtils { - /* - * NumberFormat isn't synchronized, so a separate instance must be created for each thread - * http://developer.android.com/reference/java/text/NumberFormat.html - */ - private static final ThreadLocal INTEGER_INSTANCE = new ThreadLocal() { - @Override - protected NumberFormat initialValue() { - return NumberFormat.getIntegerInstance(); - } - }; - - private static final ThreadLocal DECIMAL_INSTANCE = new ThreadLocal() { - @Override - protected DecimalFormat initialValue() { - return (DecimalFormat) DecimalFormat.getInstance(); - } - }; - - /* - * returns the passed integer formatted with thousands-separators based on the current locale - */ - public static final String formatInt(int value) { - return INTEGER_INSTANCE.get().format(value).toString(); - } - - public static final String formatDecimal(int value) { - return DECIMAL_INSTANCE.get().format(value).toString(); - } - - /* - * returns the passed long formatted as an human readable filesize. Ex: 10 GB - * unitStrings is expected to be an array of all possible sizes from byte to TeraByte, in the current locale - */ - public static final String formatFileSize(long size, final String[] unitStrings) { - final double log1024 = Math.log10(1024); - if (size <= 0) { - return "0"; - } - int digitGroups = (int) (Math.log10(size) / log1024); - - NumberFormat f = NumberFormat.getInstance(); - if (f instanceof DecimalFormat) { - ((DecimalFormat) f).applyPattern("#,##0.#"); - } - return String.format(unitStrings[digitGroups], f.format(size / Math.pow(1024, digitGroups))); - } - - /* - * returns the passed double percentage (0 to 1) formatted as an human readable percentage. Ex: 0.25 returns 25% - */ - public static final String formatPercentage(double value) { - return formatPercentageLimit100(value, false); - } - - /* - * returns the passed double percentage (0 to 1) formatted as an human readable percentage. Ex: 0.251 returns 25.1% - * if limit100 is true, it limits the percentage to 100% - */ - public static final String formatPercentageLimit100(double value, boolean limit100) { - double limit = 1.0001; - - NumberFormat percentFormat = NumberFormat.getPercentInstance(); - percentFormat.setMaximumFractionDigits(1); - - if (limit100 && value > limit) { - value = limit; - } - - String percentage = percentFormat.format(value); - - return percentage; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java deleted file mode 100644 index 4b2fdd8875c5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.location.Address; -import android.location.Geocoder; - -import java.io.IOException; -import java.util.List; - -public final class GeocoderUtils { - private GeocoderUtils() { - throw new AssertionError(); - } - - public static Geocoder getGeocoder(Context context) { - // first make sure a Geocoder service exists on this device (requires API 9) - if (!Geocoder.isPresent()) { - return null; - } - - Geocoder gcd; - - try { - gcd = new Geocoder(context, LanguageUtils.getCurrentDeviceLanguage(context)); - } catch (NullPointerException cannotIstantiateEx) { - AppLog.e(AppLog.T.UTILS, "Cannot instantiate Geocoder", cannotIstantiateEx); - return null; - } - - return gcd; - } - - public static Address getAddressFromCoords(Context context, double latitude, double longitude) { - Address address = null; - List
addresses = null; - - Geocoder gcd = getGeocoder(context); - - if (gcd == null) { - return null; - } - - try { - addresses = gcd.getFromLocation(latitude, longitude, 1); - } catch (IOException e) { - // may get "Unable to parse response from server" IOException here if Geocoder - // service is hit too frequently - AppLog.e(AppLog.T.UTILS, - "Unable to parse response from server. Is Geocoder service hitting the server too frequently?", - e - ); - } - - // addresses may be null or empty if network isn't connected - if (addresses != null && addresses.size() > 0) { - address = addresses.get(0); - } - - return address; - } - - public static Address getAddressFromLocationName(Context context, String locationName) { - int maxResults = 1; - Address address = null; - List
addresses = null; - - Geocoder gcd = getGeocoder(context); - - if (gcd == null) { - return null; - } - - try { - addresses = gcd.getFromLocationName(locationName, maxResults); - } catch (IOException e) { - AppLog.e(AppLog.T.UTILS, "Failed to get coordinates from location", e); - } - - // addresses may be null or empty if network isn't connected - if (addresses != null && addresses.size() > 0) { - address = addresses.get(0); - } - - return address; - } - - public static String getLocationNameFromAddress(Address address) { - String locality = "", adminArea = "", country = ""; - if (address.getLocality() != null) { - locality = address.getLocality(); - } - - if (address.getAdminArea() != null) { - adminArea = address.getAdminArea(); - } - - if (address.getCountryName() != null) { - country = address.getCountryName(); - } - - return ((locality.equals("")) ? locality : locality + ", ") - + ((adminArea.equals("")) ? adminArea : adminArea + " ") + country; - } - - public static double[] getCoordsFromAddress(Address address) { - double[] coordinates = new double[2]; - - if (address.hasLatitude() && address.hasLongitude()) { - coordinates[0] = address.getLatitude(); - coordinates[1] = address.getLongitude(); - } - - return coordinates; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java deleted file mode 100644 index f650dea0dcf5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -/** - * see https://en.gravatar.com/site/implement/images/ - */ -public class GravatarUtils { - // by default tell gravatar to respond to non-existent images with a 404 - this means - // it's up to the caller to catch the 404 and provide a suitable default image - private static final DefaultImage DEFAULT_GRAVATAR = DefaultImage.MYSTERY_MAN; - - public enum DefaultImage { - MYSTERY_MAN, - STATUS_404, - IDENTICON, - MONSTER, - WAVATAR, - RETRO, - BLANK; - - @Override - public String toString() { - switch (this) { - case MYSTERY_MAN: - return "mm"; - case STATUS_404: - return "404"; - case IDENTICON: - return "identicon"; - case MONSTER: - return "monsterid"; - case WAVATAR: - return "wavatar"; - case RETRO: - return "retro"; - default: - return "blank"; - } - } - } - - /* - * gravatars often contain the ?s= parameter which determines their size - detect this and - * replace it with a new ?s= parameter which requests the avatar at the exact size needed - */ - public static String fixGravatarUrl(final String imageUrl, int avatarSz) { - return fixGravatarUrl(imageUrl, avatarSz, DEFAULT_GRAVATAR); - } - - public static String fixGravatarUrl(final String imageUrl, int avatarSz, DefaultImage defaultImage) { - if (TextUtils.isEmpty(imageUrl)) { - return ""; - } - - // if this isn't a gravatar image, return as resized photon image url - if (!imageUrl.contains("gravatar.com")) { - return PhotonUtils.getPhotonImageUrl(imageUrl, avatarSz, avatarSz); - } - - // remove all other params, then add query string for size and default image - return UrlUtils.removeQuery(imageUrl) + "?s=" + avatarSz + "&d=" + defaultImage.toString(); - } - - public static String gravatarFromEmail(final String email, int size) { - return gravatarFromEmail(email, size, DEFAULT_GRAVATAR); - } - - public static String gravatarFromEmail(final String email, int size, DefaultImage defaultImage) { - return "http://gravatar.com/avatar/" - + StringUtils.getMd5Hash(StringUtils.notNullStr(email)) - + "?d=" + defaultImage.toString() - + "&size=" + Integer.toString(size); - } - - public static String blavatarFromUrl(final String url, int size) { - return blavatarFromUrl(url, size, DEFAULT_GRAVATAR); - } - - public static String blavatarFromUrl(final String url, int size, DefaultImage defaultImage) { - return "http://gravatar.com/blavatar/" - + StringUtils.getMd5Hash(UrlUtils.getHost(url)) - + "?d=" + defaultImage.toString() - + "&size=" + Integer.toString(size); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java deleted file mode 100644 index e35972d4112e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.res.Resources; -import android.text.Html; -import android.text.Html.ImageGetter; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextUtils; -import android.text.style.ForegroundColorSpan; -import android.text.style.QuoteSpan; - -import org.apache.commons.text.StringEscapeUtils; -import org.wordpress.android.util.helpers.WPHtmlTagHandler; -import org.wordpress.android.util.helpers.WPQuoteSpan; - -public class HtmlUtils { - /** - * Removes html from the passed string - relies on Html.fromHtml which handles invalid HTML, - * but it's very slow, so avoid using this where performance is important - * @param text String containing html - * @return String without HTML - */ - public static String stripHtml(final String text) { - if (TextUtils.isEmpty(text)) { - return ""; - } - return Html.fromHtml(text).toString().trim(); - } - - /** - * This is much faster than stripHtml() but should only be used when we know the html is valid - * since the regex will be unpredictable with invalid html - * @param str String containing only valid html - * @return String without HTML - */ - public static String fastStripHtml(String str) { - if (TextUtils.isEmpty(str)) { - return str; - } - - // insert a line break before P tags unless the only one is at the start - if (str.lastIndexOf(" 0) { - str = str.replaceAll("", "\n

"); - } - - // convert BR tags to line breaks - if (str.contains("", "\n"); - } - - // use regex to strip tags, then convert entities in the result - return trimStart(StringEscapeUtils.unescapeHtml4(str.replaceAll("<(.|\n)*?>", ""))); - } - - /* - * Same as apache.commons.lang.StringUtils.stripStart() but also removes non-breaking - * space (160) chars - */ - private static String trimStart(final String str) { - int strLen; - if (str == null || (strLen = str.length()) == 0) { - return ""; - } - int start = 0; - while (start != strLen && (Character.isWhitespace(str.charAt(start)) || str.charAt(start) == 160)) { - start++; - } - return str.substring(start); - } - - /** - * Converts an R.color.xxx resource to an HTML hex color - * @param context Android Context - * @param resId Android R.color.xxx - * @return A String HTML hex color code - */ - public static String colorResToHtmlColor(Context context, int resId) { - try { - return String.format("#%06X", 0xFFFFFF & context.getResources().getColor(resId)); - } catch (Resources.NotFoundException e) { - return "#000000"; - } - } - - /** - * Remove {@code } blocks from the passed string - added to project after noticing - * comments on posts that use the "Sociable" plugin ( http://wordpress.org/plugins/sociable/ ) - * may have a script block which contains {@code } followed by a CDATA section followed by {@code ,} - * all of which will show up if we don't strip it here. - * @see Wordpress Sociable Plugin - * @return String without {@code }, {@code } blocks followed by a CDATA section - * followed by {@code ,} - * @param text String containing script tags - */ - public static String stripScript(final String text) { - if (text == null) { - return null; - } - - StringBuilder sb = new StringBuilder(text); - int start = sb.indexOf(" -1) { - int end = sb.indexOf("", start); - if (end == -1) { - return sb.toString(); - } - sb.delete(start, end + 9); - start = sb.indexOf("}, {@code

    }, {@code
    } - * tags and replacing EmoticonsUtils with Emojis - * @param source - * @param imageGetter - */ - public static SpannableStringBuilder fromHtml(String source, ImageGetter imageGetter) { - source = replaceListTagsWithCustomTags(source); - SpannableStringBuilder html; - try { - html = (SpannableStringBuilder) Html.fromHtml(source, imageGetter, new WPHtmlTagHandler()); - } catch (RuntimeException runtimeException) { - // In case our tag handler fails - html = (SpannableStringBuilder) Html.fromHtml(source, imageGetter, null); - } - EmoticonsUtils.replaceEmoticonsWithEmoji(html); - QuoteSpan[] spans = html.getSpans(0, html.length(), QuoteSpan.class); - for (QuoteSpan span : spans) { - html.setSpan(new WPQuoteSpan(), html.getSpanStart(span), html.getSpanEnd(span), html.getSpanFlags(span)); - html.setSpan(new ForegroundColorSpan(0xFF666666), html.getSpanStart(span), html.getSpanEnd(span), - html.getSpanFlags(span)); - html.removeSpan(span); - } - return html; - } - - private static String replaceListTagsWithCustomTags(String source) { - return source.replace("", "") - .replace("", "") - .replace("", ""); - } - - public static Spanned fromHtml(String source) { - return fromHtml(source, null); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java deleted file mode 100644 index d42cb0ba8aec..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java +++ /dev/null @@ -1,898 +0,0 @@ -package org.wordpress.android.util; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.media.ExifInterface; -import android.media.MediaMetadataRetriever; -import android.media.ThumbnailUtils; -import android.net.Uri; -import android.os.AsyncTask; -import android.provider.MediaStore; -import android.text.TextUtils; -import android.util.Log; -import android.webkit.MimeTypeMap; -import android.widget.ImageView; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -public class ImageUtils { - public static int[] getImageSize(Uri uri, Context context) { - String path = null; - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - - if (uri.toString().contains("content:")) { - String[] projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA}; - Cursor cur = null; - try { - cur = context.getContentResolver().query(uri, projection, null, null, null); - if (cur != null && cur.moveToFirst()) { - int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA); - path = cur.getString(dataColumn); - } - } catch (IllegalStateException stateException) { - Log.d(ImageUtils.class.getName(), "IllegalStateException querying content:" + uri); - } finally { - SqlUtils.closeCursor(cur); - } - } - - if (TextUtils.isEmpty(path)) { - // The file isn't ContentResolver, or it can't be access by ContentResolver. Try to access the file - // directly. - path = uri.toString().replace("content://media", ""); - path = path.replace("file://", ""); - } - - BitmapFactory.decodeFile(path, options); - int imageHeight = options.outHeight; - int imageWidth = options.outWidth; - return new int[]{imageWidth, imageHeight}; - } - - // Read the orientation from ContentResolver. If it fails, read from EXIF. - public static int getImageOrientation(Context ctx, String filePath) { - if (TextUtils.isEmpty(filePath) || ctx == null) { - AppLog.w(AppLog.T.UTILS, "Can't read orientation. Passed context or file is null or empty."); - return 0; - } - Uri curStream; - int orientation = 0; - - // Remove file protocol - filePath = filePath.replace("file://", ""); - - if (!filePath.contains("content://")) { - curStream = Uri.parse("content://media" + filePath); - } else { - curStream = Uri.parse(filePath); - } - - try { - Cursor cur = ctx.getContentResolver() - .query(curStream, new String[]{MediaStore.Images.Media.ORIENTATION}, null, null, null); - if (cur != null) { - if (cur.moveToFirst()) { - orientation = cur.getInt(cur.getColumnIndex(MediaStore.Images.Media.ORIENTATION)); - } - cur.close(); - } - } catch (Exception errReadingContentResolver) { - AppLog.e(AppLog.T.UTILS, "Error reading orientation of the file: " + filePath, errReadingContentResolver); - } - - if (orientation == 0) { - orientation = getExifOrientation(filePath); - } - - return orientation; - } - - - private static int getExifOrientation(String path) { - if (TextUtils.isEmpty(path)) { - AppLog.w(AppLog.T.UTILS, "Can't read EXIF orientation. Passed path is empty."); - return 0; - } - ExifInterface exif; - try { - exif = new ExifInterface(path); - } catch (IOException e) { - AppLog.e(AppLog.T.UTILS, "Can't read EXIF orientation.", e); - return 0; - } - - int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0); - - switch (exifOrientation) { - case ExifInterface.ORIENTATION_NORMAL: - return 0; - case ExifInterface.ORIENTATION_ROTATE_90: - return 90; - case ExifInterface.ORIENTATION_ROTATE_180: - return 180; - case ExifInterface.ORIENTATION_ROTATE_270: - return 270; - default: - return 0; - } - } - - public static Bitmap downloadBitmap(String url) { - final DefaultHttpClient client = new DefaultHttpClient(); - - final HttpGet getRequest = new HttpGet(url); - - try { - HttpResponse response = client.execute(getRequest); - final int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - AppLog.w(AppLog.T.UTILS, "ImageDownloader Error " + statusCode - + " while retrieving bitmap from " + url); - return null; - } - - final HttpEntity entity = response.getEntity(); - if (entity != null) { - InputStream inputStream = null; - try { - inputStream = entity.getContent(); - return BitmapFactory.decodeStream(inputStream); - } finally { - if (inputStream != null) { - inputStream.close(); - } - entity.consumeContent(); - } - } - } catch (Exception e) { - // Could provide a more explicit error message for IOException or - // IllegalStateException - getRequest.abort(); - AppLog.w(AppLog.T.UTILS, "ImageDownloader Error while retrieving bitmap from " + url); - } - return null; - } - - /** From http://developer.android.com/training/displaying-bitmaps/load-bitmap.html **/ - public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { - // Raw height and width of image - final int height = options.outHeight; - final int width = options.outWidth; - int inSampleSize = 1; - - if (height > reqHeight || width > reqWidth) { - // Calculate ratios of height and width to requested height and width - final int heightRatio = Math.round((float) height / (float) reqHeight); - final int widthRatio = Math.round((float) width / (float) reqWidth); - - // Choose the smallest ratio as inSampleSize value, this will guarantee - // a final image with both dimensions larger than or equal to the - // requested height and width. - inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; - } - - return inSampleSize; - } - - - public interface BitmapWorkerCallback { - void onBitmapReady(String filePath, ImageView imageView, Bitmap bitmap); - } - - public static class BitmapWorkerTask extends AsyncTask { - private final WeakReference mImageViewReference; - private final BitmapWorkerCallback mCallback; - private int mTargetWidth; - private int mTargetHeight; - private String mPath; - - public BitmapWorkerTask(ImageView imageView, int width, int height, BitmapWorkerCallback callback) { - // Use a WeakReference to ensure the ImageView can be garbage collected - mImageViewReference = new WeakReference(imageView); - this.mCallback = callback; - mTargetWidth = width; - mTargetHeight = height; - } - - // Decode image in background. - @Override - protected Bitmap doInBackground(String... params) { - mPath = params[0]; - - BitmapFactory.Options bfo = new BitmapFactory.Options(); - bfo.inJustDecodeBounds = true; - BitmapFactory.decodeFile(mPath, bfo); - - bfo.inSampleSize = calculateInSampleSize(bfo, mTargetWidth, mTargetHeight); - bfo.inJustDecodeBounds = false; - - // get proper rotation - int bitmapWidth = 0; - int bitmapHeight = 0; - try { - File f = new File(mPath); - ExifInterface exif = new ExifInterface(f.getPath()); - int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); - int angle = 0; - if (orientation == ExifInterface.ORIENTATION_NORMAL) { // no need to rotate - return BitmapFactory.decodeFile(mPath, bfo); - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { - angle = 90; - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { - angle = 180; - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { - angle = 270; - } - - Matrix mat = new Matrix(); - mat.postRotate(angle); - - try { - Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, bfo); - if (bmp == null) { - AppLog.e(AppLog.T.UTILS, "can't decode bitmap: " + f.getPath()); - return null; - } - bitmapWidth = bmp.getWidth(); - bitmapHeight = bmp.getHeight(); - return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true); - } catch (OutOfMemoryError oom) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error in setting image: " + oom); - } - } catch (IOException e) { - AppLog.e(AppLog.T.UTILS, "Error in setting image", e); - } - - return null; - } - - // Once complete, see if ImageView is still around and set bitmap. - @Override - protected void onPostExecute(Bitmap bitmap) { - if (mImageViewReference == null || bitmap == null) { - return; - } - - final ImageView imageView = mImageViewReference.get(); - - if (mCallback != null) { - mCallback.onBitmapReady(mPath, imageView, bitmap); - } - } - } - - public static String getTitleForWPImageSpan(Context ctx, String filePath) { - if (filePath == null) { - return null; - } - - Uri curStream; - String title; - - if (!filePath.contains("content://")) { - curStream = Uri.parse("content://media" + filePath); - } else { - curStream = Uri.parse(filePath); - } - - if (filePath.contains("video")) { - return "Video"; - } else { - String[] projection = new String[]{MediaStore.Images.Thumbnails.DATA}; - - Cursor cur; - try { - cur = ctx.getContentResolver().query(curStream, projection, null, null, null); - } catch (Exception e1) { - AppLog.e(AppLog.T.UTILS, e1); - return null; - } - File jpeg; - if (cur != null) { - String thumbData = ""; - if (cur.moveToFirst()) { - int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA); - thumbData = cur.getString(dataColumn); - } - cur.close(); - if (thumbData == null) { - return null; - } - jpeg = new File(thumbData); - } else { - String path = filePath.toString().replace("file://", ""); - jpeg = new File(path); - } - title = jpeg.getName(); - return title; - } - } - - /** - * Resizes an image to be placed in the Post Content Editor - * - * @return resized bitmap - */ - public static Bitmap getWPImageSpanThumbnailFromFilePath(Context context, String filePath, int targetWidth) { - if (filePath == null || context == null) { - return null; - } - - Uri curUri = Uri.parse(filePath); - - if (filePath.contains("video")) { - // Load the video thumbnail from the MediaStore - int videoId = 0; - try { - videoId = Integer.parseInt(curUri.getLastPathSegment()); - } catch (NumberFormatException e) { - } - ContentResolver crThumb = context.getContentResolver(); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = 1; - Bitmap videoThumbnail = - MediaStore.Video.Thumbnails.getThumbnail(crThumb, videoId, MediaStore.Video.Thumbnails.MINI_KIND, - options); - if (videoThumbnail != null) { - return getScaledBitmapAtLongestSide(videoThumbnail, targetWidth); - } else { - return null; - } - } else { - // Create resized bitmap - int rotation = getImageOrientation(context, filePath); - byte[] bytes = createThumbnailFromUri(context, curUri, targetWidth, null, rotation); - - if (bytes != null && bytes.length > 0) { - try { - Bitmap resizedBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - if (resizedBitmap != null) { - return getScaledBitmapAtLongestSide(resizedBitmap, targetWidth); - } - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error in setting image: " + e); - return null; - } - } - } - - return null; - } - - /* - Resize a bitmap to the targetSize on its longest side. - */ - public static Bitmap getScaledBitmapAtLongestSide(Bitmap bitmap, int targetSize) { - if (bitmap == null || bitmap.getWidth() <= targetSize && bitmap.getHeight() <= targetSize) { - // Do not resize. - return bitmap; - } - - int targetWidth, targetHeight; - if (bitmap.getHeight() > bitmap.getWidth()) { - // Resize portrait bitmap - targetHeight = targetSize; - float percentage = (float) targetSize / bitmap.getHeight(); - targetWidth = (int) (bitmap.getWidth() * percentage); - } else { - // Resize landscape or square image - targetWidth = targetSize; - float percentage = (float) targetSize / bitmap.getWidth(); - targetHeight = (int) (bitmap.getHeight() * percentage); - } - - return Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true); - } - - private static boolean resizeImageAndWriteToStream(Context context, - Uri imageUri, - String fileExtension, - int maxSize, - int orientation, - int quality, - OutputStream outStream) throws OutOfMemoryError, IOException { - String realFilePath = MediaUtils.getRealPathFromURI(context, imageUri); - - // get just the image bounds - BitmapFactory.Options optBounds = new BitmapFactory.Options(); - optBounds.inJustDecodeBounds = true; - - try { - BitmapFactory.decodeFile(realFilePath, optBounds); - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error while decoding the original image: " + realFilePath, e); - throw e; - } - - int scale = getScaleForResizing(maxSize, optBounds); - - BitmapFactory.Options optActual = new BitmapFactory.Options(); - optActual.inSampleSize = scale; - - // Get the roughly resized bitmap - final Bitmap bmpResized; - try { - bmpResized = BitmapFactory.decodeFile(realFilePath, optActual); - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error while decoding the original image: " + realFilePath, e); - throw e; - } - - if (bmpResized == null) { - AppLog.e(AppLog.T.UTILS, "Can't decode the resized picture."); - throw new IOException("Can't decode the resized picture."); - } - - // Resize the bitmap to exact size: calculate exact scale in order to resize accurately - float scaleBy = getScaleImageBy(maxSize, bmpResized); - - Matrix matrix = new Matrix(); - matrix.postScale(scaleBy, scaleBy); - - // apply orientation - if (orientation != 0) { - matrix.setRotate(orientation); - } - - Bitmap.CompressFormat fmt; - if (fileExtension != null - && (fileExtension.equals("png") || fileExtension.equals(".png"))) { - fmt = Bitmap.CompressFormat.PNG; - } else { - fmt = Bitmap.CompressFormat.JPEG; - } - - final Bitmap bmpRotated; - try { - bmpRotated = - Bitmap.createBitmap(bmpResized, 0, 0, bmpResized.getWidth(), bmpResized.getHeight(), matrix, true); - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError while creating the resized bitmap", e); - throw e; - } catch (NullPointerException e) { - // See: https://github.com/wordpress-mobile/WordPress-Android/issues/1844 - AppLog.e(AppLog.T.UTILS, "Bitmap.createBitmap has thrown a NPE internally. This should never happen!", e); - throw e; - } - - if (bmpRotated == null) { - // Fix an issue where bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can - // return null. - AppLog.e(AppLog.T.UTILS, - "bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can return null."); - // See: https://github.com/wordpress-mobile/WordPress-Android/issues/1848 - throw new IOException( - "bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can return null."); - } - - return bmpRotated.compress(fmt, quality, outStream); - } - - /** - * Given the path to an image, compress and resize it. - * @param context the passed context - * @param path the path to the original image - * @param maxImageSize the maximum allowed width - * @param quality the encoder quality - * @return the path to the optimized image - */ - public static String optimizeImage(Context context, String path, int maxImageSize, int quality) { - if (context == null || TextUtils.isEmpty(path)) { - return path; - } - - File file = new File(path); - if (!file.exists()) { - return path; - } - - String mimeType = MediaUtils.getMediaFileMimeType(file); - if (mimeType.equals("image/gif")) { - // Don't rescale gifs to maintain their quality - return path; - } - - Uri srcImageUri = Uri.parse(path); - if (srcImageUri == null) { - return path; - } - - String fileName = MediaUtils.getMediaFileName(file, mimeType); - String fileExtension = MimeTypeMap.getFileExtensionFromUrl(fileName).toLowerCase(Locale.ROOT); - - int[] imageDimensions = getImageSize(srcImageUri, context); - int selectedMaxSize = Math.max(imageDimensions[0], imageDimensions[1]); - if (selectedMaxSize == 0) { - // Can't read the src dimensions. - return path; - } - - // do not optimize if original-size and 100% quality are set. - if (maxImageSize == Integer.MAX_VALUE && quality == 100) { - return path; - } - - if (selectedMaxSize > maxImageSize) { - selectedMaxSize = maxImageSize; - } - - int orientation = getImageOrientation(context, path); - - File resizedImageFile; - FileOutputStream out; - - try { - // try to re-use the same name as prefix of the temp file - String prefix = FileUtils.getFileNameFromPath(fileName); - - if (TextUtils.isEmpty(prefix) || prefix.length() < 3) { - // prefix must be at least 3 characters - prefix = "wp-image"; - } - - resizedImageFile = File.createTempFile(prefix, "." + fileExtension); - out = new FileOutputStream(resizedImageFile); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create the temp file on storage. Use the original picture instead."); - return path; - } catch (SecurityException e) { - AppLog.e(AppLog.T.MEDIA, - "Can't write the tmp file due to security restrictions. Use the original picture instead."); - return path; - } - - try { - boolean res = resizeImageAndWriteToStream(context, srcImageUri, fileExtension, selectedMaxSize, orientation, - quality, out); - if (!res) { - AppLog.w(AppLog.T.MEDIA, "Failed to compress the optimized image. Use the original picture instead."); - return path; - } - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create optimized image. Use the original picture instead."); - return path; - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.MEDIA, "Can't optimize the picture due to low memory. Use the original picture instead."); - return path; - } finally { - // close the stream - try { - out.flush(); - out.close(); - } catch (IOException e) { - // nope - } - } - - String tempFilePath = resizedImageFile.getPath(); - if (!TextUtils.isEmpty(tempFilePath)) { - return tempFilePath; - } else { - AppLog.e(AppLog.T.MEDIA, "Failed to create optimized image. Use the full picture instead."); - } - - return path; - } - - /** - * Generate a thumbnail from a video url. - * Note that this method could take time if network url. - * - * @param videoPath The path to the video on internet - * @param maxWidth the maximumWidth for the thumbnail - * @return the path to the picture on disk - */ - public static Bitmap getVideoFrameFromVideo(String videoPath, int maxWidth) { - return getVideoFrameFromVideo(videoPath, maxWidth, new HashMap()); - } - - /** - * Generate a thumbnail from a video url. - * Note that this method could take time if network url. - * - * @param videoPath The path to the video on internet - * @param maxWidth the maximumWidth for the thumbnail - * @param headers optional: HTTP headers map to add to the request if the video is remote - * @return the path to the picture on disk - */ - public static Bitmap getVideoFrameFromVideo(String videoPath, int maxWidth, Map headers) { - if (TextUtils.isEmpty(videoPath) || maxWidth <= 0) { - return null; - } - - if (new File(videoPath).exists()) { - // Local file - Bitmap thumb = - ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND); - return ImageUtils.getScaledBitmapAtLongestSide(thumb, maxWidth); - } - - // Not a local file. - MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); - Bitmap bitmap = null; - try { - mediaMetadataRetriever.setDataSource(videoPath, headers); - bitmap = mediaMetadataRetriever.getFrameAtTime(); - } catch (IllegalArgumentException e) { - AppLog.e(AppLog.T.MEDIA, "The passed video path is invalid: " + videoPath); - } catch (java.lang.RuntimeException e) { - // I've see this kind of error on one of my testing device - AppLog.e(AppLog.T.MEDIA, "The passed video path is invalid: " + videoPath); - } finally { - mediaMetadataRetriever.release(); - } - - if (bitmap == null) { - AppLog.w(AppLog.T.MEDIA, "Failed to retrieve frame from the passed video path: " + videoPath); - return null; - } - - return getScaledBitmapAtLongestSide(bitmap, maxWidth); - } - - /** - * nbradbury - 21-Feb-2014 - similar to createThumbnail but more efficient since it doesn't - * require passing the full-size image as an array of bytes[] - */ - public static byte[] createThumbnailFromUri(Context context, - Uri imageUri, - int maxWidth, - String fileExtension, - int orientation) { - if (context == null || imageUri == null || maxWidth <= 0) { - return null; - } - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - boolean res = - resizeImageAndWriteToStream(context, imageUri, fileExtension, maxWidth, orientation, 75, stream); - if (!res) { - AppLog.w(AppLog.T.MEDIA, "Failed to compress the resized image. Use the full picture instead."); - return null; - } - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create resized image. Use the full picture instead."); - return null; - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.MEDIA, "Can't resize the picture due to low memory. Use the full picture instead."); - return null; - } - - return stream.toByteArray(); - } - - public static Bitmap getCircularBitmap(final Bitmap bitmap) { - if (bitmap == null) { - return null; - } - - final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(output); - final Paint paint = new Paint(); - final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - final RectF rectF = new RectF(rect); - - paint.setAntiAlias(true); - canvas.drawARGB(0, 0, 0, 0); - paint.setColor(Color.RED); - canvas.drawOval(rectF, paint); - - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - canvas.drawBitmap(bitmap, rect, rect, paint); - - return output; - } - - /** - * Returns the passed bitmap with rounded corners - * @param bitmap - the bitmap to modify - * @param radius - the radius of the corners - * @param borderColor - the border to apply (use Color.TRANSPARENT for none) - */ - public static Bitmap getRoundedEdgeBitmap(final Bitmap bitmap, int radius, int borderColor) { - if (bitmap == null) { - return null; - } - - final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(output); - final Paint paint = new Paint(); - final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - final RectF rectF = new RectF(rect); - - paint.setAntiAlias(true); - canvas.drawARGB(0, 0, 0, 0); - paint.setColor(Color.RED); - canvas.drawRoundRect(rectF, radius, radius, paint); - - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - canvas.drawBitmap(bitmap, rect, rect, paint); - - if (borderColor != Color.TRANSPARENT) { - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(1f); - paint.setColor(borderColor); - canvas.drawRoundRect(rectF, radius, radius, paint); - } - - return output; - } - - /** - * Get the maximum size a thumbnail can be to fit in either portrait or landscape orientations. - * @deprecated Use `getMaximumThumbnailSizeForEditor` available in MediaUtils class in Editors project - */ - public static int getMaximumThumbnailWidthForEditor(Context context) { - int maximumThumbnailWidthForEditor; - Point size = DisplayUtils.getDisplayPixelSize(context); - int screenWidth = size.x; - int screenHeight = size.y; - maximumThumbnailWidthForEditor = (screenWidth > screenHeight) ? screenHeight : screenWidth; - // 48dp of padding on each side so you can still place the cursor next to the image. - int padding = DisplayUtils.dpToPx(context, 48) * 2; - maximumThumbnailWidthForEditor -= padding; - return maximumThumbnailWidthForEditor; - } - - /** - * Given the path to an image, rotate it by using EXIF info - * @param context the passed context - * @param path the path to the original image - * @return the path to the rotated image or null - */ - public static String rotateImageIfNecessary(Context context, String path) { - if (context == null || TextUtils.isEmpty(path)) { - return null; - } - - File file = new File(path); - if (!file.exists()) { - return null; - } - - int orientation = getImageOrientation(context, path); - // Do not rotate portrait pictures - if (orientation == 0) { - return null; - } - - String mimeType = MediaUtils.getMediaFileMimeType(file); - if (mimeType.equals("image/gif")) { - // Don't rotate gifs to maintain their quality - return null; - } - - Uri srcImageUri = Uri.parse(path); - if (srcImageUri == null) { - return null; - } - - String fileName = MediaUtils.getMediaFileName(file, mimeType); - String fileExtension = MimeTypeMap.getFileExtensionFromUrl(fileName).toLowerCase(Locale.ROOT); - - int selectedWidth = getImageSize(srcImageUri, context)[0]; - if (selectedWidth == 0) { - // Can't read the src dimensions. - return null; - } - - File rotatedImageFile; - FileOutputStream out; - - try { - // try to re-use the same name as prefix of the temp file - String prefix = FileUtils.getFileNameFromPath(fileName); - - if (TextUtils.isEmpty(prefix) || prefix.length() < 3) { - // prefix must be at least 3 characters - prefix = "wp-image"; - } - - rotatedImageFile = File.createTempFile(prefix, "." + fileExtension); - out = new FileOutputStream(rotatedImageFile); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create the temp file on storage."); - return null; - } catch (SecurityException e) { - AppLog.e(AppLog.T.MEDIA, "Can't write the tmp file due to security restrictions."); - return null; - } - - try { - boolean res = - resizeImageAndWriteToStream(context, srcImageUri, fileExtension, selectedWidth, orientation, 85, - out); - if (!res) { - AppLog.w(AppLog.T.MEDIA, "Failed to compress the rotates image."); - return null; - } - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create rotated image."); - return null; - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.MEDIA, "Can't rotate the picture due to low memory."); - return null; - } finally { - // close the stream - try { - out.flush(); - out.close(); - } catch (IOException e) { - // nope - } - } - - String tempFilePath = rotatedImageFile.getPath(); - if (!TextUtils.isEmpty(tempFilePath)) { - return tempFilePath; - } else { - AppLog.e(AppLog.T.MEDIA, "Failed to create rotated image."); - } - - return null; - } - - // determine correct scale value (should be power of 2) - // http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/3549021#3549021 - protected static int getScaleForResizing(int maxSize, BitmapFactory.Options optBounds) { - if (maxSize < 1) { - return 1; - } - - int maxDimension = Math.max(optBounds.outWidth, optBounds.outHeight); - int scale = 1; - - while (maxDimension / scale / 2 >= maxSize) { - scale *= 2; - } - return scale; - } - - private static float getScaleImageBy(float maxSize, Bitmap bmpResized) { - int divideBy = Math.max(bmpResized.getHeight(), bmpResized.getWidth()); - float percentage = maxSize / divideBy; - - float proportionateHeight = bmpResized.getHeight() * percentage; - int finalHeight = (int) Math.rint(proportionateHeight); - - float scaleWidth = maxSize / bmpResized.getWidth(); - float scaleHeight = ((float) finalHeight) / bmpResized.getHeight(); - - return Math.min(scaleWidth, scaleHeight); - } - - public static Rect getScaledBounds(int width, int height, int maxWidth) { - float xScale = Math.max(1.0f, (float) width / maxWidth); - return new Rect(0, 0, Math.round(width / xScale), Math.round(height / xScale)); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java deleted file mode 100644 index 7e4e177b392b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java +++ /dev/null @@ -1,262 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -import org.apache.commons.text.StringEscapeUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.wordpress.android.util.AppLog.T; - -import java.util.ArrayList; - -public class JSONUtils { - private static final String QUERY_SEPERATOR = "."; - private static final String QUERY_ARRAY_INDEX_START = "["; - private static final String QUERY_ARRAY_INDEX_END = "]"; - private static final String QUERY_ARRAY_FIRST = "first"; - private static final String QUERY_ARRAY_LAST = "last"; - - private static final String JSON_NULL_STR = "null"; - private static final String TAG = "JSONUtils"; - - /** - * Given a JSONObject and a key path (e.g property.child) and a default it will - * traverse the object graph and pull out the desired property - */ - public static U queryJSON(JSONObject source, String query, U defaultObject) { - if (source == null) { - AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); - return defaultObject; - } - if (query == null) { - AppLog.e(T.UTILS, "Parameter query is null"); - return defaultObject; - } - int nextSeperator = query.indexOf(QUERY_SEPERATOR); - int nextIndexStart = query.indexOf(QUERY_ARRAY_INDEX_START); - if (nextSeperator == -1 && nextIndexStart == -1) { - // last item let's get it - try { - if (!source.has(query)) { - return defaultObject; - } - Object result = source.get(query); - if (result.getClass().isAssignableFrom(defaultObject.getClass())) { - return (U) result; - } else { - AppLog.w(T.UTILS, String.format( - "The returned object type %s is not assignable to the type %s. Using default!", - result.getClass(), defaultObject.getClass())); - return defaultObject; - } - } catch (java.lang.ClassCastException e) { - AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); - return defaultObject; - } catch (JSONException e) { - AppLog.e(T.UTILS, "Unable to get the Key from the input object. Key:" + query, e); - return defaultObject; - } - } - int endQuery; - if (nextSeperator == -1 || nextIndexStart == -1) { - endQuery = Math.max(nextSeperator, nextIndexStart); - } else { - endQuery = Math.min(nextSeperator, nextIndexStart); - } - String nextQuery = query.substring(endQuery); - String key = query.substring(0, endQuery); - try { - if (nextQuery.indexOf(QUERY_SEPERATOR) == 0) { - return queryJSON(source.getJSONObject(key), nextQuery.substring(1), defaultObject); - } else if (nextQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { - return queryJSON(source.getJSONArray(key), nextQuery, defaultObject); - } else if (!nextQuery.equals("")) { - return defaultObject; - } - Object result = source.get(key); - if (result.getClass().isAssignableFrom(defaultObject.getClass())) { - return (U) result; - } else { - AppLog.w(T.UTILS, - String.format("The returned object type %s is not assignable to the type %s. Using default!", - result.getClass(), defaultObject.getClass())); - return defaultObject; - } - } catch (java.lang.ClassCastException e) { - AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); - return defaultObject; - } catch (JSONException e) { - return defaultObject; - } - } - - /** - * Given a JSONArray and a query (e.g. [0].property) it will traverse the array and - * pull out the requested property. - * - * Acceptable indexes include negative numbers to reference items from the end of - * the list as well as "last" and "first" as more explicit references to "0" and "-1" - */ - public static U queryJSON(JSONArray source, String query, U defaultObject) { - if (source == null) { - AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); - return defaultObject; - } - if (query == null) { - AppLog.e(T.UTILS, "Parameter query is null"); - return defaultObject; - } - // query must start with [ have an index and then have ] - int indexStart = query.indexOf(QUERY_ARRAY_INDEX_START); - int indexEnd = query.indexOf(QUERY_ARRAY_INDEX_END); - if (indexStart == -1 || indexEnd == -1 || indexStart > indexEnd) { - return defaultObject; - } - // get "index" from "[index]" - String indexStr = query.substring(indexStart + 1, indexEnd); - int index; - if (indexStr.equals(QUERY_ARRAY_FIRST)) { - index = 0; - } else if (indexStr.equals(QUERY_ARRAY_LAST)) { - index = -1; - } else { - index = Integer.parseInt(indexStr); - } - if (index < 0) { - index = source.length() + index; - } - // copy remaining query - String remainingQuery = query.substring(indexEnd + 1); - try { - if (remainingQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { - return queryJSON(source.getJSONArray(index), remainingQuery, defaultObject); - } else if (remainingQuery.indexOf(QUERY_SEPERATOR) == 0) { - return queryJSON(source.getJSONObject(index), remainingQuery.substring(1), defaultObject); - } else if (!remainingQuery.equals("")) { - // TODO throw an exception since the query isn't valid? - AppLog.w(T.UTILS, String.format("Incorrect query for next object %s", remainingQuery)); - return defaultObject; - } - Object result = source.get(index); - if (result.getClass().isAssignableFrom(defaultObject.getClass())) { - return (U) result; - } else { - AppLog.w(T.UTILS, - String.format("The returned object type %s is not assignable to the type %s. Using default!", - result.getClass(), defaultObject.getClass())); - return defaultObject; - } - } catch (java.lang.ClassCastException e) { - AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); - return defaultObject; - } catch (JSONException e) { - return defaultObject; - } - } - - /** - * Convert a JSONArray (expected to contain strings) in a string list - */ - public static ArrayList fromJSONArrayToStringList(JSONArray jsonArray) { - ArrayList stringList = new ArrayList(); - for (int i = 0; i < jsonArray.length(); i++) { - try { - stringList.add(jsonArray.getString(i)); - } catch (JSONException e) { - AppLog.e(T.UTILS, e); - } - } - return stringList; - } - - /** - * Convert a string list in a JSONArray - */ - public static JSONArray fromStringListToJSONArray(ArrayList stringList) { - JSONArray jsonArray = new JSONArray(); - if (stringList != null) { - for (int i = 0; i < stringList.size(); i++) { - jsonArray.put(stringList.get(i)); - } - } - return jsonArray; - } - - /* - * wrapper for JSONObject.optString() which handles "null" values - */ - public static String getString(JSONObject json, String name) { - String value = json.optString(name); - // return empty string for "null" - if (JSON_NULL_STR.equals(value)) { - return ""; - } - return value; - } - - /* - * use with strings that contain HTML entities - */ - public static String getStringDecoded(JSONObject json, String name) { - String value = getString(json, name); - return StringEscapeUtils.unescapeHtml4(value); - } - - /* - * replacement for JSONObject.optBoolean() - optBoolean() only checks for "true" and "false", - * but our API sometimes uses "0" to denote false - */ - public static boolean getBool(JSONObject json, String name) { - String value = getString(json, name); - if (TextUtils.isEmpty(value)) { - return false; - } - if (value.equals("0")) { - return false; - } - if (value.equalsIgnoreCase("false")) { - return false; - } - if (value.equalsIgnoreCase("no")) { - return false; - } - return true; - } - - /* - * returns the JSONObject child of the passed parent that matches the passed query - * this is basically an "optJSONObject" that supports nested queries, for example: - * - * getJSONChild("meta/data/site") - * - * would find this: - * - * "meta": { - * "data": { - * "site": { - * "ID": 3584907, - * "name": "WordPress.com News", - * } - * } - * } - */ - public static JSONObject getJSONChild(final JSONObject jsonParent, final String query) { - if (jsonParent == null || TextUtils.isEmpty(query)) { - return null; - } - String[] names = query.split("/"); - JSONObject jsonChild = null; - for (int i = 0; i < names.length; i++) { - if (jsonChild == null) { - jsonChild = jsonParent.optJSONObject(names[i]); - } else { - jsonChild = jsonChild.optJSONObject(names[i]); - } - if (jsonChild == null) { - return null; - } - } - return jsonChild; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java deleted file mode 100644 index 1deaa603efd7..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -import androidx.annotation.Nullable; - -import java.util.Locale; - -/** - * Methods for dealing with i18n messages - */ -public class LanguageUtils { - /** - * @deprecated Use {@link #getCurrentDeviceLanguage()}. As of API 25, setting the locale by updating the - * configuration on the resources object was deprecated, so this method stopped working for newer versions - * of Android. The current active locale should always be set in {@link Locale#getDefault()}. When manually - * setting the active locale, the developer should set it in {@link Locale#setDefault(Locale)}. - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - public static Locale getCurrentDeviceLanguage(@Nullable Context context) { - return getCurrentDeviceLanguage(); - } - - @SuppressWarnings("WeakerAccess") - public static Locale getCurrentDeviceLanguage() { - return Locale.getDefault(); - } - - /** - * @deprecated Use {@link #getCurrentDeviceLanguageCode()}. - */ - @SuppressWarnings("WeakerAccess,DeprecatedIsStillUsed") - @Deprecated - public static String getCurrentDeviceLanguageCode(@Nullable Context context) { - return getCurrentDeviceLanguageCode(); - } - - @SuppressWarnings("WeakerAccess") - public static String getCurrentDeviceLanguageCode() { - return getCurrentDeviceLanguage().toString(); - } - - public static String getPatchedCurrentDeviceLanguage(Context context) { - return patchDeviceLanguageCode(getCurrentDeviceLanguageCode(context)); - } - - /** - * Patches a deviceLanguageCode if any of deprecated values iw, id, or yi - */ - @SuppressWarnings("WeakerAccess") - public static String patchDeviceLanguageCode(String deviceLanguageCode) { - String patchedCode = deviceLanguageCode; - /* -

    Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language - * code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This - * rewriting happens even if you construct your own {@code Locale} object, not just for - * instances returned by the various lookup methods. - */ - if (deviceLanguageCode != null) { - if (deviceLanguageCode.startsWith("iw")) { - patchedCode = deviceLanguageCode.replace("iw", "he"); - } else if (deviceLanguageCode.startsWith("in")) { - patchedCode = deviceLanguageCode.replace("in", "id"); - } else if (deviceLanguageCode.startsWith("ji")) { - patchedCode = deviceLanguageCode.replace("ji", "yi"); - } - } - - return patchedCode; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java deleted file mode 100644 index 30d38e36c514..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.wordpress.android.util; - -import androidx.annotation.Nullable; - -import org.apache.commons.lang3.ArrayUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ListUtils { - @Nullable - public static ArrayList fromLongArray(long[] array) { - if (array == null) { - return null; - } - Long[] longObjects = ArrayUtils.toObject(array); - return new ArrayList<>(Arrays.asList(longObjects)); - } - - @Nullable - public static long[] toLongArray(List list) { - if (list == null) { - return null; - } - Long[] array = list.toArray(new Long[list.size()]); - return ArrayUtils.toPrimitive(array); - } - - @Nullable - public static ArrayList fromIntArray(int[] array) { - if (array == null) { - return null; - } - Integer[] intObjects = ArrayUtils.toObject(array); - return new ArrayList<>(Arrays.asList(intObjects)); - } - - @Nullable - public static int[] toIntArray(List list) { - if (list == null) { - return null; - } - Integer[] array = list.toArray(new Integer[list.size()]); - return ArrayUtils.toPrimitive(array); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java deleted file mode 100644 index 4345a4b22cfe..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.wordpress.android.util; - -import java.util.Date; -import java.util.Map; - -/** - * wrappers for extracting values from a Map object - */ -public class MapUtils { - /* - * returns a String value for the passed key in the passed map - * always returns "" instead of null - */ - public static String getMapStr(final Map map, final String key) { - if (map == null || key == null || !map.containsKey(key) || map.get(key) == null) { - return ""; - } - return map.get(key).toString(); - } - - /* - * returns an int value for the passed key in the passed map - * defaultValue is returned if key doesn't exist or isn't a number - */ - public static int getMapInt(final Map map, final String key) { - return getMapInt(map, key, 0); - } - - public static int getMapInt(final Map map, final String key, int defaultValue) { - try { - return Integer.parseInt(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * long version of above - */ - public static long getMapLong(final Map map, final String key) { - return getMapLong(map, key, 0); - } - - public static long getMapLong(final Map map, final String key, long defaultValue) { - try { - return Long.parseLong(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * float version of above - */ - public static float getMapFloat(final Map map, final String key) { - return getMapFloat(map, key, 0); - } - - public static float getMapFloat(final Map map, final String key, float defaultValue) { - try { - return Float.parseFloat(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * double version of above - */ - public static double getMapDouble(final Map map, final String key) { - return getMapDouble(map, key, 0); - } - - public static double getMapDouble(final Map map, final String key, double defaultValue) { - try { - return Double.parseDouble(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * returns a date object from the passed key in the passed map - * returns null if key doesn't exist or isn't a date - */ - public static Date getMapDate(final Map map, final String key) { - if (map == null || key == null || !map.containsKey(key)) { - return null; - } - try { - return (Date) map.get(key); - } catch (ClassCastException e) { - return null; - } - } - - /* - * returns a boolean value from the passed key in the passed map - * returns true unless key doesn't exist, or the value is "0" or "false" - */ - public static boolean getMapBool(final Map map, final String key) { - String value = getMapStr(map, key); - if (value.isEmpty()) { - return false; - } - if (value.startsWith("0")) { // handles "0" and "0.0" - return false; - } - if (value.equalsIgnoreCase("false")) { - return false; - } - // all other values are assume to be true - return true; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java deleted file mode 100644 index d052d0758dc1..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java +++ /dev/null @@ -1,563 +0,0 @@ -package org.wordpress.android.util; - -import android.annotation.TargetApi; -import android.content.ContentUris; -import android.content.Context; -import android.content.CursorLoader; -import android.database.Cursor; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import androidx.annotation.Nullable; - -import org.wordpress.android.util.AppLog.T; - -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class MediaUtils { - private static final int DEFAULT_MAX_IMAGE_WIDTH = 1024; - private static final Pattern FILE_EXISTS_PATTERN = Pattern.compile("(.*?)(-([0-9]+))?(\\..*$)?"); - - public static boolean isValidImage(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".png") || url.endsWith(".jpg") || url.endsWith(".jpeg") || url.endsWith(".gif"); - } - - public static boolean isDocument(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".doc") || url.endsWith(".docx") || url.endsWith(".odt") || url.endsWith(".pdf"); - } - - public static boolean isPowerpoint(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".ppt") || url.endsWith(".pptx") || url.endsWith(".pps") || url.endsWith(".ppsx") - || url.endsWith(".key"); - } - - public static boolean isSpreadsheet(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".xls") || url.endsWith(".xlsx"); - } - - public static boolean isVideo(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".ogv") || url.endsWith(".mp4") || url.endsWith(".m4v") || url.endsWith(".mov") - || url.endsWith(".wmv") || url.endsWith(".avi") || url.endsWith(".mpg") || url.endsWith(".3gp") - || url.endsWith(".3g2") || url.contains("video"); - } - - public static boolean isAudio(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".mp3") || url.endsWith(".ogg") || url.endsWith(".wav") || url.endsWith(".wma") - || url.endsWith(".aiff") || url.endsWith(".aif") || url.endsWith(".aac") || url.endsWith(".m4a"); - } - - public static boolean isGif(String url) { - return "gif".equals(MimeTypeMap.getFileExtensionFromUrl(url)); - } - - public static boolean isLocalFile(String state) { - if (state == null) { - return false; - } - - return state.equalsIgnoreCase("queued") - || state.equalsIgnoreCase("uploading") - || state.equalsIgnoreCase("retry") - || state.equalsIgnoreCase("failed"); - } - - public static Uri getLastRecordedVideoUri(Context appContext) { - String[] proj = {MediaStore.Video.Media._ID}; - Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - String sortOrder = MediaStore.Video.VideoColumns.DATE_TAKEN + " DESC"; - CursorLoader loader = new CursorLoader(appContext, contentUri, proj, null, null, sortOrder); - Cursor cursor = loader.loadInBackground(); - cursor.moveToFirst(); - long value = cursor.getLong(0); - SqlUtils.closeCursor(cursor); - - return Uri.parse(contentUri.toString() + "/" + value); - } - - /** - * Get image max size setting from the image max size setting string. This string can be an int, in this case it's - * the maximum image width defined by the site. - * Examples: - * "1000" will return 1000 - * "Original Size" will return Integer.MAX_VALUE - * "Largeur originale" will return Integer.MAX_VALUE - * null will return Integer.MAX_VALUE - * @param imageMaxSizeSiteSettingString Image max size site setting string - * @return Integer.MAX_VALUE if image width is not defined or invalid, maximum image width in other cases. - */ - public static int getImageMaxSizeSettingFromString(String imageMaxSizeSiteSettingString) { - if (imageMaxSizeSiteSettingString == null) { - return Integer.MAX_VALUE; - } - try { - return Integer.valueOf(imageMaxSizeSiteSettingString); - } catch (NumberFormatException e) { - return Integer.MAX_VALUE; - } - } - - /** - * Calculate and return the maximum allowed image width by comparing the width of the image at its full size with - * the maximum upload width set in the blog settings - * @param imageSize the image's natural (full) width - * @param imageMaxSizeSiteSettingString the maximum upload width set in the site settings - * @return maximum allowed image width - */ - public static int getMaximumImageSize(int imageSize, String imageMaxSizeSiteSettingString) { - int imageMaxSizeBlogSetting = getImageMaxSizeSettingFromString(imageMaxSizeSiteSettingString); - int imageWidthPictureSetting = imageSize == 0 ? Integer.MAX_VALUE : imageSize; - - if (Math.min(imageWidthPictureSetting, imageMaxSizeBlogSetting) == Integer.MAX_VALUE) { - // Default value in case of errors reading the picture size or the blog settings is set to Original size - return DEFAULT_MAX_IMAGE_WIDTH; - } else { - return Math.min(imageWidthPictureSetting, imageMaxSizeBlogSetting); - } - } - - public static int getMaximumImageSize(Context context, Uri curStream, String imageMaxSizeBlogSettingString) { - int[] dimensions = ImageUtils.getImageSize(curStream, context); - return getMaximumImageSize(dimensions[0], imageMaxSizeBlogSettingString); - } - - public static boolean isInMediaStore(Uri mediaUri) { - // Check if the image is externally hosted (Picasa/Google Photos for example) - return mediaUri != null && mediaUri.toString().startsWith("content://media/"); - } - - public static @Nullable String getFilenameFromURI(Context context, Uri uri) { - Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, - null, null, null); - try { - String result = null; - if (cursor != null && cursor.moveToFirst()) { - int columnIndexDisplayName = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); - if (columnIndexDisplayName == -1) { - return null; - } - result = cursor.getString(columnIndexDisplayName); - } - return result; - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - /* - * Some media providers (eg. Google Photos) give us a limited access to media files just so we can copy them and - * then they revoke the access. Copying these files must be performed on the UI thread, otherwise the access might - * be revoked before the action completes. See https://github.com/wordpress-mobile/WordPress-Android/issues/5818 - */ - public static Uri downloadExternalMedia(Context context, Uri imageUri) { - if (context == null || imageUri == null) { - return null; - } - String mimeType = UrlUtils.getUrlMimeType(imageUri.toString()); - File cacheDir = context.getCacheDir(); - - if (cacheDir != null && !cacheDir.exists()) { - cacheDir.mkdirs(); - } - try { - InputStream input; - // Download the file - if (imageUri.toString().startsWith("content://")) { - input = context.getContentResolver().openInputStream(imageUri); - if (input == null) { - AppLog.e(T.UTILS, "openInputStream returned null"); - return null; - } - } else { - input = new URL(imageUri.toString()).openStream(); - } - - String fileName = getFilenameFromURI(context, imageUri); - if (TextUtils.isEmpty(fileName)) { - fileName = generateTimeStampedFileName(mimeType); - } - - File f = getUniqueCacheFileForName(fileName, cacheDir, mimeType); - - OutputStream output = new FileOutputStream(f); - - byte[] data = new byte[1024]; - int count; - while ((count = input.read(data)) != -1) { - output.write(data, 0, count); - } - - output.flush(); - output.close(); - input.close(); - - return Uri.fromFile(f); - } catch (IOException e) { - AppLog.e(T.UTILS, e); - } - - return null; - } - - private static File getUniqueCacheFileForName(String fileName, File cacheDir, String mimeType) { - File file = new File(cacheDir, fileName); - - while (file.exists()) { - Matcher matcher = FILE_EXISTS_PATTERN.matcher(fileName); - if (matcher.matches()) { - String baseFileName = matcher.group(1); - String existingDuplicationNumber = matcher.group(3); - String fileType = StringUtils.notNullStr(matcher.group(4)); - - if (existingDuplicationNumber == null) { - // Not a copy already - fileName = baseFileName + "-1" + fileType; - } else { - fileName = baseFileName + "-" + (StringUtils.stringToInt(existingDuplicationNumber) + 1) + fileType; - } - } else { - // Shouldn't happen, but in case our match fails fall back to timestamped file name - fileName = generateTimeStampedFileName(mimeType); - } - file = new File(cacheDir, fileName); - } - return file; - } - - public static String generateTimeStampedFileName(String mimeType) { - return "wp-" + System.currentTimeMillis() + "." + getExtensionForMimeType(mimeType); - } - - public static String getMimeTypeOfInputStream(InputStream stream) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(stream, null, options); - return options.outMimeType; - } - - public static String getMediaFileMimeType(File mediaFile) { - String originalFileName = mediaFile.getName().toLowerCase(Locale.ROOT); - String mimeType = UrlUtils.getUrlMimeType(originalFileName); - - if (TextUtils.isEmpty(mimeType)) { - try { - String filePathForGuessingMime; - if (mediaFile.getPath().contains("://")) { - filePathForGuessingMime = Uri.encode(mediaFile.getPath(), ":/"); - } else { - filePathForGuessingMime = "file://" + Uri.encode(mediaFile.getPath(), "/"); - } - URL urlForGuessingMime = new URL(filePathForGuessingMime); - URLConnection uc = urlForGuessingMime.openConnection(); - String guessedContentType = null; - try { - guessedContentType = - uc.getContentType(); // internally calls guessContentTypeFromName(url.getFile()); and - // guessContentTypeFromStream(is); - } catch (StringIndexOutOfBoundsException e) { - // Ref: https://github.com/wordpress-mobile/WordPress-Android/issues/5699 - AppLog.e(AppLog.T.MEDIA, "Error getting the content type for " + mediaFile.getPath() - + " by using URLConnection.getContentType", e); - } - // check if returned "content/unknown" - if (!TextUtils.isEmpty(guessedContentType) && !guessedContentType.equals("content/unknown")) { - mimeType = guessedContentType; - } - } catch (MalformedURLException e) { - AppLog.e(AppLog.T.MEDIA, - "MalformedURLException while trying to guess the content type for the file here " + mediaFile - .getPath() + " with URLConnection", e); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, - "Error while trying to guess the content type for the file here " + mediaFile.getPath() - + " with URLConnection", e); - } - } - - // No mimeType yet? Try to decode the image and get the mimeType from there - if (TextUtils.isEmpty(mimeType)) { - try { - DataInputStream inputStream = new DataInputStream(new FileInputStream(mediaFile)); - String mimeTypeFromStream = getMimeTypeOfInputStream(inputStream); - if (!TextUtils.isEmpty(mimeTypeFromStream)) { - mimeType = mimeTypeFromStream; - } - inputStream.close(); - } catch (FileNotFoundException e) { - AppLog.e(AppLog.T.MEDIA, - "FileNotFoundException while trying to guess the content type for the file " + mediaFile - .getPath(), e); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, - "IOException while trying to guess the content type for the file " + mediaFile.getPath(), e); - } - } - - if (TextUtils.isEmpty(mimeType)) { - mimeType = ""; - } else { - if (mimeType.equalsIgnoreCase("video/mp4v-es")) { // Fixes #533. See: http://tools.ietf.org/html/rfc3016 - mimeType = "video/mp4"; - } - } - - return mimeType; - } - - public static String getMediaFileName(File mediaFile, String mimeType) { - String originalFileName = mediaFile.getName().toLowerCase(Locale.ROOT); - String extension = MimeTypeMap.getFileExtensionFromUrl(originalFileName); - if (!TextUtils.isEmpty(extension)) { // File name already has the extension in it - return originalFileName; - } - - if (!TextUtils.isEmpty(mimeType)) { // try to get the extension from mimeType - String fileExtension = getExtensionForMimeType(mimeType); - if (!TextUtils.isEmpty(fileExtension)) { - originalFileName += "." + fileExtension; - } - } else { - // No mimetype and no extension!! - AppLog.e(AppLog.T.API, "No mimetype and no extension for " + mediaFile.getPath()); - } - - return originalFileName; - } - - public static String getExtensionForMimeType(String mimeType) { - if (TextUtils.isEmpty(mimeType)) { - return ""; - } - - MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); - String fileExtensionFromMimeType = mimeTypeMap.getExtensionFromMimeType(mimeType); - if (TextUtils.isEmpty(fileExtensionFromMimeType)) { - // We're still without an extension - split the mime type and retrieve it - String[] split = mimeType.split("/"); - fileExtensionFromMimeType = split.length > 1 ? split[1] : split[0]; - } - - return fileExtensionFromMimeType.toLowerCase(Locale.ROOT); - } - - public static String getRealPathFromURI(final Context context, Uri uri) { - String path; - if ("content".equals(uri.getScheme())) { - path = MediaUtils.getPath(context, uri); - } else if ("file".equals(uri.getScheme())) { - path = uri.getPath(); - } else { - path = uri.toString(); - } - - return path; - } - - /** - * Get a file path from a Uri. This will get the the path for Storage Access - * Framework Documents, as well as the _data field for the MediaStore and - * other file-based ContentProviders. - * - * Based on paulburke's solution for aFileChooser - https://github.com/iPaulPro/aFileChooser - * - * @param context The context. - * @param uri The Uri to query. - */ - private static String getPath(final Context context, final Uri uri) { - String path = getDocumentProviderPathKitkatOrHigher(context, uri); - - if (path != null) { - return path; - } - - // MediaStore (and general) - if ("content".equalsIgnoreCase(uri.getScheme())) { - return getDataColumn(context, uri, null, null); - } else if ("file".equalsIgnoreCase(uri.getScheme())) { // File - return uri.getPath(); - } - - return null; - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - private static String getDocumentProviderPathKitkatOrHigher(final Context context, final Uri uri) { - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - // ExternalStorageProvider - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } else if (isDownloadsDocument(uri)) { - String id = DocumentsContract.getDocumentId(uri); - - if (id != null && id.startsWith("raw:")) { - return id.substring(4); - } - - // https://github.com/Javernaut/WhatTheCodec/issues/2 - if (id != null && id.startsWith("msf:")) { - id = id.substring(4); - } - - String[] contentUriPrefixesToTry = new String[]{ - "content://downloads/public_downloads", - "content://downloads/my_downloads", - "content://downloads/all_downloads" - }; - - for (String contentUriPrefix : contentUriPrefixesToTry) { - Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id)); - try { - String path = getDataColumn(context, contentUri, null, null); - if (path != null) { - return path; - } - } catch (Exception e) { - AppLog.e(AppLog.T.UTILS, "Error reading _data column for URI: " + contentUri, e); - } - } - return downloadExternalMedia(context, uri).getPath(); - } else if (isMediaDocument(uri)) { // MediaProvider - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = MediaStore.MediaColumns._ID + "=?"; - - final String[] selectionArgs = new String[]{ - split[1] - }; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - - return null; - } - - /** - * Get the value of the data column for this Uri. This is useful for - * MediaStore Uris, and other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @param selection (Optional) Filter used in the query. - * @param selectionArgs (Optional) Selection arguments used in the query. - * @return The value of the _data column, which is typically a file path. - */ - public static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - Cursor cursor = null; - final String column = MediaStore.MediaColumns.DATA; - - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); - if (cursor != null && cursor.moveToFirst()) { - final int columnIndex = cursor.getColumnIndex(column); - if (columnIndex != -1) { - return cursor.getString(columnIndex); - } - } - } catch (SecurityException errReadingContentResolver) { - AppLog.e(AppLog.T.UTILS, "Error reading _data column for URI: " + uri, errReadingContentResolver); - } finally { - if (cursor != null) { - cursor.close(); - } - } - return null; - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is ExternalStorageProvider. - */ - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is DownloadsProvider. - */ - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is MediaProvider. - */ - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java deleted file mode 100644 index 83a2cb20066e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.wordpress.android.util; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.Build; -import android.os.Build.VERSION_CODES; -import android.provider.Settings; - -/** - * requires android.permission.ACCESS_NETWORK_STATE - */ -@SuppressLint("MissingPermission") -public class NetworkUtils { - public static final int TYPE_UNKNOWN = -1; - - /** - * returns information on the active network connection - */ - @SuppressLint("MissingPermission") - public static NetworkInfo getActiveNetworkInfo(Context context) { - if (context == null) { - return null; - } - ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (cm == null) { - return null; - } - // note that this may return null if no network is currently active - return cm.getActiveNetworkInfo(); - } - - /** - * returns the ConnectivityManager.TYPE_xxx if there's an active connection, otherwise - * returns TYPE_UNKNOWN - */ - private static int getActiveNetworkType(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - if (info == null || !info.isConnected()) { - return TYPE_UNKNOWN; - } - return info.getType(); - } - - /** - * returns true if a network connection is available - */ - public static boolean isNetworkAvailable(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - return (info != null && info.isConnected()); - } - - /** - * returns true if the user is connected to WiFi - */ - public static boolean isWiFiConnected(Context context) { - return (getActiveNetworkType(context) == ConnectivityManager.TYPE_WIFI); - } - - /** - * returns true if the user is connected with the mobile data connection - */ - public static boolean isMobileConnected(Context context) { - int networkType = getActiveNetworkType(context); - return (networkType == ConnectivityManager.TYPE_MOBILE - || networkType == ConnectivityManager.TYPE_MOBILE_DUN); - } - - /** - * returns true if airplane mode has been enabled - */ - @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) - @SuppressWarnings("deprecation") - public static boolean isAirplaneModeOn(Context context) { - // prior to JellyBean 4.2 this was Settings.System.AIRPLANE_MODE_ON, JellyBean 4.2 - // moved it to Settings.Global - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0; - } else { - return Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0; - } - } - - /** - * returns true if there's an active network connection, otherwise displays a toast error - * and returns false - */ - public static boolean checkConnection(Context context) { - if (context == null) { - return false; - } - if (isNetworkAvailable(context)) { - return true; - } - ToastUtils.showToast(context, R.string.no_network_message); - return false; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java deleted file mode 100644 index 52900a0bf27e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; - -public class PackageUtils { - /** - * Return true if Debug build. false otherwise. - */ - public static boolean isDebugBuild() { - return BuildConfig.DEBUG; - } - - public static PackageInfo getPackageInfo(Context context) { - try { - PackageManager manager = context.getPackageManager(); - return manager.getPackageInfo(context.getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } - - /** - * Return version code, or 0 if it can't be read - */ - public static int getVersionCode(Context context) { - PackageInfo packageInfo = getPackageInfo(context); - if (packageInfo != null) { - return packageInfo.versionCode; - } - return 0; - } - - /** - * Return version name, or the string "0" if it can't be read - */ - public static String getVersionName(Context context) { - PackageInfo packageInfo = getPackageInfo(context); - if (packageInfo != null) { - return packageInfo.versionName; - } - return "0"; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java deleted file mode 100644 index 8d484d847519..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.wordpress.android.util; - -import android.Manifest.permission; -import android.app.Activity; -import android.content.Context; -import android.content.pm.PackageManager; - -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; - -import java.util.ArrayList; -import java.util.List; - -public class PermissionUtils { - /** - * Check for permissions, request them if they're not granted. - * - * @return true if permissions are already granted, else request them and return false. - */ - public static boolean checkAndRequestPermissions(Activity activity, int requestCode, String[] permissionList) { - List toRequest = new ArrayList<>(); - for (String permission : permissionList) { - if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { - toRequest.add(permission); - } - } - if (toRequest.size() > 0) { - String[] requestedPermissions = toRequest.toArray(new String[toRequest.size()]); - ActivityCompat.requestPermissions(activity, requestedPermissions, requestCode); - return false; - } - return true; - } - - /** - * Check for permissions, request them if they're not granted. - * - * @return true if permissions are already granted, else request them and return false. - */ - private static boolean checkAndRequestPermissions(Fragment fragment, int requestCode, String[] permissionList) { - List toRequest = new ArrayList<>(); - for (String permission : permissionList) { - Context context = fragment.getActivity(); - if (context != null && ContextCompat.checkSelfPermission(context, permission) != PackageManager - .PERMISSION_GRANTED) { - toRequest.add(permission); - } - } - if (toRequest.size() > 0) { - String[] requestedPermissions = toRequest.toArray(new String[toRequest.size()]); - fragment.requestPermissions(requestedPermissions, requestCode); - return false; - } - return true; - } - - /** - * Check for permissions without requesting them - * - * @return true if all permissions are granted - */ - public static boolean checkPermissions(Activity activity, String[] permissionList) { - for (String permission : permissionList) { - if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { - return false; - } - } - return true; - } - - public static boolean checkCameraAndStoragePermissions(Activity activity) { - return checkPermissions(activity, - new String[]{ - permission.WRITE_EXTERNAL_STORAGE, - permission.CAMERA}); - } - - public static boolean checkAndRequestCameraAndStoragePermissions(Fragment fragment, int requestCode) { - return checkAndRequestPermissions(fragment, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE, - permission.CAMERA - }); - } - - public static boolean checkAndRequestCameraAndStoragePermissions(Activity activity, int requestCode) { - return checkAndRequestPermissions(activity, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE, - permission.CAMERA - }); - } - - public static boolean checkAndRequestStoragePermission(Activity activity, int requestCode) { - return checkAndRequestPermissions(activity, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE - }); - } - - public static boolean checkAndRequestStoragePermission(Fragment fragment, int requestCode) { - return checkAndRequestPermissions(fragment, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE - }); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java deleted file mode 100644 index 2f12eb05fae7..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * routines related to the Photon API - * http://developer.wordpress.com/docs/photon/ - */ -public class PhotonUtils { - private PhotonUtils() { - throw new AssertionError(); - } - - /* - * returns true if the passed url is an obvious "mshots" url - */ - public static boolean isMshotsUrl(final String imageUrl) { - return (imageUrl != null && imageUrl.contains("/mshots/")); - } - - /* - * returns a photon url for the passed image with the resize query set to the passed - * dimensions - note that the passed quality parameter will only affect JPEGs - */ - public enum Quality { - HIGH, - MEDIUM, - LOW - } - - public static final String ATOMIC_MEDIA_PROXY_URL_PREFIX = "https://public-api.wordpress.com/wpcom/v2/sites/"; - public static final String ATOMIC_MEDIA_PROXY_URL_SUFFIX = "/atomic-auth-proxy/file"; - - public static String getPhotonImageUrl(String imageUrl, int width, int height) { - return getPhotonImageUrl(imageUrl, width, height, Quality.MEDIUM); - } - - public static String getPhotonImageUrl(String imageUrl, int width, int height, boolean isPrivateAtomicSite) { - return getPhotonImageUrl(imageUrl, width, height, Quality.MEDIUM, isPrivateAtomicSite); - } - - public static String getPhotonImageUrl(String imageUrl, int width, int height, Quality quality) { - return getPhotonImageUrl(imageUrl, width, height, quality, false); - } - - public static String getPhotonImageUrl(String imageUrl, int width, int height, Quality quality, - boolean isPrivateAtomicSite) { - if (TextUtils.isEmpty(imageUrl)) { - return ""; - } - - // make sure it's valid - int schemePos = imageUrl.indexOf("://"); - if (schemePos == -1) { - return imageUrl; - } - - // we have encountered some image urls that incorrectly have a # fragment part, which - // must be removed before removing the query string - int fragmentPos = imageUrl.indexOf("#"); - if (fragmentPos > 0) { - imageUrl = imageUrl.substring(0, fragmentPos); - } - - String urlCopy = imageUrl; - - // remove existing query string since it may contain params that conflict with the passed ones - imageUrl = UrlUtils.removeQuery(imageUrl); - - // if this is an "mshots" url, skip photon and return it with a query that sets the width/height - if (isMshotsUrl(imageUrl)) { - return imageUrl + "?w=" + width + "&h=" + height; - } - - // strip=info removes Exif, IPTC and comment data from the output image. - String query = "?strip=info"; - - switch (quality) { - case HIGH: - query += "&quality=100"; - break; - case LOW: - query += "&quality=35"; - break; - default: // medium - query += "&quality=65"; - break; - } - - // if both width & height are passed use the "resize" param, use only "w" or "h" if just - // one of them is set - if (width > 0 && height > 0) { - query += "&resize=" + width + "," + height; - } else if (width > 0) { - query += "&w=" + width; - } else if (height > 0) { - query += "&h=" + height; - } - - if (isPrivateAtomicSite) { - try { - URL url = new URL(imageUrl); - String slug = url.getHost(); - String path = url.getPath(); - return ATOMIC_MEDIA_PROXY_URL_PREFIX + slug + ATOMIC_MEDIA_PROXY_URL_SUFFIX - + "?path=" + path + "&" + query; - } catch (MalformedURLException e) { - e.printStackTrace(); - return ""; - } - } - - // return passed url+query if it's already a photon url - if (imageUrl.contains(".wp.com")) { - if (imageUrl.contains("i0.wp.com") || imageUrl.contains("i1.wp.com") || imageUrl.contains("i2.wp.com")) { - boolean useSsl = urlCopy.indexOf("?") > 0 && urlCopy.contains("ssl=1"); - - if (useSsl) { - query += "&ssl=1"; - } - - return imageUrl + query; - } - } - - // use wordpress.com as the host if image is on wordpress.com since it supports the same - // query params and, more importantly, can handle images in private blogs - if (imageUrl.contains("wordpress.com")) { - return imageUrl + query; - } - - // must use ssl=1 parameter for https image urls - boolean useSSl = UrlUtils.isHttps(imageUrl); - if (useSSl) { - query += "&ssl=1"; - } - - return "https://i0.wp.com/" + imageUrl.substring(schemePos + 3, imageUrl.length()) + query; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java deleted file mode 100644 index 2bda40589853..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.wordpress.android.util; - -import android.os.SystemClock; - -import org.wordpress.android.util.AppLog.T; - -import java.util.ArrayList; - -/** - * forked from android.util.TimingLogger to use AppLog instead of Log + new static interface. - */ -public class ProfilingUtils { - private static ProfilingUtils sInstance; - - private String mLabel; - private ArrayList mSplits; - private ArrayList mSplitLabels; - - public static void start(String label) { - getInstance().reset(label); - } - - public static void split(String splitLabel) { - getInstance().addSplit(splitLabel); - } - - public static void dump() { - getInstance().dumpToLog(); - } - - public static void stop() { - getInstance().reset(null); - } - - private static ProfilingUtils getInstance() { - if (sInstance == null) { - sInstance = new ProfilingUtils(); - } - return sInstance; - } - - public ProfilingUtils() { - reset("init"); - } - - public void reset(String label) { - mLabel = label; - reset(); - } - - public void reset() { - if (mSplits == null) { - mSplits = new ArrayList(); - mSplitLabels = new ArrayList(); - } else { - mSplits.clear(); - mSplitLabels.clear(); - } - addSplit(null); - } - - public void addSplit(String splitLabel) { - if (mLabel == null) { - return; - } - long now = SystemClock.elapsedRealtime(); - mSplits.add(now); - mSplitLabels.add(splitLabel); - } - - public void dumpToLog() { - if (mLabel == null) { - return; - } - AppLog.d(T.PROFILING, mLabel + ": begin"); - final long first = mSplits.get(0); - long now = first; - for (int i = 1; i < mSplits.size(); i++) { - now = mSplits.get(i); - final String splitLabel = mSplitLabels.get(i); - final long prev = mSplits.get(i - 1); - AppLog.d(T.PROFILING, mLabel + ": " + (now - prev) + " ms, " + splitLabel); - } - AppLog.d(T.PROFILING, mLabel + ": end, " + (now - first) + " ms"); - } -} - diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java deleted file mode 100644 index 6bcfde06b892..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.wordpress.android.util; - -import android.app.ActivityManager; -import android.content.Context; - -public class ServiceUtils { - public static boolean isServiceRunning(Context context, Class serviceClass) { - ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { - if (serviceClass.getName().equals(service.service.getClassName())) { - return true; - } - } - return false; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java deleted file mode 100644 index 09480f156364..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.wordpress.android.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ShortcodeUtils { - public static String getVideoPressShortcodeFromId(String videoPressId) { - if (videoPressId == null || videoPressId.isEmpty()) { - return ""; - } - - return "[wpvideo " + videoPressId + "]"; - } - - public static String getVideoPressIdFromShortCode(String shortcode) { - String videoPressId = ""; - - if (shortcode != null) { - String videoPressShortcodeRegex = "^\\[wpvideo (.*)]$"; - - Pattern pattern = Pattern.compile(videoPressShortcodeRegex); - Matcher matcher = pattern.matcher(shortcode); - - if (matcher.find()) { - videoPressId = matcher.group(1); - } - } - - return videoPressId; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java deleted file mode 100644 index e9ca93d2ec7c..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.wordpress.android.util; - -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDoneException; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteStatement; - -import org.wordpress.android.util.AppLog.T; - -import java.util.ArrayList; -import java.util.List; - -public class SqlUtils { - private SqlUtils() { - throw new AssertionError(); - } - - /* - * SQLite doesn't have a boolean datatype, so booleans are stored as 0=false, 1=true - */ - public static long boolToSql(boolean value) { - return (value ? 1 : 0); - } - - public static boolean sqlToBool(int value) { - return (value != 0); - } - - public static void closeStatement(SQLiteStatement stmt) { - if (stmt != null) { - stmt.close(); - } - } - - public static void closeCursor(Cursor c) { - if (c != null && !c.isClosed()) { - c.close(); - } - } - - /* - * wrapper for DatabaseUtils.longForQuery() which returns 0 if query returns no rows - */ - public static long longForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - try { - return DatabaseUtils.longForQuery(db, query, selectionArgs); - } catch (SQLiteDoneException e) { - return 0; - } - } - - public static int intForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - long value = longForQuery(db, query, selectionArgs); - return (int) value; - } - - public static boolean boolForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - long value = longForQuery(db, query, selectionArgs); - return sqlToBool((int) value); - } - - /* - * wrapper for DatabaseUtils.stringForQuery(), returns "" if query returns no rows - */ - public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - try { - return DatabaseUtils.stringForQuery(db, query, selectionArgs); - } catch (SQLiteDoneException e) { - return ""; - } - } - - /* - * returns the number of rows in the passed table - */ - public static long getRowCount(SQLiteDatabase db, String tableName) { - return DatabaseUtils.queryNumEntries(db, tableName); - } - - /* - * removes all rows from the passed table - */ - public static void deleteAllRowsInTable(SQLiteDatabase db, String tableName) { - db.delete(tableName, null, null); - } - - /* - * drop all tables from the passed SQLiteDatabase - make sure to pass a - * writable database - */ - public static boolean dropAllTables(SQLiteDatabase db) throws SQLiteException { - if (db == null) { - return false; - } - - if (db.isReadOnly()) { - throw new SQLiteException("can't drop tables from a read-only database"); - } - - List tableNames = new ArrayList(); - Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null); - if (cursor.moveToFirst()) { - do { - String tableName = cursor.getString(0); - if (!tableName.equals("android_metadata") && !tableName.equals("sqlite_sequence")) { - tableNames.add(tableName); - } - } while (cursor.moveToNext()); - } - - db.beginTransaction(); - try { - for (String tableName : tableNames) { - db.execSQL("DROP TABLE IF EXISTS " + tableName); - } - db.setTransactionSuccessful(); - return true; - } finally { - db.endTransaction(); - closeCursor(cursor); - } - } - - /* - * Android's CursorWindow has a max size of 2MB per row which can be exceeded - * with a very large text column, causing an IllegalStateException when the - * row is read - prevent this by limiting the amount of text that's stored in - * the text column. - * https://github.com/android/platform_frameworks_base/blob/b77bc869241644a662f7e615b0b00ecb5aee373d/core/res/res - * /values/config.xml#L1268 - * https://github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/core/java - * /android/database/CursorWindow.java#L103 - */ - // Max 512K characters (a UTF-8 char is 4 bytes max, so a 512K characters string is always < 2Mb) - private static final int MAX_TEXT_LEN = 1024 * 1024 / 2; - - public static String maxSQLiteText(final String text) { - if (text.length() <= MAX_TEXT_LEN) { - return text; - } - AppLog.w(T.UTILS, "sqlite > max text exceeded, storing truncated text"); - return text.substring(0, MAX_TEXT_LEN); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java deleted file mode 100644 index ef96282eb1fb..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java +++ /dev/null @@ -1,363 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.text.TextUtils; - -import androidx.annotation.StringRes; - -import org.wordpress.android.util.AppLog.T; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -public class StringUtils { - /** - * Compare two Strings lexicographically - * Mirrors {@link org.apache.commons.lang3.StringUtils#compare(String, String)}. Use this version when there is a - * hint that the Apache lib might not be provided by the system. - * @param s1 the String to compare from - * @param s2 the String to compare to - * @return < 0, 0, > 0, if {@code s1} is respectively less, equal ou greater than {@code s2} - */ - public static int compare(String s1, String s2) { - if (s1 == s2) { - return 0; - } else if (s1 == null) { - return -1; - } else if (s2 == null) { - return 1; - } else { - return s1.compareTo(s2); - } - } - - /** - * Compare two Strings lexicographically, ignoring case differences. - * Mirrors {@link org.apache.commons.lang3.StringUtils#compareIgnoreCase(String, String)}. Use this version when - * there is a hint that the Apache lib might not be provided by the system. - * @param s1 the String to compare from - * @param s2 the String to compare to - * @return < 0, 0, > 0, if {@code s1} is respectively less, equal ou greater than {@code s2} - */ - public static int compareIgnoreCase(final String s1, final String s2) { - if (s1 == s2) { - return 0; - } - if (s1 == null) { - return -1; - } - if (s2 == null) { - return 1; - } - return s1.compareToIgnoreCase(s2); - } - - public static String[] mergeStringArrays(String[] array1, String[] array2) { - if (array1 == null || array1.length == 0) { - return array2; - } - if (array2 == null || array2.length == 0) { - return array1; - } - List array1List = Arrays.asList(array1); - List array2List = Arrays.asList(array2); - List result = new ArrayList(array1List); - List tmp = new ArrayList(array1List); - tmp.retainAll(array2List); - result.addAll(array2List); - return ((String[]) result.toArray(new String[result.size()])); - } - - public static String convertHTMLTagsForUpload(String source) { - // bold - source = source.replace("", ""); - source = source.replace("", ""); - - // italics - source = source.replace("", ""); - source = source.replace("", ""); - - return source; - } - - public static String convertHTMLTagsForDisplay(String source) { - // bold - source = source.replace("", ""); - source = source.replace("", ""); - - // italics - source = source.replace("", ""); - source = source.replace("", ""); - - return source; - } - - public static String addPTags(String source) { - String[] asploded = source.split("\n\n"); - - if (asploded.length > 0) { - StringBuilder wrappedHTML = new StringBuilder(); - for (int i = 0; i < asploded.length; i++) { - String trimmed = asploded[i].trim(); - if (trimmed.length() > 0) { - trimmed = trimmed.replace("
    ", "
    ").replace("
    ", "
    ").replace("
    \n", "
    ") - .replace("\n", "
    "); - wrappedHTML.append("

    "); - wrappedHTML.append(trimmed); - wrappedHTML.append("

    "); - } - } - return wrappedHTML.toString(); - } else { - return source; - } - } - - public static BigInteger getMd5IntHash(String input) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] messageDigest = md.digest(input.getBytes()); - BigInteger number = new BigInteger(1, messageDigest); - return number; - } catch (NoSuchAlgorithmException e) { - AppLog.e(T.UTILS, e); - return null; - } - } - - public static String getMd5Hash(String input) { - BigInteger number = getMd5IntHash(input); - String md5 = number.toString(16); - while (md5.length() < 32) { - md5 = "0" + md5; - } - return md5; - } - - /* - * nbradbury - adapted from Html.escapeHtml(), which was added in API Level 16 - * TODO: not thoroughly tested yet, so marked as private - not sure I like the way - * this replaces two spaces with " " - */ - private static String escapeHtml(final String text) { - if (text == null) { - return ""; - } - - StringBuilder out = new StringBuilder(); - int length = text.length(); - - for (int i = 0; i < length; i++) { - char c = text.charAt(i); - - if (c == '<') { - out.append("<"); - } else if (c == '>') { - out.append(">"); - } else if (c == '&') { - out.append("&"); - } else if (c > 0x7E || c < ' ') { - out.append("&#").append((int) c).append(";"); - } else if (c == ' ') { - while (i + 1 < length && text.charAt(i + 1) == ' ') { - out.append(" "); - i++; - } - - out.append(' '); - } else { - out.append(c); - } - } - - return out.toString(); - } - - /* - * returns empty string if passed string is null, otherwise returns passed string - */ - public static String notNullStr(String s) { - if (s == null) { - return ""; - } - return s; - } - - /** - * returns true if two strings are equal or two strings are null - */ - public static boolean equals(String s1, String s2) { - if (s1 == null) { - return s2 == null; - } - return s1.equals(s2); - } - - /* - * capitalizes the first letter in the passed string - based on Apache commons/lang3/StringUtils - * http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/StringUtils - * .java?revision=1497829&view=markup - */ - public static String capitalize(final String str) { - int strLen; - if (str == null || (strLen = str.length()) == 0) { - return str; - } - - char firstChar = str.charAt(0); - if (Character.isTitleCase(firstChar)) { - return str; - } - - return new StringBuilder(strLen).append(Character.toTitleCase(firstChar)).append(str.substring(1)).toString(); - } - - public static String removeTrailingSlash(final String str) { - if (TextUtils.isEmpty(str) || !str.endsWith("/")) { - return str; - } - - return str.substring(0, str.length() - 1); - } - - /* - * Wrap an image URL in a photon URL - * Check out http://developer.wordpress.com/docs/photon/ - */ - public static String getPhotonUrl(String imageUrl, int size) { - imageUrl = imageUrl.replace("http://", "").replace("https://", ""); - return "http://i0.wp.com/" + imageUrl + "?w=" + size; - } - - public static String replaceUnicodeSurrogateBlocksWithHTMLEntities(final String inputString) { - final int length = inputString.length(); - StringBuilder out = new StringBuilder(); // Used to hold the output. - for (int offset = 0; offset < length;) { - final int codepoint = inputString.codePointAt(offset); - final char current = inputString.charAt(offset); - if (Character.isHighSurrogate(current) || Character.isLowSurrogate(current)) { - if (EmoticonsUtils.WP_SMILIES_CODE_POINT_TO_TEXT.get(codepoint) != null) { - out.append(EmoticonsUtils.WP_SMILIES_CODE_POINT_TO_TEXT.get(codepoint)); - } else { - final String htmlEscapedChar = "&#x" + Integer.toHexString(codepoint) + ";"; - out.append(htmlEscapedChar); - } - } else { - out.append(current); - } - offset += Character.charCount(codepoint); - } - return out.toString(); - } - - /** - * Used to convert a language code ([lc]_[rc] where lc is language code (en, fr, es, etc...) - * and rc is region code (zh-CN, zh-HK, zh-TW, etc...) to a displayable string with the languages - * name. - * - * The input string must be between 2 and 6 characters, inclusive. An empty string is returned - * if that is not the case. - * - * If the input string is recognized by {@link Locale} the result of this method is the given - * - * @return non-null - */ - public static String getLanguageString(String languagueCode, Locale displayLocale) { - if (languagueCode == null || languagueCode.length() < 2 || languagueCode.length() > 6) { - return ""; - } - - Locale languageLocale = new Locale(languagueCode.substring(0, 2)); - return languageLocale.getDisplayLanguage(displayLocale) + languagueCode.substring(2); - } - - /** - * This method ensures that the output String has only - * valid XML unicode characters as specified by the - * XML 1.0 standard. For reference, please see - * the - * standard. This method will return an empty - * String if the input is null or empty. - * - * @param in The String whose non-valid characters we want to remove. - * @return The in String, stripped of non-valid characters. - */ - public static final String stripNonValidXMLCharacters(String in) { - StringBuilder out = new StringBuilder(); // Used to hold the output. - char current; // Used to reference the current character. - - if (in == null || ("".equals(in))) { - return ""; // vacancy test. - } - for (int i = 0; i < in.length(); i++) { - current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen. - if ((current == 0x9) - || (current == 0xA) - || (current == 0xD) - || ((current >= 0x20) && (current <= 0xD7FF)) - || ((current >= 0xE000) && (current <= 0xFFFD)) - || ((current >= 0x10000) && (current <= 0x10FFFF))) { - out.append(current); - } - } - return out.toString(); - } - - /* - * simple wrapper for Integer.valueOf(string) so caller doesn't need to catch NumberFormatException - */ - public static int stringToInt(String s) { - return stringToInt(s, 0); - } - - public static int stringToInt(String s, int defaultValue) { - if (s == null) { - return defaultValue; - } - try { - return Integer.valueOf(s); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public static long stringToLong(String s) { - return stringToLong(s, 0L); - } - - public static long stringToLong(String s, long defaultValue) { - if (s == null) { - return defaultValue; - } - try { - return Long.valueOf(s); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * Formats the string for the given quantity, using the given arguments. - * We need this because our translation platform doesn't support Android plurals. - * - * @param zero The desired string identifier to get when quantity is exactly 0 - * @param one The desired string identifier to get when quantity is exactly 1 - * @param other The desired string identifier to get when quantity is not (0 or 1) - * @param quantity The number used to get the correct string - */ - public static String getQuantityString(Context context, @StringRes int zero, @StringRes int one, - @StringRes int other, int quantity) { - if (quantity == 0) { - return context.getString(zero); - } - if (quantity == 1) { - return context.getString(one); - } - return String.format(context.getString(other), quantity); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java deleted file mode 100644 index e3fee7fc33b7..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -public class SystemServiceFactory { - private static SystemServiceFactoryAbstract sFactory; - - public static Object get(Context context, String name) { - if (sFactory == null) { - sFactory = new SystemServiceFactoryDefault(); - } - return sFactory.get(context, name); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java deleted file mode 100644 index 7b86f6631062..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -public interface SystemServiceFactoryAbstract { - Object get(Context context, String name); -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java deleted file mode 100644 index eb488dde9bf4..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -public class SystemServiceFactoryDefault implements SystemServiceFactoryAbstract { - public Object get(Context context, String name) { - return context.getSystemService(name); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java deleted file mode 100644 index 470867364b8c..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.view.Gravity; -import android.widget.Toast; - -/** - * Provides a simplified way to show toast messages without having to create the toast, set the - * desired gravity, etc. - */ -public class ToastUtils { - public enum Duration { - SHORT, LONG - } - - private ToastUtils() { - throw new AssertionError(); - } - - public static Toast showToast(Context context, int stringResId) { - return showToast(context, stringResId, Duration.SHORT); - } - - public static Toast showToast(Context context, int stringResId, Duration duration) { - return showToast(context, context.getString(stringResId), duration); - } - - public static Toast showToast(Context context, String text) { - return showToast(context, text, Duration.SHORT); - } - - public static Toast showToast(Context context, String text, Duration duration) { - return showToast(context, text, duration, Gravity.CENTER); - } - - public static Toast showToast(Context context, String text, Duration duration, int gravity) { - return showToast(context, text, duration, gravity, 0, 0); - } - - public static Toast showToast( - Context context, - String text, - Duration duration, - int gravity, - int xOffset, - int yOffset) { - Toast toast = Toast.makeText(context, text, - (duration == Duration.SHORT ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG)); - toast.setGravity(gravity, xOffset, yOffset); - toast.show(); - return toast; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java deleted file mode 100644 index 0068ac9d4d8b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java +++ /dev/null @@ -1,318 +0,0 @@ -package org.wordpress.android.util; - -import android.net.Uri; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; -import android.webkit.URLUtil; - -import androidx.annotation.Nullable; - -import org.wordpress.android.util.AppLog.T; - -import java.io.UnsupportedEncodingException; -import java.net.IDN; -import java.net.URI; -import java.net.URL; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import static org.wordpress.android.util.PhotonUtils.ATOMIC_MEDIA_PROXY_URL_PREFIX; -import static org.wordpress.android.util.PhotonUtils.ATOMIC_MEDIA_PROXY_URL_SUFFIX; - -public class UrlUtils { - public static String urlEncode(final String text) { - try { - return URLEncoder.encode(text, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return text; - } - } - - public static String urlDecode(final String text) { - try { - return URLDecoder.decode(text, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return text; - } - } - - /** - * @param urlString url to get host from - * @return host of uri if available. Empty string otherwise. - */ - public static String getHost(final String urlString) { - if (urlString != null) { - Uri uri = Uri.parse(urlString); - if (uri.getHost() != null) { - return uri.getHost(); - } - } - return ""; - } - - public static boolean isContentUri(String uri) { - return "content".equals(Uri.parse(uri).getScheme()); - } - - /** - * Convert IDN names to punycode if necessary - */ - public static String convertUrlToPunycodeIfNeeded(String url) { - if (!Charset.forName("US-ASCII").newEncoder().canEncode(url)) { - if (url.toLowerCase(Locale.ROOT).startsWith("http://")) { - url = "http://" + IDN.toASCII(url.substring(7), IDN.ALLOW_UNASSIGNED); - } else if (url.toLowerCase(Locale.ROOT).startsWith("https://")) { - url = "https://" + IDN.toASCII(url.substring(8), IDN.ALLOW_UNASSIGNED); - } else { - url = IDN.toASCII(url, IDN.ALLOW_UNASSIGNED); - } - } - return url; - } - - /** - * Remove leading double slash, and inherit protocol scheme - */ - public static String removeLeadingDoubleSlash(String url, String scheme) { - if (url != null && url.startsWith("//")) { - url = url.substring(2); - if (scheme != null) { - if (scheme.endsWith("://")) { - url = scheme + url; - } else { - AppLog.e(T.UTILS, "Invalid scheme used: " + scheme); - } - } - } - return url; - } - - /** - * Add scheme prefix to an URL. This method must be called on all user entered or server fetched URLs to ensure - * http client will work as expected. - * - * @param url url entered by the user or fetched from a server - * @param addHttps true and the url is not starting with http://, it will make the url starts with https:// - * @return url prefixed by http:// or https:// - */ - public static String addUrlSchemeIfNeeded(String url, boolean addHttps) { - if (url == null) { - return null; - } - - // Remove leading double slash (eg. // example.com), needed for some wporg instances configured to - // switch between http or https - url = removeLeadingDoubleSlash(url, (addHttps ? "https" : "http") + "://"); - - // If the URL is a valid http or https URL, we're good to go - if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) { - return url; - } - - // Else, remove the old scheme and prefix it by https:// or http:// - return (addHttps ? "https" : "http") + "://" + removeScheme(url); - } - - /** - * normalizes a URL, primarily for comparison purposes, for example so that - * normalizeUrl("http://google.com/") = normalizeUrl("http://google.com") - */ - public static String normalizeUrl(final String urlString) { - if (urlString == null) { - return null; - } - - // this routine is called from some performance-critical code and creating a URI from a string - // is slow, so skip it when possible - if we know it's not a relative path (and 99.9% of the - // time it won't be for our purposes) then we can normalize it without java.net.URI.normalize() - if (urlString.startsWith("http") - && !urlString.contains("build/intermediates/exploded-aar/org.wordpress/graphview/3.1.1")) { - // return without a trailing slash - if (urlString.endsWith("/")) { - return urlString.substring(0, urlString.length() - 1); - } - return urlString; - } - - // url is relative, so fall back to using slower java.net.URI normalization - try { - URI uri = URI.create(urlString); - return uri.normalize().toString(); - } catch (IllegalArgumentException e) { - return urlString; - } - } - - - /** - * returns the passed url without the scheme - */ - public static String removeScheme(final String urlString) { - if (urlString == null) { - return null; - } - - int doubleslash = urlString.indexOf("//"); - if (doubleslash == -1) { - doubleslash = 0; - } else { - doubleslash += 2; - } - - return urlString.substring(doubleslash, urlString.length()); - } - - /** - * returns the passed url without the query parameters - */ - public static String removeQuery(final String urlString) { - if (urlString == null) { - return null; - } - return Uri.parse(urlString).buildUpon().clearQuery().toString(); - } - - /** - * returns true if passed url is https: - */ - public static boolean isHttps(final String urlString) { - return (urlString != null && urlString.startsWith("https:")); - } - - public static boolean isHttps(URL url) { - return url != null && "https".equals(url.getProtocol()); - } - - public static boolean isHttps(URI uri) { - if (uri == null) { - return false; - } - - String protocol = uri.getScheme(); - return protocol != null && protocol.equals("https"); - } - - /** - * returns https: version of passed http: url - */ - public static String makeHttps(final String urlString) { - if (urlString == null || !urlString.startsWith("http:")) { - return urlString; - } - return "https:" + urlString.substring(5, urlString.length()); - } - - /** - * see http://stackoverflow.com/a/8591230/1673548 - */ - public static String getUrlMimeType(final String urlString) { - if (urlString == null) { - return null; - } - - String extension = MimeTypeMap.getFileExtensionFromUrl(urlString); - if (extension == null) { - return null; - } - - MimeTypeMap mime = MimeTypeMap.getSingleton(); - String mimeType = mime.getMimeTypeFromExtension(extension); - if (mimeType == null) { - return null; - } - - return mimeType; - } - - /** - * returns false if the url is not valid or if the url host is null, else true - */ - public static boolean isValidUrlAndHostNotNull(String url) { - try { - URI uri = URI.create(url); - if (uri.getHost() == null) { - return false; - } - } catch (IllegalArgumentException e) { - return false; - } - return true; - } - - // returns true if the passed url is for an image - public static boolean isImageUrl(String url) { - if (TextUtils.isEmpty(url)) { - return false; - } - - String cleanedUrl = removeQuery(url.toLowerCase(Locale.ROOT)); - - if (isAtomicImageProxyUrl(cleanedUrl)) { - return true; - } - - return cleanedUrl.endsWith("jpg") || cleanedUrl.endsWith("jpeg") - || cleanedUrl.endsWith("gif") || cleanedUrl.endsWith("png"); - } - - public static @Nullable String getPageJumpOrNull(String url) { - if (TextUtils.isEmpty(url)) { - return null; - } - - if (url.contains("#") - && url.indexOf("#") < url.length() - 1 - && url.split("#").length == 2) { - return url.substring(url.indexOf('#') + 1); - } - - return null; - } - - private static boolean isAtomicImageProxyUrl(String urlString) { - return urlString.startsWith(ATOMIC_MEDIA_PROXY_URL_PREFIX) && urlString.endsWith(ATOMIC_MEDIA_PROXY_URL_SUFFIX); - } - - public static String appendUrlParameter(String url, String paramName, String paramValue) { - Map parameters = new HashMap<>(); - parameters.put(paramName, paramValue); - return appendUrlParameters(url, parameters); - } - - public static String appendUrlParameters(String url, Map parameters) { - Uri.Builder uriBuilder = Uri.parse(url).buildUpon(); - for (Map.Entry parameter : parameters.entrySet()) { - uriBuilder.appendQueryParameter(parameter.getKey(), parameter.getValue()); - } - return uriBuilder.build().toString(); - } - - /** - * Extracts the subdomain from a domain string. - * @param domain A domain is expected. Protocol is optional - * @return The subdomain or an empty string. - */ - public static String extractSubDomain(String domain) { - String str = UrlUtils.addUrlSchemeIfNeeded(domain, false); - String host = UrlUtils.getHost(str); - if (host.length() > 0) { - String[] parts = host.split("\\."); - if (parts.length > 1) { // There should be at least 2 dots for there to be a subdomain. - return parts[0]; - } - } - return ""; - } - - public static String removeXmlrpcSuffix(String siteAddress) { - if (siteAddress.toLowerCase(Locale.ROOT).endsWith("/xmlrpc.php")) { - return siteAddress.substring(0, siteAddress.lastIndexOf("xmlrpc.php")); - } else { - return siteAddress; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java deleted file mode 100644 index 8ccb5c4a51c8..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wordpress.android.util; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.content.Context; -import android.util.Patterns; - -import org.wordpress.android.util.AppLog.T; - -import java.util.regex.Pattern; - -public class UserEmailUtils { - /** - * Get primary account and return its name if it matches the email address pattern. - * - * @return primary account email address if it can be found or empty string else. - */ - public static String getPrimaryEmail(Context context) { - try { - AccountManager accountManager = AccountManager.get(context); - if (accountManager == null) { - return ""; - } - Account[] accounts = accountManager.getAccounts(); - Pattern emailPattern = Patterns.EMAIL_ADDRESS; - for (Account account : accounts) { - // make sure account.name is an email address before adding to the list - if (emailPattern.matcher(account.name).matches()) { - return account.name; - } - } - return ""; - } catch (SecurityException e) { - // exception will occur if app doesn't have GET_ACCOUNTS permission - AppLog.e(T.UTILS, "SecurityException - missing GET_ACCOUNTS permission"); - return ""; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java deleted file mode 100644 index 38ed56a7e744..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.wordpress.android.util; - - -import android.content.Context; -import android.media.MediaMetadataRetriever; -import android.net.Uri; - -import java.io.File; - -public class VideoUtils { - public static long getVideoDurationMS(Context context, File file) { - if (context == null || file == null) { - AppLog.e(AppLog.T.MEDIA, "context and file can't be null."); - return 0L; - } - return getVideoDurationMS(context, Uri.fromFile(file)); - } - - public static long getVideoDurationMS(Context context, Uri videoUri) { - if (context == null || videoUri == null) { - AppLog.e(AppLog.T.MEDIA, "context and videoUri can't be null."); - return 0L; - } - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - try { - retriever.setDataSource(context, videoUri); - } catch (IllegalArgumentException | SecurityException e) { - AppLog.e(AppLog.T.MEDIA, "Can't read duration of the video.", e); - return 0L; - } catch (RuntimeException e) { - // Ref: https://github.com/wordpress-mobile/WordPress-Android/issues/5431 - AppLog.e(AppLog.T.MEDIA, - "Can't read duration of the video due to a Runtime Exception happened setting the datasource", e); - return 0L; - } - - String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); - if (time == null) { - return 0L; - } - return Long.parseLong(time); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java deleted file mode 100644 index 9f7a11eeb6e9..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.wordpress.android.util; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Outline; -import android.os.Build; -import android.view.View; -import android.view.ViewOutlineProvider; - -import androidx.annotation.AttrRes; -import androidx.annotation.NonNull; -import androidx.annotation.StyleRes; -import androidx.core.view.ViewCompat; - -import java.util.concurrent.atomic.AtomicInteger; - -public class ViewUtils { - /** - * Generate a value suitable for use in {@link View#setId(int)}. - * This value will not collide with ID values generated at build time by aapt for R.id. - * Uses the native implementation if API 17 or above, otherwise uses a copied implementation. - * - * @return a generated ID value - */ - public static int generateViewId() { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - return View.generateViewId(); - } else { - return copiedGenerateViewId(); - } - } - - private static final AtomicInteger NEXT_GENERATED_ID = new AtomicInteger(1); - - /** - * Copied from {@link View#generateViewId()} - * Generate a value suitable for use in {@link View#setId(int)}. - * This value will not collide with ID values generated at build time by aapt for R.id. - * - * @return a generated ID value - */ - private static int copiedGenerateViewId() { - for (;;) { - final int result = NEXT_GENERATED_ID.get(); - // aapt-generated IDs have the high byte nonzero; clamp to the range under that. - int newValue = result + 1; - if (newValue > 0x00FFFFFF) { - newValue = 1; // Roll over to 1, not 0. - } - if (NEXT_GENERATED_ID.compareAndSet(result, newValue)) { - return result; - } - } - } - - public static void setButtonBackgroundColor(Context context, View button, @StyleRes int styleId, - @AttrRes int colorAttribute) { - TypedArray a = context.obtainStyledAttributes(styleId, new int[]{colorAttribute}); - ColorStateList color = a.getColorStateList(0); - a.recycle(); - ViewCompat.setBackgroundTintList(button, color); - } - - /** - * adds an inset circular shadow outline the passed view (Lollipop+ only) - note that - * the view should have its elevation set prior to calling this - */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public static void addCircularShadowOutline(@NonNull View view) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - view.setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, view.getWidth(), view.getHeight()); - } - }); - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java deleted file mode 100644 index 6247957819dc..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.wordpress.android.util; - -import android.os.Build; -import android.webkit.CookieManager; -import android.webkit.ValueCallback; - -public class WebViewUtils { - public static void clearCookiesAsync() { - clearCookiesAsync(null); - } - - public static void clearCookiesAsync(ValueCallback callback) { - CookieManager cookieManager = CookieManager.getInstance(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - cookieManager.removeAllCookies(callback); - } else { - //noinspection deprecation - cookieManager.removeAllCookie(); - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java deleted file mode 100644 index 1cd723331330..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wordpress.android.util.helpers; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class Debouncer { - private final ScheduledExecutorService mScheduler = Executors.newSingleThreadScheduledExecutor(); - private final ConcurrentHashMap> mDelayedMap = new ConcurrentHashMap<>(); - - /** - * Debounces {@code callable} by {@code delay}, i.e., schedules it to be executed after {@code delay}, - * or cancels its execution if the method is called with the same key within the {@code delay} again. - */ - public void debounce(final Object key, final Runnable runnable, long delay, TimeUnit unit) { - if (mScheduler.isShutdown()) { - return; - } - final Future prev = mDelayedMap.put(key, mScheduler.schedule(new Runnable() { - @Override - public void run() { - try { - runnable.run(); - } finally { - mDelayedMap.remove(key); - } - } - }, delay, unit)); - if (prev != null) { - prev.cancel(true); - } - } - - public void shutdown() { - mScheduler.shutdownNow(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java deleted file mode 100644 index 914373c8f2e1..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.preference.PreferenceManager; -import android.view.View; -import android.widget.ListView; - -public class ListScrollPositionManager { - private int mSelectedPosition; - private int mListViewScrollStateIndex; - private int mListViewScrollStateOffset; - private ListView mListView; - private boolean mSetSelection; - - public ListScrollPositionManager(ListView listView, boolean setSelection) { - mListView = listView; - mSetSelection = setSelection; - } - - public void saveScrollOffset() { - mListViewScrollStateIndex = mListView.getFirstVisiblePosition(); - View view = mListView.getChildAt(0); - mListViewScrollStateOffset = 0; - if (view != null) { - mListViewScrollStateOffset = view.getTop(); - } - if (mSetSelection) { - mSelectedPosition = mListView.getCheckedItemPosition(); - } - } - - public void restoreScrollOffset() { - mListView.setSelectionFromTop(mListViewScrollStateIndex, mListViewScrollStateOffset); - if (mSetSelection) { - mListView.setItemChecked(mSelectedPosition, true); - } - } - - public void saveToPreferences(Context context, String uniqueId) { - saveScrollOffset(); - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - Editor editor = settings.edit(); - editor.putInt("scroll-position-manager-index-" + uniqueId, mListViewScrollStateIndex); - editor.putInt("scroll-position-manager-offset-" + uniqueId, mListViewScrollStateOffset); - editor.putInt("scroll-position-manager-selected-position-" + uniqueId, mSelectedPosition); - editor.apply(); - } - - public void restoreFromPreferences(Context context, String uniqueId) { - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - mListViewScrollStateIndex = settings.getInt("scroll-position-manager-index-" + uniqueId, 0); - mListViewScrollStateOffset = settings.getInt("scroll-position-manager-offset-" + uniqueId, 0); - mSelectedPosition = settings.getInt("scroll-position-manager-selected-position-" + uniqueId, 0); - restoreScrollOffset(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java deleted file mode 100644 index 98d815802ed2..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java +++ /dev/null @@ -1,348 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import org.wordpress.android.util.MapUtils; -import org.wordpress.android.util.StringUtils; -import org.wordpress.android.util.UrlUtils; - -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -public class MediaFile { - protected int mId; - protected long mPostID; - protected String mFilePath = null; // path of the file into disk - protected String mFileName = null; // name of the file into the server - protected String mTitle = null; - protected String mDescription = null; - protected String mCaption = null; - protected int mHorizontalAlignment; // 0 = none, 1 = left, 2 = center, 3 = right - protected boolean mVerticalAligment = false; // false = bottom, true = top - protected int mWidth = 500; - protected int mHeight; - protected String mMimeType = ""; - protected String mVideoPressShortCode = null; - protected boolean mFeatured = false; - protected boolean mIsVideo = false; - protected boolean mFeaturedInPost; - protected String mFileURL = null; // url of the file to download - protected String mThumbnailURL = null; // url of the thumbnail to download - private String mBlogId; - private long mDateCreatedGmt; - private String mUploadState = null; - private String mMediaId; - - private static final String VIDEOPRESS_SHORTCODE_ID = "videopress_shortcode"; - - public MediaFile(String blogId, Map resultMap, boolean isWPCom) { - setBlogId(blogId); - setMediaId(MapUtils.getMapStr(resultMap, "attachment_id")); - setPostID(MapUtils.getMapLong(resultMap, "parent")); - setTitle(MapUtils.getMapStr(resultMap, "title")); - setCaption(MapUtils.getMapStr(resultMap, "caption")); - setDescription(MapUtils.getMapStr(resultMap, "description")); - setVideoPressShortCode(MapUtils.getMapStr(resultMap, VIDEOPRESS_SHORTCODE_ID)); - - // get the file name from the link - String link = MapUtils.getMapStr(resultMap, "link"); - setFileName(new String(link).replaceAll("^.*/([A-Za-z0-9_-]+)\\.\\w+$", "$1")); - - String fileType = new String(link).replaceAll(".*\\.(\\w+)$", "$1").toLowerCase(Locale.ROOT); - String fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileType); - setMimeType(fileMimeType); - - // make the file urls be https://... so that we can get these images with oauth when the blogs are private - // assume no https for images in self-hosted blogs - String fileUrl = MapUtils.getMapStr(resultMap, "link"); - if (isWPCom) { - fileUrl = fileUrl.replace("http:", "https:"); - } - setFileURL(fileUrl); - - String thumbnailURL = MapUtils.getMapStr(resultMap, "thumbnail"); - if (thumbnailURL.startsWith("http")) { - if (isWPCom) { - thumbnailURL = thumbnailURL.replace("http:", "https:"); - } - setThumbnailURL(thumbnailURL); - } - - Date date = MapUtils.getMapDate(resultMap, "date_created_gmt"); - if (date != null) { - setDateCreatedGMT(date.getTime()); - } - - Object meta = resultMap.get("metadata"); - if (meta != null && meta instanceof Map) { - Map metadata = (Map) meta; - setWidth(MapUtils.getMapInt(metadata, "width")); - setHeight(MapUtils.getMapInt(metadata, "height")); - } - } - - public MediaFile() { - // default constructor - } - - public MediaFile(MediaFile mediaFile) { - this.mId = mediaFile.mId; - this.mPostID = mediaFile.mPostID; - this.mFilePath = mediaFile.mFilePath; - this.mFileName = mediaFile.mFileName; - this.mTitle = mediaFile.mTitle; - this.mDescription = mediaFile.mDescription; - this.mCaption = mediaFile.mCaption; - this.mHorizontalAlignment = mediaFile.mHorizontalAlignment; - this.mVerticalAligment = mediaFile.mVerticalAligment; - this.mWidth = mediaFile.mWidth; - this.mHeight = mediaFile.mHeight; - this.mMimeType = mediaFile.mMimeType; - this.mVideoPressShortCode = mediaFile.mVideoPressShortCode; - this.mFeatured = mediaFile.mFeatured; - this.mIsVideo = mediaFile.mIsVideo; - this.mFeaturedInPost = mediaFile.mFeaturedInPost; - this.mFileURL = mediaFile.mFileURL; - this.mThumbnailURL = mediaFile.mThumbnailURL; - this.mBlogId = mediaFile.mBlogId; - this.mDateCreatedGmt = mediaFile.mDateCreatedGmt; - this.mUploadState = mediaFile.mUploadState; - this.mMediaId = mediaFile.mMediaId; - } - - public int getId() { - return mId; - } - - public void setId(int id) { - this.mId = id; - } - - public String getMediaId() { - return mMediaId; - } - - public void setMediaId(String id) { - mMediaId = id; - } - - public boolean isFeatured() { - return mFeatured; - } - - public void setFeatured(boolean featured) { - this.mFeatured = featured; - } - - public long getPostID() { - return mPostID; - } - - public void setPostID(long postID) { - this.mPostID = postID; - } - - public String getFilePath() { - return mFilePath; - } - - public void setFilePath(String filePath) { - this.mFilePath = filePath; - } - - public String getTitle() { - return mTitle; - } - - public void setTitle(String title) { - this.mTitle = title; - } - - public String getCaption() { - return mCaption; - } - - public void setCaption(String caption) { - this.mCaption = caption; - } - - public String getDescription() { - return mDescription; - } - - public void setDescription(String description) { - this.mDescription = description; - } - - public String getFileURL() { - return mFileURL; - } - - public void setFileURL(String fileURL) { - this.mFileURL = fileURL; - } - - public String getThumbnailURL() { - return mThumbnailURL; - } - - public void setThumbnailURL(String thumbnailURL) { - this.mThumbnailURL = thumbnailURL; - } - - public boolean isVerticalAlignmentOnTop() { - return mVerticalAligment; - } - - public void setVerticalAlignmentOnTop(boolean verticalAligment) { - this.mVerticalAligment = verticalAligment; - } - - public int getWidth() { - return mWidth; - } - - public void setWidth(int width) { - this.mWidth = width; - } - - public int getHeight() { - return mHeight; - } - - public void setHeight(int height) { - this.mHeight = height; - } - - public String getFileName() { - return mFileName; - } - - public void setFileName(String fileName) { - this.mFileName = fileName; - } - - public String getMimeType() { - return StringUtils.notNullStr(mMimeType); - } - - public void setMimeType(String type) { - mMimeType = StringUtils.notNullStr(type); - } - - public String getVideoPressShortCode() { - return mVideoPressShortCode; - } - - public void setVideoPressShortCode(String videoPressShortCode) { - this.mVideoPressShortCode = videoPressShortCode; - } - - public int getHorizontalAlignment() { - return mHorizontalAlignment; - } - - public void setHorizontalAlignment(int horizontalAlignment) { - this.mHorizontalAlignment = horizontalAlignment; - } - - public boolean isVideo() { - return mIsVideo; - } - - public void setVideo(boolean isVideo) { - this.mIsVideo = isVideo; - } - - public boolean isFeaturedInPost() { - return mFeaturedInPost; - } - - public void setFeaturedInPost(boolean featuredInPost) { - this.mFeaturedInPost = featuredInPost; - } - - public String getBlogId() { - return mBlogId; - } - - public void setBlogId(String blogId) { - this.mBlogId = blogId; - } - - public void setDateCreatedGMT(long dateCreatedGmt) { - this.mDateCreatedGmt = dateCreatedGmt; - } - - public long getDateCreatedGMT() { - return mDateCreatedGmt; - } - - public void setUploadState(String uploadState) { - this.mUploadState = uploadState; - } - - public String getUploadState() { - return mUploadState; - } - - /** - * Outputs the Html for an image - * If a fullSizeUrl exists, a link will be created to it from the resizedPictureUrl - */ - public String getImageHtmlForUrls(String fullSizeUrl, String resizedPictureURL, boolean shouldAddImageWidthCSS) { - String alignment = ""; - switch (getHorizontalAlignment()) { - case 0: - alignment = "alignnone"; - break; - case 1: - alignment = "alignleft"; - break; - case 2: - alignment = "aligncenter"; - break; - case 3: - alignment = "alignright"; - break; - } - - String alignmentCSS = "class=\"" + alignment + " size-full\" "; - - if (shouldAddImageWidthCSS) { - alignmentCSS += "style=\"max-width: " + getWidth() + "px\" "; - } - - // Check if we uploaded a featured picture that is not added to the Post content (normal case) - if ((fullSizeUrl != null && fullSizeUrl.equalsIgnoreCase("")) - || (resizedPictureURL != null && resizedPictureURL.equalsIgnoreCase(""))) { - return ""; // Not featured in Post. Do not add to the content. - } - - if (fullSizeUrl == null && resizedPictureURL != null) { - fullSizeUrl = resizedPictureURL; - } else if (fullSizeUrl != null && resizedPictureURL == null) { - resizedPictureURL = fullSizeUrl; - } - - String mediaTitle = StringUtils.notNullStr(getTitle()); - - String content = String.format(Locale.US, "\"image\"", - fullSizeUrl, mediaTitle, alignmentCSS, resizedPictureURL); - - if (!TextUtils.isEmpty(getCaption())) { - content = String.format(Locale.US, "[caption id=\"\" align=\"%s\" width=\"%d\"]%s%s[/caption]", - alignment, getWidth(), content, TextUtils.htmlEncode(getCaption())); - } - - return content; - } - - public String getAttachmentPageURL(String siteUrl) { - siteUrl = UrlUtils.makeHttps(siteUrl); - String attachmentPageUrl = UrlUtils.appendUrlParameter(siteUrl, "p", mMediaId); - return attachmentPageUrl; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java deleted file mode 100644 index ea13f012b699..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.wordpress.android.util.helpers; - -import java.io.Serializable; -import java.util.ArrayList; - -/** - * A model representing a Media Gallery. - * A unique id is not used on the website, but only in this app. - * It is used to uniquely determining the instance of the object, as it is - * passed between post and media gallery editor. - */ -public class MediaGallery implements Serializable { - private static final long serialVersionUID = 2359176987182027508L; - - private long mUniqueId; - private boolean mIsRandom; - private String mType; - private int mNumColumns; - private ArrayList mIds; - - public MediaGallery(boolean isRandom, String type, int numColumns, ArrayList ids) { - mIsRandom = isRandom; - mType = type; - mNumColumns = numColumns; - mIds = ids; - mUniqueId = System.currentTimeMillis(); - } - - public MediaGallery() { - mIsRandom = false; - mType = ""; - mNumColumns = 3; - mIds = new ArrayList<>(); - mUniqueId = System.currentTimeMillis(); - } - - public boolean isRandom() { - return mIsRandom; - } - - public void setRandom(boolean isRandom) { - this.mIsRandom = isRandom; - } - - public String getType() { - return mType; - } - - public void setType(String type) { - this.mType = type; - } - - public int getNumColumns() { - return mNumColumns; - } - - public void setNumColumns(int numColumns) { - this.mNumColumns = numColumns; - } - - public ArrayList getIds() { - return mIds; - } - - public String getIdsStr() { - String idsStr = ""; - if (mIds.size() > 0) { - for (Long id : mIds) { - idsStr += id + ","; - } - idsStr = idsStr.substring(0, idsStr.length() - 1); - } - return idsStr; - } - - public void setIds(ArrayList ids) { - this.mIds = ids; - } - - /** - * An id to uniquely identify a media gallery object, so that the same object can be edited in the post editor - */ - public long getUniqueId() { - return mUniqueId; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java deleted file mode 100644 index 588b98141c27..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.content.Context; -import android.text.style.ImageSpan; - -public class MediaGalleryImageSpan extends ImageSpan { - private MediaGallery mMediaGallery; - - public MediaGalleryImageSpan(Context context, MediaGallery mediaGallery, int placeHolder) { - super(context, placeHolder); - setMediaGallery(mediaGallery); - } - - public MediaGallery getMediaGallery() { - return mMediaGallery; - } - - public void setMediaGallery(MediaGallery mediaGallery) { - this.mMediaGallery = mediaGallery; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java deleted file mode 100644 index 93021257449d..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.os.Bundle; -import android.view.View; - -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - - -public class RecyclerViewScrollPositionManager { - private static final String RV_POSITION = "rv_position"; - private static final String RV_OFFSET = "rv_offset"; - private int mRVPosition = 0; - private int mRVOffset = 0; - - public void onSaveInstanceState(Bundle outState, RecyclerView recyclerView) { - // make sure the layout manager is assigned to the RecyclerView - // also take into account this needs to be a LinearLayoutManager, otherwise ClassCastException occurs - outState.putInt(RV_POSITION, - ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition()); - View firstItemView = recyclerView.getChildAt(0); - int offset = (firstItemView == null) ? 0 : (firstItemView.getTop() - recyclerView.getPaddingTop()); - outState.putInt(RV_OFFSET, offset); - } - - public void onRestoreInstanceState(Bundle savedInstanceState) { - mRVPosition = savedInstanceState.getInt(RV_POSITION); - mRVOffset = savedInstanceState.getInt(RV_OFFSET); - } - - public void restoreScrollOffset(RecyclerView recyclerView) { - if (mRVPosition > 0 || mRVOffset > 0) { - ((LinearLayoutManager) recyclerView.getLayoutManager()) - .scrollToPositionWithOffset(mRVPosition, mRVOffset); - } - mRVPosition = 0; - mRVOffset = 0; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java deleted file mode 100644 index 14cc5efef9a8..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.content.Context; - -import androidx.annotation.ColorInt; -import androidx.annotation.ColorRes; -import androidx.core.content.ContextCompat; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener; - -import org.wordpress.android.util.widgets.CustomSwipeRefreshLayout; - -public class SwipeToRefreshHelper implements OnRefreshListener { - private CustomSwipeRefreshLayout mSwipeRefreshLayout; - private RefreshListener mRefreshListener; - private boolean mRefreshing; - - public interface RefreshListener { - void onRefreshStarted(); - } - - /** - * Helps {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by passing the - * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color. - * - * @param context {@link Context} in which this layout is used. - * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents - * of a view via a vertical swipe gesture. - * @param listener {@link RefreshListener} notified when a refresh is triggered - * via the swipe gesture. - * - * @deprecated Use {@link #SwipeToRefreshHelper(CustomSwipeRefreshLayout, RefreshListener, int, int...)} instead. - */ - @Deprecated - public SwipeToRefreshHelper(Context context, CustomSwipeRefreshLayout swipeRefreshLayout, - RefreshListener listener) { - init(swipeRefreshLayout, listener, ContextCompat.getColor(context, android.R.color.white), - android.R.color.holo_blue_dark); - } - - /** - * Helps {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by passing the - * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color(s). - * - * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents - * of a view via a vertical swipe gesture. - * @param listener {@link RefreshListener} notified when a refresh is triggered - * via the swipe gesture. - * @param progressAnimationColors Comma-separated color resource integers used in the progress - * animation. The first color will also be the color of the bar - * that grows in response to a user swipe gesture. - */ - public SwipeToRefreshHelper(CustomSwipeRefreshLayout swipeRefreshLayout, RefreshListener listener, - @ColorInt int backgroundColor, - @ColorRes int... progressAnimationColors) { - init(swipeRefreshLayout, listener, backgroundColor, progressAnimationColors); - } - - /** - * Initializes {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by assigning - * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color(s). - * - * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents - * of a view via a vertical swipe gesture. - * @param listener {@link RefreshListener} notified when a refresh is triggered - * via the swipe gesture. - * @param progressAnimationColors Comma-separated color resource integers used in the progress - * animation. The first color will also be the color of the bar - * that grows in response to a user swipe gesture. - */ - public void init(CustomSwipeRefreshLayout swipeRefreshLayout, RefreshListener listener, - @ColorInt int backgroundColor, - @ColorRes int... progressAnimationColors) { - mRefreshListener = listener; - mSwipeRefreshLayout = swipeRefreshLayout; - mSwipeRefreshLayout.setOnRefreshListener(this); - mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(backgroundColor); - mSwipeRefreshLayout.setColorSchemeResources(progressAnimationColors); - } - - public void setRefreshing(boolean refreshing) { - mRefreshing = refreshing; - // Delayed refresh, it fixes https://code.google.com/p/android/issues/detail?id=77712 - // 50ms seems a good compromise (always worked during tests) and fast enough so user can't notice the delay - if (refreshing) { - mSwipeRefreshLayout.postDelayed(new Runnable() { - @Override - public void run() { - // use mRefreshing so if the refresh takes less than 50ms, loading indicator won't show up. - mSwipeRefreshLayout.setRefreshing(mRefreshing); - } - }, 50); - } else { - mSwipeRefreshLayout.setRefreshing(false); - } - } - - public boolean isRefreshing() { - return mSwipeRefreshLayout.isRefreshing(); - } - - @Override - public void onRefresh() { - mRefreshListener.onRefreshStarted(); - } - - public void setEnabled(boolean enabled) { - mSwipeRefreshLayout.setEnabled(enabled); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java deleted file mode 100644 index 5e0da1f6b2b4..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.wordpress.android.util.helpers; - -//See: http://stackoverflow.com/a/11024200 -public class Version implements Comparable { - private String mVersion; - - public final String get() { - return this.mVersion; - } - - public Version(String version) { - if (version == null) { - throw new IllegalArgumentException("Version can not be null"); - } - if (!version.matches("[0-9]+(\\.[0-9]+)*")) { - throw new IllegalArgumentException("Invalid version format"); - } - this.mVersion = version; - } - - @Override public int compareTo(Version that) { - if (that == null) { - return 1; - } - String[] thisParts = this.get().split("\\."); - String[] thatParts = that.get().split("\\."); - int length = Math.max(thisParts.length, thatParts.length); - for (int i = 0; i < length; i++) { - int thisPart = i < thisParts.length - ? Integer.parseInt(thisParts[i]) : 0; - int thatPart = i < thatParts.length - ? Integer.parseInt(thatParts[i]) : 0; - if (thisPart < thatPart) { - return -1; - } - if (thisPart > thatPart) { - return 1; - } - } - return 0; - } - - @Override public boolean equals(Object that) { - if (this == that) { - return true; - } - if (that == null) { - return false; - } - if (this.getClass() != that.getClass()) { - return false; - } - return this.compareTo((Version) that) == 0; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java deleted file mode 100644 index e8d21791b454..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.text.Editable; -import android.text.Html; -import android.text.style.BulletSpan; -import android.text.style.LeadingMarginSpan; - -import org.xml.sax.XMLReader; - -import java.util.ArrayList; -import java.util.List; - -/** - * Handle tags that the Html class doesn't understand - * Tweaked from source at http://stackoverflow.com/questions/4044509/android-how-to-use-the-html-taghandler - */ -public class WPHtmlTagHandler implements Html.TagHandler { - private static final int SPAN_INDENT_WIDTH = 15; - - private int mListItemCount = 0; - private List mListParents = new ArrayList<>(); - - @Override - public void handleTag(final boolean opening, final String tag, Editable output, - final XMLReader xmlReader) { - if (tag != null) { - switch (tag) { - case "WPUL": - if (opening) { - mListParents.add("ul"); - } else { - mListParents.remove("ul"); - } - break; - case "WPOL": - if (opening) { - mListParents.add("ol"); - } else { - mListParents.remove("ol"); - } - break; - case "WPLI": - if (!opening) { - handleListTag(output); - } - break; - case "dd": - if (opening) { - mListParents.add("dd"); - } else { - mListParents.remove("dd"); - } - break; - } - } - } - - private void handleListTag(Editable output) { - int size = mListParents.size(); - if (size > 0 && output != null) { - if ("ul".equals(mListParents.get(size - 1))) { - output.append("\n"); - String[] split = output.toString().split("\n"); - int start = 0; - if (split.length != 1) { - int lastIndex = split.length - 1; - start = output.length() - split[lastIndex].length() - 1; - } - output.setSpan(new BulletSpan(SPAN_INDENT_WIDTH * mListParents.size()), start, output.length(), 0); - } else if ("ol".equals(mListParents.get(size - 1))) { - mListItemCount++; - output.append("\n"); - String[] split = output.toString().split("\n"); - int start = 0; - if (split.length != 1) { - int lastIndex = split.length - 1; - start = output.length() - split[lastIndex].length() - 1; - } - output.insert(start, mListItemCount + ". "); - output.setSpan(new LeadingMarginSpan.Standard(SPAN_INDENT_WIDTH * mListParents.size()), start, - output.length(), 0); - } - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java deleted file mode 100644 index 61ba1b2d4708..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java +++ /dev/null @@ -1,140 +0,0 @@ -//Add WordPress image fields to ImageSpan object - -package org.wordpress.android.util.helpers; - -import android.content.Context; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.style.ImageSpan; - -public class WPImageSpan extends ImageSpan implements Parcelable { - protected Uri mImageSource = null; - protected boolean mNetworkImageLoaded = false; - protected MediaFile mMediaFile; - protected int mStartPosition, mEndPosition; - - protected WPImageSpan() { - super((Bitmap) null); - } - - public WPImageSpan(Context context, Bitmap b, Uri src) { - super(context, b); - this.mImageSource = src; - mMediaFile = new MediaFile(); - } - - public WPImageSpan(Context context, int resId, Uri src) { - super(context, resId); - this.mImageSource = src; - mMediaFile = new MediaFile(); - } - - public void setPosition(int start, int end) { - mStartPosition = start; - mEndPosition = end; - } - - public int getStartPosition() { - return mStartPosition >= 0 ? mStartPosition : 0; - } - - public int getEndPosition() { - return mEndPosition < getStartPosition() ? getStartPosition() : mEndPosition; - } - - public MediaFile getMediaFile() { - return mMediaFile; - } - - public void setMediaFile(MediaFile mediaFile) { - this.mMediaFile = mediaFile; - } - - public void setImageSource(Uri imageSource) { - this.mImageSource = imageSource; - } - - public Uri getImageSource() { - return mImageSource; - } - - public boolean isNetworkImageLoaded() { - return mNetworkImageLoaded; - } - - public void setNetworkImageLoaded(boolean networkImageLoaded) { - this.mNetworkImageLoaded = networkImageLoaded; - } - - protected void setupFromParcel(Parcel in) { - MediaFile mediaFile = new MediaFile(); - - boolean[] booleans = new boolean[2]; - in.readBooleanArray(booleans); - setNetworkImageLoaded(booleans[0]); - mediaFile.setVideo(booleans[1]); - - setImageSource(Uri.parse(in.readString())); - mediaFile.setMediaId(in.readString()); - mediaFile.setBlogId(in.readString()); - mediaFile.setPostID(in.readLong()); - mediaFile.setCaption(in.readString()); - mediaFile.setDescription(in.readString()); - mediaFile.setTitle(in.readString()); - mediaFile.setMimeType(in.readString()); - mediaFile.setFileName(in.readString()); - mediaFile.setThumbnailURL(in.readString()); - mediaFile.setVideoPressShortCode(in.readString()); - mediaFile.setFileURL(in.readString()); - mediaFile.setFilePath(in.readString()); - mediaFile.setDateCreatedGMT(in.readLong()); - mediaFile.setWidth(in.readInt()); - mediaFile.setHeight(in.readInt()); - setPosition(in.readInt(), in.readInt()); - - setMediaFile(mediaFile); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public WPImageSpan createFromParcel(Parcel in) { - WPImageSpan imageSpan = new WPImageSpan(); - imageSpan.setupFromParcel(in); - return imageSpan; - } - - public WPImageSpan[] newArray(int size) { - return new WPImageSpan[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) { - parcel.writeBooleanArray(new boolean[]{mNetworkImageLoaded, mMediaFile.isVideo()}); - parcel.writeString(mImageSource.toString()); - parcel.writeString(mMediaFile.getMediaId()); - parcel.writeString(mMediaFile.getBlogId()); - parcel.writeLong(mMediaFile.getPostID()); - parcel.writeString(mMediaFile.getCaption()); - parcel.writeString(mMediaFile.getDescription()); - parcel.writeString(mMediaFile.getTitle()); - parcel.writeString(mMediaFile.getMimeType()); - parcel.writeString(mMediaFile.getFileName()); - parcel.writeString(mMediaFile.getThumbnailURL()); - parcel.writeString(mMediaFile.getVideoPressShortCode()); - parcel.writeString(mMediaFile.getFileURL()); - parcel.writeString(mMediaFile.getFilePath()); - parcel.writeLong(mMediaFile.getDateCreatedGMT()); - parcel.writeInt(mMediaFile.getWidth()); - parcel.writeInt(mMediaFile.getHeight()); - parcel.writeInt(getStartPosition()); - parcel.writeInt(getEndPosition()); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java deleted file mode 100644 index 07d75e6af556..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.text.Layout; -import android.text.style.QuoteSpan; - -/** - * Customzed QuoteSpan for use in SpannableString's - */ -public class WPQuoteSpan extends QuoteSpan { - public static final int STRIPE_COLOR = 0xFF21759B; - private static final int STRIPE_WIDTH = 5; - private static final int GAP_WIDTH = 20; - - public WPQuoteSpan() { - super(STRIPE_COLOR); - } - - @Override - public int getLeadingMargin(boolean first) { - int margin = GAP_WIDTH * 2 + STRIPE_WIDTH; - return margin; - } - - /** - * Draw a nice thick gray bar if Ice Cream Sandwhich or newer. There's a - * bug on older devices that does not respect the increased margin. - */ - @Override - public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, - CharSequence text, int start, int end, boolean first, Layout layout) { - Paint.Style style = p.getStyle(); - int color = p.getColor(); - - p.setStyle(Paint.Style.FILL); - p.setColor(STRIPE_COLOR); - - c.drawRect(GAP_WIDTH + x, top, x + dir * STRIPE_WIDTH, bottom, p); - - p.setStyle(style); - p.setColor(color); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java deleted file mode 100644 index fbc23d069360..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package org.wordpress.android.util.helpers; - -import android.os.Parcel; -import android.text.style.UnderlineSpan; - -/** - * WPUnderlineSpan is used as an alternative class to UnderlineSpan. UnderlineSpan is used by EditText auto - * correct, so it can get mixed up with our formatting. - */ -public class WPUnderlineSpan extends UnderlineSpan { - public WPUnderlineSpan() { - super(); - } - - public WPUnderlineSpan(Parcel src) { - super(src); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java deleted file mode 100644 index 119677cb00e8..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.app.Activity; -import android.text.TextUtils; -import android.view.View; -import android.webkit.WebChromeClient; -import android.webkit.WebView; -import android.widget.ProgressBar; - -public class WPWebChromeClient extends WebChromeClient { - private final ProgressBar mProgressBar; - private final Activity mActivity; - private final boolean mAutoUpdateActivityTitle; - - public WPWebChromeClient(Activity activity, ProgressBar progressBar) { - mActivity = activity; - mProgressBar = progressBar; - mAutoUpdateActivityTitle = true; - } - - public WPWebChromeClient(Activity activity, - ProgressBar progressBar, - boolean autoUpdateActivityTitle) { - mActivity = activity; - mProgressBar = progressBar; - mAutoUpdateActivityTitle = autoUpdateActivityTitle; - } - - public void onProgressChanged(WebView webView, int progress) { - if (mActivity != null - && !mActivity.isFinishing() - && mAutoUpdateActivityTitle - && !TextUtils.isEmpty(webView.getTitle())) { - mActivity.setTitle(webView.getTitle()); - } - if (mProgressBar != null) { - if (progress == 100) { - mProgressBar.setVisibility(View.GONE); - } else { - mProgressBar.setVisibility(View.VISIBLE); - mProgressBar.setProgress(progress); - } - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt deleted file mode 100644 index 732e831c27ac..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -/** - * Prunes the Log File Store by retaining only the last `maxLogFileCount` log files. - * - * The file list is created upon instantiation – any files added - * afterwards won't be modified. - * - * @param logFileProvider: An interface where the log files will be retrieved from - * @param maxLogFileCount: The number of log files to retain - */ -class LogFileCleaner(private val logFileProvider: LogFileProviderInterface, private val maxLogFileCount: Int) { - /** - * Immediately removes all log files known to exist by this instance except for - * the most recent `maxLogFileCount` items. - */ - fun clean() { - logFileProvider.getLogFiles() - .dropLast(maxLogFileCount) - .forEach { it.delete() } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt deleted file mode 100644 index 0b59ec372b7b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -import android.content.Context -import java.io.File - -private const val LOG_FILE_DIRECTORY = "logs" - -/** - * A collection of helpers for Log Files. - */ -class LogFileProvider(private val logFileDirectoryPath: String) : LogFileProviderInterface { - /** - * Provides a {@link java.io.File} directory in which to store log files. - * - * If the directory doesn't already exist, it will be created. - */ - override fun getLogFileDirectory(): File { - val logFileDirectory = File(logFileDirectoryPath, LOG_FILE_DIRECTORY) - - if (!logFileDirectory.exists()) { - logFileDirectory.mkdir() - } - - return logFileDirectory - } - - /** - * Provides a list of stored log files, ordered oldest to newest. - */ - override fun getLogFiles(): List { - return getLogFileDirectory() - .listFiles() - .sortedBy { it.lastModified() } - } - - companion object { - @JvmStatic - fun fromContext(context: Context): LogFileProvider { - return LogFileProvider(context.applicationInfo.dataDir) - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt deleted file mode 100644 index e415ed5b738e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -import java.io.File - -/** - * An interface to retrieve log files - */ -interface LogFileProviderInterface { - fun getLogFiles(): List - - fun getLogFileDirectory(): File -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt deleted file mode 100644 index 41e900f1ec0a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -import org.jetbrains.annotations.TestOnly -import java.io.File -import java.io.FileWriter -import java.util.Date -import org.wordpress.android.util.DateTimeUtils -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors - -/** - * A class that manages writing to a log file. - * - * This class creates and writes to a log file, and will typically persist for the entire lifecycle - * of its host application. - */ -class LogFileWriter @JvmOverloads constructor( - logFileProvider: LogFileProviderInterface, - fileId: String = DateTimeUtils.iso8601FromDate(Date()) -) { - private val file = File(logFileProvider.getLogFileDirectory(), "$fileId.log") - private val fileWriter: FileWriter = FileWriter(file) - - /** - * A serial executor used to write to the file in a background thread - */ - private val queue: ExecutorService = Executors.newSingleThreadExecutor() - - /** - * A reference to the underlying {@link Java.IO.File} file. - * Should only be used for testing. - */ - @TestOnly - fun getFile(): File = file - - /** - * Writes the provided string to the log file synchronously - */ - fun write(data: String) { - queue.execute { - fileWriter.write(data) - fileWriter.flush() - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java deleted file mode 100644 index 5f2c62e9a0b6..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java +++ /dev/null @@ -1,307 +0,0 @@ -package org.wordpress.android.util.widgets; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.widget.TextView; - -import androidx.appcompat.widget.AppCompatTextView; -import androidx.core.view.ViewCompat; - -/** - * Text view that auto adjusts text size to fit within the view. - * If the text size equals the minimum text size and still does not - * fit, append with an ellipsis. - * - * See http://stackoverflow.com/a/5535672 - * - */ -public class AutoResizeTextView extends AppCompatTextView { - // Minimum text size for this text view - private static final float MIN_TEXT_SIZE = 20; - - // Interface for resize notifications - public interface OnTextResizeListener { - void onTextResize(TextView textView, float oldSize, float newSize); - } - - // Our ellipse string - Unicode Character 'HORIZONTAL ELLIPSIS' - private static final String M_ELLIPSIS = "\u2026"; - - // Registered resize listener - private OnTextResizeListener mTextResizeListener; - - // Flag for text and/or size changes to force a resize - private boolean mNeedsResize = false; - - // Text size that is set from code. This acts as a starting point for resizing - private float mTextSize; - - // Temporary upper bounds on the starting text size - private float mMaxTextSize = 0; - - // Lower bounds for text size - private float mMinTextSize = MIN_TEXT_SIZE; - - // Text view line spacing multiplier - private float mSpacingMult = 1.0f; - - // Text view additional line spacing - private float mSpacingAdd = 0.0f; - - // Add ellipsis to text that overflows at the smallest text size - private boolean mAddEllipsis = true; - - // Default constructor override - public AutoResizeTextView(Context context) { - this(context, null); - } - - // Default constructor when inflating from XML file - public AutoResizeTextView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - // Default constructor override - public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mTextSize = getTextSize(); - } - - /** - * When text changes, set the force resize flag to true and reset the text size. - */ - @Override - protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) { - mNeedsResize = true; - // Since this view may be reused, it is good to reset the text size - resetTextSize(); - } - - /** - * If the text view size changed, set the force resize flag to true - */ - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - if (w != oldw || h != oldh) { - mNeedsResize = true; - } - } - - /** - * Register listener to receive resize notifications - * @param listener - */ - public void setOnResizeListener(OnTextResizeListener listener) { - mTextResizeListener = listener; - } - - /** - * Override the set text size to update our internal reference values - */ - @Override - public void setTextSize(float size) { - super.setTextSize(size); - mTextSize = getTextSize(); - } - - /** - * Override the set text size to update our internal reference values - */ - @Override - public void setTextSize(int unit, float size) { - super.setTextSize(unit, size); - mTextSize = getTextSize(); - } - - /** - * Override the set line spacing to update our internal reference values - */ - @Override - public void setLineSpacing(float add, float mult) { - super.setLineSpacing(add, mult); - mSpacingMult = mult; - mSpacingAdd = add; - } - - /** - * Set the upper text size limit and invalidate the view - * @param maxTextSize - */ - public void setMaxTextSize(float maxTextSize) { - mMaxTextSize = maxTextSize; - requestLayout(); - invalidate(); - } - - /** - * Return upper text size limit - * @return - */ - public float getMaxTextSize() { - return mMaxTextSize; - } - - /** - * Set the lower text size limit and invalidate the view - * @param minTextSize - */ - public void setMinTextSize(float minTextSize) { - mMinTextSize = minTextSize; - requestLayout(); - invalidate(); - } - - /** - * Return lower text size limit - * @return - */ - public float getMinTextSize() { - return mMinTextSize; - } - - /** - * Set flag to add ellipsis to text that overflows at the smallest text size - * @param addEllipsis - */ - public void setAddEllipsis(boolean addEllipsis) { - mAddEllipsis = addEllipsis; - } - - /** - * Return flag to add ellipsis to text that overflows at the smallest text size - * @return - */ - public boolean getAddEllipsis() { - return mAddEllipsis; - } - - /** - * Reset the text to the original size - */ - private void resetTextSize() { - if (mTextSize > 0) { - super.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); - mMaxTextSize = mTextSize; - } - } - - /** - * Resize text after measuring - */ - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (changed || mNeedsResize) { - int widthLimit = (right - left) - getCompoundPaddingLeft() - getCompoundPaddingRight(); - int heightLimit = (bottom - top) - getCompoundPaddingBottom() - getCompoundPaddingTop(); - resizeText(widthLimit, heightLimit); - } - super.onLayout(changed, left, top, right, bottom); - } - - /** - * Resize the text size with default width and height - */ - public void resizeText() { - int heightLimit = getHeight() - getPaddingBottom() - getPaddingTop(); - int widthLimit = getWidth() - ViewCompat.getPaddingStart(this) - ViewCompat.getPaddingStart(this); - resizeText(widthLimit, heightLimit); - } - - /** - * Resize the text size with specified width and height - * @param width - * @param height - */ - @SuppressLint("SetTextI18n") public void resizeText(int width, int height) { - CharSequence text = getText(); - // Do not resize if the view does not have dimensions or there is no text - if (text == null || text.length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { - return; - } - - // Get the text view's paint object - TextPaint textPaint = getPaint(); - - // Store the current text size - float oldTextSize = textPaint.getTextSize(); - // If there is a max text size set, use the lesser of that and the default text size - float targetTextSize = mMaxTextSize > 0 ? Math.min(mTextSize, mMaxTextSize) : mTextSize; - - // Get the required text height - int textHeight = getTextHeight(text, textPaint, width, targetTextSize); - - // Until we either fit within our text view or we had reached our min text size, incrementally try smaller sizes - while (textHeight > height && targetTextSize > mMinTextSize) { - targetTextSize = Math.max(targetTextSize - 2, mMinTextSize); - textHeight = getTextHeight(text, textPaint, width, targetTextSize); - } - - // If we had reached our minimum text size and still don't fit, append an ellipsis - if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { - // Draw using a static layout - // modified: use a copy of TextPaint for measuring - TextPaint paint = new TextPaint(textPaint); - // Draw using a static layout - StaticLayout layout = new StaticLayout(text, paint, width, Layout.Alignment.ALIGN_NORMAL, - mSpacingMult, mSpacingAdd, false); - // Check that we have a least one line of rendered text - if (layout.getLineCount() > 0) { - // Since the line at the specific vertical position would be cut off, - // we must trim up to the previous line - int lastLine = layout.getLineForVertical(height) - 1; - // If the text would not even fit on a single line, clear it - if (lastLine < 0) { - setText(""); - } else { - // Otherwise, trim to the previous line and add an ellipsis - int start = layout.getLineStart(lastLine); - int end = layout.getLineEnd(lastLine); - float lineWidth = layout.getLineWidth(lastLine); - float ellipseWidth = paint.measureText(M_ELLIPSIS); - - // Trim characters off until we have enough room to draw the ellipsis - while (width < lineWidth + ellipseWidth) { - lineWidth = paint.measureText(text.subSequence(start, --end + 1).toString()); - } - if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) { - setText(M_ELLIPSIS + text.subSequence(0, end)); - } else { - setText(text.subSequence(0, end) + M_ELLIPSIS); - } - } - } - } - - // Some devices try to auto adjust line spacing, so force default line spacing - // and invalidate the layout as a side effect - setTextSize(TypedValue.COMPLEX_UNIT_PX, targetTextSize); - setLineSpacing(mSpacingAdd, mSpacingMult); - - // Notify the listener if registered - if (mTextResizeListener != null) { - mTextResizeListener.onTextResize(this, oldTextSize, targetTextSize); - } - - // Reset force resize flag - mNeedsResize = false; - } - - // Set the text size of the text paint object and use a static layout to render text off screen before measuring - private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) { - // modified: make a copy of the original TextPaint object for measuring - // (apparently the object gets modified while measuring, see also the - // docs for TextView.getPaint() (which states to access it read-only) - TextPaint paintCopy = new TextPaint(paint); - // Update the text paint object - paintCopy.setTextSize(textSize); - // Measure using a static layout - StaticLayout layout = new StaticLayout(source, paintCopy, width, Layout.Alignment.ALIGN_NORMAL, - mSpacingMult, mSpacingAdd, true); - return layout.getHeight(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java deleted file mode 100644 index 91c72674d487..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.wordpress.android.util.widgets; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.AppLog.T; - -public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { - public CustomSwipeRefreshLayout(Context context) { - super(context); - } - - public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - try { - return super.onTouchEvent(event); - } catch (IllegalArgumentException e) { - // Fix for https://github.com/wordpress-mobile/WordPress-Android/issues/2373 - // Catch IllegalArgumentException which can be fired by the underlying SwipeRefreshLayout.onTouchEvent() - // method. - // When android support-v4 fixes it, we'll have to remove that custom layout completely. - AppLog.e(T.UTILS, e); - return true; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java deleted file mode 100644 index 2c3951c61ec5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.wordpress.android.util.widgets; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.widget.EditText; - -import com.google.android.material.textfield.TextInputLayout; - -import org.wordpress.android.util.R; - -/** - * Custom TextInputLayout to provide a usable getBaseline() and error view padding - */ -public class WPTextInputLayout extends TextInputLayout { - public WPTextInputLayout(Context context) { - super(context); - } - - public WPTextInputLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public WPTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - public int getBaseline() { - EditText editText = getEditText(); - return editText != null ? editText.getBaseline() - editText.getPaddingBottom() - + getResources().getDimensionPixelSize(R.dimen.textinputlayout_baseline_correction) - : 0; - } - - @Override - public void setErrorEnabled(boolean enabled) { - super.setErrorEnabled(enabled); - - // remove hardcoded side padding of the error view - if (enabled) { - View errorView = findViewById(com.google.android.material.R.id.textinput_error); - if (errorView != null && errorView.getParent() != null) { - ((View) errorView.getParent()) - .setPadding(0, errorView.getPaddingTop(), 0, errorView.getPaddingBottom()); - } - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/res/values/dimens.xml b/libs/utils/WordPressUtils/src/main/res/values/dimens.xml deleted file mode 100644 index 4f3fdecd3158..000000000000 --- a/libs/utils/WordPressUtils/src/main/res/values/dimens.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 2dp - 4.3dp - -8.6dp - diff --git a/libs/utils/WordPressUtils/src/main/res/values/strings.xml b/libs/utils/WordPressUtils/src/main/res/values/strings.xml deleted file mode 100644 index 34d25dada509..000000000000 --- a/libs/utils/WordPressUtils/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - There is no network available - Now - diff --git a/libs/utils/WordPressUtils/src/main/res/values/tags.xml b/libs/utils/WordPressUtils/src/main/res/values/tags.xml deleted file mode 100644 index 796e3fab2be0..000000000000 --- a/libs/utils/WordPressUtils/src/main/res/values/tags.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java deleted file mode 100644 index a6ae733607e5..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Ignore; -import org.junit.Test; - -import java.util.Date; -import java.util.TimeZone; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DateTimeUtilsTest { - private final long mDefaultDate = 1564484058163L; // it's Tue Jul 30 2019 10:54:18 in UTC - - @Test - public void testIso8601UTCFromDate() { - // Arrange - TimeZone.setDefault(TimeZone.getTimeZone("GMT+2:00")); - Date date = new Date(mDefaultDate); - String expected = "2019-07-30T10:54:18+00:00"; - - // Act - String actual = DateTimeUtils.iso8601UTCFromDate(date); - - // Assert - assertThat(actual).isEqualTo(expected); - } - - @Test - @Ignore(value = "This test is failing because `DateTimeUtils.localDateToUTC` doesn't work as expected. I've " - + "marked it as deprecated and this tests serves just as a documentation.") - public void testLocalDateToUTC() { - // Arrange - TimeZone.setDefault(TimeZone.getTimeZone("GMT+2:00")); - Date date = new Date(mDefaultDate); - // this succeeds - assertThat(DateTimeUtils.iso8601FromDate(date)).isEqualTo("2019-07-30T12:54:18+0200"); - - // Act - String actual = DateTimeUtils.iso8601FromDate(DateTimeUtils.localDateToUTC(date)); - - // Assert - - // fails because `localDateToUTC` doesn't work as expected. See DateTimeUtils.localDateToUTC for more info. - assertThat(actual).isEqualTo("2019-07-30T10:54:18+00:00"); - } -} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt deleted file mode 100644 index 71789bd844dc..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -package org.wordpress.android.util - -import android.content.Context -import android.os.Build -import androidx.test.core.app.ApplicationProvider -import java.io.File -import java.io.FileReader -import kotlin.random.Random -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.util.helpers.logfile.LogFileCleaner -import org.wordpress.android.util.helpers.logfile.LogFileProvider - -/** - * The number of test files to create for each test run - */ -private const val MAX_FILES = 10 - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1]) -class LogFileCleanerTest { - private lateinit var logFileProvider: LogFileProvider - - @Before - fun setup() { - val context: Context = ApplicationProvider.getApplicationContext() - logFileProvider = LogFileProvider.fromContext(context) - - repeat(MAX_FILES) { - val file = File(logFileProvider.getLogFileDirectory(), "$it.log") - file.writeText("$it") - file.setLastModified(it * 10_000L) - } - - assert(logFileProvider.getLogFileDirectory().listFiles().count() == MAX_FILES) - } - - @After - fun tearDown() { - // Delete the test directory after each test - logFileProvider.getLogFileDirectory().deleteRecursively() - } - - @Test - fun testThatCleanerPreservesMostRecentlyCreatedFiles() { - val maxLogFileCount = Random.nextInt(MAX_FILES) - LogFileCleaner(logFileProvider, maxLogFileCount).clean() - - // Strings are easier to assert against than arrays - val remainingFileIds = logFileProvider.getLogFiles().joinToString(",") { - FileReader(it).readText() - } - - val expectedValue = (MAX_FILES - 1 downTo 0).take(maxLogFileCount).reversed().joinToString(",") - assertEquals(expectedValue, remainingFileIds) - } - - @Test - fun testThatCleanerPreservesCorrectNumberOfFiles() { - val numberOfFiles = Random.nextInt(MAX_FILES) - LogFileCleaner(logFileProvider, numberOfFiles).clean() - assertEquals(numberOfFiles, logFileProvider.getLogFileDirectory().listFiles().count()) - } - - @Test - fun testThatCleanerErasesAllFilesIfGivenZero() { - LogFileCleaner(logFileProvider, 0).clean() - assert(logFileProvider.getLogFileDirectory().listFiles().isEmpty()) - } -} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt deleted file mode 100644 index e4921c21e750..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -package org.wordpress.android.util - -import android.content.Context -import android.os.Build -import androidx.test.core.app.ApplicationProvider -import java.io.File -import java.util.UUID -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.util.helpers.logfile.LogFileProvider - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1]) -class LogFileHelpersTest { - private lateinit var testProvider: LogFileProvider - - @Before - fun setup() { - val context: Context = ApplicationProvider.getApplicationContext() - testProvider = LogFileProvider.fromContext(context) - } - - @After - fun tearDown() { - // Delete the test directory after each test - testProvider.getLogFileDirectory().deleteRecursively() - } - - @Test - fun testThatLogFileDirectoryIsCreatedIfNotExists() { - val directory = testProvider.getLogFileDirectory() - assert(directory.exists()) - } - - @Test - fun testThatLogFilesListsAllFiles() { - val directory = testProvider.getLogFileDirectory() - File(directory, UUID.randomUUID().toString()).createNewFile() - Assert.assertEquals(testProvider.getLogFiles().count(), 1) - } - - @Test - fun testThatLogFilesSortsFilesWithMostRecentFirst() { - val directory = testProvider.getLogFileDirectory() - - listOf(1_000L, 1_000_000L).shuffled().forEach { modifiedDate -> - File(directory, UUID.randomUUID().toString()).also { file -> - // Use timestamps in increments of 1000 to avoid issues from the File System's date precision - val date = modifiedDate * 1000 - file.createNewFile() - file.setLastModified(date) - assert(file.lastModified() == date) - } - } - - val files = testProvider.getLogFiles() - assert(files.first().lastModified() < files.last().lastModified()) - } -} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt deleted file mode 100644 index 998a29398783..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.wordpress.android.util - -import android.content.Context -import android.os.Build -import androidx.test.core.app.ApplicationProvider -import java.io.FileReader -import java.util.UUID -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.util.helpers.logfile.LogFileProvider -import org.wordpress.android.util.helpers.logfile.LogFileWriter - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1]) -class LogFileWriterTest { - private lateinit var testProvider: LogFileProvider - - @Before - fun setup() { - val context: Context = ApplicationProvider.getApplicationContext() - testProvider = LogFileProvider.fromContext(context) - } - - @After - fun tearDown() { - // Delete the test directory after each test - testProvider.getLogFileDirectory().deleteRecursively() - } - - @Test - fun testThatFileWriterCreatesLogFile() { - val writer = LogFileWriter(testProvider) - assert(writer.getFile().exists()) - } - - @Test - fun testThatContentsAreWrittenToFile() { - val randomString = UUID.randomUUID().toString() - val writer = LogFileWriter(testProvider) - writer.write(randomString) - - // Allow the async process to persist the file changes - Thread.sleep(1000) - - val contents = FileReader(writer.getFile()).readText() - assertEquals(randomString, contents) - } -} diff --git a/libs/utils/build.gradle b/libs/utils/build.gradle deleted file mode 100644 index ebb5278a193c..000000000000 --- a/libs/utils/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -buildscript { - repositories { - jcenter() - } - - dependencies { - classpath 'com.automattic.android:fetchstyle:1.1' - } -} - -apply plugin: 'com.automattic.android.fetchstyle' - -allprojects { - apply plugin: 'checkstyle' - - repositories { - jcenter() - maven { - url "https://maven.google.com" - } - } - - if (tasks.findByPath('checkstyle') == null) { - tasks.create(name: 'checkstyle', type: Checkstyle) { - source 'src' - - classpath = files() - } - - checkstyle { - toolVersion = '8.3' - configFile file("${project.rootDir}/config/checkstyle.xml") - } - } - - // Suppress false Javadoc lint errors preventing Bintray release - // See https://stackoverflow.com/questions/34828426/disable-javadoc-check-for-bintray-upload - tasks.withType(Javadoc) { - options.addBooleanOption('Xdoclint:none', true) - } -} diff --git a/libs/utils/config/checkstyle.xml b/libs/utils/config/checkstyle.xml deleted file mode 100644 index 2ebaaac1412c..000000000000 --- a/libs/utils/config/checkstyle.xml +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/utils/gradle/wrapper/gradle-wrapper.jar b/libs/utils/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index a118be48be882fa18946b374de0bf77a651f374b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54783 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$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="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# 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 - ;; -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" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - 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 -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 -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 - -# 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\"" - fi - i=$((i+1)) - 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 - -exec "$JAVACMD" "$@" diff --git a/libs/utils/gradlew.bat b/libs/utils/gradlew.bat deleted file mode 100644 index f9553162f122..000000000000 --- a/libs/utils/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@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= - -@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 - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -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% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/libs/utils/settings.gradle b/libs/utils/settings.gradle deleted file mode 100644 index 3519745edd00..000000000000 --- a/libs/utils/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':WordPressUtils' \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index ffa909a31212..7166fe5dabce 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,7 +7,7 @@ include ':photoeditor' project(':photoeditor').projectDir = new File(rootProject.projectDir, 'libs/stories-android/photoeditor') include ':libs:image-editor:ImageEditor' -include ':libs:utils:WordPressUtils' +includeBuild('../WordPress-Utils-Android') include ':libs:networking:WordPressNetworking' include ':libs:analytics:WordPressAnalytics' include ':libs:editor:WordPressEditor' From 76c75b2aac7e8026c5bee22ee39afb01b014ae81 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 1 Sep 2020 10:21:24 -0400 Subject: [PATCH 002/144] Use binary version of utils library --- WordPress/build.gradle | 16 ++++++++++++---- build.gradle | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 1c3c52a60a7b..5c93ede84358 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -301,13 +301,21 @@ dependencies { implementation ("com.github.wordpress-mobile.WordPress-FluxC-Android:fluxc:$fluxCVersion") { exclude group: "com.android.volley" + exclude group: 'org.wordpress', module: 'utils' } implementation ('com.github.indexos.media-for-mobile:android:43a9026f0973a2f0a74fa813132f6a16f7499c3a') - implementation 'org.wordpress.android:WordPressUtils' - testImplementation 'org.wordpress.android:WordPressUtils' - debugImplementation 'org.wordpress.android:WordPressUtils' + + if (buildUtilsFromLocalDirectory) { + implementation 'org.wordpress.android:WordPressUtils' + testImplementation 'org.wordpress.android:WordPressUtils' + debugImplementation 'org.wordpress.android:WordPressUtils' + } else { + implementation 'org.wordpress:utils:1.29' + testImplementation 'org.wordpress:utils:1.29' + debugImplementation 'org.wordpress:utils:1.29' + } // implementation project(path:':libs:utils:WordPressUtils') // testImplementation project(path:':libs:utils:WordPressUtils') // debugImplementation project(path:':libs:utils:WordPressUtils') @@ -358,7 +366,7 @@ dependencies { configurations.all { // Exclude packaged wordpress sub projects, force the use of the source project // (eg. use :libs:utils:WordPressUtils instead of 'org.wordpress:utils') - exclude group: 'org.wordpress', module: 'utils' + //exclude group: 'org.wordpress', module: 'utils' exclude group: 'org.wordpress', module: 'analytics' } diff --git a/build.gradle b/build.gradle index 538be77170d7..d6f6d26ae263 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript { ext.kotlin_ktx_version = '1.2.0' ext.androidx_work_version = "2.0.1" ext.buildGutenbergMobileJSBundle = 1 + ext.buildUtilsFromLocalDirectory = false repositories { google() From e6f8cb2d0aa853d9a6a48f39b5389f72236bada3 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 1 Sep 2020 11:08:04 -0400 Subject: [PATCH 003/144] Read included builds from a text file --- .gitignore | 1 + included-builds-example.txt | 1 + settings.gradle | 8 +++++++- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 included-builds-example.txt diff --git a/.gitignore b/.gitignore index a96664763f7f..19c767ec2809 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,4 @@ sentry.properties WordPress/release.jks WordPress/debug.keystore WordPress/*.jks +included-builds.txt diff --git a/included-builds-example.txt b/included-builds-example.txt new file mode 100644 index 000000000000..cec66164793c --- /dev/null +++ b/included-builds-example.txt @@ -0,0 +1 @@ +../WordPress-Utils-Android diff --git a/settings.gradle b/settings.gradle index 7166fe5dabce..5b3962a879a1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,7 +7,6 @@ include ':photoeditor' project(':photoeditor').projectDir = new File(rootProject.projectDir, 'libs/stories-android/photoeditor') include ':libs:image-editor:ImageEditor' -includeBuild('../WordPress-Utils-Android') include ':libs:networking:WordPressNetworking' include ':libs:analytics:WordPressAnalytics' include ':libs:editor:WordPressEditor' @@ -15,6 +14,13 @@ include ':libs:login:WordPressLoginFlow' include ':libs:WordPressProcessors' include ':libs:WordPressAnnotations' +def includedBuilds = new File('./included-builds.txt') +if (includedBuilds.exists()) { + includedBuilds.eachLine { line -> + includeBuild(line) + } +} + include ':WordPressMocks' project(':WordPressMocks').projectDir = new File(rootProject.projectDir, properties.getOrDefault('wp.wordpress_mocks_path', 'libs/mocks') + '/WordPressMocks') From 8dc93a8b107ced8eb0122f03ec7faeae4be6f51f Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 1 Sep 2020 11:12:50 -0400 Subject: [PATCH 004/144] Add utils library version as a const --- WordPress/build.gradle | 9 +++------ build.gradle | 1 + 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 5c93ede84358..cfbc6feee333 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -312,13 +312,10 @@ dependencies { testImplementation 'org.wordpress.android:WordPressUtils' debugImplementation 'org.wordpress.android:WordPressUtils' } else { - implementation 'org.wordpress:utils:1.29' - testImplementation 'org.wordpress:utils:1.29' - debugImplementation 'org.wordpress:utils:1.29' + implementation "org.wordpress:utils:$wordPressUtilsVersion" + testImplementation "org.wordpress:utils:$wordPressUtilsVersion" + debugImplementation "org.wordpress:utils:$wordPressUtilsVersion" } -// implementation project(path:':libs:utils:WordPressUtils') -// testImplementation project(path:':libs:utils:WordPressUtils') -// debugImplementation project(path:':libs:utils:WordPressUtils') implementation (project(path:':libs:networking:WordPressNetworking')) { exclude group: "com.android.volley" } diff --git a/build.gradle b/build.gradle index d6f6d26ae263..6c2199519e85 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript { ext.kotlin_ktx_version = '1.2.0' ext.androidx_work_version = "2.0.1" ext.buildGutenbergMobileJSBundle = 1 + ext.wordPressUtilsVersion = '1.29' ext.buildUtilsFromLocalDirectory = false repositories { From 798c4b297a0f7ae01df4ab6adf28355b38f40707 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 1 Sep 2020 11:18:21 -0400 Subject: [PATCH 005/144] Removes utils library tasks from CircleCI --- .circleci/config.yml | 45 -------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1b60a2ebb08d..ecde38a62746 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -122,11 +122,6 @@ jobs: environment: SUPPRESS_GUTENBERG_MOBILE_JS_BUNDLE_BUILD: 1 command: SUPPRESS_GUTENBERG_MOBILE_JS_BUNDLE_BUILD=1 ./gradlew testVanillaRelease --stacktrace --no-daemon - - run: - name: Test WordPressUtils - environment: - SUPPRESS_GUTENBERG_MOBILE_JS_BUNDLE_BUILD: 1 - command: cd libs/utils && ./gradlew --stacktrace testReleaseUnitTest - android/save-gradle-cache - android/save-test-results lint: @@ -268,40 +263,6 @@ jobs: include_job_number_field: false include_project_field: false failure_message: ':red_circle: WordPress Android connected tests failed on \`${CIRCLE_BRANCH}\` branch after merge by ${CIRCLE_USERNAME}. See for details.\n\nPlease reach out in #platform9 if you think this failure is not caused by your changes, so we can investigate.' - WordPressUtils Connected Tests: - docker: - - image: circleci/android@sha256:061e2535826cc3fe4c4a440e716bf06c36c80401ee635c339c6803b3e427ebb3 - steps: - - git/shallow-checkout: - init-submodules: true - - checkout-submodules - - android/restore-gradle-cache - - copy-gradle-properties - - update-gradle-memory - - restore-gutenberg-bundle-cache - - run: - name: Ensure assets folder exists - command: mkdir -p libs/gutenberg-mobile/gutenberg/packages/react-native-bridge/android/src/main/assets - - attach_workspace: - at: libs/gutenberg-mobile/gutenberg/packages/react-native-bridge/android/src/main/assets - - run: - name: Build - environment: - SUPPRESS_GUTENBERG_MOBILE_JS_BUNDLE_BUILD: 1 - command: ./gradlew WordPress:assembleVanillaDebug && cd libs/utils && ./gradlew assembleAndroidTest --stacktrace - - run: - name: Decrypt credentials - command: openssl aes-256-cbc -md sha256 -d -in .circleci/.firebase.secrets.json.enc -out .circleci/.firebase.secrets.json -k "${FIREBASE_SECRETS_ENCRYPTION_KEY}" - - android/firebase-test: - key-file: .circleci/.firebase.secrets.json - type: instrumentation - apk-path: WordPress/build/outputs/apk/vanilla/debug/org.wordpress.android-vanilla-debug.apk - test-apk-path: libs/utils/WordPressUtils/build/outputs/apk/androidTest/debug/WordPressUtils-debug-androidTest.apk - device: model=Nexus5X,version=26,locale=en,orientation=portrait - project: api-project-108380595987 - timeout: 10m - results-history-name: CircleCI WPUtils Connected Tests - - android/save-gradle-cache strings-check: docker: - image: circleci/ruby:2.6.4 @@ -382,12 +343,6 @@ workflows: filters: branches: ignore: /pull\/[0-9]+/ - - WordPressUtils Connected Tests: - requires: - - gutenberg-bundle-build - filters: - branches: - ignore: /pull\/[0-9]+/ - Connected Tests: requires: - gutenberg-bundle-build From acc1a040f904c0d003b6de7c396610bf09cd26be Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 1 Sep 2020 12:04:10 -0400 Subject: [PATCH 006/144] Manually exclude utils from libraries for WordPress build --- WordPress/build.gradle | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index cfbc6feee333..193e9f286e18 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -318,12 +318,18 @@ dependencies { } implementation (project(path:':libs:networking:WordPressNetworking')) { exclude group: "com.android.volley" + exclude group: 'org.wordpress', module: 'utils' + } + implementation (project(path:':libs:analytics:WordPressAnalytics')) { + exclude group: 'org.wordpress', module: 'utils' + } + implementation (project(path:':libs:editor:WordPressEditor')) { + exclude group: 'org.wordpress', module: 'utils' } - implementation project(path:':libs:analytics:WordPressAnalytics') - implementation project(path:':libs:editor:WordPressEditor') implementation (project(path:':libs:login:WordPressLoginFlow')) { exclude group: "com.github.wordpress-mobile.WordPress-FluxC-Android", module: "fluxc" exclude group: 'com.github.bumptech.glide' + exclude group: 'org.wordpress', module: 'utils' } implementation (group: 'com.zendesk', name: 'support', version: '2.0.0') { @@ -363,7 +369,6 @@ dependencies { configurations.all { // Exclude packaged wordpress sub projects, force the use of the source project // (eg. use :libs:utils:WordPressUtils instead of 'org.wordpress:utils') - //exclude group: 'org.wordpress', module: 'utils' exclude group: 'org.wordpress', module: 'analytics' } From 1a6219c759618da0c864da333d601d9c75182601 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 4 Sep 2020 13:15:24 -0400 Subject: [PATCH 007/144] Adds comments to included-builds-example.txt file --- included-builds-example.txt | 13 +++++++++++++ settings.gradle | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/included-builds-example.txt b/included-builds-example.txt index cec66164793c..0ca9dc958788 100644 --- a/included-builds-example.txt +++ b/included-builds-example.txt @@ -1 +1,14 @@ +# This file is completely optional, but its usage makes it easier to work with libraries +# in local path. This example file needs to be copied as `included-builds.txt` to take +# effect. +# +# `settings.gradle` will call `includeBuild` on each relative path in this file. +# +# `includeBuild` call alone will not make a project a dependency of WordPress-Android. +# In order for a project to be a dependency, its module needs to be added in the +# `dependencies` section of the `build.gradle` file just like any other dependency. +# +# Android Studio will show each included project even if it's not added as a dependency. +# However, if an included build is not added as a dependency, it'll have no impact on +# the builds. ../WordPress-Utils-Android diff --git a/settings.gradle b/settings.gradle index 5b3962a879a1..f04ea374160d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,9 @@ include ':libs:WordPressAnnotations' def includedBuilds = new File('./included-builds.txt') if (includedBuilds.exists()) { includedBuilds.eachLine { line -> - includeBuild(line) + if (!line.isEmpty() && !line.startsWith("#")) { + includeBuild(line) + } } } From bcb36be64ae59d1a5c5da8b37f50a44dbdad35ee Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Sat, 5 Sep 2020 16:58:11 -0400 Subject: [PATCH 008/144] Remove libs/utils issues from lint-baseline.xml --- WordPress/lint-baseline.xml | 185 ------------------------------------ 1 file changed, 185 deletions(-) diff --git a/WordPress/lint-baseline.xml b/WordPress/lint-baseline.xml index 023d9ff9aabc..d6576ca0a54b 100644 --- a/WordPress/lint-baseline.xml +++ b/WordPress/lint-baseline.xml @@ -84,22 +84,6 @@ column="20"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date: Mon, 21 Sep 2020 16:16:15 -0400 Subject: [PATCH 009/144] Updates utils to 1.30 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b06c202d97f2..a86f793357d6 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { ext.kotlin_ktx_version = '1.2.0' ext.androidx_work_version = "2.0.1" ext.buildGutenbergMobileJSBundle = 1 - ext.wordPressUtilsVersion = '1.29' + ext.wordPressUtilsVersion = '1.30' ext.buildUtilsFromLocalDirectory = false repositories { From 82adce444c1cfa6d43778479daee2f9b2aa61c3d Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Mon, 21 Sep 2020 19:21:01 -0400 Subject: [PATCH 010/144] Update WordPressUtils dependency group --- WordPress/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 88c136e9305b..d87eba33de47 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -310,9 +310,9 @@ dependencies { if (buildUtilsFromLocalDirectory) { - implementation 'org.wordpress.android:WordPressUtils' - testImplementation 'org.wordpress.android:WordPressUtils' - debugImplementation 'org.wordpress.android:WordPressUtils' + implementation 'org.wordpress:WordPressUtils' + testImplementation 'org.wordpress:WordPressUtils' + debugImplementation 'org.wordpress:WordPressUtils' } else { implementation "org.wordpress:utils:$wordPressUtilsVersion" testImplementation "org.wordpress:utils:$wordPressUtilsVersion" From e571c3fffd2ea73e875c298903da8e3f7f4fda33 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Mon, 21 Sep 2020 19:23:05 -0400 Subject: [PATCH 011/144] Re-add libs/utils to make it easier to review the changes --- libs/utils/.circleci/config.yml | 44 + libs/utils/.editorconfig | 2 + libs/utils/.gitignore | 57 ++ libs/utils/.idea/checkstyle-idea.xml | 18 + libs/utils/.idea/codeStyleSettings.xml | 274 ++++++ libs/utils/.idea/codeStyles/Project.xml | 281 ++++++ .../.idea/codeStyles/codeStyleConfig.xml | 5 + libs/utils/.idea/compiler.xml | 22 + .../.idea/copyright/profiles_settings.xml | 3 + libs/utils/.idea/encodings.xml | 6 + libs/utils/.idea/externalDependencies.xml | 6 + .../inspectionProfiles/Project_Default.xml | 16 + .../inspectionProfiles/profiles_settings.xml | 7 + libs/utils/.idea/vcs.xml | 6 + libs/utils/README.md | 3 +- libs/utils/WordPressUtils/README.md | 1 + libs/utils/WordPressUtils/build.gradle | 1 + .../android/util/ImageUtilsTest.java | 89 ++ .../wordpress/android/util/JSONUtilsTest.java | 37 + .../android/util/PhotonUtilsTest.java | 106 +++ .../android/util/ShortcodeUtilsTest.java | 32 + .../wordpress/android/util/UrlUtilsTest.java | 131 +++ .../src/main/AndroidManifest.xml | 6 + .../util/AccessibilityEventListener.java | 7 + .../android/util/AccessibilityUtils.java | 108 +++ .../wordpress/android/util/ActivityUtils.java | 55 ++ .../wordpress/android/util/AlertUtils.java | 100 ++ .../org/wordpress/android/util/AppLog.java | 381 ++++++++ .../android/util/AutoForeground.java | 223 +++++ .../util/AutoForegroundNotification.java | 79 ++ .../wordpress/android/util/DateTimeUtils.java | 251 +++++ .../wordpress/android/util/DeviceUtils.java | 179 ++++ .../wordpress/android/util/EditTextUtils.java | 88 ++ .../android/util/EmoticonsUtils.java | 110 +++ .../org/wordpress/android/util/FileUtils.java | 61 ++ .../wordpress/android/util/FormatUtils.java | 79 ++ .../wordpress/android/util/GeocoderUtils.java | 115 +++ .../wordpress/android/util/GravatarUtils.java | 86 ++ .../wordpress/android/util/ImageUtils.java | 898 ++++++++++++++++++ .../org/wordpress/android/util/JSONUtils.java | 262 +++++ .../wordpress/android/util/LanguageUtils.java | 72 ++ .../org/wordpress/android/util/ListUtils.java | 47 + .../org/wordpress/android/util/MapUtils.java | 115 +++ .../wordpress/android/util/MediaUtils.java | 563 +++++++++++ .../wordpress/android/util/NetworkUtils.java | 100 ++ .../wordpress/android/util/PackageUtils.java | 45 + .../android/util/PermissionUtils.java | 104 ++ .../wordpress/android/util/PhotonUtils.java | 143 +++ .../android/util/ProfilingUtils.java | 87 ++ .../wordpress/android/util/ServiceUtils.java | 16 + .../android/util/ShortcodeUtils.java | 31 + .../org/wordpress/android/util/SqlUtils.java | 146 +++ .../wordpress/android/util/StringUtils.java | 363 +++++++ .../android/util/SystemServiceFactory.java | 14 + .../util/SystemServiceFactoryAbstract.java | 7 + .../util/SystemServiceFactoryDefault.java | 9 + .../wordpress/android/util/ToastUtils.java | 53 ++ .../org/wordpress/android/util/UrlUtils.java | 318 +++++++ .../android/util/UserEmailUtils.java | 39 + .../wordpress/android/util/VideoUtils.java | 43 + .../org/wordpress/android/util/ViewUtils.java | 81 ++ .../wordpress/android/util/WebViewUtils.java | 22 + .../android/util/helpers/Debouncer.java | 39 + .../helpers/ListScrollPositionManager.java | 58 ++ .../android/util/helpers/MediaFile.java | 348 +++++++ .../android/util/helpers/MediaGallery.java | 86 ++ .../util/helpers/MediaGalleryImageSpan.java | 21 + .../RecyclerViewScrollPositionManager.java | 39 + .../util/helpers/SwipeToRefreshHelper.java | 110 +++ .../android/util/helpers/Version.java | 55 ++ .../util/helpers/WPHtmlTagHandler.java | 85 ++ .../android/util/helpers/WPImageSpan.java | 140 +++ .../android/util/helpers/WPQuoteSpan.java | 44 + .../android/util/helpers/WPUnderlineSpan.java | 34 + .../util/helpers/WPWebChromeClient.java | 45 + .../util/helpers/logfile/LogFileCleaner.kt | 22 + .../util/helpers/logfile/LogFileProvider.kt | 42 + .../logfile/LogFileProviderInterface.kt | 12 + .../util/helpers/logfile/LogFileWriter.kt | 45 + .../util/widgets/AutoResizeTextView.java | 307 ++++++ .../widgets/CustomSwipeRefreshLayout.java | 34 + .../util/widgets/WPTextInputLayout.java | 49 + .../src/main/res/values/dimens.xml | 6 + .../src/main/res/values/strings.xml | 5 + .../src/main/res/values/tags.xml | 3 + .../android/util/DateTimeUtilsTest.java | 46 + .../android/util/LogFileCleanerTest.kt | 75 ++ .../android/util/LogFileHelpersTest.kt | 64 ++ .../android/util/LogFileWriterTest.kt | 53 ++ libs/utils/build.gradle | 41 + libs/utils/config/checkstyle.xml | 276 ++++++ libs/utils/settings.gradle | 1 + 92 files changed, 8837 insertions(+), 1 deletion(-) create mode 100644 libs/utils/.circleci/config.yml create mode 100644 libs/utils/.editorconfig create mode 100644 libs/utils/.gitignore create mode 100644 libs/utils/.idea/checkstyle-idea.xml create mode 100644 libs/utils/.idea/codeStyleSettings.xml create mode 100644 libs/utils/.idea/codeStyles/Project.xml create mode 100644 libs/utils/.idea/codeStyles/codeStyleConfig.xml create mode 100644 libs/utils/.idea/compiler.xml create mode 100644 libs/utils/.idea/copyright/profiles_settings.xml create mode 100644 libs/utils/.idea/encodings.xml create mode 100644 libs/utils/.idea/externalDependencies.xml create mode 100644 libs/utils/.idea/inspectionProfiles/Project_Default.xml create mode 100644 libs/utils/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 libs/utils/.idea/vcs.xml create mode 100644 libs/utils/WordPressUtils/README.md create mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java create mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java create mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java create mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java create mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java create mode 100644 libs/utils/WordPressUtils/src/main/AndroidManifest.xml create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java create mode 100644 libs/utils/WordPressUtils/src/main/res/values/dimens.xml create mode 100644 libs/utils/WordPressUtils/src/main/res/values/strings.xml create mode 100644 libs/utils/WordPressUtils/src/main/res/values/tags.xml create mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java create mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt create mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt create mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt create mode 100644 libs/utils/build.gradle create mode 100644 libs/utils/config/checkstyle.xml create mode 100644 libs/utils/settings.gradle diff --git a/libs/utils/.circleci/config.yml b/libs/utils/.circleci/config.yml new file mode 100644 index 000000000000..a54887b167e1 --- /dev/null +++ b/libs/utils/.circleci/config.yml @@ -0,0 +1,44 @@ +version: 2.1 + +orbs: + android: wordpress-mobile/android@0.0.22 + +commands: + copy-gradle-properties: + steps: + - run: + name: Setup gradle.properties + command: cp gradle.properties-example gradle.properties + +jobs: + Lint: + executor: + name: android/default + api-version: "27" + steps: + - checkout + - copy-gradle-properties + - android/restore-gradle-cache + - run: + name: Lint & Checkstyle + command: ./gradlew --stacktrace lint checkstyle + - android/save-gradle-cache + - android/save-lint-results + Build: + executor: + name: android/default + api-version: "27" + steps: + - checkout + - copy-gradle-properties + - android/restore-gradle-cache + - run: + name: Build + command: ./gradlew --stacktrace assembleDebug assembleRelease + - android/save-gradle-cache + +workflows: + WordPress-Utils-Android: + jobs: + - Lint + - Build diff --git a/libs/utils/.editorconfig b/libs/utils/.editorconfig new file mode 100644 index 000000000000..590d68372e0d --- /dev/null +++ b/libs/utils/.editorconfig @@ -0,0 +1,2 @@ +[*.{kt,kts}] +max_line_length=120 diff --git a/libs/utils/.gitignore b/libs/utils/.gitignore new file mode 100644 index 000000000000..3f762d543ec7 --- /dev/null +++ b/libs/utils/.gitignore @@ -0,0 +1,57 @@ +# OS X generated file +.DS_Store + +# built application files +*.apk +*.ap_ + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ +build/ +build.log + +# Local configuration file (sdk path, etc) +local.properties + +# Eclipse project files +.settings/ +.classpath +.project + +# Intellij project files +*.iml +*.ipr +*.iws +/.idea/* + +# IntelliJ/Android Studio exceptions +!/.idea/vcs.xml +!/.idea/codeStyles/ +!/.idea/fileTemplates/ +!/.idea/inspectionProfiles/ +!/.idea/scopes/ +!/.idea/codeStyleSettings.xml +!/.idea/encodings.xml +!/.idea/copyright/ +!/.idea/compiler.xml +# Enforce plugins +!/.idea/externalDependencies.xml +# Checkstyle configuration +!/.idea/checkstyle-idea.xml + +# Gradle +.gradle/ +gradle.properties + +# Silver Searcher ignore file +.agignore + +# Windows Backup +*.bak diff --git a/libs/utils/.idea/checkstyle-idea.xml b/libs/utils/.idea/checkstyle-idea.xml new file mode 100644 index 000000000000..0cfcc74ce7f4 --- /dev/null +++ b/libs/utils/.idea/checkstyle-idea.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/libs/utils/.idea/codeStyleSettings.xml b/libs/utils/.idea/codeStyleSettings.xml new file mode 100644 index 000000000000..c3f56acf6b1c --- /dev/null +++ b/libs/utils/.idea/codeStyleSettings.xml @@ -0,0 +1,274 @@ + + + + + + \ No newline at end of file diff --git a/libs/utils/.idea/codeStyles/Project.xml b/libs/utils/.idea/codeStyles/Project.xml new file mode 100644 index 000000000000..a6f575ec5fc6 --- /dev/null +++ b/libs/utils/.idea/codeStyles/Project.xml @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/utils/.idea/codeStyles/codeStyleConfig.xml b/libs/utils/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000000..79ee123c2b23 --- /dev/null +++ b/libs/utils/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/libs/utils/.idea/compiler.xml b/libs/utils/.idea/compiler.xml new file mode 100644 index 000000000000..9a8b7e5c45ee --- /dev/null +++ b/libs/utils/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/libs/utils/.idea/copyright/profiles_settings.xml b/libs/utils/.idea/copyright/profiles_settings.xml new file mode 100644 index 000000000000..e7bedf3377d4 --- /dev/null +++ b/libs/utils/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/libs/utils/.idea/encodings.xml b/libs/utils/.idea/encodings.xml new file mode 100644 index 000000000000..97626ba45445 --- /dev/null +++ b/libs/utils/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/libs/utils/.idea/externalDependencies.xml b/libs/utils/.idea/externalDependencies.xml new file mode 100644 index 000000000000..687e9fd1e473 --- /dev/null +++ b/libs/utils/.idea/externalDependencies.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/libs/utils/.idea/inspectionProfiles/Project_Default.xml b/libs/utils/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000000..4e2b427ce8a3 --- /dev/null +++ b/libs/utils/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/libs/utils/.idea/inspectionProfiles/profiles_settings.xml b/libs/utils/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000000..3b312839bf2e --- /dev/null +++ b/libs/utils/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/libs/utils/.idea/vcs.xml b/libs/utils/.idea/vcs.xml new file mode 100644 index 000000000000..94a25f7f4cb4 --- /dev/null +++ b/libs/utils/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/libs/utils/README.md b/libs/utils/README.md index c88ec2d9106d..9a17a4008c5a 100644 --- a/libs/utils/README.md +++ b/libs/utils/README.md @@ -24,7 +24,8 @@ $ ./gradlew assemble test publishToMavenLocal When a new version is ready to be published to the remote repository, use the following command to publish it to Bintray: ```shell -$ ./gradlew clean build bintrayPublish -PbintrayUser=FIXME -PbintrayKey=FIXME +$ ./gradlew clean build +$ ./gradlew bintrayUpload -PbintrayUser=FIXME -PbintrayKey=FIXME ``` ## Apps and libraries using WordPress-Utils-Android: diff --git a/libs/utils/WordPressUtils/README.md b/libs/utils/WordPressUtils/README.md new file mode 100644 index 000000000000..62a759585e63 --- /dev/null +++ b/libs/utils/WordPressUtils/README.md @@ -0,0 +1 @@ +# org.wordpress.android.util \ No newline at end of file diff --git a/libs/utils/WordPressUtils/build.gradle b/libs/utils/WordPressUtils/build.gradle index 3aeb2984c876..d10606781fd4 100644 --- a/libs/utils/WordPressUtils/build.gradle +++ b/libs/utils/WordPressUtils/build.gradle @@ -91,6 +91,7 @@ bintray { user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') key = project.hasProperty('bintrayKey') ? project.property('bintrayKey') : System.getenv('BINTRAY_KEY') publications = ['UtilsPublication'] + publish = true pkg { repo = 'maven' name = 'utils' diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java new file mode 100644 index 000000000000..05b0af2f7ade --- /dev/null +++ b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java @@ -0,0 +1,89 @@ +package org.wordpress.android.util; + +import android.graphics.BitmapFactory; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ImageUtilsTest { + @Test + public void testGetScaleForResizingReturnsOneWhenMaxSizeIsZero() { + BitmapFactory.Options options = new BitmapFactory.Options(); + int scale = ImageUtils.getScaleForResizing(0, options); + + assertEquals(1, scale); + } + + @Test + public void testGetScaleForResizingSameSizeReturnsOne() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.outHeight = 100; + options.outWidth = 100; + int maxSize = 100; + + int scale = ImageUtils.getScaleForResizing(maxSize, options); + + assertEquals(1, scale); + } + + @Test + public void testGetScaleForResizingPortraitMaxHeightSameAsMaxSizeReturnsOne() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.outHeight = 100; + options.outWidth = 1; + int maxSize = 100; + + int scale = ImageUtils.getScaleForResizing(maxSize, options); + + assertEquals(1, scale); + } + + @Test + public void testGetScaleForResizingLandscapeMaxWidthSameAsMaxSizeReturnsOne() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.outHeight = 1; + options.outWidth = 100; + int maxSize = 100; + + int scale = ImageUtils.getScaleForResizing(maxSize, options); + + assertEquals(1, scale); + } + + @Test + public void testGetScaleForResizingDoubleSizeReturnsTwo() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.outHeight = 100; + options.outWidth = 200; + int maxSize = 100; + + int scale = ImageUtils.getScaleForResizing(maxSize, options); + + assertEquals(2, scale); + } + + @Test + public void testGetScaleForResizingThreeTimesSizeReturnsTwo() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.outHeight = 100; + options.outWidth = 300; + int maxSize = 100; + + int scale = ImageUtils.getScaleForResizing(maxSize, options); + + assertEquals(2, scale); + } + + @Test + public void testGetScaleForResizingEightTimesSizeReturnsEight() { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.outHeight = 100; + options.outWidth = 800; + int maxSize = 100; + + int scale = ImageUtils.getScaleForResizing(maxSize, options); + + assertEquals(8, scale); + } +} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java new file mode 100644 index 000000000000..e02656fe4f3f --- /dev/null +++ b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java @@ -0,0 +1,37 @@ +package org.wordpress.android.util; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; + +public class JSONUtilsTest { + @Test + public void testQueryJSONNullSource1() { + JSONUtils.queryJSON((JSONObject) null, "", ""); + } + + @Test + public void testQueryJSONNullSource2() { + JSONUtils.queryJSON((JSONArray) null, "", ""); + } + + @Test + public void testQueryJSONNullQuery1() { + JSONUtils.queryJSON(new JSONObject(), null, ""); + } + + @Test + public void testQueryJSONNullQuery2() { + JSONUtils.queryJSON(new JSONArray(), null, ""); + } + + @Test + public void testQueryJSONNullReturnValue1() { + JSONUtils.queryJSON(new JSONObject(), "", null); + } + + @Test + public void testQueryJSONNullReturnValue2() { + JSONUtils.queryJSON(new JSONArray(), "", null); + } +} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java new file mode 100644 index 000000000000..0e2d4b301706 --- /dev/null +++ b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java @@ -0,0 +1,106 @@ +package org.wordpress.android.util; + +import org.junit.Test; +import org.wordpress.android.util.PhotonUtils.Quality; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + + +public class PhotonUtilsTest { + @Test + public void getPhotonImageUrlIsEmptyWhenUrlIsNull() { + String photonUrl = PhotonUtils.getPhotonImageUrl(null, 0, 1); + + assertThat(photonUrl, equalTo("")); + } + + @Test + public void getPhotonImageUrlIsEmptyWhenUrlIsEmpty() { + String photonUrl = PhotonUtils.getPhotonImageUrl("", 0, 1); + + assertThat(photonUrl, equalTo("")); + } + + @Test + public void getPhotonImageUrlReturnsImageUrlOnNoScheme() { + String imageUrl = "wordpress.com"; + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1); + + assertThat(photonUrl, equalTo(imageUrl)); + } + + @Test + public void getPhotonImageUrlReturnsMshots() { + String imageUrl = "http://test.wordpress.com/mshots/test.jpg?query=dummy"; + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1); + + assertThat(photonUrl, equalTo("http://test.wordpress.com/mshots/test.jpg?w=0&h=1")); + } + + @Test + public void getPhotonImageUrlReturnsCorrectQuality() { + Map qualities = new HashMap<>(); + qualities.put(Quality.HIGH, "100"); + qualities.put(Quality.MEDIUM, "65"); + qualities.put(Quality.LOW, "35"); + + String imageUrl = "http://test.wordpress.com/test.jpg?query=dummy"; + + for (Quality quality : qualities.keySet()) { + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1, quality); + assertThat(photonUrl, containsString("&quality=" + qualities.get(quality))); + } + } + + @Test + public void getPhotonImageUrlUsesResize() { + String imageUrl = "http://test.wordpress.com/test.jpg?query=dummy"; + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("http://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); + } + + @Test + public void getPhotonImageUrlManageSslOnPhotonUrl() { + String imageUrl = "https://i0.wp.com/test.jpg?query=dummy"; + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("https://i0.wp.com/test.jpg?strip=info&quality=65&resize=2,1")); + + imageUrl = "https://i0.wp.com/test.jpg?query=dummy&ssl=1"; + photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("https://i0.wp.com/test.jpg?strip=info&quality=65&resize=2,1&ssl=1")); + } + + @Test + public void getPhotonImageUrlDoNotUseSslOnWordPressCom() { + String imageUrl = "https://test.wordpress.com/test.jpg?query=dummy"; + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("https://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); + + imageUrl = "https://test.wordpress.com/test.jpg?query=dummy&ssl=1"; + photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("https://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); + } + + @Test + public void getPhotonImageUrlUsesSslOnHttpsImageUrl() { + String imageUrl = "http://mysite.com/test.jpg?query=dummy"; + String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("https://i0.wp.com/mysite.com/test.jpg?strip=info&quality=65&resize=2,1")); + + imageUrl = "https://mysite.com/test.jpg?query=dummy&ssl=1"; + photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); + + assertThat(photonUrl, equalTo("https://i0.wp.com/mysite.com/test.jpg?strip=info&quality=65&resize=2,1&ssl=1")); + } +} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java new file mode 100644 index 000000000000..32435e40e6e8 --- /dev/null +++ b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java @@ -0,0 +1,32 @@ +package org.wordpress.android.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ShortcodeUtilsTest { + @Test + public void testGetVideoPressShortcodeFromId() { + assertEquals("[wpvideo abcd1234]", ShortcodeUtils.getVideoPressShortcodeFromId("abcd1234")); + } + + @Test + public void testGetVideoPressShortcodeFromNullId() { + assertEquals("", ShortcodeUtils.getVideoPressShortcodeFromId(null)); + } + + @Test + public void testGetVideoPressIdFromCorrectShortcode() { + assertEquals("abcd1234", ShortcodeUtils.getVideoPressIdFromShortCode("[wpvideo abcd1234]")); + } + + @Test + public void testGetVideoPressIdFromInvalidShortcode() { + assertEquals("", ShortcodeUtils.getVideoPressIdFromShortCode("[other abcd1234]")); + } + + @Test + public void testGetVideoPressIdFromNullShortcode() { + assertEquals("", ShortcodeUtils.getVideoPressIdFromShortCode(null)); + } +} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java new file mode 100644 index 000000000000..9cf88220712d --- /dev/null +++ b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java @@ -0,0 +1,131 @@ +package org.wordpress.android.util; + +import org.junit.Test; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class UrlUtilsTest { + @Test + public void testGetDomainFromUrlWithEmptyStringDoesNotReturnNull() { + assertNotNull(UrlUtils.getHost("")); + } + + @Test + public void testGetDomainFromUrlWithNoHostDoesNotReturnNull() { + assertNotNull(UrlUtils.getHost("wordpress")); + } + + @Test + public void testGetDomainFromUrlWithHostReturnsHost() { + String url = "http://www.wordpress.com"; + String host = UrlUtils.getHost(url); + + assertTrue(host.equals("www.wordpress.com")); + } + + @Test + public void testAppendUrlParameter1() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test", "preview", "true"); + assertEquals("http://wp.com/test?preview=true", url); + } + + @Test + public void testAppendUrlParameter2() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony", "preview", "true"); + assertEquals("http://wp.com/test?q=pony&preview=true", url); + } + + @Test + public void testAppendUrlParameter3() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony#unicorn", "preview", "true"); + assertEquals("http://wp.com/test?q=pony&preview=true#unicorn", url); + } + + @Test + public void testAppendUrlParameter4() { + String url = UrlUtils.appendUrlParameter("/relative/test", "preview", "true"); + assertEquals("/relative/test?preview=true", url); + } + + @Test + public void testAppendUrlParameter5() { + String url = UrlUtils.appendUrlParameter("/relative/", "preview", "true"); + assertEquals("/relative/?preview=true", url); + } + + @Test + public void testAppendUrlParameter6() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test/", "preview", "true"); + assertEquals("http://wp.com/test/?preview=true", url); + } + + @Test + public void testAppendUrlParameter7() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test/?q=pony", "preview", "true"); + assertEquals("http://wp.com/test/?q=pony&preview=true", url); + } + + @Test + public void testAppendUrlParameters1() { + Map params = new HashMap<>(); + params.put("w", "200"); + params.put("h", "300"); + String url = UrlUtils.appendUrlParameters("http://wp.com/test", params); + if (!url.equals("http://wp.com/test?h=300&w=200") && !url.equals("http://wp.com/test?w=200&h=300")) { + assertTrue("failed test on url: " + url, false); + } + } + + @Test + public void testAppendUrlParameters2() { + Map params = new HashMap<>(); + params.put("h", "300"); + params.put("w", "200"); + String url = UrlUtils.appendUrlParameters("/relative/test", params); + if (!url.equals("/relative/test?h=300&w=200") && !url.equals("/relative/test?w=200&h=300")) { + assertTrue("failed test on url: " + url, false); + } + } + + @Test + public void testHttps1() { + assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com/xmlrpc.php"))); + } + + @Test + public void testHttps2() { + assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com#.b.com/test"))); + } + + @Test + public void testHttps3() { + assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com/xmlrpc.php"))); + } + + @Test + public void testHttps4() { + assertTrue(UrlUtils.isHttps(buildURL("https://wordpress.com"))); + } + + @Test + public void testHttps5() { + assertTrue(UrlUtils.isHttps(buildURL("https://wordpress.com/test#test"))); + } + + private URL buildURL(String address) { + URL url = null; + try { + url = new URL(address); + } catch (MalformedURLException e) { + } + return url; + } +} diff --git a/libs/utils/WordPressUtils/src/main/AndroidManifest.xml b/libs/utils/WordPressUtils/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..d52c0f661462 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java new file mode 100644 index 000000000000..78b9ee6d9fd6 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java @@ -0,0 +1,7 @@ +package org.wordpress.android.util; + +import android.view.accessibility.AccessibilityEvent; + +public interface AccessibilityEventListener { + void onResult(AccessibilityEvent event); +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java new file mode 100644 index 000000000000..3c6ad25eebd5 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java @@ -0,0 +1,108 @@ +package org.wordpress.android.util; + +import android.app.Activity; +import android.content.Context; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; + +import com.google.android.material.snackbar.Snackbar; + +import org.wordpress.android.util.AppLog.T; + +import static android.content.Context.ACCESSIBILITY_SERVICE; +import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED; + +public class AccessibilityUtils { + private static final int SNACKBAR_WITH_ACTION_DURATION_IN_MILLIS = 10000; + + public static boolean isAccessibilityEnabled(Context ctx) { + AccessibilityManager am = (AccessibilityManager) ctx.getSystemService(ACCESSIBILITY_SERVICE); + return am != null && am.isEnabled(); + } + + /** + * If the default duration is LENGTH_INDEFINITE, ignore accessibility duration and return LENGTH_INDEFINITE. + * If the accessibility is enabled, returns increased snackbar duration, otherwise returns defaultDuration. + * + * @param defaultDuration Either be one of the predefined lengths: LENGTH_SHORT, LENGTH_LONG, or a custom duration + * in milliseconds. + */ + public static int getSnackbarDuration(Context ctx, int defaultDuration) { + return defaultDuration == Snackbar.LENGTH_INDEFINITE ? Snackbar.LENGTH_INDEFINITE + : isAccessibilityEnabled(ctx) ? SNACKBAR_WITH_ACTION_DURATION_IN_MILLIS : defaultDuration; + } + + public static void setActionModeDoneButtonContentDescription(@Nullable final Activity activity, + @NonNull final String contentDescription) { + if (activity != null) { + View decorView = activity.getWindow().getDecorView(); + + decorView.post(new Runnable() { + @Override public void run() { + View doneButton = activity.findViewById(androidx.appcompat.R.id.action_mode_close_button); + + if (doneButton != null) { + doneButton.setContentDescription(contentDescription); + } + } + }); + } + } + + public static void addPopulateAccessibilityEventFocusedListener(@NonNull final View target, + @NonNull final AccessibilityEventListener + listener) { + ViewCompat.setAccessibilityDelegate(target, new AccessibilityDelegateCompat() { + @Override public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { + if (event.getEventType() == TYPE_VIEW_ACCESSIBILITY_FOCUSED) { + listener.onResult(event); + } + super.onPopulateAccessibilityEvent(host, event); + } + }); + } + + public static void disableHintAnnouncement(@NonNull TextView textView) { + setAccessibilityDelegateSafely(textView, new AccessibilityDelegateCompat() { + @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setHintText(null); + } + }); + } + + /** + * When the minsdk is 28 this can be replaced by adding android:accessibilityHeading="true" as a property to the + * view's xml declaration. + * @param view that will become a heading. + */ + public static void enableAccessibilityHeading(@NonNull View view) { + setAccessibilityDelegateSafely(view, new AccessibilityDelegateCompat() { + @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setHeading(true); + } + }); + } + + public static void setAccessibilityDelegateSafely(View view, + AccessibilityDelegateCompat accessibilityDelegateCompat) { + if (ViewCompat.hasAccessibilityDelegate(view)) { + final String errorMessage = "View already has an AccessibilityDelegate."; + if (PackageUtils.isDebugBuild()) { + throw new RuntimeException(errorMessage); + } + AppLog.e(T.UTILS, errorMessage); + } else { + ViewCompat.setAccessibilityDelegate(view, accessibilityDelegateCompat); + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java new file mode 100644 index 000000000000..0751b0a5d977 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java @@ -0,0 +1,55 @@ +package org.wordpress.android.util; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.inputmethod.InputMethodManager; + +import androidx.annotation.Nullable; + +public class ActivityUtils { + /** + * Hides the keyboard in the given {@link Activity}'s current focus using the + * {@link InputMethodManager#HIDE_NOT_ALWAYS} flag, which will hide the keyboard unless it was originally shown + * with {@link InputMethodManager#SHOW_FORCED}. + */ + public static void hideKeyboard(Activity activity) { + if (activity != null && activity.getCurrentFocus() != null) { + InputMethodManager inputManager = (InputMethodManager) activity.getSystemService( + Context.INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), + InputMethodManager.HIDE_NOT_ALWAYS); + } + } + + /** + * Hides the keyboard for the given {@link View}. No {@link InputMethodManager} flag is used, therefore the + * keyboard is forcibly hidden regardless of the circumstances. + */ + public static void hideKeyboardForced(@Nullable final View view) { + if (view == null) { + return; + } + InputMethodManager inputMethodManager = + (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + + /** + * Shows the keyboard for the given {@link View} using the {@link InputMethodManager#SHOW_IMPLICIT} flag, + * which is an implicit request (i.e. not requested by the user) to show the keyboard. + */ + public static void showKeyboard(@Nullable final View view) { + if (view == null) { + return; + } + InputMethodManager inputMethodManager = + (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); + } + + public static boolean isDeepLinking(Intent intent) { + return Intent.ACTION_VIEW.equals(intent.getAction()); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java new file mode 100644 index 000000000000..6a09c42f20c1 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 wordpress.org + * + * 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. + */ + +package org.wordpress.android.util; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; + +public class AlertUtils { + /** + * Show Alert Dialog + * @param context + * @param titleId + * @param messageId + */ + public static void showAlert(Context context, int titleId, int messageId) { + Dialog dlg = new AlertDialog.Builder(context) + .setTitle(titleId) + .setPositiveButton(android.R.string.ok, null) + .setMessage(messageId) + .create(); + + dlg.show(); + } + + /** + * Show Alert Dialog + * @param context + * @param titleId + * @param message + */ + public static void showAlert(Context context, int titleId, String message) { + Dialog dlg = new AlertDialog.Builder(context) + .setTitle(titleId) + .setPositiveButton(android.R.string.ok, null) + .setMessage(message) + .create(); + + dlg.show(); + } + + /** + * Show Alert Dialog + * @param context + * @param titleId + * @param messageId + * @param positiveButtontxt + * @param positiveListener + * @param negativeButtontxt + * @param negativeListener + */ + public static void showAlert(Context context, int titleId, int messageId, + CharSequence positiveButtontxt, DialogInterface.OnClickListener positiveListener, + CharSequence negativeButtontxt, DialogInterface.OnClickListener negativeListener) { + Dialog dlg = new AlertDialog.Builder(context) + .setTitle(titleId) + .setPositiveButton(positiveButtontxt, positiveListener) + .setNegativeButton(negativeButtontxt, negativeListener) + .setMessage(messageId) + .setCancelable(false) + .create(); + + dlg.show(); + } + + /** + * Show Alert Dialog + * @param context + * @param titleId + * @param message + * @param positiveButtontxt + * @param positiveListener + */ + public static void showAlert(Context context, int titleId, String message, + CharSequence positiveButtontxt, DialogInterface.OnClickListener positiveListener) { + Dialog dlg = new AlertDialog.Builder(context) + .setTitle(titleId) + .setPositiveButton(positiveButtontxt, positiveListener) + .setMessage(message) + .setCancelable(false) + .create(); + + dlg.show(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java new file mode 100644 index 000000000000..b0bb2a6e467a --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java @@ -0,0 +1,381 @@ +package org.wordpress.android.util; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.NonNull; + +import org.wordpress.android.util.helpers.logfile.LogFileCleaner; +import org.wordpress.android.util.helpers.logfile.LogFileProvider; +import org.wordpress.android.util.helpers.logfile.LogFileWriter; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.NoSuchElementException; +import java.util.TimeZone; + +import static java.lang.String.format; + +/** + * simple wrapper for Android log calls, enables recording and displaying log + */ +public class AppLog { + // T for Tag + public enum T { + READER, + EDITOR, + MEDIA, + NUX, + API, + STATS, + UTILS, + NOTIFS, + DB, + POSTS, + PAGES, + COMMENTS, + THEMES, + TESTS, + PROFILING, + SIMPERIUM, + SUGGESTION, + MAIN, + SETTINGS, + PLANS, + PEOPLE, + SHARING, + PLUGINS, + ACTIVITY_LOG, + JETPACK_REMOTE_INSTALL, + SUPPORT, + SITE_CREATION, + DOMAIN_REGISTRATION, + FEATURE_ANNOUNCEMENT + } + + public static final String TAG = "WordPress"; + public static final int HEADER_LINE_COUNT = 2; + private static boolean mEnableRecording = false; + private static List mListeners = new ArrayList<>(0); + private static TimeZone mUtcTimeZone = TimeZone.getTimeZone("UTC"); + + private AppLog() { + throw new AssertionError(); + } + + /** + * Capture log so it can be displayed by AppLogViewerActivity + * @param enable A boolean flag to capture log. Default is false, pass true to enable recording + */ + public static void enableRecording(boolean enable) { + mEnableRecording = enable; + } + + public static void addListener(@NonNull AppLogListener listener) { + mListeners.add(listener); + } + + public static void removeListeners() { + mListeners.clear(); + } + + public interface AppLogListener { + void onLog(T tag, LogLevel logLevel, String message); + } + + /** + * Add a LogFileWriter that will persist logs to disk + * @param context The current application context + * @param maxLogCount The maximum number of logs that should be stored + */ + public static void enableLogFilePersistence(Context context, int maxLogCount) { + LogFileProvider logFileProvider = LogFileProvider.fromContext(context); + new LogFileCleaner(logFileProvider, maxLogCount).clean(); + + sLogFileWriter = new LogFileWriter(logFileProvider); + sLogFileWriter.write(getAppInfoHeaderText(context) + "\n"); + sLogFileWriter.write(getDeviceInfoHeaderText(context) + "\n"); + } + + private static LogFileWriter sLogFileWriter; + + /** + * Sends a VERBOSE log message + * @param tag Used to identify the source of a log message. + * It usually identifies the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + public static void v(T tag, String message) { + message = StringUtils.notNullStr(message); + Log.v(TAG + "-" + tag.toString(), message); + addEntry(tag, LogLevel.v, message); + } + + /** + * Sends a DEBUG log message + * @param tag Used to identify the source of a log message. + * It usually identifies the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + public static void d(T tag, String message) { + message = StringUtils.notNullStr(message); + Log.d(TAG + "-" + tag.toString(), message); + addEntry(tag, LogLevel.d, message); + } + + /** + * Sends a INFO log message + * @param tag Used to identify the source of a log message. + * It usually identifies the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + public static void i(T tag, String message) { + message = StringUtils.notNullStr(message); + Log.i(TAG + "-" + tag.toString(), message); + addEntry(tag, LogLevel.i, message); + } + + /** + * Sends a WARN log message + * @param tag Used to identify the source of a log message. + * It usually identifies the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + public static void w(T tag, String message) { + message = StringUtils.notNullStr(message); + Log.w(TAG + "-" + tag.toString(), message); + addEntry(tag, LogLevel.w, message); + } + + /** + * Sends a ERROR log message + * @param tag Used to identify the source of a log message. + * It usually identifies the class or activity where the log call occurs. + * @param message The message you would like logged. + */ + public static void e(T tag, String message) { + message = StringUtils.notNullStr(message); + Log.e(TAG + "-" + tag.toString(), message); + addEntry(tag, LogLevel.e, message); + } + + /** + * Send a ERROR log message and log the exception. + * @param tag Used to identify the source of a log message. + * It usually identifies the class or activity where the log call occurs. + * @param message The message you would like logged. + * @param tr An exception to log + */ + public static void e(T tag, String message, Throwable tr) { + message = StringUtils.notNullStr(message); + Log.e(TAG + "-" + tag.toString(), message, tr); + addEntry(tag, LogLevel.e, message + " - exception: " + tr.getMessage()); + addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr)); + } + + /** + * Sends a ERROR log message and the exception with StackTrace + * @param tag Used to identify the source of a log message. It usually identifies the class or activity where the + * log call occurs. + * @param tr An exception to log to get StackTrace + */ + public static void e(T tag, Throwable tr) { + Log.e(TAG + "-" + tag.toString(), tr.getMessage(), tr); + addEntry(tag, LogLevel.e, tr.getMessage()); + addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr)); + } + + /** + * Sends a ERROR log message + * @param tag Used to identify the source of a log message. It usually identifies the class or activity where the + * log call occurs. + * @param volleyErrorMsg + * @param statusCode + */ + public static void e(T tag, String volleyErrorMsg, int statusCode) { + if (TextUtils.isEmpty(volleyErrorMsg)) { + return; + } + String logText; + if (statusCode == -1) { + logText = volleyErrorMsg; + } else { + logText = volleyErrorMsg + ", status " + statusCode; + } + Log.e(TAG + "-" + tag.toString(), logText); + addEntry(tag, LogLevel.w, logText); + } + + // -------------------------------------------------------------------------------------------------------- + + private static final int MAX_ENTRIES = 99; + + public enum LogLevel { + v, d, i, w, e; + } + + private static class LogEntry { + final LogLevel mLogLevel; + final String mLogText; + final java.util.Date mDate; + final T mLogTag; + + LogEntry(LogLevel logLevel, String logText, T logTag) { + mLogLevel = logLevel; + mDate = new Date(); + if (logText == null) { + mLogText = "null"; + } else { + mLogText = logText; + } + mLogTag = logTag; + } + + private String formatLogDate() { + SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd kk:mm", Locale.US); + sdf.setTimeZone(mUtcTimeZone); + return sdf.format(mDate); + } + + private String toHtml() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + sb.append(formatLogDate()).append(" "); + sb.append(mLogTag.name()).append(" "); + sb.append(mLogLevel.name()); + sb.append("] "); + sb.append(TextUtils.htmlEncode(mLogText).replace("\n", "
    ")); + return sb.toString(); + } + + @Override + public @NonNull String toString() { + return "[" + + formatLogDate() + + " " + + mLogTag.name() + + "] " + + mLogText + + "\n"; + } + } + + private static class LogEntryList extends ArrayList { + private synchronized boolean addEntry(LogEntry entry) { + if (size() >= MAX_ENTRIES) { + removeFirstEntry(); + } + return add(entry); + } + + private void removeFirstEntry() { + Iterator it = iterator(); + if (!it.hasNext()) { + return; + } + try { + remove(it.next()); + } catch (NoSuchElementException e) { + // ignore + } + } + } + + private static LogEntryList mLogEntries = new LogEntryList(); + + private static void addEntry(T tag, LogLevel level, String text) { + // Call our listeners if any + for (AppLogListener listener : mListeners) { + listener.onLog(tag, level, text); + } + // Record entry if enabled + if (mEnableRecording) { + LogEntry entry = new LogEntry(level, text, tag); + mLogEntries.addEntry(entry); + + if (sLogFileWriter != null) { + sLogFileWriter.write(entry.toString()); + } + } + } + + private static String getStringStackTrace(Throwable throwable) { + StringWriter errors = new StringWriter(); + throwable.printStackTrace(new PrintWriter(errors)); + return errors.toString(); + } + + + private static String getAppInfoHeaderText(Context context) { + StringBuilder sb = new StringBuilder(); + PackageManager packageManager = context.getPackageManager(); + PackageInfo pkInfo = PackageUtils.getPackageInfo(context); + + ApplicationInfo applicationInfo = pkInfo != null ? pkInfo.applicationInfo : null; + String appName; + if (applicationInfo != null && packageManager.getApplicationLabel(applicationInfo) != null) { + appName = packageManager.getApplicationLabel(applicationInfo).toString(); + } else { + appName = "Unknown"; + } + sb.append(appName).append(" - ").append(PackageUtils.getVersionName(context)) + .append(" - Version code: ").append(PackageUtils.getVersionCode(context)); + return sb.toString(); + } + + private static String getDeviceInfoHeaderText(Context context) { + return "Android device name: " + DeviceUtils.getInstance().getDeviceName(context); + } + + /** + * Returns entire log as html for display (see AppLogViewerActivity) + * @param context + * @return Arraylist of Strings containing log messages + */ + public static ArrayList toHtmlList(Context context) { + ArrayList items = new ArrayList(); + + // add version & device info - be sure to change HEADER_LINE_COUNT if additional lines are added + items.add("" + getAppInfoHeaderText(context) + ""); + items.add("" + getDeviceInfoHeaderText(context) + ""); + + Iterator it = new ArrayList<>(mLogEntries).iterator(); + while (it.hasNext()) { + items.add(it.next().toHtml()); + } + return items; + } + + /** + * Converts the entire log to plain text + * @param context + * @return The log as plain text + */ + public static synchronized String toPlainText(Context context) { + StringBuilder sb = new StringBuilder(); + + // add version & device info + sb.append(getAppInfoHeaderText(context)).append("\n") + .append(getDeviceInfoHeaderText(context)).append("\n\n"); + + Iterator it = new ArrayList<>(mLogEntries).iterator(); + int lineNum = 1; + while (it.hasNext()) { + LogEntry entry = it.next(); + sb.append(format(Locale.US, "%02d - ", lineNum)) + .append(entry.toString()); + lineNum++; + } + return sb.toString(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java new file mode 100644 index 000000000000..4cdc2911058f --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java @@ -0,0 +1,223 @@ +package org.wordpress.android.util; + +import android.app.Notification; +import android.app.Service; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Binder; +import android.os.IBinder; + +import androidx.annotation.CallSuper; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationManagerCompat; + +import org.greenrobot.eventbus.EventBus; +import org.wordpress.android.util.AutoForeground.ServiceState; + +import java.util.HashMap; +import java.util.Map; + +public abstract class AutoForeground + extends Service { + public static final int NOTIFICATION_ID_PROGRESS = 1; + public static final int NOTIFICATION_ID_SUCCESS = 2; + public static final int NOTIFICATION_ID_FAILURE = 3; + + public interface ServiceState { + boolean isIdle(); + + boolean isInProgress(); + + boolean isError(); + + boolean isTerminal(); + + String getStepName(); + } + + public static class ServiceEventConnection { + private final ServiceConnection mServiceConnection; + + public ServiceEventConnection(Context context, Class clazz, Object client) { + EventBus.getDefault().register(client); + + mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + // nothing here + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + // nothing here + } + }; + + context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); + } + + public void disconnect(Context context, Object client) { + context.unbindService(mServiceConnection); + EventBus.getDefault().unregister(client); + } + } + + private class LocalBinder extends Binder { + } + + private final IBinder mBinder = new LocalBinder(); + + private final Class mStateClass; + + private boolean mIsForeground; + + protected abstract void onProgressStart(); + + protected abstract void onProgressEnd(); + + protected abstract Notification getNotification(StateClass state); + + protected abstract void trackStateUpdate(Map props); + + @SuppressWarnings("unchecked") + protected AutoForeground(StateClass initialState) { + mStateClass = (Class) initialState.getClass(); + + // initialize the sticky phase if it hasn't already + if (EventBus.getDefault().getStickyEvent(mStateClass) == null) { + notifyState(initialState); + } + } + + public boolean isForeground() { + return mIsForeground; + } + + @Nullable + private StateClass getState() { + return getState(mStateClass); + } + + @Nullable + protected static StateClass getState(Class stateClass) { + return EventBus.getDefault().getStickyEvent(stateClass); + } + + @Nullable + @CallSuper + @Override + public IBinder onBind(Intent intent) { + clearAllNotifications(); + return mBinder; + } + + @CallSuper + @Override + public void onRebind(Intent intent) { + super.onRebind(intent); + + clearAllNotifications(); + background(); + } + + @CallSuper + @Override + public boolean onUnbind(Intent intent) { + if (!hasConnectedClients()) { + final StateClass state = getState(); + if (state != null && state.isInProgress()) { + promoteForeground(state); + } + } + + return true; // call onRebind() if new clients connect + } + + protected void clearAllNotifications() { + NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); + NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_SUCCESS); + NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_FAILURE); + } + + private EventBus getEventBus() { + return EventBus.getDefault(); + } + + private boolean hasConnectedClients() { + return getEventBus().hasSubscriberForEvent(mStateClass); + } + + private void promoteForeground(StateClass currentState) { + startForeground(NOTIFICATION_ID_PROGRESS, getNotification(currentState)); + mIsForeground = true; + } + + private void background() { + stopForeground(true); + mIsForeground = false; + } + + @CallSuper + protected void setState(StateClass newState) { + StateClass currentState = getState(); + if ((currentState == null || !currentState.isInProgress()) && newState.isInProgress()) { + onProgressStart(); + } + + track(newState); + notifyState(newState); + + if (newState.isTerminal()) { + onProgressEnd(); + stopSelf(); + } + } + + protected void track(ServiceState state) { + Map props = new HashMap<>(); + props.put("login_phase", state == null ? "null" : state.getStepName()); + props.put("login_service_is_foreground", isForeground()); + trackStateUpdate(props); + } + + protected static void clearServiceState(Class klass) { + EventBus.getDefault().removeStickyEvent(klass); + } + + @CallSuper + protected void notifyState(StateClass state) { + // sticky emit the state. The stickiness serves as a state keeping mechanism for clients to re-read upon connect + getEventBus().postSticky(state); + + if (hasConnectedClients()) { + // there are connected clients so, nothing more to do here + return; + } + + // ok, no connected clients so, update might need to be delivered to a notification as well + + if (state.isIdle()) { + // no need to have a notification when idle + return; + } + + if (state.isInProgress()) { + // operation still is progress so, update the notification + NotificationManagerCompat.from(this).notify(NOTIFICATION_ID_PROGRESS, getNotification(state)); + return; + } + + // operation has ended so, demote the Service to a background one + background(); + + // dismiss the sticky notification + NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); + + // put out a simple success/failure notification + NotificationManagerCompat.from(this).notify( + state.isError() ? NOTIFICATION_ID_FAILURE : NOTIFICATION_ID_SUCCESS, + getNotification(state)); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java new file mode 100644 index 000000000000..db8c8b32b592 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java @@ -0,0 +1,79 @@ +package org.wordpress.android.util; + +import android.app.Notification; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; + +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.StringRes; +import androidx.core.app.NotificationCompat; + +import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_FAILURE; +import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_PROGRESS; +import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_SUCCESS; + +public class AutoForegroundNotification { + private static Intent getResumeIntent(Context context) { + // Let's get an Intent with the sole purpose of _resuming_ the app from the background + Intent resumeIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); + + // getLaunchIntentForPackage() seems to set the Package Name but if we construct a launcher Intent manually + // the package name is not set so, let's null it out here to match the manual Intent. + resumeIntent.setSelector(null); + resumeIntent.setPackage(null); + + return resumeIntent; + } + + private static NotificationCompat.Builder getNotificationBuilder(Context context, String channelId, int requestCode, + @StringRes int title, @StringRes int content, + @DrawableRes int icon, @ColorRes int accentColor) { + NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); + bigTextStyle.setBigContentTitle(context.getString(title)); + bigTextStyle.bigText(context.getString(content)); + + return new NotificationCompat.Builder(context, channelId) + .setStyle(bigTextStyle) + .setContentTitle(context.getString(title)) + .setContentText(context.getString(content)) + .setSmallIcon(icon) + .setColor(context.getResources().getColor(accentColor)) + .setAutoCancel(true) + .setOnlyAlertOnce(true) + .setContentIntent(PendingIntent.getActivity( + context, + requestCode, + getResumeIntent(context), + PendingIntent.FLAG_ONE_SHOT)); + } + + public static Notification progress(Context context, String channelId, int progress, @StringRes int title, + @StringRes int content, + @DrawableRes int icon, @ColorRes int accentColor) { + return getNotificationBuilder(context, channelId, NOTIFICATION_ID_PROGRESS, title, content, icon, accentColor) + .setProgress(100, progress, false) + .build(); + } + + public static Notification progressIndeterminate(Context context, String channelId, @StringRes int title, + @StringRes int content, @DrawableRes int icon, + @ColorRes int accentColor) { + return getNotificationBuilder(context, channelId, NOTIFICATION_ID_PROGRESS, title, content, icon, accentColor) + .setProgress(0, 0, true) + .build(); + } + + public static Notification success(Context context, String channelId, @StringRes int title, @StringRes int content, + @DrawableRes int icon, @ColorRes int accentColor) { + return getNotificationBuilder(context, channelId, NOTIFICATION_ID_SUCCESS, title, content, icon, accentColor) + .build(); + } + + public static Notification failure(Context context, String channelId, @StringRes int title, @StringRes int content, + @DrawableRes int icon, @ColorRes int accentColor) { + return getNotificationBuilder(context, channelId, NOTIFICATION_ID_FAILURE, title, content, icon, accentColor) + .build(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java new file mode 100644 index 000000000000..3f8f0fee74e4 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java @@ -0,0 +1,251 @@ +package org.wordpress.android.util; + +import android.content.Context; +import android.text.TextUtils; +import android.text.format.DateUtils; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class DateTimeUtils { + private DateTimeUtils() { + throw new AssertionError(); + } + + // See http://drdobbs.com/java/184405382 + private static final ThreadLocal ISO8601_FORMAT = new ThreadLocal() { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); + } + }; + + public static String javaDateToTimeSpan(final Date date, Context context, long currentTime) { + if (date == null) { + return ""; + } + + long passedTime = date.getTime(); + + // return "now" if less than a minute has elapsed + long secondsSince = (currentTime - passedTime) / 1000; + if (secondsSince < 60) { + return context.getString(R.string.timespan_now); + } + + long daysSince = secondsSince / (60 * 60 * 24); + + // less than a year old, let `DateUtils.getRelativeTimeSpanString` do the job + if (daysSince < 365) { + return DateUtils.getRelativeTimeSpanString(passedTime, currentTime, DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_ALL).toString(); + } + + // date is older, so include year (ex: Jan 30, 2013) + return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_ABBREV_ALL); + } + + /** + * Converts a date to a localized relative time span ("Now", "8 hr. ago", "Yesterday", "3 days ago", "Jul 10, 1940") + * We're using a call to `DateUtils.getRelativeTimeSpanString` in most cases. + */ + public static String javaDateToTimeSpan(final Date date, Context context) { + return javaDateToTimeSpan(date, context, System.currentTimeMillis()); + } + + /** + * Given an ISO 8601-formatted date as a String, returns a {@link Date}. + */ + public static Date dateFromIso8601(final String strDate) { + try { + DateFormat formatter = ISO8601_FORMAT.get(); + return formatter.parse(strDate); + } catch (ParseException e) { + return null; + } + } + + /** + * Given an ISO 8601-formatted date as a String, returns a {@link Date} in UTC. + */ + public static Date dateUTCFromIso8601(String iso8601date) { + try { + iso8601date = iso8601date.replace("Z", "+0000").replace("+00:00", "+0000"); + DateFormat formatter = ISO8601_FORMAT.get(); + formatter.setTimeZone(TimeZone.getTimeZone("UTC")); + return formatter.parse(iso8601date); + } catch (ParseException e) { + return null; + } + } + + /** + * Given a {@link Date}, returns an ISO 8601-formatted String. + */ + public static String iso8601FromDate(Date date) { + if (date == null) { + return ""; + } + DateFormat formatter = ISO8601_FORMAT.get(); + return formatter.format(date); + } + + /** + * Given a {@link Date}, returns an ISO 8601-formatted String in UTC. + */ + public static String iso8601UTCFromDate(Date date) { + if (date == null) { + return ""; + } + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat formatter = ISO8601_FORMAT.get(); + formatter.setTimeZone(tz); + + String iso8601date = formatter.format(date); + + // Use "+00:00" notation rather than "+0000" to be consistent with the WP.COM API + return iso8601date.replace("+0000", "+00:00"); + } + + /** + * Returns the current UTC date. + * + * @deprecated This method doesn't work as expected and shouldn't be used in production code. It doesn't take + * into account that `Date` class uses TimeZone.getDefault(). It substracts the currentOffsetFromUTC, but the + * final date still uses system default timezone. + */ + @Deprecated + public static Date nowUTC() { + Date dateTimeNow = new Date(); + return localDateToUTC(dateTimeNow); + } + + /** + * + * @deprecated This method doesn't work as expected and shouldn't be used in production code. It doesn't take + * into account that `Date` class uses TimeZone.getDefault(). It substracts the currentOffsetFromUTC, but the + * final date still uses system default timezone. + */ + @Deprecated + public static Date localDateToUTC(Date dtLocal) { + if (dtLocal == null) { + return null; + } + TimeZone tz = TimeZone.getDefault(); + int currentOffsetFromUTC = tz.getRawOffset() + (tz.inDaylightTime(dtLocal) ? tz.getDSTSavings() : 0); + return new Date(dtLocal.getTime() - currentOffsetFromUTC); + } + + // Routines to return a diff between two dates - always return a positive number + + public static int daysBetween(Date dt1, Date dt2) { + long hrDiff = hoursBetween(dt1, dt2); + if (hrDiff == 0) { + return 0; + } + return (int) (hrDiff / 24); + } + + public static int hoursBetween(Date dt1, Date dt2) { + long minDiff = minutesBetween(dt1, dt2); + if (minDiff == 0) { + return 0; + } + return (int) (minDiff / 60); + } + + public static int minutesBetween(Date dt1, Date dt2) { + long msDiff = millisecondsBetween(dt1, dt2); + if (msDiff == 0) { + return 0; + } + return (int) (msDiff / 60000); + } + + public static int secondsBetween(Date dt1, Date dt2) { + long msDiff = millisecondsBetween(dt1, dt2); + if (msDiff == 0) { + return 0; + } + return (int) (msDiff / 1000); + } + + public static long millisecondsBetween(Date dt1, Date dt2) { + if (dt1 == null || dt2 == null) { + return 0; + } + return Math.abs(dt1.getTime() - dt2.getTime()); + } + + public static boolean isSameYear(Date dt1, Date dt2) { + if (dt1 == null || dt2 == null) { + return false; + } + return dt1.getYear() == dt2.getYear(); + } + + public static boolean isSameMonthAndYear(Date dt1, Date dt2) { + if (dt1 == null || dt2 == null) { + return false; + } + return dt1.getYear() == dt2.getYear() && dt1.getMonth() == dt2.getMonth(); + } + + // Routines involving Unix timestamps (GMT assumed) + + /** + * Given an ISO 8601-formatted date as a String, returns the corresponding UNIX timestamp. + */ + public static long timestampFromIso8601(final String strDate) { + return timestampFromIso8601Millis(strDate) / 1000; + } + + /** + * Given an ISO 8601-formatted date as a String, returns the corresponding timestamp in milliseconds. + * + * @return 0 if the parameter is null, empty or not a date. + */ + public static long timestampFromIso8601Millis(final String strDate) { + if (TextUtils.isEmpty(strDate)) { + return 0; + } + Date date = dateFromIso8601(strDate); + if (date == null) { + return 0; + } + return date.getTime(); + } + + /** + * Given a UNIX timestamp, returns the corresponding {@link Date}. + */ + public static Date dateFromTimestamp(long timestamp) { + return new java.util.Date(timestamp * 1000); + } + + /** + * Given a UNIX timestamp, returns an ISO 8601-formatted date as a String. + */ + public static String iso8601FromTimestamp(long timestamp) { + return iso8601FromDate(dateFromTimestamp(timestamp)); + } + + /** + * Given a UNIX timestamp, returns an ISO 8601-formatted date in UTC as a String. + */ + public static String iso8601UTCFromTimestamp(long timestamp) { + return iso8601UTCFromDate(dateFromTimestamp(timestamp)); + } + + /** + * Given a UNIX timestamp, returns a relative time span ("8h", "3d", etc.). + */ + public static String timeSpanFromTimestamp(long timestamp, Context context) { + Date dateGMT = dateFromTimestamp(timestamp); + return javaDateToTimeSpan(dateGMT, context); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java new file mode 100644 index 000000000000..dcd7d1d4ec0a --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java @@ -0,0 +1,179 @@ +package org.wordpress.android.util; + +import android.app.KeyguardManager; +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Environment; +import android.os.StatFs; + +import androidx.annotation.NonNull; + +import org.wordpress.android.util.AppLog.T; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class DeviceUtils { + private static final String APP_RUNTIME_ON_CHROME_FLAG = "org.chromium.arc.device_management"; + + private static DeviceUtils instance; + private boolean mIsKindleFire = false; + + public boolean isKindleFire() { + return mIsKindleFire; + } + + public static DeviceUtils getInstance() { + if (instance == null) { + instance = new DeviceUtils(); + } + return instance; + } + + private DeviceUtils() { + mIsKindleFire = android.os.Build.MODEL.equalsIgnoreCase("kindle fire") ? true : false; + } + + /** + * Checks camera availability recursively based on API level. + * + * TODO: change "android.hardware.camera.front" and "android.hardware.camera.any" to + * {@link PackageManager#FEATURE_CAMERA_FRONT} and {@link PackageManager#FEATURE_CAMERA_ANY}, + * respectively, once they become accessible or minSdk version is incremented. + * + * @param context The context. + * @return Whether camera is available. + */ + public boolean hasCamera(Context context) { + final PackageManager pm = context.getPackageManager(); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { + return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) + || pm.hasSystemFeature("android.hardware.camera.front"); + } + + return pm.hasSystemFeature("android.hardware.camera.any"); + } + + public String getDeviceName(Context context) { + String manufacturer = Build.MANUFACTURER; + String undecodedModel = Build.MODEL; + String model = null; + + try { + Properties prop = new Properties(); + InputStream fileStream; + // Read the device name from a precomplied list: + // see http://making.meetup.com/post/29648976176/human-readble-android-device-names + fileStream = context.getAssets().open("android_models.properties"); + prop.load(fileStream); + fileStream.close(); + String decodedModel = prop.getProperty(undecodedModel.replaceAll(" ", "_")); + if (decodedModel != null && !decodedModel.trim().equals("")) { + model = decodedModel; + } + } catch (IOException e) { + AppLog.e(T.UTILS, "Can't read `android_models.properties` file from assets, or it's in the wrong form.", e); + AppLog.d(T.UTILS, + "If you need more info about the file, please check the reference implementation available here: " + + "https://github.com/wordpress-mobile/WordPress-Android/blob/dd989429bd701a66bcba911de08f2e8d336798ef" + + "/WordPress/src/main/assets/android_models.properties"); + } + + if (model == null) { // Device model not found in the list + if (undecodedModel.startsWith(manufacturer)) { + model = capitalize(undecodedModel); + } else { + model = capitalize(manufacturer) + " " + undecodedModel; + } + } + return model; + } + + public boolean isDeviceLocked(Context context) { + KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); + return myKM.inKeyguardRestrictedInputMode(); + } + + /** + * Checks if the current device runtime is ARC which effectively means it is a chromebook. + * + * @param context The context. + * @return Whether the device is a chromebook. + */ + public boolean isChromebook(Context context) { + return context.getPackageManager().hasSystemFeature(APP_RUNTIME_ON_CHROME_FLAG); + } + + /** + * Checks if the device has a hardware keyboard - note this will return true for emulators + */ + public boolean hasHardwareKeyboard(@NonNull Context context) { + return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS; + } + + private String capitalize(String s) { + if (s == null || s.length() == 0) { + return ""; + } + char first = s.charAt(0); + if (Character.isUpperCase(first)) { + return s; + } else { + return Character.toUpperCase(first) + s.substring(1); + } + } + + // Taken and modified from https://stackoverflow.com/a/8133437 + public static String getTotalAvailableMemorySize() { + File internalMemoryPath = Environment.getDataDirectory(); + long availableInternal = availableSpaceAtFilePath(internalMemoryPath); + long availableExternal = 0L; + if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { + File externalStoragePath = Environment.getExternalStorageDirectory(); + availableExternal = availableSpaceAtFilePath(externalStoragePath); + } + return formatSize(availableInternal + availableExternal); + } + + private static long availableSpaceAtFilePath(File path) { + StatFs stat = new StatFs(path.getPath()); + long bytesAvailable; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { + return stat.getBlockSizeLong() * stat.getAvailableBlocksLong(); + } else { + //noinspection deprecation - Deprecated calls properly handled + bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks(); + } + return bytesAvailable; + } + + private static String formatSize(long size) { + String suffix = null; + + if (size >= 1024) { + suffix = "KB"; + size /= 1024; + if (size >= 1024) { + suffix = "MB"; + size /= 1024; + } + } + + StringBuilder resultBuffer = new StringBuilder(Long.toString(size)); + + int commaOffset = resultBuffer.length() - 3; + while (commaOffset > 0) { + resultBuffer.insert(commaOffset, ','); + commaOffset -= 3; + } + + if (suffix != null) { + resultBuffer.append(suffix); + } + return resultBuffer.toString(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java new file mode 100644 index 000000000000..ec4e0b69313a --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java @@ -0,0 +1,88 @@ +package org.wordpress.android.util; + +import android.app.Activity; +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; + +/** + * EditText utils + */ +public class EditTextUtils { + private EditTextUtils() { + throw new AssertionError(); + } + + /** + * returns non-null text string from passed TextView + */ + public static String getText(TextView textView) { + return (textView != null) ? textView.getText().toString() : ""; + } + + /** + * moves caret to end of text + */ + public static void moveToEnd(EditText edit) { + if (edit.getText() == null) { + return; + } + edit.setSelection(edit.getText().toString().length()); + } + + /** + * returns true if nothing has been entered into passed editor + */ + public static boolean isEmpty(EditText edit) { + return TextUtils.isEmpty(getText(edit)); + } + + /** + * hide the soft keyboard for the passed EditText + * + * @deprecated Use {@link ActivityUtils#hideKeyboard(Activity)} or {@link ActivityUtils#hideKeyboardForced(View)} + * instead. + */ + // TODO: Replace instances with ActivityUtils#showKeyboard(Activity) or ActivityUtils#showKeyboardForced(View) to + // consolidate similar methods and favor library version. + @Deprecated + public static void hideSoftInput(EditText edit) { + if (edit == null) { + return; + } + + InputMethodManager imm = getInputMethodManager(edit); + if (imm != null) { + imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); + } + } + + /** + * show the soft keyboard for the passed EditText + * + * @deprecated Use {@link ActivityUtils#showKeyboard(View)} instead. + */ + // TODO: Replace instances with ActivityUtils#showKeyboard(View) to consolidate similar methods and favor library + // version. + @Deprecated + public static void showSoftInput(EditText edit) { + if (edit == null) { + return; + } + + edit.requestFocus(); + + InputMethodManager imm = getInputMethodManager(edit); + if (imm != null) { + imm.showSoftInput(edit, InputMethodManager.SHOW_IMPLICIT); + } + } + + private static InputMethodManager getInputMethodManager(EditText edit) { + Context context = edit.getContext(); + return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java new file mode 100644 index 000000000000..08d0d3417c2d --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java @@ -0,0 +1,110 @@ +package org.wordpress.android.util; + +import android.text.Html; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.text.style.ImageSpan; +import android.util.SparseArray; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES; + +public class EmoticonsUtils { + public static final int EMOTICON_COLOR = 0xFF21759B; + private static final boolean HAS_EMOJI = SDK_INT >= VERSION_CODES.JELLY_BEAN; + private static final Map WP_SMILIES; + public static final SparseArray WP_SMILIES_CODE_POINT_TO_TEXT; + + static { + Map smilies = new HashMap(); + smilies.put("icon_mrgreen.gif", HAS_EMOJI ? "\uD83D\uDE00" : ":mrgreen:"); + smilies.put("icon_neutral.gif", HAS_EMOJI ? "\uD83D\uDE14" : ":|"); + smilies.put("icon_twisted.gif", HAS_EMOJI ? "\uD83D\uDE16" : ":twisted:"); + smilies.put("icon_arrow.gif", HAS_EMOJI ? "\u27A1" : ":arrow:"); + smilies.put("icon_eek.gif", HAS_EMOJI ? "\uD83D\uDE32" : "8-O"); + smilies.put("icon_smile.gif", HAS_EMOJI ? "\uD83D\uDE0A" : ":)"); + smilies.put("icon_confused.gif", HAS_EMOJI ? "\uD83D\uDE15" : ":?"); + smilies.put("icon_cool.gif", HAS_EMOJI ? "\uD83D\uDE0A" : "8)"); + smilies.put("icon_evil.gif", HAS_EMOJI ? "\uD83D\uDE21" : ":evil:"); + smilies.put("icon_biggrin.gif", HAS_EMOJI ? "\uD83D\uDE03" : ":D"); + smilies.put("icon_idea.gif", HAS_EMOJI ? "\uD83D\uDCA1" : ":idea:"); + smilies.put("icon_redface.gif", HAS_EMOJI ? "\uD83D\uDE33" : ":oops:"); + smilies.put("icon_razz.gif", HAS_EMOJI ? "\uD83D\uDE1D" : ":P"); + smilies.put("icon_rolleyes.gif", HAS_EMOJI ? "\uD83D\uDE0F" : ":roll:"); + smilies.put("icon_wink.gif", HAS_EMOJI ? "\uD83D\uDE09" : ";)"); + smilies.put("icon_cry.gif", HAS_EMOJI ? "\uD83D\uDE22" : ":'("); + smilies.put("icon_surprised.gif", HAS_EMOJI ? "\uD83D\uDE32" : ":o"); + smilies.put("icon_lol.gif", HAS_EMOJI ? "\uD83D\uDE03" : ":lol:"); + smilies.put("icon_mad.gif", HAS_EMOJI ? "\uD83D\uDE21" : ":x"); + smilies.put("icon_sad.gif", HAS_EMOJI ? "\uD83D\uDE1E" : ":("); + smilies.put("icon_exclaim.gif", HAS_EMOJI ? "\u2757" : ":!:"); + smilies.put("icon_question.gif", HAS_EMOJI ? "\u2753" : ":?:"); + + WP_SMILIES = Collections.unmodifiableMap(smilies); + + WP_SMILIES_CODE_POINT_TO_TEXT = new SparseArray(20); + WP_SMILIES_CODE_POINT_TO_TEXT.put(10145, ":arrow:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128161, ":idea:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128512, ":mrgreen:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128515, ":D"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128522, ":)"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128521, ";)"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128532, ":|"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128533, ":?"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128534, ":twisted:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128542, ":("); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128545, ":evil:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128546, ":'("); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128562, ":o"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128563, ":oops:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(128527, ":roll:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(10071, ":!:"); + WP_SMILIES_CODE_POINT_TO_TEXT.put(10067, ":?:"); + } + + public static String lookupImageSmiley(String url) { + return lookupImageSmiley(url, ""); + } + + public static String lookupImageSmiley(String url, String ifNone) { + if (url == null) { + return ifNone; + } + String file = url.substring(url.lastIndexOf("/") + 1); + if (WP_SMILIES.containsKey(file)) { + return WP_SMILIES.get(file); + } + return ifNone; + } + + public static Spanned replaceEmoticonsWithEmoji(SpannableStringBuilder html) { + ImageSpan[] imgs = html.getSpans(0, html.length(), ImageSpan.class); + for (ImageSpan img : imgs) { + String emoticon = EmoticonsUtils.lookupImageSmiley(img.getSource()); + if (!emoticon.equals("")) { + int start = html.getSpanStart(img); + html.replace(start, html.getSpanEnd(img), emoticon); + html.setSpan(new ForegroundColorSpan(EMOTICON_COLOR), start, + start + emoticon.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + html.removeSpan(img); + } + } + return html; + } + + public static String replaceEmoticonsWithEmoji(final String text) { + if (text != null && text.contains("icon_")) { + final SpannableStringBuilder html = + (SpannableStringBuilder) replaceEmoticonsWithEmoji((SpannableStringBuilder) Html.fromHtml(text)); + // Html.toHtml() is used here rather than toString() since the latter strips html + return Html.toHtml(html); + } else { + return text; + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java new file mode 100644 index 000000000000..cadee0b6906f --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java @@ -0,0 +1,61 @@ +package org.wordpress.android.util; + +import android.text.TextUtils; + +import java.io.File; + +public class FileUtils { + /** + * Returns the length of the file denoted by this abstract pathname. + * The return value is unspecified if this pathname denotes a directory. + * + * @return The length, in bytes, of the file denoted by this abstract + * pathname, or -1L if the file does not exist, or an + * exception is thrown accessing the file. + * Some operating systems may return 0L for pathnames + * denoting system-dependent entities such as devices or pipes. + */ + public static long length(String path) { + // File not found + File file = new File(path); + try { + if (!file.exists()) { + AppLog.w(AppLog.T.MEDIA, "Can't access the file. It doesn't exists anymore?"); + return -1L; + } + + return file.length(); + } catch (SecurityException e) { + AppLog.e(AppLog.T.MEDIA, "Can't access the file.", e); + return -1L; + } + } + + /** + * Given the full file path, or the filename with extension (i.e. my-picture.jpg), returns the filename part only + * (my-picture). + * + * @param filePath The path to the file or the full filename + * @return filename part only or null + */ + public static String getFileNameFromPath(String filePath) { + if (TextUtils.isEmpty(filePath)) { + return null; + } + if (filePath.contains("/")) { + if (filePath.lastIndexOf("/") + 1 >= filePath.length()) { + filePath = filePath.substring(0, filePath.length() - 1); + } + filePath = filePath.substring(filePath.lastIndexOf("/") + 1); + } + + String filename; + int dotPos = filePath.indexOf('.'); + if (dotPos > 0) { + filename = filePath.substring(0, dotPos); + } else { + filename = filePath; + } + return filename; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java new file mode 100644 index 000000000000..c2850e58d11c --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java @@ -0,0 +1,79 @@ +package org.wordpress.android.util; + +import java.text.DecimalFormat; +import java.text.NumberFormat; + +public class FormatUtils { + /* + * NumberFormat isn't synchronized, so a separate instance must be created for each thread + * http://developer.android.com/reference/java/text/NumberFormat.html + */ + private static final ThreadLocal INTEGER_INSTANCE = new ThreadLocal() { + @Override + protected NumberFormat initialValue() { + return NumberFormat.getIntegerInstance(); + } + }; + + private static final ThreadLocal DECIMAL_INSTANCE = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return (DecimalFormat) DecimalFormat.getInstance(); + } + }; + + /* + * returns the passed integer formatted with thousands-separators based on the current locale + */ + public static final String formatInt(int value) { + return INTEGER_INSTANCE.get().format(value).toString(); + } + + public static final String formatDecimal(int value) { + return DECIMAL_INSTANCE.get().format(value).toString(); + } + + /* + * returns the passed long formatted as an human readable filesize. Ex: 10 GB + * unitStrings is expected to be an array of all possible sizes from byte to TeraByte, in the current locale + */ + public static final String formatFileSize(long size, final String[] unitStrings) { + final double log1024 = Math.log10(1024); + if (size <= 0) { + return "0"; + } + int digitGroups = (int) (Math.log10(size) / log1024); + + NumberFormat f = NumberFormat.getInstance(); + if (f instanceof DecimalFormat) { + ((DecimalFormat) f).applyPattern("#,##0.#"); + } + return String.format(unitStrings[digitGroups], f.format(size / Math.pow(1024, digitGroups))); + } + + /* + * returns the passed double percentage (0 to 1) formatted as an human readable percentage. Ex: 0.25 returns 25% + */ + public static final String formatPercentage(double value) { + return formatPercentageLimit100(value, false); + } + + /* + * returns the passed double percentage (0 to 1) formatted as an human readable percentage. Ex: 0.251 returns 25.1% + * if limit100 is true, it limits the percentage to 100% + */ + public static final String formatPercentageLimit100(double value, boolean limit100) { + double limit = 1.0001; + + NumberFormat percentFormat = NumberFormat.getPercentInstance(); + percentFormat.setMaximumFractionDigits(1); + + if (limit100 && value > limit) { + value = limit; + } + + String percentage = percentFormat.format(value); + + return percentage; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java new file mode 100644 index 000000000000..4b2fdd8875c5 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java @@ -0,0 +1,115 @@ +package org.wordpress.android.util; + +import android.content.Context; +import android.location.Address; +import android.location.Geocoder; + +import java.io.IOException; +import java.util.List; + +public final class GeocoderUtils { + private GeocoderUtils() { + throw new AssertionError(); + } + + public static Geocoder getGeocoder(Context context) { + // first make sure a Geocoder service exists on this device (requires API 9) + if (!Geocoder.isPresent()) { + return null; + } + + Geocoder gcd; + + try { + gcd = new Geocoder(context, LanguageUtils.getCurrentDeviceLanguage(context)); + } catch (NullPointerException cannotIstantiateEx) { + AppLog.e(AppLog.T.UTILS, "Cannot instantiate Geocoder", cannotIstantiateEx); + return null; + } + + return gcd; + } + + public static Address getAddressFromCoords(Context context, double latitude, double longitude) { + Address address = null; + List
    addresses = null; + + Geocoder gcd = getGeocoder(context); + + if (gcd == null) { + return null; + } + + try { + addresses = gcd.getFromLocation(latitude, longitude, 1); + } catch (IOException e) { + // may get "Unable to parse response from server" IOException here if Geocoder + // service is hit too frequently + AppLog.e(AppLog.T.UTILS, + "Unable to parse response from server. Is Geocoder service hitting the server too frequently?", + e + ); + } + + // addresses may be null or empty if network isn't connected + if (addresses != null && addresses.size() > 0) { + address = addresses.get(0); + } + + return address; + } + + public static Address getAddressFromLocationName(Context context, String locationName) { + int maxResults = 1; + Address address = null; + List
    addresses = null; + + Geocoder gcd = getGeocoder(context); + + if (gcd == null) { + return null; + } + + try { + addresses = gcd.getFromLocationName(locationName, maxResults); + } catch (IOException e) { + AppLog.e(AppLog.T.UTILS, "Failed to get coordinates from location", e); + } + + // addresses may be null or empty if network isn't connected + if (addresses != null && addresses.size() > 0) { + address = addresses.get(0); + } + + return address; + } + + public static String getLocationNameFromAddress(Address address) { + String locality = "", adminArea = "", country = ""; + if (address.getLocality() != null) { + locality = address.getLocality(); + } + + if (address.getAdminArea() != null) { + adminArea = address.getAdminArea(); + } + + if (address.getCountryName() != null) { + country = address.getCountryName(); + } + + return ((locality.equals("")) ? locality : locality + ", ") + + ((adminArea.equals("")) ? adminArea : adminArea + " ") + country; + } + + public static double[] getCoordsFromAddress(Address address) { + double[] coordinates = new double[2]; + + if (address.hasLatitude() && address.hasLongitude()) { + coordinates[0] = address.getLatitude(); + coordinates[1] = address.getLongitude(); + } + + return coordinates; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java new file mode 100644 index 000000000000..f650dea0dcf5 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java @@ -0,0 +1,86 @@ +package org.wordpress.android.util; + +import android.text.TextUtils; + +/** + * see https://en.gravatar.com/site/implement/images/ + */ +public class GravatarUtils { + // by default tell gravatar to respond to non-existent images with a 404 - this means + // it's up to the caller to catch the 404 and provide a suitable default image + private static final DefaultImage DEFAULT_GRAVATAR = DefaultImage.MYSTERY_MAN; + + public enum DefaultImage { + MYSTERY_MAN, + STATUS_404, + IDENTICON, + MONSTER, + WAVATAR, + RETRO, + BLANK; + + @Override + public String toString() { + switch (this) { + case MYSTERY_MAN: + return "mm"; + case STATUS_404: + return "404"; + case IDENTICON: + return "identicon"; + case MONSTER: + return "monsterid"; + case WAVATAR: + return "wavatar"; + case RETRO: + return "retro"; + default: + return "blank"; + } + } + } + + /* + * gravatars often contain the ?s= parameter which determines their size - detect this and + * replace it with a new ?s= parameter which requests the avatar at the exact size needed + */ + public static String fixGravatarUrl(final String imageUrl, int avatarSz) { + return fixGravatarUrl(imageUrl, avatarSz, DEFAULT_GRAVATAR); + } + + public static String fixGravatarUrl(final String imageUrl, int avatarSz, DefaultImage defaultImage) { + if (TextUtils.isEmpty(imageUrl)) { + return ""; + } + + // if this isn't a gravatar image, return as resized photon image url + if (!imageUrl.contains("gravatar.com")) { + return PhotonUtils.getPhotonImageUrl(imageUrl, avatarSz, avatarSz); + } + + // remove all other params, then add query string for size and default image + return UrlUtils.removeQuery(imageUrl) + "?s=" + avatarSz + "&d=" + defaultImage.toString(); + } + + public static String gravatarFromEmail(final String email, int size) { + return gravatarFromEmail(email, size, DEFAULT_GRAVATAR); + } + + public static String gravatarFromEmail(final String email, int size, DefaultImage defaultImage) { + return "http://gravatar.com/avatar/" + + StringUtils.getMd5Hash(StringUtils.notNullStr(email)) + + "?d=" + defaultImage.toString() + + "&size=" + Integer.toString(size); + } + + public static String blavatarFromUrl(final String url, int size) { + return blavatarFromUrl(url, size, DEFAULT_GRAVATAR); + } + + public static String blavatarFromUrl(final String url, int size, DefaultImage defaultImage) { + return "http://gravatar.com/blavatar/" + + StringUtils.getMd5Hash(UrlUtils.getHost(url)) + + "?d=" + defaultImage.toString() + + "&size=" + Integer.toString(size); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java new file mode 100644 index 000000000000..d42cb0ba8aec --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java @@ -0,0 +1,898 @@ +package org.wordpress.android.util; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Point; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.media.ExifInterface; +import android.media.MediaMetadataRetriever; +import android.media.ThumbnailUtils; +import android.net.Uri; +import android.os.AsyncTask; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.util.Log; +import android.webkit.MimeTypeMap; +import android.widget.ImageView; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +public class ImageUtils { + public static int[] getImageSize(Uri uri, Context context) { + String path = null; + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + + if (uri.toString().contains("content:")) { + String[] projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA}; + Cursor cur = null; + try { + cur = context.getContentResolver().query(uri, projection, null, null, null); + if (cur != null && cur.moveToFirst()) { + int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA); + path = cur.getString(dataColumn); + } + } catch (IllegalStateException stateException) { + Log.d(ImageUtils.class.getName(), "IllegalStateException querying content:" + uri); + } finally { + SqlUtils.closeCursor(cur); + } + } + + if (TextUtils.isEmpty(path)) { + // The file isn't ContentResolver, or it can't be access by ContentResolver. Try to access the file + // directly. + path = uri.toString().replace("content://media", ""); + path = path.replace("file://", ""); + } + + BitmapFactory.decodeFile(path, options); + int imageHeight = options.outHeight; + int imageWidth = options.outWidth; + return new int[]{imageWidth, imageHeight}; + } + + // Read the orientation from ContentResolver. If it fails, read from EXIF. + public static int getImageOrientation(Context ctx, String filePath) { + if (TextUtils.isEmpty(filePath) || ctx == null) { + AppLog.w(AppLog.T.UTILS, "Can't read orientation. Passed context or file is null or empty."); + return 0; + } + Uri curStream; + int orientation = 0; + + // Remove file protocol + filePath = filePath.replace("file://", ""); + + if (!filePath.contains("content://")) { + curStream = Uri.parse("content://media" + filePath); + } else { + curStream = Uri.parse(filePath); + } + + try { + Cursor cur = ctx.getContentResolver() + .query(curStream, new String[]{MediaStore.Images.Media.ORIENTATION}, null, null, null); + if (cur != null) { + if (cur.moveToFirst()) { + orientation = cur.getInt(cur.getColumnIndex(MediaStore.Images.Media.ORIENTATION)); + } + cur.close(); + } + } catch (Exception errReadingContentResolver) { + AppLog.e(AppLog.T.UTILS, "Error reading orientation of the file: " + filePath, errReadingContentResolver); + } + + if (orientation == 0) { + orientation = getExifOrientation(filePath); + } + + return orientation; + } + + + private static int getExifOrientation(String path) { + if (TextUtils.isEmpty(path)) { + AppLog.w(AppLog.T.UTILS, "Can't read EXIF orientation. Passed path is empty."); + return 0; + } + ExifInterface exif; + try { + exif = new ExifInterface(path); + } catch (IOException e) { + AppLog.e(AppLog.T.UTILS, "Can't read EXIF orientation.", e); + return 0; + } + + int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0); + + switch (exifOrientation) { + case ExifInterface.ORIENTATION_NORMAL: + return 0; + case ExifInterface.ORIENTATION_ROTATE_90: + return 90; + case ExifInterface.ORIENTATION_ROTATE_180: + return 180; + case ExifInterface.ORIENTATION_ROTATE_270: + return 270; + default: + return 0; + } + } + + public static Bitmap downloadBitmap(String url) { + final DefaultHttpClient client = new DefaultHttpClient(); + + final HttpGet getRequest = new HttpGet(url); + + try { + HttpResponse response = client.execute(getRequest); + final int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + AppLog.w(AppLog.T.UTILS, "ImageDownloader Error " + statusCode + + " while retrieving bitmap from " + url); + return null; + } + + final HttpEntity entity = response.getEntity(); + if (entity != null) { + InputStream inputStream = null; + try { + inputStream = entity.getContent(); + return BitmapFactory.decodeStream(inputStream); + } finally { + if (inputStream != null) { + inputStream.close(); + } + entity.consumeContent(); + } + } + } catch (Exception e) { + // Could provide a more explicit error message for IOException or + // IllegalStateException + getRequest.abort(); + AppLog.w(AppLog.T.UTILS, "ImageDownloader Error while retrieving bitmap from " + url); + } + return null; + } + + /** From http://developer.android.com/training/displaying-bitmaps/load-bitmap.html **/ + public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { + // Raw height and width of image + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + // Calculate ratios of height and width to requested height and width + final int heightRatio = Math.round((float) height / (float) reqHeight); + final int widthRatio = Math.round((float) width / (float) reqWidth); + + // Choose the smallest ratio as inSampleSize value, this will guarantee + // a final image with both dimensions larger than or equal to the + // requested height and width. + inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; + } + + return inSampleSize; + } + + + public interface BitmapWorkerCallback { + void onBitmapReady(String filePath, ImageView imageView, Bitmap bitmap); + } + + public static class BitmapWorkerTask extends AsyncTask { + private final WeakReference mImageViewReference; + private final BitmapWorkerCallback mCallback; + private int mTargetWidth; + private int mTargetHeight; + private String mPath; + + public BitmapWorkerTask(ImageView imageView, int width, int height, BitmapWorkerCallback callback) { + // Use a WeakReference to ensure the ImageView can be garbage collected + mImageViewReference = new WeakReference(imageView); + this.mCallback = callback; + mTargetWidth = width; + mTargetHeight = height; + } + + // Decode image in background. + @Override + protected Bitmap doInBackground(String... params) { + mPath = params[0]; + + BitmapFactory.Options bfo = new BitmapFactory.Options(); + bfo.inJustDecodeBounds = true; + BitmapFactory.decodeFile(mPath, bfo); + + bfo.inSampleSize = calculateInSampleSize(bfo, mTargetWidth, mTargetHeight); + bfo.inJustDecodeBounds = false; + + // get proper rotation + int bitmapWidth = 0; + int bitmapHeight = 0; + try { + File f = new File(mPath); + ExifInterface exif = new ExifInterface(f.getPath()); + int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); + int angle = 0; + if (orientation == ExifInterface.ORIENTATION_NORMAL) { // no need to rotate + return BitmapFactory.decodeFile(mPath, bfo); + } else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { + angle = 90; + } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { + angle = 180; + } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { + angle = 270; + } + + Matrix mat = new Matrix(); + mat.postRotate(angle); + + try { + Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, bfo); + if (bmp == null) { + AppLog.e(AppLog.T.UTILS, "can't decode bitmap: " + f.getPath()); + return null; + } + bitmapWidth = bmp.getWidth(); + bitmapHeight = bmp.getHeight(); + return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true); + } catch (OutOfMemoryError oom) { + AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error in setting image: " + oom); + } + } catch (IOException e) { + AppLog.e(AppLog.T.UTILS, "Error in setting image", e); + } + + return null; + } + + // Once complete, see if ImageView is still around and set bitmap. + @Override + protected void onPostExecute(Bitmap bitmap) { + if (mImageViewReference == null || bitmap == null) { + return; + } + + final ImageView imageView = mImageViewReference.get(); + + if (mCallback != null) { + mCallback.onBitmapReady(mPath, imageView, bitmap); + } + } + } + + public static String getTitleForWPImageSpan(Context ctx, String filePath) { + if (filePath == null) { + return null; + } + + Uri curStream; + String title; + + if (!filePath.contains("content://")) { + curStream = Uri.parse("content://media" + filePath); + } else { + curStream = Uri.parse(filePath); + } + + if (filePath.contains("video")) { + return "Video"; + } else { + String[] projection = new String[]{MediaStore.Images.Thumbnails.DATA}; + + Cursor cur; + try { + cur = ctx.getContentResolver().query(curStream, projection, null, null, null); + } catch (Exception e1) { + AppLog.e(AppLog.T.UTILS, e1); + return null; + } + File jpeg; + if (cur != null) { + String thumbData = ""; + if (cur.moveToFirst()) { + int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA); + thumbData = cur.getString(dataColumn); + } + cur.close(); + if (thumbData == null) { + return null; + } + jpeg = new File(thumbData); + } else { + String path = filePath.toString().replace("file://", ""); + jpeg = new File(path); + } + title = jpeg.getName(); + return title; + } + } + + /** + * Resizes an image to be placed in the Post Content Editor + * + * @return resized bitmap + */ + public static Bitmap getWPImageSpanThumbnailFromFilePath(Context context, String filePath, int targetWidth) { + if (filePath == null || context == null) { + return null; + } + + Uri curUri = Uri.parse(filePath); + + if (filePath.contains("video")) { + // Load the video thumbnail from the MediaStore + int videoId = 0; + try { + videoId = Integer.parseInt(curUri.getLastPathSegment()); + } catch (NumberFormatException e) { + } + ContentResolver crThumb = context.getContentResolver(); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inSampleSize = 1; + Bitmap videoThumbnail = + MediaStore.Video.Thumbnails.getThumbnail(crThumb, videoId, MediaStore.Video.Thumbnails.MINI_KIND, + options); + if (videoThumbnail != null) { + return getScaledBitmapAtLongestSide(videoThumbnail, targetWidth); + } else { + return null; + } + } else { + // Create resized bitmap + int rotation = getImageOrientation(context, filePath); + byte[] bytes = createThumbnailFromUri(context, curUri, targetWidth, null, rotation); + + if (bytes != null && bytes.length > 0) { + try { + Bitmap resizedBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + if (resizedBitmap != null) { + return getScaledBitmapAtLongestSide(resizedBitmap, targetWidth); + } + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error in setting image: " + e); + return null; + } + } + } + + return null; + } + + /* + Resize a bitmap to the targetSize on its longest side. + */ + public static Bitmap getScaledBitmapAtLongestSide(Bitmap bitmap, int targetSize) { + if (bitmap == null || bitmap.getWidth() <= targetSize && bitmap.getHeight() <= targetSize) { + // Do not resize. + return bitmap; + } + + int targetWidth, targetHeight; + if (bitmap.getHeight() > bitmap.getWidth()) { + // Resize portrait bitmap + targetHeight = targetSize; + float percentage = (float) targetSize / bitmap.getHeight(); + targetWidth = (int) (bitmap.getWidth() * percentage); + } else { + // Resize landscape or square image + targetWidth = targetSize; + float percentage = (float) targetSize / bitmap.getWidth(); + targetHeight = (int) (bitmap.getHeight() * percentage); + } + + return Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true); + } + + private static boolean resizeImageAndWriteToStream(Context context, + Uri imageUri, + String fileExtension, + int maxSize, + int orientation, + int quality, + OutputStream outStream) throws OutOfMemoryError, IOException { + String realFilePath = MediaUtils.getRealPathFromURI(context, imageUri); + + // get just the image bounds + BitmapFactory.Options optBounds = new BitmapFactory.Options(); + optBounds.inJustDecodeBounds = true; + + try { + BitmapFactory.decodeFile(realFilePath, optBounds); + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error while decoding the original image: " + realFilePath, e); + throw e; + } + + int scale = getScaleForResizing(maxSize, optBounds); + + BitmapFactory.Options optActual = new BitmapFactory.Options(); + optActual.inSampleSize = scale; + + // Get the roughly resized bitmap + final Bitmap bmpResized; + try { + bmpResized = BitmapFactory.decodeFile(realFilePath, optActual); + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error while decoding the original image: " + realFilePath, e); + throw e; + } + + if (bmpResized == null) { + AppLog.e(AppLog.T.UTILS, "Can't decode the resized picture."); + throw new IOException("Can't decode the resized picture."); + } + + // Resize the bitmap to exact size: calculate exact scale in order to resize accurately + float scaleBy = getScaleImageBy(maxSize, bmpResized); + + Matrix matrix = new Matrix(); + matrix.postScale(scaleBy, scaleBy); + + // apply orientation + if (orientation != 0) { + matrix.setRotate(orientation); + } + + Bitmap.CompressFormat fmt; + if (fileExtension != null + && (fileExtension.equals("png") || fileExtension.equals(".png"))) { + fmt = Bitmap.CompressFormat.PNG; + } else { + fmt = Bitmap.CompressFormat.JPEG; + } + + final Bitmap bmpRotated; + try { + bmpRotated = + Bitmap.createBitmap(bmpResized, 0, 0, bmpResized.getWidth(), bmpResized.getHeight(), matrix, true); + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.UTILS, "OutOfMemoryError while creating the resized bitmap", e); + throw e; + } catch (NullPointerException e) { + // See: https://github.com/wordpress-mobile/WordPress-Android/issues/1844 + AppLog.e(AppLog.T.UTILS, "Bitmap.createBitmap has thrown a NPE internally. This should never happen!", e); + throw e; + } + + if (bmpRotated == null) { + // Fix an issue where bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can + // return null. + AppLog.e(AppLog.T.UTILS, + "bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can return null."); + // See: https://github.com/wordpress-mobile/WordPress-Android/issues/1848 + throw new IOException( + "bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can return null."); + } + + return bmpRotated.compress(fmt, quality, outStream); + } + + /** + * Given the path to an image, compress and resize it. + * @param context the passed context + * @param path the path to the original image + * @param maxImageSize the maximum allowed width + * @param quality the encoder quality + * @return the path to the optimized image + */ + public static String optimizeImage(Context context, String path, int maxImageSize, int quality) { + if (context == null || TextUtils.isEmpty(path)) { + return path; + } + + File file = new File(path); + if (!file.exists()) { + return path; + } + + String mimeType = MediaUtils.getMediaFileMimeType(file); + if (mimeType.equals("image/gif")) { + // Don't rescale gifs to maintain their quality + return path; + } + + Uri srcImageUri = Uri.parse(path); + if (srcImageUri == null) { + return path; + } + + String fileName = MediaUtils.getMediaFileName(file, mimeType); + String fileExtension = MimeTypeMap.getFileExtensionFromUrl(fileName).toLowerCase(Locale.ROOT); + + int[] imageDimensions = getImageSize(srcImageUri, context); + int selectedMaxSize = Math.max(imageDimensions[0], imageDimensions[1]); + if (selectedMaxSize == 0) { + // Can't read the src dimensions. + return path; + } + + // do not optimize if original-size and 100% quality are set. + if (maxImageSize == Integer.MAX_VALUE && quality == 100) { + return path; + } + + if (selectedMaxSize > maxImageSize) { + selectedMaxSize = maxImageSize; + } + + int orientation = getImageOrientation(context, path); + + File resizedImageFile; + FileOutputStream out; + + try { + // try to re-use the same name as prefix of the temp file + String prefix = FileUtils.getFileNameFromPath(fileName); + + if (TextUtils.isEmpty(prefix) || prefix.length() < 3) { + // prefix must be at least 3 characters + prefix = "wp-image"; + } + + resizedImageFile = File.createTempFile(prefix, "." + fileExtension); + out = new FileOutputStream(resizedImageFile); + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, "Failed to create the temp file on storage. Use the original picture instead."); + return path; + } catch (SecurityException e) { + AppLog.e(AppLog.T.MEDIA, + "Can't write the tmp file due to security restrictions. Use the original picture instead."); + return path; + } + + try { + boolean res = resizeImageAndWriteToStream(context, srcImageUri, fileExtension, selectedMaxSize, orientation, + quality, out); + if (!res) { + AppLog.w(AppLog.T.MEDIA, "Failed to compress the optimized image. Use the original picture instead."); + return path; + } + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, "Failed to create optimized image. Use the original picture instead."); + return path; + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.MEDIA, "Can't optimize the picture due to low memory. Use the original picture instead."); + return path; + } finally { + // close the stream + try { + out.flush(); + out.close(); + } catch (IOException e) { + // nope + } + } + + String tempFilePath = resizedImageFile.getPath(); + if (!TextUtils.isEmpty(tempFilePath)) { + return tempFilePath; + } else { + AppLog.e(AppLog.T.MEDIA, "Failed to create optimized image. Use the full picture instead."); + } + + return path; + } + + /** + * Generate a thumbnail from a video url. + * Note that this method could take time if network url. + * + * @param videoPath The path to the video on internet + * @param maxWidth the maximumWidth for the thumbnail + * @return the path to the picture on disk + */ + public static Bitmap getVideoFrameFromVideo(String videoPath, int maxWidth) { + return getVideoFrameFromVideo(videoPath, maxWidth, new HashMap()); + } + + /** + * Generate a thumbnail from a video url. + * Note that this method could take time if network url. + * + * @param videoPath The path to the video on internet + * @param maxWidth the maximumWidth for the thumbnail + * @param headers optional: HTTP headers map to add to the request if the video is remote + * @return the path to the picture on disk + */ + public static Bitmap getVideoFrameFromVideo(String videoPath, int maxWidth, Map headers) { + if (TextUtils.isEmpty(videoPath) || maxWidth <= 0) { + return null; + } + + if (new File(videoPath).exists()) { + // Local file + Bitmap thumb = + ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND); + return ImageUtils.getScaledBitmapAtLongestSide(thumb, maxWidth); + } + + // Not a local file. + MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); + Bitmap bitmap = null; + try { + mediaMetadataRetriever.setDataSource(videoPath, headers); + bitmap = mediaMetadataRetriever.getFrameAtTime(); + } catch (IllegalArgumentException e) { + AppLog.e(AppLog.T.MEDIA, "The passed video path is invalid: " + videoPath); + } catch (java.lang.RuntimeException e) { + // I've see this kind of error on one of my testing device + AppLog.e(AppLog.T.MEDIA, "The passed video path is invalid: " + videoPath); + } finally { + mediaMetadataRetriever.release(); + } + + if (bitmap == null) { + AppLog.w(AppLog.T.MEDIA, "Failed to retrieve frame from the passed video path: " + videoPath); + return null; + } + + return getScaledBitmapAtLongestSide(bitmap, maxWidth); + } + + /** + * nbradbury - 21-Feb-2014 - similar to createThumbnail but more efficient since it doesn't + * require passing the full-size image as an array of bytes[] + */ + public static byte[] createThumbnailFromUri(Context context, + Uri imageUri, + int maxWidth, + String fileExtension, + int orientation) { + if (context == null || imageUri == null || maxWidth <= 0) { + return null; + } + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + boolean res = + resizeImageAndWriteToStream(context, imageUri, fileExtension, maxWidth, orientation, 75, stream); + if (!res) { + AppLog.w(AppLog.T.MEDIA, "Failed to compress the resized image. Use the full picture instead."); + return null; + } + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, "Failed to create resized image. Use the full picture instead."); + return null; + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.MEDIA, "Can't resize the picture due to low memory. Use the full picture instead."); + return null; + } + + return stream.toByteArray(); + } + + public static Bitmap getCircularBitmap(final Bitmap bitmap) { + if (bitmap == null) { + return null; + } + + final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + final RectF rectF = new RectF(rect); + + paint.setAntiAlias(true); + canvas.drawARGB(0, 0, 0, 0); + paint.setColor(Color.RED); + canvas.drawOval(rectF, paint); + + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, rect, rect, paint); + + return output; + } + + /** + * Returns the passed bitmap with rounded corners + * @param bitmap - the bitmap to modify + * @param radius - the radius of the corners + * @param borderColor - the border to apply (use Color.TRANSPARENT for none) + */ + public static Bitmap getRoundedEdgeBitmap(final Bitmap bitmap, int radius, int borderColor) { + if (bitmap == null) { + return null; + } + + final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + final RectF rectF = new RectF(rect); + + paint.setAntiAlias(true); + canvas.drawARGB(0, 0, 0, 0); + paint.setColor(Color.RED); + canvas.drawRoundRect(rectF, radius, radius, paint); + + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, rect, rect, paint); + + if (borderColor != Color.TRANSPARENT) { + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(1f); + paint.setColor(borderColor); + canvas.drawRoundRect(rectF, radius, radius, paint); + } + + return output; + } + + /** + * Get the maximum size a thumbnail can be to fit in either portrait or landscape orientations. + * @deprecated Use `getMaximumThumbnailSizeForEditor` available in MediaUtils class in Editors project + */ + public static int getMaximumThumbnailWidthForEditor(Context context) { + int maximumThumbnailWidthForEditor; + Point size = DisplayUtils.getDisplayPixelSize(context); + int screenWidth = size.x; + int screenHeight = size.y; + maximumThumbnailWidthForEditor = (screenWidth > screenHeight) ? screenHeight : screenWidth; + // 48dp of padding on each side so you can still place the cursor next to the image. + int padding = DisplayUtils.dpToPx(context, 48) * 2; + maximumThumbnailWidthForEditor -= padding; + return maximumThumbnailWidthForEditor; + } + + /** + * Given the path to an image, rotate it by using EXIF info + * @param context the passed context + * @param path the path to the original image + * @return the path to the rotated image or null + */ + public static String rotateImageIfNecessary(Context context, String path) { + if (context == null || TextUtils.isEmpty(path)) { + return null; + } + + File file = new File(path); + if (!file.exists()) { + return null; + } + + int orientation = getImageOrientation(context, path); + // Do not rotate portrait pictures + if (orientation == 0) { + return null; + } + + String mimeType = MediaUtils.getMediaFileMimeType(file); + if (mimeType.equals("image/gif")) { + // Don't rotate gifs to maintain their quality + return null; + } + + Uri srcImageUri = Uri.parse(path); + if (srcImageUri == null) { + return null; + } + + String fileName = MediaUtils.getMediaFileName(file, mimeType); + String fileExtension = MimeTypeMap.getFileExtensionFromUrl(fileName).toLowerCase(Locale.ROOT); + + int selectedWidth = getImageSize(srcImageUri, context)[0]; + if (selectedWidth == 0) { + // Can't read the src dimensions. + return null; + } + + File rotatedImageFile; + FileOutputStream out; + + try { + // try to re-use the same name as prefix of the temp file + String prefix = FileUtils.getFileNameFromPath(fileName); + + if (TextUtils.isEmpty(prefix) || prefix.length() < 3) { + // prefix must be at least 3 characters + prefix = "wp-image"; + } + + rotatedImageFile = File.createTempFile(prefix, "." + fileExtension); + out = new FileOutputStream(rotatedImageFile); + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, "Failed to create the temp file on storage."); + return null; + } catch (SecurityException e) { + AppLog.e(AppLog.T.MEDIA, "Can't write the tmp file due to security restrictions."); + return null; + } + + try { + boolean res = + resizeImageAndWriteToStream(context, srcImageUri, fileExtension, selectedWidth, orientation, 85, + out); + if (!res) { + AppLog.w(AppLog.T.MEDIA, "Failed to compress the rotates image."); + return null; + } + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, "Failed to create rotated image."); + return null; + } catch (OutOfMemoryError e) { + AppLog.e(AppLog.T.MEDIA, "Can't rotate the picture due to low memory."); + return null; + } finally { + // close the stream + try { + out.flush(); + out.close(); + } catch (IOException e) { + // nope + } + } + + String tempFilePath = rotatedImageFile.getPath(); + if (!TextUtils.isEmpty(tempFilePath)) { + return tempFilePath; + } else { + AppLog.e(AppLog.T.MEDIA, "Failed to create rotated image."); + } + + return null; + } + + // determine correct scale value (should be power of 2) + // http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/3549021#3549021 + protected static int getScaleForResizing(int maxSize, BitmapFactory.Options optBounds) { + if (maxSize < 1) { + return 1; + } + + int maxDimension = Math.max(optBounds.outWidth, optBounds.outHeight); + int scale = 1; + + while (maxDimension / scale / 2 >= maxSize) { + scale *= 2; + } + return scale; + } + + private static float getScaleImageBy(float maxSize, Bitmap bmpResized) { + int divideBy = Math.max(bmpResized.getHeight(), bmpResized.getWidth()); + float percentage = maxSize / divideBy; + + float proportionateHeight = bmpResized.getHeight() * percentage; + int finalHeight = (int) Math.rint(proportionateHeight); + + float scaleWidth = maxSize / bmpResized.getWidth(); + float scaleHeight = ((float) finalHeight) / bmpResized.getHeight(); + + return Math.min(scaleWidth, scaleHeight); + } + + public static Rect getScaledBounds(int width, int height, int maxWidth) { + float xScale = Math.max(1.0f, (float) width / maxWidth); + return new Rect(0, 0, Math.round(width / xScale), Math.round(height / xScale)); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java new file mode 100644 index 000000000000..7e4e177b392b --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java @@ -0,0 +1,262 @@ +package org.wordpress.android.util; + +import android.text.TextUtils; + +import org.apache.commons.text.StringEscapeUtils; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.wordpress.android.util.AppLog.T; + +import java.util.ArrayList; + +public class JSONUtils { + private static final String QUERY_SEPERATOR = "."; + private static final String QUERY_ARRAY_INDEX_START = "["; + private static final String QUERY_ARRAY_INDEX_END = "]"; + private static final String QUERY_ARRAY_FIRST = "first"; + private static final String QUERY_ARRAY_LAST = "last"; + + private static final String JSON_NULL_STR = "null"; + private static final String TAG = "JSONUtils"; + + /** + * Given a JSONObject and a key path (e.g property.child) and a default it will + * traverse the object graph and pull out the desired property + */ + public static U queryJSON(JSONObject source, String query, U defaultObject) { + if (source == null) { + AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); + return defaultObject; + } + if (query == null) { + AppLog.e(T.UTILS, "Parameter query is null"); + return defaultObject; + } + int nextSeperator = query.indexOf(QUERY_SEPERATOR); + int nextIndexStart = query.indexOf(QUERY_ARRAY_INDEX_START); + if (nextSeperator == -1 && nextIndexStart == -1) { + // last item let's get it + try { + if (!source.has(query)) { + return defaultObject; + } + Object result = source.get(query); + if (result.getClass().isAssignableFrom(defaultObject.getClass())) { + return (U) result; + } else { + AppLog.w(T.UTILS, String.format( + "The returned object type %s is not assignable to the type %s. Using default!", + result.getClass(), defaultObject.getClass())); + return defaultObject; + } + } catch (java.lang.ClassCastException e) { + AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); + return defaultObject; + } catch (JSONException e) { + AppLog.e(T.UTILS, "Unable to get the Key from the input object. Key:" + query, e); + return defaultObject; + } + } + int endQuery; + if (nextSeperator == -1 || nextIndexStart == -1) { + endQuery = Math.max(nextSeperator, nextIndexStart); + } else { + endQuery = Math.min(nextSeperator, nextIndexStart); + } + String nextQuery = query.substring(endQuery); + String key = query.substring(0, endQuery); + try { + if (nextQuery.indexOf(QUERY_SEPERATOR) == 0) { + return queryJSON(source.getJSONObject(key), nextQuery.substring(1), defaultObject); + } else if (nextQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { + return queryJSON(source.getJSONArray(key), nextQuery, defaultObject); + } else if (!nextQuery.equals("")) { + return defaultObject; + } + Object result = source.get(key); + if (result.getClass().isAssignableFrom(defaultObject.getClass())) { + return (U) result; + } else { + AppLog.w(T.UTILS, + String.format("The returned object type %s is not assignable to the type %s. Using default!", + result.getClass(), defaultObject.getClass())); + return defaultObject; + } + } catch (java.lang.ClassCastException e) { + AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); + return defaultObject; + } catch (JSONException e) { + return defaultObject; + } + } + + /** + * Given a JSONArray and a query (e.g. [0].property) it will traverse the array and + * pull out the requested property. + * + * Acceptable indexes include negative numbers to reference items from the end of + * the list as well as "last" and "first" as more explicit references to "0" and "-1" + */ + public static U queryJSON(JSONArray source, String query, U defaultObject) { + if (source == null) { + AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); + return defaultObject; + } + if (query == null) { + AppLog.e(T.UTILS, "Parameter query is null"); + return defaultObject; + } + // query must start with [ have an index and then have ] + int indexStart = query.indexOf(QUERY_ARRAY_INDEX_START); + int indexEnd = query.indexOf(QUERY_ARRAY_INDEX_END); + if (indexStart == -1 || indexEnd == -1 || indexStart > indexEnd) { + return defaultObject; + } + // get "index" from "[index]" + String indexStr = query.substring(indexStart + 1, indexEnd); + int index; + if (indexStr.equals(QUERY_ARRAY_FIRST)) { + index = 0; + } else if (indexStr.equals(QUERY_ARRAY_LAST)) { + index = -1; + } else { + index = Integer.parseInt(indexStr); + } + if (index < 0) { + index = source.length() + index; + } + // copy remaining query + String remainingQuery = query.substring(indexEnd + 1); + try { + if (remainingQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { + return queryJSON(source.getJSONArray(index), remainingQuery, defaultObject); + } else if (remainingQuery.indexOf(QUERY_SEPERATOR) == 0) { + return queryJSON(source.getJSONObject(index), remainingQuery.substring(1), defaultObject); + } else if (!remainingQuery.equals("")) { + // TODO throw an exception since the query isn't valid? + AppLog.w(T.UTILS, String.format("Incorrect query for next object %s", remainingQuery)); + return defaultObject; + } + Object result = source.get(index); + if (result.getClass().isAssignableFrom(defaultObject.getClass())) { + return (U) result; + } else { + AppLog.w(T.UTILS, + String.format("The returned object type %s is not assignable to the type %s. Using default!", + result.getClass(), defaultObject.getClass())); + return defaultObject; + } + } catch (java.lang.ClassCastException e) { + AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); + return defaultObject; + } catch (JSONException e) { + return defaultObject; + } + } + + /** + * Convert a JSONArray (expected to contain strings) in a string list + */ + public static ArrayList fromJSONArrayToStringList(JSONArray jsonArray) { + ArrayList stringList = new ArrayList(); + for (int i = 0; i < jsonArray.length(); i++) { + try { + stringList.add(jsonArray.getString(i)); + } catch (JSONException e) { + AppLog.e(T.UTILS, e); + } + } + return stringList; + } + + /** + * Convert a string list in a JSONArray + */ + public static JSONArray fromStringListToJSONArray(ArrayList stringList) { + JSONArray jsonArray = new JSONArray(); + if (stringList != null) { + for (int i = 0; i < stringList.size(); i++) { + jsonArray.put(stringList.get(i)); + } + } + return jsonArray; + } + + /* + * wrapper for JSONObject.optString() which handles "null" values + */ + public static String getString(JSONObject json, String name) { + String value = json.optString(name); + // return empty string for "null" + if (JSON_NULL_STR.equals(value)) { + return ""; + } + return value; + } + + /* + * use with strings that contain HTML entities + */ + public static String getStringDecoded(JSONObject json, String name) { + String value = getString(json, name); + return StringEscapeUtils.unescapeHtml4(value); + } + + /* + * replacement for JSONObject.optBoolean() - optBoolean() only checks for "true" and "false", + * but our API sometimes uses "0" to denote false + */ + public static boolean getBool(JSONObject json, String name) { + String value = getString(json, name); + if (TextUtils.isEmpty(value)) { + return false; + } + if (value.equals("0")) { + return false; + } + if (value.equalsIgnoreCase("false")) { + return false; + } + if (value.equalsIgnoreCase("no")) { + return false; + } + return true; + } + + /* + * returns the JSONObject child of the passed parent that matches the passed query + * this is basically an "optJSONObject" that supports nested queries, for example: + * + * getJSONChild("meta/data/site") + * + * would find this: + * + * "meta": { + * "data": { + * "site": { + * "ID": 3584907, + * "name": "WordPress.com News", + * } + * } + * } + */ + public static JSONObject getJSONChild(final JSONObject jsonParent, final String query) { + if (jsonParent == null || TextUtils.isEmpty(query)) { + return null; + } + String[] names = query.split("/"); + JSONObject jsonChild = null; + for (int i = 0; i < names.length; i++) { + if (jsonChild == null) { + jsonChild = jsonParent.optJSONObject(names[i]); + } else { + jsonChild = jsonChild.optJSONObject(names[i]); + } + if (jsonChild == null) { + return null; + } + } + return jsonChild; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java new file mode 100644 index 000000000000..1deaa603efd7 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java @@ -0,0 +1,72 @@ +package org.wordpress.android.util; + +import android.content.Context; + +import androidx.annotation.Nullable; + +import java.util.Locale; + +/** + * Methods for dealing with i18n messages + */ +public class LanguageUtils { + /** + * @deprecated Use {@link #getCurrentDeviceLanguage()}. As of API 25, setting the locale by updating the + * configuration on the resources object was deprecated, so this method stopped working for newer versions + * of Android. The current active locale should always be set in {@link Locale#getDefault()}. When manually + * setting the active locale, the developer should set it in {@link Locale#setDefault(Locale)}. + */ + @SuppressWarnings("DeprecatedIsStillUsed") + @Deprecated + public static Locale getCurrentDeviceLanguage(@Nullable Context context) { + return getCurrentDeviceLanguage(); + } + + @SuppressWarnings("WeakerAccess") + public static Locale getCurrentDeviceLanguage() { + return Locale.getDefault(); + } + + /** + * @deprecated Use {@link #getCurrentDeviceLanguageCode()}. + */ + @SuppressWarnings("WeakerAccess,DeprecatedIsStillUsed") + @Deprecated + public static String getCurrentDeviceLanguageCode(@Nullable Context context) { + return getCurrentDeviceLanguageCode(); + } + + @SuppressWarnings("WeakerAccess") + public static String getCurrentDeviceLanguageCode() { + return getCurrentDeviceLanguage().toString(); + } + + public static String getPatchedCurrentDeviceLanguage(Context context) { + return patchDeviceLanguageCode(getCurrentDeviceLanguageCode(context)); + } + + /** + * Patches a deviceLanguageCode if any of deprecated values iw, id, or yi + */ + @SuppressWarnings("WeakerAccess") + public static String patchDeviceLanguageCode(String deviceLanguageCode) { + String patchedCode = deviceLanguageCode; + /* +

    Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language + * code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This + * rewriting happens even if you construct your own {@code Locale} object, not just for + * instances returned by the various lookup methods. + */ + if (deviceLanguageCode != null) { + if (deviceLanguageCode.startsWith("iw")) { + patchedCode = deviceLanguageCode.replace("iw", "he"); + } else if (deviceLanguageCode.startsWith("in")) { + patchedCode = deviceLanguageCode.replace("in", "id"); + } else if (deviceLanguageCode.startsWith("ji")) { + patchedCode = deviceLanguageCode.replace("ji", "yi"); + } + } + + return patchedCode; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java new file mode 100644 index 000000000000..30d38e36c514 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java @@ -0,0 +1,47 @@ +package org.wordpress.android.util; + +import androidx.annotation.Nullable; + +import org.apache.commons.lang3.ArrayUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ListUtils { + @Nullable + public static ArrayList fromLongArray(long[] array) { + if (array == null) { + return null; + } + Long[] longObjects = ArrayUtils.toObject(array); + return new ArrayList<>(Arrays.asList(longObjects)); + } + + @Nullable + public static long[] toLongArray(List list) { + if (list == null) { + return null; + } + Long[] array = list.toArray(new Long[list.size()]); + return ArrayUtils.toPrimitive(array); + } + + @Nullable + public static ArrayList fromIntArray(int[] array) { + if (array == null) { + return null; + } + Integer[] intObjects = ArrayUtils.toObject(array); + return new ArrayList<>(Arrays.asList(intObjects)); + } + + @Nullable + public static int[] toIntArray(List list) { + if (list == null) { + return null; + } + Integer[] array = list.toArray(new Integer[list.size()]); + return ArrayUtils.toPrimitive(array); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java new file mode 100644 index 000000000000..4345a4b22cfe --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java @@ -0,0 +1,115 @@ +package org.wordpress.android.util; + +import java.util.Date; +import java.util.Map; + +/** + * wrappers for extracting values from a Map object + */ +public class MapUtils { + /* + * returns a String value for the passed key in the passed map + * always returns "" instead of null + */ + public static String getMapStr(final Map map, final String key) { + if (map == null || key == null || !map.containsKey(key) || map.get(key) == null) { + return ""; + } + return map.get(key).toString(); + } + + /* + * returns an int value for the passed key in the passed map + * defaultValue is returned if key doesn't exist or isn't a number + */ + public static int getMapInt(final Map map, final String key) { + return getMapInt(map, key, 0); + } + + public static int getMapInt(final Map map, final String key, int defaultValue) { + try { + return Integer.parseInt(getMapStr(map, key)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /* + * long version of above + */ + public static long getMapLong(final Map map, final String key) { + return getMapLong(map, key, 0); + } + + public static long getMapLong(final Map map, final String key, long defaultValue) { + try { + return Long.parseLong(getMapStr(map, key)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /* + * float version of above + */ + public static float getMapFloat(final Map map, final String key) { + return getMapFloat(map, key, 0); + } + + public static float getMapFloat(final Map map, final String key, float defaultValue) { + try { + return Float.parseFloat(getMapStr(map, key)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /* + * double version of above + */ + public static double getMapDouble(final Map map, final String key) { + return getMapDouble(map, key, 0); + } + + public static double getMapDouble(final Map map, final String key, double defaultValue) { + try { + return Double.parseDouble(getMapStr(map, key)); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /* + * returns a date object from the passed key in the passed map + * returns null if key doesn't exist or isn't a date + */ + public static Date getMapDate(final Map map, final String key) { + if (map == null || key == null || !map.containsKey(key)) { + return null; + } + try { + return (Date) map.get(key); + } catch (ClassCastException e) { + return null; + } + } + + /* + * returns a boolean value from the passed key in the passed map + * returns true unless key doesn't exist, or the value is "0" or "false" + */ + public static boolean getMapBool(final Map map, final String key) { + String value = getMapStr(map, key); + if (value.isEmpty()) { + return false; + } + if (value.startsWith("0")) { // handles "0" and "0.0" + return false; + } + if (value.equalsIgnoreCase("false")) { + return false; + } + // all other values are assume to be true + return true; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java new file mode 100644 index 000000000000..d052d0758dc1 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java @@ -0,0 +1,563 @@ +package org.wordpress.android.util; + +import android.annotation.TargetApi; +import android.content.ContentUris; +import android.content.Context; +import android.content.CursorLoader; +import android.database.Cursor; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; +import android.provider.OpenableColumns; +import android.text.TextUtils; +import android.webkit.MimeTypeMap; + +import androidx.annotation.Nullable; + +import org.wordpress.android.util.AppLog.T; + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MediaUtils { + private static final int DEFAULT_MAX_IMAGE_WIDTH = 1024; + private static final Pattern FILE_EXISTS_PATTERN = Pattern.compile("(.*?)(-([0-9]+))?(\\..*$)?"); + + public static boolean isValidImage(String url) { + if (url == null) { + return false; + } + url = url.toLowerCase(Locale.ROOT); + return url.endsWith(".png") || url.endsWith(".jpg") || url.endsWith(".jpeg") || url.endsWith(".gif"); + } + + public static boolean isDocument(String url) { + if (url == null) { + return false; + } + url = url.toLowerCase(Locale.ROOT); + return url.endsWith(".doc") || url.endsWith(".docx") || url.endsWith(".odt") || url.endsWith(".pdf"); + } + + public static boolean isPowerpoint(String url) { + if (url == null) { + return false; + } + url = url.toLowerCase(Locale.ROOT); + return url.endsWith(".ppt") || url.endsWith(".pptx") || url.endsWith(".pps") || url.endsWith(".ppsx") + || url.endsWith(".key"); + } + + public static boolean isSpreadsheet(String url) { + if (url == null) { + return false; + } + url = url.toLowerCase(Locale.ROOT); + return url.endsWith(".xls") || url.endsWith(".xlsx"); + } + + public static boolean isVideo(String url) { + if (url == null) { + return false; + } + url = url.toLowerCase(Locale.ROOT); + return url.endsWith(".ogv") || url.endsWith(".mp4") || url.endsWith(".m4v") || url.endsWith(".mov") + || url.endsWith(".wmv") || url.endsWith(".avi") || url.endsWith(".mpg") || url.endsWith(".3gp") + || url.endsWith(".3g2") || url.contains("video"); + } + + public static boolean isAudio(String url) { + if (url == null) { + return false; + } + url = url.toLowerCase(Locale.ROOT); + return url.endsWith(".mp3") || url.endsWith(".ogg") || url.endsWith(".wav") || url.endsWith(".wma") + || url.endsWith(".aiff") || url.endsWith(".aif") || url.endsWith(".aac") || url.endsWith(".m4a"); + } + + public static boolean isGif(String url) { + return "gif".equals(MimeTypeMap.getFileExtensionFromUrl(url)); + } + + public static boolean isLocalFile(String state) { + if (state == null) { + return false; + } + + return state.equalsIgnoreCase("queued") + || state.equalsIgnoreCase("uploading") + || state.equalsIgnoreCase("retry") + || state.equalsIgnoreCase("failed"); + } + + public static Uri getLastRecordedVideoUri(Context appContext) { + String[] proj = {MediaStore.Video.Media._ID}; + Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + String sortOrder = MediaStore.Video.VideoColumns.DATE_TAKEN + " DESC"; + CursorLoader loader = new CursorLoader(appContext, contentUri, proj, null, null, sortOrder); + Cursor cursor = loader.loadInBackground(); + cursor.moveToFirst(); + long value = cursor.getLong(0); + SqlUtils.closeCursor(cursor); + + return Uri.parse(contentUri.toString() + "/" + value); + } + + /** + * Get image max size setting from the image max size setting string. This string can be an int, in this case it's + * the maximum image width defined by the site. + * Examples: + * "1000" will return 1000 + * "Original Size" will return Integer.MAX_VALUE + * "Largeur originale" will return Integer.MAX_VALUE + * null will return Integer.MAX_VALUE + * @param imageMaxSizeSiteSettingString Image max size site setting string + * @return Integer.MAX_VALUE if image width is not defined or invalid, maximum image width in other cases. + */ + public static int getImageMaxSizeSettingFromString(String imageMaxSizeSiteSettingString) { + if (imageMaxSizeSiteSettingString == null) { + return Integer.MAX_VALUE; + } + try { + return Integer.valueOf(imageMaxSizeSiteSettingString); + } catch (NumberFormatException e) { + return Integer.MAX_VALUE; + } + } + + /** + * Calculate and return the maximum allowed image width by comparing the width of the image at its full size with + * the maximum upload width set in the blog settings + * @param imageSize the image's natural (full) width + * @param imageMaxSizeSiteSettingString the maximum upload width set in the site settings + * @return maximum allowed image width + */ + public static int getMaximumImageSize(int imageSize, String imageMaxSizeSiteSettingString) { + int imageMaxSizeBlogSetting = getImageMaxSizeSettingFromString(imageMaxSizeSiteSettingString); + int imageWidthPictureSetting = imageSize == 0 ? Integer.MAX_VALUE : imageSize; + + if (Math.min(imageWidthPictureSetting, imageMaxSizeBlogSetting) == Integer.MAX_VALUE) { + // Default value in case of errors reading the picture size or the blog settings is set to Original size + return DEFAULT_MAX_IMAGE_WIDTH; + } else { + return Math.min(imageWidthPictureSetting, imageMaxSizeBlogSetting); + } + } + + public static int getMaximumImageSize(Context context, Uri curStream, String imageMaxSizeBlogSettingString) { + int[] dimensions = ImageUtils.getImageSize(curStream, context); + return getMaximumImageSize(dimensions[0], imageMaxSizeBlogSettingString); + } + + public static boolean isInMediaStore(Uri mediaUri) { + // Check if the image is externally hosted (Picasa/Google Photos for example) + return mediaUri != null && mediaUri.toString().startsWith("content://media/"); + } + + public static @Nullable String getFilenameFromURI(Context context, Uri uri) { + Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, + null, null, null); + try { + String result = null; + if (cursor != null && cursor.moveToFirst()) { + int columnIndexDisplayName = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); + if (columnIndexDisplayName == -1) { + return null; + } + result = cursor.getString(columnIndexDisplayName); + } + return result; + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + + /* + * Some media providers (eg. Google Photos) give us a limited access to media files just so we can copy them and + * then they revoke the access. Copying these files must be performed on the UI thread, otherwise the access might + * be revoked before the action completes. See https://github.com/wordpress-mobile/WordPress-Android/issues/5818 + */ + public static Uri downloadExternalMedia(Context context, Uri imageUri) { + if (context == null || imageUri == null) { + return null; + } + String mimeType = UrlUtils.getUrlMimeType(imageUri.toString()); + File cacheDir = context.getCacheDir(); + + if (cacheDir != null && !cacheDir.exists()) { + cacheDir.mkdirs(); + } + try { + InputStream input; + // Download the file + if (imageUri.toString().startsWith("content://")) { + input = context.getContentResolver().openInputStream(imageUri); + if (input == null) { + AppLog.e(T.UTILS, "openInputStream returned null"); + return null; + } + } else { + input = new URL(imageUri.toString()).openStream(); + } + + String fileName = getFilenameFromURI(context, imageUri); + if (TextUtils.isEmpty(fileName)) { + fileName = generateTimeStampedFileName(mimeType); + } + + File f = getUniqueCacheFileForName(fileName, cacheDir, mimeType); + + OutputStream output = new FileOutputStream(f); + + byte[] data = new byte[1024]; + int count; + while ((count = input.read(data)) != -1) { + output.write(data, 0, count); + } + + output.flush(); + output.close(); + input.close(); + + return Uri.fromFile(f); + } catch (IOException e) { + AppLog.e(T.UTILS, e); + } + + return null; + } + + private static File getUniqueCacheFileForName(String fileName, File cacheDir, String mimeType) { + File file = new File(cacheDir, fileName); + + while (file.exists()) { + Matcher matcher = FILE_EXISTS_PATTERN.matcher(fileName); + if (matcher.matches()) { + String baseFileName = matcher.group(1); + String existingDuplicationNumber = matcher.group(3); + String fileType = StringUtils.notNullStr(matcher.group(4)); + + if (existingDuplicationNumber == null) { + // Not a copy already + fileName = baseFileName + "-1" + fileType; + } else { + fileName = baseFileName + "-" + (StringUtils.stringToInt(existingDuplicationNumber) + 1) + fileType; + } + } else { + // Shouldn't happen, but in case our match fails fall back to timestamped file name + fileName = generateTimeStampedFileName(mimeType); + } + file = new File(cacheDir, fileName); + } + return file; + } + + public static String generateTimeStampedFileName(String mimeType) { + return "wp-" + System.currentTimeMillis() + "." + getExtensionForMimeType(mimeType); + } + + public static String getMimeTypeOfInputStream(InputStream stream) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(stream, null, options); + return options.outMimeType; + } + + public static String getMediaFileMimeType(File mediaFile) { + String originalFileName = mediaFile.getName().toLowerCase(Locale.ROOT); + String mimeType = UrlUtils.getUrlMimeType(originalFileName); + + if (TextUtils.isEmpty(mimeType)) { + try { + String filePathForGuessingMime; + if (mediaFile.getPath().contains("://")) { + filePathForGuessingMime = Uri.encode(mediaFile.getPath(), ":/"); + } else { + filePathForGuessingMime = "file://" + Uri.encode(mediaFile.getPath(), "/"); + } + URL urlForGuessingMime = new URL(filePathForGuessingMime); + URLConnection uc = urlForGuessingMime.openConnection(); + String guessedContentType = null; + try { + guessedContentType = + uc.getContentType(); // internally calls guessContentTypeFromName(url.getFile()); and + // guessContentTypeFromStream(is); + } catch (StringIndexOutOfBoundsException e) { + // Ref: https://github.com/wordpress-mobile/WordPress-Android/issues/5699 + AppLog.e(AppLog.T.MEDIA, "Error getting the content type for " + mediaFile.getPath() + + " by using URLConnection.getContentType", e); + } + // check if returned "content/unknown" + if (!TextUtils.isEmpty(guessedContentType) && !guessedContentType.equals("content/unknown")) { + mimeType = guessedContentType; + } + } catch (MalformedURLException e) { + AppLog.e(AppLog.T.MEDIA, + "MalformedURLException while trying to guess the content type for the file here " + mediaFile + .getPath() + " with URLConnection", e); + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, + "Error while trying to guess the content type for the file here " + mediaFile.getPath() + + " with URLConnection", e); + } + } + + // No mimeType yet? Try to decode the image and get the mimeType from there + if (TextUtils.isEmpty(mimeType)) { + try { + DataInputStream inputStream = new DataInputStream(new FileInputStream(mediaFile)); + String mimeTypeFromStream = getMimeTypeOfInputStream(inputStream); + if (!TextUtils.isEmpty(mimeTypeFromStream)) { + mimeType = mimeTypeFromStream; + } + inputStream.close(); + } catch (FileNotFoundException e) { + AppLog.e(AppLog.T.MEDIA, + "FileNotFoundException while trying to guess the content type for the file " + mediaFile + .getPath(), e); + } catch (IOException e) { + AppLog.e(AppLog.T.MEDIA, + "IOException while trying to guess the content type for the file " + mediaFile.getPath(), e); + } + } + + if (TextUtils.isEmpty(mimeType)) { + mimeType = ""; + } else { + if (mimeType.equalsIgnoreCase("video/mp4v-es")) { // Fixes #533. See: http://tools.ietf.org/html/rfc3016 + mimeType = "video/mp4"; + } + } + + return mimeType; + } + + public static String getMediaFileName(File mediaFile, String mimeType) { + String originalFileName = mediaFile.getName().toLowerCase(Locale.ROOT); + String extension = MimeTypeMap.getFileExtensionFromUrl(originalFileName); + if (!TextUtils.isEmpty(extension)) { // File name already has the extension in it + return originalFileName; + } + + if (!TextUtils.isEmpty(mimeType)) { // try to get the extension from mimeType + String fileExtension = getExtensionForMimeType(mimeType); + if (!TextUtils.isEmpty(fileExtension)) { + originalFileName += "." + fileExtension; + } + } else { + // No mimetype and no extension!! + AppLog.e(AppLog.T.API, "No mimetype and no extension for " + mediaFile.getPath()); + } + + return originalFileName; + } + + public static String getExtensionForMimeType(String mimeType) { + if (TextUtils.isEmpty(mimeType)) { + return ""; + } + + MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); + String fileExtensionFromMimeType = mimeTypeMap.getExtensionFromMimeType(mimeType); + if (TextUtils.isEmpty(fileExtensionFromMimeType)) { + // We're still without an extension - split the mime type and retrieve it + String[] split = mimeType.split("/"); + fileExtensionFromMimeType = split.length > 1 ? split[1] : split[0]; + } + + return fileExtensionFromMimeType.toLowerCase(Locale.ROOT); + } + + public static String getRealPathFromURI(final Context context, Uri uri) { + String path; + if ("content".equals(uri.getScheme())) { + path = MediaUtils.getPath(context, uri); + } else if ("file".equals(uri.getScheme())) { + path = uri.getPath(); + } else { + path = uri.toString(); + } + + return path; + } + + /** + * Get a file path from a Uri. This will get the the path for Storage Access + * Framework Documents, as well as the _data field for the MediaStore and + * other file-based ContentProviders. + * + * Based on paulburke's solution for aFileChooser - https://github.com/iPaulPro/aFileChooser + * + * @param context The context. + * @param uri The Uri to query. + */ + private static String getPath(final Context context, final Uri uri) { + String path = getDocumentProviderPathKitkatOrHigher(context, uri); + + if (path != null) { + return path; + } + + // MediaStore (and general) + if ("content".equalsIgnoreCase(uri.getScheme())) { + return getDataColumn(context, uri, null, null); + } else if ("file".equalsIgnoreCase(uri.getScheme())) { // File + return uri.getPath(); + } + + return null; + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + private static String getDocumentProviderPathKitkatOrHigher(final Context context, final Uri uri) { + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + + // TODO handle non-primary volumes + } else if (isDownloadsDocument(uri)) { + String id = DocumentsContract.getDocumentId(uri); + + if (id != null && id.startsWith("raw:")) { + return id.substring(4); + } + + // https://github.com/Javernaut/WhatTheCodec/issues/2 + if (id != null && id.startsWith("msf:")) { + id = id.substring(4); + } + + String[] contentUriPrefixesToTry = new String[]{ + "content://downloads/public_downloads", + "content://downloads/my_downloads", + "content://downloads/all_downloads" + }; + + for (String contentUriPrefix : contentUriPrefixesToTry) { + Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id)); + try { + String path = getDataColumn(context, contentUri, null, null); + if (path != null) { + return path; + } + } catch (Exception e) { + AppLog.e(AppLog.T.UTILS, "Error reading _data column for URI: " + contentUri, e); + } + } + return downloadExternalMedia(context, uri).getPath(); + } else if (isMediaDocument(uri)) { // MediaProvider + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = MediaStore.MediaColumns._ID + "=?"; + + final String[] selectionArgs = new String[]{ + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } + + return null; + } + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + */ + public static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + Cursor cursor = null; + final String column = MediaStore.MediaColumns.DATA; + + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + final int columnIndex = cursor.getColumnIndex(column); + if (columnIndex != -1) { + return cursor.getString(columnIndex); + } + } + } catch (SecurityException errReadingContentResolver) { + AppLog.e(AppLog.T.UTILS, "Error reading _data column for URI: " + uri, errReadingContentResolver); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java new file mode 100644 index 000000000000..83a2cb20066e --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java @@ -0,0 +1,100 @@ +package org.wordpress.android.util; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Build; +import android.os.Build.VERSION_CODES; +import android.provider.Settings; + +/** + * requires android.permission.ACCESS_NETWORK_STATE + */ +@SuppressLint("MissingPermission") +public class NetworkUtils { + public static final int TYPE_UNKNOWN = -1; + + /** + * returns information on the active network connection + */ + @SuppressLint("MissingPermission") + public static NetworkInfo getActiveNetworkInfo(Context context) { + if (context == null) { + return null; + } + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (cm == null) { + return null; + } + // note that this may return null if no network is currently active + return cm.getActiveNetworkInfo(); + } + + /** + * returns the ConnectivityManager.TYPE_xxx if there's an active connection, otherwise + * returns TYPE_UNKNOWN + */ + private static int getActiveNetworkType(Context context) { + NetworkInfo info = getActiveNetworkInfo(context); + if (info == null || !info.isConnected()) { + return TYPE_UNKNOWN; + } + return info.getType(); + } + + /** + * returns true if a network connection is available + */ + public static boolean isNetworkAvailable(Context context) { + NetworkInfo info = getActiveNetworkInfo(context); + return (info != null && info.isConnected()); + } + + /** + * returns true if the user is connected to WiFi + */ + public static boolean isWiFiConnected(Context context) { + return (getActiveNetworkType(context) == ConnectivityManager.TYPE_WIFI); + } + + /** + * returns true if the user is connected with the mobile data connection + */ + public static boolean isMobileConnected(Context context) { + int networkType = getActiveNetworkType(context); + return (networkType == ConnectivityManager.TYPE_MOBILE + || networkType == ConnectivityManager.TYPE_MOBILE_DUN); + } + + /** + * returns true if airplane mode has been enabled + */ + @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) + @SuppressWarnings("deprecation") + public static boolean isAirplaneModeOn(Context context) { + // prior to JellyBean 4.2 this was Settings.System.AIRPLANE_MODE_ON, JellyBean 4.2 + // moved it to Settings.Global + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { + return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0; + } else { + return Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0; + } + } + + /** + * returns true if there's an active network connection, otherwise displays a toast error + * and returns false + */ + public static boolean checkConnection(Context context) { + if (context == null) { + return false; + } + if (isNetworkAvailable(context)) { + return true; + } + ToastUtils.showToast(context, R.string.no_network_message); + return false; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java new file mode 100644 index 000000000000..52900a0bf27e --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java @@ -0,0 +1,45 @@ +package org.wordpress.android.util; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; + +public class PackageUtils { + /** + * Return true if Debug build. false otherwise. + */ + public static boolean isDebugBuild() { + return BuildConfig.DEBUG; + } + + public static PackageInfo getPackageInfo(Context context) { + try { + PackageManager manager = context.getPackageManager(); + return manager.getPackageInfo(context.getPackageName(), 0); + } catch (PackageManager.NameNotFoundException e) { + return null; + } + } + + /** + * Return version code, or 0 if it can't be read + */ + public static int getVersionCode(Context context) { + PackageInfo packageInfo = getPackageInfo(context); + if (packageInfo != null) { + return packageInfo.versionCode; + } + return 0; + } + + /** + * Return version name, or the string "0" if it can't be read + */ + public static String getVersionName(Context context) { + PackageInfo packageInfo = getPackageInfo(context); + if (packageInfo != null) { + return packageInfo.versionName; + } + return "0"; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java new file mode 100644 index 000000000000..8d484d847519 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java @@ -0,0 +1,104 @@ +package org.wordpress.android.util; + +import android.Manifest.permission; +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; + +import java.util.ArrayList; +import java.util.List; + +public class PermissionUtils { + /** + * Check for permissions, request them if they're not granted. + * + * @return true if permissions are already granted, else request them and return false. + */ + public static boolean checkAndRequestPermissions(Activity activity, int requestCode, String[] permissionList) { + List toRequest = new ArrayList<>(); + for (String permission : permissionList) { + if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + toRequest.add(permission); + } + } + if (toRequest.size() > 0) { + String[] requestedPermissions = toRequest.toArray(new String[toRequest.size()]); + ActivityCompat.requestPermissions(activity, requestedPermissions, requestCode); + return false; + } + return true; + } + + /** + * Check for permissions, request them if they're not granted. + * + * @return true if permissions are already granted, else request them and return false. + */ + private static boolean checkAndRequestPermissions(Fragment fragment, int requestCode, String[] permissionList) { + List toRequest = new ArrayList<>(); + for (String permission : permissionList) { + Context context = fragment.getActivity(); + if (context != null && ContextCompat.checkSelfPermission(context, permission) != PackageManager + .PERMISSION_GRANTED) { + toRequest.add(permission); + } + } + if (toRequest.size() > 0) { + String[] requestedPermissions = toRequest.toArray(new String[toRequest.size()]); + fragment.requestPermissions(requestedPermissions, requestCode); + return false; + } + return true; + } + + /** + * Check for permissions without requesting them + * + * @return true if all permissions are granted + */ + public static boolean checkPermissions(Activity activity, String[] permissionList) { + for (String permission : permissionList) { + if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + + public static boolean checkCameraAndStoragePermissions(Activity activity) { + return checkPermissions(activity, + new String[]{ + permission.WRITE_EXTERNAL_STORAGE, + permission.CAMERA}); + } + + public static boolean checkAndRequestCameraAndStoragePermissions(Fragment fragment, int requestCode) { + return checkAndRequestPermissions(fragment, requestCode, new String[]{ + permission.WRITE_EXTERNAL_STORAGE, + permission.CAMERA + }); + } + + public static boolean checkAndRequestCameraAndStoragePermissions(Activity activity, int requestCode) { + return checkAndRequestPermissions(activity, requestCode, new String[]{ + permission.WRITE_EXTERNAL_STORAGE, + permission.CAMERA + }); + } + + public static boolean checkAndRequestStoragePermission(Activity activity, int requestCode) { + return checkAndRequestPermissions(activity, requestCode, new String[]{ + permission.WRITE_EXTERNAL_STORAGE + }); + } + + public static boolean checkAndRequestStoragePermission(Fragment fragment, int requestCode) { + return checkAndRequestPermissions(fragment, requestCode, new String[]{ + permission.WRITE_EXTERNAL_STORAGE + }); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java new file mode 100644 index 000000000000..2f12eb05fae7 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java @@ -0,0 +1,143 @@ +package org.wordpress.android.util; + +import android.text.TextUtils; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * routines related to the Photon API + * http://developer.wordpress.com/docs/photon/ + */ +public class PhotonUtils { + private PhotonUtils() { + throw new AssertionError(); + } + + /* + * returns true if the passed url is an obvious "mshots" url + */ + public static boolean isMshotsUrl(final String imageUrl) { + return (imageUrl != null && imageUrl.contains("/mshots/")); + } + + /* + * returns a photon url for the passed image with the resize query set to the passed + * dimensions - note that the passed quality parameter will only affect JPEGs + */ + public enum Quality { + HIGH, + MEDIUM, + LOW + } + + public static final String ATOMIC_MEDIA_PROXY_URL_PREFIX = "https://public-api.wordpress.com/wpcom/v2/sites/"; + public static final String ATOMIC_MEDIA_PROXY_URL_SUFFIX = "/atomic-auth-proxy/file"; + + public static String getPhotonImageUrl(String imageUrl, int width, int height) { + return getPhotonImageUrl(imageUrl, width, height, Quality.MEDIUM); + } + + public static String getPhotonImageUrl(String imageUrl, int width, int height, boolean isPrivateAtomicSite) { + return getPhotonImageUrl(imageUrl, width, height, Quality.MEDIUM, isPrivateAtomicSite); + } + + public static String getPhotonImageUrl(String imageUrl, int width, int height, Quality quality) { + return getPhotonImageUrl(imageUrl, width, height, quality, false); + } + + public static String getPhotonImageUrl(String imageUrl, int width, int height, Quality quality, + boolean isPrivateAtomicSite) { + if (TextUtils.isEmpty(imageUrl)) { + return ""; + } + + // make sure it's valid + int schemePos = imageUrl.indexOf("://"); + if (schemePos == -1) { + return imageUrl; + } + + // we have encountered some image urls that incorrectly have a # fragment part, which + // must be removed before removing the query string + int fragmentPos = imageUrl.indexOf("#"); + if (fragmentPos > 0) { + imageUrl = imageUrl.substring(0, fragmentPos); + } + + String urlCopy = imageUrl; + + // remove existing query string since it may contain params that conflict with the passed ones + imageUrl = UrlUtils.removeQuery(imageUrl); + + // if this is an "mshots" url, skip photon and return it with a query that sets the width/height + if (isMshotsUrl(imageUrl)) { + return imageUrl + "?w=" + width + "&h=" + height; + } + + // strip=info removes Exif, IPTC and comment data from the output image. + String query = "?strip=info"; + + switch (quality) { + case HIGH: + query += "&quality=100"; + break; + case LOW: + query += "&quality=35"; + break; + default: // medium + query += "&quality=65"; + break; + } + + // if both width & height are passed use the "resize" param, use only "w" or "h" if just + // one of them is set + if (width > 0 && height > 0) { + query += "&resize=" + width + "," + height; + } else if (width > 0) { + query += "&w=" + width; + } else if (height > 0) { + query += "&h=" + height; + } + + if (isPrivateAtomicSite) { + try { + URL url = new URL(imageUrl); + String slug = url.getHost(); + String path = url.getPath(); + return ATOMIC_MEDIA_PROXY_URL_PREFIX + slug + ATOMIC_MEDIA_PROXY_URL_SUFFIX + + "?path=" + path + "&" + query; + } catch (MalformedURLException e) { + e.printStackTrace(); + return ""; + } + } + + // return passed url+query if it's already a photon url + if (imageUrl.contains(".wp.com")) { + if (imageUrl.contains("i0.wp.com") || imageUrl.contains("i1.wp.com") || imageUrl.contains("i2.wp.com")) { + boolean useSsl = urlCopy.indexOf("?") > 0 && urlCopy.contains("ssl=1"); + + if (useSsl) { + query += "&ssl=1"; + } + + return imageUrl + query; + } + } + + // use wordpress.com as the host if image is on wordpress.com since it supports the same + // query params and, more importantly, can handle images in private blogs + if (imageUrl.contains("wordpress.com")) { + return imageUrl + query; + } + + // must use ssl=1 parameter for https image urls + boolean useSSl = UrlUtils.isHttps(imageUrl); + if (useSSl) { + query += "&ssl=1"; + } + + return "https://i0.wp.com/" + imageUrl.substring(schemePos + 3, imageUrl.length()) + query; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java new file mode 100644 index 000000000000..2bda40589853 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java @@ -0,0 +1,87 @@ +package org.wordpress.android.util; + +import android.os.SystemClock; + +import org.wordpress.android.util.AppLog.T; + +import java.util.ArrayList; + +/** + * forked from android.util.TimingLogger to use AppLog instead of Log + new static interface. + */ +public class ProfilingUtils { + private static ProfilingUtils sInstance; + + private String mLabel; + private ArrayList mSplits; + private ArrayList mSplitLabels; + + public static void start(String label) { + getInstance().reset(label); + } + + public static void split(String splitLabel) { + getInstance().addSplit(splitLabel); + } + + public static void dump() { + getInstance().dumpToLog(); + } + + public static void stop() { + getInstance().reset(null); + } + + private static ProfilingUtils getInstance() { + if (sInstance == null) { + sInstance = new ProfilingUtils(); + } + return sInstance; + } + + public ProfilingUtils() { + reset("init"); + } + + public void reset(String label) { + mLabel = label; + reset(); + } + + public void reset() { + if (mSplits == null) { + mSplits = new ArrayList(); + mSplitLabels = new ArrayList(); + } else { + mSplits.clear(); + mSplitLabels.clear(); + } + addSplit(null); + } + + public void addSplit(String splitLabel) { + if (mLabel == null) { + return; + } + long now = SystemClock.elapsedRealtime(); + mSplits.add(now); + mSplitLabels.add(splitLabel); + } + + public void dumpToLog() { + if (mLabel == null) { + return; + } + AppLog.d(T.PROFILING, mLabel + ": begin"); + final long first = mSplits.get(0); + long now = first; + for (int i = 1; i < mSplits.size(); i++) { + now = mSplits.get(i); + final String splitLabel = mSplitLabels.get(i); + final long prev = mSplits.get(i - 1); + AppLog.d(T.PROFILING, mLabel + ": " + (now - prev) + " ms, " + splitLabel); + } + AppLog.d(T.PROFILING, mLabel + ": end, " + (now - first) + " ms"); + } +} + diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java new file mode 100644 index 000000000000..6bcfde06b892 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java @@ -0,0 +1,16 @@ +package org.wordpress.android.util; + +import android.app.ActivityManager; +import android.content.Context; + +public class ServiceUtils { + public static boolean isServiceRunning(Context context, Class serviceClass) { + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { + if (serviceClass.getName().equals(service.service.getClassName())) { + return true; + } + } + return false; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java new file mode 100644 index 000000000000..09480f156364 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java @@ -0,0 +1,31 @@ +package org.wordpress.android.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ShortcodeUtils { + public static String getVideoPressShortcodeFromId(String videoPressId) { + if (videoPressId == null || videoPressId.isEmpty()) { + return ""; + } + + return "[wpvideo " + videoPressId + "]"; + } + + public static String getVideoPressIdFromShortCode(String shortcode) { + String videoPressId = ""; + + if (shortcode != null) { + String videoPressShortcodeRegex = "^\\[wpvideo (.*)]$"; + + Pattern pattern = Pattern.compile(videoPressShortcodeRegex); + Matcher matcher = pattern.matcher(shortcode); + + if (matcher.find()) { + videoPressId = matcher.group(1); + } + } + + return videoPressId; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java new file mode 100644 index 000000000000..e9ca93d2ec7c --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java @@ -0,0 +1,146 @@ +package org.wordpress.android.util; + +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDoneException; +import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteStatement; + +import org.wordpress.android.util.AppLog.T; + +import java.util.ArrayList; +import java.util.List; + +public class SqlUtils { + private SqlUtils() { + throw new AssertionError(); + } + + /* + * SQLite doesn't have a boolean datatype, so booleans are stored as 0=false, 1=true + */ + public static long boolToSql(boolean value) { + return (value ? 1 : 0); + } + + public static boolean sqlToBool(int value) { + return (value != 0); + } + + public static void closeStatement(SQLiteStatement stmt) { + if (stmt != null) { + stmt.close(); + } + } + + public static void closeCursor(Cursor c) { + if (c != null && !c.isClosed()) { + c.close(); + } + } + + /* + * wrapper for DatabaseUtils.longForQuery() which returns 0 if query returns no rows + */ + public static long longForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { + try { + return DatabaseUtils.longForQuery(db, query, selectionArgs); + } catch (SQLiteDoneException e) { + return 0; + } + } + + public static int intForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { + long value = longForQuery(db, query, selectionArgs); + return (int) value; + } + + public static boolean boolForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { + long value = longForQuery(db, query, selectionArgs); + return sqlToBool((int) value); + } + + /* + * wrapper for DatabaseUtils.stringForQuery(), returns "" if query returns no rows + */ + public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { + try { + return DatabaseUtils.stringForQuery(db, query, selectionArgs); + } catch (SQLiteDoneException e) { + return ""; + } + } + + /* + * returns the number of rows in the passed table + */ + public static long getRowCount(SQLiteDatabase db, String tableName) { + return DatabaseUtils.queryNumEntries(db, tableName); + } + + /* + * removes all rows from the passed table + */ + public static void deleteAllRowsInTable(SQLiteDatabase db, String tableName) { + db.delete(tableName, null, null); + } + + /* + * drop all tables from the passed SQLiteDatabase - make sure to pass a + * writable database + */ + public static boolean dropAllTables(SQLiteDatabase db) throws SQLiteException { + if (db == null) { + return false; + } + + if (db.isReadOnly()) { + throw new SQLiteException("can't drop tables from a read-only database"); + } + + List tableNames = new ArrayList(); + Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null); + if (cursor.moveToFirst()) { + do { + String tableName = cursor.getString(0); + if (!tableName.equals("android_metadata") && !tableName.equals("sqlite_sequence")) { + tableNames.add(tableName); + } + } while (cursor.moveToNext()); + } + + db.beginTransaction(); + try { + for (String tableName : tableNames) { + db.execSQL("DROP TABLE IF EXISTS " + tableName); + } + db.setTransactionSuccessful(); + return true; + } finally { + db.endTransaction(); + closeCursor(cursor); + } + } + + /* + * Android's CursorWindow has a max size of 2MB per row which can be exceeded + * with a very large text column, causing an IllegalStateException when the + * row is read - prevent this by limiting the amount of text that's stored in + * the text column. + * https://github.com/android/platform_frameworks_base/blob/b77bc869241644a662f7e615b0b00ecb5aee373d/core/res/res + * /values/config.xml#L1268 + * https://github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/core/java + * /android/database/CursorWindow.java#L103 + */ + // Max 512K characters (a UTF-8 char is 4 bytes max, so a 512K characters string is always < 2Mb) + private static final int MAX_TEXT_LEN = 1024 * 1024 / 2; + + public static String maxSQLiteText(final String text) { + if (text.length() <= MAX_TEXT_LEN) { + return text; + } + AppLog.w(T.UTILS, "sqlite > max text exceeded, storing truncated text"); + return text.substring(0, MAX_TEXT_LEN); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java new file mode 100644 index 000000000000..ef96282eb1fb --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java @@ -0,0 +1,363 @@ +package org.wordpress.android.util; + +import android.content.Context; +import android.text.TextUtils; + +import androidx.annotation.StringRes; + +import org.wordpress.android.util.AppLog.T; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +public class StringUtils { + /** + * Compare two Strings lexicographically + * Mirrors {@link org.apache.commons.lang3.StringUtils#compare(String, String)}. Use this version when there is a + * hint that the Apache lib might not be provided by the system. + * @param s1 the String to compare from + * @param s2 the String to compare to + * @return < 0, 0, > 0, if {@code s1} is respectively less, equal ou greater than {@code s2} + */ + public static int compare(String s1, String s2) { + if (s1 == s2) { + return 0; + } else if (s1 == null) { + return -1; + } else if (s2 == null) { + return 1; + } else { + return s1.compareTo(s2); + } + } + + /** + * Compare two Strings lexicographically, ignoring case differences. + * Mirrors {@link org.apache.commons.lang3.StringUtils#compareIgnoreCase(String, String)}. Use this version when + * there is a hint that the Apache lib might not be provided by the system. + * @param s1 the String to compare from + * @param s2 the String to compare to + * @return < 0, 0, > 0, if {@code s1} is respectively less, equal ou greater than {@code s2} + */ + public static int compareIgnoreCase(final String s1, final String s2) { + if (s1 == s2) { + return 0; + } + if (s1 == null) { + return -1; + } + if (s2 == null) { + return 1; + } + return s1.compareToIgnoreCase(s2); + } + + public static String[] mergeStringArrays(String[] array1, String[] array2) { + if (array1 == null || array1.length == 0) { + return array2; + } + if (array2 == null || array2.length == 0) { + return array1; + } + List array1List = Arrays.asList(array1); + List array2List = Arrays.asList(array2); + List result = new ArrayList(array1List); + List tmp = new ArrayList(array1List); + tmp.retainAll(array2List); + result.addAll(array2List); + return ((String[]) result.toArray(new String[result.size()])); + } + + public static String convertHTMLTagsForUpload(String source) { + // bold + source = source.replace("", ""); + source = source.replace("", ""); + + // italics + source = source.replace("", ""); + source = source.replace("", ""); + + return source; + } + + public static String convertHTMLTagsForDisplay(String source) { + // bold + source = source.replace("", ""); + source = source.replace("", ""); + + // italics + source = source.replace("", ""); + source = source.replace("", ""); + + return source; + } + + public static String addPTags(String source) { + String[] asploded = source.split("\n\n"); + + if (asploded.length > 0) { + StringBuilder wrappedHTML = new StringBuilder(); + for (int i = 0; i < asploded.length; i++) { + String trimmed = asploded[i].trim(); + if (trimmed.length() > 0) { + trimmed = trimmed.replace("
    ", "
    ").replace("
    ", "
    ").replace("
    \n", "
    ") + .replace("\n", "
    "); + wrappedHTML.append("

    "); + wrappedHTML.append(trimmed); + wrappedHTML.append("

    "); + } + } + return wrappedHTML.toString(); + } else { + return source; + } + } + + public static BigInteger getMd5IntHash(String input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest(input.getBytes()); + BigInteger number = new BigInteger(1, messageDigest); + return number; + } catch (NoSuchAlgorithmException e) { + AppLog.e(T.UTILS, e); + return null; + } + } + + public static String getMd5Hash(String input) { + BigInteger number = getMd5IntHash(input); + String md5 = number.toString(16); + while (md5.length() < 32) { + md5 = "0" + md5; + } + return md5; + } + + /* + * nbradbury - adapted from Html.escapeHtml(), which was added in API Level 16 + * TODO: not thoroughly tested yet, so marked as private - not sure I like the way + * this replaces two spaces with " " + */ + private static String escapeHtml(final String text) { + if (text == null) { + return ""; + } + + StringBuilder out = new StringBuilder(); + int length = text.length(); + + for (int i = 0; i < length; i++) { + char c = text.charAt(i); + + if (c == '<') { + out.append("<"); + } else if (c == '>') { + out.append(">"); + } else if (c == '&') { + out.append("&"); + } else if (c > 0x7E || c < ' ') { + out.append("&#").append((int) c).append(";"); + } else if (c == ' ') { + while (i + 1 < length && text.charAt(i + 1) == ' ') { + out.append(" "); + i++; + } + + out.append(' '); + } else { + out.append(c); + } + } + + return out.toString(); + } + + /* + * returns empty string if passed string is null, otherwise returns passed string + */ + public static String notNullStr(String s) { + if (s == null) { + return ""; + } + return s; + } + + /** + * returns true if two strings are equal or two strings are null + */ + public static boolean equals(String s1, String s2) { + if (s1 == null) { + return s2 == null; + } + return s1.equals(s2); + } + + /* + * capitalizes the first letter in the passed string - based on Apache commons/lang3/StringUtils + * http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/StringUtils + * .java?revision=1497829&view=markup + */ + public static String capitalize(final String str) { + int strLen; + if (str == null || (strLen = str.length()) == 0) { + return str; + } + + char firstChar = str.charAt(0); + if (Character.isTitleCase(firstChar)) { + return str; + } + + return new StringBuilder(strLen).append(Character.toTitleCase(firstChar)).append(str.substring(1)).toString(); + } + + public static String removeTrailingSlash(final String str) { + if (TextUtils.isEmpty(str) || !str.endsWith("/")) { + return str; + } + + return str.substring(0, str.length() - 1); + } + + /* + * Wrap an image URL in a photon URL + * Check out http://developer.wordpress.com/docs/photon/ + */ + public static String getPhotonUrl(String imageUrl, int size) { + imageUrl = imageUrl.replace("http://", "").replace("https://", ""); + return "http://i0.wp.com/" + imageUrl + "?w=" + size; + } + + public static String replaceUnicodeSurrogateBlocksWithHTMLEntities(final String inputString) { + final int length = inputString.length(); + StringBuilder out = new StringBuilder(); // Used to hold the output. + for (int offset = 0; offset < length;) { + final int codepoint = inputString.codePointAt(offset); + final char current = inputString.charAt(offset); + if (Character.isHighSurrogate(current) || Character.isLowSurrogate(current)) { + if (EmoticonsUtils.WP_SMILIES_CODE_POINT_TO_TEXT.get(codepoint) != null) { + out.append(EmoticonsUtils.WP_SMILIES_CODE_POINT_TO_TEXT.get(codepoint)); + } else { + final String htmlEscapedChar = "&#x" + Integer.toHexString(codepoint) + ";"; + out.append(htmlEscapedChar); + } + } else { + out.append(current); + } + offset += Character.charCount(codepoint); + } + return out.toString(); + } + + /** + * Used to convert a language code ([lc]_[rc] where lc is language code (en, fr, es, etc...) + * and rc is region code (zh-CN, zh-HK, zh-TW, etc...) to a displayable string with the languages + * name. + * + * The input string must be between 2 and 6 characters, inclusive. An empty string is returned + * if that is not the case. + * + * If the input string is recognized by {@link Locale} the result of this method is the given + * + * @return non-null + */ + public static String getLanguageString(String languagueCode, Locale displayLocale) { + if (languagueCode == null || languagueCode.length() < 2 || languagueCode.length() > 6) { + return ""; + } + + Locale languageLocale = new Locale(languagueCode.substring(0, 2)); + return languageLocale.getDisplayLanguage(displayLocale) + languagueCode.substring(2); + } + + /** + * This method ensures that the output String has only + * valid XML unicode characters as specified by the + * XML 1.0 standard. For reference, please see + * the + * standard. This method will return an empty + * String if the input is null or empty. + * + * @param in The String whose non-valid characters we want to remove. + * @return The in String, stripped of non-valid characters. + */ + public static final String stripNonValidXMLCharacters(String in) { + StringBuilder out = new StringBuilder(); // Used to hold the output. + char current; // Used to reference the current character. + + if (in == null || ("".equals(in))) { + return ""; // vacancy test. + } + for (int i = 0; i < in.length(); i++) { + current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen. + if ((current == 0x9) + || (current == 0xA) + || (current == 0xD) + || ((current >= 0x20) && (current <= 0xD7FF)) + || ((current >= 0xE000) && (current <= 0xFFFD)) + || ((current >= 0x10000) && (current <= 0x10FFFF))) { + out.append(current); + } + } + return out.toString(); + } + + /* + * simple wrapper for Integer.valueOf(string) so caller doesn't need to catch NumberFormatException + */ + public static int stringToInt(String s) { + return stringToInt(s, 0); + } + + public static int stringToInt(String s, int defaultValue) { + if (s == null) { + return defaultValue; + } + try { + return Integer.valueOf(s); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + public static long stringToLong(String s) { + return stringToLong(s, 0L); + } + + public static long stringToLong(String s, long defaultValue) { + if (s == null) { + return defaultValue; + } + try { + return Long.valueOf(s); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * Formats the string for the given quantity, using the given arguments. + * We need this because our translation platform doesn't support Android plurals. + * + * @param zero The desired string identifier to get when quantity is exactly 0 + * @param one The desired string identifier to get when quantity is exactly 1 + * @param other The desired string identifier to get when quantity is not (0 or 1) + * @param quantity The number used to get the correct string + */ + public static String getQuantityString(Context context, @StringRes int zero, @StringRes int one, + @StringRes int other, int quantity) { + if (quantity == 0) { + return context.getString(zero); + } + if (quantity == 1) { + return context.getString(one); + } + return String.format(context.getString(other), quantity); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java new file mode 100644 index 000000000000..e3fee7fc33b7 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java @@ -0,0 +1,14 @@ +package org.wordpress.android.util; + +import android.content.Context; + +public class SystemServiceFactory { + private static SystemServiceFactoryAbstract sFactory; + + public static Object get(Context context, String name) { + if (sFactory == null) { + sFactory = new SystemServiceFactoryDefault(); + } + return sFactory.get(context, name); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java new file mode 100644 index 000000000000..7b86f6631062 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java @@ -0,0 +1,7 @@ +package org.wordpress.android.util; + +import android.content.Context; + +public interface SystemServiceFactoryAbstract { + Object get(Context context, String name); +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java new file mode 100644 index 000000000000..eb488dde9bf4 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java @@ -0,0 +1,9 @@ +package org.wordpress.android.util; + +import android.content.Context; + +public class SystemServiceFactoryDefault implements SystemServiceFactoryAbstract { + public Object get(Context context, String name) { + return context.getSystemService(name); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java new file mode 100644 index 000000000000..470867364b8c --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java @@ -0,0 +1,53 @@ +package org.wordpress.android.util; + +import android.content.Context; +import android.view.Gravity; +import android.widget.Toast; + +/** + * Provides a simplified way to show toast messages without having to create the toast, set the + * desired gravity, etc. + */ +public class ToastUtils { + public enum Duration { + SHORT, LONG + } + + private ToastUtils() { + throw new AssertionError(); + } + + public static Toast showToast(Context context, int stringResId) { + return showToast(context, stringResId, Duration.SHORT); + } + + public static Toast showToast(Context context, int stringResId, Duration duration) { + return showToast(context, context.getString(stringResId), duration); + } + + public static Toast showToast(Context context, String text) { + return showToast(context, text, Duration.SHORT); + } + + public static Toast showToast(Context context, String text, Duration duration) { + return showToast(context, text, duration, Gravity.CENTER); + } + + public static Toast showToast(Context context, String text, Duration duration, int gravity) { + return showToast(context, text, duration, gravity, 0, 0); + } + + public static Toast showToast( + Context context, + String text, + Duration duration, + int gravity, + int xOffset, + int yOffset) { + Toast toast = Toast.makeText(context, text, + (duration == Duration.SHORT ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG)); + toast.setGravity(gravity, xOffset, yOffset); + toast.show(); + return toast; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java new file mode 100644 index 000000000000..0068ac9d4d8b --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java @@ -0,0 +1,318 @@ +package org.wordpress.android.util; + +import android.net.Uri; +import android.text.TextUtils; +import android.webkit.MimeTypeMap; +import android.webkit.URLUtil; + +import androidx.annotation.Nullable; + +import org.wordpress.android.util.AppLog.T; + +import java.io.UnsupportedEncodingException; +import java.net.IDN; +import java.net.URI; +import java.net.URL; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import static org.wordpress.android.util.PhotonUtils.ATOMIC_MEDIA_PROXY_URL_PREFIX; +import static org.wordpress.android.util.PhotonUtils.ATOMIC_MEDIA_PROXY_URL_SUFFIX; + +public class UrlUtils { + public static String urlEncode(final String text) { + try { + return URLEncoder.encode(text, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return text; + } + } + + public static String urlDecode(final String text) { + try { + return URLDecoder.decode(text, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return text; + } + } + + /** + * @param urlString url to get host from + * @return host of uri if available. Empty string otherwise. + */ + public static String getHost(final String urlString) { + if (urlString != null) { + Uri uri = Uri.parse(urlString); + if (uri.getHost() != null) { + return uri.getHost(); + } + } + return ""; + } + + public static boolean isContentUri(String uri) { + return "content".equals(Uri.parse(uri).getScheme()); + } + + /** + * Convert IDN names to punycode if necessary + */ + public static String convertUrlToPunycodeIfNeeded(String url) { + if (!Charset.forName("US-ASCII").newEncoder().canEncode(url)) { + if (url.toLowerCase(Locale.ROOT).startsWith("http://")) { + url = "http://" + IDN.toASCII(url.substring(7), IDN.ALLOW_UNASSIGNED); + } else if (url.toLowerCase(Locale.ROOT).startsWith("https://")) { + url = "https://" + IDN.toASCII(url.substring(8), IDN.ALLOW_UNASSIGNED); + } else { + url = IDN.toASCII(url, IDN.ALLOW_UNASSIGNED); + } + } + return url; + } + + /** + * Remove leading double slash, and inherit protocol scheme + */ + public static String removeLeadingDoubleSlash(String url, String scheme) { + if (url != null && url.startsWith("//")) { + url = url.substring(2); + if (scheme != null) { + if (scheme.endsWith("://")) { + url = scheme + url; + } else { + AppLog.e(T.UTILS, "Invalid scheme used: " + scheme); + } + } + } + return url; + } + + /** + * Add scheme prefix to an URL. This method must be called on all user entered or server fetched URLs to ensure + * http client will work as expected. + * + * @param url url entered by the user or fetched from a server + * @param addHttps true and the url is not starting with http://, it will make the url starts with https:// + * @return url prefixed by http:// or https:// + */ + public static String addUrlSchemeIfNeeded(String url, boolean addHttps) { + if (url == null) { + return null; + } + + // Remove leading double slash (eg. // example.com), needed for some wporg instances configured to + // switch between http or https + url = removeLeadingDoubleSlash(url, (addHttps ? "https" : "http") + "://"); + + // If the URL is a valid http or https URL, we're good to go + if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) { + return url; + } + + // Else, remove the old scheme and prefix it by https:// or http:// + return (addHttps ? "https" : "http") + "://" + removeScheme(url); + } + + /** + * normalizes a URL, primarily for comparison purposes, for example so that + * normalizeUrl("http://google.com/") = normalizeUrl("http://google.com") + */ + public static String normalizeUrl(final String urlString) { + if (urlString == null) { + return null; + } + + // this routine is called from some performance-critical code and creating a URI from a string + // is slow, so skip it when possible - if we know it's not a relative path (and 99.9% of the + // time it won't be for our purposes) then we can normalize it without java.net.URI.normalize() + if (urlString.startsWith("http") + && !urlString.contains("build/intermediates/exploded-aar/org.wordpress/graphview/3.1.1")) { + // return without a trailing slash + if (urlString.endsWith("/")) { + return urlString.substring(0, urlString.length() - 1); + } + return urlString; + } + + // url is relative, so fall back to using slower java.net.URI normalization + try { + URI uri = URI.create(urlString); + return uri.normalize().toString(); + } catch (IllegalArgumentException e) { + return urlString; + } + } + + + /** + * returns the passed url without the scheme + */ + public static String removeScheme(final String urlString) { + if (urlString == null) { + return null; + } + + int doubleslash = urlString.indexOf("//"); + if (doubleslash == -1) { + doubleslash = 0; + } else { + doubleslash += 2; + } + + return urlString.substring(doubleslash, urlString.length()); + } + + /** + * returns the passed url without the query parameters + */ + public static String removeQuery(final String urlString) { + if (urlString == null) { + return null; + } + return Uri.parse(urlString).buildUpon().clearQuery().toString(); + } + + /** + * returns true if passed url is https: + */ + public static boolean isHttps(final String urlString) { + return (urlString != null && urlString.startsWith("https:")); + } + + public static boolean isHttps(URL url) { + return url != null && "https".equals(url.getProtocol()); + } + + public static boolean isHttps(URI uri) { + if (uri == null) { + return false; + } + + String protocol = uri.getScheme(); + return protocol != null && protocol.equals("https"); + } + + /** + * returns https: version of passed http: url + */ + public static String makeHttps(final String urlString) { + if (urlString == null || !urlString.startsWith("http:")) { + return urlString; + } + return "https:" + urlString.substring(5, urlString.length()); + } + + /** + * see http://stackoverflow.com/a/8591230/1673548 + */ + public static String getUrlMimeType(final String urlString) { + if (urlString == null) { + return null; + } + + String extension = MimeTypeMap.getFileExtensionFromUrl(urlString); + if (extension == null) { + return null; + } + + MimeTypeMap mime = MimeTypeMap.getSingleton(); + String mimeType = mime.getMimeTypeFromExtension(extension); + if (mimeType == null) { + return null; + } + + return mimeType; + } + + /** + * returns false if the url is not valid or if the url host is null, else true + */ + public static boolean isValidUrlAndHostNotNull(String url) { + try { + URI uri = URI.create(url); + if (uri.getHost() == null) { + return false; + } + } catch (IllegalArgumentException e) { + return false; + } + return true; + } + + // returns true if the passed url is for an image + public static boolean isImageUrl(String url) { + if (TextUtils.isEmpty(url)) { + return false; + } + + String cleanedUrl = removeQuery(url.toLowerCase(Locale.ROOT)); + + if (isAtomicImageProxyUrl(cleanedUrl)) { + return true; + } + + return cleanedUrl.endsWith("jpg") || cleanedUrl.endsWith("jpeg") + || cleanedUrl.endsWith("gif") || cleanedUrl.endsWith("png"); + } + + public static @Nullable String getPageJumpOrNull(String url) { + if (TextUtils.isEmpty(url)) { + return null; + } + + if (url.contains("#") + && url.indexOf("#") < url.length() - 1 + && url.split("#").length == 2) { + return url.substring(url.indexOf('#') + 1); + } + + return null; + } + + private static boolean isAtomicImageProxyUrl(String urlString) { + return urlString.startsWith(ATOMIC_MEDIA_PROXY_URL_PREFIX) && urlString.endsWith(ATOMIC_MEDIA_PROXY_URL_SUFFIX); + } + + public static String appendUrlParameter(String url, String paramName, String paramValue) { + Map parameters = new HashMap<>(); + parameters.put(paramName, paramValue); + return appendUrlParameters(url, parameters); + } + + public static String appendUrlParameters(String url, Map parameters) { + Uri.Builder uriBuilder = Uri.parse(url).buildUpon(); + for (Map.Entry parameter : parameters.entrySet()) { + uriBuilder.appendQueryParameter(parameter.getKey(), parameter.getValue()); + } + return uriBuilder.build().toString(); + } + + /** + * Extracts the subdomain from a domain string. + * @param domain A domain is expected. Protocol is optional + * @return The subdomain or an empty string. + */ + public static String extractSubDomain(String domain) { + String str = UrlUtils.addUrlSchemeIfNeeded(domain, false); + String host = UrlUtils.getHost(str); + if (host.length() > 0) { + String[] parts = host.split("\\."); + if (parts.length > 1) { // There should be at least 2 dots for there to be a subdomain. + return parts[0]; + } + } + return ""; + } + + public static String removeXmlrpcSuffix(String siteAddress) { + if (siteAddress.toLowerCase(Locale.ROOT).endsWith("/xmlrpc.php")) { + return siteAddress.substring(0, siteAddress.lastIndexOf("xmlrpc.php")); + } else { + return siteAddress; + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java new file mode 100644 index 000000000000..8ccb5c4a51c8 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java @@ -0,0 +1,39 @@ +package org.wordpress.android.util; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.Context; +import android.util.Patterns; + +import org.wordpress.android.util.AppLog.T; + +import java.util.regex.Pattern; + +public class UserEmailUtils { + /** + * Get primary account and return its name if it matches the email address pattern. + * + * @return primary account email address if it can be found or empty string else. + */ + public static String getPrimaryEmail(Context context) { + try { + AccountManager accountManager = AccountManager.get(context); + if (accountManager == null) { + return ""; + } + Account[] accounts = accountManager.getAccounts(); + Pattern emailPattern = Patterns.EMAIL_ADDRESS; + for (Account account : accounts) { + // make sure account.name is an email address before adding to the list + if (emailPattern.matcher(account.name).matches()) { + return account.name; + } + } + return ""; + } catch (SecurityException e) { + // exception will occur if app doesn't have GET_ACCOUNTS permission + AppLog.e(T.UTILS, "SecurityException - missing GET_ACCOUNTS permission"); + return ""; + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java new file mode 100644 index 000000000000..38ed56a7e744 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java @@ -0,0 +1,43 @@ +package org.wordpress.android.util; + + +import android.content.Context; +import android.media.MediaMetadataRetriever; +import android.net.Uri; + +import java.io.File; + +public class VideoUtils { + public static long getVideoDurationMS(Context context, File file) { + if (context == null || file == null) { + AppLog.e(AppLog.T.MEDIA, "context and file can't be null."); + return 0L; + } + return getVideoDurationMS(context, Uri.fromFile(file)); + } + + public static long getVideoDurationMS(Context context, Uri videoUri) { + if (context == null || videoUri == null) { + AppLog.e(AppLog.T.MEDIA, "context and videoUri can't be null."); + return 0L; + } + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + try { + retriever.setDataSource(context, videoUri); + } catch (IllegalArgumentException | SecurityException e) { + AppLog.e(AppLog.T.MEDIA, "Can't read duration of the video.", e); + return 0L; + } catch (RuntimeException e) { + // Ref: https://github.com/wordpress-mobile/WordPress-Android/issues/5431 + AppLog.e(AppLog.T.MEDIA, + "Can't read duration of the video due to a Runtime Exception happened setting the datasource", e); + return 0L; + } + + String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); + if (time == null) { + return 0L; + } + return Long.parseLong(time); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java new file mode 100644 index 000000000000..9f7a11eeb6e9 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java @@ -0,0 +1,81 @@ +package org.wordpress.android.util; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Outline; +import android.os.Build; +import android.view.View; +import android.view.ViewOutlineProvider; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.StyleRes; +import androidx.core.view.ViewCompat; + +import java.util.concurrent.atomic.AtomicInteger; + +public class ViewUtils { + /** + * Generate a value suitable for use in {@link View#setId(int)}. + * This value will not collide with ID values generated at build time by aapt for R.id. + * Uses the native implementation if API 17 or above, otherwise uses a copied implementation. + * + * @return a generated ID value + */ + public static int generateViewId() { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + return View.generateViewId(); + } else { + return copiedGenerateViewId(); + } + } + + private static final AtomicInteger NEXT_GENERATED_ID = new AtomicInteger(1); + + /** + * Copied from {@link View#generateViewId()} + * Generate a value suitable for use in {@link View#setId(int)}. + * This value will not collide with ID values generated at build time by aapt for R.id. + * + * @return a generated ID value + */ + private static int copiedGenerateViewId() { + for (;;) { + final int result = NEXT_GENERATED_ID.get(); + // aapt-generated IDs have the high byte nonzero; clamp to the range under that. + int newValue = result + 1; + if (newValue > 0x00FFFFFF) { + newValue = 1; // Roll over to 1, not 0. + } + if (NEXT_GENERATED_ID.compareAndSet(result, newValue)) { + return result; + } + } + } + + public static void setButtonBackgroundColor(Context context, View button, @StyleRes int styleId, + @AttrRes int colorAttribute) { + TypedArray a = context.obtainStyledAttributes(styleId, new int[]{colorAttribute}); + ColorStateList color = a.getColorStateList(0); + a.recycle(); + ViewCompat.setBackgroundTintList(button, color); + } + + /** + * adds an inset circular shadow outline the passed view (Lollipop+ only) - note that + * the view should have its elevation set prior to calling this + */ + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public static void addCircularShadowOutline(@NonNull View view) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + view.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, view.getWidth(), view.getHeight()); + } + }); + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java new file mode 100644 index 000000000000..6247957819dc --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java @@ -0,0 +1,22 @@ +package org.wordpress.android.util; + +import android.os.Build; +import android.webkit.CookieManager; +import android.webkit.ValueCallback; + +public class WebViewUtils { + public static void clearCookiesAsync() { + clearCookiesAsync(null); + } + + public static void clearCookiesAsync(ValueCallback callback) { + CookieManager cookieManager = CookieManager.getInstance(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + cookieManager.removeAllCookies(callback); + } else { + //noinspection deprecation + cookieManager.removeAllCookie(); + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java new file mode 100644 index 000000000000..1cd723331330 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java @@ -0,0 +1,39 @@ +package org.wordpress.android.util.helpers; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class Debouncer { + private final ScheduledExecutorService mScheduler = Executors.newSingleThreadScheduledExecutor(); + private final ConcurrentHashMap> mDelayedMap = new ConcurrentHashMap<>(); + + /** + * Debounces {@code callable} by {@code delay}, i.e., schedules it to be executed after {@code delay}, + * or cancels its execution if the method is called with the same key within the {@code delay} again. + */ + public void debounce(final Object key, final Runnable runnable, long delay, TimeUnit unit) { + if (mScheduler.isShutdown()) { + return; + } + final Future prev = mDelayedMap.put(key, mScheduler.schedule(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + mDelayedMap.remove(key); + } + } + }, delay, unit)); + if (prev != null) { + prev.cancel(true); + } + } + + public void shutdown() { + mScheduler.shutdownNow(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java new file mode 100644 index 000000000000..914373c8f2e1 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java @@ -0,0 +1,58 @@ +package org.wordpress.android.util.helpers; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.preference.PreferenceManager; +import android.view.View; +import android.widget.ListView; + +public class ListScrollPositionManager { + private int mSelectedPosition; + private int mListViewScrollStateIndex; + private int mListViewScrollStateOffset; + private ListView mListView; + private boolean mSetSelection; + + public ListScrollPositionManager(ListView listView, boolean setSelection) { + mListView = listView; + mSetSelection = setSelection; + } + + public void saveScrollOffset() { + mListViewScrollStateIndex = mListView.getFirstVisiblePosition(); + View view = mListView.getChildAt(0); + mListViewScrollStateOffset = 0; + if (view != null) { + mListViewScrollStateOffset = view.getTop(); + } + if (mSetSelection) { + mSelectedPosition = mListView.getCheckedItemPosition(); + } + } + + public void restoreScrollOffset() { + mListView.setSelectionFromTop(mListViewScrollStateIndex, mListViewScrollStateOffset); + if (mSetSelection) { + mListView.setItemChecked(mSelectedPosition, true); + } + } + + public void saveToPreferences(Context context, String uniqueId) { + saveScrollOffset(); + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + Editor editor = settings.edit(); + editor.putInt("scroll-position-manager-index-" + uniqueId, mListViewScrollStateIndex); + editor.putInt("scroll-position-manager-offset-" + uniqueId, mListViewScrollStateOffset); + editor.putInt("scroll-position-manager-selected-position-" + uniqueId, mSelectedPosition); + editor.apply(); + } + + public void restoreFromPreferences(Context context, String uniqueId) { + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + mListViewScrollStateIndex = settings.getInt("scroll-position-manager-index-" + uniqueId, 0); + mListViewScrollStateOffset = settings.getInt("scroll-position-manager-offset-" + uniqueId, 0); + mSelectedPosition = settings.getInt("scroll-position-manager-selected-position-" + uniqueId, 0); + restoreScrollOffset(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java new file mode 100644 index 000000000000..98d815802ed2 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java @@ -0,0 +1,348 @@ +package org.wordpress.android.util.helpers; + +import android.text.TextUtils; +import android.webkit.MimeTypeMap; + +import org.wordpress.android.util.MapUtils; +import org.wordpress.android.util.StringUtils; +import org.wordpress.android.util.UrlUtils; + +import java.util.Date; +import java.util.Locale; +import java.util.Map; + +public class MediaFile { + protected int mId; + protected long mPostID; + protected String mFilePath = null; // path of the file into disk + protected String mFileName = null; // name of the file into the server + protected String mTitle = null; + protected String mDescription = null; + protected String mCaption = null; + protected int mHorizontalAlignment; // 0 = none, 1 = left, 2 = center, 3 = right + protected boolean mVerticalAligment = false; // false = bottom, true = top + protected int mWidth = 500; + protected int mHeight; + protected String mMimeType = ""; + protected String mVideoPressShortCode = null; + protected boolean mFeatured = false; + protected boolean mIsVideo = false; + protected boolean mFeaturedInPost; + protected String mFileURL = null; // url of the file to download + protected String mThumbnailURL = null; // url of the thumbnail to download + private String mBlogId; + private long mDateCreatedGmt; + private String mUploadState = null; + private String mMediaId; + + private static final String VIDEOPRESS_SHORTCODE_ID = "videopress_shortcode"; + + public MediaFile(String blogId, Map resultMap, boolean isWPCom) { + setBlogId(blogId); + setMediaId(MapUtils.getMapStr(resultMap, "attachment_id")); + setPostID(MapUtils.getMapLong(resultMap, "parent")); + setTitle(MapUtils.getMapStr(resultMap, "title")); + setCaption(MapUtils.getMapStr(resultMap, "caption")); + setDescription(MapUtils.getMapStr(resultMap, "description")); + setVideoPressShortCode(MapUtils.getMapStr(resultMap, VIDEOPRESS_SHORTCODE_ID)); + + // get the file name from the link + String link = MapUtils.getMapStr(resultMap, "link"); + setFileName(new String(link).replaceAll("^.*/([A-Za-z0-9_-]+)\\.\\w+$", "$1")); + + String fileType = new String(link).replaceAll(".*\\.(\\w+)$", "$1").toLowerCase(Locale.ROOT); + String fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileType); + setMimeType(fileMimeType); + + // make the file urls be https://... so that we can get these images with oauth when the blogs are private + // assume no https for images in self-hosted blogs + String fileUrl = MapUtils.getMapStr(resultMap, "link"); + if (isWPCom) { + fileUrl = fileUrl.replace("http:", "https:"); + } + setFileURL(fileUrl); + + String thumbnailURL = MapUtils.getMapStr(resultMap, "thumbnail"); + if (thumbnailURL.startsWith("http")) { + if (isWPCom) { + thumbnailURL = thumbnailURL.replace("http:", "https:"); + } + setThumbnailURL(thumbnailURL); + } + + Date date = MapUtils.getMapDate(resultMap, "date_created_gmt"); + if (date != null) { + setDateCreatedGMT(date.getTime()); + } + + Object meta = resultMap.get("metadata"); + if (meta != null && meta instanceof Map) { + Map metadata = (Map) meta; + setWidth(MapUtils.getMapInt(metadata, "width")); + setHeight(MapUtils.getMapInt(metadata, "height")); + } + } + + public MediaFile() { + // default constructor + } + + public MediaFile(MediaFile mediaFile) { + this.mId = mediaFile.mId; + this.mPostID = mediaFile.mPostID; + this.mFilePath = mediaFile.mFilePath; + this.mFileName = mediaFile.mFileName; + this.mTitle = mediaFile.mTitle; + this.mDescription = mediaFile.mDescription; + this.mCaption = mediaFile.mCaption; + this.mHorizontalAlignment = mediaFile.mHorizontalAlignment; + this.mVerticalAligment = mediaFile.mVerticalAligment; + this.mWidth = mediaFile.mWidth; + this.mHeight = mediaFile.mHeight; + this.mMimeType = mediaFile.mMimeType; + this.mVideoPressShortCode = mediaFile.mVideoPressShortCode; + this.mFeatured = mediaFile.mFeatured; + this.mIsVideo = mediaFile.mIsVideo; + this.mFeaturedInPost = mediaFile.mFeaturedInPost; + this.mFileURL = mediaFile.mFileURL; + this.mThumbnailURL = mediaFile.mThumbnailURL; + this.mBlogId = mediaFile.mBlogId; + this.mDateCreatedGmt = mediaFile.mDateCreatedGmt; + this.mUploadState = mediaFile.mUploadState; + this.mMediaId = mediaFile.mMediaId; + } + + public int getId() { + return mId; + } + + public void setId(int id) { + this.mId = id; + } + + public String getMediaId() { + return mMediaId; + } + + public void setMediaId(String id) { + mMediaId = id; + } + + public boolean isFeatured() { + return mFeatured; + } + + public void setFeatured(boolean featured) { + this.mFeatured = featured; + } + + public long getPostID() { + return mPostID; + } + + public void setPostID(long postID) { + this.mPostID = postID; + } + + public String getFilePath() { + return mFilePath; + } + + public void setFilePath(String filePath) { + this.mFilePath = filePath; + } + + public String getTitle() { + return mTitle; + } + + public void setTitle(String title) { + this.mTitle = title; + } + + public String getCaption() { + return mCaption; + } + + public void setCaption(String caption) { + this.mCaption = caption; + } + + public String getDescription() { + return mDescription; + } + + public void setDescription(String description) { + this.mDescription = description; + } + + public String getFileURL() { + return mFileURL; + } + + public void setFileURL(String fileURL) { + this.mFileURL = fileURL; + } + + public String getThumbnailURL() { + return mThumbnailURL; + } + + public void setThumbnailURL(String thumbnailURL) { + this.mThumbnailURL = thumbnailURL; + } + + public boolean isVerticalAlignmentOnTop() { + return mVerticalAligment; + } + + public void setVerticalAlignmentOnTop(boolean verticalAligment) { + this.mVerticalAligment = verticalAligment; + } + + public int getWidth() { + return mWidth; + } + + public void setWidth(int width) { + this.mWidth = width; + } + + public int getHeight() { + return mHeight; + } + + public void setHeight(int height) { + this.mHeight = height; + } + + public String getFileName() { + return mFileName; + } + + public void setFileName(String fileName) { + this.mFileName = fileName; + } + + public String getMimeType() { + return StringUtils.notNullStr(mMimeType); + } + + public void setMimeType(String type) { + mMimeType = StringUtils.notNullStr(type); + } + + public String getVideoPressShortCode() { + return mVideoPressShortCode; + } + + public void setVideoPressShortCode(String videoPressShortCode) { + this.mVideoPressShortCode = videoPressShortCode; + } + + public int getHorizontalAlignment() { + return mHorizontalAlignment; + } + + public void setHorizontalAlignment(int horizontalAlignment) { + this.mHorizontalAlignment = horizontalAlignment; + } + + public boolean isVideo() { + return mIsVideo; + } + + public void setVideo(boolean isVideo) { + this.mIsVideo = isVideo; + } + + public boolean isFeaturedInPost() { + return mFeaturedInPost; + } + + public void setFeaturedInPost(boolean featuredInPost) { + this.mFeaturedInPost = featuredInPost; + } + + public String getBlogId() { + return mBlogId; + } + + public void setBlogId(String blogId) { + this.mBlogId = blogId; + } + + public void setDateCreatedGMT(long dateCreatedGmt) { + this.mDateCreatedGmt = dateCreatedGmt; + } + + public long getDateCreatedGMT() { + return mDateCreatedGmt; + } + + public void setUploadState(String uploadState) { + this.mUploadState = uploadState; + } + + public String getUploadState() { + return mUploadState; + } + + /** + * Outputs the Html for an image + * If a fullSizeUrl exists, a link will be created to it from the resizedPictureUrl + */ + public String getImageHtmlForUrls(String fullSizeUrl, String resizedPictureURL, boolean shouldAddImageWidthCSS) { + String alignment = ""; + switch (getHorizontalAlignment()) { + case 0: + alignment = "alignnone"; + break; + case 1: + alignment = "alignleft"; + break; + case 2: + alignment = "aligncenter"; + break; + case 3: + alignment = "alignright"; + break; + } + + String alignmentCSS = "class=\"" + alignment + " size-full\" "; + + if (shouldAddImageWidthCSS) { + alignmentCSS += "style=\"max-width: " + getWidth() + "px\" "; + } + + // Check if we uploaded a featured picture that is not added to the Post content (normal case) + if ((fullSizeUrl != null && fullSizeUrl.equalsIgnoreCase("")) + || (resizedPictureURL != null && resizedPictureURL.equalsIgnoreCase(""))) { + return ""; // Not featured in Post. Do not add to the content. + } + + if (fullSizeUrl == null && resizedPictureURL != null) { + fullSizeUrl = resizedPictureURL; + } else if (fullSizeUrl != null && resizedPictureURL == null) { + resizedPictureURL = fullSizeUrl; + } + + String mediaTitle = StringUtils.notNullStr(getTitle()); + + String content = String.format(Locale.US, "\"image\"", + fullSizeUrl, mediaTitle, alignmentCSS, resizedPictureURL); + + if (!TextUtils.isEmpty(getCaption())) { + content = String.format(Locale.US, "[caption id=\"\" align=\"%s\" width=\"%d\"]%s%s[/caption]", + alignment, getWidth(), content, TextUtils.htmlEncode(getCaption())); + } + + return content; + } + + public String getAttachmentPageURL(String siteUrl) { + siteUrl = UrlUtils.makeHttps(siteUrl); + String attachmentPageUrl = UrlUtils.appendUrlParameter(siteUrl, "p", mMediaId); + return attachmentPageUrl; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java new file mode 100644 index 000000000000..ea13f012b699 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java @@ -0,0 +1,86 @@ +package org.wordpress.android.util.helpers; + +import java.io.Serializable; +import java.util.ArrayList; + +/** + * A model representing a Media Gallery. + * A unique id is not used on the website, but only in this app. + * It is used to uniquely determining the instance of the object, as it is + * passed between post and media gallery editor. + */ +public class MediaGallery implements Serializable { + private static final long serialVersionUID = 2359176987182027508L; + + private long mUniqueId; + private boolean mIsRandom; + private String mType; + private int mNumColumns; + private ArrayList mIds; + + public MediaGallery(boolean isRandom, String type, int numColumns, ArrayList ids) { + mIsRandom = isRandom; + mType = type; + mNumColumns = numColumns; + mIds = ids; + mUniqueId = System.currentTimeMillis(); + } + + public MediaGallery() { + mIsRandom = false; + mType = ""; + mNumColumns = 3; + mIds = new ArrayList<>(); + mUniqueId = System.currentTimeMillis(); + } + + public boolean isRandom() { + return mIsRandom; + } + + public void setRandom(boolean isRandom) { + this.mIsRandom = isRandom; + } + + public String getType() { + return mType; + } + + public void setType(String type) { + this.mType = type; + } + + public int getNumColumns() { + return mNumColumns; + } + + public void setNumColumns(int numColumns) { + this.mNumColumns = numColumns; + } + + public ArrayList getIds() { + return mIds; + } + + public String getIdsStr() { + String idsStr = ""; + if (mIds.size() > 0) { + for (Long id : mIds) { + idsStr += id + ","; + } + idsStr = idsStr.substring(0, idsStr.length() - 1); + } + return idsStr; + } + + public void setIds(ArrayList ids) { + this.mIds = ids; + } + + /** + * An id to uniquely identify a media gallery object, so that the same object can be edited in the post editor + */ + public long getUniqueId() { + return mUniqueId; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java new file mode 100644 index 000000000000..588b98141c27 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java @@ -0,0 +1,21 @@ +package org.wordpress.android.util.helpers; + +import android.content.Context; +import android.text.style.ImageSpan; + +public class MediaGalleryImageSpan extends ImageSpan { + private MediaGallery mMediaGallery; + + public MediaGalleryImageSpan(Context context, MediaGallery mediaGallery, int placeHolder) { + super(context, placeHolder); + setMediaGallery(mediaGallery); + } + + public MediaGallery getMediaGallery() { + return mMediaGallery; + } + + public void setMediaGallery(MediaGallery mediaGallery) { + this.mMediaGallery = mediaGallery; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java new file mode 100644 index 000000000000..93021257449d --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java @@ -0,0 +1,39 @@ +package org.wordpress.android.util.helpers; + +import android.os.Bundle; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + + +public class RecyclerViewScrollPositionManager { + private static final String RV_POSITION = "rv_position"; + private static final String RV_OFFSET = "rv_offset"; + private int mRVPosition = 0; + private int mRVOffset = 0; + + public void onSaveInstanceState(Bundle outState, RecyclerView recyclerView) { + // make sure the layout manager is assigned to the RecyclerView + // also take into account this needs to be a LinearLayoutManager, otherwise ClassCastException occurs + outState.putInt(RV_POSITION, + ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition()); + View firstItemView = recyclerView.getChildAt(0); + int offset = (firstItemView == null) ? 0 : (firstItemView.getTop() - recyclerView.getPaddingTop()); + outState.putInt(RV_OFFSET, offset); + } + + public void onRestoreInstanceState(Bundle savedInstanceState) { + mRVPosition = savedInstanceState.getInt(RV_POSITION); + mRVOffset = savedInstanceState.getInt(RV_OFFSET); + } + + public void restoreScrollOffset(RecyclerView recyclerView) { + if (mRVPosition > 0 || mRVOffset > 0) { + ((LinearLayoutManager) recyclerView.getLayoutManager()) + .scrollToPositionWithOffset(mRVPosition, mRVOffset); + } + mRVPosition = 0; + mRVOffset = 0; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java new file mode 100644 index 000000000000..14cc5efef9a8 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java @@ -0,0 +1,110 @@ +package org.wordpress.android.util.helpers; + +import android.content.Context; + +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.core.content.ContextCompat; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener; + +import org.wordpress.android.util.widgets.CustomSwipeRefreshLayout; + +public class SwipeToRefreshHelper implements OnRefreshListener { + private CustomSwipeRefreshLayout mSwipeRefreshLayout; + private RefreshListener mRefreshListener; + private boolean mRefreshing; + + public interface RefreshListener { + void onRefreshStarted(); + } + + /** + * Helps {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by passing the + * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color. + * + * @param context {@link Context} in which this layout is used. + * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents + * of a view via a vertical swipe gesture. + * @param listener {@link RefreshListener} notified when a refresh is triggered + * via the swipe gesture. + * + * @deprecated Use {@link #SwipeToRefreshHelper(CustomSwipeRefreshLayout, RefreshListener, int, int...)} instead. + */ + @Deprecated + public SwipeToRefreshHelper(Context context, CustomSwipeRefreshLayout swipeRefreshLayout, + RefreshListener listener) { + init(swipeRefreshLayout, listener, ContextCompat.getColor(context, android.R.color.white), + android.R.color.holo_blue_dark); + } + + /** + * Helps {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by passing the + * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color(s). + * + * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents + * of a view via a vertical swipe gesture. + * @param listener {@link RefreshListener} notified when a refresh is triggered + * via the swipe gesture. + * @param progressAnimationColors Comma-separated color resource integers used in the progress + * animation. The first color will also be the color of the bar + * that grows in response to a user swipe gesture. + */ + public SwipeToRefreshHelper(CustomSwipeRefreshLayout swipeRefreshLayout, RefreshListener listener, + @ColorInt int backgroundColor, + @ColorRes int... progressAnimationColors) { + init(swipeRefreshLayout, listener, backgroundColor, progressAnimationColors); + } + + /** + * Initializes {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by assigning + * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color(s). + * + * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents + * of a view via a vertical swipe gesture. + * @param listener {@link RefreshListener} notified when a refresh is triggered + * via the swipe gesture. + * @param progressAnimationColors Comma-separated color resource integers used in the progress + * animation. The first color will also be the color of the bar + * that grows in response to a user swipe gesture. + */ + public void init(CustomSwipeRefreshLayout swipeRefreshLayout, RefreshListener listener, + @ColorInt int backgroundColor, + @ColorRes int... progressAnimationColors) { + mRefreshListener = listener; + mSwipeRefreshLayout = swipeRefreshLayout; + mSwipeRefreshLayout.setOnRefreshListener(this); + mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(backgroundColor); + mSwipeRefreshLayout.setColorSchemeResources(progressAnimationColors); + } + + public void setRefreshing(boolean refreshing) { + mRefreshing = refreshing; + // Delayed refresh, it fixes https://code.google.com/p/android/issues/detail?id=77712 + // 50ms seems a good compromise (always worked during tests) and fast enough so user can't notice the delay + if (refreshing) { + mSwipeRefreshLayout.postDelayed(new Runnable() { + @Override + public void run() { + // use mRefreshing so if the refresh takes less than 50ms, loading indicator won't show up. + mSwipeRefreshLayout.setRefreshing(mRefreshing); + } + }, 50); + } else { + mSwipeRefreshLayout.setRefreshing(false); + } + } + + public boolean isRefreshing() { + return mSwipeRefreshLayout.isRefreshing(); + } + + @Override + public void onRefresh() { + mRefreshListener.onRefreshStarted(); + } + + public void setEnabled(boolean enabled) { + mSwipeRefreshLayout.setEnabled(enabled); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java new file mode 100644 index 000000000000..5e0da1f6b2b4 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java @@ -0,0 +1,55 @@ +package org.wordpress.android.util.helpers; + +//See: http://stackoverflow.com/a/11024200 +public class Version implements Comparable { + private String mVersion; + + public final String get() { + return this.mVersion; + } + + public Version(String version) { + if (version == null) { + throw new IllegalArgumentException("Version can not be null"); + } + if (!version.matches("[0-9]+(\\.[0-9]+)*")) { + throw new IllegalArgumentException("Invalid version format"); + } + this.mVersion = version; + } + + @Override public int compareTo(Version that) { + if (that == null) { + return 1; + } + String[] thisParts = this.get().split("\\."); + String[] thatParts = that.get().split("\\."); + int length = Math.max(thisParts.length, thatParts.length); + for (int i = 0; i < length; i++) { + int thisPart = i < thisParts.length + ? Integer.parseInt(thisParts[i]) : 0; + int thatPart = i < thatParts.length + ? Integer.parseInt(thatParts[i]) : 0; + if (thisPart < thatPart) { + return -1; + } + if (thisPart > thatPart) { + return 1; + } + } + return 0; + } + + @Override public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (this.getClass() != that.getClass()) { + return false; + } + return this.compareTo((Version) that) == 0; + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java new file mode 100644 index 000000000000..e8d21791b454 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java @@ -0,0 +1,85 @@ +package org.wordpress.android.util.helpers; + +import android.text.Editable; +import android.text.Html; +import android.text.style.BulletSpan; +import android.text.style.LeadingMarginSpan; + +import org.xml.sax.XMLReader; + +import java.util.ArrayList; +import java.util.List; + +/** + * Handle tags that the Html class doesn't understand + * Tweaked from source at http://stackoverflow.com/questions/4044509/android-how-to-use-the-html-taghandler + */ +public class WPHtmlTagHandler implements Html.TagHandler { + private static final int SPAN_INDENT_WIDTH = 15; + + private int mListItemCount = 0; + private List mListParents = new ArrayList<>(); + + @Override + public void handleTag(final boolean opening, final String tag, Editable output, + final XMLReader xmlReader) { + if (tag != null) { + switch (tag) { + case "WPUL": + if (opening) { + mListParents.add("ul"); + } else { + mListParents.remove("ul"); + } + break; + case "WPOL": + if (opening) { + mListParents.add("ol"); + } else { + mListParents.remove("ol"); + } + break; + case "WPLI": + if (!opening) { + handleListTag(output); + } + break; + case "dd": + if (opening) { + mListParents.add("dd"); + } else { + mListParents.remove("dd"); + } + break; + } + } + } + + private void handleListTag(Editable output) { + int size = mListParents.size(); + if (size > 0 && output != null) { + if ("ul".equals(mListParents.get(size - 1))) { + output.append("\n"); + String[] split = output.toString().split("\n"); + int start = 0; + if (split.length != 1) { + int lastIndex = split.length - 1; + start = output.length() - split[lastIndex].length() - 1; + } + output.setSpan(new BulletSpan(SPAN_INDENT_WIDTH * mListParents.size()), start, output.length(), 0); + } else if ("ol".equals(mListParents.get(size - 1))) { + mListItemCount++; + output.append("\n"); + String[] split = output.toString().split("\n"); + int start = 0; + if (split.length != 1) { + int lastIndex = split.length - 1; + start = output.length() - split[lastIndex].length() - 1; + } + output.insert(start, mListItemCount + ". "); + output.setSpan(new LeadingMarginSpan.Standard(SPAN_INDENT_WIDTH * mListParents.size()), start, + output.length(), 0); + } + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java new file mode 100644 index 000000000000..61ba1b2d4708 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java @@ -0,0 +1,140 @@ +//Add WordPress image fields to ImageSpan object + +package org.wordpress.android.util.helpers; + +import android.content.Context; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.style.ImageSpan; + +public class WPImageSpan extends ImageSpan implements Parcelable { + protected Uri mImageSource = null; + protected boolean mNetworkImageLoaded = false; + protected MediaFile mMediaFile; + protected int mStartPosition, mEndPosition; + + protected WPImageSpan() { + super((Bitmap) null); + } + + public WPImageSpan(Context context, Bitmap b, Uri src) { + super(context, b); + this.mImageSource = src; + mMediaFile = new MediaFile(); + } + + public WPImageSpan(Context context, int resId, Uri src) { + super(context, resId); + this.mImageSource = src; + mMediaFile = new MediaFile(); + } + + public void setPosition(int start, int end) { + mStartPosition = start; + mEndPosition = end; + } + + public int getStartPosition() { + return mStartPosition >= 0 ? mStartPosition : 0; + } + + public int getEndPosition() { + return mEndPosition < getStartPosition() ? getStartPosition() : mEndPosition; + } + + public MediaFile getMediaFile() { + return mMediaFile; + } + + public void setMediaFile(MediaFile mediaFile) { + this.mMediaFile = mediaFile; + } + + public void setImageSource(Uri imageSource) { + this.mImageSource = imageSource; + } + + public Uri getImageSource() { + return mImageSource; + } + + public boolean isNetworkImageLoaded() { + return mNetworkImageLoaded; + } + + public void setNetworkImageLoaded(boolean networkImageLoaded) { + this.mNetworkImageLoaded = networkImageLoaded; + } + + protected void setupFromParcel(Parcel in) { + MediaFile mediaFile = new MediaFile(); + + boolean[] booleans = new boolean[2]; + in.readBooleanArray(booleans); + setNetworkImageLoaded(booleans[0]); + mediaFile.setVideo(booleans[1]); + + setImageSource(Uri.parse(in.readString())); + mediaFile.setMediaId(in.readString()); + mediaFile.setBlogId(in.readString()); + mediaFile.setPostID(in.readLong()); + mediaFile.setCaption(in.readString()); + mediaFile.setDescription(in.readString()); + mediaFile.setTitle(in.readString()); + mediaFile.setMimeType(in.readString()); + mediaFile.setFileName(in.readString()); + mediaFile.setThumbnailURL(in.readString()); + mediaFile.setVideoPressShortCode(in.readString()); + mediaFile.setFileURL(in.readString()); + mediaFile.setFilePath(in.readString()); + mediaFile.setDateCreatedGMT(in.readLong()); + mediaFile.setWidth(in.readInt()); + mediaFile.setHeight(in.readInt()); + setPosition(in.readInt(), in.readInt()); + + setMediaFile(mediaFile); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public WPImageSpan createFromParcel(Parcel in) { + WPImageSpan imageSpan = new WPImageSpan(); + imageSpan.setupFromParcel(in); + return imageSpan; + } + + public WPImageSpan[] newArray(int size) { + return new WPImageSpan[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeBooleanArray(new boolean[]{mNetworkImageLoaded, mMediaFile.isVideo()}); + parcel.writeString(mImageSource.toString()); + parcel.writeString(mMediaFile.getMediaId()); + parcel.writeString(mMediaFile.getBlogId()); + parcel.writeLong(mMediaFile.getPostID()); + parcel.writeString(mMediaFile.getCaption()); + parcel.writeString(mMediaFile.getDescription()); + parcel.writeString(mMediaFile.getTitle()); + parcel.writeString(mMediaFile.getMimeType()); + parcel.writeString(mMediaFile.getFileName()); + parcel.writeString(mMediaFile.getThumbnailURL()); + parcel.writeString(mMediaFile.getVideoPressShortCode()); + parcel.writeString(mMediaFile.getFileURL()); + parcel.writeString(mMediaFile.getFilePath()); + parcel.writeLong(mMediaFile.getDateCreatedGMT()); + parcel.writeInt(mMediaFile.getWidth()); + parcel.writeInt(mMediaFile.getHeight()); + parcel.writeInt(getStartPosition()); + parcel.writeInt(getEndPosition()); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java new file mode 100644 index 000000000000..07d75e6af556 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java @@ -0,0 +1,44 @@ +package org.wordpress.android.util.helpers; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.Layout; +import android.text.style.QuoteSpan; + +/** + * Customzed QuoteSpan for use in SpannableString's + */ +public class WPQuoteSpan extends QuoteSpan { + public static final int STRIPE_COLOR = 0xFF21759B; + private static final int STRIPE_WIDTH = 5; + private static final int GAP_WIDTH = 20; + + public WPQuoteSpan() { + super(STRIPE_COLOR); + } + + @Override + public int getLeadingMargin(boolean first) { + int margin = GAP_WIDTH * 2 + STRIPE_WIDTH; + return margin; + } + + /** + * Draw a nice thick gray bar if Ice Cream Sandwhich or newer. There's a + * bug on older devices that does not respect the increased margin. + */ + @Override + public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, + CharSequence text, int start, int end, boolean first, Layout layout) { + Paint.Style style = p.getStyle(); + int color = p.getColor(); + + p.setStyle(Paint.Style.FILL); + p.setColor(STRIPE_COLOR); + + c.drawRect(GAP_WIDTH + x, top, x + dir * STRIPE_WIDTH, bottom, p); + + p.setStyle(style); + p.setColor(color); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java new file mode 100644 index 000000000000..fbc23d069360 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * 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. + */ + +package org.wordpress.android.util.helpers; + +import android.os.Parcel; +import android.text.style.UnderlineSpan; + +/** + * WPUnderlineSpan is used as an alternative class to UnderlineSpan. UnderlineSpan is used by EditText auto + * correct, so it can get mixed up with our formatting. + */ +public class WPUnderlineSpan extends UnderlineSpan { + public WPUnderlineSpan() { + super(); + } + + public WPUnderlineSpan(Parcel src) { + super(src); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java new file mode 100644 index 000000000000..119677cb00e8 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java @@ -0,0 +1,45 @@ +package org.wordpress.android.util.helpers; + +import android.app.Activity; +import android.text.TextUtils; +import android.view.View; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.widget.ProgressBar; + +public class WPWebChromeClient extends WebChromeClient { + private final ProgressBar mProgressBar; + private final Activity mActivity; + private final boolean mAutoUpdateActivityTitle; + + public WPWebChromeClient(Activity activity, ProgressBar progressBar) { + mActivity = activity; + mProgressBar = progressBar; + mAutoUpdateActivityTitle = true; + } + + public WPWebChromeClient(Activity activity, + ProgressBar progressBar, + boolean autoUpdateActivityTitle) { + mActivity = activity; + mProgressBar = progressBar; + mAutoUpdateActivityTitle = autoUpdateActivityTitle; + } + + public void onProgressChanged(WebView webView, int progress) { + if (mActivity != null + && !mActivity.isFinishing() + && mAutoUpdateActivityTitle + && !TextUtils.isEmpty(webView.getTitle())) { + mActivity.setTitle(webView.getTitle()); + } + if (mProgressBar != null) { + if (progress == 100) { + mProgressBar.setVisibility(View.GONE); + } else { + mProgressBar.setVisibility(View.VISIBLE); + mProgressBar.setProgress(progress); + } + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt new file mode 100644 index 000000000000..732e831c27ac --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt @@ -0,0 +1,22 @@ +package org.wordpress.android.util.helpers.logfile + +/** + * Prunes the Log File Store by retaining only the last `maxLogFileCount` log files. + * + * The file list is created upon instantiation – any files added + * afterwards won't be modified. + * + * @param logFileProvider: An interface where the log files will be retrieved from + * @param maxLogFileCount: The number of log files to retain + */ +class LogFileCleaner(private val logFileProvider: LogFileProviderInterface, private val maxLogFileCount: Int) { + /** + * Immediately removes all log files known to exist by this instance except for + * the most recent `maxLogFileCount` items. + */ + fun clean() { + logFileProvider.getLogFiles() + .dropLast(maxLogFileCount) + .forEach { it.delete() } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt new file mode 100644 index 000000000000..0b59ec372b7b --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt @@ -0,0 +1,42 @@ +package org.wordpress.android.util.helpers.logfile + +import android.content.Context +import java.io.File + +private const val LOG_FILE_DIRECTORY = "logs" + +/** + * A collection of helpers for Log Files. + */ +class LogFileProvider(private val logFileDirectoryPath: String) : LogFileProviderInterface { + /** + * Provides a {@link java.io.File} directory in which to store log files. + * + * If the directory doesn't already exist, it will be created. + */ + override fun getLogFileDirectory(): File { + val logFileDirectory = File(logFileDirectoryPath, LOG_FILE_DIRECTORY) + + if (!logFileDirectory.exists()) { + logFileDirectory.mkdir() + } + + return logFileDirectory + } + + /** + * Provides a list of stored log files, ordered oldest to newest. + */ + override fun getLogFiles(): List { + return getLogFileDirectory() + .listFiles() + .sortedBy { it.lastModified() } + } + + companion object { + @JvmStatic + fun fromContext(context: Context): LogFileProvider { + return LogFileProvider(context.applicationInfo.dataDir) + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt new file mode 100644 index 000000000000..e415ed5b738e --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt @@ -0,0 +1,12 @@ +package org.wordpress.android.util.helpers.logfile + +import java.io.File + +/** + * An interface to retrieve log files + */ +interface LogFileProviderInterface { + fun getLogFiles(): List + + fun getLogFileDirectory(): File +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt new file mode 100644 index 000000000000..41e900f1ec0a --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt @@ -0,0 +1,45 @@ +package org.wordpress.android.util.helpers.logfile + +import org.jetbrains.annotations.TestOnly +import java.io.File +import java.io.FileWriter +import java.util.Date +import org.wordpress.android.util.DateTimeUtils +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +/** + * A class that manages writing to a log file. + * + * This class creates and writes to a log file, and will typically persist for the entire lifecycle + * of its host application. + */ +class LogFileWriter @JvmOverloads constructor( + logFileProvider: LogFileProviderInterface, + fileId: String = DateTimeUtils.iso8601FromDate(Date()) +) { + private val file = File(logFileProvider.getLogFileDirectory(), "$fileId.log") + private val fileWriter: FileWriter = FileWriter(file) + + /** + * A serial executor used to write to the file in a background thread + */ + private val queue: ExecutorService = Executors.newSingleThreadExecutor() + + /** + * A reference to the underlying {@link Java.IO.File} file. + * Should only be used for testing. + */ + @TestOnly + fun getFile(): File = file + + /** + * Writes the provided string to the log file synchronously + */ + fun write(data: String) { + queue.execute { + fileWriter.write(data) + fileWriter.flush() + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java new file mode 100644 index 000000000000..5f2c62e9a0b6 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java @@ -0,0 +1,307 @@ +package org.wordpress.android.util.widgets; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.TextView; + +import androidx.appcompat.widget.AppCompatTextView; +import androidx.core.view.ViewCompat; + +/** + * Text view that auto adjusts text size to fit within the view. + * If the text size equals the minimum text size and still does not + * fit, append with an ellipsis. + * + * See http://stackoverflow.com/a/5535672 + * + */ +public class AutoResizeTextView extends AppCompatTextView { + // Minimum text size for this text view + private static final float MIN_TEXT_SIZE = 20; + + // Interface for resize notifications + public interface OnTextResizeListener { + void onTextResize(TextView textView, float oldSize, float newSize); + } + + // Our ellipse string - Unicode Character 'HORIZONTAL ELLIPSIS' + private static final String M_ELLIPSIS = "\u2026"; + + // Registered resize listener + private OnTextResizeListener mTextResizeListener; + + // Flag for text and/or size changes to force a resize + private boolean mNeedsResize = false; + + // Text size that is set from code. This acts as a starting point for resizing + private float mTextSize; + + // Temporary upper bounds on the starting text size + private float mMaxTextSize = 0; + + // Lower bounds for text size + private float mMinTextSize = MIN_TEXT_SIZE; + + // Text view line spacing multiplier + private float mSpacingMult = 1.0f; + + // Text view additional line spacing + private float mSpacingAdd = 0.0f; + + // Add ellipsis to text that overflows at the smallest text size + private boolean mAddEllipsis = true; + + // Default constructor override + public AutoResizeTextView(Context context) { + this(context, null); + } + + // Default constructor when inflating from XML file + public AutoResizeTextView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + // Default constructor override + public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mTextSize = getTextSize(); + } + + /** + * When text changes, set the force resize flag to true and reset the text size. + */ + @Override + protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) { + mNeedsResize = true; + // Since this view may be reused, it is good to reset the text size + resetTextSize(); + } + + /** + * If the text view size changed, set the force resize flag to true + */ + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + if (w != oldw || h != oldh) { + mNeedsResize = true; + } + } + + /** + * Register listener to receive resize notifications + * @param listener + */ + public void setOnResizeListener(OnTextResizeListener listener) { + mTextResizeListener = listener; + } + + /** + * Override the set text size to update our internal reference values + */ + @Override + public void setTextSize(float size) { + super.setTextSize(size); + mTextSize = getTextSize(); + } + + /** + * Override the set text size to update our internal reference values + */ + @Override + public void setTextSize(int unit, float size) { + super.setTextSize(unit, size); + mTextSize = getTextSize(); + } + + /** + * Override the set line spacing to update our internal reference values + */ + @Override + public void setLineSpacing(float add, float mult) { + super.setLineSpacing(add, mult); + mSpacingMult = mult; + mSpacingAdd = add; + } + + /** + * Set the upper text size limit and invalidate the view + * @param maxTextSize + */ + public void setMaxTextSize(float maxTextSize) { + mMaxTextSize = maxTextSize; + requestLayout(); + invalidate(); + } + + /** + * Return upper text size limit + * @return + */ + public float getMaxTextSize() { + return mMaxTextSize; + } + + /** + * Set the lower text size limit and invalidate the view + * @param minTextSize + */ + public void setMinTextSize(float minTextSize) { + mMinTextSize = minTextSize; + requestLayout(); + invalidate(); + } + + /** + * Return lower text size limit + * @return + */ + public float getMinTextSize() { + return mMinTextSize; + } + + /** + * Set flag to add ellipsis to text that overflows at the smallest text size + * @param addEllipsis + */ + public void setAddEllipsis(boolean addEllipsis) { + mAddEllipsis = addEllipsis; + } + + /** + * Return flag to add ellipsis to text that overflows at the smallest text size + * @return + */ + public boolean getAddEllipsis() { + return mAddEllipsis; + } + + /** + * Reset the text to the original size + */ + private void resetTextSize() { + if (mTextSize > 0) { + super.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); + mMaxTextSize = mTextSize; + } + } + + /** + * Resize text after measuring + */ + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (changed || mNeedsResize) { + int widthLimit = (right - left) - getCompoundPaddingLeft() - getCompoundPaddingRight(); + int heightLimit = (bottom - top) - getCompoundPaddingBottom() - getCompoundPaddingTop(); + resizeText(widthLimit, heightLimit); + } + super.onLayout(changed, left, top, right, bottom); + } + + /** + * Resize the text size with default width and height + */ + public void resizeText() { + int heightLimit = getHeight() - getPaddingBottom() - getPaddingTop(); + int widthLimit = getWidth() - ViewCompat.getPaddingStart(this) - ViewCompat.getPaddingStart(this); + resizeText(widthLimit, heightLimit); + } + + /** + * Resize the text size with specified width and height + * @param width + * @param height + */ + @SuppressLint("SetTextI18n") public void resizeText(int width, int height) { + CharSequence text = getText(); + // Do not resize if the view does not have dimensions or there is no text + if (text == null || text.length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { + return; + } + + // Get the text view's paint object + TextPaint textPaint = getPaint(); + + // Store the current text size + float oldTextSize = textPaint.getTextSize(); + // If there is a max text size set, use the lesser of that and the default text size + float targetTextSize = mMaxTextSize > 0 ? Math.min(mTextSize, mMaxTextSize) : mTextSize; + + // Get the required text height + int textHeight = getTextHeight(text, textPaint, width, targetTextSize); + + // Until we either fit within our text view or we had reached our min text size, incrementally try smaller sizes + while (textHeight > height && targetTextSize > mMinTextSize) { + targetTextSize = Math.max(targetTextSize - 2, mMinTextSize); + textHeight = getTextHeight(text, textPaint, width, targetTextSize); + } + + // If we had reached our minimum text size and still don't fit, append an ellipsis + if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { + // Draw using a static layout + // modified: use a copy of TextPaint for measuring + TextPaint paint = new TextPaint(textPaint); + // Draw using a static layout + StaticLayout layout = new StaticLayout(text, paint, width, Layout.Alignment.ALIGN_NORMAL, + mSpacingMult, mSpacingAdd, false); + // Check that we have a least one line of rendered text + if (layout.getLineCount() > 0) { + // Since the line at the specific vertical position would be cut off, + // we must trim up to the previous line + int lastLine = layout.getLineForVertical(height) - 1; + // If the text would not even fit on a single line, clear it + if (lastLine < 0) { + setText(""); + } else { + // Otherwise, trim to the previous line and add an ellipsis + int start = layout.getLineStart(lastLine); + int end = layout.getLineEnd(lastLine); + float lineWidth = layout.getLineWidth(lastLine); + float ellipseWidth = paint.measureText(M_ELLIPSIS); + + // Trim characters off until we have enough room to draw the ellipsis + while (width < lineWidth + ellipseWidth) { + lineWidth = paint.measureText(text.subSequence(start, --end + 1).toString()); + } + if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) { + setText(M_ELLIPSIS + text.subSequence(0, end)); + } else { + setText(text.subSequence(0, end) + M_ELLIPSIS); + } + } + } + } + + // Some devices try to auto adjust line spacing, so force default line spacing + // and invalidate the layout as a side effect + setTextSize(TypedValue.COMPLEX_UNIT_PX, targetTextSize); + setLineSpacing(mSpacingAdd, mSpacingMult); + + // Notify the listener if registered + if (mTextResizeListener != null) { + mTextResizeListener.onTextResize(this, oldTextSize, targetTextSize); + } + + // Reset force resize flag + mNeedsResize = false; + } + + // Set the text size of the text paint object and use a static layout to render text off screen before measuring + private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) { + // modified: make a copy of the original TextPaint object for measuring + // (apparently the object gets modified while measuring, see also the + // docs for TextView.getPaint() (which states to access it read-only) + TextPaint paintCopy = new TextPaint(paint); + // Update the text paint object + paintCopy.setTextSize(textSize); + // Measure using a static layout + StaticLayout layout = new StaticLayout(source, paintCopy, width, Layout.Alignment.ALIGN_NORMAL, + mSpacingMult, mSpacingAdd, true); + return layout.getHeight(); + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java new file mode 100644 index 000000000000..91c72674d487 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java @@ -0,0 +1,34 @@ +package org.wordpress.android.util.widgets; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.AppLog.T; + +public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { + public CustomSwipeRefreshLayout(Context context) { + super(context); + } + + public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + try { + return super.onTouchEvent(event); + } catch (IllegalArgumentException e) { + // Fix for https://github.com/wordpress-mobile/WordPress-Android/issues/2373 + // Catch IllegalArgumentException which can be fired by the underlying SwipeRefreshLayout.onTouchEvent() + // method. + // When android support-v4 fixes it, we'll have to remove that custom layout completely. + AppLog.e(T.UTILS, e); + return true; + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java new file mode 100644 index 000000000000..2c3951c61ec5 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java @@ -0,0 +1,49 @@ +package org.wordpress.android.util.widgets; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.EditText; + +import com.google.android.material.textfield.TextInputLayout; + +import org.wordpress.android.util.R; + +/** + * Custom TextInputLayout to provide a usable getBaseline() and error view padding + */ +public class WPTextInputLayout extends TextInputLayout { + public WPTextInputLayout(Context context) { + super(context); + } + + public WPTextInputLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public WPTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public int getBaseline() { + EditText editText = getEditText(); + return editText != null ? editText.getBaseline() - editText.getPaddingBottom() + + getResources().getDimensionPixelSize(R.dimen.textinputlayout_baseline_correction) + : 0; + } + + @Override + public void setErrorEnabled(boolean enabled) { + super.setErrorEnabled(enabled); + + // remove hardcoded side padding of the error view + if (enabled) { + View errorView = findViewById(com.google.android.material.R.id.textinput_error); + if (errorView != null && errorView.getParent() != null) { + ((View) errorView.getParent()) + .setPadding(0, errorView.getPaddingTop(), 0, errorView.getPaddingBottom()); + } + } + } +} diff --git a/libs/utils/WordPressUtils/src/main/res/values/dimens.xml b/libs/utils/WordPressUtils/src/main/res/values/dimens.xml new file mode 100644 index 000000000000..4f3fdecd3158 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/res/values/dimens.xml @@ -0,0 +1,6 @@ + + + 2dp + 4.3dp + -8.6dp + diff --git a/libs/utils/WordPressUtils/src/main/res/values/strings.xml b/libs/utils/WordPressUtils/src/main/res/values/strings.xml new file mode 100644 index 000000000000..34d25dada509 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + + There is no network available + Now + diff --git a/libs/utils/WordPressUtils/src/main/res/values/tags.xml b/libs/utils/WordPressUtils/src/main/res/values/tags.xml new file mode 100644 index 000000000000..796e3fab2be0 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/res/values/tags.xml @@ -0,0 +1,3 @@ + + + diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java new file mode 100644 index 000000000000..a6ae733607e5 --- /dev/null +++ b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java @@ -0,0 +1,46 @@ +package org.wordpress.android.util; + +import org.junit.Ignore; +import org.junit.Test; + +import java.util.Date; +import java.util.TimeZone; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DateTimeUtilsTest { + private final long mDefaultDate = 1564484058163L; // it's Tue Jul 30 2019 10:54:18 in UTC + + @Test + public void testIso8601UTCFromDate() { + // Arrange + TimeZone.setDefault(TimeZone.getTimeZone("GMT+2:00")); + Date date = new Date(mDefaultDate); + String expected = "2019-07-30T10:54:18+00:00"; + + // Act + String actual = DateTimeUtils.iso8601UTCFromDate(date); + + // Assert + assertThat(actual).isEqualTo(expected); + } + + @Test + @Ignore(value = "This test is failing because `DateTimeUtils.localDateToUTC` doesn't work as expected. I've " + + "marked it as deprecated and this tests serves just as a documentation.") + public void testLocalDateToUTC() { + // Arrange + TimeZone.setDefault(TimeZone.getTimeZone("GMT+2:00")); + Date date = new Date(mDefaultDate); + // this succeeds + assertThat(DateTimeUtils.iso8601FromDate(date)).isEqualTo("2019-07-30T12:54:18+0200"); + + // Act + String actual = DateTimeUtils.iso8601FromDate(DateTimeUtils.localDateToUTC(date)); + + // Assert + + // fails because `localDateToUTC` doesn't work as expected. See DateTimeUtils.localDateToUTC for more info. + assertThat(actual).isEqualTo("2019-07-30T10:54:18+00:00"); + } +} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt new file mode 100644 index 000000000000..71789bd844dc --- /dev/null +++ b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt @@ -0,0 +1,75 @@ +package org.wordpress.android.util + +import android.content.Context +import android.os.Build +import androidx.test.core.app.ApplicationProvider +import java.io.File +import java.io.FileReader +import kotlin.random.Random +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.wordpress.android.util.helpers.logfile.LogFileCleaner +import org.wordpress.android.util.helpers.logfile.LogFileProvider + +/** + * The number of test files to create for each test run + */ +private const val MAX_FILES = 10 + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [Build.VERSION_CODES.O_MR1]) +class LogFileCleanerTest { + private lateinit var logFileProvider: LogFileProvider + + @Before + fun setup() { + val context: Context = ApplicationProvider.getApplicationContext() + logFileProvider = LogFileProvider.fromContext(context) + + repeat(MAX_FILES) { + val file = File(logFileProvider.getLogFileDirectory(), "$it.log") + file.writeText("$it") + file.setLastModified(it * 10_000L) + } + + assert(logFileProvider.getLogFileDirectory().listFiles().count() == MAX_FILES) + } + + @After + fun tearDown() { + // Delete the test directory after each test + logFileProvider.getLogFileDirectory().deleteRecursively() + } + + @Test + fun testThatCleanerPreservesMostRecentlyCreatedFiles() { + val maxLogFileCount = Random.nextInt(MAX_FILES) + LogFileCleaner(logFileProvider, maxLogFileCount).clean() + + // Strings are easier to assert against than arrays + val remainingFileIds = logFileProvider.getLogFiles().joinToString(",") { + FileReader(it).readText() + } + + val expectedValue = (MAX_FILES - 1 downTo 0).take(maxLogFileCount).reversed().joinToString(",") + assertEquals(expectedValue, remainingFileIds) + } + + @Test + fun testThatCleanerPreservesCorrectNumberOfFiles() { + val numberOfFiles = Random.nextInt(MAX_FILES) + LogFileCleaner(logFileProvider, numberOfFiles).clean() + assertEquals(numberOfFiles, logFileProvider.getLogFileDirectory().listFiles().count()) + } + + @Test + fun testThatCleanerErasesAllFilesIfGivenZero() { + LogFileCleaner(logFileProvider, 0).clean() + assert(logFileProvider.getLogFileDirectory().listFiles().isEmpty()) + } +} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt new file mode 100644 index 000000000000..e4921c21e750 --- /dev/null +++ b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt @@ -0,0 +1,64 @@ +package org.wordpress.android.util + +import android.content.Context +import android.os.Build +import androidx.test.core.app.ApplicationProvider +import java.io.File +import java.util.UUID +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.wordpress.android.util.helpers.logfile.LogFileProvider + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [Build.VERSION_CODES.O_MR1]) +class LogFileHelpersTest { + private lateinit var testProvider: LogFileProvider + + @Before + fun setup() { + val context: Context = ApplicationProvider.getApplicationContext() + testProvider = LogFileProvider.fromContext(context) + } + + @After + fun tearDown() { + // Delete the test directory after each test + testProvider.getLogFileDirectory().deleteRecursively() + } + + @Test + fun testThatLogFileDirectoryIsCreatedIfNotExists() { + val directory = testProvider.getLogFileDirectory() + assert(directory.exists()) + } + + @Test + fun testThatLogFilesListsAllFiles() { + val directory = testProvider.getLogFileDirectory() + File(directory, UUID.randomUUID().toString()).createNewFile() + Assert.assertEquals(testProvider.getLogFiles().count(), 1) + } + + @Test + fun testThatLogFilesSortsFilesWithMostRecentFirst() { + val directory = testProvider.getLogFileDirectory() + + listOf(1_000L, 1_000_000L).shuffled().forEach { modifiedDate -> + File(directory, UUID.randomUUID().toString()).also { file -> + // Use timestamps in increments of 1000 to avoid issues from the File System's date precision + val date = modifiedDate * 1000 + file.createNewFile() + file.setLastModified(date) + assert(file.lastModified() == date) + } + } + + val files = testProvider.getLogFiles() + assert(files.first().lastModified() < files.last().lastModified()) + } +} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt new file mode 100644 index 000000000000..998a29398783 --- /dev/null +++ b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt @@ -0,0 +1,53 @@ +package org.wordpress.android.util + +import android.content.Context +import android.os.Build +import androidx.test.core.app.ApplicationProvider +import java.io.FileReader +import java.util.UUID +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.wordpress.android.util.helpers.logfile.LogFileProvider +import org.wordpress.android.util.helpers.logfile.LogFileWriter + +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [Build.VERSION_CODES.O_MR1]) +class LogFileWriterTest { + private lateinit var testProvider: LogFileProvider + + @Before + fun setup() { + val context: Context = ApplicationProvider.getApplicationContext() + testProvider = LogFileProvider.fromContext(context) + } + + @After + fun tearDown() { + // Delete the test directory after each test + testProvider.getLogFileDirectory().deleteRecursively() + } + + @Test + fun testThatFileWriterCreatesLogFile() { + val writer = LogFileWriter(testProvider) + assert(writer.getFile().exists()) + } + + @Test + fun testThatContentsAreWrittenToFile() { + val randomString = UUID.randomUUID().toString() + val writer = LogFileWriter(testProvider) + writer.write(randomString) + + // Allow the async process to persist the file changes + Thread.sleep(1000) + + val contents = FileReader(writer.getFile()).readText() + assertEquals(randomString, contents) + } +} diff --git a/libs/utils/build.gradle b/libs/utils/build.gradle new file mode 100644 index 000000000000..ebb5278a193c --- /dev/null +++ b/libs/utils/build.gradle @@ -0,0 +1,41 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.automattic.android:fetchstyle:1.1' + } +} + +apply plugin: 'com.automattic.android.fetchstyle' + +allprojects { + apply plugin: 'checkstyle' + + repositories { + jcenter() + maven { + url "https://maven.google.com" + } + } + + if (tasks.findByPath('checkstyle') == null) { + tasks.create(name: 'checkstyle', type: Checkstyle) { + source 'src' + + classpath = files() + } + + checkstyle { + toolVersion = '8.3' + configFile file("${project.rootDir}/config/checkstyle.xml") + } + } + + // Suppress false Javadoc lint errors preventing Bintray release + // See https://stackoverflow.com/questions/34828426/disable-javadoc-check-for-bintray-upload + tasks.withType(Javadoc) { + options.addBooleanOption('Xdoclint:none', true) + } +} diff --git a/libs/utils/config/checkstyle.xml b/libs/utils/config/checkstyle.xml new file mode 100644 index 000000000000..2ebaaac1412c --- /dev/null +++ b/libs/utils/config/checkstyle.xml @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/utils/settings.gradle b/libs/utils/settings.gradle new file mode 100644 index 000000000000..3519745edd00 --- /dev/null +++ b/libs/utils/settings.gradle @@ -0,0 +1 @@ +include ':WordPressUtils' \ No newline at end of file From f19af8bdba0f16a980c8179ab338a18aec377e01 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 25 Sep 2020 18:37:51 -0400 Subject: [PATCH 012/144] Updates composite build approach for utils --- WordPress/build.gradle | 13 +++---------- build.gradle | 1 - included-builds-example.txt | 14 -------------- local-builds.gradle-example | 1 + settings.gradle | 19 ++++++++++--------- 5 files changed, 14 insertions(+), 34 deletions(-) delete mode 100644 included-builds-example.txt diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 55888a11dbee..796047a335e1 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -308,16 +308,9 @@ dependencies { implementation ('com.github.indexos.media-for-mobile:android:43a9026f0973a2f0a74fa813132f6a16f7499c3a') - - if (buildUtilsFromLocalDirectory) { - implementation 'org.wordpress:WordPressUtils' - testImplementation 'org.wordpress:WordPressUtils' - debugImplementation 'org.wordpress:WordPressUtils' - } else { - implementation "org.wordpress:utils:$wordPressUtilsVersion" - testImplementation "org.wordpress:utils:$wordPressUtilsVersion" - debugImplementation "org.wordpress:utils:$wordPressUtilsVersion" - } + implementation "$gradle.ext.wputilsBinaryPath:$wordPressUtilsVersion" + testImplementation "$gradle.ext.wputilsBinaryPath:$wordPressUtilsVersion" + debugImplementation "$gradle.ext.wputilsBinaryPath:$wordPressUtilsVersion" implementation (project(path:':libs:networking:WordPressNetworking')) { exclude group: "com.android.volley" exclude group: 'org.wordpress', module: 'utils' diff --git a/build.gradle b/build.gradle index a86f793357d6..5a8259719370 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,6 @@ buildscript { ext.androidx_work_version = "2.0.1" ext.buildGutenbergMobileJSBundle = 1 ext.wordPressUtilsVersion = '1.30' - ext.buildUtilsFromLocalDirectory = false repositories { google() diff --git a/included-builds-example.txt b/included-builds-example.txt deleted file mode 100644 index 0ca9dc958788..000000000000 --- a/included-builds-example.txt +++ /dev/null @@ -1,14 +0,0 @@ -# This file is completely optional, but its usage makes it easier to work with libraries -# in local path. This example file needs to be copied as `included-builds.txt` to take -# effect. -# -# `settings.gradle` will call `includeBuild` on each relative path in this file. -# -# `includeBuild` call alone will not make a project a dependency of WordPress-Android. -# In order for a project to be a dependency, its module needs to be added in the -# `dependencies` section of the `build.gradle` file just like any other dependency. -# -# Android Studio will show each included project even if it's not added as a dependency. -# However, if an included build is not added as a dependency, it'll have no impact on -# the builds. -../WordPress-Utils-Android diff --git a/local-builds.gradle-example b/local-builds.gradle-example index 76fa93da077d..9c8ebd6375f5 100644 --- a/local-builds.gradle-example +++ b/local-builds.gradle-example @@ -15,4 +15,5 @@ binary build if you're not working on a specific library. */ ext { localFluxCPath = "../WordPress-FluxC-Android" + localWPUtilsPath = "../WordPress-Utils-Android" } diff --git a/settings.gradle b/settings.gradle index f6b3eb08b6a5..6417b09c1b95 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,15 +18,6 @@ include ':libs:login:WordPressLoginFlow' include ':libs:WordPressProcessors' include ':libs:WordPressAnnotations' -def includedBuilds = new File('./included-builds.txt') -if (includedBuilds.exists()) { - includedBuilds.eachLine { line -> - if (!line.isEmpty() && !line.startsWith("#")) { - includeBuild(line) - } - } -} - include ':WordPressMocks' project(':WordPressMocks').projectDir = new File(rootProject.projectDir, properties.getOrDefault('wp.wordpress_mocks_path', 'libs/mocks') + '/WordPressMocks') @@ -64,6 +55,7 @@ if (properties.getOrDefault('wp.BUILD_GUTENBERG_FROM_SOURCE', false).toBoolean() } gradle.ext.fluxCBinaryPath = "com.github.wordpress-mobile.WordPress-FluxC-Android" +gradle.ext.wputilsBinaryPath = "org.wordpress:utils" def localBuilds = new File('local-builds.gradle') if (localBuilds.exists()) { @@ -88,5 +80,14 @@ if (localBuilds.exists()) { } } } + + if (ext.has("localWPUtilsPath")) { + includeBuild(ext.localWPUtilsPath) { + dependencySubstitution { + println "Substituting wputils with the local build" + substitute module("$gradle.ext.wputilsBinaryPath") with project(':WordPressUtils') + } + } + } } From aca7a1edf029ee7b54e527ba48068c2789bf6388 Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Tue, 24 Nov 2020 10:58:32 +0100 Subject: [PATCH 013/144] Update WPUtils version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b02697bfb377..48a0f71f43e3 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { ext.kotlin_ktx_version = '1.2.0' ext.androidx_work_version = "2.0.1" ext.buildGutenbergMobileJSBundle = 1 - ext.wordPressUtilsVersion = '1.30' + ext.wordPressUtilsVersion = '1.30.1-beta.1' repositories { google() From e7e37018406307e2da1d18a238ee03575ee4cf12 Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Tue, 24 Nov 2020 12:32:30 +0100 Subject: [PATCH 014/144] Remove WPUtils subtree --- libs/utils/.circleci/config.yml | 59 -- libs/utils/.editorconfig | 2 - libs/utils/.gitignore | 57 -- libs/utils/.idea/checkstyle-idea.xml | 18 - libs/utils/.idea/codeStyleSettings.xml | 274 ------ libs/utils/.idea/codeStyles/Project.xml | 281 ------ .../.idea/codeStyles/codeStyleConfig.xml | 5 - libs/utils/.idea/compiler.xml | 22 - .../.idea/copyright/profiles_settings.xml | 3 - libs/utils/.idea/encodings.xml | 6 - libs/utils/.idea/externalDependencies.xml | 6 - .../inspectionProfiles/Project_Default.xml | 16 - .../inspectionProfiles/profiles_settings.xml | 7 - libs/utils/.idea/vcs.xml | 6 - libs/utils/README.md | 41 - libs/utils/WordPressUtils/README.md | 1 - libs/utils/WordPressUtils/build.gradle | 122 --- .../WordPressUtils/gradle.properties-example | 7 - .../android/util/ImageUtilsTest.java | 89 -- .../wordpress/android/util/JSONUtilsTest.java | 37 - .../android/util/PhotonUtilsTest.java | 106 --- .../android/util/ShortcodeUtilsTest.java | 32 - .../wordpress/android/util/UrlUtilsTest.java | 131 --- .../src/main/AndroidManifest.xml | 6 - .../util/AccessibilityEventListener.java | 7 - .../android/util/AccessibilityUtils.java | 108 --- .../wordpress/android/util/ActivityUtils.java | 55 -- .../wordpress/android/util/AlertUtils.java | 100 -- .../org/wordpress/android/util/AppLog.java | 382 -------- .../android/util/AutoForeground.java | 223 ----- .../util/AutoForegroundNotification.java | 79 -- .../wordpress/android/util/DateTimeUtils.java | 251 ----- .../wordpress/android/util/DeviceUtils.java | 179 ---- .../wordpress/android/util/DisplayUtils.java | 103 -- .../wordpress/android/util/EditTextUtils.java | 88 -- .../android/util/EmoticonsUtils.java | 110 --- .../org/wordpress/android/util/FileUtils.java | 61 -- .../wordpress/android/util/FormatUtils.java | 79 -- .../wordpress/android/util/GeocoderUtils.java | 115 --- .../wordpress/android/util/GravatarUtils.java | 86 -- .../org/wordpress/android/util/HtmlUtils.java | 163 ---- .../wordpress/android/util/ImageUtils.java | 898 ------------------ .../org/wordpress/android/util/JSONUtils.java | 262 ----- .../wordpress/android/util/LanguageUtils.java | 72 -- .../org/wordpress/android/util/ListUtils.java | 47 - .../org/wordpress/android/util/MapUtils.java | 115 --- .../wordpress/android/util/MediaUtils.java | 571 ----------- .../wordpress/android/util/NetworkUtils.java | 100 -- .../wordpress/android/util/PackageUtils.java | 45 - .../android/util/PermissionUtils.java | 104 -- .../wordpress/android/util/PhotonUtils.java | 143 --- .../android/util/ProfilingUtils.java | 87 -- .../wordpress/android/util/ServiceUtils.java | 16 - .../android/util/ShortcodeUtils.java | 31 - .../org/wordpress/android/util/SqlUtils.java | 146 --- .../wordpress/android/util/StringUtils.java | 363 ------- .../android/util/SystemServiceFactory.java | 14 - .../util/SystemServiceFactoryAbstract.java | 7 - .../util/SystemServiceFactoryDefault.java | 9 - .../wordpress/android/util/ToastUtils.java | 53 -- .../org/wordpress/android/util/UrlUtils.java | 318 ------- .../android/util/UserEmailUtils.java | 39 - .../wordpress/android/util/VideoUtils.java | 43 - .../org/wordpress/android/util/ViewUtils.java | 81 -- .../wordpress/android/util/WebViewUtils.java | 22 - .../android/util/helpers/Debouncer.java | 39 - .../helpers/ListScrollPositionManager.java | 58 -- .../android/util/helpers/MediaFile.java | 348 ------- .../android/util/helpers/MediaGallery.java | 86 -- .../util/helpers/MediaGalleryImageSpan.java | 21 - .../RecyclerViewScrollPositionManager.java | 39 - .../util/helpers/SwipeToRefreshHelper.java | 110 --- .../android/util/helpers/Version.java | 55 -- .../util/helpers/WPHtmlTagHandler.java | 85 -- .../android/util/helpers/WPImageSpan.java | 140 --- .../android/util/helpers/WPQuoteSpan.java | 44 - .../android/util/helpers/WPUnderlineSpan.java | 34 - .../util/helpers/WPWebChromeClient.java | 45 - .../util/helpers/logfile/LogFileCleaner.kt | 22 - .../util/helpers/logfile/LogFileProvider.kt | 42 - .../logfile/LogFileProviderInterface.kt | 12 - .../util/helpers/logfile/LogFileWriter.kt | 45 - .../util/widgets/AutoResizeTextView.java | 307 ------ .../widgets/CustomSwipeRefreshLayout.java | 34 - .../util/widgets/WPTextInputLayout.java | 49 - .../src/main/res/values/dimens.xml | 6 - .../src/main/res/values/strings.xml | 5 - .../src/main/res/values/tags.xml | 3 - .../android/util/DateTimeUtilsTest.java | 46 - .../android/util/LogFileCleanerTest.kt | 75 -- .../android/util/LogFileHelpersTest.kt | 64 -- .../android/util/LogFileWriterTest.kt | 53 -- libs/utils/build.gradle | 41 - libs/utils/config/checkstyle.xml | 276 ------ libs/utils/gradle.properties-example | 1 - libs/utils/gradle/wrapper/gradle-wrapper.jar | Bin 58695 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - libs/utils/gradlew | 183 ---- libs/utils/gradlew.bat | 103 -- libs/utils/settings.gradle | 1 - 100 files changed, 9586 deletions(-) delete mode 100644 libs/utils/.circleci/config.yml delete mode 100644 libs/utils/.editorconfig delete mode 100644 libs/utils/.gitignore delete mode 100644 libs/utils/.idea/checkstyle-idea.xml delete mode 100644 libs/utils/.idea/codeStyleSettings.xml delete mode 100644 libs/utils/.idea/codeStyles/Project.xml delete mode 100644 libs/utils/.idea/codeStyles/codeStyleConfig.xml delete mode 100644 libs/utils/.idea/compiler.xml delete mode 100644 libs/utils/.idea/copyright/profiles_settings.xml delete mode 100644 libs/utils/.idea/encodings.xml delete mode 100644 libs/utils/.idea/externalDependencies.xml delete mode 100644 libs/utils/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 libs/utils/.idea/inspectionProfiles/profiles_settings.xml delete mode 100644 libs/utils/.idea/vcs.xml delete mode 100644 libs/utils/README.md delete mode 100644 libs/utils/WordPressUtils/README.md delete mode 100644 libs/utils/WordPressUtils/build.gradle delete mode 100644 libs/utils/WordPressUtils/gradle.properties-example delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/main/AndroidManifest.xml delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java delete mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java delete mode 100644 libs/utils/WordPressUtils/src/main/res/values/dimens.xml delete mode 100644 libs/utils/WordPressUtils/src/main/res/values/strings.xml delete mode 100644 libs/utils/WordPressUtils/src/main/res/values/tags.xml delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt delete mode 100644 libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt delete mode 100644 libs/utils/build.gradle delete mode 100644 libs/utils/config/checkstyle.xml delete mode 100644 libs/utils/gradle.properties-example delete mode 100644 libs/utils/gradle/wrapper/gradle-wrapper.jar delete mode 100644 libs/utils/gradle/wrapper/gradle-wrapper.properties delete mode 100755 libs/utils/gradlew delete mode 100644 libs/utils/gradlew.bat delete mode 100644 libs/utils/settings.gradle diff --git a/libs/utils/.circleci/config.yml b/libs/utils/.circleci/config.yml deleted file mode 100644 index b863a75292c5..000000000000 --- a/libs/utils/.circleci/config.yml +++ /dev/null @@ -1,59 +0,0 @@ -version: 2.1 - -orbs: - android: wordpress-mobile/android@0.0.22 - -commands: - copy-gradle-properties: - steps: - - run: - name: Setup gradle.properties - command: cp gradle.properties-example gradle.properties - -jobs: - Lint: - executor: - name: android/default - api-version: "27" - steps: - - checkout - - copy-gradle-properties - - android/restore-gradle-cache - - run: - name: Lint & Checkstyle - command: ./gradlew --stacktrace lint checkstyle - - android/save-gradle-cache - - android/save-lint-results - Test: - executor: - name: android/default - api-version: "27" - steps: - - checkout - - copy-gradle-properties - - android/restore-gradle-cache - - run: - name: Test - command: ./gradlew --stacktrace test - - android/save-gradle-cache - Build: - executor: - name: android/default - api-version: "27" - steps: - - checkout - - copy-gradle-properties - - android/restore-gradle-cache - - run: - name: Build - command: ./gradlew --stacktrace assembleDebug assembleRelease - - android/save-gradle-cache - -workflows: - WordPress-Utils-Android: - jobs: - - Lint - - Test - - Build: - requires: - - Test diff --git a/libs/utils/.editorconfig b/libs/utils/.editorconfig deleted file mode 100644 index 590d68372e0d..000000000000 --- a/libs/utils/.editorconfig +++ /dev/null @@ -1,2 +0,0 @@ -[*.{kt,kts}] -max_line_length=120 diff --git a/libs/utils/.gitignore b/libs/utils/.gitignore deleted file mode 100644 index 3f762d543ec7..000000000000 --- a/libs/utils/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -# OS X generated file -.DS_Store - -# built application files -*.apk -*.ap_ - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ -build/ -build.log - -# Local configuration file (sdk path, etc) -local.properties - -# Eclipse project files -.settings/ -.classpath -.project - -# Intellij project files -*.iml -*.ipr -*.iws -/.idea/* - -# IntelliJ/Android Studio exceptions -!/.idea/vcs.xml -!/.idea/codeStyles/ -!/.idea/fileTemplates/ -!/.idea/inspectionProfiles/ -!/.idea/scopes/ -!/.idea/codeStyleSettings.xml -!/.idea/encodings.xml -!/.idea/copyright/ -!/.idea/compiler.xml -# Enforce plugins -!/.idea/externalDependencies.xml -# Checkstyle configuration -!/.idea/checkstyle-idea.xml - -# Gradle -.gradle/ -gradle.properties - -# Silver Searcher ignore file -.agignore - -# Windows Backup -*.bak diff --git a/libs/utils/.idea/checkstyle-idea.xml b/libs/utils/.idea/checkstyle-idea.xml deleted file mode 100644 index 0cfcc74ce7f4..000000000000 --- a/libs/utils/.idea/checkstyle-idea.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/codeStyleSettings.xml b/libs/utils/.idea/codeStyleSettings.xml deleted file mode 100644 index c3f56acf6b1c..000000000000 --- a/libs/utils/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/codeStyles/Project.xml b/libs/utils/.idea/codeStyles/Project.xml deleted file mode 100644 index a6f575ec5fc6..000000000000 --- a/libs/utils/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/codeStyles/codeStyleConfig.xml b/libs/utils/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c2b23..000000000000 --- a/libs/utils/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/utils/.idea/compiler.xml b/libs/utils/.idea/compiler.xml deleted file mode 100644 index 9a8b7e5c45ee..000000000000 --- a/libs/utils/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/copyright/profiles_settings.xml b/libs/utils/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3377d4..000000000000 --- a/libs/utils/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/libs/utils/.idea/encodings.xml b/libs/utils/.idea/encodings.xml deleted file mode 100644 index 97626ba45445..000000000000 --- a/libs/utils/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/externalDependencies.xml b/libs/utils/.idea/externalDependencies.xml deleted file mode 100644 index 687e9fd1e473..000000000000 --- a/libs/utils/.idea/externalDependencies.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/.idea/inspectionProfiles/Project_Default.xml b/libs/utils/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 4e2b427ce8a3..000000000000 --- a/libs/utils/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/utils/.idea/inspectionProfiles/profiles_settings.xml b/libs/utils/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b312839bf2e..000000000000 --- a/libs/utils/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/utils/.idea/vcs.xml b/libs/utils/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4cb4..000000000000 --- a/libs/utils/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/libs/utils/README.md b/libs/utils/README.md deleted file mode 100644 index 9a17a4008c5a..000000000000 --- a/libs/utils/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# WordPress-Utils-Android - -Collection of utility methods for Android and WordPress. - -## Use the library in your project - -* In your build.gradle: -```groovy -dependencies { - compile 'org.wordpress:utils:1.30.0' // use version 1.30.0 -} -``` - -## Publish an updated version to your local maven repository - -You can bump the [version name in the main build file: `WordPressUtils/build.gradle`][1]. After updating the build file, you can build, and publish the library to your local maven repo. That will let you try the new version in your app for example. - -```shell -$ ./gradlew assemble test publishToMavenLocal -``` - -## Publish it to Bintray - -When a new version is ready to be published to the remote repository, use the following command to publish it to Bintray: - -```shell -$ ./gradlew clean build -$ ./gradlew bintrayUpload -PbintrayUser=FIXME -PbintrayKey=FIXME -``` - -## Apps and libraries using WordPress-Utils-Android: - -- [WordPress for Android][2] -- [FluxC][3] - -## License -Dual licensed under MIT, and GPL. - -[1]: https://github.com/wordpress-mobile/WordPress-Utils-Android/blob/a9fbe8e6597d44055ec2180dbf45aecbfc332a20/WordPressUtils/build.gradle#L37 -[2]: https://github.com/wordpress-mobile/WordPress-Android -[3]: https://github.com/wordpress-mobile/WordPress-FluxC-Android diff --git a/libs/utils/WordPressUtils/README.md b/libs/utils/WordPressUtils/README.md deleted file mode 100644 index 62a759585e63..000000000000 --- a/libs/utils/WordPressUtils/README.md +++ /dev/null @@ -1 +0,0 @@ -# org.wordpress.android.util \ No newline at end of file diff --git a/libs/utils/WordPressUtils/build.gradle b/libs/utils/WordPressUtils/build.gradle deleted file mode 100644 index 5cb460031f40..000000000000 --- a/libs/utils/WordPressUtils/build.gradle +++ /dev/null @@ -1,122 +0,0 @@ -buildscript { - ext.kotlinVersion = '1.4.10' - ext.kotlin_ktx_version = '1.2.0' - - repositories { - google() - jcenter() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - classpath 'com.android.tools.build:gradle:4.0.1' - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5' - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'maven-publish' -apply plugin: 'com.jfrog.bintray' - -repositories { - google() - jcenter() -} - -dependencies { - implementation 'org.apache.commons:commons-text:1.1' - implementation 'com.android.volley:volley:1.1.1' - implementation 'com.google.android.material:material:1.2.1' - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - implementation 'androidx.recyclerview:recyclerview:1.0.0' - implementation 'org.greenrobot:eventbus:3.0.0' - - implementation "androidx.core:core-ktx:$kotlin_ktx_version" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" - - testImplementation 'junit:junit:4.12' - testImplementation 'org.assertj:assertj-core:3.11.1' - testImplementation "org.robolectric:robolectric:4.4" - testImplementation 'androidx.test:core:1.0.0' - - lintChecks 'org.wordpress:lint:1.0.1' - androidTestImplementation 'androidx.test:runner:1.1.0' - androidTestImplementation 'androidx.test:rules:1.1.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.0' - androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2' - -} - -android { - useLibrary 'org.apache.http.legacy' - - compileSdkVersion 29 - - defaultConfig { - versionName "1.30" - minSdkVersion 18 - targetSdkVersion 29 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - testOptions { - unitTests { - includeAndroidResources = true - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } -} - -android.libraryVariants.all { variant -> - task("generate${variant.name}Javadoc", type: Javadoc) { - description "Generates Javadoc for $variant.name." - source = variant.javaCompile.source - - options { - links "http://docs.oracle.com/javase/7/docs/api/" - } - exclude '**/R.java' - doFirst { - classpath = - files(variant.javaCompile.classpath.files, - project.android.getBootClasspath()) - } - } -} - -bintray { - user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') - key = project.hasProperty('bintrayKey') ? project.property('bintrayKey') : System.getenv('BINTRAY_KEY') - publications = ['UtilsPublication'] - publish = true - pkg { - repo = 'maven' - name = 'utils' - userOrg = 'wordpress-mobile' - licenses = ['MIT', 'GPL'] - vcsUrl = 'https://github.com/wordpress-mobile/WordPress-Utils-Android.git' - version { - name = android.defaultConfig.versionName - desc = 'Utils library for Android' - released = new Date() - } - } -} - -project.afterEvaluate { - publishing { - publications { - UtilsPublication(MavenPublication) { - from components.release - groupId 'org.wordpress' - artifactId 'utils' - version android.defaultConfig.versionName - } - } - } -} - diff --git a/libs/utils/WordPressUtils/gradle.properties-example b/libs/utils/WordPressUtils/gradle.properties-example deleted file mode 100644 index c9edd062db8b..000000000000 --- a/libs/utils/WordPressUtils/gradle.properties-example +++ /dev/null @@ -1,7 +0,0 @@ -android.useAndroidX=true -ossrhUsername=hello -ossrhPassword=world - -signing.keyId=byebye -signing.password=secret -signing.secretKeyRingFile=/home/user/secret.gpg diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java deleted file mode 100644 index 05b0af2f7ade..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ImageUtilsTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.wordpress.android.util; - -import android.graphics.BitmapFactory; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ImageUtilsTest { - @Test - public void testGetScaleForResizingReturnsOneWhenMaxSizeIsZero() { - BitmapFactory.Options options = new BitmapFactory.Options(); - int scale = ImageUtils.getScaleForResizing(0, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingSameSizeReturnsOne() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 100; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingPortraitMaxHeightSameAsMaxSizeReturnsOne() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 1; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingLandscapeMaxWidthSameAsMaxSizeReturnsOne() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 1; - options.outWidth = 100; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(1, scale); - } - - @Test - public void testGetScaleForResizingDoubleSizeReturnsTwo() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 200; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(2, scale); - } - - @Test - public void testGetScaleForResizingThreeTimesSizeReturnsTwo() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 300; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(2, scale); - } - - @Test - public void testGetScaleForResizingEightTimesSizeReturnsEight() { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.outHeight = 100; - options.outWidth = 800; - int maxSize = 100; - - int scale = ImageUtils.getScaleForResizing(maxSize, options); - - assertEquals(8, scale); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java deleted file mode 100644 index e02656fe4f3f..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.wordpress.android.util; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.junit.Test; - -public class JSONUtilsTest { - @Test - public void testQueryJSONNullSource1() { - JSONUtils.queryJSON((JSONObject) null, "", ""); - } - - @Test - public void testQueryJSONNullSource2() { - JSONUtils.queryJSON((JSONArray) null, "", ""); - } - - @Test - public void testQueryJSONNullQuery1() { - JSONUtils.queryJSON(new JSONObject(), null, ""); - } - - @Test - public void testQueryJSONNullQuery2() { - JSONUtils.queryJSON(new JSONArray(), null, ""); - } - - @Test - public void testQueryJSONNullReturnValue1() { - JSONUtils.queryJSON(new JSONObject(), "", null); - } - - @Test - public void testQueryJSONNullReturnValue2() { - JSONUtils.queryJSON(new JSONArray(), "", null); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java deleted file mode 100644 index 0e2d4b301706..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/PhotonUtilsTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Test; -import org.wordpress.android.util.PhotonUtils.Quality; - -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; - - -public class PhotonUtilsTest { - @Test - public void getPhotonImageUrlIsEmptyWhenUrlIsNull() { - String photonUrl = PhotonUtils.getPhotonImageUrl(null, 0, 1); - - assertThat(photonUrl, equalTo("")); - } - - @Test - public void getPhotonImageUrlIsEmptyWhenUrlIsEmpty() { - String photonUrl = PhotonUtils.getPhotonImageUrl("", 0, 1); - - assertThat(photonUrl, equalTo("")); - } - - @Test - public void getPhotonImageUrlReturnsImageUrlOnNoScheme() { - String imageUrl = "wordpress.com"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1); - - assertThat(photonUrl, equalTo(imageUrl)); - } - - @Test - public void getPhotonImageUrlReturnsMshots() { - String imageUrl = "http://test.wordpress.com/mshots/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1); - - assertThat(photonUrl, equalTo("http://test.wordpress.com/mshots/test.jpg?w=0&h=1")); - } - - @Test - public void getPhotonImageUrlReturnsCorrectQuality() { - Map qualities = new HashMap<>(); - qualities.put(Quality.HIGH, "100"); - qualities.put(Quality.MEDIUM, "65"); - qualities.put(Quality.LOW, "35"); - - String imageUrl = "http://test.wordpress.com/test.jpg?query=dummy"; - - for (Quality quality : qualities.keySet()) { - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 0, 1, quality); - assertThat(photonUrl, containsString("&quality=" + qualities.get(quality))); - } - } - - @Test - public void getPhotonImageUrlUsesResize() { - String imageUrl = "http://test.wordpress.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("http://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); - } - - @Test - public void getPhotonImageUrlManageSslOnPhotonUrl() { - String imageUrl = "https://i0.wp.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/test.jpg?strip=info&quality=65&resize=2,1")); - - imageUrl = "https://i0.wp.com/test.jpg?query=dummy&ssl=1"; - photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/test.jpg?strip=info&quality=65&resize=2,1&ssl=1")); - } - - @Test - public void getPhotonImageUrlDoNotUseSslOnWordPressCom() { - String imageUrl = "https://test.wordpress.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); - - imageUrl = "https://test.wordpress.com/test.jpg?query=dummy&ssl=1"; - photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://test.wordpress.com/test.jpg?strip=info&quality=65&resize=2,1")); - } - - @Test - public void getPhotonImageUrlUsesSslOnHttpsImageUrl() { - String imageUrl = "http://mysite.com/test.jpg?query=dummy"; - String photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/mysite.com/test.jpg?strip=info&quality=65&resize=2,1")); - - imageUrl = "https://mysite.com/test.jpg?query=dummy&ssl=1"; - photonUrl = PhotonUtils.getPhotonImageUrl(imageUrl, 2, 1); - - assertThat(photonUrl, equalTo("https://i0.wp.com/mysite.com/test.jpg?strip=info&quality=65&resize=2,1&ssl=1")); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java deleted file mode 100644 index 32435e40e6e8..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/ShortcodeUtilsTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ShortcodeUtilsTest { - @Test - public void testGetVideoPressShortcodeFromId() { - assertEquals("[wpvideo abcd1234]", ShortcodeUtils.getVideoPressShortcodeFromId("abcd1234")); - } - - @Test - public void testGetVideoPressShortcodeFromNullId() { - assertEquals("", ShortcodeUtils.getVideoPressShortcodeFromId(null)); - } - - @Test - public void testGetVideoPressIdFromCorrectShortcode() { - assertEquals("abcd1234", ShortcodeUtils.getVideoPressIdFromShortCode("[wpvideo abcd1234]")); - } - - @Test - public void testGetVideoPressIdFromInvalidShortcode() { - assertEquals("", ShortcodeUtils.getVideoPressIdFromShortCode("[other abcd1234]")); - } - - @Test - public void testGetVideoPressIdFromNullShortcode() { - assertEquals("", ShortcodeUtils.getVideoPressIdFromShortCode(null)); - } -} diff --git a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java b/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java deleted file mode 100644 index 9cf88220712d..000000000000 --- a/libs/utils/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Test; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class UrlUtilsTest { - @Test - public void testGetDomainFromUrlWithEmptyStringDoesNotReturnNull() { - assertNotNull(UrlUtils.getHost("")); - } - - @Test - public void testGetDomainFromUrlWithNoHostDoesNotReturnNull() { - assertNotNull(UrlUtils.getHost("wordpress")); - } - - @Test - public void testGetDomainFromUrlWithHostReturnsHost() { - String url = "http://www.wordpress.com"; - String host = UrlUtils.getHost(url); - - assertTrue(host.equals("www.wordpress.com")); - } - - @Test - public void testAppendUrlParameter1() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test", "preview", "true"); - assertEquals("http://wp.com/test?preview=true", url); - } - - @Test - public void testAppendUrlParameter2() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony", "preview", "true"); - assertEquals("http://wp.com/test?q=pony&preview=true", url); - } - - @Test - public void testAppendUrlParameter3() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony#unicorn", "preview", "true"); - assertEquals("http://wp.com/test?q=pony&preview=true#unicorn", url); - } - - @Test - public void testAppendUrlParameter4() { - String url = UrlUtils.appendUrlParameter("/relative/test", "preview", "true"); - assertEquals("/relative/test?preview=true", url); - } - - @Test - public void testAppendUrlParameter5() { - String url = UrlUtils.appendUrlParameter("/relative/", "preview", "true"); - assertEquals("/relative/?preview=true", url); - } - - @Test - public void testAppendUrlParameter6() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test/", "preview", "true"); - assertEquals("http://wp.com/test/?preview=true", url); - } - - @Test - public void testAppendUrlParameter7() { - String url = UrlUtils.appendUrlParameter("http://wp.com/test/?q=pony", "preview", "true"); - assertEquals("http://wp.com/test/?q=pony&preview=true", url); - } - - @Test - public void testAppendUrlParameters1() { - Map params = new HashMap<>(); - params.put("w", "200"); - params.put("h", "300"); - String url = UrlUtils.appendUrlParameters("http://wp.com/test", params); - if (!url.equals("http://wp.com/test?h=300&w=200") && !url.equals("http://wp.com/test?w=200&h=300")) { - assertTrue("failed test on url: " + url, false); - } - } - - @Test - public void testAppendUrlParameters2() { - Map params = new HashMap<>(); - params.put("h", "300"); - params.put("w", "200"); - String url = UrlUtils.appendUrlParameters("/relative/test", params); - if (!url.equals("/relative/test?h=300&w=200") && !url.equals("/relative/test?w=200&h=300")) { - assertTrue("failed test on url: " + url, false); - } - } - - @Test - public void testHttps1() { - assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com/xmlrpc.php"))); - } - - @Test - public void testHttps2() { - assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com#.b.com/test"))); - } - - @Test - public void testHttps3() { - assertFalse(UrlUtils.isHttps(buildURL("http://wordpress.com/xmlrpc.php"))); - } - - @Test - public void testHttps4() { - assertTrue(UrlUtils.isHttps(buildURL("https://wordpress.com"))); - } - - @Test - public void testHttps5() { - assertTrue(UrlUtils.isHttps(buildURL("https://wordpress.com/test#test"))); - } - - private URL buildURL(String address) { - URL url = null; - try { - url = new URL(address); - } catch (MalformedURLException e) { - } - return url; - } -} diff --git a/libs/utils/WordPressUtils/src/main/AndroidManifest.xml b/libs/utils/WordPressUtils/src/main/AndroidManifest.xml deleted file mode 100644 index d52c0f661462..000000000000 --- a/libs/utils/WordPressUtils/src/main/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java deleted file mode 100644 index 78b9ee6d9fd6..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityEventListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wordpress.android.util; - -import android.view.accessibility.AccessibilityEvent; - -public interface AccessibilityEventListener { - void onResult(AccessibilityEvent event); -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java deleted file mode 100644 index 3c6ad25eebd5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AccessibilityUtils.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Activity; -import android.content.Context; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.view.AccessibilityDelegateCompat; -import androidx.core.view.ViewCompat; -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; - -import com.google.android.material.snackbar.Snackbar; - -import org.wordpress.android.util.AppLog.T; - -import static android.content.Context.ACCESSIBILITY_SERVICE; -import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED; - -public class AccessibilityUtils { - private static final int SNACKBAR_WITH_ACTION_DURATION_IN_MILLIS = 10000; - - public static boolean isAccessibilityEnabled(Context ctx) { - AccessibilityManager am = (AccessibilityManager) ctx.getSystemService(ACCESSIBILITY_SERVICE); - return am != null && am.isEnabled(); - } - - /** - * If the default duration is LENGTH_INDEFINITE, ignore accessibility duration and return LENGTH_INDEFINITE. - * If the accessibility is enabled, returns increased snackbar duration, otherwise returns defaultDuration. - * - * @param defaultDuration Either be one of the predefined lengths: LENGTH_SHORT, LENGTH_LONG, or a custom duration - * in milliseconds. - */ - public static int getSnackbarDuration(Context ctx, int defaultDuration) { - return defaultDuration == Snackbar.LENGTH_INDEFINITE ? Snackbar.LENGTH_INDEFINITE - : isAccessibilityEnabled(ctx) ? SNACKBAR_WITH_ACTION_DURATION_IN_MILLIS : defaultDuration; - } - - public static void setActionModeDoneButtonContentDescription(@Nullable final Activity activity, - @NonNull final String contentDescription) { - if (activity != null) { - View decorView = activity.getWindow().getDecorView(); - - decorView.post(new Runnable() { - @Override public void run() { - View doneButton = activity.findViewById(androidx.appcompat.R.id.action_mode_close_button); - - if (doneButton != null) { - doneButton.setContentDescription(contentDescription); - } - } - }); - } - } - - public static void addPopulateAccessibilityEventFocusedListener(@NonNull final View target, - @NonNull final AccessibilityEventListener - listener) { - ViewCompat.setAccessibilityDelegate(target, new AccessibilityDelegateCompat() { - @Override public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { - if (event.getEventType() == TYPE_VIEW_ACCESSIBILITY_FOCUSED) { - listener.onResult(event); - } - super.onPopulateAccessibilityEvent(host, event); - } - }); - } - - public static void disableHintAnnouncement(@NonNull TextView textView) { - setAccessibilityDelegateSafely(textView, new AccessibilityDelegateCompat() { - @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setHintText(null); - } - }); - } - - /** - * When the minsdk is 28 this can be replaced by adding android:accessibilityHeading="true" as a property to the - * view's xml declaration. - * @param view that will become a heading. - */ - public static void enableAccessibilityHeading(@NonNull View view) { - setAccessibilityDelegateSafely(view, new AccessibilityDelegateCompat() { - @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setHeading(true); - } - }); - } - - public static void setAccessibilityDelegateSafely(View view, - AccessibilityDelegateCompat accessibilityDelegateCompat) { - if (ViewCompat.hasAccessibilityDelegate(view)) { - final String errorMessage = "View already has an AccessibilityDelegate."; - if (PackageUtils.isDebugBuild()) { - throw new RuntimeException(errorMessage); - } - AppLog.e(T.UTILS, errorMessage); - } else { - ViewCompat.setAccessibilityDelegate(view, accessibilityDelegateCompat); - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java deleted file mode 100644 index 0751b0a5d977..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ActivityUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.view.View; -import android.view.inputmethod.InputMethodManager; - -import androidx.annotation.Nullable; - -public class ActivityUtils { - /** - * Hides the keyboard in the given {@link Activity}'s current focus using the - * {@link InputMethodManager#HIDE_NOT_ALWAYS} flag, which will hide the keyboard unless it was originally shown - * with {@link InputMethodManager#SHOW_FORCED}. - */ - public static void hideKeyboard(Activity activity) { - if (activity != null && activity.getCurrentFocus() != null) { - InputMethodManager inputManager = (InputMethodManager) activity.getSystemService( - Context.INPUT_METHOD_SERVICE); - inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), - InputMethodManager.HIDE_NOT_ALWAYS); - } - } - - /** - * Hides the keyboard for the given {@link View}. No {@link InputMethodManager} flag is used, therefore the - * keyboard is forcibly hidden regardless of the circumstances. - */ - public static void hideKeyboardForced(@Nullable final View view) { - if (view == null) { - return; - } - InputMethodManager inputMethodManager = - (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - - /** - * Shows the keyboard for the given {@link View} using the {@link InputMethodManager#SHOW_IMPLICIT} flag, - * which is an implicit request (i.e. not requested by the user) to show the keyboard. - */ - public static void showKeyboard(@Nullable final View view) { - if (view == null) { - return; - } - InputMethodManager inputMethodManager = - (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); - } - - public static boolean isDeepLinking(Intent intent) { - return Intent.ACTION_VIEW.equals(intent.getAction()); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java deleted file mode 100644 index 6a09c42f20c1..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AlertUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2011 wordpress.org - * - * 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. - */ - -package org.wordpress.android.util; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; - -public class AlertUtils { - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param messageId - */ - public static void showAlert(Context context, int titleId, int messageId) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(android.R.string.ok, null) - .setMessage(messageId) - .create(); - - dlg.show(); - } - - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param message - */ - public static void showAlert(Context context, int titleId, String message) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(android.R.string.ok, null) - .setMessage(message) - .create(); - - dlg.show(); - } - - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param messageId - * @param positiveButtontxt - * @param positiveListener - * @param negativeButtontxt - * @param negativeListener - */ - public static void showAlert(Context context, int titleId, int messageId, - CharSequence positiveButtontxt, DialogInterface.OnClickListener positiveListener, - CharSequence negativeButtontxt, DialogInterface.OnClickListener negativeListener) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(positiveButtontxt, positiveListener) - .setNegativeButton(negativeButtontxt, negativeListener) - .setMessage(messageId) - .setCancelable(false) - .create(); - - dlg.show(); - } - - /** - * Show Alert Dialog - * @param context - * @param titleId - * @param message - * @param positiveButtontxt - * @param positiveListener - */ - public static void showAlert(Context context, int titleId, String message, - CharSequence positiveButtontxt, DialogInterface.OnClickListener positiveListener) { - Dialog dlg = new AlertDialog.Builder(context) - .setTitle(titleId) - .setPositiveButton(positiveButtontxt, positiveListener) - .setMessage(message) - .setCancelable(false) - .create(); - - dlg.show(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java deleted file mode 100644 index f1d93476c24b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AppLog.java +++ /dev/null @@ -1,382 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.NonNull; - -import org.wordpress.android.util.helpers.logfile.LogFileCleaner; -import org.wordpress.android.util.helpers.logfile.LogFileProvider; -import org.wordpress.android.util.helpers.logfile.LogFileWriter; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.NoSuchElementException; -import java.util.TimeZone; - -import static java.lang.String.format; - -/** - * simple wrapper for Android log calls, enables recording and displaying log - */ -public class AppLog { - // T for Tag - public enum T { - READER, - EDITOR, - MEDIA, - NUX, - API, - STATS, - UTILS, - NOTIFS, - DB, - POSTS, - PAGES, - COMMENTS, - THEMES, - TESTS, - PROFILING, - SIMPERIUM, - SUGGESTION, - MAIN, - SETTINGS, - PLANS, - PEOPLE, - SHARING, - PLUGINS, - ACTIVITY_LOG, - JETPACK_REMOTE_INSTALL, - SUPPORT, - SITE_CREATION, - DOMAIN_REGISTRATION, - FEATURE_ANNOUNCEMENT, - PREPUBLISHING_NUDGES - } - - public static final String TAG = "WordPress"; - public static final int HEADER_LINE_COUNT = 2; - private static boolean mEnableRecording = false; - private static List mListeners = new ArrayList<>(0); - private static TimeZone mUtcTimeZone = TimeZone.getTimeZone("UTC"); - - private AppLog() { - throw new AssertionError(); - } - - /** - * Capture log so it can be displayed by AppLogViewerActivity - * @param enable A boolean flag to capture log. Default is false, pass true to enable recording - */ - public static void enableRecording(boolean enable) { - mEnableRecording = enable; - } - - public static void addListener(@NonNull AppLogListener listener) { - mListeners.add(listener); - } - - public static void removeListeners() { - mListeners.clear(); - } - - public interface AppLogListener { - void onLog(T tag, LogLevel logLevel, String message); - } - - /** - * Add a LogFileWriter that will persist logs to disk - * @param context The current application context - * @param maxLogCount The maximum number of logs that should be stored - */ - public static void enableLogFilePersistence(Context context, int maxLogCount) { - LogFileProvider logFileProvider = LogFileProvider.fromContext(context); - new LogFileCleaner(logFileProvider, maxLogCount).clean(); - - sLogFileWriter = new LogFileWriter(logFileProvider); - sLogFileWriter.write(getAppInfoHeaderText(context) + "\n"); - sLogFileWriter.write(getDeviceInfoHeaderText(context) + "\n"); - } - - private static LogFileWriter sLogFileWriter; - - /** - * Sends a VERBOSE log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void v(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.v(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.v, message); - } - - /** - * Sends a DEBUG log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void d(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.d(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.d, message); - } - - /** - * Sends a INFO log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void i(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.i(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.i, message); - } - - /** - * Sends a WARN log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void w(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.w(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.w, message); - } - - /** - * Sends a ERROR log message - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - */ - public static void e(T tag, String message) { - message = StringUtils.notNullStr(message); - Log.e(TAG + "-" + tag.toString(), message); - addEntry(tag, LogLevel.e, message); - } - - /** - * Send a ERROR log message and log the exception. - * @param tag Used to identify the source of a log message. - * It usually identifies the class or activity where the log call occurs. - * @param message The message you would like logged. - * @param tr An exception to log - */ - public static void e(T tag, String message, Throwable tr) { - message = StringUtils.notNullStr(message); - Log.e(TAG + "-" + tag.toString(), message, tr); - addEntry(tag, LogLevel.e, message + " - exception: " + tr.getMessage()); - addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr)); - } - - /** - * Sends a ERROR log message and the exception with StackTrace - * @param tag Used to identify the source of a log message. It usually identifies the class or activity where the - * log call occurs. - * @param tr An exception to log to get StackTrace - */ - public static void e(T tag, Throwable tr) { - Log.e(TAG + "-" + tag.toString(), tr.getMessage(), tr); - addEntry(tag, LogLevel.e, tr.getMessage()); - addEntry(tag, LogLevel.e, "StackTrace: " + getStringStackTrace(tr)); - } - - /** - * Sends a ERROR log message - * @param tag Used to identify the source of a log message. It usually identifies the class or activity where the - * log call occurs. - * @param volleyErrorMsg - * @param statusCode - */ - public static void e(T tag, String volleyErrorMsg, int statusCode) { - if (TextUtils.isEmpty(volleyErrorMsg)) { - return; - } - String logText; - if (statusCode == -1) { - logText = volleyErrorMsg; - } else { - logText = volleyErrorMsg + ", status " + statusCode; - } - Log.e(TAG + "-" + tag.toString(), logText); - addEntry(tag, LogLevel.w, logText); - } - - // -------------------------------------------------------------------------------------------------------- - - private static final int MAX_ENTRIES = 99; - - public enum LogLevel { - v, d, i, w, e; - } - - private static class LogEntry { - final LogLevel mLogLevel; - final String mLogText; - final java.util.Date mDate; - final T mLogTag; - - LogEntry(LogLevel logLevel, String logText, T logTag) { - mLogLevel = logLevel; - mDate = new Date(); - if (logText == null) { - mLogText = "null"; - } else { - mLogText = logText; - } - mLogTag = logTag; - } - - private String formatLogDate() { - SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd kk:mm", Locale.US); - sdf.setTimeZone(mUtcTimeZone); - return sdf.format(mDate); - } - - private String toHtml() { - StringBuilder sb = new StringBuilder(); - sb.append("["); - sb.append(formatLogDate()).append(" "); - sb.append(mLogTag.name()).append(" "); - sb.append(mLogLevel.name()); - sb.append("] "); - sb.append(TextUtils.htmlEncode(mLogText).replace("\n", "
    ")); - return sb.toString(); - } - - @Override - public @NonNull String toString() { - return "[" - + formatLogDate() - + " " - + mLogTag.name() - + "] " - + mLogText - + "\n"; - } - } - - private static class LogEntryList extends ArrayList { - private synchronized boolean addEntry(LogEntry entry) { - if (size() >= MAX_ENTRIES) { - removeFirstEntry(); - } - return add(entry); - } - - private void removeFirstEntry() { - Iterator it = iterator(); - if (!it.hasNext()) { - return; - } - try { - remove(it.next()); - } catch (NoSuchElementException e) { - // ignore - } - } - } - - private static LogEntryList mLogEntries = new LogEntryList(); - - private static void addEntry(T tag, LogLevel level, String text) { - // Call our listeners if any - for (AppLogListener listener : mListeners) { - listener.onLog(tag, level, text); - } - // Record entry if enabled - if (mEnableRecording) { - LogEntry entry = new LogEntry(level, text, tag); - mLogEntries.addEntry(entry); - - if (sLogFileWriter != null) { - sLogFileWriter.write(entry.toString()); - } - } - } - - private static String getStringStackTrace(Throwable throwable) { - StringWriter errors = new StringWriter(); - throwable.printStackTrace(new PrintWriter(errors)); - return errors.toString(); - } - - - private static String getAppInfoHeaderText(Context context) { - StringBuilder sb = new StringBuilder(); - PackageManager packageManager = context.getPackageManager(); - PackageInfo pkInfo = PackageUtils.getPackageInfo(context); - - ApplicationInfo applicationInfo = pkInfo != null ? pkInfo.applicationInfo : null; - String appName; - if (applicationInfo != null && packageManager.getApplicationLabel(applicationInfo) != null) { - appName = packageManager.getApplicationLabel(applicationInfo).toString(); - } else { - appName = "Unknown"; - } - sb.append(appName).append(" - ").append(PackageUtils.getVersionName(context)) - .append(" - Version code: ").append(PackageUtils.getVersionCode(context)); - return sb.toString(); - } - - private static String getDeviceInfoHeaderText(Context context) { - return "Android device name: " + DeviceUtils.getInstance().getDeviceName(context); - } - - /** - * Returns entire log as html for display (see AppLogViewerActivity) - * @param context - * @return Arraylist of Strings containing log messages - */ - public static ArrayList toHtmlList(Context context) { - ArrayList items = new ArrayList(); - - // add version & device info - be sure to change HEADER_LINE_COUNT if additional lines are added - items.add("" + getAppInfoHeaderText(context) + ""); - items.add("" + getDeviceInfoHeaderText(context) + ""); - - Iterator it = new ArrayList<>(mLogEntries).iterator(); - while (it.hasNext()) { - items.add(it.next().toHtml()); - } - return items; - } - - /** - * Converts the entire log to plain text - * @param context - * @return The log as plain text - */ - public static synchronized String toPlainText(Context context) { - StringBuilder sb = new StringBuilder(); - - // add version & device info - sb.append(getAppInfoHeaderText(context)).append("\n") - .append(getDeviceInfoHeaderText(context)).append("\n\n"); - - Iterator it = new ArrayList<>(mLogEntries).iterator(); - int lineNum = 1; - while (it.hasNext()) { - LogEntry entry = it.next(); - sb.append(format(Locale.US, "%02d - ", lineNum)) - .append(entry.toString()); - lineNum++; - } - return sb.toString(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java deleted file mode 100644 index 4cdc2911058f..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForeground.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Notification; -import android.app.Service; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Binder; -import android.os.IBinder; - -import androidx.annotation.CallSuper; -import androidx.annotation.Nullable; -import androidx.core.app.NotificationManagerCompat; - -import org.greenrobot.eventbus.EventBus; -import org.wordpress.android.util.AutoForeground.ServiceState; - -import java.util.HashMap; -import java.util.Map; - -public abstract class AutoForeground - extends Service { - public static final int NOTIFICATION_ID_PROGRESS = 1; - public static final int NOTIFICATION_ID_SUCCESS = 2; - public static final int NOTIFICATION_ID_FAILURE = 3; - - public interface ServiceState { - boolean isIdle(); - - boolean isInProgress(); - - boolean isError(); - - boolean isTerminal(); - - String getStepName(); - } - - public static class ServiceEventConnection { - private final ServiceConnection mServiceConnection; - - public ServiceEventConnection(Context context, Class clazz, Object client) { - EventBus.getDefault().register(client); - - mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName componentName, IBinder iBinder) { - // nothing here - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - // nothing here - } - }; - - context.bindService(new Intent(context, clazz), mServiceConnection, Context.BIND_AUTO_CREATE); - } - - public void disconnect(Context context, Object client) { - context.unbindService(mServiceConnection); - EventBus.getDefault().unregister(client); - } - } - - private class LocalBinder extends Binder { - } - - private final IBinder mBinder = new LocalBinder(); - - private final Class mStateClass; - - private boolean mIsForeground; - - protected abstract void onProgressStart(); - - protected abstract void onProgressEnd(); - - protected abstract Notification getNotification(StateClass state); - - protected abstract void trackStateUpdate(Map props); - - @SuppressWarnings("unchecked") - protected AutoForeground(StateClass initialState) { - mStateClass = (Class) initialState.getClass(); - - // initialize the sticky phase if it hasn't already - if (EventBus.getDefault().getStickyEvent(mStateClass) == null) { - notifyState(initialState); - } - } - - public boolean isForeground() { - return mIsForeground; - } - - @Nullable - private StateClass getState() { - return getState(mStateClass); - } - - @Nullable - protected static StateClass getState(Class stateClass) { - return EventBus.getDefault().getStickyEvent(stateClass); - } - - @Nullable - @CallSuper - @Override - public IBinder onBind(Intent intent) { - clearAllNotifications(); - return mBinder; - } - - @CallSuper - @Override - public void onRebind(Intent intent) { - super.onRebind(intent); - - clearAllNotifications(); - background(); - } - - @CallSuper - @Override - public boolean onUnbind(Intent intent) { - if (!hasConnectedClients()) { - final StateClass state = getState(); - if (state != null && state.isInProgress()) { - promoteForeground(state); - } - } - - return true; // call onRebind() if new clients connect - } - - protected void clearAllNotifications() { - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_SUCCESS); - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_FAILURE); - } - - private EventBus getEventBus() { - return EventBus.getDefault(); - } - - private boolean hasConnectedClients() { - return getEventBus().hasSubscriberForEvent(mStateClass); - } - - private void promoteForeground(StateClass currentState) { - startForeground(NOTIFICATION_ID_PROGRESS, getNotification(currentState)); - mIsForeground = true; - } - - private void background() { - stopForeground(true); - mIsForeground = false; - } - - @CallSuper - protected void setState(StateClass newState) { - StateClass currentState = getState(); - if ((currentState == null || !currentState.isInProgress()) && newState.isInProgress()) { - onProgressStart(); - } - - track(newState); - notifyState(newState); - - if (newState.isTerminal()) { - onProgressEnd(); - stopSelf(); - } - } - - protected void track(ServiceState state) { - Map props = new HashMap<>(); - props.put("login_phase", state == null ? "null" : state.getStepName()); - props.put("login_service_is_foreground", isForeground()); - trackStateUpdate(props); - } - - protected static void clearServiceState(Class klass) { - EventBus.getDefault().removeStickyEvent(klass); - } - - @CallSuper - protected void notifyState(StateClass state) { - // sticky emit the state. The stickiness serves as a state keeping mechanism for clients to re-read upon connect - getEventBus().postSticky(state); - - if (hasConnectedClients()) { - // there are connected clients so, nothing more to do here - return; - } - - // ok, no connected clients so, update might need to be delivered to a notification as well - - if (state.isIdle()) { - // no need to have a notification when idle - return; - } - - if (state.isInProgress()) { - // operation still is progress so, update the notification - NotificationManagerCompat.from(this).notify(NOTIFICATION_ID_PROGRESS, getNotification(state)); - return; - } - - // operation has ended so, demote the Service to a background one - background(); - - // dismiss the sticky notification - NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID_PROGRESS); - - // put out a simple success/failure notification - NotificationManagerCompat.from(this).notify( - state.isError() ? NOTIFICATION_ID_FAILURE : NOTIFICATION_ID_SUCCESS, - getNotification(state)); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java deleted file mode 100644 index db8c8b32b592..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/AutoForegroundNotification.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; - -import androidx.annotation.ColorRes; -import androidx.annotation.DrawableRes; -import androidx.annotation.StringRes; -import androidx.core.app.NotificationCompat; - -import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_FAILURE; -import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_PROGRESS; -import static org.wordpress.android.util.AutoForeground.NOTIFICATION_ID_SUCCESS; - -public class AutoForegroundNotification { - private static Intent getResumeIntent(Context context) { - // Let's get an Intent with the sole purpose of _resuming_ the app from the background - Intent resumeIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); - - // getLaunchIntentForPackage() seems to set the Package Name but if we construct a launcher Intent manually - // the package name is not set so, let's null it out here to match the manual Intent. - resumeIntent.setSelector(null); - resumeIntent.setPackage(null); - - return resumeIntent; - } - - private static NotificationCompat.Builder getNotificationBuilder(Context context, String channelId, int requestCode, - @StringRes int title, @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(); - bigTextStyle.setBigContentTitle(context.getString(title)); - bigTextStyle.bigText(context.getString(content)); - - return new NotificationCompat.Builder(context, channelId) - .setStyle(bigTextStyle) - .setContentTitle(context.getString(title)) - .setContentText(context.getString(content)) - .setSmallIcon(icon) - .setColor(context.getResources().getColor(accentColor)) - .setAutoCancel(true) - .setOnlyAlertOnce(true) - .setContentIntent(PendingIntent.getActivity( - context, - requestCode, - getResumeIntent(context), - PendingIntent.FLAG_ONE_SHOT)); - } - - public static Notification progress(Context context, String channelId, int progress, @StringRes int title, - @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_PROGRESS, title, content, icon, accentColor) - .setProgress(100, progress, false) - .build(); - } - - public static Notification progressIndeterminate(Context context, String channelId, @StringRes int title, - @StringRes int content, @DrawableRes int icon, - @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_PROGRESS, title, content, icon, accentColor) - .setProgress(0, 0, true) - .build(); - } - - public static Notification success(Context context, String channelId, @StringRes int title, @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_SUCCESS, title, content, icon, accentColor) - .build(); - } - - public static Notification failure(Context context, String channelId, @StringRes int title, @StringRes int content, - @DrawableRes int icon, @ColorRes int accentColor) { - return getNotificationBuilder(context, channelId, NOTIFICATION_ID_FAILURE, title, content, icon, accentColor) - .build(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java deleted file mode 100644 index 3f8f0fee74e4..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DateTimeUtils.java +++ /dev/null @@ -1,251 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.text.TextUtils; -import android.text.format.DateUtils; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -public class DateTimeUtils { - private DateTimeUtils() { - throw new AssertionError(); - } - - // See http://drdobbs.com/java/184405382 - private static final ThreadLocal ISO8601_FORMAT = new ThreadLocal() { - @Override - protected DateFormat initialValue() { - return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); - } - }; - - public static String javaDateToTimeSpan(final Date date, Context context, long currentTime) { - if (date == null) { - return ""; - } - - long passedTime = date.getTime(); - - // return "now" if less than a minute has elapsed - long secondsSince = (currentTime - passedTime) / 1000; - if (secondsSince < 60) { - return context.getString(R.string.timespan_now); - } - - long daysSince = secondsSince / (60 * 60 * 24); - - // less than a year old, let `DateUtils.getRelativeTimeSpanString` do the job - if (daysSince < 365) { - return DateUtils.getRelativeTimeSpanString(passedTime, currentTime, DateUtils.MINUTE_IN_MILLIS, - DateUtils.FORMAT_ABBREV_ALL).toString(); - } - - // date is older, so include year (ex: Jan 30, 2013) - return DateUtils.formatDateTime(context, passedTime, DateUtils.FORMAT_ABBREV_ALL); - } - - /** - * Converts a date to a localized relative time span ("Now", "8 hr. ago", "Yesterday", "3 days ago", "Jul 10, 1940") - * We're using a call to `DateUtils.getRelativeTimeSpanString` in most cases. - */ - public static String javaDateToTimeSpan(final Date date, Context context) { - return javaDateToTimeSpan(date, context, System.currentTimeMillis()); - } - - /** - * Given an ISO 8601-formatted date as a String, returns a {@link Date}. - */ - public static Date dateFromIso8601(final String strDate) { - try { - DateFormat formatter = ISO8601_FORMAT.get(); - return formatter.parse(strDate); - } catch (ParseException e) { - return null; - } - } - - /** - * Given an ISO 8601-formatted date as a String, returns a {@link Date} in UTC. - */ - public static Date dateUTCFromIso8601(String iso8601date) { - try { - iso8601date = iso8601date.replace("Z", "+0000").replace("+00:00", "+0000"); - DateFormat formatter = ISO8601_FORMAT.get(); - formatter.setTimeZone(TimeZone.getTimeZone("UTC")); - return formatter.parse(iso8601date); - } catch (ParseException e) { - return null; - } - } - - /** - * Given a {@link Date}, returns an ISO 8601-formatted String. - */ - public static String iso8601FromDate(Date date) { - if (date == null) { - return ""; - } - DateFormat formatter = ISO8601_FORMAT.get(); - return formatter.format(date); - } - - /** - * Given a {@link Date}, returns an ISO 8601-formatted String in UTC. - */ - public static String iso8601UTCFromDate(Date date) { - if (date == null) { - return ""; - } - TimeZone tz = TimeZone.getTimeZone("UTC"); - DateFormat formatter = ISO8601_FORMAT.get(); - formatter.setTimeZone(tz); - - String iso8601date = formatter.format(date); - - // Use "+00:00" notation rather than "+0000" to be consistent with the WP.COM API - return iso8601date.replace("+0000", "+00:00"); - } - - /** - * Returns the current UTC date. - * - * @deprecated This method doesn't work as expected and shouldn't be used in production code. It doesn't take - * into account that `Date` class uses TimeZone.getDefault(). It substracts the currentOffsetFromUTC, but the - * final date still uses system default timezone. - */ - @Deprecated - public static Date nowUTC() { - Date dateTimeNow = new Date(); - return localDateToUTC(dateTimeNow); - } - - /** - * - * @deprecated This method doesn't work as expected and shouldn't be used in production code. It doesn't take - * into account that `Date` class uses TimeZone.getDefault(). It substracts the currentOffsetFromUTC, but the - * final date still uses system default timezone. - */ - @Deprecated - public static Date localDateToUTC(Date dtLocal) { - if (dtLocal == null) { - return null; - } - TimeZone tz = TimeZone.getDefault(); - int currentOffsetFromUTC = tz.getRawOffset() + (tz.inDaylightTime(dtLocal) ? tz.getDSTSavings() : 0); - return new Date(dtLocal.getTime() - currentOffsetFromUTC); - } - - // Routines to return a diff between two dates - always return a positive number - - public static int daysBetween(Date dt1, Date dt2) { - long hrDiff = hoursBetween(dt1, dt2); - if (hrDiff == 0) { - return 0; - } - return (int) (hrDiff / 24); - } - - public static int hoursBetween(Date dt1, Date dt2) { - long minDiff = minutesBetween(dt1, dt2); - if (minDiff == 0) { - return 0; - } - return (int) (minDiff / 60); - } - - public static int minutesBetween(Date dt1, Date dt2) { - long msDiff = millisecondsBetween(dt1, dt2); - if (msDiff == 0) { - return 0; - } - return (int) (msDiff / 60000); - } - - public static int secondsBetween(Date dt1, Date dt2) { - long msDiff = millisecondsBetween(dt1, dt2); - if (msDiff == 0) { - return 0; - } - return (int) (msDiff / 1000); - } - - public static long millisecondsBetween(Date dt1, Date dt2) { - if (dt1 == null || dt2 == null) { - return 0; - } - return Math.abs(dt1.getTime() - dt2.getTime()); - } - - public static boolean isSameYear(Date dt1, Date dt2) { - if (dt1 == null || dt2 == null) { - return false; - } - return dt1.getYear() == dt2.getYear(); - } - - public static boolean isSameMonthAndYear(Date dt1, Date dt2) { - if (dt1 == null || dt2 == null) { - return false; - } - return dt1.getYear() == dt2.getYear() && dt1.getMonth() == dt2.getMonth(); - } - - // Routines involving Unix timestamps (GMT assumed) - - /** - * Given an ISO 8601-formatted date as a String, returns the corresponding UNIX timestamp. - */ - public static long timestampFromIso8601(final String strDate) { - return timestampFromIso8601Millis(strDate) / 1000; - } - - /** - * Given an ISO 8601-formatted date as a String, returns the corresponding timestamp in milliseconds. - * - * @return 0 if the parameter is null, empty or not a date. - */ - public static long timestampFromIso8601Millis(final String strDate) { - if (TextUtils.isEmpty(strDate)) { - return 0; - } - Date date = dateFromIso8601(strDate); - if (date == null) { - return 0; - } - return date.getTime(); - } - - /** - * Given a UNIX timestamp, returns the corresponding {@link Date}. - */ - public static Date dateFromTimestamp(long timestamp) { - return new java.util.Date(timestamp * 1000); - } - - /** - * Given a UNIX timestamp, returns an ISO 8601-formatted date as a String. - */ - public static String iso8601FromTimestamp(long timestamp) { - return iso8601FromDate(dateFromTimestamp(timestamp)); - } - - /** - * Given a UNIX timestamp, returns an ISO 8601-formatted date in UTC as a String. - */ - public static String iso8601UTCFromTimestamp(long timestamp) { - return iso8601UTCFromDate(dateFromTimestamp(timestamp)); - } - - /** - * Given a UNIX timestamp, returns a relative time span ("8h", "3d", etc.). - */ - public static String timeSpanFromTimestamp(long timestamp, Context context) { - Date dateGMT = dateFromTimestamp(timestamp); - return javaDateToTimeSpan(dateGMT, context); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java deleted file mode 100644 index dcd7d1d4ec0a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DeviceUtils.java +++ /dev/null @@ -1,179 +0,0 @@ -package org.wordpress.android.util; - -import android.app.KeyguardManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Environment; -import android.os.StatFs; - -import androidx.annotation.NonNull; - -import org.wordpress.android.util.AppLog.T; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -public class DeviceUtils { - private static final String APP_RUNTIME_ON_CHROME_FLAG = "org.chromium.arc.device_management"; - - private static DeviceUtils instance; - private boolean mIsKindleFire = false; - - public boolean isKindleFire() { - return mIsKindleFire; - } - - public static DeviceUtils getInstance() { - if (instance == null) { - instance = new DeviceUtils(); - } - return instance; - } - - private DeviceUtils() { - mIsKindleFire = android.os.Build.MODEL.equalsIgnoreCase("kindle fire") ? true : false; - } - - /** - * Checks camera availability recursively based on API level. - * - * TODO: change "android.hardware.camera.front" and "android.hardware.camera.any" to - * {@link PackageManager#FEATURE_CAMERA_FRONT} and {@link PackageManager#FEATURE_CAMERA_ANY}, - * respectively, once they become accessible or minSdk version is incremented. - * - * @param context The context. - * @return Whether camera is available. - */ - public boolean hasCamera(Context context) { - final PackageManager pm = context.getPackageManager(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) - || pm.hasSystemFeature("android.hardware.camera.front"); - } - - return pm.hasSystemFeature("android.hardware.camera.any"); - } - - public String getDeviceName(Context context) { - String manufacturer = Build.MANUFACTURER; - String undecodedModel = Build.MODEL; - String model = null; - - try { - Properties prop = new Properties(); - InputStream fileStream; - // Read the device name from a precomplied list: - // see http://making.meetup.com/post/29648976176/human-readble-android-device-names - fileStream = context.getAssets().open("android_models.properties"); - prop.load(fileStream); - fileStream.close(); - String decodedModel = prop.getProperty(undecodedModel.replaceAll(" ", "_")); - if (decodedModel != null && !decodedModel.trim().equals("")) { - model = decodedModel; - } - } catch (IOException e) { - AppLog.e(T.UTILS, "Can't read `android_models.properties` file from assets, or it's in the wrong form.", e); - AppLog.d(T.UTILS, - "If you need more info about the file, please check the reference implementation available here: " - + "https://github.com/wordpress-mobile/WordPress-Android/blob/dd989429bd701a66bcba911de08f2e8d336798ef" - + "/WordPress/src/main/assets/android_models.properties"); - } - - if (model == null) { // Device model not found in the list - if (undecodedModel.startsWith(manufacturer)) { - model = capitalize(undecodedModel); - } else { - model = capitalize(manufacturer) + " " + undecodedModel; - } - } - return model; - } - - public boolean isDeviceLocked(Context context) { - KeyguardManager myKM = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); - return myKM.inKeyguardRestrictedInputMode(); - } - - /** - * Checks if the current device runtime is ARC which effectively means it is a chromebook. - * - * @param context The context. - * @return Whether the device is a chromebook. - */ - public boolean isChromebook(Context context) { - return context.getPackageManager().hasSystemFeature(APP_RUNTIME_ON_CHROME_FLAG); - } - - /** - * Checks if the device has a hardware keyboard - note this will return true for emulators - */ - public boolean hasHardwareKeyboard(@NonNull Context context) { - return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS; - } - - private String capitalize(String s) { - if (s == null || s.length() == 0) { - return ""; - } - char first = s.charAt(0); - if (Character.isUpperCase(first)) { - return s; - } else { - return Character.toUpperCase(first) + s.substring(1); - } - } - - // Taken and modified from https://stackoverflow.com/a/8133437 - public static String getTotalAvailableMemorySize() { - File internalMemoryPath = Environment.getDataDirectory(); - long availableInternal = availableSpaceAtFilePath(internalMemoryPath); - long availableExternal = 0L; - if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { - File externalStoragePath = Environment.getExternalStorageDirectory(); - availableExternal = availableSpaceAtFilePath(externalStoragePath); - } - return formatSize(availableInternal + availableExternal); - } - - private static long availableSpaceAtFilePath(File path) { - StatFs stat = new StatFs(path.getPath()); - long bytesAvailable; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { - return stat.getBlockSizeLong() * stat.getAvailableBlocksLong(); - } else { - //noinspection deprecation - Deprecated calls properly handled - bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks(); - } - return bytesAvailable; - } - - private static String formatSize(long size) { - String suffix = null; - - if (size >= 1024) { - suffix = "KB"; - size /= 1024; - if (size >= 1024) { - suffix = "MB"; - size /= 1024; - } - } - - StringBuilder resultBuffer = new StringBuilder(Long.toString(size)); - - int commaOffset = resultBuffer.length() - 3; - while (commaOffset > 0) { - resultBuffer.insert(commaOffset, ','); - commaOffset -= 3; - } - - if (suffix != null) { - resultBuffer.append(suffix); - } - return resultBuffer.toString(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java deleted file mode 100644 index 60877b7082f5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/DisplayUtils.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Point; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.Display; -import android.view.Window; -import android.view.WindowManager; - -public class DisplayUtils { - private DisplayUtils() { - throw new AssertionError(); - } - - public static boolean isLandscape(Context context) { - if (context == null) { - return false; - } - return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; - } - - public static Point getDisplayPixelSize(Context context) { - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - Point size = new Point(); - display.getSize(size); - return size; - } - - public static int getDisplayPixelWidth(Context context) { - Point size = getDisplayPixelSize(context); - return (size.x); - } - - public static int getDisplayPixelHeight(Context context) { - Point size = getDisplayPixelSize(context); - return (size.y); - } - - public static int getDisplayPixelWidth() { - return Resources.getSystem().getDisplayMetrics().widthPixels; - } - - public static float spToPx(Context context, float sp) { - DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - final float scale = displayMetrics.scaledDensity; - return sp * scale; - } - - public static int dpToPx(Context context, int dp) { - float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, - context.getResources().getDisplayMetrics()); - return (int) px; - } - - public static int pxToDp(Context context, int px) { - DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - return (int) ((px / displayMetrics.density) + 0.5); - } - - public static boolean isXLargeTablet(Context context) { - if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) - == Configuration.SCREENLAYOUT_SIZE_XLARGE) { - return true; - } - return false; - } - - public static boolean isTablet(Context context) { - return (context.getResources().getConfiguration().screenLayout - & Configuration.SCREENLAYOUT_SIZE_MASK) - == Configuration.SCREENLAYOUT_SIZE_LARGE; - } - - /** - * returns the height of the ActionBar if one is enabled - supports both the native ActionBar - * and ActionBarSherlock - http://stackoverflow.com/a/15476793/1673548 - */ - public static int getActionBarHeight(Context context) { - if (context == null) { - return 0; - } - TypedValue tv = new TypedValue(); - if (context.getTheme() != null - && context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { - return TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); - } - - // if we get this far, it's because the device doesn't support an ActionBar, - // so return the standard ActionBar height (48dp) - return dpToPx(context, 48); - } - - /** - * detect when FEATURE_ACTION_BAR_OVERLAY has been set - */ - public static boolean hasActionBarOverlay(Window window) { - return window.hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java deleted file mode 100644 index ec4e0b69313a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EditTextUtils.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.wordpress.android.util; - -import android.app.Activity; -import android.content.Context; -import android.text.TextUtils; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.EditText; -import android.widget.TextView; - -/** - * EditText utils - */ -public class EditTextUtils { - private EditTextUtils() { - throw new AssertionError(); - } - - /** - * returns non-null text string from passed TextView - */ - public static String getText(TextView textView) { - return (textView != null) ? textView.getText().toString() : ""; - } - - /** - * moves caret to end of text - */ - public static void moveToEnd(EditText edit) { - if (edit.getText() == null) { - return; - } - edit.setSelection(edit.getText().toString().length()); - } - - /** - * returns true if nothing has been entered into passed editor - */ - public static boolean isEmpty(EditText edit) { - return TextUtils.isEmpty(getText(edit)); - } - - /** - * hide the soft keyboard for the passed EditText - * - * @deprecated Use {@link ActivityUtils#hideKeyboard(Activity)} or {@link ActivityUtils#hideKeyboardForced(View)} - * instead. - */ - // TODO: Replace instances with ActivityUtils#showKeyboard(Activity) or ActivityUtils#showKeyboardForced(View) to - // consolidate similar methods and favor library version. - @Deprecated - public static void hideSoftInput(EditText edit) { - if (edit == null) { - return; - } - - InputMethodManager imm = getInputMethodManager(edit); - if (imm != null) { - imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); - } - } - - /** - * show the soft keyboard for the passed EditText - * - * @deprecated Use {@link ActivityUtils#showKeyboard(View)} instead. - */ - // TODO: Replace instances with ActivityUtils#showKeyboard(View) to consolidate similar methods and favor library - // version. - @Deprecated - public static void showSoftInput(EditText edit) { - if (edit == null) { - return; - } - - edit.requestFocus(); - - InputMethodManager imm = getInputMethodManager(edit); - if (imm != null) { - imm.showSoftInput(edit, InputMethodManager.SHOW_IMPLICIT); - } - } - - private static InputMethodManager getInputMethodManager(EditText edit) { - Context context = edit.getContext(); - return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java deleted file mode 100644 index 08d0d3417c2d..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/EmoticonsUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.wordpress.android.util; - -import android.text.Html; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.style.ForegroundColorSpan; -import android.text.style.ImageSpan; -import android.util.SparseArray; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES; - -public class EmoticonsUtils { - public static final int EMOTICON_COLOR = 0xFF21759B; - private static final boolean HAS_EMOJI = SDK_INT >= VERSION_CODES.JELLY_BEAN; - private static final Map WP_SMILIES; - public static final SparseArray WP_SMILIES_CODE_POINT_TO_TEXT; - - static { - Map smilies = new HashMap(); - smilies.put("icon_mrgreen.gif", HAS_EMOJI ? "\uD83D\uDE00" : ":mrgreen:"); - smilies.put("icon_neutral.gif", HAS_EMOJI ? "\uD83D\uDE14" : ":|"); - smilies.put("icon_twisted.gif", HAS_EMOJI ? "\uD83D\uDE16" : ":twisted:"); - smilies.put("icon_arrow.gif", HAS_EMOJI ? "\u27A1" : ":arrow:"); - smilies.put("icon_eek.gif", HAS_EMOJI ? "\uD83D\uDE32" : "8-O"); - smilies.put("icon_smile.gif", HAS_EMOJI ? "\uD83D\uDE0A" : ":)"); - smilies.put("icon_confused.gif", HAS_EMOJI ? "\uD83D\uDE15" : ":?"); - smilies.put("icon_cool.gif", HAS_EMOJI ? "\uD83D\uDE0A" : "8)"); - smilies.put("icon_evil.gif", HAS_EMOJI ? "\uD83D\uDE21" : ":evil:"); - smilies.put("icon_biggrin.gif", HAS_EMOJI ? "\uD83D\uDE03" : ":D"); - smilies.put("icon_idea.gif", HAS_EMOJI ? "\uD83D\uDCA1" : ":idea:"); - smilies.put("icon_redface.gif", HAS_EMOJI ? "\uD83D\uDE33" : ":oops:"); - smilies.put("icon_razz.gif", HAS_EMOJI ? "\uD83D\uDE1D" : ":P"); - smilies.put("icon_rolleyes.gif", HAS_EMOJI ? "\uD83D\uDE0F" : ":roll:"); - smilies.put("icon_wink.gif", HAS_EMOJI ? "\uD83D\uDE09" : ";)"); - smilies.put("icon_cry.gif", HAS_EMOJI ? "\uD83D\uDE22" : ":'("); - smilies.put("icon_surprised.gif", HAS_EMOJI ? "\uD83D\uDE32" : ":o"); - smilies.put("icon_lol.gif", HAS_EMOJI ? "\uD83D\uDE03" : ":lol:"); - smilies.put("icon_mad.gif", HAS_EMOJI ? "\uD83D\uDE21" : ":x"); - smilies.put("icon_sad.gif", HAS_EMOJI ? "\uD83D\uDE1E" : ":("); - smilies.put("icon_exclaim.gif", HAS_EMOJI ? "\u2757" : ":!:"); - smilies.put("icon_question.gif", HAS_EMOJI ? "\u2753" : ":?:"); - - WP_SMILIES = Collections.unmodifiableMap(smilies); - - WP_SMILIES_CODE_POINT_TO_TEXT = new SparseArray(20); - WP_SMILIES_CODE_POINT_TO_TEXT.put(10145, ":arrow:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128161, ":idea:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128512, ":mrgreen:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128515, ":D"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128522, ":)"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128521, ";)"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128532, ":|"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128533, ":?"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128534, ":twisted:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128542, ":("); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128545, ":evil:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128546, ":'("); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128562, ":o"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128563, ":oops:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(128527, ":roll:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(10071, ":!:"); - WP_SMILIES_CODE_POINT_TO_TEXT.put(10067, ":?:"); - } - - public static String lookupImageSmiley(String url) { - return lookupImageSmiley(url, ""); - } - - public static String lookupImageSmiley(String url, String ifNone) { - if (url == null) { - return ifNone; - } - String file = url.substring(url.lastIndexOf("/") + 1); - if (WP_SMILIES.containsKey(file)) { - return WP_SMILIES.get(file); - } - return ifNone; - } - - public static Spanned replaceEmoticonsWithEmoji(SpannableStringBuilder html) { - ImageSpan[] imgs = html.getSpans(0, html.length(), ImageSpan.class); - for (ImageSpan img : imgs) { - String emoticon = EmoticonsUtils.lookupImageSmiley(img.getSource()); - if (!emoticon.equals("")) { - int start = html.getSpanStart(img); - html.replace(start, html.getSpanEnd(img), emoticon); - html.setSpan(new ForegroundColorSpan(EMOTICON_COLOR), start, - start + emoticon.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - html.removeSpan(img); - } - } - return html; - } - - public static String replaceEmoticonsWithEmoji(final String text) { - if (text != null && text.contains("icon_")) { - final SpannableStringBuilder html = - (SpannableStringBuilder) replaceEmoticonsWithEmoji((SpannableStringBuilder) Html.fromHtml(text)); - // Html.toHtml() is used here rather than toString() since the latter strips html - return Html.toHtml(html); - } else { - return text; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java deleted file mode 100644 index cadee0b6906f..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FileUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -import java.io.File; - -public class FileUtils { - /** - * Returns the length of the file denoted by this abstract pathname. - * The return value is unspecified if this pathname denotes a directory. - * - * @return The length, in bytes, of the file denoted by this abstract - * pathname, or -1L if the file does not exist, or an - * exception is thrown accessing the file. - * Some operating systems may return 0L for pathnames - * denoting system-dependent entities such as devices or pipes. - */ - public static long length(String path) { - // File not found - File file = new File(path); - try { - if (!file.exists()) { - AppLog.w(AppLog.T.MEDIA, "Can't access the file. It doesn't exists anymore?"); - return -1L; - } - - return file.length(); - } catch (SecurityException e) { - AppLog.e(AppLog.T.MEDIA, "Can't access the file.", e); - return -1L; - } - } - - /** - * Given the full file path, or the filename with extension (i.e. my-picture.jpg), returns the filename part only - * (my-picture). - * - * @param filePath The path to the file or the full filename - * @return filename part only or null - */ - public static String getFileNameFromPath(String filePath) { - if (TextUtils.isEmpty(filePath)) { - return null; - } - if (filePath.contains("/")) { - if (filePath.lastIndexOf("/") + 1 >= filePath.length()) { - filePath = filePath.substring(0, filePath.length() - 1); - } - filePath = filePath.substring(filePath.lastIndexOf("/") + 1); - } - - String filename; - int dotPos = filePath.indexOf('.'); - if (dotPos > 0) { - filename = filePath.substring(0, dotPos); - } else { - filename = filePath; - } - return filename; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java deleted file mode 100644 index c2850e58d11c..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/FormatUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.wordpress.android.util; - -import java.text.DecimalFormat; -import java.text.NumberFormat; - -public class FormatUtils { - /* - * NumberFormat isn't synchronized, so a separate instance must be created for each thread - * http://developer.android.com/reference/java/text/NumberFormat.html - */ - private static final ThreadLocal INTEGER_INSTANCE = new ThreadLocal() { - @Override - protected NumberFormat initialValue() { - return NumberFormat.getIntegerInstance(); - } - }; - - private static final ThreadLocal DECIMAL_INSTANCE = new ThreadLocal() { - @Override - protected DecimalFormat initialValue() { - return (DecimalFormat) DecimalFormat.getInstance(); - } - }; - - /* - * returns the passed integer formatted with thousands-separators based on the current locale - */ - public static final String formatInt(int value) { - return INTEGER_INSTANCE.get().format(value).toString(); - } - - public static final String formatDecimal(int value) { - return DECIMAL_INSTANCE.get().format(value).toString(); - } - - /* - * returns the passed long formatted as an human readable filesize. Ex: 10 GB - * unitStrings is expected to be an array of all possible sizes from byte to TeraByte, in the current locale - */ - public static final String formatFileSize(long size, final String[] unitStrings) { - final double log1024 = Math.log10(1024); - if (size <= 0) { - return "0"; - } - int digitGroups = (int) (Math.log10(size) / log1024); - - NumberFormat f = NumberFormat.getInstance(); - if (f instanceof DecimalFormat) { - ((DecimalFormat) f).applyPattern("#,##0.#"); - } - return String.format(unitStrings[digitGroups], f.format(size / Math.pow(1024, digitGroups))); - } - - /* - * returns the passed double percentage (0 to 1) formatted as an human readable percentage. Ex: 0.25 returns 25% - */ - public static final String formatPercentage(double value) { - return formatPercentageLimit100(value, false); - } - - /* - * returns the passed double percentage (0 to 1) formatted as an human readable percentage. Ex: 0.251 returns 25.1% - * if limit100 is true, it limits the percentage to 100% - */ - public static final String formatPercentageLimit100(double value, boolean limit100) { - double limit = 1.0001; - - NumberFormat percentFormat = NumberFormat.getPercentInstance(); - percentFormat.setMaximumFractionDigits(1); - - if (limit100 && value > limit) { - value = limit; - } - - String percentage = percentFormat.format(value); - - return percentage; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java deleted file mode 100644 index 4b2fdd8875c5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GeocoderUtils.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.location.Address; -import android.location.Geocoder; - -import java.io.IOException; -import java.util.List; - -public final class GeocoderUtils { - private GeocoderUtils() { - throw new AssertionError(); - } - - public static Geocoder getGeocoder(Context context) { - // first make sure a Geocoder service exists on this device (requires API 9) - if (!Geocoder.isPresent()) { - return null; - } - - Geocoder gcd; - - try { - gcd = new Geocoder(context, LanguageUtils.getCurrentDeviceLanguage(context)); - } catch (NullPointerException cannotIstantiateEx) { - AppLog.e(AppLog.T.UTILS, "Cannot instantiate Geocoder", cannotIstantiateEx); - return null; - } - - return gcd; - } - - public static Address getAddressFromCoords(Context context, double latitude, double longitude) { - Address address = null; - List
    addresses = null; - - Geocoder gcd = getGeocoder(context); - - if (gcd == null) { - return null; - } - - try { - addresses = gcd.getFromLocation(latitude, longitude, 1); - } catch (IOException e) { - // may get "Unable to parse response from server" IOException here if Geocoder - // service is hit too frequently - AppLog.e(AppLog.T.UTILS, - "Unable to parse response from server. Is Geocoder service hitting the server too frequently?", - e - ); - } - - // addresses may be null or empty if network isn't connected - if (addresses != null && addresses.size() > 0) { - address = addresses.get(0); - } - - return address; - } - - public static Address getAddressFromLocationName(Context context, String locationName) { - int maxResults = 1; - Address address = null; - List
    addresses = null; - - Geocoder gcd = getGeocoder(context); - - if (gcd == null) { - return null; - } - - try { - addresses = gcd.getFromLocationName(locationName, maxResults); - } catch (IOException e) { - AppLog.e(AppLog.T.UTILS, "Failed to get coordinates from location", e); - } - - // addresses may be null or empty if network isn't connected - if (addresses != null && addresses.size() > 0) { - address = addresses.get(0); - } - - return address; - } - - public static String getLocationNameFromAddress(Address address) { - String locality = "", adminArea = "", country = ""; - if (address.getLocality() != null) { - locality = address.getLocality(); - } - - if (address.getAdminArea() != null) { - adminArea = address.getAdminArea(); - } - - if (address.getCountryName() != null) { - country = address.getCountryName(); - } - - return ((locality.equals("")) ? locality : locality + ", ") - + ((adminArea.equals("")) ? adminArea : adminArea + " ") + country; - } - - public static double[] getCoordsFromAddress(Address address) { - double[] coordinates = new double[2]; - - if (address.hasLatitude() && address.hasLongitude()) { - coordinates[0] = address.getLatitude(); - coordinates[1] = address.getLongitude(); - } - - return coordinates; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java deleted file mode 100644 index f650dea0dcf5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/GravatarUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -/** - * see https://en.gravatar.com/site/implement/images/ - */ -public class GravatarUtils { - // by default tell gravatar to respond to non-existent images with a 404 - this means - // it's up to the caller to catch the 404 and provide a suitable default image - private static final DefaultImage DEFAULT_GRAVATAR = DefaultImage.MYSTERY_MAN; - - public enum DefaultImage { - MYSTERY_MAN, - STATUS_404, - IDENTICON, - MONSTER, - WAVATAR, - RETRO, - BLANK; - - @Override - public String toString() { - switch (this) { - case MYSTERY_MAN: - return "mm"; - case STATUS_404: - return "404"; - case IDENTICON: - return "identicon"; - case MONSTER: - return "monsterid"; - case WAVATAR: - return "wavatar"; - case RETRO: - return "retro"; - default: - return "blank"; - } - } - } - - /* - * gravatars often contain the ?s= parameter which determines their size - detect this and - * replace it with a new ?s= parameter which requests the avatar at the exact size needed - */ - public static String fixGravatarUrl(final String imageUrl, int avatarSz) { - return fixGravatarUrl(imageUrl, avatarSz, DEFAULT_GRAVATAR); - } - - public static String fixGravatarUrl(final String imageUrl, int avatarSz, DefaultImage defaultImage) { - if (TextUtils.isEmpty(imageUrl)) { - return ""; - } - - // if this isn't a gravatar image, return as resized photon image url - if (!imageUrl.contains("gravatar.com")) { - return PhotonUtils.getPhotonImageUrl(imageUrl, avatarSz, avatarSz); - } - - // remove all other params, then add query string for size and default image - return UrlUtils.removeQuery(imageUrl) + "?s=" + avatarSz + "&d=" + defaultImage.toString(); - } - - public static String gravatarFromEmail(final String email, int size) { - return gravatarFromEmail(email, size, DEFAULT_GRAVATAR); - } - - public static String gravatarFromEmail(final String email, int size, DefaultImage defaultImage) { - return "http://gravatar.com/avatar/" - + StringUtils.getMd5Hash(StringUtils.notNullStr(email)) - + "?d=" + defaultImage.toString() - + "&size=" + Integer.toString(size); - } - - public static String blavatarFromUrl(final String url, int size) { - return blavatarFromUrl(url, size, DEFAULT_GRAVATAR); - } - - public static String blavatarFromUrl(final String url, int size, DefaultImage defaultImage) { - return "http://gravatar.com/blavatar/" - + StringUtils.getMd5Hash(UrlUtils.getHost(url)) - + "?d=" + defaultImage.toString() - + "&size=" + Integer.toString(size); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java deleted file mode 100644 index e91024b12587..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/HtmlUtils.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.res.Resources; -import android.text.Html; -import android.text.Html.ImageGetter; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextUtils; -import android.text.style.ForegroundColorSpan; -import android.text.style.QuoteSpan; - -import org.apache.commons.text.StringEscapeUtils; -import org.wordpress.android.util.helpers.WPHtmlTagHandler; -import org.wordpress.android.util.helpers.WPQuoteSpan; - -import static org.wordpress.android.util.AppLog.T.UTILS; - -public class HtmlUtils { - /** - * Removes html from the passed string - relies on Html.fromHtml which handles invalid HTML, - * but it's very slow, so avoid using this where performance is important - * @param text String containing html - * @return String without HTML - */ - public static String stripHtml(final String text) { - if (TextUtils.isEmpty(text)) { - return ""; - } - return Html.fromHtml(text).toString().trim(); - } - - /** - * This is much faster than stripHtml() but should only be used when we know the html is valid - * since the regex will be unpredictable with invalid html - * @param str String containing only valid html - * @return String without HTML - */ - public static String fastStripHtml(String str) { - if (TextUtils.isEmpty(str)) { - return str; - } - - // insert a line break before P tags unless the only one is at the start - if (str.lastIndexOf(" 0) { - str = str.replaceAll("", "\n

    "); - } - - // convert BR tags to line breaks - if (str.contains("", "\n"); - } - - // use regex to strip tags, then convert entities in the result - return trimStart(StringEscapeUtils.unescapeHtml4(str.replaceAll("<(.|\n)*?>", ""))); - } - - /* - * Same as apache.commons.lang.StringUtils.stripStart() but also removes non-breaking - * space (160) chars - */ - private static String trimStart(final String str) { - int strLen; - if (str == null || (strLen = str.length()) == 0) { - return ""; - } - int start = 0; - while (start != strLen && (Character.isWhitespace(str.charAt(start)) || str.charAt(start) == 160)) { - start++; - } - return str.substring(start); - } - - /** - * Converts an R.color.xxx resource to an HTML hex color - * @param context Android Context - * @param resId Android R.color.xxx - * @return A String HTML hex color code - */ - public static String colorResToHtmlColor(Context context, int resId) { - try { - return String.format("#%06X", 0xFFFFFF & context.getResources().getColor(resId)); - } catch (Resources.NotFoundException e) { - return "#000000"; - } - } - - /** - * Remove {@code } blocks from the passed string - added to project after noticing - * comments on posts that use the "Sociable" plugin ( http://wordpress.org/plugins/sociable/ ) - * may have a script block which contains {@code } followed by a CDATA section followed by {@code ,} - * all of which will show up if we don't strip it here. - * @see Wordpress Sociable Plugin - * @return String without {@code }, {@code } blocks followed by a CDATA section - * followed by {@code ,} - * @param text String containing script tags - */ - public static String stripScript(final String text) { - if (text == null) { - return null; - } - - StringBuilder sb = new StringBuilder(text); - int start = sb.indexOf(" -1) { - int end = sb.indexOf("", start); - if (end == -1) { - return sb.toString(); - } - sb.delete(start, end + 9); - start = sb.indexOf("}, {@code

      }, {@code
      } - * tags and replacing EmoticonsUtils with Emojis - * @param source - * @param imageGetter - */ - public static SpannableStringBuilder fromHtml(String source, ImageGetter imageGetter) { - source = replaceListTagsWithCustomTags(source); - SpannableStringBuilder html; - try { - html = (SpannableStringBuilder) Html.fromHtml(source, imageGetter, new WPHtmlTagHandler()); - } catch (RuntimeException runtimeException) { - // In case our tag handler fails - try { - html = (SpannableStringBuilder) Html.fromHtml(source, imageGetter, null); - } catch (IllegalArgumentException illegalArgumentException) { - // In case the html is missing a required parameter (for example: "src" missing from img) - html = new SpannableStringBuilder(""); - AppLog.w(UTILS, "Could not parse html"); - } - } - - EmoticonsUtils.replaceEmoticonsWithEmoji(html); - QuoteSpan[] spans = html.getSpans(0, html.length(), QuoteSpan.class); - for (QuoteSpan span : spans) { - html.setSpan(new WPQuoteSpan(), html.getSpanStart(span), html.getSpanEnd(span), html.getSpanFlags(span)); - html.setSpan(new ForegroundColorSpan(0xFF666666), html.getSpanStart(span), html.getSpanEnd(span), - html.getSpanFlags(span)); - html.removeSpan(span); - } - return html; - } - - private static String replaceListTagsWithCustomTags(String source) { - return source.replace("", "") - .replace("", "") - .replace("", ""); - } - - public static Spanned fromHtml(String source) { - return fromHtml(source, null); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java deleted file mode 100644 index d42cb0ba8aec..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ImageUtils.java +++ /dev/null @@ -1,898 +0,0 @@ -package org.wordpress.android.util; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.media.ExifInterface; -import android.media.MediaMetadataRetriever; -import android.media.ThumbnailUtils; -import android.net.Uri; -import android.os.AsyncTask; -import android.provider.MediaStore; -import android.text.TextUtils; -import android.util.Log; -import android.webkit.MimeTypeMap; -import android.widget.ImageView; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -public class ImageUtils { - public static int[] getImageSize(Uri uri, Context context) { - String path = null; - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - - if (uri.toString().contains("content:")) { - String[] projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA}; - Cursor cur = null; - try { - cur = context.getContentResolver().query(uri, projection, null, null, null); - if (cur != null && cur.moveToFirst()) { - int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA); - path = cur.getString(dataColumn); - } - } catch (IllegalStateException stateException) { - Log.d(ImageUtils.class.getName(), "IllegalStateException querying content:" + uri); - } finally { - SqlUtils.closeCursor(cur); - } - } - - if (TextUtils.isEmpty(path)) { - // The file isn't ContentResolver, or it can't be access by ContentResolver. Try to access the file - // directly. - path = uri.toString().replace("content://media", ""); - path = path.replace("file://", ""); - } - - BitmapFactory.decodeFile(path, options); - int imageHeight = options.outHeight; - int imageWidth = options.outWidth; - return new int[]{imageWidth, imageHeight}; - } - - // Read the orientation from ContentResolver. If it fails, read from EXIF. - public static int getImageOrientation(Context ctx, String filePath) { - if (TextUtils.isEmpty(filePath) || ctx == null) { - AppLog.w(AppLog.T.UTILS, "Can't read orientation. Passed context or file is null or empty."); - return 0; - } - Uri curStream; - int orientation = 0; - - // Remove file protocol - filePath = filePath.replace("file://", ""); - - if (!filePath.contains("content://")) { - curStream = Uri.parse("content://media" + filePath); - } else { - curStream = Uri.parse(filePath); - } - - try { - Cursor cur = ctx.getContentResolver() - .query(curStream, new String[]{MediaStore.Images.Media.ORIENTATION}, null, null, null); - if (cur != null) { - if (cur.moveToFirst()) { - orientation = cur.getInt(cur.getColumnIndex(MediaStore.Images.Media.ORIENTATION)); - } - cur.close(); - } - } catch (Exception errReadingContentResolver) { - AppLog.e(AppLog.T.UTILS, "Error reading orientation of the file: " + filePath, errReadingContentResolver); - } - - if (orientation == 0) { - orientation = getExifOrientation(filePath); - } - - return orientation; - } - - - private static int getExifOrientation(String path) { - if (TextUtils.isEmpty(path)) { - AppLog.w(AppLog.T.UTILS, "Can't read EXIF orientation. Passed path is empty."); - return 0; - } - ExifInterface exif; - try { - exif = new ExifInterface(path); - } catch (IOException e) { - AppLog.e(AppLog.T.UTILS, "Can't read EXIF orientation.", e); - return 0; - } - - int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0); - - switch (exifOrientation) { - case ExifInterface.ORIENTATION_NORMAL: - return 0; - case ExifInterface.ORIENTATION_ROTATE_90: - return 90; - case ExifInterface.ORIENTATION_ROTATE_180: - return 180; - case ExifInterface.ORIENTATION_ROTATE_270: - return 270; - default: - return 0; - } - } - - public static Bitmap downloadBitmap(String url) { - final DefaultHttpClient client = new DefaultHttpClient(); - - final HttpGet getRequest = new HttpGet(url); - - try { - HttpResponse response = client.execute(getRequest); - final int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - AppLog.w(AppLog.T.UTILS, "ImageDownloader Error " + statusCode - + " while retrieving bitmap from " + url); - return null; - } - - final HttpEntity entity = response.getEntity(); - if (entity != null) { - InputStream inputStream = null; - try { - inputStream = entity.getContent(); - return BitmapFactory.decodeStream(inputStream); - } finally { - if (inputStream != null) { - inputStream.close(); - } - entity.consumeContent(); - } - } - } catch (Exception e) { - // Could provide a more explicit error message for IOException or - // IllegalStateException - getRequest.abort(); - AppLog.w(AppLog.T.UTILS, "ImageDownloader Error while retrieving bitmap from " + url); - } - return null; - } - - /** From http://developer.android.com/training/displaying-bitmaps/load-bitmap.html **/ - public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { - // Raw height and width of image - final int height = options.outHeight; - final int width = options.outWidth; - int inSampleSize = 1; - - if (height > reqHeight || width > reqWidth) { - // Calculate ratios of height and width to requested height and width - final int heightRatio = Math.round((float) height / (float) reqHeight); - final int widthRatio = Math.round((float) width / (float) reqWidth); - - // Choose the smallest ratio as inSampleSize value, this will guarantee - // a final image with both dimensions larger than or equal to the - // requested height and width. - inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; - } - - return inSampleSize; - } - - - public interface BitmapWorkerCallback { - void onBitmapReady(String filePath, ImageView imageView, Bitmap bitmap); - } - - public static class BitmapWorkerTask extends AsyncTask { - private final WeakReference mImageViewReference; - private final BitmapWorkerCallback mCallback; - private int mTargetWidth; - private int mTargetHeight; - private String mPath; - - public BitmapWorkerTask(ImageView imageView, int width, int height, BitmapWorkerCallback callback) { - // Use a WeakReference to ensure the ImageView can be garbage collected - mImageViewReference = new WeakReference(imageView); - this.mCallback = callback; - mTargetWidth = width; - mTargetHeight = height; - } - - // Decode image in background. - @Override - protected Bitmap doInBackground(String... params) { - mPath = params[0]; - - BitmapFactory.Options bfo = new BitmapFactory.Options(); - bfo.inJustDecodeBounds = true; - BitmapFactory.decodeFile(mPath, bfo); - - bfo.inSampleSize = calculateInSampleSize(bfo, mTargetWidth, mTargetHeight); - bfo.inJustDecodeBounds = false; - - // get proper rotation - int bitmapWidth = 0; - int bitmapHeight = 0; - try { - File f = new File(mPath); - ExifInterface exif = new ExifInterface(f.getPath()); - int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); - int angle = 0; - if (orientation == ExifInterface.ORIENTATION_NORMAL) { // no need to rotate - return BitmapFactory.decodeFile(mPath, bfo); - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { - angle = 90; - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { - angle = 180; - } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { - angle = 270; - } - - Matrix mat = new Matrix(); - mat.postRotate(angle); - - try { - Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, bfo); - if (bmp == null) { - AppLog.e(AppLog.T.UTILS, "can't decode bitmap: " + f.getPath()); - return null; - } - bitmapWidth = bmp.getWidth(); - bitmapHeight = bmp.getHeight(); - return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true); - } catch (OutOfMemoryError oom) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error in setting image: " + oom); - } - } catch (IOException e) { - AppLog.e(AppLog.T.UTILS, "Error in setting image", e); - } - - return null; - } - - // Once complete, see if ImageView is still around and set bitmap. - @Override - protected void onPostExecute(Bitmap bitmap) { - if (mImageViewReference == null || bitmap == null) { - return; - } - - final ImageView imageView = mImageViewReference.get(); - - if (mCallback != null) { - mCallback.onBitmapReady(mPath, imageView, bitmap); - } - } - } - - public static String getTitleForWPImageSpan(Context ctx, String filePath) { - if (filePath == null) { - return null; - } - - Uri curStream; - String title; - - if (!filePath.contains("content://")) { - curStream = Uri.parse("content://media" + filePath); - } else { - curStream = Uri.parse(filePath); - } - - if (filePath.contains("video")) { - return "Video"; - } else { - String[] projection = new String[]{MediaStore.Images.Thumbnails.DATA}; - - Cursor cur; - try { - cur = ctx.getContentResolver().query(curStream, projection, null, null, null); - } catch (Exception e1) { - AppLog.e(AppLog.T.UTILS, e1); - return null; - } - File jpeg; - if (cur != null) { - String thumbData = ""; - if (cur.moveToFirst()) { - int dataColumn = cur.getColumnIndex(MediaStore.Images.Media.DATA); - thumbData = cur.getString(dataColumn); - } - cur.close(); - if (thumbData == null) { - return null; - } - jpeg = new File(thumbData); - } else { - String path = filePath.toString().replace("file://", ""); - jpeg = new File(path); - } - title = jpeg.getName(); - return title; - } - } - - /** - * Resizes an image to be placed in the Post Content Editor - * - * @return resized bitmap - */ - public static Bitmap getWPImageSpanThumbnailFromFilePath(Context context, String filePath, int targetWidth) { - if (filePath == null || context == null) { - return null; - } - - Uri curUri = Uri.parse(filePath); - - if (filePath.contains("video")) { - // Load the video thumbnail from the MediaStore - int videoId = 0; - try { - videoId = Integer.parseInt(curUri.getLastPathSegment()); - } catch (NumberFormatException e) { - } - ContentResolver crThumb = context.getContentResolver(); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = 1; - Bitmap videoThumbnail = - MediaStore.Video.Thumbnails.getThumbnail(crThumb, videoId, MediaStore.Video.Thumbnails.MINI_KIND, - options); - if (videoThumbnail != null) { - return getScaledBitmapAtLongestSide(videoThumbnail, targetWidth); - } else { - return null; - } - } else { - // Create resized bitmap - int rotation = getImageOrientation(context, filePath); - byte[] bytes = createThumbnailFromUri(context, curUri, targetWidth, null, rotation); - - if (bytes != null && bytes.length > 0) { - try { - Bitmap resizedBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - if (resizedBitmap != null) { - return getScaledBitmapAtLongestSide(resizedBitmap, targetWidth); - } - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error in setting image: " + e); - return null; - } - } - } - - return null; - } - - /* - Resize a bitmap to the targetSize on its longest side. - */ - public static Bitmap getScaledBitmapAtLongestSide(Bitmap bitmap, int targetSize) { - if (bitmap == null || bitmap.getWidth() <= targetSize && bitmap.getHeight() <= targetSize) { - // Do not resize. - return bitmap; - } - - int targetWidth, targetHeight; - if (bitmap.getHeight() > bitmap.getWidth()) { - // Resize portrait bitmap - targetHeight = targetSize; - float percentage = (float) targetSize / bitmap.getHeight(); - targetWidth = (int) (bitmap.getWidth() * percentage); - } else { - // Resize landscape or square image - targetWidth = targetSize; - float percentage = (float) targetSize / bitmap.getWidth(); - targetHeight = (int) (bitmap.getHeight() * percentage); - } - - return Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true); - } - - private static boolean resizeImageAndWriteToStream(Context context, - Uri imageUri, - String fileExtension, - int maxSize, - int orientation, - int quality, - OutputStream outStream) throws OutOfMemoryError, IOException { - String realFilePath = MediaUtils.getRealPathFromURI(context, imageUri); - - // get just the image bounds - BitmapFactory.Options optBounds = new BitmapFactory.Options(); - optBounds.inJustDecodeBounds = true; - - try { - BitmapFactory.decodeFile(realFilePath, optBounds); - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error while decoding the original image: " + realFilePath, e); - throw e; - } - - int scale = getScaleForResizing(maxSize, optBounds); - - BitmapFactory.Options optActual = new BitmapFactory.Options(); - optActual.inSampleSize = scale; - - // Get the roughly resized bitmap - final Bitmap bmpResized; - try { - bmpResized = BitmapFactory.decodeFile(realFilePath, optActual); - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError Error while decoding the original image: " + realFilePath, e); - throw e; - } - - if (bmpResized == null) { - AppLog.e(AppLog.T.UTILS, "Can't decode the resized picture."); - throw new IOException("Can't decode the resized picture."); - } - - // Resize the bitmap to exact size: calculate exact scale in order to resize accurately - float scaleBy = getScaleImageBy(maxSize, bmpResized); - - Matrix matrix = new Matrix(); - matrix.postScale(scaleBy, scaleBy); - - // apply orientation - if (orientation != 0) { - matrix.setRotate(orientation); - } - - Bitmap.CompressFormat fmt; - if (fileExtension != null - && (fileExtension.equals("png") || fileExtension.equals(".png"))) { - fmt = Bitmap.CompressFormat.PNG; - } else { - fmt = Bitmap.CompressFormat.JPEG; - } - - final Bitmap bmpRotated; - try { - bmpRotated = - Bitmap.createBitmap(bmpResized, 0, 0, bmpResized.getWidth(), bmpResized.getHeight(), matrix, true); - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.UTILS, "OutOfMemoryError while creating the resized bitmap", e); - throw e; - } catch (NullPointerException e) { - // See: https://github.com/wordpress-mobile/WordPress-Android/issues/1844 - AppLog.e(AppLog.T.UTILS, "Bitmap.createBitmap has thrown a NPE internally. This should never happen!", e); - throw e; - } - - if (bmpRotated == null) { - // Fix an issue where bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can - // return null. - AppLog.e(AppLog.T.UTILS, - "bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can return null."); - // See: https://github.com/wordpress-mobile/WordPress-Android/issues/1848 - throw new IOException( - "bmpRotated is null even if the documentation doesn't say Bitmap.createBitmap can return null."); - } - - return bmpRotated.compress(fmt, quality, outStream); - } - - /** - * Given the path to an image, compress and resize it. - * @param context the passed context - * @param path the path to the original image - * @param maxImageSize the maximum allowed width - * @param quality the encoder quality - * @return the path to the optimized image - */ - public static String optimizeImage(Context context, String path, int maxImageSize, int quality) { - if (context == null || TextUtils.isEmpty(path)) { - return path; - } - - File file = new File(path); - if (!file.exists()) { - return path; - } - - String mimeType = MediaUtils.getMediaFileMimeType(file); - if (mimeType.equals("image/gif")) { - // Don't rescale gifs to maintain their quality - return path; - } - - Uri srcImageUri = Uri.parse(path); - if (srcImageUri == null) { - return path; - } - - String fileName = MediaUtils.getMediaFileName(file, mimeType); - String fileExtension = MimeTypeMap.getFileExtensionFromUrl(fileName).toLowerCase(Locale.ROOT); - - int[] imageDimensions = getImageSize(srcImageUri, context); - int selectedMaxSize = Math.max(imageDimensions[0], imageDimensions[1]); - if (selectedMaxSize == 0) { - // Can't read the src dimensions. - return path; - } - - // do not optimize if original-size and 100% quality are set. - if (maxImageSize == Integer.MAX_VALUE && quality == 100) { - return path; - } - - if (selectedMaxSize > maxImageSize) { - selectedMaxSize = maxImageSize; - } - - int orientation = getImageOrientation(context, path); - - File resizedImageFile; - FileOutputStream out; - - try { - // try to re-use the same name as prefix of the temp file - String prefix = FileUtils.getFileNameFromPath(fileName); - - if (TextUtils.isEmpty(prefix) || prefix.length() < 3) { - // prefix must be at least 3 characters - prefix = "wp-image"; - } - - resizedImageFile = File.createTempFile(prefix, "." + fileExtension); - out = new FileOutputStream(resizedImageFile); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create the temp file on storage. Use the original picture instead."); - return path; - } catch (SecurityException e) { - AppLog.e(AppLog.T.MEDIA, - "Can't write the tmp file due to security restrictions. Use the original picture instead."); - return path; - } - - try { - boolean res = resizeImageAndWriteToStream(context, srcImageUri, fileExtension, selectedMaxSize, orientation, - quality, out); - if (!res) { - AppLog.w(AppLog.T.MEDIA, "Failed to compress the optimized image. Use the original picture instead."); - return path; - } - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create optimized image. Use the original picture instead."); - return path; - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.MEDIA, "Can't optimize the picture due to low memory. Use the original picture instead."); - return path; - } finally { - // close the stream - try { - out.flush(); - out.close(); - } catch (IOException e) { - // nope - } - } - - String tempFilePath = resizedImageFile.getPath(); - if (!TextUtils.isEmpty(tempFilePath)) { - return tempFilePath; - } else { - AppLog.e(AppLog.T.MEDIA, "Failed to create optimized image. Use the full picture instead."); - } - - return path; - } - - /** - * Generate a thumbnail from a video url. - * Note that this method could take time if network url. - * - * @param videoPath The path to the video on internet - * @param maxWidth the maximumWidth for the thumbnail - * @return the path to the picture on disk - */ - public static Bitmap getVideoFrameFromVideo(String videoPath, int maxWidth) { - return getVideoFrameFromVideo(videoPath, maxWidth, new HashMap()); - } - - /** - * Generate a thumbnail from a video url. - * Note that this method could take time if network url. - * - * @param videoPath The path to the video on internet - * @param maxWidth the maximumWidth for the thumbnail - * @param headers optional: HTTP headers map to add to the request if the video is remote - * @return the path to the picture on disk - */ - public static Bitmap getVideoFrameFromVideo(String videoPath, int maxWidth, Map headers) { - if (TextUtils.isEmpty(videoPath) || maxWidth <= 0) { - return null; - } - - if (new File(videoPath).exists()) { - // Local file - Bitmap thumb = - ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND); - return ImageUtils.getScaledBitmapAtLongestSide(thumb, maxWidth); - } - - // Not a local file. - MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); - Bitmap bitmap = null; - try { - mediaMetadataRetriever.setDataSource(videoPath, headers); - bitmap = mediaMetadataRetriever.getFrameAtTime(); - } catch (IllegalArgumentException e) { - AppLog.e(AppLog.T.MEDIA, "The passed video path is invalid: " + videoPath); - } catch (java.lang.RuntimeException e) { - // I've see this kind of error on one of my testing device - AppLog.e(AppLog.T.MEDIA, "The passed video path is invalid: " + videoPath); - } finally { - mediaMetadataRetriever.release(); - } - - if (bitmap == null) { - AppLog.w(AppLog.T.MEDIA, "Failed to retrieve frame from the passed video path: " + videoPath); - return null; - } - - return getScaledBitmapAtLongestSide(bitmap, maxWidth); - } - - /** - * nbradbury - 21-Feb-2014 - similar to createThumbnail but more efficient since it doesn't - * require passing the full-size image as an array of bytes[] - */ - public static byte[] createThumbnailFromUri(Context context, - Uri imageUri, - int maxWidth, - String fileExtension, - int orientation) { - if (context == null || imageUri == null || maxWidth <= 0) { - return null; - } - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - boolean res = - resizeImageAndWriteToStream(context, imageUri, fileExtension, maxWidth, orientation, 75, stream); - if (!res) { - AppLog.w(AppLog.T.MEDIA, "Failed to compress the resized image. Use the full picture instead."); - return null; - } - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create resized image. Use the full picture instead."); - return null; - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.MEDIA, "Can't resize the picture due to low memory. Use the full picture instead."); - return null; - } - - return stream.toByteArray(); - } - - public static Bitmap getCircularBitmap(final Bitmap bitmap) { - if (bitmap == null) { - return null; - } - - final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(output); - final Paint paint = new Paint(); - final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - final RectF rectF = new RectF(rect); - - paint.setAntiAlias(true); - canvas.drawARGB(0, 0, 0, 0); - paint.setColor(Color.RED); - canvas.drawOval(rectF, paint); - - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - canvas.drawBitmap(bitmap, rect, rect, paint); - - return output; - } - - /** - * Returns the passed bitmap with rounded corners - * @param bitmap - the bitmap to modify - * @param radius - the radius of the corners - * @param borderColor - the border to apply (use Color.TRANSPARENT for none) - */ - public static Bitmap getRoundedEdgeBitmap(final Bitmap bitmap, int radius, int borderColor) { - if (bitmap == null) { - return null; - } - - final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(output); - final Paint paint = new Paint(); - final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); - final RectF rectF = new RectF(rect); - - paint.setAntiAlias(true); - canvas.drawARGB(0, 0, 0, 0); - paint.setColor(Color.RED); - canvas.drawRoundRect(rectF, radius, radius, paint); - - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - canvas.drawBitmap(bitmap, rect, rect, paint); - - if (borderColor != Color.TRANSPARENT) { - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(1f); - paint.setColor(borderColor); - canvas.drawRoundRect(rectF, radius, radius, paint); - } - - return output; - } - - /** - * Get the maximum size a thumbnail can be to fit in either portrait or landscape orientations. - * @deprecated Use `getMaximumThumbnailSizeForEditor` available in MediaUtils class in Editors project - */ - public static int getMaximumThumbnailWidthForEditor(Context context) { - int maximumThumbnailWidthForEditor; - Point size = DisplayUtils.getDisplayPixelSize(context); - int screenWidth = size.x; - int screenHeight = size.y; - maximumThumbnailWidthForEditor = (screenWidth > screenHeight) ? screenHeight : screenWidth; - // 48dp of padding on each side so you can still place the cursor next to the image. - int padding = DisplayUtils.dpToPx(context, 48) * 2; - maximumThumbnailWidthForEditor -= padding; - return maximumThumbnailWidthForEditor; - } - - /** - * Given the path to an image, rotate it by using EXIF info - * @param context the passed context - * @param path the path to the original image - * @return the path to the rotated image or null - */ - public static String rotateImageIfNecessary(Context context, String path) { - if (context == null || TextUtils.isEmpty(path)) { - return null; - } - - File file = new File(path); - if (!file.exists()) { - return null; - } - - int orientation = getImageOrientation(context, path); - // Do not rotate portrait pictures - if (orientation == 0) { - return null; - } - - String mimeType = MediaUtils.getMediaFileMimeType(file); - if (mimeType.equals("image/gif")) { - // Don't rotate gifs to maintain their quality - return null; - } - - Uri srcImageUri = Uri.parse(path); - if (srcImageUri == null) { - return null; - } - - String fileName = MediaUtils.getMediaFileName(file, mimeType); - String fileExtension = MimeTypeMap.getFileExtensionFromUrl(fileName).toLowerCase(Locale.ROOT); - - int selectedWidth = getImageSize(srcImageUri, context)[0]; - if (selectedWidth == 0) { - // Can't read the src dimensions. - return null; - } - - File rotatedImageFile; - FileOutputStream out; - - try { - // try to re-use the same name as prefix of the temp file - String prefix = FileUtils.getFileNameFromPath(fileName); - - if (TextUtils.isEmpty(prefix) || prefix.length() < 3) { - // prefix must be at least 3 characters - prefix = "wp-image"; - } - - rotatedImageFile = File.createTempFile(prefix, "." + fileExtension); - out = new FileOutputStream(rotatedImageFile); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create the temp file on storage."); - return null; - } catch (SecurityException e) { - AppLog.e(AppLog.T.MEDIA, "Can't write the tmp file due to security restrictions."); - return null; - } - - try { - boolean res = - resizeImageAndWriteToStream(context, srcImageUri, fileExtension, selectedWidth, orientation, 85, - out); - if (!res) { - AppLog.w(AppLog.T.MEDIA, "Failed to compress the rotates image."); - return null; - } - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, "Failed to create rotated image."); - return null; - } catch (OutOfMemoryError e) { - AppLog.e(AppLog.T.MEDIA, "Can't rotate the picture due to low memory."); - return null; - } finally { - // close the stream - try { - out.flush(); - out.close(); - } catch (IOException e) { - // nope - } - } - - String tempFilePath = rotatedImageFile.getPath(); - if (!TextUtils.isEmpty(tempFilePath)) { - return tempFilePath; - } else { - AppLog.e(AppLog.T.MEDIA, "Failed to create rotated image."); - } - - return null; - } - - // determine correct scale value (should be power of 2) - // http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/3549021#3549021 - protected static int getScaleForResizing(int maxSize, BitmapFactory.Options optBounds) { - if (maxSize < 1) { - return 1; - } - - int maxDimension = Math.max(optBounds.outWidth, optBounds.outHeight); - int scale = 1; - - while (maxDimension / scale / 2 >= maxSize) { - scale *= 2; - } - return scale; - } - - private static float getScaleImageBy(float maxSize, Bitmap bmpResized) { - int divideBy = Math.max(bmpResized.getHeight(), bmpResized.getWidth()); - float percentage = maxSize / divideBy; - - float proportionateHeight = bmpResized.getHeight() * percentage; - int finalHeight = (int) Math.rint(proportionateHeight); - - float scaleWidth = maxSize / bmpResized.getWidth(); - float scaleHeight = ((float) finalHeight) / bmpResized.getHeight(); - - return Math.min(scaleWidth, scaleHeight); - } - - public static Rect getScaledBounds(int width, int height, int maxWidth) { - float xScale = Math.max(1.0f, (float) width / maxWidth); - return new Rect(0, 0, Math.round(width / xScale), Math.round(height / xScale)); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java deleted file mode 100644 index 7e4e177b392b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java +++ /dev/null @@ -1,262 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -import org.apache.commons.text.StringEscapeUtils; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.wordpress.android.util.AppLog.T; - -import java.util.ArrayList; - -public class JSONUtils { - private static final String QUERY_SEPERATOR = "."; - private static final String QUERY_ARRAY_INDEX_START = "["; - private static final String QUERY_ARRAY_INDEX_END = "]"; - private static final String QUERY_ARRAY_FIRST = "first"; - private static final String QUERY_ARRAY_LAST = "last"; - - private static final String JSON_NULL_STR = "null"; - private static final String TAG = "JSONUtils"; - - /** - * Given a JSONObject and a key path (e.g property.child) and a default it will - * traverse the object graph and pull out the desired property - */ - public static U queryJSON(JSONObject source, String query, U defaultObject) { - if (source == null) { - AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); - return defaultObject; - } - if (query == null) { - AppLog.e(T.UTILS, "Parameter query is null"); - return defaultObject; - } - int nextSeperator = query.indexOf(QUERY_SEPERATOR); - int nextIndexStart = query.indexOf(QUERY_ARRAY_INDEX_START); - if (nextSeperator == -1 && nextIndexStart == -1) { - // last item let's get it - try { - if (!source.has(query)) { - return defaultObject; - } - Object result = source.get(query); - if (result.getClass().isAssignableFrom(defaultObject.getClass())) { - return (U) result; - } else { - AppLog.w(T.UTILS, String.format( - "The returned object type %s is not assignable to the type %s. Using default!", - result.getClass(), defaultObject.getClass())); - return defaultObject; - } - } catch (java.lang.ClassCastException e) { - AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); - return defaultObject; - } catch (JSONException e) { - AppLog.e(T.UTILS, "Unable to get the Key from the input object. Key:" + query, e); - return defaultObject; - } - } - int endQuery; - if (nextSeperator == -1 || nextIndexStart == -1) { - endQuery = Math.max(nextSeperator, nextIndexStart); - } else { - endQuery = Math.min(nextSeperator, nextIndexStart); - } - String nextQuery = query.substring(endQuery); - String key = query.substring(0, endQuery); - try { - if (nextQuery.indexOf(QUERY_SEPERATOR) == 0) { - return queryJSON(source.getJSONObject(key), nextQuery.substring(1), defaultObject); - } else if (nextQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { - return queryJSON(source.getJSONArray(key), nextQuery, defaultObject); - } else if (!nextQuery.equals("")) { - return defaultObject; - } - Object result = source.get(key); - if (result.getClass().isAssignableFrom(defaultObject.getClass())) { - return (U) result; - } else { - AppLog.w(T.UTILS, - String.format("The returned object type %s is not assignable to the type %s. Using default!", - result.getClass(), defaultObject.getClass())); - return defaultObject; - } - } catch (java.lang.ClassCastException e) { - AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); - return defaultObject; - } catch (JSONException e) { - return defaultObject; - } - } - - /** - * Given a JSONArray and a query (e.g. [0].property) it will traverse the array and - * pull out the requested property. - * - * Acceptable indexes include negative numbers to reference items from the end of - * the list as well as "last" and "first" as more explicit references to "0" and "-1" - */ - public static U queryJSON(JSONArray source, String query, U defaultObject) { - if (source == null) { - AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); - return defaultObject; - } - if (query == null) { - AppLog.e(T.UTILS, "Parameter query is null"); - return defaultObject; - } - // query must start with [ have an index and then have ] - int indexStart = query.indexOf(QUERY_ARRAY_INDEX_START); - int indexEnd = query.indexOf(QUERY_ARRAY_INDEX_END); - if (indexStart == -1 || indexEnd == -1 || indexStart > indexEnd) { - return defaultObject; - } - // get "index" from "[index]" - String indexStr = query.substring(indexStart + 1, indexEnd); - int index; - if (indexStr.equals(QUERY_ARRAY_FIRST)) { - index = 0; - } else if (indexStr.equals(QUERY_ARRAY_LAST)) { - index = -1; - } else { - index = Integer.parseInt(indexStr); - } - if (index < 0) { - index = source.length() + index; - } - // copy remaining query - String remainingQuery = query.substring(indexEnd + 1); - try { - if (remainingQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { - return queryJSON(source.getJSONArray(index), remainingQuery, defaultObject); - } else if (remainingQuery.indexOf(QUERY_SEPERATOR) == 0) { - return queryJSON(source.getJSONObject(index), remainingQuery.substring(1), defaultObject); - } else if (!remainingQuery.equals("")) { - // TODO throw an exception since the query isn't valid? - AppLog.w(T.UTILS, String.format("Incorrect query for next object %s", remainingQuery)); - return defaultObject; - } - Object result = source.get(index); - if (result.getClass().isAssignableFrom(defaultObject.getClass())) { - return (U) result; - } else { - AppLog.w(T.UTILS, - String.format("The returned object type %s is not assignable to the type %s. Using default!", - result.getClass(), defaultObject.getClass())); - return defaultObject; - } - } catch (java.lang.ClassCastException e) { - AppLog.e(T.UTILS, "Unable to cast the object to " + defaultObject.getClass().getName(), e); - return defaultObject; - } catch (JSONException e) { - return defaultObject; - } - } - - /** - * Convert a JSONArray (expected to contain strings) in a string list - */ - public static ArrayList fromJSONArrayToStringList(JSONArray jsonArray) { - ArrayList stringList = new ArrayList(); - for (int i = 0; i < jsonArray.length(); i++) { - try { - stringList.add(jsonArray.getString(i)); - } catch (JSONException e) { - AppLog.e(T.UTILS, e); - } - } - return stringList; - } - - /** - * Convert a string list in a JSONArray - */ - public static JSONArray fromStringListToJSONArray(ArrayList stringList) { - JSONArray jsonArray = new JSONArray(); - if (stringList != null) { - for (int i = 0; i < stringList.size(); i++) { - jsonArray.put(stringList.get(i)); - } - } - return jsonArray; - } - - /* - * wrapper for JSONObject.optString() which handles "null" values - */ - public static String getString(JSONObject json, String name) { - String value = json.optString(name); - // return empty string for "null" - if (JSON_NULL_STR.equals(value)) { - return ""; - } - return value; - } - - /* - * use with strings that contain HTML entities - */ - public static String getStringDecoded(JSONObject json, String name) { - String value = getString(json, name); - return StringEscapeUtils.unescapeHtml4(value); - } - - /* - * replacement for JSONObject.optBoolean() - optBoolean() only checks for "true" and "false", - * but our API sometimes uses "0" to denote false - */ - public static boolean getBool(JSONObject json, String name) { - String value = getString(json, name); - if (TextUtils.isEmpty(value)) { - return false; - } - if (value.equals("0")) { - return false; - } - if (value.equalsIgnoreCase("false")) { - return false; - } - if (value.equalsIgnoreCase("no")) { - return false; - } - return true; - } - - /* - * returns the JSONObject child of the passed parent that matches the passed query - * this is basically an "optJSONObject" that supports nested queries, for example: - * - * getJSONChild("meta/data/site") - * - * would find this: - * - * "meta": { - * "data": { - * "site": { - * "ID": 3584907, - * "name": "WordPress.com News", - * } - * } - * } - */ - public static JSONObject getJSONChild(final JSONObject jsonParent, final String query) { - if (jsonParent == null || TextUtils.isEmpty(query)) { - return null; - } - String[] names = query.split("/"); - JSONObject jsonChild = null; - for (int i = 0; i < names.length; i++) { - if (jsonChild == null) { - jsonChild = jsonParent.optJSONObject(names[i]); - } else { - jsonChild = jsonChild.optJSONObject(names[i]); - } - if (jsonChild == null) { - return null; - } - } - return jsonChild; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java deleted file mode 100644 index 1deaa603efd7..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/LanguageUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -import androidx.annotation.Nullable; - -import java.util.Locale; - -/** - * Methods for dealing with i18n messages - */ -public class LanguageUtils { - /** - * @deprecated Use {@link #getCurrentDeviceLanguage()}. As of API 25, setting the locale by updating the - * configuration on the resources object was deprecated, so this method stopped working for newer versions - * of Android. The current active locale should always be set in {@link Locale#getDefault()}. When manually - * setting the active locale, the developer should set it in {@link Locale#setDefault(Locale)}. - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - public static Locale getCurrentDeviceLanguage(@Nullable Context context) { - return getCurrentDeviceLanguage(); - } - - @SuppressWarnings("WeakerAccess") - public static Locale getCurrentDeviceLanguage() { - return Locale.getDefault(); - } - - /** - * @deprecated Use {@link #getCurrentDeviceLanguageCode()}. - */ - @SuppressWarnings("WeakerAccess,DeprecatedIsStillUsed") - @Deprecated - public static String getCurrentDeviceLanguageCode(@Nullable Context context) { - return getCurrentDeviceLanguageCode(); - } - - @SuppressWarnings("WeakerAccess") - public static String getCurrentDeviceLanguageCode() { - return getCurrentDeviceLanguage().toString(); - } - - public static String getPatchedCurrentDeviceLanguage(Context context) { - return patchDeviceLanguageCode(getCurrentDeviceLanguageCode(context)); - } - - /** - * Patches a deviceLanguageCode if any of deprecated values iw, id, or yi - */ - @SuppressWarnings("WeakerAccess") - public static String patchDeviceLanguageCode(String deviceLanguageCode) { - String patchedCode = deviceLanguageCode; - /* -

      Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language - * code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This - * rewriting happens even if you construct your own {@code Locale} object, not just for - * instances returned by the various lookup methods. - */ - if (deviceLanguageCode != null) { - if (deviceLanguageCode.startsWith("iw")) { - patchedCode = deviceLanguageCode.replace("iw", "he"); - } else if (deviceLanguageCode.startsWith("in")) { - patchedCode = deviceLanguageCode.replace("in", "id"); - } else if (deviceLanguageCode.startsWith("ji")) { - patchedCode = deviceLanguageCode.replace("ji", "yi"); - } - } - - return patchedCode; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java deleted file mode 100644 index 30d38e36c514..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ListUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.wordpress.android.util; - -import androidx.annotation.Nullable; - -import org.apache.commons.lang3.ArrayUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ListUtils { - @Nullable - public static ArrayList fromLongArray(long[] array) { - if (array == null) { - return null; - } - Long[] longObjects = ArrayUtils.toObject(array); - return new ArrayList<>(Arrays.asList(longObjects)); - } - - @Nullable - public static long[] toLongArray(List list) { - if (list == null) { - return null; - } - Long[] array = list.toArray(new Long[list.size()]); - return ArrayUtils.toPrimitive(array); - } - - @Nullable - public static ArrayList fromIntArray(int[] array) { - if (array == null) { - return null; - } - Integer[] intObjects = ArrayUtils.toObject(array); - return new ArrayList<>(Arrays.asList(intObjects)); - } - - @Nullable - public static int[] toIntArray(List list) { - if (list == null) { - return null; - } - Integer[] array = list.toArray(new Integer[list.size()]); - return ArrayUtils.toPrimitive(array); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java deleted file mode 100644 index 4345a4b22cfe..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MapUtils.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.wordpress.android.util; - -import java.util.Date; -import java.util.Map; - -/** - * wrappers for extracting values from a Map object - */ -public class MapUtils { - /* - * returns a String value for the passed key in the passed map - * always returns "" instead of null - */ - public static String getMapStr(final Map map, final String key) { - if (map == null || key == null || !map.containsKey(key) || map.get(key) == null) { - return ""; - } - return map.get(key).toString(); - } - - /* - * returns an int value for the passed key in the passed map - * defaultValue is returned if key doesn't exist or isn't a number - */ - public static int getMapInt(final Map map, final String key) { - return getMapInt(map, key, 0); - } - - public static int getMapInt(final Map map, final String key, int defaultValue) { - try { - return Integer.parseInt(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * long version of above - */ - public static long getMapLong(final Map map, final String key) { - return getMapLong(map, key, 0); - } - - public static long getMapLong(final Map map, final String key, long defaultValue) { - try { - return Long.parseLong(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * float version of above - */ - public static float getMapFloat(final Map map, final String key) { - return getMapFloat(map, key, 0); - } - - public static float getMapFloat(final Map map, final String key, float defaultValue) { - try { - return Float.parseFloat(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * double version of above - */ - public static double getMapDouble(final Map map, final String key) { - return getMapDouble(map, key, 0); - } - - public static double getMapDouble(final Map map, final String key, double defaultValue) { - try { - return Double.parseDouble(getMapStr(map, key)); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /* - * returns a date object from the passed key in the passed map - * returns null if key doesn't exist or isn't a date - */ - public static Date getMapDate(final Map map, final String key) { - if (map == null || key == null || !map.containsKey(key)) { - return null; - } - try { - return (Date) map.get(key); - } catch (ClassCastException e) { - return null; - } - } - - /* - * returns a boolean value from the passed key in the passed map - * returns true unless key doesn't exist, or the value is "0" or "false" - */ - public static boolean getMapBool(final Map map, final String key) { - String value = getMapStr(map, key); - if (value.isEmpty()) { - return false; - } - if (value.startsWith("0")) { // handles "0" and "0.0" - return false; - } - if (value.equalsIgnoreCase("false")) { - return false; - } - // all other values are assume to be true - return true; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java deleted file mode 100644 index 88ec0f53f755..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/MediaUtils.java +++ /dev/null @@ -1,571 +0,0 @@ -package org.wordpress.android.util; - -import android.annotation.TargetApi; -import android.content.ContentUris; -import android.content.Context; -import android.content.CursorLoader; -import android.database.Cursor; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import androidx.annotation.Nullable; - -import org.wordpress.android.util.AppLog.T; - -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class MediaUtils { - private static final int DEFAULT_MAX_IMAGE_WIDTH = 1024; - private static final Pattern FILE_EXISTS_PATTERN = Pattern.compile("(.*?)(-([0-9]+))?(\\..*$)?"); - - public static boolean isValidImage(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".png") || url.endsWith(".jpg") || url.endsWith(".jpeg") || url.endsWith(".gif"); - } - - public static boolean isDocument(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".doc") || url.endsWith(".docx") || url.endsWith(".odt") || url.endsWith(".pdf"); - } - - public static boolean isPowerpoint(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".ppt") || url.endsWith(".pptx") || url.endsWith(".pps") || url.endsWith(".ppsx") - || url.endsWith(".key"); - } - - public static boolean isSpreadsheet(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".xls") || url.endsWith(".xlsx"); - } - - public static boolean isVideo(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".ogv") || url.endsWith(".mp4") || url.endsWith(".m4v") || url.endsWith(".mov") - || url.endsWith(".wmv") || url.endsWith(".avi") || url.endsWith(".mpg") || url.endsWith(".3gp") - || url.endsWith(".3g2") || url.contains("video"); - } - - public static boolean isAudio(String url) { - if (url == null) { - return false; - } - url = url.toLowerCase(Locale.ROOT); - return url.endsWith(".mp3") || url.endsWith(".ogg") || url.endsWith(".wav") || url.endsWith(".wma") - || url.endsWith(".aiff") || url.endsWith(".aif") || url.endsWith(".aac") || url.endsWith(".m4a"); - } - - public static boolean isGif(String url) { - return "gif".equals(MimeTypeMap.getFileExtensionFromUrl(url)); - } - - public static boolean isLocalFile(String state) { - if (state == null) { - return false; - } - - return state.equalsIgnoreCase("queued") - || state.equalsIgnoreCase("uploading") - || state.equalsIgnoreCase("retry") - || state.equalsIgnoreCase("failed"); - } - - public static Uri getLastRecordedVideoUri(Context appContext) { - String[] proj = {MediaStore.Video.Media._ID}; - Uri contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - String sortOrder = MediaStore.Video.VideoColumns.DATE_TAKEN + " DESC"; - CursorLoader loader = new CursorLoader(appContext, contentUri, proj, null, null, sortOrder); - Cursor cursor = loader.loadInBackground(); - cursor.moveToFirst(); - long value = cursor.getLong(0); - SqlUtils.closeCursor(cursor); - - return Uri.parse(contentUri.toString() + "/" + value); - } - - /** - * Get image max size setting from the image max size setting string. This string can be an int, in this case it's - * the maximum image width defined by the site. - * Examples: - * "1000" will return 1000 - * "Original Size" will return Integer.MAX_VALUE - * "Largeur originale" will return Integer.MAX_VALUE - * null will return Integer.MAX_VALUE - * @param imageMaxSizeSiteSettingString Image max size site setting string - * @return Integer.MAX_VALUE if image width is not defined or invalid, maximum image width in other cases. - */ - public static int getImageMaxSizeSettingFromString(String imageMaxSizeSiteSettingString) { - if (imageMaxSizeSiteSettingString == null) { - return Integer.MAX_VALUE; - } - try { - return Integer.valueOf(imageMaxSizeSiteSettingString); - } catch (NumberFormatException e) { - return Integer.MAX_VALUE; - } - } - - /** - * Calculate and return the maximum allowed image width by comparing the width of the image at its full size with - * the maximum upload width set in the blog settings - * @param imageSize the image's natural (full) width - * @param imageMaxSizeSiteSettingString the maximum upload width set in the site settings - * @return maximum allowed image width - */ - public static int getMaximumImageSize(int imageSize, String imageMaxSizeSiteSettingString) { - int imageMaxSizeBlogSetting = getImageMaxSizeSettingFromString(imageMaxSizeSiteSettingString); - int imageWidthPictureSetting = imageSize == 0 ? Integer.MAX_VALUE : imageSize; - - if (Math.min(imageWidthPictureSetting, imageMaxSizeBlogSetting) == Integer.MAX_VALUE) { - // Default value in case of errors reading the picture size or the blog settings is set to Original size - return DEFAULT_MAX_IMAGE_WIDTH; - } else { - return Math.min(imageWidthPictureSetting, imageMaxSizeBlogSetting); - } - } - - public static int getMaximumImageSize(Context context, Uri curStream, String imageMaxSizeBlogSettingString) { - int[] dimensions = ImageUtils.getImageSize(curStream, context); - return getMaximumImageSize(dimensions[0], imageMaxSizeBlogSettingString); - } - - public static boolean isInMediaStore(Uri mediaUri) { - // Check if the image is externally hosted (Picasa/Google Photos for example) - return mediaUri != null && mediaUri.toString().startsWith("content://media/"); - } - - public static boolean isFile(Uri mediaUri) { - return mediaUri != null && mediaUri.toString().startsWith("file://"); - } - - public static @Nullable String getFilenameFromURI(Context context, Uri uri) { - Cursor cursor = context.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, - null, null, null); - try { - String result = null; - if (cursor != null && cursor.moveToFirst()) { - int columnIndexDisplayName = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); - if (columnIndexDisplayName == -1) { - return null; - } - result = cursor.getString(columnIndexDisplayName); - } - return result; - } catch (IllegalArgumentException exception) { - // This exception happens when Google Photos tries to retrieve latitude for videos even if it's not - // a requested column - return null; - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - /* - * Some media providers (eg. Google Photos) give us a limited access to media files just so we can copy them and - * then they revoke the access. Copying these files must be performed on the UI thread, otherwise the access might - * be revoked before the action completes. See https://github.com/wordpress-mobile/WordPress-Android/issues/5818 - */ - public static Uri downloadExternalMedia(Context context, Uri imageUri) { - if (context == null || imageUri == null) { - return null; - } - String mimeType = UrlUtils.getUrlMimeType(imageUri.toString()); - File cacheDir = context.getCacheDir(); - - if (cacheDir != null && !cacheDir.exists()) { - cacheDir.mkdirs(); - } - try { - InputStream input; - // Download the file - if (imageUri.toString().startsWith("content://")) { - input = context.getContentResolver().openInputStream(imageUri); - if (input == null) { - AppLog.e(T.UTILS, "openInputStream returned null"); - return null; - } - } else { - input = new URL(imageUri.toString()).openStream(); - } - - String fileName = getFilenameFromURI(context, imageUri); - if (TextUtils.isEmpty(fileName)) { - fileName = generateTimeStampedFileName(mimeType); - } - - File f = getUniqueCacheFileForName(fileName, cacheDir, mimeType); - - OutputStream output = new FileOutputStream(f); - - byte[] data = new byte[1024]; - int count; - while ((count = input.read(data)) != -1) { - output.write(data, 0, count); - } - - output.flush(); - output.close(); - input.close(); - - return Uri.fromFile(f); - } catch (IOException e) { - AppLog.e(T.UTILS, e); - } - - return null; - } - - private static File getUniqueCacheFileForName(String fileName, File cacheDir, String mimeType) { - File file = new File(cacheDir, fileName); - - while (file.exists()) { - Matcher matcher = FILE_EXISTS_PATTERN.matcher(fileName); - if (matcher.matches()) { - String baseFileName = matcher.group(1); - String existingDuplicationNumber = matcher.group(3); - String fileType = StringUtils.notNullStr(matcher.group(4)); - - if (existingDuplicationNumber == null) { - // Not a copy already - fileName = baseFileName + "-1" + fileType; - } else { - fileName = baseFileName + "-" + (StringUtils.stringToInt(existingDuplicationNumber) + 1) + fileType; - } - } else { - // Shouldn't happen, but in case our match fails fall back to timestamped file name - fileName = generateTimeStampedFileName(mimeType); - } - file = new File(cacheDir, fileName); - } - return file; - } - - public static String generateTimeStampedFileName(String mimeType) { - return "wp-" + System.currentTimeMillis() + "." + getExtensionForMimeType(mimeType); - } - - public static String getMimeTypeOfInputStream(InputStream stream) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(stream, null, options); - return options.outMimeType; - } - - public static String getMediaFileMimeType(File mediaFile) { - String originalFileName = mediaFile.getName().toLowerCase(Locale.ROOT); - String mimeType = UrlUtils.getUrlMimeType(originalFileName); - - if (TextUtils.isEmpty(mimeType)) { - try { - String filePathForGuessingMime; - if (mediaFile.getPath().contains("://")) { - filePathForGuessingMime = Uri.encode(mediaFile.getPath(), ":/"); - } else { - filePathForGuessingMime = "file://" + Uri.encode(mediaFile.getPath(), "/"); - } - URL urlForGuessingMime = new URL(filePathForGuessingMime); - URLConnection uc = urlForGuessingMime.openConnection(); - String guessedContentType = null; - try { - guessedContentType = - uc.getContentType(); // internally calls guessContentTypeFromName(url.getFile()); and - // guessContentTypeFromStream(is); - } catch (StringIndexOutOfBoundsException e) { - // Ref: https://github.com/wordpress-mobile/WordPress-Android/issues/5699 - AppLog.e(AppLog.T.MEDIA, "Error getting the content type for " + mediaFile.getPath() - + " by using URLConnection.getContentType", e); - } - // check if returned "content/unknown" - if (!TextUtils.isEmpty(guessedContentType) && !guessedContentType.equals("content/unknown")) { - mimeType = guessedContentType; - } - } catch (MalformedURLException e) { - AppLog.e(AppLog.T.MEDIA, - "MalformedURLException while trying to guess the content type for the file here " + mediaFile - .getPath() + " with URLConnection", e); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, - "Error while trying to guess the content type for the file here " + mediaFile.getPath() - + " with URLConnection", e); - } - } - - // No mimeType yet? Try to decode the image and get the mimeType from there - if (TextUtils.isEmpty(mimeType)) { - try { - DataInputStream inputStream = new DataInputStream(new FileInputStream(mediaFile)); - String mimeTypeFromStream = getMimeTypeOfInputStream(inputStream); - if (!TextUtils.isEmpty(mimeTypeFromStream)) { - mimeType = mimeTypeFromStream; - } - inputStream.close(); - } catch (FileNotFoundException e) { - AppLog.e(AppLog.T.MEDIA, - "FileNotFoundException while trying to guess the content type for the file " + mediaFile - .getPath(), e); - } catch (IOException e) { - AppLog.e(AppLog.T.MEDIA, - "IOException while trying to guess the content type for the file " + mediaFile.getPath(), e); - } - } - - if (TextUtils.isEmpty(mimeType)) { - mimeType = ""; - } else { - if (mimeType.equalsIgnoreCase("video/mp4v-es")) { // Fixes #533. See: http://tools.ietf.org/html/rfc3016 - mimeType = "video/mp4"; - } - } - - return mimeType; - } - - public static String getMediaFileName(File mediaFile, String mimeType) { - String originalFileName = mediaFile.getName().toLowerCase(Locale.ROOT); - String extension = MimeTypeMap.getFileExtensionFromUrl(originalFileName); - if (!TextUtils.isEmpty(extension)) { // File name already has the extension in it - return originalFileName; - } - - if (!TextUtils.isEmpty(mimeType)) { // try to get the extension from mimeType - String fileExtension = getExtensionForMimeType(mimeType); - if (!TextUtils.isEmpty(fileExtension)) { - originalFileName += "." + fileExtension; - } - } else { - // No mimetype and no extension!! - AppLog.e(AppLog.T.API, "No mimetype and no extension for " + mediaFile.getPath()); - } - - return originalFileName; - } - - public static String getExtensionForMimeType(String mimeType) { - if (TextUtils.isEmpty(mimeType)) { - return ""; - } - - MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); - String fileExtensionFromMimeType = mimeTypeMap.getExtensionFromMimeType(mimeType); - if (TextUtils.isEmpty(fileExtensionFromMimeType)) { - // We're still without an extension - split the mime type and retrieve it - String[] split = mimeType.split("/"); - fileExtensionFromMimeType = split.length > 1 ? split[1] : split[0]; - } - - return fileExtensionFromMimeType.toLowerCase(Locale.ROOT); - } - - public static String getRealPathFromURI(final Context context, Uri uri) { - String path; - if ("content".equals(uri.getScheme())) { - path = MediaUtils.getPath(context, uri); - } else if ("file".equals(uri.getScheme())) { - path = uri.getPath(); - } else { - path = uri.toString(); - } - - return path; - } - - /** - * Get a file path from a Uri. This will get the the path for Storage Access - * Framework Documents, as well as the _data field for the MediaStore and - * other file-based ContentProviders. - * - * Based on paulburke's solution for aFileChooser - https://github.com/iPaulPro/aFileChooser - * - * @param context The context. - * @param uri The Uri to query. - */ - private static String getPath(final Context context, final Uri uri) { - String path = getDocumentProviderPathKitkatOrHigher(context, uri); - - if (path != null) { - return path; - } - - // MediaStore (and general) - if ("content".equalsIgnoreCase(uri.getScheme())) { - return getDataColumn(context, uri, null, null); - } else if ("file".equalsIgnoreCase(uri.getScheme())) { // File - return uri.getPath(); - } - - return null; - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - private static String getDocumentProviderPathKitkatOrHigher(final Context context, final Uri uri) { - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - // ExternalStorageProvider - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } else if (isDownloadsDocument(uri)) { - String id = DocumentsContract.getDocumentId(uri); - - if (id != null && id.startsWith("raw:")) { - return id.substring(4); - } - - // https://github.com/Javernaut/WhatTheCodec/issues/2 - if (id != null && id.startsWith("msf:")) { - id = id.substring(4); - } - - String[] contentUriPrefixesToTry = new String[]{ - "content://downloads/public_downloads", - "content://downloads/my_downloads", - "content://downloads/all_downloads" - }; - - for (String contentUriPrefix : contentUriPrefixesToTry) { - Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id)); - try { - String path = getDataColumn(context, contentUri, null, null); - if (path != null) { - return path; - } - } catch (Exception e) { - AppLog.e(AppLog.T.UTILS, "Error reading _data column for URI: " + contentUri, e); - } - } - return downloadExternalMedia(context, uri).getPath(); - } else if (isMediaDocument(uri)) { // MediaProvider - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = MediaStore.MediaColumns._ID + "=?"; - - final String[] selectionArgs = new String[]{ - split[1] - }; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - - return null; - } - - /** - * Get the value of the data column for this Uri. This is useful for - * MediaStore Uris, and other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @param selection (Optional) Filter used in the query. - * @param selectionArgs (Optional) Selection arguments used in the query. - * @return The value of the _data column, which is typically a file path. - */ - public static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - Cursor cursor = null; - final String column = MediaStore.MediaColumns.DATA; - - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); - if (cursor != null && cursor.moveToFirst()) { - final int columnIndex = cursor.getColumnIndex(column); - if (columnIndex != -1) { - return cursor.getString(columnIndex); - } - } - } catch (SecurityException errReadingContentResolver) { - AppLog.e(AppLog.T.UTILS, "Error reading _data column for URI: " + uri, errReadingContentResolver); - } finally { - if (cursor != null) { - cursor.close(); - } - } - return null; - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is ExternalStorageProvider. - */ - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is DownloadsProvider. - */ - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is MediaProvider. - */ - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java deleted file mode 100644 index 83a2cb20066e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/NetworkUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.wordpress.android.util; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.Build; -import android.os.Build.VERSION_CODES; -import android.provider.Settings; - -/** - * requires android.permission.ACCESS_NETWORK_STATE - */ -@SuppressLint("MissingPermission") -public class NetworkUtils { - public static final int TYPE_UNKNOWN = -1; - - /** - * returns information on the active network connection - */ - @SuppressLint("MissingPermission") - public static NetworkInfo getActiveNetworkInfo(Context context) { - if (context == null) { - return null; - } - ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (cm == null) { - return null; - } - // note that this may return null if no network is currently active - return cm.getActiveNetworkInfo(); - } - - /** - * returns the ConnectivityManager.TYPE_xxx if there's an active connection, otherwise - * returns TYPE_UNKNOWN - */ - private static int getActiveNetworkType(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - if (info == null || !info.isConnected()) { - return TYPE_UNKNOWN; - } - return info.getType(); - } - - /** - * returns true if a network connection is available - */ - public static boolean isNetworkAvailable(Context context) { - NetworkInfo info = getActiveNetworkInfo(context); - return (info != null && info.isConnected()); - } - - /** - * returns true if the user is connected to WiFi - */ - public static boolean isWiFiConnected(Context context) { - return (getActiveNetworkType(context) == ConnectivityManager.TYPE_WIFI); - } - - /** - * returns true if the user is connected with the mobile data connection - */ - public static boolean isMobileConnected(Context context) { - int networkType = getActiveNetworkType(context); - return (networkType == ConnectivityManager.TYPE_MOBILE - || networkType == ConnectivityManager.TYPE_MOBILE_DUN); - } - - /** - * returns true if airplane mode has been enabled - */ - @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) - @SuppressWarnings("deprecation") - public static boolean isAirplaneModeOn(Context context) { - // prior to JellyBean 4.2 this was Settings.System.AIRPLANE_MODE_ON, JellyBean 4.2 - // moved it to Settings.Global - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { - return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0; - } else { - return Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0; - } - } - - /** - * returns true if there's an active network connection, otherwise displays a toast error - * and returns false - */ - public static boolean checkConnection(Context context) { - if (context == null) { - return false; - } - if (isNetworkAvailable(context)) { - return true; - } - ToastUtils.showToast(context, R.string.no_network_message); - return false; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java deleted file mode 100644 index 52900a0bf27e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PackageUtils.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; - -public class PackageUtils { - /** - * Return true if Debug build. false otherwise. - */ - public static boolean isDebugBuild() { - return BuildConfig.DEBUG; - } - - public static PackageInfo getPackageInfo(Context context) { - try { - PackageManager manager = context.getPackageManager(); - return manager.getPackageInfo(context.getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } - - /** - * Return version code, or 0 if it can't be read - */ - public static int getVersionCode(Context context) { - PackageInfo packageInfo = getPackageInfo(context); - if (packageInfo != null) { - return packageInfo.versionCode; - } - return 0; - } - - /** - * Return version name, or the string "0" if it can't be read - */ - public static String getVersionName(Context context) { - PackageInfo packageInfo = getPackageInfo(context); - if (packageInfo != null) { - return packageInfo.versionName; - } - return "0"; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java deleted file mode 100644 index 8d484d847519..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PermissionUtils.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.wordpress.android.util; - -import android.Manifest.permission; -import android.app.Activity; -import android.content.Context; -import android.content.pm.PackageManager; - -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; - -import java.util.ArrayList; -import java.util.List; - -public class PermissionUtils { - /** - * Check for permissions, request them if they're not granted. - * - * @return true if permissions are already granted, else request them and return false. - */ - public static boolean checkAndRequestPermissions(Activity activity, int requestCode, String[] permissionList) { - List toRequest = new ArrayList<>(); - for (String permission : permissionList) { - if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { - toRequest.add(permission); - } - } - if (toRequest.size() > 0) { - String[] requestedPermissions = toRequest.toArray(new String[toRequest.size()]); - ActivityCompat.requestPermissions(activity, requestedPermissions, requestCode); - return false; - } - return true; - } - - /** - * Check for permissions, request them if they're not granted. - * - * @return true if permissions are already granted, else request them and return false. - */ - private static boolean checkAndRequestPermissions(Fragment fragment, int requestCode, String[] permissionList) { - List toRequest = new ArrayList<>(); - for (String permission : permissionList) { - Context context = fragment.getActivity(); - if (context != null && ContextCompat.checkSelfPermission(context, permission) != PackageManager - .PERMISSION_GRANTED) { - toRequest.add(permission); - } - } - if (toRequest.size() > 0) { - String[] requestedPermissions = toRequest.toArray(new String[toRequest.size()]); - fragment.requestPermissions(requestedPermissions, requestCode); - return false; - } - return true; - } - - /** - * Check for permissions without requesting them - * - * @return true if all permissions are granted - */ - public static boolean checkPermissions(Activity activity, String[] permissionList) { - for (String permission : permissionList) { - if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { - return false; - } - } - return true; - } - - public static boolean checkCameraAndStoragePermissions(Activity activity) { - return checkPermissions(activity, - new String[]{ - permission.WRITE_EXTERNAL_STORAGE, - permission.CAMERA}); - } - - public static boolean checkAndRequestCameraAndStoragePermissions(Fragment fragment, int requestCode) { - return checkAndRequestPermissions(fragment, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE, - permission.CAMERA - }); - } - - public static boolean checkAndRequestCameraAndStoragePermissions(Activity activity, int requestCode) { - return checkAndRequestPermissions(activity, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE, - permission.CAMERA - }); - } - - public static boolean checkAndRequestStoragePermission(Activity activity, int requestCode) { - return checkAndRequestPermissions(activity, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE - }); - } - - public static boolean checkAndRequestStoragePermission(Fragment fragment, int requestCode) { - return checkAndRequestPermissions(fragment, requestCode, new String[]{ - permission.WRITE_EXTERNAL_STORAGE - }); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java deleted file mode 100644 index 2f12eb05fae7..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/PhotonUtils.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.wordpress.android.util; - -import android.text.TextUtils; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * routines related to the Photon API - * http://developer.wordpress.com/docs/photon/ - */ -public class PhotonUtils { - private PhotonUtils() { - throw new AssertionError(); - } - - /* - * returns true if the passed url is an obvious "mshots" url - */ - public static boolean isMshotsUrl(final String imageUrl) { - return (imageUrl != null && imageUrl.contains("/mshots/")); - } - - /* - * returns a photon url for the passed image with the resize query set to the passed - * dimensions - note that the passed quality parameter will only affect JPEGs - */ - public enum Quality { - HIGH, - MEDIUM, - LOW - } - - public static final String ATOMIC_MEDIA_PROXY_URL_PREFIX = "https://public-api.wordpress.com/wpcom/v2/sites/"; - public static final String ATOMIC_MEDIA_PROXY_URL_SUFFIX = "/atomic-auth-proxy/file"; - - public static String getPhotonImageUrl(String imageUrl, int width, int height) { - return getPhotonImageUrl(imageUrl, width, height, Quality.MEDIUM); - } - - public static String getPhotonImageUrl(String imageUrl, int width, int height, boolean isPrivateAtomicSite) { - return getPhotonImageUrl(imageUrl, width, height, Quality.MEDIUM, isPrivateAtomicSite); - } - - public static String getPhotonImageUrl(String imageUrl, int width, int height, Quality quality) { - return getPhotonImageUrl(imageUrl, width, height, quality, false); - } - - public static String getPhotonImageUrl(String imageUrl, int width, int height, Quality quality, - boolean isPrivateAtomicSite) { - if (TextUtils.isEmpty(imageUrl)) { - return ""; - } - - // make sure it's valid - int schemePos = imageUrl.indexOf("://"); - if (schemePos == -1) { - return imageUrl; - } - - // we have encountered some image urls that incorrectly have a # fragment part, which - // must be removed before removing the query string - int fragmentPos = imageUrl.indexOf("#"); - if (fragmentPos > 0) { - imageUrl = imageUrl.substring(0, fragmentPos); - } - - String urlCopy = imageUrl; - - // remove existing query string since it may contain params that conflict with the passed ones - imageUrl = UrlUtils.removeQuery(imageUrl); - - // if this is an "mshots" url, skip photon and return it with a query that sets the width/height - if (isMshotsUrl(imageUrl)) { - return imageUrl + "?w=" + width + "&h=" + height; - } - - // strip=info removes Exif, IPTC and comment data from the output image. - String query = "?strip=info"; - - switch (quality) { - case HIGH: - query += "&quality=100"; - break; - case LOW: - query += "&quality=35"; - break; - default: // medium - query += "&quality=65"; - break; - } - - // if both width & height are passed use the "resize" param, use only "w" or "h" if just - // one of them is set - if (width > 0 && height > 0) { - query += "&resize=" + width + "," + height; - } else if (width > 0) { - query += "&w=" + width; - } else if (height > 0) { - query += "&h=" + height; - } - - if (isPrivateAtomicSite) { - try { - URL url = new URL(imageUrl); - String slug = url.getHost(); - String path = url.getPath(); - return ATOMIC_MEDIA_PROXY_URL_PREFIX + slug + ATOMIC_MEDIA_PROXY_URL_SUFFIX - + "?path=" + path + "&" + query; - } catch (MalformedURLException e) { - e.printStackTrace(); - return ""; - } - } - - // return passed url+query if it's already a photon url - if (imageUrl.contains(".wp.com")) { - if (imageUrl.contains("i0.wp.com") || imageUrl.contains("i1.wp.com") || imageUrl.contains("i2.wp.com")) { - boolean useSsl = urlCopy.indexOf("?") > 0 && urlCopy.contains("ssl=1"); - - if (useSsl) { - query += "&ssl=1"; - } - - return imageUrl + query; - } - } - - // use wordpress.com as the host if image is on wordpress.com since it supports the same - // query params and, more importantly, can handle images in private blogs - if (imageUrl.contains("wordpress.com")) { - return imageUrl + query; - } - - // must use ssl=1 parameter for https image urls - boolean useSSl = UrlUtils.isHttps(imageUrl); - if (useSSl) { - query += "&ssl=1"; - } - - return "https://i0.wp.com/" + imageUrl.substring(schemePos + 3, imageUrl.length()) + query; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java deleted file mode 100644 index 2bda40589853..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.wordpress.android.util; - -import android.os.SystemClock; - -import org.wordpress.android.util.AppLog.T; - -import java.util.ArrayList; - -/** - * forked from android.util.TimingLogger to use AppLog instead of Log + new static interface. - */ -public class ProfilingUtils { - private static ProfilingUtils sInstance; - - private String mLabel; - private ArrayList mSplits; - private ArrayList mSplitLabels; - - public static void start(String label) { - getInstance().reset(label); - } - - public static void split(String splitLabel) { - getInstance().addSplit(splitLabel); - } - - public static void dump() { - getInstance().dumpToLog(); - } - - public static void stop() { - getInstance().reset(null); - } - - private static ProfilingUtils getInstance() { - if (sInstance == null) { - sInstance = new ProfilingUtils(); - } - return sInstance; - } - - public ProfilingUtils() { - reset("init"); - } - - public void reset(String label) { - mLabel = label; - reset(); - } - - public void reset() { - if (mSplits == null) { - mSplits = new ArrayList(); - mSplitLabels = new ArrayList(); - } else { - mSplits.clear(); - mSplitLabels.clear(); - } - addSplit(null); - } - - public void addSplit(String splitLabel) { - if (mLabel == null) { - return; - } - long now = SystemClock.elapsedRealtime(); - mSplits.add(now); - mSplitLabels.add(splitLabel); - } - - public void dumpToLog() { - if (mLabel == null) { - return; - } - AppLog.d(T.PROFILING, mLabel + ": begin"); - final long first = mSplits.get(0); - long now = first; - for (int i = 1; i < mSplits.size(); i++) { - now = mSplits.get(i); - final String splitLabel = mSplitLabels.get(i); - final long prev = mSplits.get(i - 1); - AppLog.d(T.PROFILING, mLabel + ": " + (now - prev) + " ms, " + splitLabel); - } - AppLog.d(T.PROFILING, mLabel + ": end, " + (now - first) + " ms"); - } -} - diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java deleted file mode 100644 index 6bcfde06b892..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ServiceUtils.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.wordpress.android.util; - -import android.app.ActivityManager; -import android.content.Context; - -public class ServiceUtils { - public static boolean isServiceRunning(Context context, Class serviceClass) { - ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { - if (serviceClass.getName().equals(service.service.getClassName())) { - return true; - } - } - return false; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java deleted file mode 100644 index 09480f156364..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ShortcodeUtils.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.wordpress.android.util; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ShortcodeUtils { - public static String getVideoPressShortcodeFromId(String videoPressId) { - if (videoPressId == null || videoPressId.isEmpty()) { - return ""; - } - - return "[wpvideo " + videoPressId + "]"; - } - - public static String getVideoPressIdFromShortCode(String shortcode) { - String videoPressId = ""; - - if (shortcode != null) { - String videoPressShortcodeRegex = "^\\[wpvideo (.*)]$"; - - Pattern pattern = Pattern.compile(videoPressShortcodeRegex); - Matcher matcher = pattern.matcher(shortcode); - - if (matcher.find()) { - videoPressId = matcher.group(1); - } - } - - return videoPressId; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java deleted file mode 100644 index e9ca93d2ec7c..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SqlUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.wordpress.android.util; - -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDoneException; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteStatement; - -import org.wordpress.android.util.AppLog.T; - -import java.util.ArrayList; -import java.util.List; - -public class SqlUtils { - private SqlUtils() { - throw new AssertionError(); - } - - /* - * SQLite doesn't have a boolean datatype, so booleans are stored as 0=false, 1=true - */ - public static long boolToSql(boolean value) { - return (value ? 1 : 0); - } - - public static boolean sqlToBool(int value) { - return (value != 0); - } - - public static void closeStatement(SQLiteStatement stmt) { - if (stmt != null) { - stmt.close(); - } - } - - public static void closeCursor(Cursor c) { - if (c != null && !c.isClosed()) { - c.close(); - } - } - - /* - * wrapper for DatabaseUtils.longForQuery() which returns 0 if query returns no rows - */ - public static long longForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - try { - return DatabaseUtils.longForQuery(db, query, selectionArgs); - } catch (SQLiteDoneException e) { - return 0; - } - } - - public static int intForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - long value = longForQuery(db, query, selectionArgs); - return (int) value; - } - - public static boolean boolForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - long value = longForQuery(db, query, selectionArgs); - return sqlToBool((int) value); - } - - /* - * wrapper for DatabaseUtils.stringForQuery(), returns "" if query returns no rows - */ - public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - try { - return DatabaseUtils.stringForQuery(db, query, selectionArgs); - } catch (SQLiteDoneException e) { - return ""; - } - } - - /* - * returns the number of rows in the passed table - */ - public static long getRowCount(SQLiteDatabase db, String tableName) { - return DatabaseUtils.queryNumEntries(db, tableName); - } - - /* - * removes all rows from the passed table - */ - public static void deleteAllRowsInTable(SQLiteDatabase db, String tableName) { - db.delete(tableName, null, null); - } - - /* - * drop all tables from the passed SQLiteDatabase - make sure to pass a - * writable database - */ - public static boolean dropAllTables(SQLiteDatabase db) throws SQLiteException { - if (db == null) { - return false; - } - - if (db.isReadOnly()) { - throw new SQLiteException("can't drop tables from a read-only database"); - } - - List tableNames = new ArrayList(); - Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null); - if (cursor.moveToFirst()) { - do { - String tableName = cursor.getString(0); - if (!tableName.equals("android_metadata") && !tableName.equals("sqlite_sequence")) { - tableNames.add(tableName); - } - } while (cursor.moveToNext()); - } - - db.beginTransaction(); - try { - for (String tableName : tableNames) { - db.execSQL("DROP TABLE IF EXISTS " + tableName); - } - db.setTransactionSuccessful(); - return true; - } finally { - db.endTransaction(); - closeCursor(cursor); - } - } - - /* - * Android's CursorWindow has a max size of 2MB per row which can be exceeded - * with a very large text column, causing an IllegalStateException when the - * row is read - prevent this by limiting the amount of text that's stored in - * the text column. - * https://github.com/android/platform_frameworks_base/blob/b77bc869241644a662f7e615b0b00ecb5aee373d/core/res/res - * /values/config.xml#L1268 - * https://github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/core/java - * /android/database/CursorWindow.java#L103 - */ - // Max 512K characters (a UTF-8 char is 4 bytes max, so a 512K characters string is always < 2Mb) - private static final int MAX_TEXT_LEN = 1024 * 1024 / 2; - - public static String maxSQLiteText(final String text) { - if (text.length() <= MAX_TEXT_LEN) { - return text; - } - AppLog.w(T.UTILS, "sqlite > max text exceeded, storing truncated text"); - return text.substring(0, MAX_TEXT_LEN); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java deleted file mode 100644 index ef96282eb1fb..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java +++ /dev/null @@ -1,363 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.text.TextUtils; - -import androidx.annotation.StringRes; - -import org.wordpress.android.util.AppLog.T; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -public class StringUtils { - /** - * Compare two Strings lexicographically - * Mirrors {@link org.apache.commons.lang3.StringUtils#compare(String, String)}. Use this version when there is a - * hint that the Apache lib might not be provided by the system. - * @param s1 the String to compare from - * @param s2 the String to compare to - * @return < 0, 0, > 0, if {@code s1} is respectively less, equal ou greater than {@code s2} - */ - public static int compare(String s1, String s2) { - if (s1 == s2) { - return 0; - } else if (s1 == null) { - return -1; - } else if (s2 == null) { - return 1; - } else { - return s1.compareTo(s2); - } - } - - /** - * Compare two Strings lexicographically, ignoring case differences. - * Mirrors {@link org.apache.commons.lang3.StringUtils#compareIgnoreCase(String, String)}. Use this version when - * there is a hint that the Apache lib might not be provided by the system. - * @param s1 the String to compare from - * @param s2 the String to compare to - * @return < 0, 0, > 0, if {@code s1} is respectively less, equal ou greater than {@code s2} - */ - public static int compareIgnoreCase(final String s1, final String s2) { - if (s1 == s2) { - return 0; - } - if (s1 == null) { - return -1; - } - if (s2 == null) { - return 1; - } - return s1.compareToIgnoreCase(s2); - } - - public static String[] mergeStringArrays(String[] array1, String[] array2) { - if (array1 == null || array1.length == 0) { - return array2; - } - if (array2 == null || array2.length == 0) { - return array1; - } - List array1List = Arrays.asList(array1); - List array2List = Arrays.asList(array2); - List result = new ArrayList(array1List); - List tmp = new ArrayList(array1List); - tmp.retainAll(array2List); - result.addAll(array2List); - return ((String[]) result.toArray(new String[result.size()])); - } - - public static String convertHTMLTagsForUpload(String source) { - // bold - source = source.replace("", ""); - source = source.replace("", ""); - - // italics - source = source.replace("", ""); - source = source.replace("", ""); - - return source; - } - - public static String convertHTMLTagsForDisplay(String source) { - // bold - source = source.replace("", ""); - source = source.replace("", ""); - - // italics - source = source.replace("", ""); - source = source.replace("", ""); - - return source; - } - - public static String addPTags(String source) { - String[] asploded = source.split("\n\n"); - - if (asploded.length > 0) { - StringBuilder wrappedHTML = new StringBuilder(); - for (int i = 0; i < asploded.length; i++) { - String trimmed = asploded[i].trim(); - if (trimmed.length() > 0) { - trimmed = trimmed.replace("
      ", "
      ").replace("
      ", "
      ").replace("
      \n", "
      ") - .replace("\n", "
      "); - wrappedHTML.append("

      "); - wrappedHTML.append(trimmed); - wrappedHTML.append("

      "); - } - } - return wrappedHTML.toString(); - } else { - return source; - } - } - - public static BigInteger getMd5IntHash(String input) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] messageDigest = md.digest(input.getBytes()); - BigInteger number = new BigInteger(1, messageDigest); - return number; - } catch (NoSuchAlgorithmException e) { - AppLog.e(T.UTILS, e); - return null; - } - } - - public static String getMd5Hash(String input) { - BigInteger number = getMd5IntHash(input); - String md5 = number.toString(16); - while (md5.length() < 32) { - md5 = "0" + md5; - } - return md5; - } - - /* - * nbradbury - adapted from Html.escapeHtml(), which was added in API Level 16 - * TODO: not thoroughly tested yet, so marked as private - not sure I like the way - * this replaces two spaces with " " - */ - private static String escapeHtml(final String text) { - if (text == null) { - return ""; - } - - StringBuilder out = new StringBuilder(); - int length = text.length(); - - for (int i = 0; i < length; i++) { - char c = text.charAt(i); - - if (c == '<') { - out.append("<"); - } else if (c == '>') { - out.append(">"); - } else if (c == '&') { - out.append("&"); - } else if (c > 0x7E || c < ' ') { - out.append("&#").append((int) c).append(";"); - } else if (c == ' ') { - while (i + 1 < length && text.charAt(i + 1) == ' ') { - out.append(" "); - i++; - } - - out.append(' '); - } else { - out.append(c); - } - } - - return out.toString(); - } - - /* - * returns empty string if passed string is null, otherwise returns passed string - */ - public static String notNullStr(String s) { - if (s == null) { - return ""; - } - return s; - } - - /** - * returns true if two strings are equal or two strings are null - */ - public static boolean equals(String s1, String s2) { - if (s1 == null) { - return s2 == null; - } - return s1.equals(s2); - } - - /* - * capitalizes the first letter in the passed string - based on Apache commons/lang3/StringUtils - * http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/StringUtils - * .java?revision=1497829&view=markup - */ - public static String capitalize(final String str) { - int strLen; - if (str == null || (strLen = str.length()) == 0) { - return str; - } - - char firstChar = str.charAt(0); - if (Character.isTitleCase(firstChar)) { - return str; - } - - return new StringBuilder(strLen).append(Character.toTitleCase(firstChar)).append(str.substring(1)).toString(); - } - - public static String removeTrailingSlash(final String str) { - if (TextUtils.isEmpty(str) || !str.endsWith("/")) { - return str; - } - - return str.substring(0, str.length() - 1); - } - - /* - * Wrap an image URL in a photon URL - * Check out http://developer.wordpress.com/docs/photon/ - */ - public static String getPhotonUrl(String imageUrl, int size) { - imageUrl = imageUrl.replace("http://", "").replace("https://", ""); - return "http://i0.wp.com/" + imageUrl + "?w=" + size; - } - - public static String replaceUnicodeSurrogateBlocksWithHTMLEntities(final String inputString) { - final int length = inputString.length(); - StringBuilder out = new StringBuilder(); // Used to hold the output. - for (int offset = 0; offset < length;) { - final int codepoint = inputString.codePointAt(offset); - final char current = inputString.charAt(offset); - if (Character.isHighSurrogate(current) || Character.isLowSurrogate(current)) { - if (EmoticonsUtils.WP_SMILIES_CODE_POINT_TO_TEXT.get(codepoint) != null) { - out.append(EmoticonsUtils.WP_SMILIES_CODE_POINT_TO_TEXT.get(codepoint)); - } else { - final String htmlEscapedChar = "&#x" + Integer.toHexString(codepoint) + ";"; - out.append(htmlEscapedChar); - } - } else { - out.append(current); - } - offset += Character.charCount(codepoint); - } - return out.toString(); - } - - /** - * Used to convert a language code ([lc]_[rc] where lc is language code (en, fr, es, etc...) - * and rc is region code (zh-CN, zh-HK, zh-TW, etc...) to a displayable string with the languages - * name. - * - * The input string must be between 2 and 6 characters, inclusive. An empty string is returned - * if that is not the case. - * - * If the input string is recognized by {@link Locale} the result of this method is the given - * - * @return non-null - */ - public static String getLanguageString(String languagueCode, Locale displayLocale) { - if (languagueCode == null || languagueCode.length() < 2 || languagueCode.length() > 6) { - return ""; - } - - Locale languageLocale = new Locale(languagueCode.substring(0, 2)); - return languageLocale.getDisplayLanguage(displayLocale) + languagueCode.substring(2); - } - - /** - * This method ensures that the output String has only - * valid XML unicode characters as specified by the - * XML 1.0 standard. For reference, please see - * the - * standard. This method will return an empty - * String if the input is null or empty. - * - * @param in The String whose non-valid characters we want to remove. - * @return The in String, stripped of non-valid characters. - */ - public static final String stripNonValidXMLCharacters(String in) { - StringBuilder out = new StringBuilder(); // Used to hold the output. - char current; // Used to reference the current character. - - if (in == null || ("".equals(in))) { - return ""; // vacancy test. - } - for (int i = 0; i < in.length(); i++) { - current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen. - if ((current == 0x9) - || (current == 0xA) - || (current == 0xD) - || ((current >= 0x20) && (current <= 0xD7FF)) - || ((current >= 0xE000) && (current <= 0xFFFD)) - || ((current >= 0x10000) && (current <= 0x10FFFF))) { - out.append(current); - } - } - return out.toString(); - } - - /* - * simple wrapper for Integer.valueOf(string) so caller doesn't need to catch NumberFormatException - */ - public static int stringToInt(String s) { - return stringToInt(s, 0); - } - - public static int stringToInt(String s, int defaultValue) { - if (s == null) { - return defaultValue; - } - try { - return Integer.valueOf(s); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public static long stringToLong(String s) { - return stringToLong(s, 0L); - } - - public static long stringToLong(String s, long defaultValue) { - if (s == null) { - return defaultValue; - } - try { - return Long.valueOf(s); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - /** - * Formats the string for the given quantity, using the given arguments. - * We need this because our translation platform doesn't support Android plurals. - * - * @param zero The desired string identifier to get when quantity is exactly 0 - * @param one The desired string identifier to get when quantity is exactly 1 - * @param other The desired string identifier to get when quantity is not (0 or 1) - * @param quantity The number used to get the correct string - */ - public static String getQuantityString(Context context, @StringRes int zero, @StringRes int one, - @StringRes int other, int quantity) { - if (quantity == 0) { - return context.getString(zero); - } - if (quantity == 1) { - return context.getString(one); - } - return String.format(context.getString(other), quantity); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java deleted file mode 100644 index e3fee7fc33b7..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -public class SystemServiceFactory { - private static SystemServiceFactoryAbstract sFactory; - - public static Object get(Context context, String name) { - if (sFactory == null) { - sFactory = new SystemServiceFactoryDefault(); - } - return sFactory.get(context, name); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java deleted file mode 100644 index 7b86f6631062..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryAbstract.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -public interface SystemServiceFactoryAbstract { - Object get(Context context, String name); -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java deleted file mode 100644 index eb488dde9bf4..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/SystemServiceFactoryDefault.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; - -public class SystemServiceFactoryDefault implements SystemServiceFactoryAbstract { - public Object get(Context context, String name) { - return context.getSystemService(name); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java deleted file mode 100644 index 470867364b8c..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ToastUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.wordpress.android.util; - -import android.content.Context; -import android.view.Gravity; -import android.widget.Toast; - -/** - * Provides a simplified way to show toast messages without having to create the toast, set the - * desired gravity, etc. - */ -public class ToastUtils { - public enum Duration { - SHORT, LONG - } - - private ToastUtils() { - throw new AssertionError(); - } - - public static Toast showToast(Context context, int stringResId) { - return showToast(context, stringResId, Duration.SHORT); - } - - public static Toast showToast(Context context, int stringResId, Duration duration) { - return showToast(context, context.getString(stringResId), duration); - } - - public static Toast showToast(Context context, String text) { - return showToast(context, text, Duration.SHORT); - } - - public static Toast showToast(Context context, String text, Duration duration) { - return showToast(context, text, duration, Gravity.CENTER); - } - - public static Toast showToast(Context context, String text, Duration duration, int gravity) { - return showToast(context, text, duration, gravity, 0, 0); - } - - public static Toast showToast( - Context context, - String text, - Duration duration, - int gravity, - int xOffset, - int yOffset) { - Toast toast = Toast.makeText(context, text, - (duration == Duration.SHORT ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG)); - toast.setGravity(gravity, xOffset, yOffset); - toast.show(); - return toast; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java deleted file mode 100644 index 0068ac9d4d8b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java +++ /dev/null @@ -1,318 +0,0 @@ -package org.wordpress.android.util; - -import android.net.Uri; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; -import android.webkit.URLUtil; - -import androidx.annotation.Nullable; - -import org.wordpress.android.util.AppLog.T; - -import java.io.UnsupportedEncodingException; -import java.net.IDN; -import java.net.URI; -import java.net.URL; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -import static org.wordpress.android.util.PhotonUtils.ATOMIC_MEDIA_PROXY_URL_PREFIX; -import static org.wordpress.android.util.PhotonUtils.ATOMIC_MEDIA_PROXY_URL_SUFFIX; - -public class UrlUtils { - public static String urlEncode(final String text) { - try { - return URLEncoder.encode(text, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return text; - } - } - - public static String urlDecode(final String text) { - try { - return URLDecoder.decode(text, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return text; - } - } - - /** - * @param urlString url to get host from - * @return host of uri if available. Empty string otherwise. - */ - public static String getHost(final String urlString) { - if (urlString != null) { - Uri uri = Uri.parse(urlString); - if (uri.getHost() != null) { - return uri.getHost(); - } - } - return ""; - } - - public static boolean isContentUri(String uri) { - return "content".equals(Uri.parse(uri).getScheme()); - } - - /** - * Convert IDN names to punycode if necessary - */ - public static String convertUrlToPunycodeIfNeeded(String url) { - if (!Charset.forName("US-ASCII").newEncoder().canEncode(url)) { - if (url.toLowerCase(Locale.ROOT).startsWith("http://")) { - url = "http://" + IDN.toASCII(url.substring(7), IDN.ALLOW_UNASSIGNED); - } else if (url.toLowerCase(Locale.ROOT).startsWith("https://")) { - url = "https://" + IDN.toASCII(url.substring(8), IDN.ALLOW_UNASSIGNED); - } else { - url = IDN.toASCII(url, IDN.ALLOW_UNASSIGNED); - } - } - return url; - } - - /** - * Remove leading double slash, and inherit protocol scheme - */ - public static String removeLeadingDoubleSlash(String url, String scheme) { - if (url != null && url.startsWith("//")) { - url = url.substring(2); - if (scheme != null) { - if (scheme.endsWith("://")) { - url = scheme + url; - } else { - AppLog.e(T.UTILS, "Invalid scheme used: " + scheme); - } - } - } - return url; - } - - /** - * Add scheme prefix to an URL. This method must be called on all user entered or server fetched URLs to ensure - * http client will work as expected. - * - * @param url url entered by the user or fetched from a server - * @param addHttps true and the url is not starting with http://, it will make the url starts with https:// - * @return url prefixed by http:// or https:// - */ - public static String addUrlSchemeIfNeeded(String url, boolean addHttps) { - if (url == null) { - return null; - } - - // Remove leading double slash (eg. // example.com), needed for some wporg instances configured to - // switch between http or https - url = removeLeadingDoubleSlash(url, (addHttps ? "https" : "http") + "://"); - - // If the URL is a valid http or https URL, we're good to go - if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) { - return url; - } - - // Else, remove the old scheme and prefix it by https:// or http:// - return (addHttps ? "https" : "http") + "://" + removeScheme(url); - } - - /** - * normalizes a URL, primarily for comparison purposes, for example so that - * normalizeUrl("http://google.com/") = normalizeUrl("http://google.com") - */ - public static String normalizeUrl(final String urlString) { - if (urlString == null) { - return null; - } - - // this routine is called from some performance-critical code and creating a URI from a string - // is slow, so skip it when possible - if we know it's not a relative path (and 99.9% of the - // time it won't be for our purposes) then we can normalize it without java.net.URI.normalize() - if (urlString.startsWith("http") - && !urlString.contains("build/intermediates/exploded-aar/org.wordpress/graphview/3.1.1")) { - // return without a trailing slash - if (urlString.endsWith("/")) { - return urlString.substring(0, urlString.length() - 1); - } - return urlString; - } - - // url is relative, so fall back to using slower java.net.URI normalization - try { - URI uri = URI.create(urlString); - return uri.normalize().toString(); - } catch (IllegalArgumentException e) { - return urlString; - } - } - - - /** - * returns the passed url without the scheme - */ - public static String removeScheme(final String urlString) { - if (urlString == null) { - return null; - } - - int doubleslash = urlString.indexOf("//"); - if (doubleslash == -1) { - doubleslash = 0; - } else { - doubleslash += 2; - } - - return urlString.substring(doubleslash, urlString.length()); - } - - /** - * returns the passed url without the query parameters - */ - public static String removeQuery(final String urlString) { - if (urlString == null) { - return null; - } - return Uri.parse(urlString).buildUpon().clearQuery().toString(); - } - - /** - * returns true if passed url is https: - */ - public static boolean isHttps(final String urlString) { - return (urlString != null && urlString.startsWith("https:")); - } - - public static boolean isHttps(URL url) { - return url != null && "https".equals(url.getProtocol()); - } - - public static boolean isHttps(URI uri) { - if (uri == null) { - return false; - } - - String protocol = uri.getScheme(); - return protocol != null && protocol.equals("https"); - } - - /** - * returns https: version of passed http: url - */ - public static String makeHttps(final String urlString) { - if (urlString == null || !urlString.startsWith("http:")) { - return urlString; - } - return "https:" + urlString.substring(5, urlString.length()); - } - - /** - * see http://stackoverflow.com/a/8591230/1673548 - */ - public static String getUrlMimeType(final String urlString) { - if (urlString == null) { - return null; - } - - String extension = MimeTypeMap.getFileExtensionFromUrl(urlString); - if (extension == null) { - return null; - } - - MimeTypeMap mime = MimeTypeMap.getSingleton(); - String mimeType = mime.getMimeTypeFromExtension(extension); - if (mimeType == null) { - return null; - } - - return mimeType; - } - - /** - * returns false if the url is not valid or if the url host is null, else true - */ - public static boolean isValidUrlAndHostNotNull(String url) { - try { - URI uri = URI.create(url); - if (uri.getHost() == null) { - return false; - } - } catch (IllegalArgumentException e) { - return false; - } - return true; - } - - // returns true if the passed url is for an image - public static boolean isImageUrl(String url) { - if (TextUtils.isEmpty(url)) { - return false; - } - - String cleanedUrl = removeQuery(url.toLowerCase(Locale.ROOT)); - - if (isAtomicImageProxyUrl(cleanedUrl)) { - return true; - } - - return cleanedUrl.endsWith("jpg") || cleanedUrl.endsWith("jpeg") - || cleanedUrl.endsWith("gif") || cleanedUrl.endsWith("png"); - } - - public static @Nullable String getPageJumpOrNull(String url) { - if (TextUtils.isEmpty(url)) { - return null; - } - - if (url.contains("#") - && url.indexOf("#") < url.length() - 1 - && url.split("#").length == 2) { - return url.substring(url.indexOf('#') + 1); - } - - return null; - } - - private static boolean isAtomicImageProxyUrl(String urlString) { - return urlString.startsWith(ATOMIC_MEDIA_PROXY_URL_PREFIX) && urlString.endsWith(ATOMIC_MEDIA_PROXY_URL_SUFFIX); - } - - public static String appendUrlParameter(String url, String paramName, String paramValue) { - Map parameters = new HashMap<>(); - parameters.put(paramName, paramValue); - return appendUrlParameters(url, parameters); - } - - public static String appendUrlParameters(String url, Map parameters) { - Uri.Builder uriBuilder = Uri.parse(url).buildUpon(); - for (Map.Entry parameter : parameters.entrySet()) { - uriBuilder.appendQueryParameter(parameter.getKey(), parameter.getValue()); - } - return uriBuilder.build().toString(); - } - - /** - * Extracts the subdomain from a domain string. - * @param domain A domain is expected. Protocol is optional - * @return The subdomain or an empty string. - */ - public static String extractSubDomain(String domain) { - String str = UrlUtils.addUrlSchemeIfNeeded(domain, false); - String host = UrlUtils.getHost(str); - if (host.length() > 0) { - String[] parts = host.split("\\."); - if (parts.length > 1) { // There should be at least 2 dots for there to be a subdomain. - return parts[0]; - } - } - return ""; - } - - public static String removeXmlrpcSuffix(String siteAddress) { - if (siteAddress.toLowerCase(Locale.ROOT).endsWith("/xmlrpc.php")) { - return siteAddress.substring(0, siteAddress.lastIndexOf("xmlrpc.php")); - } else { - return siteAddress; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java deleted file mode 100644 index 8ccb5c4a51c8..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/UserEmailUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wordpress.android.util; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.content.Context; -import android.util.Patterns; - -import org.wordpress.android.util.AppLog.T; - -import java.util.regex.Pattern; - -public class UserEmailUtils { - /** - * Get primary account and return its name if it matches the email address pattern. - * - * @return primary account email address if it can be found or empty string else. - */ - public static String getPrimaryEmail(Context context) { - try { - AccountManager accountManager = AccountManager.get(context); - if (accountManager == null) { - return ""; - } - Account[] accounts = accountManager.getAccounts(); - Pattern emailPattern = Patterns.EMAIL_ADDRESS; - for (Account account : accounts) { - // make sure account.name is an email address before adding to the list - if (emailPattern.matcher(account.name).matches()) { - return account.name; - } - } - return ""; - } catch (SecurityException e) { - // exception will occur if app doesn't have GET_ACCOUNTS permission - AppLog.e(T.UTILS, "SecurityException - missing GET_ACCOUNTS permission"); - return ""; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java deleted file mode 100644 index 38ed56a7e744..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/VideoUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.wordpress.android.util; - - -import android.content.Context; -import android.media.MediaMetadataRetriever; -import android.net.Uri; - -import java.io.File; - -public class VideoUtils { - public static long getVideoDurationMS(Context context, File file) { - if (context == null || file == null) { - AppLog.e(AppLog.T.MEDIA, "context and file can't be null."); - return 0L; - } - return getVideoDurationMS(context, Uri.fromFile(file)); - } - - public static long getVideoDurationMS(Context context, Uri videoUri) { - if (context == null || videoUri == null) { - AppLog.e(AppLog.T.MEDIA, "context and videoUri can't be null."); - return 0L; - } - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - try { - retriever.setDataSource(context, videoUri); - } catch (IllegalArgumentException | SecurityException e) { - AppLog.e(AppLog.T.MEDIA, "Can't read duration of the video.", e); - return 0L; - } catch (RuntimeException e) { - // Ref: https://github.com/wordpress-mobile/WordPress-Android/issues/5431 - AppLog.e(AppLog.T.MEDIA, - "Can't read duration of the video due to a Runtime Exception happened setting the datasource", e); - return 0L; - } - - String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); - if (time == null) { - return 0L; - } - return Long.parseLong(time); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java deleted file mode 100644 index 9f7a11eeb6e9..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/ViewUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.wordpress.android.util; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.TypedArray; -import android.graphics.Outline; -import android.os.Build; -import android.view.View; -import android.view.ViewOutlineProvider; - -import androidx.annotation.AttrRes; -import androidx.annotation.NonNull; -import androidx.annotation.StyleRes; -import androidx.core.view.ViewCompat; - -import java.util.concurrent.atomic.AtomicInteger; - -public class ViewUtils { - /** - * Generate a value suitable for use in {@link View#setId(int)}. - * This value will not collide with ID values generated at build time by aapt for R.id. - * Uses the native implementation if API 17 or above, otherwise uses a copied implementation. - * - * @return a generated ID value - */ - public static int generateViewId() { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - return View.generateViewId(); - } else { - return copiedGenerateViewId(); - } - } - - private static final AtomicInteger NEXT_GENERATED_ID = new AtomicInteger(1); - - /** - * Copied from {@link View#generateViewId()} - * Generate a value suitable for use in {@link View#setId(int)}. - * This value will not collide with ID values generated at build time by aapt for R.id. - * - * @return a generated ID value - */ - private static int copiedGenerateViewId() { - for (;;) { - final int result = NEXT_GENERATED_ID.get(); - // aapt-generated IDs have the high byte nonzero; clamp to the range under that. - int newValue = result + 1; - if (newValue > 0x00FFFFFF) { - newValue = 1; // Roll over to 1, not 0. - } - if (NEXT_GENERATED_ID.compareAndSet(result, newValue)) { - return result; - } - } - } - - public static void setButtonBackgroundColor(Context context, View button, @StyleRes int styleId, - @AttrRes int colorAttribute) { - TypedArray a = context.obtainStyledAttributes(styleId, new int[]{colorAttribute}); - ColorStateList color = a.getColorStateList(0); - a.recycle(); - ViewCompat.setBackgroundTintList(button, color); - } - - /** - * adds an inset circular shadow outline the passed view (Lollipop+ only) - note that - * the view should have its elevation set prior to calling this - */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public static void addCircularShadowOutline(@NonNull View view) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - view.setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, view.getWidth(), view.getHeight()); - } - }); - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java deleted file mode 100644 index 6247957819dc..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/WebViewUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.wordpress.android.util; - -import android.os.Build; -import android.webkit.CookieManager; -import android.webkit.ValueCallback; - -public class WebViewUtils { - public static void clearCookiesAsync() { - clearCookiesAsync(null); - } - - public static void clearCookiesAsync(ValueCallback callback) { - CookieManager cookieManager = CookieManager.getInstance(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - cookieManager.removeAllCookies(callback); - } else { - //noinspection deprecation - cookieManager.removeAllCookie(); - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java deleted file mode 100644 index 1cd723331330..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Debouncer.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wordpress.android.util.helpers; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class Debouncer { - private final ScheduledExecutorService mScheduler = Executors.newSingleThreadScheduledExecutor(); - private final ConcurrentHashMap> mDelayedMap = new ConcurrentHashMap<>(); - - /** - * Debounces {@code callable} by {@code delay}, i.e., schedules it to be executed after {@code delay}, - * or cancels its execution if the method is called with the same key within the {@code delay} again. - */ - public void debounce(final Object key, final Runnable runnable, long delay, TimeUnit unit) { - if (mScheduler.isShutdown()) { - return; - } - final Future prev = mDelayedMap.put(key, mScheduler.schedule(new Runnable() { - @Override - public void run() { - try { - runnable.run(); - } finally { - mDelayedMap.remove(key); - } - } - }, delay, unit)); - if (prev != null) { - prev.cancel(true); - } - } - - public void shutdown() { - mScheduler.shutdownNow(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java deleted file mode 100644 index 914373c8f2e1..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/ListScrollPositionManager.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.preference.PreferenceManager; -import android.view.View; -import android.widget.ListView; - -public class ListScrollPositionManager { - private int mSelectedPosition; - private int mListViewScrollStateIndex; - private int mListViewScrollStateOffset; - private ListView mListView; - private boolean mSetSelection; - - public ListScrollPositionManager(ListView listView, boolean setSelection) { - mListView = listView; - mSetSelection = setSelection; - } - - public void saveScrollOffset() { - mListViewScrollStateIndex = mListView.getFirstVisiblePosition(); - View view = mListView.getChildAt(0); - mListViewScrollStateOffset = 0; - if (view != null) { - mListViewScrollStateOffset = view.getTop(); - } - if (mSetSelection) { - mSelectedPosition = mListView.getCheckedItemPosition(); - } - } - - public void restoreScrollOffset() { - mListView.setSelectionFromTop(mListViewScrollStateIndex, mListViewScrollStateOffset); - if (mSetSelection) { - mListView.setItemChecked(mSelectedPosition, true); - } - } - - public void saveToPreferences(Context context, String uniqueId) { - saveScrollOffset(); - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - Editor editor = settings.edit(); - editor.putInt("scroll-position-manager-index-" + uniqueId, mListViewScrollStateIndex); - editor.putInt("scroll-position-manager-offset-" + uniqueId, mListViewScrollStateOffset); - editor.putInt("scroll-position-manager-selected-position-" + uniqueId, mSelectedPosition); - editor.apply(); - } - - public void restoreFromPreferences(Context context, String uniqueId) { - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - mListViewScrollStateIndex = settings.getInt("scroll-position-manager-index-" + uniqueId, 0); - mListViewScrollStateOffset = settings.getInt("scroll-position-manager-offset-" + uniqueId, 0); - mSelectedPosition = settings.getInt("scroll-position-manager-selected-position-" + uniqueId, 0); - restoreScrollOffset(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java deleted file mode 100644 index 98d815802ed2..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaFile.java +++ /dev/null @@ -1,348 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import org.wordpress.android.util.MapUtils; -import org.wordpress.android.util.StringUtils; -import org.wordpress.android.util.UrlUtils; - -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -public class MediaFile { - protected int mId; - protected long mPostID; - protected String mFilePath = null; // path of the file into disk - protected String mFileName = null; // name of the file into the server - protected String mTitle = null; - protected String mDescription = null; - protected String mCaption = null; - protected int mHorizontalAlignment; // 0 = none, 1 = left, 2 = center, 3 = right - protected boolean mVerticalAligment = false; // false = bottom, true = top - protected int mWidth = 500; - protected int mHeight; - protected String mMimeType = ""; - protected String mVideoPressShortCode = null; - protected boolean mFeatured = false; - protected boolean mIsVideo = false; - protected boolean mFeaturedInPost; - protected String mFileURL = null; // url of the file to download - protected String mThumbnailURL = null; // url of the thumbnail to download - private String mBlogId; - private long mDateCreatedGmt; - private String mUploadState = null; - private String mMediaId; - - private static final String VIDEOPRESS_SHORTCODE_ID = "videopress_shortcode"; - - public MediaFile(String blogId, Map resultMap, boolean isWPCom) { - setBlogId(blogId); - setMediaId(MapUtils.getMapStr(resultMap, "attachment_id")); - setPostID(MapUtils.getMapLong(resultMap, "parent")); - setTitle(MapUtils.getMapStr(resultMap, "title")); - setCaption(MapUtils.getMapStr(resultMap, "caption")); - setDescription(MapUtils.getMapStr(resultMap, "description")); - setVideoPressShortCode(MapUtils.getMapStr(resultMap, VIDEOPRESS_SHORTCODE_ID)); - - // get the file name from the link - String link = MapUtils.getMapStr(resultMap, "link"); - setFileName(new String(link).replaceAll("^.*/([A-Za-z0-9_-]+)\\.\\w+$", "$1")); - - String fileType = new String(link).replaceAll(".*\\.(\\w+)$", "$1").toLowerCase(Locale.ROOT); - String fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileType); - setMimeType(fileMimeType); - - // make the file urls be https://... so that we can get these images with oauth when the blogs are private - // assume no https for images in self-hosted blogs - String fileUrl = MapUtils.getMapStr(resultMap, "link"); - if (isWPCom) { - fileUrl = fileUrl.replace("http:", "https:"); - } - setFileURL(fileUrl); - - String thumbnailURL = MapUtils.getMapStr(resultMap, "thumbnail"); - if (thumbnailURL.startsWith("http")) { - if (isWPCom) { - thumbnailURL = thumbnailURL.replace("http:", "https:"); - } - setThumbnailURL(thumbnailURL); - } - - Date date = MapUtils.getMapDate(resultMap, "date_created_gmt"); - if (date != null) { - setDateCreatedGMT(date.getTime()); - } - - Object meta = resultMap.get("metadata"); - if (meta != null && meta instanceof Map) { - Map metadata = (Map) meta; - setWidth(MapUtils.getMapInt(metadata, "width")); - setHeight(MapUtils.getMapInt(metadata, "height")); - } - } - - public MediaFile() { - // default constructor - } - - public MediaFile(MediaFile mediaFile) { - this.mId = mediaFile.mId; - this.mPostID = mediaFile.mPostID; - this.mFilePath = mediaFile.mFilePath; - this.mFileName = mediaFile.mFileName; - this.mTitle = mediaFile.mTitle; - this.mDescription = mediaFile.mDescription; - this.mCaption = mediaFile.mCaption; - this.mHorizontalAlignment = mediaFile.mHorizontalAlignment; - this.mVerticalAligment = mediaFile.mVerticalAligment; - this.mWidth = mediaFile.mWidth; - this.mHeight = mediaFile.mHeight; - this.mMimeType = mediaFile.mMimeType; - this.mVideoPressShortCode = mediaFile.mVideoPressShortCode; - this.mFeatured = mediaFile.mFeatured; - this.mIsVideo = mediaFile.mIsVideo; - this.mFeaturedInPost = mediaFile.mFeaturedInPost; - this.mFileURL = mediaFile.mFileURL; - this.mThumbnailURL = mediaFile.mThumbnailURL; - this.mBlogId = mediaFile.mBlogId; - this.mDateCreatedGmt = mediaFile.mDateCreatedGmt; - this.mUploadState = mediaFile.mUploadState; - this.mMediaId = mediaFile.mMediaId; - } - - public int getId() { - return mId; - } - - public void setId(int id) { - this.mId = id; - } - - public String getMediaId() { - return mMediaId; - } - - public void setMediaId(String id) { - mMediaId = id; - } - - public boolean isFeatured() { - return mFeatured; - } - - public void setFeatured(boolean featured) { - this.mFeatured = featured; - } - - public long getPostID() { - return mPostID; - } - - public void setPostID(long postID) { - this.mPostID = postID; - } - - public String getFilePath() { - return mFilePath; - } - - public void setFilePath(String filePath) { - this.mFilePath = filePath; - } - - public String getTitle() { - return mTitle; - } - - public void setTitle(String title) { - this.mTitle = title; - } - - public String getCaption() { - return mCaption; - } - - public void setCaption(String caption) { - this.mCaption = caption; - } - - public String getDescription() { - return mDescription; - } - - public void setDescription(String description) { - this.mDescription = description; - } - - public String getFileURL() { - return mFileURL; - } - - public void setFileURL(String fileURL) { - this.mFileURL = fileURL; - } - - public String getThumbnailURL() { - return mThumbnailURL; - } - - public void setThumbnailURL(String thumbnailURL) { - this.mThumbnailURL = thumbnailURL; - } - - public boolean isVerticalAlignmentOnTop() { - return mVerticalAligment; - } - - public void setVerticalAlignmentOnTop(boolean verticalAligment) { - this.mVerticalAligment = verticalAligment; - } - - public int getWidth() { - return mWidth; - } - - public void setWidth(int width) { - this.mWidth = width; - } - - public int getHeight() { - return mHeight; - } - - public void setHeight(int height) { - this.mHeight = height; - } - - public String getFileName() { - return mFileName; - } - - public void setFileName(String fileName) { - this.mFileName = fileName; - } - - public String getMimeType() { - return StringUtils.notNullStr(mMimeType); - } - - public void setMimeType(String type) { - mMimeType = StringUtils.notNullStr(type); - } - - public String getVideoPressShortCode() { - return mVideoPressShortCode; - } - - public void setVideoPressShortCode(String videoPressShortCode) { - this.mVideoPressShortCode = videoPressShortCode; - } - - public int getHorizontalAlignment() { - return mHorizontalAlignment; - } - - public void setHorizontalAlignment(int horizontalAlignment) { - this.mHorizontalAlignment = horizontalAlignment; - } - - public boolean isVideo() { - return mIsVideo; - } - - public void setVideo(boolean isVideo) { - this.mIsVideo = isVideo; - } - - public boolean isFeaturedInPost() { - return mFeaturedInPost; - } - - public void setFeaturedInPost(boolean featuredInPost) { - this.mFeaturedInPost = featuredInPost; - } - - public String getBlogId() { - return mBlogId; - } - - public void setBlogId(String blogId) { - this.mBlogId = blogId; - } - - public void setDateCreatedGMT(long dateCreatedGmt) { - this.mDateCreatedGmt = dateCreatedGmt; - } - - public long getDateCreatedGMT() { - return mDateCreatedGmt; - } - - public void setUploadState(String uploadState) { - this.mUploadState = uploadState; - } - - public String getUploadState() { - return mUploadState; - } - - /** - * Outputs the Html for an image - * If a fullSizeUrl exists, a link will be created to it from the resizedPictureUrl - */ - public String getImageHtmlForUrls(String fullSizeUrl, String resizedPictureURL, boolean shouldAddImageWidthCSS) { - String alignment = ""; - switch (getHorizontalAlignment()) { - case 0: - alignment = "alignnone"; - break; - case 1: - alignment = "alignleft"; - break; - case 2: - alignment = "aligncenter"; - break; - case 3: - alignment = "alignright"; - break; - } - - String alignmentCSS = "class=\"" + alignment + " size-full\" "; - - if (shouldAddImageWidthCSS) { - alignmentCSS += "style=\"max-width: " + getWidth() + "px\" "; - } - - // Check if we uploaded a featured picture that is not added to the Post content (normal case) - if ((fullSizeUrl != null && fullSizeUrl.equalsIgnoreCase("")) - || (resizedPictureURL != null && resizedPictureURL.equalsIgnoreCase(""))) { - return ""; // Not featured in Post. Do not add to the content. - } - - if (fullSizeUrl == null && resizedPictureURL != null) { - fullSizeUrl = resizedPictureURL; - } else if (fullSizeUrl != null && resizedPictureURL == null) { - resizedPictureURL = fullSizeUrl; - } - - String mediaTitle = StringUtils.notNullStr(getTitle()); - - String content = String.format(Locale.US, "\"image\"", - fullSizeUrl, mediaTitle, alignmentCSS, resizedPictureURL); - - if (!TextUtils.isEmpty(getCaption())) { - content = String.format(Locale.US, "[caption id=\"\" align=\"%s\" width=\"%d\"]%s%s[/caption]", - alignment, getWidth(), content, TextUtils.htmlEncode(getCaption())); - } - - return content; - } - - public String getAttachmentPageURL(String siteUrl) { - siteUrl = UrlUtils.makeHttps(siteUrl); - String attachmentPageUrl = UrlUtils.appendUrlParameter(siteUrl, "p", mMediaId); - return attachmentPageUrl; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java deleted file mode 100644 index ea13f012b699..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGallery.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.wordpress.android.util.helpers; - -import java.io.Serializable; -import java.util.ArrayList; - -/** - * A model representing a Media Gallery. - * A unique id is not used on the website, but only in this app. - * It is used to uniquely determining the instance of the object, as it is - * passed between post and media gallery editor. - */ -public class MediaGallery implements Serializable { - private static final long serialVersionUID = 2359176987182027508L; - - private long mUniqueId; - private boolean mIsRandom; - private String mType; - private int mNumColumns; - private ArrayList mIds; - - public MediaGallery(boolean isRandom, String type, int numColumns, ArrayList ids) { - mIsRandom = isRandom; - mType = type; - mNumColumns = numColumns; - mIds = ids; - mUniqueId = System.currentTimeMillis(); - } - - public MediaGallery() { - mIsRandom = false; - mType = ""; - mNumColumns = 3; - mIds = new ArrayList<>(); - mUniqueId = System.currentTimeMillis(); - } - - public boolean isRandom() { - return mIsRandom; - } - - public void setRandom(boolean isRandom) { - this.mIsRandom = isRandom; - } - - public String getType() { - return mType; - } - - public void setType(String type) { - this.mType = type; - } - - public int getNumColumns() { - return mNumColumns; - } - - public void setNumColumns(int numColumns) { - this.mNumColumns = numColumns; - } - - public ArrayList getIds() { - return mIds; - } - - public String getIdsStr() { - String idsStr = ""; - if (mIds.size() > 0) { - for (Long id : mIds) { - idsStr += id + ","; - } - idsStr = idsStr.substring(0, idsStr.length() - 1); - } - return idsStr; - } - - public void setIds(ArrayList ids) { - this.mIds = ids; - } - - /** - * An id to uniquely identify a media gallery object, so that the same object can be edited in the post editor - */ - public long getUniqueId() { - return mUniqueId; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java deleted file mode 100644 index 588b98141c27..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/MediaGalleryImageSpan.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.content.Context; -import android.text.style.ImageSpan; - -public class MediaGalleryImageSpan extends ImageSpan { - private MediaGallery mMediaGallery; - - public MediaGalleryImageSpan(Context context, MediaGallery mediaGallery, int placeHolder) { - super(context, placeHolder); - setMediaGallery(mediaGallery); - } - - public MediaGallery getMediaGallery() { - return mMediaGallery; - } - - public void setMediaGallery(MediaGallery mediaGallery) { - this.mMediaGallery = mediaGallery; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java deleted file mode 100644 index 93021257449d..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/RecyclerViewScrollPositionManager.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.os.Bundle; -import android.view.View; - -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - - -public class RecyclerViewScrollPositionManager { - private static final String RV_POSITION = "rv_position"; - private static final String RV_OFFSET = "rv_offset"; - private int mRVPosition = 0; - private int mRVOffset = 0; - - public void onSaveInstanceState(Bundle outState, RecyclerView recyclerView) { - // make sure the layout manager is assigned to the RecyclerView - // also take into account this needs to be a LinearLayoutManager, otherwise ClassCastException occurs - outState.putInt(RV_POSITION, - ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition()); - View firstItemView = recyclerView.getChildAt(0); - int offset = (firstItemView == null) ? 0 : (firstItemView.getTop() - recyclerView.getPaddingTop()); - outState.putInt(RV_OFFSET, offset); - } - - public void onRestoreInstanceState(Bundle savedInstanceState) { - mRVPosition = savedInstanceState.getInt(RV_POSITION); - mRVOffset = savedInstanceState.getInt(RV_OFFSET); - } - - public void restoreScrollOffset(RecyclerView recyclerView) { - if (mRVPosition > 0 || mRVOffset > 0) { - ((LinearLayoutManager) recyclerView.getLayoutManager()) - .scrollToPositionWithOffset(mRVPosition, mRVOffset); - } - mRVPosition = 0; - mRVOffset = 0; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java deleted file mode 100644 index 14cc5efef9a8..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/SwipeToRefreshHelper.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.content.Context; - -import androidx.annotation.ColorInt; -import androidx.annotation.ColorRes; -import androidx.core.content.ContextCompat; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener; - -import org.wordpress.android.util.widgets.CustomSwipeRefreshLayout; - -public class SwipeToRefreshHelper implements OnRefreshListener { - private CustomSwipeRefreshLayout mSwipeRefreshLayout; - private RefreshListener mRefreshListener; - private boolean mRefreshing; - - public interface RefreshListener { - void onRefreshStarted(); - } - - /** - * Helps {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by passing the - * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color. - * - * @param context {@link Context} in which this layout is used. - * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents - * of a view via a vertical swipe gesture. - * @param listener {@link RefreshListener} notified when a refresh is triggered - * via the swipe gesture. - * - * @deprecated Use {@link #SwipeToRefreshHelper(CustomSwipeRefreshLayout, RefreshListener, int, int...)} instead. - */ - @Deprecated - public SwipeToRefreshHelper(Context context, CustomSwipeRefreshLayout swipeRefreshLayout, - RefreshListener listener) { - init(swipeRefreshLayout, listener, ContextCompat.getColor(context, android.R.color.white), - android.R.color.holo_blue_dark); - } - - /** - * Helps {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by passing the - * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color(s). - * - * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents - * of a view via a vertical swipe gesture. - * @param listener {@link RefreshListener} notified when a refresh is triggered - * via the swipe gesture. - * @param progressAnimationColors Comma-separated color resource integers used in the progress - * animation. The first color will also be the color of the bar - * that grows in response to a user swipe gesture. - */ - public SwipeToRefreshHelper(CustomSwipeRefreshLayout swipeRefreshLayout, RefreshListener listener, - @ColorInt int backgroundColor, - @ColorRes int... progressAnimationColors) { - init(swipeRefreshLayout, listener, backgroundColor, progressAnimationColors); - } - - /** - * Initializes {@link org.wordpress.android.util.widgets.CustomSwipeRefreshLayout} by assigning - * {@link SwipeRefreshLayout}, {@link RefreshListener}, and color(s). - * - * @param swipeRefreshLayout {@link CustomSwipeRefreshLayout} for refreshing the contents - * of a view via a vertical swipe gesture. - * @param listener {@link RefreshListener} notified when a refresh is triggered - * via the swipe gesture. - * @param progressAnimationColors Comma-separated color resource integers used in the progress - * animation. The first color will also be the color of the bar - * that grows in response to a user swipe gesture. - */ - public void init(CustomSwipeRefreshLayout swipeRefreshLayout, RefreshListener listener, - @ColorInt int backgroundColor, - @ColorRes int... progressAnimationColors) { - mRefreshListener = listener; - mSwipeRefreshLayout = swipeRefreshLayout; - mSwipeRefreshLayout.setOnRefreshListener(this); - mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(backgroundColor); - mSwipeRefreshLayout.setColorSchemeResources(progressAnimationColors); - } - - public void setRefreshing(boolean refreshing) { - mRefreshing = refreshing; - // Delayed refresh, it fixes https://code.google.com/p/android/issues/detail?id=77712 - // 50ms seems a good compromise (always worked during tests) and fast enough so user can't notice the delay - if (refreshing) { - mSwipeRefreshLayout.postDelayed(new Runnable() { - @Override - public void run() { - // use mRefreshing so if the refresh takes less than 50ms, loading indicator won't show up. - mSwipeRefreshLayout.setRefreshing(mRefreshing); - } - }, 50); - } else { - mSwipeRefreshLayout.setRefreshing(false); - } - } - - public boolean isRefreshing() { - return mSwipeRefreshLayout.isRefreshing(); - } - - @Override - public void onRefresh() { - mRefreshListener.onRefreshStarted(); - } - - public void setEnabled(boolean enabled) { - mSwipeRefreshLayout.setEnabled(enabled); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java deleted file mode 100644 index 5e0da1f6b2b4..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/Version.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.wordpress.android.util.helpers; - -//See: http://stackoverflow.com/a/11024200 -public class Version implements Comparable { - private String mVersion; - - public final String get() { - return this.mVersion; - } - - public Version(String version) { - if (version == null) { - throw new IllegalArgumentException("Version can not be null"); - } - if (!version.matches("[0-9]+(\\.[0-9]+)*")) { - throw new IllegalArgumentException("Invalid version format"); - } - this.mVersion = version; - } - - @Override public int compareTo(Version that) { - if (that == null) { - return 1; - } - String[] thisParts = this.get().split("\\."); - String[] thatParts = that.get().split("\\."); - int length = Math.max(thisParts.length, thatParts.length); - for (int i = 0; i < length; i++) { - int thisPart = i < thisParts.length - ? Integer.parseInt(thisParts[i]) : 0; - int thatPart = i < thatParts.length - ? Integer.parseInt(thatParts[i]) : 0; - if (thisPart < thatPart) { - return -1; - } - if (thisPart > thatPart) { - return 1; - } - } - return 0; - } - - @Override public boolean equals(Object that) { - if (this == that) { - return true; - } - if (that == null) { - return false; - } - if (this.getClass() != that.getClass()) { - return false; - } - return this.compareTo((Version) that) == 0; - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java deleted file mode 100644 index e8d21791b454..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPHtmlTagHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.text.Editable; -import android.text.Html; -import android.text.style.BulletSpan; -import android.text.style.LeadingMarginSpan; - -import org.xml.sax.XMLReader; - -import java.util.ArrayList; -import java.util.List; - -/** - * Handle tags that the Html class doesn't understand - * Tweaked from source at http://stackoverflow.com/questions/4044509/android-how-to-use-the-html-taghandler - */ -public class WPHtmlTagHandler implements Html.TagHandler { - private static final int SPAN_INDENT_WIDTH = 15; - - private int mListItemCount = 0; - private List mListParents = new ArrayList<>(); - - @Override - public void handleTag(final boolean opening, final String tag, Editable output, - final XMLReader xmlReader) { - if (tag != null) { - switch (tag) { - case "WPUL": - if (opening) { - mListParents.add("ul"); - } else { - mListParents.remove("ul"); - } - break; - case "WPOL": - if (opening) { - mListParents.add("ol"); - } else { - mListParents.remove("ol"); - } - break; - case "WPLI": - if (!opening) { - handleListTag(output); - } - break; - case "dd": - if (opening) { - mListParents.add("dd"); - } else { - mListParents.remove("dd"); - } - break; - } - } - } - - private void handleListTag(Editable output) { - int size = mListParents.size(); - if (size > 0 && output != null) { - if ("ul".equals(mListParents.get(size - 1))) { - output.append("\n"); - String[] split = output.toString().split("\n"); - int start = 0; - if (split.length != 1) { - int lastIndex = split.length - 1; - start = output.length() - split[lastIndex].length() - 1; - } - output.setSpan(new BulletSpan(SPAN_INDENT_WIDTH * mListParents.size()), start, output.length(), 0); - } else if ("ol".equals(mListParents.get(size - 1))) { - mListItemCount++; - output.append("\n"); - String[] split = output.toString().split("\n"); - int start = 0; - if (split.length != 1) { - int lastIndex = split.length - 1; - start = output.length() - split[lastIndex].length() - 1; - } - output.insert(start, mListItemCount + ". "); - output.setSpan(new LeadingMarginSpan.Standard(SPAN_INDENT_WIDTH * mListParents.size()), start, - output.length(), 0); - } - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java deleted file mode 100644 index 61ba1b2d4708..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPImageSpan.java +++ /dev/null @@ -1,140 +0,0 @@ -//Add WordPress image fields to ImageSpan object - -package org.wordpress.android.util.helpers; - -import android.content.Context; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.style.ImageSpan; - -public class WPImageSpan extends ImageSpan implements Parcelable { - protected Uri mImageSource = null; - protected boolean mNetworkImageLoaded = false; - protected MediaFile mMediaFile; - protected int mStartPosition, mEndPosition; - - protected WPImageSpan() { - super((Bitmap) null); - } - - public WPImageSpan(Context context, Bitmap b, Uri src) { - super(context, b); - this.mImageSource = src; - mMediaFile = new MediaFile(); - } - - public WPImageSpan(Context context, int resId, Uri src) { - super(context, resId); - this.mImageSource = src; - mMediaFile = new MediaFile(); - } - - public void setPosition(int start, int end) { - mStartPosition = start; - mEndPosition = end; - } - - public int getStartPosition() { - return mStartPosition >= 0 ? mStartPosition : 0; - } - - public int getEndPosition() { - return mEndPosition < getStartPosition() ? getStartPosition() : mEndPosition; - } - - public MediaFile getMediaFile() { - return mMediaFile; - } - - public void setMediaFile(MediaFile mediaFile) { - this.mMediaFile = mediaFile; - } - - public void setImageSource(Uri imageSource) { - this.mImageSource = imageSource; - } - - public Uri getImageSource() { - return mImageSource; - } - - public boolean isNetworkImageLoaded() { - return mNetworkImageLoaded; - } - - public void setNetworkImageLoaded(boolean networkImageLoaded) { - this.mNetworkImageLoaded = networkImageLoaded; - } - - protected void setupFromParcel(Parcel in) { - MediaFile mediaFile = new MediaFile(); - - boolean[] booleans = new boolean[2]; - in.readBooleanArray(booleans); - setNetworkImageLoaded(booleans[0]); - mediaFile.setVideo(booleans[1]); - - setImageSource(Uri.parse(in.readString())); - mediaFile.setMediaId(in.readString()); - mediaFile.setBlogId(in.readString()); - mediaFile.setPostID(in.readLong()); - mediaFile.setCaption(in.readString()); - mediaFile.setDescription(in.readString()); - mediaFile.setTitle(in.readString()); - mediaFile.setMimeType(in.readString()); - mediaFile.setFileName(in.readString()); - mediaFile.setThumbnailURL(in.readString()); - mediaFile.setVideoPressShortCode(in.readString()); - mediaFile.setFileURL(in.readString()); - mediaFile.setFilePath(in.readString()); - mediaFile.setDateCreatedGMT(in.readLong()); - mediaFile.setWidth(in.readInt()); - mediaFile.setHeight(in.readInt()); - setPosition(in.readInt(), in.readInt()); - - setMediaFile(mediaFile); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public WPImageSpan createFromParcel(Parcel in) { - WPImageSpan imageSpan = new WPImageSpan(); - imageSpan.setupFromParcel(in); - return imageSpan; - } - - public WPImageSpan[] newArray(int size) { - return new WPImageSpan[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int i) { - parcel.writeBooleanArray(new boolean[]{mNetworkImageLoaded, mMediaFile.isVideo()}); - parcel.writeString(mImageSource.toString()); - parcel.writeString(mMediaFile.getMediaId()); - parcel.writeString(mMediaFile.getBlogId()); - parcel.writeLong(mMediaFile.getPostID()); - parcel.writeString(mMediaFile.getCaption()); - parcel.writeString(mMediaFile.getDescription()); - parcel.writeString(mMediaFile.getTitle()); - parcel.writeString(mMediaFile.getMimeType()); - parcel.writeString(mMediaFile.getFileName()); - parcel.writeString(mMediaFile.getThumbnailURL()); - parcel.writeString(mMediaFile.getVideoPressShortCode()); - parcel.writeString(mMediaFile.getFileURL()); - parcel.writeString(mMediaFile.getFilePath()); - parcel.writeLong(mMediaFile.getDateCreatedGMT()); - parcel.writeInt(mMediaFile.getWidth()); - parcel.writeInt(mMediaFile.getHeight()); - parcel.writeInt(getStartPosition()); - parcel.writeInt(getEndPosition()); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java deleted file mode 100644 index 07d75e6af556..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPQuoteSpan.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.text.Layout; -import android.text.style.QuoteSpan; - -/** - * Customzed QuoteSpan for use in SpannableString's - */ -public class WPQuoteSpan extends QuoteSpan { - public static final int STRIPE_COLOR = 0xFF21759B; - private static final int STRIPE_WIDTH = 5; - private static final int GAP_WIDTH = 20; - - public WPQuoteSpan() { - super(STRIPE_COLOR); - } - - @Override - public int getLeadingMargin(boolean first) { - int margin = GAP_WIDTH * 2 + STRIPE_WIDTH; - return margin; - } - - /** - * Draw a nice thick gray bar if Ice Cream Sandwhich or newer. There's a - * bug on older devices that does not respect the increased margin. - */ - @Override - public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, - CharSequence text, int start, int end, boolean first, Layout layout) { - Paint.Style style = p.getStyle(); - int color = p.getColor(); - - p.setStyle(Paint.Style.FILL); - p.setColor(STRIPE_COLOR); - - c.drawRect(GAP_WIDTH + x, top, x + dir * STRIPE_WIDTH, bottom, p); - - p.setStyle(style); - p.setColor(color); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java deleted file mode 100644 index fbc23d069360..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPUnderlineSpan.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package org.wordpress.android.util.helpers; - -import android.os.Parcel; -import android.text.style.UnderlineSpan; - -/** - * WPUnderlineSpan is used as an alternative class to UnderlineSpan. UnderlineSpan is used by EditText auto - * correct, so it can get mixed up with our formatting. - */ -public class WPUnderlineSpan extends UnderlineSpan { - public WPUnderlineSpan() { - super(); - } - - public WPUnderlineSpan(Parcel src) { - super(src); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java deleted file mode 100644 index 119677cb00e8..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.wordpress.android.util.helpers; - -import android.app.Activity; -import android.text.TextUtils; -import android.view.View; -import android.webkit.WebChromeClient; -import android.webkit.WebView; -import android.widget.ProgressBar; - -public class WPWebChromeClient extends WebChromeClient { - private final ProgressBar mProgressBar; - private final Activity mActivity; - private final boolean mAutoUpdateActivityTitle; - - public WPWebChromeClient(Activity activity, ProgressBar progressBar) { - mActivity = activity; - mProgressBar = progressBar; - mAutoUpdateActivityTitle = true; - } - - public WPWebChromeClient(Activity activity, - ProgressBar progressBar, - boolean autoUpdateActivityTitle) { - mActivity = activity; - mProgressBar = progressBar; - mAutoUpdateActivityTitle = autoUpdateActivityTitle; - } - - public void onProgressChanged(WebView webView, int progress) { - if (mActivity != null - && !mActivity.isFinishing() - && mAutoUpdateActivityTitle - && !TextUtils.isEmpty(webView.getTitle())) { - mActivity.setTitle(webView.getTitle()); - } - if (mProgressBar != null) { - if (progress == 100) { - mProgressBar.setVisibility(View.GONE); - } else { - mProgressBar.setVisibility(View.VISIBLE); - mProgressBar.setProgress(progress); - } - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt deleted file mode 100644 index 732e831c27ac..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileCleaner.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -/** - * Prunes the Log File Store by retaining only the last `maxLogFileCount` log files. - * - * The file list is created upon instantiation – any files added - * afterwards won't be modified. - * - * @param logFileProvider: An interface where the log files will be retrieved from - * @param maxLogFileCount: The number of log files to retain - */ -class LogFileCleaner(private val logFileProvider: LogFileProviderInterface, private val maxLogFileCount: Int) { - /** - * Immediately removes all log files known to exist by this instance except for - * the most recent `maxLogFileCount` items. - */ - fun clean() { - logFileProvider.getLogFiles() - .dropLast(maxLogFileCount) - .forEach { it.delete() } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt deleted file mode 100644 index 0b59ec372b7b..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProvider.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -import android.content.Context -import java.io.File - -private const val LOG_FILE_DIRECTORY = "logs" - -/** - * A collection of helpers for Log Files. - */ -class LogFileProvider(private val logFileDirectoryPath: String) : LogFileProviderInterface { - /** - * Provides a {@link java.io.File} directory in which to store log files. - * - * If the directory doesn't already exist, it will be created. - */ - override fun getLogFileDirectory(): File { - val logFileDirectory = File(logFileDirectoryPath, LOG_FILE_DIRECTORY) - - if (!logFileDirectory.exists()) { - logFileDirectory.mkdir() - } - - return logFileDirectory - } - - /** - * Provides a list of stored log files, ordered oldest to newest. - */ - override fun getLogFiles(): List { - return getLogFileDirectory() - .listFiles() - .sortedBy { it.lastModified() } - } - - companion object { - @JvmStatic - fun fromContext(context: Context): LogFileProvider { - return LogFileProvider(context.applicationInfo.dataDir) - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt deleted file mode 100644 index e415ed5b738e..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileProviderInterface.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -import java.io.File - -/** - * An interface to retrieve log files - */ -interface LogFileProviderInterface { - fun getLogFiles(): List - - fun getLogFileDirectory(): File -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt deleted file mode 100644 index 41e900f1ec0a..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/logfile/LogFileWriter.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.wordpress.android.util.helpers.logfile - -import org.jetbrains.annotations.TestOnly -import java.io.File -import java.io.FileWriter -import java.util.Date -import org.wordpress.android.util.DateTimeUtils -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors - -/** - * A class that manages writing to a log file. - * - * This class creates and writes to a log file, and will typically persist for the entire lifecycle - * of its host application. - */ -class LogFileWriter @JvmOverloads constructor( - logFileProvider: LogFileProviderInterface, - fileId: String = DateTimeUtils.iso8601FromDate(Date()) -) { - private val file = File(logFileProvider.getLogFileDirectory(), "$fileId.log") - private val fileWriter: FileWriter = FileWriter(file) - - /** - * A serial executor used to write to the file in a background thread - */ - private val queue: ExecutorService = Executors.newSingleThreadExecutor() - - /** - * A reference to the underlying {@link Java.IO.File} file. - * Should only be used for testing. - */ - @TestOnly - fun getFile(): File = file - - /** - * Writes the provided string to the log file synchronously - */ - fun write(data: String) { - queue.execute { - fileWriter.write(data) - fileWriter.flush() - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java deleted file mode 100644 index 5f2c62e9a0b6..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/AutoResizeTextView.java +++ /dev/null @@ -1,307 +0,0 @@ -package org.wordpress.android.util.widgets; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.widget.TextView; - -import androidx.appcompat.widget.AppCompatTextView; -import androidx.core.view.ViewCompat; - -/** - * Text view that auto adjusts text size to fit within the view. - * If the text size equals the minimum text size and still does not - * fit, append with an ellipsis. - * - * See http://stackoverflow.com/a/5535672 - * - */ -public class AutoResizeTextView extends AppCompatTextView { - // Minimum text size for this text view - private static final float MIN_TEXT_SIZE = 20; - - // Interface for resize notifications - public interface OnTextResizeListener { - void onTextResize(TextView textView, float oldSize, float newSize); - } - - // Our ellipse string - Unicode Character 'HORIZONTAL ELLIPSIS' - private static final String M_ELLIPSIS = "\u2026"; - - // Registered resize listener - private OnTextResizeListener mTextResizeListener; - - // Flag for text and/or size changes to force a resize - private boolean mNeedsResize = false; - - // Text size that is set from code. This acts as a starting point for resizing - private float mTextSize; - - // Temporary upper bounds on the starting text size - private float mMaxTextSize = 0; - - // Lower bounds for text size - private float mMinTextSize = MIN_TEXT_SIZE; - - // Text view line spacing multiplier - private float mSpacingMult = 1.0f; - - // Text view additional line spacing - private float mSpacingAdd = 0.0f; - - // Add ellipsis to text that overflows at the smallest text size - private boolean mAddEllipsis = true; - - // Default constructor override - public AutoResizeTextView(Context context) { - this(context, null); - } - - // Default constructor when inflating from XML file - public AutoResizeTextView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - // Default constructor override - public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mTextSize = getTextSize(); - } - - /** - * When text changes, set the force resize flag to true and reset the text size. - */ - @Override - protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) { - mNeedsResize = true; - // Since this view may be reused, it is good to reset the text size - resetTextSize(); - } - - /** - * If the text view size changed, set the force resize flag to true - */ - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - if (w != oldw || h != oldh) { - mNeedsResize = true; - } - } - - /** - * Register listener to receive resize notifications - * @param listener - */ - public void setOnResizeListener(OnTextResizeListener listener) { - mTextResizeListener = listener; - } - - /** - * Override the set text size to update our internal reference values - */ - @Override - public void setTextSize(float size) { - super.setTextSize(size); - mTextSize = getTextSize(); - } - - /** - * Override the set text size to update our internal reference values - */ - @Override - public void setTextSize(int unit, float size) { - super.setTextSize(unit, size); - mTextSize = getTextSize(); - } - - /** - * Override the set line spacing to update our internal reference values - */ - @Override - public void setLineSpacing(float add, float mult) { - super.setLineSpacing(add, mult); - mSpacingMult = mult; - mSpacingAdd = add; - } - - /** - * Set the upper text size limit and invalidate the view - * @param maxTextSize - */ - public void setMaxTextSize(float maxTextSize) { - mMaxTextSize = maxTextSize; - requestLayout(); - invalidate(); - } - - /** - * Return upper text size limit - * @return - */ - public float getMaxTextSize() { - return mMaxTextSize; - } - - /** - * Set the lower text size limit and invalidate the view - * @param minTextSize - */ - public void setMinTextSize(float minTextSize) { - mMinTextSize = minTextSize; - requestLayout(); - invalidate(); - } - - /** - * Return lower text size limit - * @return - */ - public float getMinTextSize() { - return mMinTextSize; - } - - /** - * Set flag to add ellipsis to text that overflows at the smallest text size - * @param addEllipsis - */ - public void setAddEllipsis(boolean addEllipsis) { - mAddEllipsis = addEllipsis; - } - - /** - * Return flag to add ellipsis to text that overflows at the smallest text size - * @return - */ - public boolean getAddEllipsis() { - return mAddEllipsis; - } - - /** - * Reset the text to the original size - */ - private void resetTextSize() { - if (mTextSize > 0) { - super.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); - mMaxTextSize = mTextSize; - } - } - - /** - * Resize text after measuring - */ - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (changed || mNeedsResize) { - int widthLimit = (right - left) - getCompoundPaddingLeft() - getCompoundPaddingRight(); - int heightLimit = (bottom - top) - getCompoundPaddingBottom() - getCompoundPaddingTop(); - resizeText(widthLimit, heightLimit); - } - super.onLayout(changed, left, top, right, bottom); - } - - /** - * Resize the text size with default width and height - */ - public void resizeText() { - int heightLimit = getHeight() - getPaddingBottom() - getPaddingTop(); - int widthLimit = getWidth() - ViewCompat.getPaddingStart(this) - ViewCompat.getPaddingStart(this); - resizeText(widthLimit, heightLimit); - } - - /** - * Resize the text size with specified width and height - * @param width - * @param height - */ - @SuppressLint("SetTextI18n") public void resizeText(int width, int height) { - CharSequence text = getText(); - // Do not resize if the view does not have dimensions or there is no text - if (text == null || text.length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { - return; - } - - // Get the text view's paint object - TextPaint textPaint = getPaint(); - - // Store the current text size - float oldTextSize = textPaint.getTextSize(); - // If there is a max text size set, use the lesser of that and the default text size - float targetTextSize = mMaxTextSize > 0 ? Math.min(mTextSize, mMaxTextSize) : mTextSize; - - // Get the required text height - int textHeight = getTextHeight(text, textPaint, width, targetTextSize); - - // Until we either fit within our text view or we had reached our min text size, incrementally try smaller sizes - while (textHeight > height && targetTextSize > mMinTextSize) { - targetTextSize = Math.max(targetTextSize - 2, mMinTextSize); - textHeight = getTextHeight(text, textPaint, width, targetTextSize); - } - - // If we had reached our minimum text size and still don't fit, append an ellipsis - if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { - // Draw using a static layout - // modified: use a copy of TextPaint for measuring - TextPaint paint = new TextPaint(textPaint); - // Draw using a static layout - StaticLayout layout = new StaticLayout(text, paint, width, Layout.Alignment.ALIGN_NORMAL, - mSpacingMult, mSpacingAdd, false); - // Check that we have a least one line of rendered text - if (layout.getLineCount() > 0) { - // Since the line at the specific vertical position would be cut off, - // we must trim up to the previous line - int lastLine = layout.getLineForVertical(height) - 1; - // If the text would not even fit on a single line, clear it - if (lastLine < 0) { - setText(""); - } else { - // Otherwise, trim to the previous line and add an ellipsis - int start = layout.getLineStart(lastLine); - int end = layout.getLineEnd(lastLine); - float lineWidth = layout.getLineWidth(lastLine); - float ellipseWidth = paint.measureText(M_ELLIPSIS); - - // Trim characters off until we have enough room to draw the ellipsis - while (width < lineWidth + ellipseWidth) { - lineWidth = paint.measureText(text.subSequence(start, --end + 1).toString()); - } - if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) { - setText(M_ELLIPSIS + text.subSequence(0, end)); - } else { - setText(text.subSequence(0, end) + M_ELLIPSIS); - } - } - } - } - - // Some devices try to auto adjust line spacing, so force default line spacing - // and invalidate the layout as a side effect - setTextSize(TypedValue.COMPLEX_UNIT_PX, targetTextSize); - setLineSpacing(mSpacingAdd, mSpacingMult); - - // Notify the listener if registered - if (mTextResizeListener != null) { - mTextResizeListener.onTextResize(this, oldTextSize, targetTextSize); - } - - // Reset force resize flag - mNeedsResize = false; - } - - // Set the text size of the text paint object and use a static layout to render text off screen before measuring - private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) { - // modified: make a copy of the original TextPaint object for measuring - // (apparently the object gets modified while measuring, see also the - // docs for TextView.getPaint() (which states to access it read-only) - TextPaint paintCopy = new TextPaint(paint); - // Update the text paint object - paintCopy.setTextSize(textSize); - // Measure using a static layout - StaticLayout layout = new StaticLayout(source, paintCopy, width, Layout.Alignment.ALIGN_NORMAL, - mSpacingMult, mSpacingAdd, true); - return layout.getHeight(); - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java deleted file mode 100644 index 91c72674d487..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/CustomSwipeRefreshLayout.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.wordpress.android.util.widgets; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.AppLog.T; - -public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { - public CustomSwipeRefreshLayout(Context context) { - super(context); - } - - public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - try { - return super.onTouchEvent(event); - } catch (IllegalArgumentException e) { - // Fix for https://github.com/wordpress-mobile/WordPress-Android/issues/2373 - // Catch IllegalArgumentException which can be fired by the underlying SwipeRefreshLayout.onTouchEvent() - // method. - // When android support-v4 fixes it, we'll have to remove that custom layout completely. - AppLog.e(T.UTILS, e); - return true; - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java deleted file mode 100644 index 2c3951c61ec5..000000000000 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/widgets/WPTextInputLayout.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.wordpress.android.util.widgets; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.widget.EditText; - -import com.google.android.material.textfield.TextInputLayout; - -import org.wordpress.android.util.R; - -/** - * Custom TextInputLayout to provide a usable getBaseline() and error view padding - */ -public class WPTextInputLayout extends TextInputLayout { - public WPTextInputLayout(Context context) { - super(context); - } - - public WPTextInputLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public WPTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - public int getBaseline() { - EditText editText = getEditText(); - return editText != null ? editText.getBaseline() - editText.getPaddingBottom() - + getResources().getDimensionPixelSize(R.dimen.textinputlayout_baseline_correction) - : 0; - } - - @Override - public void setErrorEnabled(boolean enabled) { - super.setErrorEnabled(enabled); - - // remove hardcoded side padding of the error view - if (enabled) { - View errorView = findViewById(com.google.android.material.R.id.textinput_error); - if (errorView != null && errorView.getParent() != null) { - ((View) errorView.getParent()) - .setPadding(0, errorView.getPaddingTop(), 0, errorView.getPaddingBottom()); - } - } - } -} diff --git a/libs/utils/WordPressUtils/src/main/res/values/dimens.xml b/libs/utils/WordPressUtils/src/main/res/values/dimens.xml deleted file mode 100644 index 4f3fdecd3158..000000000000 --- a/libs/utils/WordPressUtils/src/main/res/values/dimens.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 2dp - 4.3dp - -8.6dp - diff --git a/libs/utils/WordPressUtils/src/main/res/values/strings.xml b/libs/utils/WordPressUtils/src/main/res/values/strings.xml deleted file mode 100644 index 34d25dada509..000000000000 --- a/libs/utils/WordPressUtils/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - There is no network available - Now - diff --git a/libs/utils/WordPressUtils/src/main/res/values/tags.xml b/libs/utils/WordPressUtils/src/main/res/values/tags.xml deleted file mode 100644 index 796e3fab2be0..000000000000 --- a/libs/utils/WordPressUtils/src/main/res/values/tags.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java deleted file mode 100644 index a6ae733607e5..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/DateTimeUtilsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.wordpress.android.util; - -import org.junit.Ignore; -import org.junit.Test; - -import java.util.Date; -import java.util.TimeZone; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DateTimeUtilsTest { - private final long mDefaultDate = 1564484058163L; // it's Tue Jul 30 2019 10:54:18 in UTC - - @Test - public void testIso8601UTCFromDate() { - // Arrange - TimeZone.setDefault(TimeZone.getTimeZone("GMT+2:00")); - Date date = new Date(mDefaultDate); - String expected = "2019-07-30T10:54:18+00:00"; - - // Act - String actual = DateTimeUtils.iso8601UTCFromDate(date); - - // Assert - assertThat(actual).isEqualTo(expected); - } - - @Test - @Ignore(value = "This test is failing because `DateTimeUtils.localDateToUTC` doesn't work as expected. I've " - + "marked it as deprecated and this tests serves just as a documentation.") - public void testLocalDateToUTC() { - // Arrange - TimeZone.setDefault(TimeZone.getTimeZone("GMT+2:00")); - Date date = new Date(mDefaultDate); - // this succeeds - assertThat(DateTimeUtils.iso8601FromDate(date)).isEqualTo("2019-07-30T12:54:18+0200"); - - // Act - String actual = DateTimeUtils.iso8601FromDate(DateTimeUtils.localDateToUTC(date)); - - // Assert - - // fails because `localDateToUTC` doesn't work as expected. See DateTimeUtils.localDateToUTC for more info. - assertThat(actual).isEqualTo("2019-07-30T10:54:18+00:00"); - } -} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt deleted file mode 100644 index 71789bd844dc..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileCleanerTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -package org.wordpress.android.util - -import android.content.Context -import android.os.Build -import androidx.test.core.app.ApplicationProvider -import java.io.File -import java.io.FileReader -import kotlin.random.Random -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.util.helpers.logfile.LogFileCleaner -import org.wordpress.android.util.helpers.logfile.LogFileProvider - -/** - * The number of test files to create for each test run - */ -private const val MAX_FILES = 10 - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1]) -class LogFileCleanerTest { - private lateinit var logFileProvider: LogFileProvider - - @Before - fun setup() { - val context: Context = ApplicationProvider.getApplicationContext() - logFileProvider = LogFileProvider.fromContext(context) - - repeat(MAX_FILES) { - val file = File(logFileProvider.getLogFileDirectory(), "$it.log") - file.writeText("$it") - file.setLastModified(it * 10_000L) - } - - assert(logFileProvider.getLogFileDirectory().listFiles().count() == MAX_FILES) - } - - @After - fun tearDown() { - // Delete the test directory after each test - logFileProvider.getLogFileDirectory().deleteRecursively() - } - - @Test - fun testThatCleanerPreservesMostRecentlyCreatedFiles() { - val maxLogFileCount = Random.nextInt(MAX_FILES) - LogFileCleaner(logFileProvider, maxLogFileCount).clean() - - // Strings are easier to assert against than arrays - val remainingFileIds = logFileProvider.getLogFiles().joinToString(",") { - FileReader(it).readText() - } - - val expectedValue = (MAX_FILES - 1 downTo 0).take(maxLogFileCount).reversed().joinToString(",") - assertEquals(expectedValue, remainingFileIds) - } - - @Test - fun testThatCleanerPreservesCorrectNumberOfFiles() { - val numberOfFiles = Random.nextInt(MAX_FILES) - LogFileCleaner(logFileProvider, numberOfFiles).clean() - assertEquals(numberOfFiles, logFileProvider.getLogFileDirectory().listFiles().count()) - } - - @Test - fun testThatCleanerErasesAllFilesIfGivenZero() { - LogFileCleaner(logFileProvider, 0).clean() - assert(logFileProvider.getLogFileDirectory().listFiles().isEmpty()) - } -} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt deleted file mode 100644 index e4921c21e750..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileHelpersTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -package org.wordpress.android.util - -import android.content.Context -import android.os.Build -import androidx.test.core.app.ApplicationProvider -import java.io.File -import java.util.UUID -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.util.helpers.logfile.LogFileProvider - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1]) -class LogFileHelpersTest { - private lateinit var testProvider: LogFileProvider - - @Before - fun setup() { - val context: Context = ApplicationProvider.getApplicationContext() - testProvider = LogFileProvider.fromContext(context) - } - - @After - fun tearDown() { - // Delete the test directory after each test - testProvider.getLogFileDirectory().deleteRecursively() - } - - @Test - fun testThatLogFileDirectoryIsCreatedIfNotExists() { - val directory = testProvider.getLogFileDirectory() - assert(directory.exists()) - } - - @Test - fun testThatLogFilesListsAllFiles() { - val directory = testProvider.getLogFileDirectory() - File(directory, UUID.randomUUID().toString()).createNewFile() - Assert.assertEquals(testProvider.getLogFiles().count(), 1) - } - - @Test - fun testThatLogFilesSortsFilesWithMostRecentFirst() { - val directory = testProvider.getLogFileDirectory() - - listOf(1_000L, 1_000_000L).shuffled().forEach { modifiedDate -> - File(directory, UUID.randomUUID().toString()).also { file -> - // Use timestamps in increments of 1000 to avoid issues from the File System's date precision - val date = modifiedDate * 1000 - file.createNewFile() - file.setLastModified(date) - assert(file.lastModified() == date) - } - } - - val files = testProvider.getLogFiles() - assert(files.first().lastModified() < files.last().lastModified()) - } -} diff --git a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt b/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt deleted file mode 100644 index 998a29398783..000000000000 --- a/libs/utils/WordPressUtils/src/test/java/org/wordpress/android/util/LogFileWriterTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.wordpress.android.util - -import android.content.Context -import android.os.Build -import androidx.test.core.app.ApplicationProvider -import java.io.FileReader -import java.util.UUID -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.util.helpers.logfile.LogFileProvider -import org.wordpress.android.util.helpers.logfile.LogFileWriter - -@RunWith(RobolectricTestRunner::class) -@Config(sdk = [Build.VERSION_CODES.O_MR1]) -class LogFileWriterTest { - private lateinit var testProvider: LogFileProvider - - @Before - fun setup() { - val context: Context = ApplicationProvider.getApplicationContext() - testProvider = LogFileProvider.fromContext(context) - } - - @After - fun tearDown() { - // Delete the test directory after each test - testProvider.getLogFileDirectory().deleteRecursively() - } - - @Test - fun testThatFileWriterCreatesLogFile() { - val writer = LogFileWriter(testProvider) - assert(writer.getFile().exists()) - } - - @Test - fun testThatContentsAreWrittenToFile() { - val randomString = UUID.randomUUID().toString() - val writer = LogFileWriter(testProvider) - writer.write(randomString) - - // Allow the async process to persist the file changes - Thread.sleep(1000) - - val contents = FileReader(writer.getFile()).readText() - assertEquals(randomString, contents) - } -} diff --git a/libs/utils/build.gradle b/libs/utils/build.gradle deleted file mode 100644 index ebb5278a193c..000000000000 --- a/libs/utils/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -buildscript { - repositories { - jcenter() - } - - dependencies { - classpath 'com.automattic.android:fetchstyle:1.1' - } -} - -apply plugin: 'com.automattic.android.fetchstyle' - -allprojects { - apply plugin: 'checkstyle' - - repositories { - jcenter() - maven { - url "https://maven.google.com" - } - } - - if (tasks.findByPath('checkstyle') == null) { - tasks.create(name: 'checkstyle', type: Checkstyle) { - source 'src' - - classpath = files() - } - - checkstyle { - toolVersion = '8.3' - configFile file("${project.rootDir}/config/checkstyle.xml") - } - } - - // Suppress false Javadoc lint errors preventing Bintray release - // See https://stackoverflow.com/questions/34828426/disable-javadoc-check-for-bintray-upload - tasks.withType(Javadoc) { - options.addBooleanOption('Xdoclint:none', true) - } -} diff --git a/libs/utils/config/checkstyle.xml b/libs/utils/config/checkstyle.xml deleted file mode 100644 index 2ebaaac1412c..000000000000 --- a/libs/utils/config/checkstyle.xml +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/utils/gradle.properties-example b/libs/utils/gradle.properties-example deleted file mode 100644 index 5bac8ac50462..000000000000 --- a/libs/utils/gradle.properties-example +++ /dev/null @@ -1 +0,0 @@ -android.useAndroidX=true diff --git a/libs/utils/gradle/wrapper/gradle-wrapper.jar b/libs/utils/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index f3d88b1c2faf2fc91d853cd5d4242b5547257070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58695 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 diff --git a/libs/utils/gradle/wrapper/gradle-wrapper.properties b/libs/utils/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 4e1cc9db6b59..000000000000 --- a/libs/utils/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/libs/utils/gradlew b/libs/utils/gradlew deleted file mode 100755 index 2fe81a7d95e4..000000000000 --- a/libs/utils/gradlew +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or 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 -## -############################################################################## - -# 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 -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$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='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# 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 - ;; -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" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - 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 -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 -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 - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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\"" - fi - i=`expr $i + 1` - 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" - -exec "$JAVACMD" "$@" diff --git a/libs/utils/gradlew.bat b/libs/utils/gradlew.bat deleted file mode 100644 index 62bd9b9ccefe..000000000000 --- a/libs/utils/gradlew.bat +++ /dev/null @@ -1,103 +0,0 @@ -@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 -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -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="-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 - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -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% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/libs/utils/settings.gradle b/libs/utils/settings.gradle deleted file mode 100644 index 3519745edd00..000000000000 --- a/libs/utils/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':WordPressUtils' \ No newline at end of file From 0e16a990a348ae2b0afe72a2bbe4cc5ab482cc31 Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Tue, 24 Nov 2020 12:33:29 +0100 Subject: [PATCH 015/144] Remove WPUtils stuff from CI config Silence a wrong lint error Suppress lint issues on local builds Fix unused resource warning Silence lint errors Revert "Silence lint errors" This reverts commit 57449da95c0d685d97ea4c5191ef80e3e5b49352. Revert "Fix unused resource warning" This reverts commit b70fed75cc64a89a05a3910b2cb243b8250f27ca. Revert "Suppress lint issues on local builds" This reverts commit af3cbeff9b0d7d34ae313c77111350e88aac08ba. Revert "Silence a wrong lint error" This reverts commit e911e43f196bc2d54d8511e70de88e6a1499dead. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 699243233190..4fb8accf2ff6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,7 @@ commands: steps: - run: name: Setup gradle.properties - command: cp gradle.properties-example gradle.properties && cp libs/utils/WordPressUtils/gradle.properties-example libs/utils/WordPressUtils/gradle.properties + command: cp gradle.properties-example gradle.properties update-gradle-memory: parameters: jvmargs: From 4c84a981dc63ece16246c48251832bc62e7510e9 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Fri, 27 Nov 2020 13:48:07 +0900 Subject: [PATCH 016/144] Change substitution path for local utils build --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 6417b09c1b95..44db8e9da53d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -85,7 +85,7 @@ if (localBuilds.exists()) { includeBuild(ext.localWPUtilsPath) { dependencySubstitution { println "Substituting wputils with the local build" - substitute module("$gradle.ext.wputilsBinaryPath") with project(':WordPressUtils') + substitute module("$gradle.ext.wputilsBinaryPath:WordPressUtils") with project(':WordPressUtils') } } } From 4be841e007be0ad40736646f839ac42e74cd0995 Mon Sep 17 00:00:00 2001 From: develric Date: Wed, 2 Dec 2020 00:49:08 +0100 Subject: [PATCH 017/144] Adding a base WebChromeClientWithVideoPoster that provides getDefaultVideoPoster. --- .../helpers/WebChromeClientWithVideoPoster.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WebChromeClientWithVideoPoster.kt diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WebChromeClientWithVideoPoster.kt b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WebChromeClientWithVideoPoster.kt new file mode 100644 index 000000000000..eccdfb2d6581 --- /dev/null +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WebChromeClientWithVideoPoster.kt @@ -0,0 +1,20 @@ +package org.wordpress.android.util.helpers + +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.view.View +import android.webkit.WebChromeClient +import androidx.annotation.DrawableRes + +abstract class WebChromeClientWithVideoPoster( + view: View?, + @DrawableRes defaultVideoPosterRes: Int +) : WebChromeClient() { + private val defaultPoster: Bitmap? = view?.context?.let { + BitmapFactory.decodeResource(it.resources, defaultVideoPosterRes) + } + + final override fun getDefaultVideoPoster(): Bitmap? { + return super.getDefaultVideoPoster() ?: defaultPoster + } +} From bb7736d51c497e85f76a8354911c9a29818e694f Mon Sep 17 00:00:00 2001 From: develric Date: Wed, 2 Dec 2020 00:50:50 +0100 Subject: [PATCH 018/144] Using new base class in ReaderWebView and ReaderVideoViewerActivity. --- .../android/ui/reader/ReaderVideoViewerActivity.java | 4 ++-- .../wordpress/android/ui/reader/views/ReaderWebView.java | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java index 979c045357ac..819262ab700c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java @@ -3,7 +3,6 @@ import android.graphics.Color; import android.os.Bundle; import android.view.View; -import android.webkit.WebChromeClient; import android.webkit.WebView; import android.widget.ProgressBar; @@ -12,6 +11,7 @@ import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.ui.LocaleAwareActivity; +import org.wordpress.android.util.helpers.WebChromeClientWithVideoPoster; /** * Full screen landscape video player for the reader @@ -33,7 +33,7 @@ public void onCreate(Bundle savedInstanceState) { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setUserAgentString(WordPress.getUserAgent()); - mWebView.setWebChromeClient(new WebChromeClient() { + mWebView.setWebChromeClient(new WebChromeClientWithVideoPoster(mWebView, R.drawable.media_image_placeholder) { public void onProgressChanged(WebView view, int progress) { if (progress == 100) { mProgress.setVisibility(View.GONE); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java index ed775561bcbb..454a9c3020bb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java @@ -11,17 +11,18 @@ import android.view.View; import android.view.ViewGroup; import android.webkit.CookieManager; -import android.webkit.WebChromeClient; import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; +import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.ui.WPWebView; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.UrlUtils; import org.wordpress.android.util.WPUrlUtils; +import org.wordpress.android.util.helpers.WebChromeClientWithVideoPoster; import java.io.IOException; import java.net.HttpURLConnection; @@ -260,6 +261,8 @@ private static class ReaderWebViewClient extends WebViewClient { mReaderWebView = readerWebView; } + + @Override public void onPageFinished(WebView view, String url) { if (mReaderWebView.hasPageFinishedListener()) { @@ -312,12 +315,13 @@ public WebResourceResponse shouldInterceptRequest(WebView view, String url) { } } - private static class ReaderWebChromeClient extends WebChromeClient { + private static class ReaderWebChromeClient extends WebChromeClientWithVideoPoster { private final ReaderWebView mReaderWebView; private View mCustomView; private CustomViewCallback mCustomViewCallback; ReaderWebChromeClient(ReaderWebView readerWebView) { + super(readerWebView, R.drawable.media_image_placeholder); if (readerWebView == null) { throw new IllegalArgumentException("ReaderWebChromeClient requires readerWebView"); } From 0734ea93a13b53537862df1202da7aaf5892332e Mon Sep 17 00:00:00 2001 From: develric Date: Wed, 2 Dec 2020 01:12:31 +0100 Subject: [PATCH 019/144] Using new base class in WPWebChromeClient. --- .../wordpress/android/ui/WPWebViewActivity.java | 7 ++++++- .../android/util/helpers/WPWebChromeClient.java | 15 +++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java index 2e7eade5cc39..6791e6ce3c05 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java @@ -681,7 +681,12 @@ protected void configureWebView() { WebViewClient webViewClient = createWebViewClient(allowedURL); mWebView.setWebViewClient(webViewClient); - mWebView.setWebChromeClient(new WPWebChromeClient(this, (ProgressBar) findViewById(R.id.progress_bar))); + mWebView.setWebChromeClient(new WPWebChromeClient( + this, + mWebView, + R.drawable.media_image_placeholder, + (ProgressBar) findViewById(R.id.progress_bar) + )); } protected WebViewClient createWebViewClient(List allowedURL) { diff --git a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java index 119677cb00e8..52f785e162d9 100644 --- a/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java +++ b/libs/utils/WordPressUtils/src/main/java/org/wordpress/android/util/helpers/WPWebChromeClient.java @@ -3,24 +3,27 @@ import android.app.Activity; import android.text.TextUtils; import android.view.View; -import android.webkit.WebChromeClient; import android.webkit.WebView; import android.widget.ProgressBar; -public class WPWebChromeClient extends WebChromeClient { +import androidx.annotation.DrawableRes; + + +public class WPWebChromeClient extends WebChromeClientWithVideoPoster { private final ProgressBar mProgressBar; private final Activity mActivity; private final boolean mAutoUpdateActivityTitle; - public WPWebChromeClient(Activity activity, ProgressBar progressBar) { - mActivity = activity; - mProgressBar = progressBar; - mAutoUpdateActivityTitle = true; + public WPWebChromeClient(Activity activity, View view, @DrawableRes int defaultPoster, ProgressBar progressBar) { + this(activity, view, defaultPoster, progressBar, true); } public WPWebChromeClient(Activity activity, + View view, + @DrawableRes int defaultPoster, ProgressBar progressBar, boolean autoUpdateActivityTitle) { + super(view, defaultPoster); mActivity = activity; mProgressBar = progressBar; mAutoUpdateActivityTitle = autoUpdateActivityTitle; From 570ba66e5b2bf4f6b372773c1ea3b4e751c9712b Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Wed, 2 Dec 2020 10:34:27 +0900 Subject: [PATCH 020/144] Only show story block in picker if supported by site --- .../java/org/wordpress/android/ui/posts/EditPostActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index c341ccc82924..73ce54345a57 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -2307,7 +2307,7 @@ private GutenbergPropsBuilder getGutenbergPropsBuilder() { boolean unsupportedBlockEditorSwitch = !mIsJetpackSsoEnabled && "gutenberg".equals(mSite.getWebEditor()); return new GutenbergPropsBuilder( - mWPStoriesFeatureConfig.isEnabled(), + mWPStoriesFeatureConfig.isEnabled() && SiteUtils.supportsStoriesFeature(mSite), enableMentions, isUnsupportedBlockEditorEnabled, unsupportedBlockEditorSwitch, From 7fc2f749e78452b85bfd4fae432c5b3bb4ffe3c5 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Tue, 1 Dec 2020 20:47:19 -0300 Subject: [PATCH 021/144] only allow updating a Post to the server when a Story is finished being saved, to avoid sending a Post containing a story block with temporary ids --- .../android/ui/posts/EditPostActivity.java | 38 +++++++++++++++++-- .../ui/posts/editor/StoriesEventListener.kt | 10 +++++ WordPress/src/main/res/values/strings.xml | 1 + 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index c341ccc82924..ee35d50ea1f7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -1323,12 +1323,34 @@ private boolean handleBackPressed() { } else if (mEditorPhotoPicker.isPhotoPickerShowing()) { mEditorPhotoPicker.hidePhotoPicker(); } else { - savePostAndOptionallyFinish(true, false); + performWhenNoStoriesBeingSaved(new DoWhenNoStoriesBeingSavedCallback() { + @Override public void doWhenNoStoriesBeingSaved() { + savePostAndOptionallyFinish(true, false); + } + }); } return true; } + interface DoWhenNoStoriesBeingSavedCallback { + void doWhenNoStoriesBeingSaved(); + } + + private void performWhenNoStoriesBeingSaved(DoWhenNoStoriesBeingSavedCallback callback) { + if (mWPStoriesFeatureConfig.isEnabled()) { + if (mStoriesEventListener.getStoriesSavingInProgress().isEmpty()) { + callback.doWhenNoStoriesBeingSaved(); + } else { + // Oops! A story is still being saved, let's wait + ToastUtils.showToast(EditPostActivity.this, + getString(R.string.toast_edit_story_update_in_progress_title)); + } + } else { + callback.doWhenNoStoriesBeingSaved(); + } + } + private RemotePreviewLogicHelper.RemotePreviewHelperFunctions getEditPostActivityStrategyFunctions() { return new RemotePreviewLogicHelper.RemotePreviewHelperFunctions() { @Override @@ -1500,7 +1522,7 @@ private boolean performSecondaryAction() { case PUBLISH_NOW: mAnalyticsTrackerWrapper.track(Stat.EDITOR_POST_PUBLISH_TAPPED); mPublishPostImmediatelyUseCase.updatePostToPublishImmediately(mEditPostRepository, mIsNewPost); - showPrepublishingNudgeBottomSheet(); + checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet(); return true; case NONE: throw new IllegalStateException("Switch in `secondaryAction` shouldn't go through the NONE case"); @@ -1612,12 +1634,12 @@ private void performPrimaryAction() { switch (getPrimaryAction()) { case PUBLISH_NOW: mAnalyticsTrackerWrapper.track(Stat.EDITOR_POST_PUBLISH_TAPPED); - showPrepublishingNudgeBottomSheet(); + checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet(); return; case UPDATE: case SCHEDULE: case SUBMIT_FOR_REVIEW: - showPrepublishingNudgeBottomSheet(); + checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet(); return; case SAVE: uploadPost(false); @@ -2015,6 +2037,14 @@ private void setupPrepublishingBottomSheetRunnable() { }; } + private void checkNoStorySaveOperationInProgressAndShowPrepublishingNudgeBottomSheet() { + performWhenNoStoriesBeingSaved(new DoWhenNoStoriesBeingSavedCallback() { + @Override public void doWhenNoStoriesBeingSaved() { + showPrepublishingNudgeBottomSheet(); + } + }); + } + private void showPrepublishingNudgeBottomSheet() { mViewPager.setCurrentItem(PAGE_CONTENT); ActivityUtils.hideKeyboard(this); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt index b8559f5a8bf0..d718edcabdca 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/editor/StoriesEventListener.kt @@ -13,7 +13,9 @@ import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveCompleted import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveFailed import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveProgress import com.wordpress.stories.compose.frame.StorySaveEvents.FrameSaveStart +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveProcessStart import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import com.wordpress.stories.compose.story.StoryIndex import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.R @@ -58,6 +60,8 @@ class StoriesEventListener @Inject constructor( private lateinit var site: SiteModel private lateinit var editPostRepository: EditPostRepository private var storySaveMediaListener: StorySaveMediaListener? = null + var storiesSavingInProgress = HashSet() + private set @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) private fun onCreate() { @@ -168,6 +172,7 @@ class StoriesEventListener @Inject constructor( @Subscribe(threadMode = ThreadMode.MAIN) fun onStorySaveProcessFinished(event: StorySaveResult) { + storiesSavingInProgress.remove(event.storyIndex) if (!lifecycle.currentState.isAtLeast(CREATED)) { return } @@ -179,6 +184,11 @@ class StoriesEventListener @Inject constructor( } } + @Subscribe(threadMode = ThreadMode.MAIN) + fun onStorySaveStart(event: StorySaveProcessStart) { + storiesSavingInProgress.add(event.storyIndex) + } + // Editor load / cancel events fun onRequestMediaFilesEditorLoad( activity: Activity, diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 732fff4d611c..e543f3d4310e 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2958,6 +2958,7 @@ We couldn\'t find the media for this story on the site. GIF files not supported One or more slides have not been added to your Story because Stories don\'t support GIF files at the moment. Please choose a static image or video background instead. + Story being saved, please wait… Capture Flip camera Flash From 41dd63573c4422b0ae2715c920647a16c0a94bc8 Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Wed, 2 Dec 2020 19:03:45 +0100 Subject: [PATCH 022/144] Skip prechecks on release builds on CI --- fastlane/Fastfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 521771446c23..978cf887f692 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -241,11 +241,12 @@ ENV["validate_translations"]="lintVanillaRelease" # This lane builds the final release of the app and uploads it # ----------------------------------------------------------------------------------- # Usage: - # bundle exec fastlane build_and_upload_release [skip_confirm:] [create_release: ] + # bundle exec fastlane build_and_upload_release [skip_confirm:] [skip_prechecks:] [create_release: ] # # Example: # bundle exec fastlane build_and_upload_release # bundle exec fastlane build_and_upload_release skip_confirm:true + # bundle exec fastlane build_and_upload_release skip_prechecks:true # bundle exec fastlane build_and_upload_release create_release:true ##################################################################################### desc "Builds and updates for distribution" @@ -254,7 +255,7 @@ ENV["validate_translations"]="lintVanillaRelease" alpha: false, beta: false, final: true) - android_build_preflight() + android_build_preflight() unless (options[:skip_prechecks]) # Create the file names version=android_get_release_version() From 9231083bad077faa86cb0b744c65b046bc33fd28 Mon Sep 17 00:00:00 2001 From: develric Date: Wed, 2 Dec 2020 23:46:45 +0100 Subject: [PATCH 023/144] Using media_movieclip as poster placeholder. --- .../main/java/org/wordpress/android/ui/WPWebViewActivity.java | 2 +- .../wordpress/android/ui/reader/ReaderVideoViewerActivity.java | 2 +- .../org/wordpress/android/ui/reader/views/ReaderWebView.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java index 6791e6ce3c05..050aa4000948 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java @@ -684,7 +684,7 @@ protected void configureWebView() { mWebView.setWebChromeClient(new WPWebChromeClient( this, mWebView, - R.drawable.media_image_placeholder, + R.drawable.media_movieclip, (ProgressBar) findViewById(R.id.progress_bar) )); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java index 819262ab700c..49437736da92 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderVideoViewerActivity.java @@ -33,7 +33,7 @@ public void onCreate(Bundle savedInstanceState) { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setUserAgentString(WordPress.getUserAgent()); - mWebView.setWebChromeClient(new WebChromeClientWithVideoPoster(mWebView, R.drawable.media_image_placeholder) { + mWebView.setWebChromeClient(new WebChromeClientWithVideoPoster(mWebView, R.drawable.media_movieclip) { public void onProgressChanged(WebView view, int progress) { if (progress == 100) { mProgress.setVisibility(View.GONE); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java index 454a9c3020bb..5e23eebeae62 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java @@ -321,7 +321,7 @@ private static class ReaderWebChromeClient extends WebChromeClientWithVideoPoste private CustomViewCallback mCustomViewCallback; ReaderWebChromeClient(ReaderWebView readerWebView) { - super(readerWebView, R.drawable.media_image_placeholder); + super(readerWebView, R.drawable.media_movieclip); if (readerWebView == null) { throw new IllegalArgumentException("ReaderWebChromeClient requires readerWebView"); } From 9a2e3a44729cb9804a1217def70b20363f4fb774 Mon Sep 17 00:00:00 2001 From: develric Date: Wed, 2 Dec 2020 23:47:13 +0100 Subject: [PATCH 024/144] Setting WebChromeClientWithVideoPoster as base class for PublicizeWebChromeClient. --- .../android/ui/publicize/PublicizeWebViewFragment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java index 4abb649881cd..d7eea88d0e00 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java @@ -26,6 +26,7 @@ import org.wordpress.android.ui.WPWebViewActivity; import org.wordpress.android.ui.publicize.PublicizeConstants.ConnectAction; import org.wordpress.android.util.WebViewUtils; +import org.wordpress.android.util.helpers.WebChromeClientWithVideoPoster; import javax.inject.Inject; @@ -192,9 +193,9 @@ public void onPageFinished(WebView view, String url) { } } - private class PublicizeWebChromeClient extends WebChromeClient { + private class PublicizeWebChromeClient extends WebChromeClientWithVideoPoster { PublicizeWebChromeClient() { - super(); + super(mWebView, R.drawable.media_movieclip); } @Override From a07a10e5b9fc42ad24001b0713f889d05fb90506 Mon Sep 17 00:00:00 2001 From: develric Date: Thu, 3 Dec 2020 00:10:52 +0100 Subject: [PATCH 025/144] Fixing linter. --- .../wordpress/android/ui/publicize/PublicizeWebViewFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java index d7eea88d0e00..2a284e76a5e4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/publicize/PublicizeWebViewFragment.java @@ -6,7 +6,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; From 1f43fd94fd03eef4bd7aea2c0c5d84ff465384fd Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Thu, 3 Dec 2020 13:06:59 +0900 Subject: [PATCH 026/144] Calculate end index of Story block relative to start Fixes a StringIndexOutOfBoundsException when the Story block is not the first block in the post. Previously the end of the first block would be matched, causing the substring end index to be earlier than the start index. --- .../android/ui/stories/SaveStoryGutenbergBlockUseCase.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt index 8dae05f35665..65c3ed0fce73 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/SaveStoryGutenbergBlockUseCase.kt @@ -101,9 +101,10 @@ class SaveStoryGutenbergBlockUseCase @Inject constructor( while (storyBlockStartIndex > -1 && storyBlockStartIndex < content.length) { storyBlockStartIndex = content.indexOf(HEADING_START, storyBlockStartIndex) if (storyBlockStartIndex > -1) { + val storyBlockEndIndex = content.indexOf(HEADING_END, storyBlockStartIndex) val jsonString: String = content.substring( storyBlockStartIndex + HEADING_START.length, - content.indexOf(HEADING_END)) + storyBlockEndIndex) content = listener.doWithMediaFilesJson(content, jsonString) storyBlockStartIndex += HEADING_START.length } From 76bec26dc8abb1248d6833daae388546c868276d Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Thu, 3 Dec 2020 13:33:19 +0900 Subject: [PATCH 027/144] Update Story intro screen assets and links --- .../ui/stories/intro/StoriesIntroViewModel.kt | 4 ++-- .../drawable-hdpi/stories_intro_cover_1.png | Bin 161615 -> 131960 bytes .../drawable-hdpi/stories_intro_cover_2.png | Bin 143374 -> 135676 bytes .../drawable-xhdpi/stories_intro_cover_1.png | Bin 253706 -> 197496 bytes .../drawable-xhdpi/stories_intro_cover_2.png | Bin 211074 -> 199284 bytes 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt index de217a9e9816..a2d64f8343a3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/intro/StoriesIntroViewModel.kt @@ -56,8 +56,8 @@ class StoriesIntroViewModel @Inject constructor( } companion object { - private const val STORY_URL_1 = "https://wpstories.wordpress.com/2020/10/12/patagonia-2/" - private const val STORY_URL_2 = "https://wpstories.wordpress.com/2020/10/12/hiking-in-the-southwest/" + private const val STORY_URL_1 = "https://wpstories.wordpress.com/2020/12/02/story-demo-01/" + private const val STORY_URL_2 = "https://wpstories.wordpress.com/2020/12/02/story-demo-02/" private const val STORY_FULLSCREEN_URL_PARAMS = "?wp-story-load-in-fullscreen=true&wp-story-play-on-load=true" } } diff --git a/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_1.png b/WordPress/src/main/res/drawable-hdpi/stories_intro_cover_1.png index fb0f763f0735eb47b01ab3a409601c994a87f127..9a8f74d1815a1c67c695e3e7a6718a21a2fc6f31 100644 GIT binary patch literal 131960 zcmY(q1yEc;vnY(aySuyV0>RzgT{aNh-QC>@?oM!mEWw>5K+wf4u(-p^ckli0|K6!O zH9b8o)2BwdyZXdwsL7+Fkf1<8L7^)u$Y}j*XP}^m9}XX04i|TOPHtggVNNa{P97fie-!KtXEQ9;26Fyqgp-?t zi}QbF|6>LG2P>lP4z&HJ`9Jc-xdH!0`TyYlM-PDWKg$2F$^5sa|AqZ$syGUO^M5~^ zIEu;$qahU3Cn!Z3NgZG4^8v?1+cmFkpNmExFWtc^d1(xJD>uF}rUX1@4VtV~&D>*4 zg;+Quqyr);7-LBoX-y~)as`~^S4}di*6;ff*6>(Z#H|*iND`|SXc=v6`DOI+&85+W zg7#I_)dA0M7j;cdJ_ipk%>ypm&KS(d3WuygsImT{zU)9RrGU z_Vw@ViaLpNxj6@@T&rI3$I)(gT@Rv9$$0f+Rt%yyZ)3QqpUoq>ejDmiE{OhE9(n^> zRJpz9z3oYOBuh|7!2HGk{d%adv8*mZ?*9e^tPpj_UEcvljxXmCSOZ<}I-;k$ONU{2 z=t{uZ9Gm+^{s?LS->PNC*ABkrJv3!R!v4W~$3cdoxn(X{$MEI@j?IwokY<%1TEf!*x*^BSn$thlEG_2dBk_5?`WRxn$V;Y4iIjH9Rr6M&MGep8YTY1L<~tkQnu4 z&#J6uiz`IR12h-**@ls-{_8qg4%<^8yBbM^ZGN&~{^oZOKTq?@0eLtilq#ITBO||1J_gZs9iVra|JFW1i85qSa zT)32ZPm<`ndtg+l{uP?`URWC16I<}MIxe2A9MX3v{tCvN2hZPFhF}&nzXYkh%!+!! zf2>zNbjJYi`j=0ZXtx}t>SL;R)1AA`mxaD(4IX{yos3BYs_wZweaHVhablTEP@H)H zb{*d?Sw7iRH?rZ;CCm^3UgtwLEviA=I^#?EBm8OLk|AkVwPnY5h(M(y?(=2BenaBb`bcD`ax z+mEd9Is5(fqf9PAQGYyXd1F?2c(9)q92V6rb{XN#5*S`~i*E+=ZOd?IUu8U>`d0bn zUaNbe0!YjftHlDW8`Zq`^3Wb)UwHeR{X+gEVuGp*oK2sR94UXVtjHT18+*^fDhX^1 z1n66n+~40b_+esT$nE(Iif-Nv7l_7Drf^a+1iv~Lj}ElAdS1~`z(ilAWV|!@p;)|L zJb^|QcV-Ay{gXK}IKFp>GaIE~uUzr_GvKbcJ$PDUQou5tL{I&_yiB&UJH$A!6!LKv z5`tpvsC*)VL?yq7#yR<^7yThOEhrE@2Pd;W9sYoAGG z9{bo-R#ca{0OS&X1sg?oReR9}2j2acVCS>9V{90_7Ox-b$OQql(?w?b?6@tHD+k-I zBrCvK@o!vLls*1;Lytdx`~cY(`^o+17^q+@jRr1rJr6cI#@~Li^tZAgN9AcsEL|uU znj>HQqMjJ}+u{`@@v1Lp%y^N^0q}71JF0*lPX+;|e*9EUtUxqb)c z7XQAvZJD2ocvq7ibS8QK`?~B#zGXkYyj)!(w%IK)x&4VDQ03?ZD87vmqJ9Y^ZyNV` z`o|FSByeGwzx=3D;*D7yR1fJ&AT&Q}yx~=~{`2waIY#1@w|o$C8FcAzGFJqe4?N_3 zK}EGyAz3&*Jq6oKycmLcIo+H70>+tT3ocdmf{X_@S4#HTayj6!+M}g>J)dt+0408h z0`n_!l<#>Z#37KE_oW$^x94W3wC~g39``dS%^r8mpVQXlDT6#cFP-(uqb;NGHnuKw z9JMrE0wko)?>An-FpzcteDCJOo{l~;FHLP<35Kwt6E-=%>3mVf45TnYtx8!X>) zp3fy+VE8azEw?Pci|tf_vQ@jpx|H)$(6R?dZerwz>`i>cemiVbgUE`uvhqZpZddgoPq84Wtcq!w=4r}=vRF08U0h>?*#>e+wD$f z1Fav3AFm%9m0|aPpg-SEhdf+zZ2P}$y}P_0F2AtnT#MS!RSd%s&W|Fy7)88fr|1lI zsWe6osob$eR|jN8hTIbd`(0!V-ktIEzHPs%e^~q#-F^|HEXp%~oH!pjm$x5lSGTgS zH%X>6Y=jz46l|Yj4tcbvu<$XN9PM%7XL$SSRf-t%!p2Pldy^5Y;SgS5K7s4|?zTa~ zmQYYiv@?MuA_K1i@MU1e zJ3^uJSm+gjh8PJR7CqszLSW=6TD6TVqf(CMJO-urNp}XK zh`2`%g-}D%&SyaG7jHWunG5}K-T?atA8+%GwLi}}EA!^Q7ZT4`DZvpY9)qvbgZ+YDj0-9*^JCd&>O-B7K$G?_VgY{4MRz6x2|;&6V)#MVy>9gFJk`|5KX z9OB&X`-~xuZ#nOC+X3^KuRHP|&*$f_=B8ray8#av57BRL17JufO%54D4S(*K$*vvE zCyi*DA;YOICXdcWDlGZ1GZ%`>)I9;AYB7<~fDnL$gMccKCo5?}aQh}@F1OntzlS0-R9d!&$ zPduU-c0Z*ox5;Xxu07rrLrTTa9PR`td}-Css%`uyBeiL4fp?oid)c% zF}EDpmvs;8q=uHl^P2Xk8r9{(Ld6^fx{OrviARV`@a0+t2dlUUQV<++OO+1`EtPj4e2T0DTg8Z&088LGm5j9E6(s1-A0&2u; z_l$dr1>VlbtXkzHUfKt_VoFyx$zR79B|ZdmvQu7{rWSFx2igbt&o7)TnRRl~;b0qe z2$heM#+0DxkbcO~2Sa;FW!qeJ)hH=cR!%B+>we|hQ9vf`pX|(ys)KSbfkBZz)E>E$ zkR^#efPP1*9Dq|RUM~rLhXxK%zE|i9OjU+2*rn8reu{?*!%~l|sWy?Uz(%&NH1Stf zgyYB9--(CG-%jY(@`SCi>_Bz#uqH*ys3@{m*61+~dAftVI?h!o1YSY_g}w|Kgp?GsGiqb_@c`*P<}je&IRw{4wkmgd>mGPfAz^u zX?V@y-RrRoIN~56i(62JnX9B?t>coZ6JPP5ljQKdbmm;!;NkTZifgPb$!!c)!c|C?gv5A11))9eTnEgbWC_>ntTm zNza?OlW&%LM`R%x?@Ak^#F3?Ph4rh4+J2GWzGT^C33KQn1a=&tH(AV-}o|hI|Y@ ztADhczYT1^Fg|eQbIWB!Q@9@SA^P3O%hx6W@fx0mc9oJf zqm%@~KYn`Ph?eM)bYBZjVmJ>QE7`LD#LuEucVY!XCCqgIbc(MFEMz~&RyspFXaGox z6z`MGPoE>S;o;=9gO!QjW9uarA^IvAh~<)?vW|WAa;=JPLM1;b`1GnlOQhMznVCVH z^X__mNySp@VkW!OK41Qlw2ZA;E;Wkjr=RIPG?XLz&HheYa?rN!B%woYu+40h(Us)I z&}CAM4@4z?N%Im{b~|+x2nIMyp-{9Gk^!_8fl1mD{yld5SejT8*7GA-lBjOZV-7;% zrNx$Gr;7(y-&h4D?uIW#o>pSF99jD}9U6kwy~+H0B@vsM$*(ZGGq1vOcP(+e?oNL# zo-9|7lc2t^GEXnzz{+iyzcqjKeSjb1v?T_DT$bHR@tmG-^@jKJX_%P~tWS(S!*?T^ zDIXl;#kIS&@W*{u6b`8!7|Y^=BC0YZ@D5av3TU6zx^TG ze_IG=Z(u9KqrYXNTsk40kD}p6ic>+Ia_^~`sN<*UU3_33`>5m2!jc0jC85b*yw+4Y z1?*?Y`WemNCWsqfidd?f3{%XZR)a@LeM;EOAki87P(mkh>M9`H;eM7?N|3lwi_2zu zMgLx=;)73$?Wv~?p8Y_8*LRRC%t$%`SKMclNh#t}Vi0XpX}&MqP1}~v0*d1-$oFmT zaO+B5?e!4r_u-JXj<)LrAHkJ8m}I-zgNhZ2diuuBS-=%az1ucrk_z&A z-v|>te#efs#dZ8x_iGkjIPX=se{G(mhO4GtP44fXbYW(01Uf4}FQKe?_Z)bSM%Mx@dE6z=_Yq^I4=p1Xc!uIf zB-jjhP?c+3?mkvbEW6`@LJO5P+al6pk-rtWAF(+E^SLskBU^FMjp=!2psygNUOwf0 ziSoPWy-V<}V2H=RWz#sw?{hdq{AGys#-n)6{`SdR%>+{jB~7TIn=~VvC|}}ETcWx3 z{C#Ts1yMa{`{4s3QDko7@9yFfBLW~ZKB;`?a*C40vO#?SBMw5NPY=tWPulQ5Wx@nG zQFTWlTi{pr+Tjw2jTpzHFW?mh*UE@VBceeTW2orFcIxV)^feVeHxRV$mb1tuK0M*f zwGOC6+K$pUE2#>ABxS0lknHOGkhli9YL*BoNC!t;WWq?Sqo)X&PgHFdxtV@t3IZQ3 zK4F~zP2khyqgf0W^eA4lDgsZ#ze4sJ(-gSw@TMeTH1qmzRB)wCdz=dW1T8UtD748w|2S4fGVLC(SJ)p0>yug9a)E+JbA=RzC@okr+6}5s z&|puw+(Vo#-Ry2I#z;TTO9HPMKh{5XCB8?hr3~JG3;8A}ArTUKwd!T;3xBM=QiAMR zhjLq9UBZ1YHqh`LWJ;VL-6sYVzI7Pn!HKcCyIr$$2i7Tz9jBG(N`RS7js(48c8VAg!PqhoXkY_;1rLIf;iT?^lFG{)_{NBUJ6;jlV^X&$-&P4@xqHi(+HnPBMps^GN(L-MmNse zjy4~dUL|~0NNp+LQjAi(ango(ip0{DIv@n=Ege$M*OCT({)0s?qVn$Kc&8EG!^tNAU^qA-n{ztGrTNA&$0NrSaLO z_cD}3TkTnz1$+k&{aE|lt)+Y_`7Xj+N`b(3IeLClB^=7b#>Vl66{l=JFD_Up;`Mn( z;WSLQy*S|cq_9GCN+)ZT)>nj#w6imN+`c%-+jm}GqIW2)>vDa4Q`gf_F_S;anAPS` z$3&coO11GuJ*h0SbcruD@i4#4SP`XCKT_(iFWx6+8N%=^!}q!wjrwd^PQ}SDl^ObP zTpRdf1ezT2deG}E_&PX9hQ!Z3p77C#f&24i2#@3v#&Z@IRYkRM)g=ixM&`E3ch z9G+bl+i>Y(-V}O{ySFlHEg}Y?4H%M=_YW1Qa2LVldx}I2$UehEgJxgWd(`|>_$=tN zf>IfnoX^t7>FR%0?0M|6kO^5MhiC$ThpOo5*mglEX zvOeUqNm%~6xjgl1Xw<1k%#VkO;H6jTm+->!c5$)Q($aq`efiN!Y5W?o{W9>SOVtG1 zj$_Y}`Fk*;%}cvTfJrm~a5Q4ZeBoXE3=*aJtJPjxG&fw#W}8sl{;4s79X5}_*d2Gdp25ObzL zB^!PyRIt@Ha-K+rB-y3WOmh71lbWBy5orYA223U?;JdC>7)(v{D&oW|AHwzo2RqhFgct)+>#rYkD{^4y$9Ukqz(4Dy@(Dm( zDqiZEm;^DZ4`(nlS@fRn1vQ!UG;-wH?bVM=!d+%RieV}@x7QC$Yd686W)Y1Ew*n`& z3}Oouuf7b6W)3MCyO9r*ATNt~8;ZA~M7G=;r2|^aimd>A;w#PrdRxNotMl^=iRWR; zD|o&;OV6k418^K;aSL59;9C~($>&bhDq!B$Ge2qS+qZ9uf4J#mMLYfD-?Fc2-`<#v zo1>6qZ)qMlJ0SMCRZ%++Ozwa8wXiIsK2LE{Be;cHe9{xBZJg6qplQ%OR#>6Q5o!n( zDw&Fjnc6^Q(rHuxYsWTbD^Er+j8%*XeITVHt(Q&8Z$=cPszjknqEBI}mu9TXaJKzE zv>6K5yA1=*6E#es#v%|9!w>OH)Ys71v$T&yg+1c+QKQ7A_nJ&-ekeBx#nmolN|2Q+ zZfc11&kIp@-cRakihY+VT8ux3p|PAn&Eiik zvm%M!^rz{qt+ZAU&pk=Z-@jkYM6p=s2{b588|E4Ev+g2jvoc3pyCwKAvoI->` zXaaVtgX%hb60Kcf4iY*e^_kDVtbXyh%;gtKttC+g>cSGdG97B~%Vy`suc>T`j~*`} z?47CDi}4t>RuiZVRs&*QG9@`pFIehE=I`9xd_?tSv3)wM2j6%^)v|xGXK^s*`JvQK zh!iNo$!zrv=lw9b#)p;15U!*m{T(V)f&6LMP5J|QU zYuAJ^7% zYiDqwcaWJnNKKbB@EqKS%nxPhY={tX!>0n!DCu*;l@^n#`Ky@cD`s|))#)R+q~;(^ zXe2?PcOQe2EbA%zJpW=HflqYPK5MX_3H@bYShJ2T#uIQ1<~7w%Mp~pf10q6>1{k$3 z4{O0x{b6TOH>79-Tqsioy#9?Vj}v_9c(wth*b8+sV8m!see7)nISAt=io?K-X--)Jno~!-!0hiuyy1eAdR+Xz)%Vs%T`)Itv*PF8g*at1(Z!~<$F=3k zBhoL1RpP!cu5}vTd9@-$PBhaVJg>)(qvboQ2gD_Auagu$3RHn&CIsC|43TLEN?eb# z(j7VZ8P%&-xx9WXZSkCH*iuxBhxnE1yV8P|eoXPDoTa0J-EhXe=;7#b>?TImII<+8 zbsp##R&`==9Zk9PF;K9m^Rq41zF)JIh}G~V1$sGOy?=kg27YTf%mG_#==-q_JYtY6 z(Zn=eb##HyQKAh-TdOOSfE=BAWS*hLF`II-HmPdtyg6PJc6I z6GA@MZ75zh)w2}2Rv_qt@m=Y1blU|gRg6Of4_f9M%TiO!?9?!I9ydj&%`XeM^u?k! zK(tK&u@!6ABz!||{q#5bW|UeA*s*p0=V6Mg&klW`108?lj>9lrXRoC5d6y$SY7Zy< ze#63^Jb>MBr?@Dnmenn6i4yoh-RMiF=B|4NFZ~$$E^6D_7MoRxR1z45SpmHS*-I$- zgMOCHD3&_)8KIckk|0u_`G@+F;NGqX^PVlnF`azkhS{WXGxEk`pxlW?kfG7THD{ zp#uHdzjh{NbA=Boa7GK<(BjrAb6oaZZIQ0%8CtXOh*AMU4>j!~L!+i#(&?X@{USyb9-zHQGfcv)J+TRZwm>BVfC#@Dw2BAz`&@CAliqG zpFs@o&mjKJG+!6oh}P7O zz1J_vB7E8jQ!U5P}zL!Q#ZNU_ZI%hRqVbbshKX~2T@&kVhZ(kZ?LCjKxK#G0C zvoy9e(VQ@wvpLF@QV!|-jN{!{2LvBd{@%!;X0*G?ZTlgvXIDmpwyybqPMY<=j zXXfGd3uNn|2^WO8ePdu@2JrFoy`N100a$^Hh_9#!Zte^0@bvbV;6$+cs*S|#&WEGbtenpF_ ztJHeXL?PZf`jiSOTcRqweX@_LLlBW=L89#%`co#yJ;6EGu}cHXL-wugF?OZmaTnP@ z8C&uuyDf>2;2i}=t!y=mUJgejwqkkOAn|M9S(j@SzZQ*PjZ_Zxv@-pA-Pt*-Y8MY< zVD0PTsT7}L>G_xg8GTW)w1@?=d6an%i*^+8T1I>ElqTSMRIE{IcrxXMg!}Vbu3Zv> zieOf^p3K^roVC@Xk|_e)&XRJ^L220!Eb}9;@Kv%2D)fA7w#--3BNvQjvu@c}-$zgm z2PS9HfMj#)bfBG2Zh`ecmbI?+k{x$qpJ)JR?EV6BT1g6`Ea@951I@TbPrk1?cI`Ir z8BO#PrM%Kek9>=CGS;RabbA_e-TN~O79q`=4>{;z5f(%1<+!93IJ>#6QtepG8J=u& zN7?G5NJd60C@6>^?)wEzI@%-IjY+B{d>vOd$1#W$$xH7=e?6jnDqn{t*@XbtFH> z_=*S)U7dcs8=kwCo>AM#RTy7Bl@IC-AEV?q%ZR7@Y7JIc0@)X2)W&mGS`WL4T;CCy ziU;P*ih8`vNVt5#u@9a~{6{!_F_@g|PWOTV`UB!@TtntVQ2!`eve6dC)jnZ!PnhbD zo6KUMIOGyn!rL({mYATbrVU&o;S*Ozi6MV1O8`6>416AgyguE5Ic_p5;pgf6F&4`? z+d=rz&VwIQeurEEpxxKN`|9GLdbFd}Yn-uP1Y|?zWX6AZaE|yEv91LeC@)eb0T^R1+#uQ%z!Ii)JWrEn%I+OOSY-#D72C2We3J@Zi+5RL{L+%<5xg8VWSj5Grab-D~C;>2@gwSG`5+)(XNt3XgGSYiR_elf=_EDewT0R ziVV~*OFA23*u@>>D#5(6s)eZDZ4G7^h{0CpABJwZGO06nviPlG@Irb0G-xtQHrmvK z>Da_Sp8eiD8)@Czfy?V6wRHXbyyZ(!#dw}=hKB%Y_V{XtX8@>J!J55^z4cn)GoRD; zKu)nGLBx-S=!l|!D|xmalQ8v#DN8BW01$D`oOYVF{k z4IC*581wI*rXyj&1#mJY)=pZ(2sus~sZ`}QL62q>v}9@dMKQCWQ#2yMrIFu@>sRnu zWAF)H#fYQii+2;N`HP3iB(u@y)A^}z>}HhMKkFs6TIj?!cr!@BC9Py)f0nfGA)`X* zb%1M&%F-Qq$e5uZHbmeXM4QsYYZ1VZ^C*bj{8v44jj{+;@g?83)uMx~{dj~T2fccF z5cox*O|a1NWy|Haa7e3<<`=xGv3aJXwpA{|FXjd+mngB7;0?WzYb#SZv>8S7VCbOW z73-bi$)0Z>gmdE)828h$lOh}BDVW5nj9hHz?+6< z95{ucxaD+P22^jr0UClboiB7p-QKVSFz8$h?Z%#Z`g0UVj-_#1EyIK9Fg4LPb3$2s z&fum%tI0nF-DR|dUg2MHMsT-kzI>{KsVy$k|KZSafN8N9-^ZId#oIP@)~>e^N5gJH zXFk1=$<6M8ML^?+DKRBu=sGEDV=<5XFE~9wBFx_Zdl{Vp60%8*}6OlY*gRH;c#zVnd(;4UbdHqR-M2Y{u_O%0QTLZQ)EW zy>%jOrEQih(0Qw&^YJ-##?wA*MsM_0_o$0zn}jwIIIR0PGaWZ(jFJ2?gYp&i)~c&{ zo8))18O7YWGrE4$CXrohKkc-~f(X&Y*7{Dn1wS3FaS7=7TMTyN+_q?bAhmX|SKjKa zu!`&fM^K+AZ;FY!!h!YEogt;Rn_i)c0M2uDUn>j@zEs`sIyi$XcK%GLyyQ`H1bZ_W z?YJe2AuSojre5Yyoi=nrr=uFh;t>`t`CZ^1SpWN^wE*QNsRXbyboO#tsa7J7j;8bw zH<`#yZZN%z#?e<%giV1HOeKIp)U=v>;3h;uru!rteak_aYLCQNIP1(|F+3cPM(Cxj z>`#Ym9H?0Jl0+S=6{jNtkfq0luuf0#x>oHi;FatyXkU-vR(=s8VQ)p9{#3ga#ez0^ ztfJc#03y$h5)`8JJ`PjrJl!n34O}f|gqA^XHQEp&@;=QlEV;>u z8J+qWM-FDwqQ>5G_m##X+9vwAs{7~+9J7v!N^HF4(i2Xphc9h2H&8bmi$@e@G;9-j8gY+VPS0^-}PYT%$W(c}--$X-Pa8wy+*rH!rNVrvnTC>u>@8a=Zp?nT<; zt>L$-MR>aLd)2_?BX1tuvVZ4k9JXd%PA%_6 z)^9w!&bCG2jtK(;uPwRZ7boIA61F|uABTM?%W+G;ZEq2aKaRG7$G1O{!Px$xrf4-J z2%nSO$<6aggKuknFfIemh3Xw{QFb1;E-h;FOheQKF5T|3q!0L&FFoJSe}I1wnhmEO zyMfPsCmDmj6?AcZCy(~=X!t&h9=K`V#JsZD!VsV$EB9}I%h}ggo<)G2xs1}<77tEd z;Srr&)=vrJOsH#rp{9ha+OAX%jundMnLz7TX*)C$e1wZvuxte|vIlN`r_*{OxM%^- z#@dwZOv>fE)paPoIs07RHue1M%WvFQzB5&3u8dlYLqqn$+*e zz>|hj`Vs5sISXgy_V8GSfjDWVZp*CDTm#8zh@(e6SrD>VGuyfs-c6p;U_j3k<9eqm zo|Y@ih0h+TGNI;ZB01AHL__}bsLh4o5n;y30|w^h)gLXdm}4|-R7^Qe7f{nb{x$tt z_?C^?e}u<(AB{P9MEAm$f|1gK1UWu^-C1FA)Ql|-r8xLGHR8HEu?u-;q#zI8xstb{ z+J0z~k9iP#XL7x(s=AKn4tI7(aJSBr-DRlq z@+u%qg*9sGQ~ql(oJjN$r16Tjrea?)OHkx7g0nX3U8B1)H_g)@Cevu>-M-fs4x%}h zKZ3eN7rv zpJ#at>CX`M#%I!pb$QGxh#zh_kfdKcrV!O;JB)i3!H}!p)0ifT{UouZEx+gIqY;5e9;}k)NAn0h4QbW0=X&tsd-`6Wv zclh&sn*6D4V38P)(n`<-ibo4{>Buoz%~kAI)@5&JDcL+m&wC*L?vlt7|s8$76R~z}nDap_}fuDi-5J z3uMa25mG)D>POXPIrJSpwG6LNN9Wr4iGtone@1M&rvfRxt+E13(!1IQ+D~mloIT@b z;}Qxkdp;TbM?^)h&_^*k!H_-*(u>7<8w^_9p;+l4SCkgFy*bD=$y&&+X z@Qr#Ar$^gb2CTeZc1)1|SZAk{boqdEb*MI9uUUT>wIL0~cg-opB1#ypF^Xu_LOKdI zPIauwZj`2LdyhDdu@nL!mqns~!Mk4Nd<(lDAHj{^bB9qbm9Cw}q!bx8iN$D?1f_Hf zDhQ~uG{KeJX9-^y?p0Z&w_#-v`P;fq!1pwI3g@2>p>Al!#YX8T3r%s*Fs0qHNfiML zm*+A$s3)}*FVCznoyVNGYWnml6}HFbn@z2&hoECtl%(8rsNMrX#Jp}n3r8XUepiZA zK4%sU>!ZybGr@|Mzh{eDOi|iJz-tt1dcWey3;QhXBe4_FU ziM+;_D@a;31>&J7tRuzp4^4l53V};!3_{Mr9|q2t)AHFoh3#slmL42kNhSoP?e3oR z=FjG4h9r7=dLxo0w_RNvG2g!ND?VZe2jmVBRV|mf^0)c`*Djez`Q65o$w}|DVFQOS zm2F9)!XMQ-V>rK%cs%oET|P@ZcH_m-yJyL`m=sqyz>eSwtVuC1=tx2Md?|L3#j|jr z6#ta1wt03){(|`m4JC#p8~RtWV)5jdd$C}Z6n9dx5D=3#CpcB*4(n5*hRto}KRn9L z`1OZG!s&zG#dUu!`0YR{ z>833-^pfa*IofP@cf@cvUV?J%EWcv%UexpWMR<`~qtnK)G8Z+5&4sf-h?208S|@+$ zSYu_vutqI0VCA)L_;vawF-!A+(%6=i-J>G3tq$o@^}~_uHj-g#R*4H!^~w;qcD6pR z;>@YI_&Ont$m1zU*wUz~-TbwBq6+*(XoX5B8^Lb+HCBsDlF%s2s-punV{OP@yg1Eh z2?zTVSSQ;AvWs(8Bq|saaOPt`zaAFpzI}9zgwhh@4kaNvZA|5Sf0f+#bTB;W{nOm6 z$10Fox&MSa)RocWwf>w*Kod7FH>bmWH}9GiH6x6>*Brd<3Mn7uxDAzA4Y@<%jC}eb zjv{y;6nHpJ(P3hVR5_ffnW0kqy0L6;KA4YbW>ZU2y0$Dl<+xxb-g%;|BfI% zKked2PUaL9LkyXlcl{at{AVmzFORp!0zb(jZOBhV&6{zq-3DV4pj>s6Gue{zxC}a` zwW5iy=rATv66Tkz8DaSpV`P+!>x7!R9bTc~Odwl>)Wl|dQn1OgLxDab{i(AtVkn@z z1vne09M#!@aRdYO&)$cZBbjW{!h0!&k+2d}vc*e^&unhzdz68(K-EQyMA5icu*yr$ zA#jsR6R`YqOXgjQ;Y)+TdM9;qCEn((Aq$rr7mH#SI1|Y2 z6Owy~?K^6NQA-v(6yiPSePngLX(!V{bF|BLx>^eopElgeb^N4d%FyAo+esETVT#Nw zT#?__g=fJg?~ibEmJ+JPx?gLVCylm8DI9&JaTKPFo5gr=HK9yG4IFVl^m*WS>OM2Z9LB2s4IkB0sm zds%yA!W7%M{sM|b42Si7RHBsS{mDju#NBo7VK%B_cuN&WLde%?l=g1MMAP?G)sDnwGaMkK(@&SX zE?g->PXR51!slPwtvdZ-B*c=@G7Ry%hD-Au+>C|sWOU6Rkn^QL?iQ57e7rCU(Rvz^$FKMgm+11rkG}bfh%Emu%NIER@4r#Rrg~ zht!W;&w#QNSB8q#$>xf$HsJQ;0COSt)zv20U6K>}o1VdE1EQ=N9N*Xps-|nwRR11| z_z}h>TfDsc|6lck(CceOx~M^@jrIIy9gPAa!_HabH`my3xsw>Pce z)z;n%Dod@owHwhv;Sbm73IQphX{~p@xJ{)b2fUafnNc*?GWH8OfmTF8c?WGV zQ)SZrYIo6KVv!1p*>w9Ez@NZpLIR?Ao}az0C!epIT%6EetLWjL5ZDIdj!p%DCa;i^ z=PVEJ%)P_Lf_^~fL~6r+nj)H6HTChk49Yzh#-wZ983OM}IFDLE{%s1wrQnf`iZ-o# zr0cN*7%w#Z$CxEgy#qH3x_z-!_TuU4 zMYIa~W8PWEUACAUKo!v#f_k}qF#@evIQn-DmJ(UK{aHaXO0~gz^s!w&6QZc;Neudp zOl^j1u;qxDS;wEP-G>X|@+=(ha?}ef)Do`@lDQawF7~yKUzb6YsL!((T$eJrA!Bei zjc~WHOkLnZXu#V+PK=;gux+#~ef*+|mgUaQM`e-}Jv+)`7R)?^~wQ zuNeRw9IaSGg)Y#WCRAcCx&+|4;hG{nif1x8A>EcDW7<^$D-93P&%{AeOUtG*9)N9Z|AG6AwqH=61>=aPODPs6ppy zVPSihn~=;I5OXJo$_Hrs_ZvTl`rSpV*8b|&^`FwZ(`-5cYQqUby=m|-galo0zpooF z4V?q`uPZ&p^D%R``8cN|dvjctW+Qpb&i}ErGgB(j9S0Em&IoH&DImgjlF{Oa> zHuN2Jd8w$O!2KqPgl7|*57WP#cOlt@P~rijk<+MP8aOWF-~ScoYx8fskBeWJVz^ef zx;;Cx@B)YcX0DqX%WTXZcVG1cPAn}1hWN~MERZ+PBECwZd^)Z|k@6%5IRSR}Qmvn=BcZPUg!cBMnrNaLQ+MzS(hd`Yr)EhK|kNSmh3zAxZR;Q&41SiA%Vnyk-mBc^`UD(nPiI=c9K7%}*q-=Cgc!&^TPs)Nh}4^crs1kK2s3dKav zoxfBC^Ut-r6q5@OA>`SkQe3#QJW|N(Rt(NlEP9x~FSWS+ML|FCT~#H|0`RcOtAE0? z)>m`K4$D%ARir~Fv^Wk23D?h;K2dZuwfBgtyUbzI%i2w;4<5Mlu9)8!mzc{)V7#8h z1&XUg%#HDs7(6eeygMxJgkJr;wKgy|cD#bXHC?b-o3zus#c;3+(jwF0UMpfeKn-Eh z5iCr3k2LX%0-G(hDyzq-#j~QQ$P)hCtk$iDuQn!g6R>j1$s2^#zVZk+ORkC0J`$m_ z8|iZZSJeFXhLO0U82^QQU1E!LnsAIUkbD^nHh^Z?xO8tYEKQs;+;{)aUs)Uz3E$zA z$pZg*CcT`pnG;Nie6hY|?s$n&2Ry^&?wmS!p%l~q^J_rC6RB+WlPWIy zb)3ZgClvX&F9b${#TEYtM?kp0n^US$@Ctyf6uz%=xch3ConFJ9hJwUM@TXOwb%=6M zC?|V%%?``#ab}ssg*~Wfh)qWIv}uW=G7KRmOR|jzLI@J*WFT{kFK)v!Eh+T4O39O> z0L_yOP73u`B|@Oki8hym5IsOwL|{{s)@I_3GM@psL|JOMlb9B7ntH&E^4K`|m)g*v zG)h2hXl`@Na4x*^D(#%&DY%Ej};YcIbreD$l( zV6^v!doE-1UcN(ZdpUk^i#n!9p{E<%>}&u4KmbWZK~!DR42I|`T5t41FZDTL z0v?b(d{F!nhin;0%ckFNFk=`TH2vDMFEA?I9kysJZr;9yf$%Ca`1#!zjFXR*6ECcr z?KalCoHMgQ@#8EO)?xqaZ@n(@Lw7Bwo!{j%+`bwk2VN6{(LX%RkZg5zHSfbDg4@(t zvi#7d`xG9}_NfY_mG?h;R4SD+1Xm#kC^QX8gG)`*@hAf-92HsMLgWHAEP6KrP%63fA?uRm${mN>PUW|9in4}8V(LmNMx3y%b(*NWNyaw-l{X_YON+-!a!7J$ z!;s+#%GqlUVC%QP>k$OKnLGTNb1X0l9 zKMjP1Ae@l`b-Yh&e25|B;}aOo4(Xd1={?>fS>{aE(!vZIr1yZ^qrsy$L`iMISB@;R z7%=7y$4&I$fTeI2AozRbg%^iE{M;W7=TS!YjM5~@R&(8(x+pf`r!`#iC9gP7H(b4Z zl|z+_c@fOL77cU}gI#2}rEaYpJ;vOHeHY7t0eK2#1p`ucJ6t*&jD@2yn8U*(`AJF- z92b#542M%^$r4XBl(ToyF>Z4XBk!aBZoqgm&0jLq4}jW(IBo|lu{;T@#EC-`D!>li z@iv=AZXDIzpkNdg^)R`l+YP{>n~MNT6x`Os@un+nu5P5Kp^y&Yk|%1?1Rorzjf&9~ z7Jk${mglrpiT$NFt6aL&T)3pao~}zAHE>*#9Du(6wg~Z!N-9 zK4Fw<^^9PbNAqAQV$t;8e2oeArSmizd^Cc2gbOaCQJeE2Cs*VwmmJn!#cX~OVw1T{ z7L+OY0j%acD;WL;i&rJ}toTtzbc{%MeZnisxBg* zVhSGogYDF%%)6w%M6VlzfR@Iz#F2e-ZO{v^t{lm{Ci6Go=NYD1fB7+EN@b(q#^%+l z?R^;bZ*p!DR-D7Et*yQ7DjCgFoIK~FWm*^;H+ip_r}S~|D$5Hm;iv_PrJ}4Xf(kft zOHyTVvL0nnfMo89VZiwd$vj2Htto;NWRfBn4a`E>tB{<^4Wi_*wZU+JaROd+q-*9z zE4U03&%d~=3>Ag{f`nM!F%f6{@Km-K2$uy~e?mA>+`=*WO6jT$opRwW7-`3>LNlDf zfb=b-Vfl#%qA3NDc7__rooiQz-~AWAGra4ulQ9-o8E^4Dt(7Ayz#e9(p$sA?6nTNx z)}`evbbvnxV|niHGiIk3IHcttmO?c&i-RH`9vWZbv*o?Yyy+f8o$+q1e9|t{t5Rtg zkBa78#cv^Jp32C;;n55{`jXZS=3Tz@wE|C$6qab|b*|=(#=H+o4|Vy%mEp*Vlc{fY zNJ(eu9RZQ`ekCO!pJg=8L6zIQ4Jiu}t_-SAi<~Uj0q^!b&&*YJ8(-^iADB_Tc%%Hu zOc{5PheO_@M~}){oU3GRr4X+)Ca(8vMs$Pe02z|CeHhcFO(onv-mj5ZhD7*0ytAy@F}k{rXpbAA!8m4V-Y@`}F5S0ZGZc+xzL?S6~K zk_JQrm{}M$S$ufcspCnLe|w;1&XBpBo$tFL`+YVt=jK+@06qJ;mq02>ewmU5E@;|e z$jU*R#}K7{8P(K7kCA;?=CU$Qh*b4>yqT&rvSLC20RF6eTojs?#ubQ+8L71T?Lvg1 zVsgp6h|n?Um7zh_P!!gdMyjGr&k?Oc03xLPieJc8E9zk z3*AJ?hl00;Ri6s5i{hO=eVQTZJVOZ2MA53Vud>9jV%FtRl-N~8sV^~Kut4`%6&f>K z^F4K!SnUNgH0A5ckw%b%u}}?3smf%dFHeSD%6IwLy&nx~mKCOD-ienNhsf639>(a9 zIXwrJ=CJu5y_hewr5>P{afP^%x33RxGZeeaoF<#v;B;Bny&}1hjkFecde!tfU-7Ec z;SZr%m;1h!ed`7?;RzmB;nWN3)=57a7$ZM^>^Q@~B~}(Wa7kHQ&GYLth-kR8&i>Gg zFN5{1f!{%rg9jG42==#+v6U{d;xEA7SVGJDFnyV_dOKT2c_j9rgP32@W z)Fo;B8j+`l%`a@0zsn}VucEhiNXI4r(D0;nL;}3R(Xa6JC*80bj`ME14UDEkskm2T zP`wxaSPf7qka@*fc+IWpTC5(IGGo2U!HT_n{;hlxNIL#bkHZJgbNM+{&r124u5wWZ zZpPiiz_wh$;>7MI=eM$QMo;4e*E3jAHX5+84VG+4TjXJ|MKrlMiNA`mq-O_0qY>0) z<6Y`?4%s>kbAGeK{3J>WAIe8Pu=jU$Y?+~>uLDcR4a6nppeImZX?ntXhaPL4W2?3};=z;RP#D13v zx2tpLcp~LRp*d#1!H@ndFz(Ju4+`q=&}Cg^{?2zihB4huFXwnZ!%TW4R(UBmJq|7G zOxyJ)TU=`g_DgBQTH$dYsRLFic)7~XBJZwx0Mc?^Yy8TsL|>bt)YjJ{Zt(%stF z9L}=J=7#KTUZC^X)d~~*yTm&rg>Vel`Q9A7k%^^wj>14^iw~W@$%o9p`sL4~A~P&r zY!A=>?&p*PQxPAx1{b>gF(oe+0kR0DT?oT<|0ny5Ac05Kp`M4F8OT)%qws>kXG7P= z#6tK5e|0A?4#!Y9r(+(~-lw+mi^&v5$qwOQ=Kk+^f4%rSW83ne^Vsus6K#v@J|+5K)|6VSUj)tdT&Z!pm_Ivil$NDiEn z2g^c0Ii#FXUU@CG%C33%kLh6KmDiTIOh!ZkRDw$BxwQ>m47+^sBFdf_MShMULr^GL zrUi^9io-|nW|+_Hz+1T*`WzhcIxe!GMMk3DMlMI0d>?MR9K6LO7c5Nx@}WF*;RL^* zQNd&*XGQek1+MaOuhoP61rySkEzD8e1ODoIB4e2g}0_OWdFQ%GZZ?up~aWdUSa5LmwJW zKl?c-#$rbFFjCh=Fpj!hTE<1t)^&F=n7-5BBkNfo^2?XWYz?Rov#T&(6-IQXd4U!E z(YUD)6{LnOR%U*4ol2-r<2ZD4h!$P|rmpas!$ADfA*hnr<$KcEp@K7}L%W9#bi9x@la|ek@Qt8iJQC;Vc_-j;jl%o#C>g;d^4RhEs!ZCNI!bQ7pQK zl)V~zQpZ%trWQbmw^v0A{8IuYg$kSbe&Zmb0~BJ+r%kU9cWzzJ^&@#6(P^t+sG4G4_=O#E4XN}Nsqfl_<&JKck9dN!aYtx)9x)AFDYr7RN1=z2`U8$KO{CR_ zWC3VBjQ*aE{;w((vDS6QWoI3YvITPE*3ESZsh+ z4;2K3tU(JRirflWaGKwW7OU#(xLZSXrN%`DYt{+s9*SlU6y|`%#NrQID8Kyr;R_X@ zPGM6v;=~)%V4M{Rh_kUL&%#hF;`C<#+IW$h3Qx)lSn~QL&7MrR~S?p8M59(?eytdC3EY9qEFb6YCo+U9#VTX;!cb5kO&^Wf=U0>qCCO17S~4r9 z(a9>&gytkVQlQK!m=aMaio(h&Jg64{u}k129(Z8{1W098tSXsGqjFj2b{;B@?}WSL zxBOJV2;p+xR*a2R$GHGSp0ClCwUMZ_=;PIK>iJr!@PPSeyAlRd25kY#I znQ*SAB@gt&93pYzBH!?sy&;Bd@*119lvVhY!-5HC8FK?ip-DkWtBpcWZ2K;Ut3IaK zi$S&oLWE_s5pW^J-qDj6p4(DM9IB*2Bh8gE*e4&e75?4&KGp;wU4bHNpESZf0rSq zd7KL=SLast6t`~Pjv>0inR%rwaz!QxM|#Ro+je<=7Gd7Fd?oX1>&8_;7Zcn(^~YS7 zS^V&_p>j1=7-{YDe!mUC>WL$~Xm@A0$PY3(O7XakM~mL|t|z5B;!IeoM4flzvO9-k z(_inm3UuN1>8aI#MAFCG!*s{zH?3~|Y$I)Zb)X=^iq_d;)}??|DoN-U+RJcVF#+@X zm#(I80DuFw2#^;;Nn8z2(i4RUm`LasjVE2Rr&0ZZ9#)l>m~bAU1>_?Mt1GLt*2`I% zUBq}i*l21TW*Q!0VIS61A7lBW#Uc~S8?`Cfn$vP|5nbs=oo z(aKF9m=Sn z>*VpU0J6LVdIo@jqP{l*q z-6@Hn;1N>h0<#O#Gb-lzgkS?hB&A=TYp7iH3+}XyzUA{y~zpc6;22^#M@x?>-fo&!%=W; zu;MmPoO@JDOAHy!N7+}2vjKSPtxLlh77P~I^i4S!R_?nrjt=1X2u4|LUshgQTgw)U z_RuE%!pT~>QryXAO}>0dN;G9W&X>)pFgnOIjXd~E%bZ$HbvHylR2&~ZRf>9ce{Z1$ z5=;#)l@yOHj8Vq4*h%&dPfj?`35J#?8hak`c~|Kbn{5aujyNFT+Ppmwn_CXu=waN) zv8C3SJiKQOIf1U#IEG$*XeJC-!PZdi+?h9rXP^0F*6=SzB=TxG>!gE?c#{u2XgcYU z@5@;#szUGs-?sX$gxSO7)G~h4GfwPsV%gTh@G34 zy}{YD=O_nnP1^ec>mHw*s>hEXjm#a+U%PrEMw;@G)gH`-=jzq#!)HJLnLBwW(3eb8tb2XXZUHrr}Iv*27eTlUkR^H`sX8nEj}@=d;A+XyWr+S=MA zZu(>7@}hG{HayJ+jgx+l#xNX9ymOd#7>(u!SrePGGzAr?_8e3Oji;pt4oHEq8U+x+ zAgT$UrimvoPVAZFG4AotxEKp@Q>20eT`wmha0eoA1(|#;mo1jD?hn}h(#e3s6*c^{ zFfJ)uvGUe?g_@t#yv1H7a~JUV{V&V^+AA-TkFhvPa*_$|`Lk#Ep&oX}!4Vl~0N|`% zrJfe3=3dp5c(1vQ#!D)N@&|=HE)oM%Nm26Z<>rPhl)_;doJJWPW@#)ADTT9V((h1O zv8Ysf>@5sa!0e~wND2mGx$mNcXXzy0>a& z*HupU)2y4@{A}c9URXPRoYMo$iR_`AKl!s2o<6X#zRcM-Umz2K2UL$AKf&_+t>M$3 z{xq_{pt2BSBPs1_2;GY4uD?IlC;c>}ve924>tHe7NkC6O4$yiSSILqwKv;JvAO)k6 ztq2nX(4Z=8E1Eije}zzg!O?Fbm?E#BQd+TDIJ%V*Ux_f44n#Kq1*2<^@DoNlpee;n z;PeWs!aL44tkGD3`NR(a1)t$r{2G77*@LRY^C-|OFFr?Oa*ke)pH9G7ob>uZ@UMUM ztHZNj`ARm|R3;5DhDN^l3EQ)zhru{{93D8a*T(Frd|&N#xDW%Tavf6SZA!|efzhA9 zeN}wt)gH$^1bc-P(z2nDzFy(i>s>8!nbx_B$M!w0356{dUM9IIils7ou@xsVMd7${{$BT|P93 z;`+HG`SYlML=kFL3}JoQ>=r9{cUj>&ae~Ghpk?--Ea!&DgrG6cd9kOy`#rQEu?}p{p=8Un(Z0BTudv?W*7?wQ~i_w#isu zSS4;)XPN9_R5p7ymr|9TLoi$POtA6W!uUr~vubtz(uEwvbZ6Y3uJaR3OO(y|nR55V zFTX*of!HG2YD+QS@WL2uDCFfH`P>xtw^)co9=`g40nzL1Y&%C8XEn?Txr*-jGG$sD zpB~cX=niwVOPmX<4{DGF9;JmEP?lDg;M~KQJ&o<&ix7?s=GpJDp|h8B^As@f(bLjn zy-AP%sn7nwaE;;Rsdu~+1NIxs3`;StI}SOKkA}9%W-MnRxQ0=i!|0D=S|Tfsx)6E1 ziMNh)lV6H;NY=X}BUHm+SqRh8 z`~9z*jE7ZpE5IZhe@N*=t&dVh$9!#_E>ui zHS)G9=_e}=u149{uT!q{9+XR?%!dR?w|8@q!ZJGtb4VBZ@Zx(Y zF?xFs_}j&h7EyFp|1@G(^*lCn<>IBJ*Ue_3>dE2l9u0y+s~8%3;fzK(JG9bZ?vno^ z`A@(8#&DIDx-Wm>i^Hp@&#;s4`$M<+z~80et@9VC!_+#wyVwK2^fnxT7;bN;XPK;$ zIV5}7X*9%nrBR!tlaL`CM z!jCD!Yqw~JM0Xg*{O<4ki+qsc(ML|CY;Jxnq8!;!MCNzzFd?N*TyCat63c2>86iBP zWYw#b5lS>Nfu`ir+d$q=zAp1BtwSp3LGq&#iqf9M1&Wl9&C;xj5twz=58{zWqoYCz zC;eTHr?}d&XD`I_`IlZ9KK-dr50`mo--gRWwwtuf*?0wyd|HPNr|OU=J>;wnAFFYh z_i^N(ZxcJ*aanp6qqqLm30rY{K5=Yq^Dd0NCFHFomv`+6-Bfh~@BG7_?DXl=IX`C| zq-@H>x`jD=+Z&uNu!oXaSLBq{3{wnGXB=g|<;Oub>4pCF=l^Ipck%LYgHs1r{W>Ug z{5_eYCsz0lnJz&pJWTJLKUp4uW%=7A9(Ww zRRk(-g25v#&r8|mQWweH3)eVH9+Kj$67$-r=s#ekJc>qyJxP=pCT*$p+xp(Tb|pvN z&%XIaR$Vk`mn?0ubFh#}r7gMdXIStU26=7OY<(Tmr$xkXOPTMk`IH_oDn@9_DcU9f zj{Bov#4T_L(j)x7WjKeyxG!S_*`23UuKX!OC+SYw-H3JQ;%maL#vSM6 z!xz5z%Y$)X%tuDU3opLJ0t5>ml-qL5Qr5c~rHdl;xYuvE2g4o`qXAD@`$~tsBFLi` z?dG!bs4pw?jf=y+aY@5$akFsb6a7#!`OH$5mCfYXaLQs_da}+8#QenwX(26o5 zDTagASbG%Hqyj-M4JB~xK1l-xRSMqRS{|X%Rh$v#6f1WsRKEuytJfjbN+#B7tyZBE zE?DC{hQ(k7AGz_@rYCqbJaAzyw3u7N`Sa%}F$zot=Hqa{da!YGpFIRy?eP+4rci2D zs@6GjG5aLYQ6Nhp?s~?MBM;+DY0UyG*lNnV+&IQQ!Vt_bDSYjOQ^D}#@Mnw4cdlS% z+d!C4zeBjR-ryBZ_%tBiD6GSwCHU|sF{2ljUsYR=4T>UG_e~!ia{ln&B$u$>#bwG6f^EOi>xp8^?oY$LdHPj$rEf5iW`~(pRpqnwttZRa#Cc@` zj3OkA0@!+jE{Z!xPoh$|T+FxTGNf{d=F4CzdtYkKYEvfLt~@z}sbN`q82qk`$-hg; zDrkmeP_bup&Y~3DOl2a^-|nj&Y~%I51P)Cf1i`oXHLH{Y&!=u0cT@p8C=TNp#9{N zJ-_@fFn3!$ekvQ9pL_QC;Ux0*8wAeRTu|^ZrVASWqUn0vBJ+m4{XYOxYYD9?>pg3##;t>Fsm8T~CL4uGh|DkGv<|a;I zrxl>U8j0aDB;N*fCB^k|70I5ZR5!g^qgaMPURbG1B`ro&>9lZx6>lS}QAm$)uI`be z@MXFIZg`7Tmty6t3`ktv8E4oQ$t54QI72&KgQ4Up@XyN-zx9lUHF<_DhN z0fnQ}*m-=mAPIKydNm}@4l zrd*G5kJ!`A?w^0Aq4n2pvbIZ6yJ>Zrn6|-H&v^gxY`?$VL_Y?Qom?MtUr%_(;oslF zt2w*OhCV(QT_8e-FCjxP9k;EXB9#D{{i7n&wiWmV#fr@H#L8z|>m;mM4r_o~0 zxN8_-5Kk5k;WJ?C4|f3sBeU0O$fb}sq%l}Zzus>+E`mfSF&2o4)3S=0JDh+6bE?*_ z?;%E;1^+=TQUTzlXDsIA#oC1v;yB$l_e|eHlB-c`E%?2w{C?wsq!j$=Q*99=H}#EU zEn^9rsxHkPgfqq&Pro3$weUWX6SxoYpLzMhmlp>qH(9KY5_9*Za~Y$#-oC9s%G&$< zvvb9G{kN-wA<3RW@wb12xy7w6Pw*eJZfjAb}VUP=jo1ZiA z^(9x=&o9@O^F8PJ^~ap^vgL*S1i1YKErY(x?aKr6?@$2)TjS|sa_+ZD*NhP`DUQC= zccWl|^2c3gl!N@;iQ+{f3o&OIDpI#k3l<(!2*QGU0<~rxDs479zlE2xfn%|#o0HbA zXF|$U24-wP3-C~1x#z|V$Tj>hk%CyYD>+;!h*=W1WpqTQ8HF~x2Ldcykf^cWU8$z;Ai*?$j_#pHD-Q!%7w5gc!O zh=Zjaeep+kg&w~9?`oz`WR)_xeZ_)LYr4Tsq{E}eR&^v@6fu#yR%=$IN! zQG+c{zP;VWT&cY#Z}b%Pn*D4qjg&oQ?T51F5X6n%q` z+T8q+5a*Ta*DlYxLF@io-U4YneiIvUk&@>^J}Jfg^>mcF-k3v{0F^jMuBRxo zXc?RN+LW)teTekh`#KXb6Fb0vQhl2fG=AeYI^buon zFF}tferrJM*wJ~&fBEv2)vtc>!Rq(_@b_z1g%_TD1`eX-uBzEwSY3@My?&&Gu-?le zraqc1TV<5&jl(!Y3!uL}SE|Pta2g9G|JJR0m5{1tLK9)VZWrmWISK{ z_F7$j20a5W?s3xR97HmqF#+tB-%cQtjlZnB`~3+9qzGDQ6Vb{30K$CC7vJX(sd#pw z=Y8KC8eSg|Wx2GRw1}I(c_#qtfPZtZiygH%pX;~v9XS5xmy6HZ>AP$G*3He0S{k%= zp%-vi;x?>4CLATT2MQ5{pzqq$;|lNq=aE9>Km72c)!m!dyAR+4Y#Ac1$#)#@aq0rbq?KCLgn25hbPh(6Os$e>m0!wl}g0U;SZh5v{W z?s?*^D1oELPXy>$13R}XJ%frOZP~_5cj5q(jvf*sJm5>k&GU(Dr_({EB24W=5{o#7 zg~kUSh|4(l=x1F7pAZcZ*%!Cm(YyAi6Fr}(r=W;KEE#zB{d{%F&YU^ptI&Rll^J4} zYs<{dl+N`H8=4;*E7`g(*_>OJ#{v_zfapRg0ggpq0Gh}$(>H_ZQun#D!;g*u^!d7& zhJUm6PWHEXk?(%MuDO&*)>rpy%4h$tZ?|ZWq`oXScV&6Zr~5Rq^lU*UzX7t|E&uhS z!@U+ka@3w;#`d(`1T(2EC+y6tA#%M%Y~WF`-Wt^={sOdM?LOzS4 z?~mv*0TU7GR_0R{wQcDFIGPSwE9>bnr;|X}vxCI-1?GCUxV!PP*O&3@gt(rgi_sUx z*aJ0ZTo7z2g#~GR2OHk4G}Q4zR*1QLOMCVtDn%r=_D9S;f9{KNUl>|?Pu$No;^y|t z=Je;EU6{3b5W&({{V|u@`$znnzi;gKS^s6(N+vUB_Zs*9{rPf2zI*pFe?Pw`UFX2+ z@|C4jtZm1WtVZcK5A}DpyD%jo47UrAnDz7dpB!PCb9IHQVX1s6yx#&k?PGvG1V0XNB6)PmN#dSs-Gw;aZC@Cih3HLO7>btOqW^=5D;-VOz$_xkb!RY^@vo~ zld@ksUBfl3v#4a8!$wMwL8>x8jQfVe;4UGycWj-64Fuxx;|QBR-nd?h zbcTat6~wqw{V}^w6GN{imVNrkC##3&-ybjkCR%v|DM?wtVH2(F`}|(W%KFFVW}if| z>dZ<}{x(cDS(bABU*9Q*t=&*oS0Kz{mC?%bXlq2mm}7u_X=Emt`BHYBx>^pGmd85R zclS@Do73Jg-xqKA+}=IYZs!+J+dOMv%QcOTaeUp*jDF#=(;h|Gb?4C%0>{G?$gdwq z*~?zcXSZ;XkbysB%%r`SXn?zHPk*o<{L?;#e4vIBw*b|Qr#AIyu%782E+ z$}D|59skUkDMqf#t9Rdh*T)dg{1 z4Yg>IhJ(#{=K=z9XxFgo<@iklmQPzK6#3hL{NWhW?wnZOFyPRlk4WjWLCdxSOw*@l z&#n76Z7l8is!g98w6lzJOYbllfEU-Xr2H1#ER(Aq#RLp`F&hSj6vWVF@uJ#w1aeqB z3hM0?{|`R+V9u@IFf-IG!&SV;`^>B~UcVuToESqP&MDf#saPWcmq^_FF^!cDv5Z3R zIg#soRFnCXC_-FXd@~C-T%3z0zrNLPIuS9=f@q1Xe=kR+tu$~WoMkLp^$V5vjNa~y zQ>YxX@%~%mMg_bFycBuK#>&hA@-T4}k9mlMf;I5&)CMB6hJXiBo!r zaskrrXX3?8MFX7uBok>?AV9bwG}G^S|I&}mdwbD{TiO@oIC?{XvT=Og8|trUp-Ye? zme+d#rhW}jM~o=fLjD()-hJIGr(}?(`^;JBF!}IhJ#UXV1h^?Vl*4Qz@l!5GN)oK_%!CLAH9giXLE916{il-CjI; zsC#fe^#?-y=1xwNv5D;FkpALZRx(5BZmxd-{pA?g=qsgWl4X7phxyKTzO%W$ z{#?Qao`Y!?0!A!pUwOG|)gt0WE}NHf@io+r@q}*$R(`&|=qSKI(>kdjDpv%op>w9_shZ--sQ!7o7#d-kx2; zaK>?3x_{<$>*~fWfL}rO&(Af6(vi#RyxINPT*gz+O1W4dx2#UTd}?C8W;SY9b~B#OxRg3V=(<4I&|pS&f#%OO>T~7AhZVQ-@ueR zC_GGS!UP;G+C1>wH_tW48vq8x%bx|r=Gn#jzdvHh`h6S7ot9kl*R>{f=|%rG(B=E` zOqZVB2QU`E@m`3s{5cPpHi$J(_RpsM4YvW}3!hkbppW%i`WAAoAKXlYyCRCyAN{~h zY#lM}0*duJnU&Ss+POPLv#Ke3iqKVF$k4v-<%GH$Ey!0TmEk(yKD={upzfO2duI<4 zqgb4r1U$q}?^%36=_Of!a5}jhdB2E247_1v6;7-Br8Ms`BnQrE4%R4|NWM`wUoLS4jpIlSAjRjZK- zO%IxQw%QW0%%Zj{0N%TI*Xo7L#QKO!%kjaf@5DKXy9gF!xf9ofcsM(w0tc&ps?QAe zDEQYh(zKh#{9V0rz4w$PmL7AUkeysriGT`rq}N5HckkX_HKe1feeDP1P$)K7TEMXH zTr2C)n5oz29>=%gWcBX5@6O5o899#9??jX9a}Co?Tq{n-?#mj0Ebwx915k7d)PDU` zH)yG!-M8sgtvE65EGJ!A+MS!{pYHdp(~!qsK(lGjrMd22kFS5MTlyAdcW00F;hF=& zKRedn2LU@d?bbK3QXG0acI8uO!lAaTNZaD=D{tH!3yG0|DDKJ&QCB;!(Let3ul_F6 zW${rI^R9XOD7iBZ{rOEFgr$)4&5?0(1a8gX5Ih7>iyz~;#H%j#x9Bn~PmpE8Y(feg zV;pq>8<9y^jl?&)1kd|;-~&E=wh~@XJbBzT+XE^@NX&$I#J~x7>^|?r!T4XypCmec zH&%{O5ec{nF_qO!f90bnNREThlZ?+CK?Hga4!1-Nq!%?-$zaB(&+P~vr@7N#PW1Zp zT>Zb;IW(lQ;m@ zmzl&SaKm+Qk-6sP4klCg6E}m0_22qp*Dc&~EQ>gAnJ%sow2K>5)2>VNyYK#U!nsX5 zbFMRU@49W@mz$P1`PT#t;OLa2&rMfGRLF`m73l$AK#wvr1Z>amv29x+?TIjVTF5)e z&%`tc!kG4_$`xhc^QN-cPhOKBbeM4~VDIXBI5L>|MRSei79~A#g~t@HLi9&(5hD z%6GwPW~XG%S^)hxlkaRZ9(7i&W_&Rr2Y^*VR`MD1E?yYcZcMwJLy9uk znFBle_OTYpj4PmMh8rUJ-J)5cmQj%E8kmSVb$KU?^{ngDD==8}Gl`6fI zQoUpK-KgP-ew!-?vFCRA8(X#(hSCe~C0jho(gtys4OGpq9_M$7`lHgs&K*0K*scfZ z7tE&Y-_M22&jlnBsKjY;+|}zY#YGzT<0vaiZEbLbZxW9HCSV_NuX|Jp#c7B;=6!qS zraQN;Pahz|90Bt5r+%|o`A)<$PrK9WL@JMnxqUf@V(u$Y()Q($#Whwv1mIB!Cst4G zW>ocI_f8S>5Kdor?#jybO?Ahb8zM3;CZ_Mgr7vfvHvOJbxy7l8KO^1TxqoZwJ`)A+ z7xgT?Ta*DpAWL&%(=L5BL*cj#f98B$ey5(Uj?LNT1fJFCq9YvjW@8keF%z5@kAlr{l_5b<^ z7~Qk^)n&J96I*_^84|z;vzuq#)b-B#(w`H{w+#|ctNOgYK9BTWxC%hKoWf47me-Ml zFkE3u_O#GDQ!F2SU0!@jI4hNLd%5uu2XqECPH;$0-&!%=;jSE<`xXu}`@@i?;`~p+yhB{2lox-Sqh(l*5XL?j6$7}v<;7Z-(Jx5<>T2st~rds#9k@r^1`LI>rNyQNy{OL z6KS0#kccunUiF&Csx2tu;#&(PY84PKw%kG*#GbU$Ny>d)1Uo( z?$_46DD?we3=%{YA>sbLDc-fQv6@Z)0;I($nfMYy-wlw=X)`;y@)HtMPsa#TpXn12 zLC6T8J(y|sK)|HV**%WY)=Fs0<-$=eeswVsQ2KQS16DDVyjc5(bdTX&iIUBQ6l$WL z`FTF#;oY;Q%{z1S{S@#U6$ux4%*;(pC9*DNXN5M1pv>`%4snyr(AHB?kI};#5Mv2W zB#PSo`{UXUW^(s3Fi3TN`NWCU%coA~(SI~W&tK}dTFW+i0x0&@wD%?MLjTdPORepd zie{*1(D8Kd-bIJ;W1SB(Ws_qfn2FPKY&Z;-101HFY@hRex#d6oSLZEU|97l`*6#+< zysZH=N)sg-MQfVq=C02p-HQup0A+G4Z7n~v|C<8U%X>CRppDI;51U_`Plz_i9Dok; z^m}s+z)uf4;mOVUO?y5^)Xa2xFaOEK#Dm?*ToVlo;G%#d+H@bWfJhnui$HY0F3qA4 zZ8meldIJb|qz_DSzJ5bs6r1UmH4F9Mm8|vO{SW_RdG-5proAu#lAuz13(!639Xt1{ zMw1@Vf0NJNI|0i$g9BXiYdZ=XG6_1o-wtHB)zhctnZ)jP5v@Wh6#0c04v*M!HwUPS zl=}IoXX!f@03eQ2vh#bB{aLq|xfwJh&e6eG0Bu$~B3SbYnT5r$!r3ZORew|;g72&V zxjiVgr5&Q?<2V6j{6HLF%ES_>iG+>IJ-8`uV5b2Dm!4&vaEepM53epkCk|COl_e#oxln_|8pOeZ+#c7{9D17>*i3C0YH%6cfexOTfv3WK#k5% zt_Jegum_;l_x8l{U%yR^Ux3x0W4=3IGxJKw=12E!Ml?5S*OyK@KLhf;lfDn~xZH0N z_j0Zq=AlkFeDANW)CLanq{<_0TNwK$OW5OmXNtIx5Y!v6KOchdAqWxS+mP=LC|RwT zR2ey#ogqHTT9YGc8QsHx;a=uel=pU)p!YxcFrUEffN)Wm0T5()p%8YRws(ufDPj=- z8o$*H7-vJ_<;-*>w^P!s4Wzt$=}P;(RO~LKVC@1l;>d0XG(t$ETLbI~g$YUNU3=na za`P4R*wK6KMY+Ano4IS;qs&{g21I;f7~xbzAdEf1Z}|&b0jjxz1aj*s<+#cohJ_l0 zIF{7>n#ZxSK2P=+sv%Ox9Wtmh6gx=`gxbWq2mTug+u{wPGg?Yz? zDce+hS$autw5fB}`&0dwmgW1sJQ|Ifm?>>3dTB3KkiG0J-n19AWP-!ac=>o-4^ z_pE;py7kX9<$t;J8M9&a21Jlykhsr59KYA+=33vEGyUs=W8DqE2g#aPWB)4s1=W8p zAbQ%uxVD&s7v~~<0i|aFLMgXD$tsmHPp9C-gAB_U5rQbavP2=<{luFd1=B>Zkf!9|5;Kc}QWd2w8|4Cn<3c zkuW}6l0%BaFB}=}x;q4Pur$IFh^Di|Da357W{G>tzNlTQad!}N7r23pi)G9r*zd<$ z$^x|>V1lkQ4%x;xkky0}F(2G}w7O6!se45Z?2Y?8PB+}U|Ao;ZFXkTuWDjpI2ty=W zV#*egY!k)Mt2PISdA7&pmXM|Hs{pv~sRXi+#f{E&EEP2r3G@`;oDEWS51^UB4q^eg zcYS8H30=^`)ip<&dlPKd2(mo6Jm;BpQ(9g>tA%;ozw2YU=E5lceVRm6bK2zvG1Ni;Fo5wSK#BZ~NQ4ryaadSl%tCbo z*Z`fdK@>}H8t=5!0O26S7`^0h!v#M5{9M44g{wuMcP4_!-rQSi!In73Q1BFBskis; zCJsI)D>G3lz#hk9b4{NxfAot9luZ6N%!dJrdR&4=8A*t4%)$F>`;qF8JtNmf&}Yr` z&i$)h87d&xCJ2-R6{R;8RwrvNz*88Ez*UV119H4j^%h8$1$)t*dRAc%#DEAVZjJb* zWGgXK?J&@2ek|?$=x%PXF0gUoW43KV%VYy4tewJ%0M>rz?LQn2Bke;~9tPmr<|Y zd+)s|Mm|^9=VGfKn1{&l{$JC9h4O;7o?bYIC;KsXPm}W~`me+53(Gy70i=T*W@)}d znuS|*Q&05Y8u|yxx@}qwIX7W7i>PICAW~Zoe@(koM26q*jqSuM+xp11%1ZQh5gCyTc67TcdG!%*uaCt zC0j^*c_HKp$auC@nl3|l#zX*{ZjM|aB#$p$kJp``p1IT zd%s4!u#Nf&Vee+L-kmaR?&bRM@UsT0GWk4U3^0umaWL~i0x15N9D$Jo}zACd?f=1 z?!-MJ8n&&#x;avD&@qAc`$=Ljllr|37J@o=q(@C5#QGx+ZfB}OIr^^fIKWk0%bry~qm_?X-TJ(A4`pIV> zU3S+*3(QHsmR>H?w;<8x-{$%^&G_!c;qbh_-v+Vi%kq7h-c5`1ih1L2-tz2P3$uJ* z+6C|*fA+-y$>XTo?tKR<)w8g1`Rk;4W?z8I5l76>f(To_kfk??8c|f-XgN3v>r z2?t0H$cOuwTZK4wBs!wdo>c&lK6bE7%q={!y=zDMlFF8u<9NbGH+Y&F7rlJQG!Jfq(VUC!=UTA0^^_wx2uBB5sRC1~M?ET1Z4fl9q|2 zcd*o0)bWkfS!Pp|48_GU=nHdTy+O1CcvO&<%ndaH$ zu^CA>Ehy~Y%|q*(rUC7I>-_qhQ_Hb@VN$)ACmzKcN^eB@AW$N~l>#L1XEjpC_-k9J zx0<%TCKl`rxKZ-ycT+_i<17S(EI>p6ddQO}RmLndL%0hwEz#sq)RbqPQ!I>H7*mggu#01m$Nph4W7~2@4iY~Q z-XHSCJz%5gU;&B<739Y?h@DKbtbPv@Q?<1F8uz-o1Te zOy>>BJOn4^DZ9iH2r3S|uy5@U&9T{kh{>bo45aJ|@sA$azdC<;HIB;#7FH8@ zJP-HJw`!BkWrT5#^)5^EJ$5u~sUOckYQ85HFp;8YG5?`D*s*iL$6~brG4t4OKWYKK zeGDfUr0}3C{qSgisMscObPz$C?pe37;Z{1o8GvU{-@n)6PW=CO=pPFG(b>WFbBK1}D}lc`I^rzJk-2xY-) zvPQ2WGD33mgG1Ai#?Mk)bQPQzatl8alO{@ec73Qn3>)4-pag3-3&lq~Uf5?Y7*P@x zBRJPG#jDT{vG(ti8lCySHSz4e3>W+~#6~m&;b5M>ooRY++z3Y>Bhg|c8^`4)Zj$4Y zNM?E+?0myBuf9dF!$Rb6JLsS=6fN_qmYUWK2fo?KZXBV zG#q6Ts2Z2L%tRG_7vj+dsAim9cMbPYMoE}H(=GjAkaGZ__5-fbc>>xgMA5_{U^pa1 zM9HQ$K!auJLiquY^`biw3wI|n0WhXiqKa+BMF3w-#PQoY5Eq9~G?wFe(%*jPoz?fh z|AW={zxU4S__1RnB8@^Fx8wkwV&<&?or^c#Tue+Ggu!7$TAT{7lLOf(!NPe^gpuvLJ}>dxJ#MX)xxRU35MUZHUrSqkSrFqlpL*G?^ViuZPt>!v zh#td%JTq@tkVI#{{d;|B5NKZ03HSJ$sDc_d*}p1OoW%#=9c-bAUd?XqB&!}X zzLezc-Q~d$dC21T69Z6u7BEHY+;gy0S~`S&J8+3nI1@v>3*xX&?MXBW1_u#QMy6f& zsdmEG;+oM2Z}HvS;0W}HsrcVqE?)m-DFFpUnS7b95m_Jx{XvQ|Q3ukCBg2D6s;@7% z*P-)>2d-ulq2^4C9nA8U&J^(x80kQuh^@u~DH%gp$0&v0w7nnVa4>H?!_e*9?Uo#8BW_J} zbh^&%=3VZ~oe)nI7|{%f8~>L&Xv*0R_wF8?X7s)gX;+9V0nHZg`mk?*YDNclN+15l z|M=-*Ql26h-%e59n3X5yKfvC=ndjzV?0NU@V}57QCz9n~=!GM5Hei`~z?Jobm?rT_ zbg;*#xmocA_{Y)Im3hg$YF@EMsO9@226&nKI@isE4lo3l@!_0CYTL(r^}zb@%F%WD zT%LF9^5FW^JnI|^N4NO-hiBV-=hABLT7KVIaubs-6D{xdy~eIF>ATFkwx_$5cmqIX z^@;SgVAH4PqIk_sKUQDs@Dt%MODH_Ci>|RPng99T!H@KOX#mCui7YaL<6Wb8_kC9Y zjGI*h=$X#2(K8;$;oP??gjPw#l<9+Z7z`FMk6E@L%KA>+af=*$x|cb4ylshS-d8eE z>Dkd9G0Sk)V75V+4XzCQ(P3cyhRZAp)N0E|=RV)^AOGynRwt72bnaf^<0km@=~te~ z^4Q$~cn~{pZqf!(`mvl@-oHTxaBOnjYjFn=8qK(o*4^GV$g=c!IFyH`z2)58HVtWY zY2SS)n0H2}Yqtlw$5pplMAZ6vGVtI0?JrkfUcB0bT39~p+UX{8Jx3&}2FUL>`S&6g zYHA@9N3+%_kRhOv=!6?d1178AlSdOE3o&tRe^IsodVnMZMfrCGj40`e6B5yuew(Y| zCiTN)7yNi7j*1FL@LIO_2Z?>c~H%wcF<1#yCV~!}4qp$T+yX(c) zj#WvH{)m zI)CZ<>ePv&V-9|Tq+-vSU~d`%G>dG_n}^5gJ9J385|i?lZA{xD z5EeU@XV#(p(^WbQu@IMeH_5BN0UP&i5XOnQxzAsX2>J5ViH}#O%I$dT?YCCDvQXHJbbwWdJCx&F z^K7S0EbcYay#_23Ha!L*p6n5X89<@#_hZ$2*3{HR-tRHDb}z0VbpMMYb3gp(?3f@? z@hy)OW5}|S%xy13NPFhh*Jdmu7xzLybm)+IxfC$kr=(iGpPe0qBvScfNkdstQdFLZ zhQoM2KxLXf5XGZY96oY*(Mi^Wz!``S2+``HiYgM*8ed~VeO20IHY@~>b4rWY9cZ-(gQ;Uj3QH;o_S3V?ZDSd6E8+uQ5CNjJ`D9}5rSqN1T$qwCc+w_A(qPT|IZv5FSll|*)}_hzxLW|YF%uQ<{83lo-@^3zGYTkPyKTF z_CtF*CVw_TlA7${E-C5kXXjV%e^e;J=jT^H{@vfnwthM)iCU+i*3qd5(lchnfDIJ& z^__BRf=5Z~HEx3mCT}`3=MozNJoil@?QViVn;XXa+v20(N{N2((I>?k-B`VR^2JdU zKl|+5>Q-FhdvCot(X3w-yY=%AejOLc)11z5FnRrPW@1IMj~+W&vxy}Yy}p($U-f}@IOEhz{2~UGc1Q^xgG%n=ObWXsvgc&w}}TV zVD~cNejQNV4RI_Y5y{wRdyD2~58q4#Ncp2jaU4<2GC6VlV=o@>J)KW%6!QhpI9(m) z@?NH6`jw1O`pEME@afh?Eo4b-NArQ4IQh~%cldDo+1m~J?(Nm_Jo(0bD%1WTbZN#bdZ1wqOjzK>&y!K3 z`NPdw%y36sKm@^^Ovx8B#1Qwkhg`ek7WXPF!jHv@x;0`DUc}XxcsRPt=+9vopV=a1 zBnpNc+K1TQ%eVk`Slcc)?m5<;e&08emG8{TA&jqcY&gs+wgZdSrQ|t7k@Mq(csR0^2t!$ z<0oDM4?TZ>^;L_;bABLE0MbyJiF1deEaHyt1|$Z|5q0|X$?|mM1%B;rD;%cSff`v=FtUDf18GjLgT^uHDS2 zQ+tKR$G1}053GLm{;x9t@Uv{03X`M-mMZDU`hi>2%&eJo61fA*I@3m6ZtUOe&Q>Z1=oUj4=2{$e)i zJaz2IP~k5wT^%mDX4^RT$4o2#=Qe;mO7eDzQN>FvPoMh-bQSW>GK6C2D)k{?ZVW`+1g&_{T@y4rzkW8ekJ`}$f+m_*lL?K9e zJ5%u88}}<3cPmc$c?&0fb$^I@dyq>??Js`$L4dJXZp2IxtJKswa_nf~?+@z7?GUX! z6ho#HIo9?^1RN}GDz&h9iMzTNKuT;<;G89CXT;~F7f%ZO9O@B%1Y|LXvV zxfj>?C&;;>M;r zO^8;r^G?yhtaUgQ?gU`~`oY9KF>s703%0YG)mC$fu)X>EtHILF>QkR9JMwTAv33+| zP0b5J<$ZE(?%$)wWn_T#U0Z4wNWV^UsBgG8L`2YttGM{gT~q_YduD$G3y*0@zI|-j zNLdhOeZYZd(aP2;a`0Q8P3N8le0?r;$u6HSzhdkAt7C@`CSxAyvcNjjM3oVxbW(r= zj>B17e)_XtuKwgd{Ke`@xe6y5^eX}K#)@;i8n~3%k{-ruO=-reMXL&@xEEL1l861q zmCK1#M_RlatN-aw{$di7?9E7SSBCU(h24lBEI)@P0jnI4o?&*lb1O<4f{>q4D-`dW z$K97LUpD23AAK|kCHI)^A62tMvhWkd;7llLtzSY=oESsxmW4X^kbsK zt_p1s$?n9RgtW6xF%0Yupdb}TB0mGu_TI*;Xx*+oRamL-xYEgrMEu}~KaNY_M2W%y zk?;_rtvbW!KKpb;9~p=byPvbj?9EA%Vt}N2?dv;8e!`%qV zrOe8VCC_i&9mI5ZLs@n^ii*zwg5e*DAL z`Lk!c_nYC4SMPi^qLw*Fc<6Uh9Y&AJf1A+fSD-7mNKC#D-Z;v?3zqLIgVy;+r z86t2u;-Q$d&HgZ8e|-#M^xfyw>I;cC=bq^>nY*7VgfU_nD;W%v)1Pd-Ic93gVlvE&#$iAl&HbLa%S9#O$s7v zbpZM6`h!ymYW(ZJ{+pTHy8%2zc>A3fE{W%lIM?08`k=(L;x$^4%lutNT<#k&tA552W+#j*wi6o66_k5y0%*-S*hY>2gs{ zoj93w?DUA3016^5>r$8cZXUIXi=O-R?2O%SmL%c@GcBV6-w3&#NJQkoSs)`P=$Sav zn{U1yq88TDc!@r0oN4>Y<;x+(P-hRA`lA^6r4WvuO3&N=P4lwWuW(FU7MHk(Q*=KBfHa8I%dfw^ zdgJYP${KyJ`uzO4-dz-Rb7{^dP_%WD;%u&-JmpyC&gk9x6p?aljf3$cJ$x8Ug+!2v z0ZMohsen<&JUPJZ`Y5f1?c?A`CxS1DZfDM%S#Go>>tiF5IWZXJ{DvL*PP`!l<5)+J z9IXQ=TetU86X2!fYAls)BlvumhSlS_6V&eyC!xcve7wZy?I z={Gm)-|;BnD*>b|%VGN=@Q4@zo5eMuzk2`uiN4(*f}KupXbBOZlB*84*4xtKF3y}T zvV2Go7Zjg$FK%)zB12F6#m|2pf|cWueli8@niq@CL<-;-8JMjH_*&%2#cy4H^ur%k z74nr3Iwd-SV$HR2?(9bqu%Z@10wTrjxVexKj#)+zfWqXuKLFmHS=T}dCOv=tt0Ez; ztxhR^msl>YjKgqyevfTY>ZeZ=38fvg5Vpp`|95?jO(ID7h$19d=kp;i^D@K{>T|a_ zJ#q5n>g^x?LC+tq4%w~Mg-<@1xn!}sMo(={a5+&8&xJ4}t_Cw>B||I{Z=Xc0=p|r@ zE)*^eq1#^+Hdr!04#b){8cd6bxN_zEoc9k{cdV8Er-u(89tJWe*GRKLm>%A;diUKW zIG6U*-EawmMm#_AwGPK`bc% z>gyKHZc@MhkN(lrQ2XfPj|YezCmu2pt53ze$=P~%XQs-=NffyqAiVjVH&%P&JSY}_ z2x9^S&_|_*rmjHu69G*6$wESGm_%=Y6c((P%r%R}mtY>9Rslwm7`@N9D42kZpGM49 zkxi@PMfEXJ?l>U+D(K;0Lw8v-X9GOpI4^z|2m@7wC!L;grWC zJh#*BKKu0ZI4@CF0BXx;%(b&4#31tEehBH7IG1_g2u1iN^16PGlQ+(AFHUmi%&V&( z{Qe)Lr#v1}`CQ2IT-&+th->fNccjmVYjdEV2ouiFY0DugMs06n9}$b1U0721-Wo>m zk}?!Kmoi|^MvQM^#*{v_$*e2G%+Yk1Po9Et`uYZGlCqxd4>L&cZG`E;;Vy|}&!RIo z$g;k9J}@x8gD2Q&0AP^-6JQaqgw=A2&Ax=5=-Pz~7e?GU8HN4w!WT2S?EH#MpoT1D zDutK{CP|^-!cOFN+|E49v3RzCNP9`X_WE~*VqTBx*nj1E6cf1_uPg-JAIF=b)$%y4y#LLF|Y!{4=-i-j1`h7s>~}8dLGzh{fIr z4n6Kv9Ec9uwm%Iqi&b0;urUPCB>|eg5kDbNOFNYQV%+a?mOF&yc!m$gjotZR=uuCK ztIPFTzf1LwXdOCqG<|39gz;Q!ua`$5g9NpM84b>yIkP%?;#7toj@W`zQ?Mx7kB)}PS>LBYAK3GvjrGc*W=X>kT#83iV3ErJDkr8Y2> zIQE7EYdp}z)1)jov4}u!SRcb-qD;(YTYs^{{(E3J42;&<8=FA1UT6`>z$i5YAx`iY z>`Gn-Ak2IQ#R9dHnA2p852A%vh+&l8)nboFogkch4ASC|QSYXJ;xO<3;zBa@ktX)# z;U+)(+0Q1*S3sSK5{$>%^yODyPSJ0UJxZ%+VB2T2yWb88$?ZbgA3PB5vU~OB8?Ubp zmUBKH`tG6N*OTeXe5+%1Yd93{vm9LkR8dWA-LXcs@j9!c1;7XBS~wK;NFwZsmtGtM zX7!=pe9_i%9EAI?T*-=~o)($DdS6jtfT{+V7&PLO*PJ?;DIN%h6o?Cv2?C!yeQI?v z6F5;AkQ;+ow$qTM`$a>m*M-`DmA{DYx2=UyqnO!OdM`rPTDmv31;yyY6ot86+BFu$7+MsELd$o7dxNMC9!mi4^W2jv^9cF>B8FSQuJT zW(OW^{Vp0nB3v%jF#?e`ru_)-^C65wg!scmKnEP~H$VCrhk3FwD=R;?KL1SVUxhH6 zllnR07^Pn$`}&JzZF!jEQb+7d$TD_2yEkjY(HvjIE8>p@Wf|IgV4Y^$B%+3tNb)(3 z!8E)t=N7T-VH2!I76+YdyTe(#_QXoZ44f*(spM^rEl@3`R+YnJ#{$f_ z1ljy>jzK_i@#2@=mjav!e?3dvb9Z>*Q+Tgj9BU5;AS$yzr`+BWpy(N>xNv$@ z5tW4qsK6jm00Iah&f-~zSy3>QxxWPV0ivTh7R?3S3@|HHelgQCpU=L=wWZ?lPovmk zwHEvf`Dpj5h#pXKf!Wdbuc%0q#SIt$Q;s ze|727=mly79A?yLy>Y@|F`&#M79ck%?ez841Z_$~c>H8B(j3ez{d`+b+`W5i5bV2e z|FAiTD;2MX!#9utU}M=6w=$>vD?(?Qx-LuE&cT~LW$q1B6vKfmvJjrd46HCPgl}WO zKm@H7!vHB@J2A5*+EOJ-gb)!6pXL~~W39t(&i(bZ3W z@{_0Uz4xACUK}I@`A$0hF0TVHB-^RDgyt1QJ28q56$U#PQ_SC-o-%MLo9{ zV)E4h2~LeTc!un+9UgddG0W5MP7V;eCW--Zk=}eRtKhCGyd2AH{CsNyP`&pr{`}7p z`*J=;l!(da&V8|Z>y0xJxwiU_plmOM<>glxAfAirf4(}}+7QQh)rGjfxE3D~xzian zn3V_7L)fcXRg2NnXt~Le$hykXFw#5k)570cEbEtw%ET)|B>_SAX=+{xH+- z-v-P~q{*fYkQD@Q3#kA&ccO%Ez469SPDx3)*9RYcIPc@2gB*wASVBG;tXSh-h}nssr^U!$iM%kRM0Mn$Hm}kh~+AM?d=b)71}uu*8VHpOf&| zi>2CHzyO$zf@4!2&As2CnvP+C21&ZUKHdA41ssod7DL&ZCvxNpC34NCM7I-x?k8t+ zB8nJ**tjsK9HYRC=?8vajSx^)N92kNe*Dp|6P;MALMU5Tk0=8gwN@PxF21Wqxr_&o2!!{A8F_6mG<8W;YbC0 z_BL<6H{RJ;w|S-pJj_QZ6{1Vycm?3k?UqWhSUCIn%+=pIy1Zp$DOQX;4ntg<+d{?P zK48?h4^{&{kdCLXzxLYdAN}6%w^-6gAEeM%Pb&)$k2Oj`Sw?A@4_Ue_5MK#BMK>r~ zZ@u$Y;Ra_K#QoKO{PRB#=p|h(l)>cRzWmkd)zdGHRqV^C==JMYhob>V07br~t5775 zpE^0kAU^-(lJF1Ss)4} z{Qv+mKkwdiaP=?##lIN&TF$pni?g4dooyB_eRY0y@ym0u`@I9qufF=)0NAidH|mfGw)P^=?wt%MnH@!@GV`LeV`(n+U%kp4qthD6?R z?b_uL{izBQTb9VnR8Kr688H4FNHW>l{lriNoCCMxsbD5j*>58B2cK8(rrZBRv1D7i zxO(rs_j=5V&tVtkz9b`eG?*j{G$rJSGBaIvvI)q#5%r*}@EW5A11JsB7orym!a3NP zq1F^O*#F9Fuh-rp=XarrFVrI-+0!B&4JckXe017UNDuInUA1vNF~y`^XmM@_I11H$ zlRiSh!{u0b=u=C&v&j$9JCDN5-tB#(d|yjBezI4!`Y2Y;G>Ys;ADtr-zubpA!l0|9WNZopT-(m z`wRj9;otwyA$f6liHRS5_(_O*s5yFZb)fZm_4U`yP!85TtLqsCp8oY;Md^z#YfecW zlNKE!F{|4pc>owOYQC>0ntt~?iQjR)TZwWCjxZa`2o-1>c7_!Botoxr-Lt3pQE%Wz zI+|=%>-!*)yD6Hv;i!fP+k?x|YwACdpU#WBLv94&epb_+JF>d0kK1e4N*u-q4<$-^m%Uqbe`k~V_)*i*4HL!O3J@Dm zHMuw5Jz+iF4WLoS;Tnm2M6985Av1kKgY+7lW_mtivAmB04}0(NIDk3QrVt;u&>k2l|XYYY+3?`=on#>bpX6nPRtyUCpzPLIMJVf9lLE&$eGV#tk@2pO~d}as}^SOc) z2eY#N;^#k`WIZ`B$C#cI^Dk%QXr_CAP!o)7@9+6Ni^EvT0s=+U8uv$g(3oF{I*#Yo zjUKQ!(VY(J@Bs=L+GNgjX0nU|(?M46r26HNjdRq1guJ7@uR2MgVlCDNy` zoB5MC^ZoCAZ}q=@`Sj{9qlmc2OQ%m{c0E}P)|nZ{*zId`#H`*sGdoB?{G!y)91gGx z&?M?02dE?>u-aOGdma+bTm*HviMbJm1L3wdKCRqrv!Z|hr+*rd*1wmkkTM?s^AUi% zt2YvT0mB$vLKw(N?pG)rg$=6efA8u)V$bL2&Se<*Xd->>wgq6d!}-gUZ_d=i4$XRZ z)~3X(U2&luare(MoZPscGTt1et_?6wWJ2$w%%3gIA&^`Bmw)i)>bu{4XDIgQhFQZN zHYaG^qU$Y&j22}8ltoge>W|Zbk7i5}uV!BMl{#?eMny*YV-{v96~Bi_5SJe0sQK!% z3lX>7iDCyMRF6k2wZ;yJ2r-DeU5b0J;_T9S~5SlE$7|02zIZZjBY-J5OnM1$x z+AC4&#EE2jg}ILwWT>(vIamc1lywH&{m7Cwr`UDxU-XxN6qIie#&}$7+zyoMaqpR3 zfh}PD-5T=rPl)uJs*pI$w2p)Jp10q4eTqz=*bg!Zzx{*XnMIY4qqczYKz4H~G>BNM z51h!T=(ecym8+MVlV3$ib4C_`NdFN|glhvByk8Cu;QhmY{?EpYyLWF9+7A{4zHt6R zAt%ZDfrj>Rwm08=XZ6Ng@2o!l_-q{F&GF^zPv_jzdIN0YjzW8US&tf{O8fK@#1wHe z4|Xj0qyOq(#$8`ZfQ<+Sd5^!YPu=(FXP>qCpXdvgNJ8cYED+25A)@>CA0A|q&o9KEcYmU=n~xnk7f=62hgolT@$}4@ zGpkQO{dATyyzn{4AWRDkF(yeS9j4V=9G7!P|EwE(dN~&VC{}+Y(TPYRK5SbQK|VO= z*o`LGU;%=`+->4jeE+)U#S-ykr^|H|4STetscjr(xDJG=b$jAWcmMt9?QH=TW;iE09 zm(RR1j?NJu5*s=1_Kw*?Z}B7h6VSN#t+#6f)y!9slD>Vmm`gN@&^*G4%$4~=3tGPR|}IUw(0Z&QpYW^nd&Zzqk6mfAWut zkp3)@F5lGa$5t=Ba%KQe)P*PjA`i23*gxxmqbM(B%qTdq=lP5ZGH!3CgHfda@Q?oK z>O}sVl&3^Hks$RqVsbr2UHS$?5WuGotNJN+OdQ+YYbo|A>Zea18If~q$SyMaN^nKj z*%y+~?+^hdXwrmY8AP%DjqhHLQkkhEzBPwsHBBaL)3G|v{c-i2uLG67tdA`r%cLk{ z9<4dE^5DoI3^wG(Fli&N&2uW5bK+#QnB!L8Kl;@#Mg+N&0(ardqL7m{|JA?xU#$+e zz?3XjGJX`66`enjMdOCb?%B7Ip($;XJ z+Q7-=vv|PP6+3p6mONr;Rq1PEtY1wV-3u~{mD*a~j=3aCu&NExrl?|tqgO->^jW(& z#JsC{A}#`$ZW05QyH(ufIOwH`@aIDP*n# z^@E6maz`46!}Ay64mcRSa)XdEF~7Qbcl9rS^3Tg}`O!F@hjaHDeQnv}h<)kz7!wi; z8Fa3-iIs84d%{4of|O5{ZWTg2t^FXs{#3^xDQACT8mpf@ZJN?KIMI`?Bb1>=#Qk9g z0U5lL)6`8w-4`;kLwdoekg21N?8~Uc3Mv2Vw~l%^vp**XVSIx`f-ikFiC7$E%290Z zd=|E{MbT<9;2W8CfB1v%rTiDgo6NT(N-RLoTJoZMi(|uH4TOS9X}2f>Bgx^?MVs<~ zo2fbq+)D4rf&>YM8k6(uuXbCa7KW9o8G)Q36@tx2F^XK`)T2kXo1houyNL4a2yy40 z7Qtf6-{)8btmAM+nG@DgM}Y4=5MvOO65Yb%ihxAYlSLOBMZCM$9NjHd8}i(5UwLMC z0FO(Kg{O8jsLhAf+8RWkS!qm-W90Y^;?yp$_SW9{BnmA@NFQx=@lD@}bsAzg+2~Y{ z;*N7PDLtAaP_ScSW=QenxpOmKkr0O(@7r&_RUFvi=7Z%5a0ep$g0-f$FdtZ4X0U%%(Olqst;5v2rW^xtmXMZ|x{;uuf zeN-JReK*^>@D?0|hyZa!?+VMmm1h@M5!$a#z>Okc4N5e#^ks@N@{Ge+SmEsYP2p#W zVe40V^~>|057(eWL8`}(i|lOzQFy>30qkzpGa>$*tb#?2o?t`fl`hMI`+_gT(ZlQ2j8nuNvYt}l9~o=Ej~6K-zD~tZzMkX7u$d1L(bA)B zF}N?o&XHpE=)@uzthF^`wwJ(W%|}|Puf+e2udqf+MZZ#?l4!brTn&YLb$q+FGKJp| zH%fm?SdZ8Eu|b%P((mD6(;E&$BwHU_lI5T7+P$k?-%`4>Z422SU61SMWue+Acd*vI{^mUHS-UKE+5o`cWCVcR`bHP*Wa>biwE6L!K86GJ;t(O9Ra~C# zfaolGBFCR}45A`#3ciDO2%w2RC6ejWq$~6um2Kz+%*f2!Kpi14Ua+XYkYPlvno@l4 z&F_78ILPCE-<_}+_k}F(U(a&b*%+*A>)bezsrgqwTAN297Pu0zeK8-?zG^Dd#US6Y zLT>C>VBT*=pq8Y)S-e3UX$TBE)|ePBI~Rd6cM#h+wwGQ#R?GU;(mI~vJUGg_0SON^zF$YRI)Uv+L zM0b9adVOtyrlwZyD>6P1XATEO{X+~~jbm?PAfU4mYefmO>H+RA&YiDKo0`TATg1f) zi9$ENe!B;!vvaV|0ou_UmST6_yC5UAe*xNMZUV|#DO5GFslzO5E8=sxhUQDzk#o*?wg`^BcO03@ywxk4b z1hzy&Ov~w*U&|qAUd8C)Hi(2FDf!+0d|bUDTf@b0_s zuKYR9pFcmJ)zF%3wE59L7famIDdlVwgBF@#l0?T|PcBrX;l}mb0fH?D+A!zxmm@2l zD7E!aa_PNfO#T21b+b0MHk%jXI2OvlUwiHK5g!x-gp7dP!Qm#U2~xcC_S-{kt`#N% zVJwUV2kb;9#pAq-jQc{)IL8td+dTjw1O&80mAl3oBXU>(c0h^05T~{-KGk7jyh zl9d!UWk~~Q)*JPP5s0Zm()|$If>&AZ`)dD&*JLohf3OYop*g_)XY(VE^&nnH3`TelU6T>6RC> zloVc(b;abr@%rn{K#LG1Qilt&kTorcdRtfeBg%*f*qgV0SK;ShWE$N#LOI%qK{F9> zr_S4EVMjSR$Bv$u_%9KwL_wi80DNy&6Sq15uBd7Yv$JQ&uOrHZY)Ui;l|3>Ioyzb131RRk3-_@wWkmxgrbP+t8-&ynLaTBjy%!Z zJ=0>09u%eyV$4380e)SHi}epHSU>ovnqau&iT>+6qVGA^{6WMF90`qskgTu_7v@Ak|75XDJtj$7>r&NzE-uT>5i zmx$W8!}~*;f=p*arCM8#ZzGJ8TOf;L&0&;T8q0!n591*FquvzTPgOz*QPj9nh2_en z%Q*=1p2oI$S%q4>l#@yhyLn;yoG_Z&89ROp32_d5lLe%6D9Ur$-*FpMR24>f;>XH+ zx5e8~&wv@%35;eUE#|>0x7am{GRLz^98&xbMWstn!~qQCy>jznRH-nIWMOegqMvVH zzck#59Uq&QBTlZqk#E2v@pwyZrpKUo+Yq^ebDt-c1{9}Go*Y6!mjqY? zTo$3p8U;IG#w7q7$1mhictX}I1Ot=ibt>Wm(tr^ce$X7=&KO~AkV09fiIeLA9II*S zzQtdpZ=M4f#A?)8ov{g-$DumU7lNQMN{oSGpa`PtD^Ail*T`W#9%Km8B88g{1+WnX z$0K8^56`#8pM3Da>i_=#_>+tXulK&fb((v|ide}_+U6x z#j$PK`utQbV)m!2?AxCtQ6DaRd46^IllRkakC*dvclxl=*&)l{J9P3lI*g0&#$ozf zdf)F2wrvz5iCk~I^;UzVe8<9D06;37WpBs=aj?IaN+u(F(gSWit~3uNu1Rx0Q>?)o zluqMJxQ$pdRDd^D3Nm{+gcOTJ6r1?5CKMug2bSyaR)z*Ef+Fz&SR`RJlz-8_77_BH zED$2qp#>u{vR9ch8+dZ+`xZ zpN|7{f1)bg^30jjt?`lZADJgciG?~x<$E_u4tbcH%>m#Rdc@Zz@|W1SH3CUw8D0lT z46^G?`;ZNi4M6oz-lqs-vyXrV$RauzY9N#{P|*#N*~F}ksC^;g^Iyd2yGHlSz&9fO zgVuQ}6!qKuiGo)XfgxuJgDDiMHN|cBMaaYx>KbE)>On_oqC-0m>6(ED_d zS4xs%(j%sQ$q0}Y3#Ibg?ob3(qS2W2nkgam98BWSMB45|(VnCWMbX4AsR_*Ui#nkq zOpp);m%y%fZ(FDZTf695S%#=BK-=VL$eS0=BidQ2uGt_O0YFNt$|k!)YLkB}@r+D9 z;!XBi^{=kSvAWzM+@CG|0Qk*xwi}hked~MQiDKb8`2;d7ywp|~SU<{oGYiiY2LV|9 z$+aNvp?((mo9=_Y023!vUTI%`gH69Juz6!Zk!&WBYIYAx4*TeX56g%=o!{kf)~IFo zGCJ9X!sP+|#Hls!fLbY6fO+zzlT%mOJ8>*P=x?$15m6R^Bqp0@Isy~^WF>Zuv4WMMm!xc4RU{Z;c^I? z+u_v7)vfcKm*QE5NpRNJ+G;|?UVH7eEbk$L7jziK9Dn@Bf4urP|K{IpEhk}1O6r!P zQn%zYfkaz(Jl*r$qepkP96EYx*MZ}w{`c+8zU^KELY3sm^R;LWz@bDqi%A!PO%$Sk z0R9;MM9`|o1!})8{Drup9Y9QMAtvBxhqH(rs>p(}O?z^3?j8=5LlfdejfK5n$z*xJ zXMz@ayX#F3ggIEO7(m&YhOx!uqRKQ zp3oj*=J8U3UyOy1*~o5Whci|$-0pI`_;_IhcZ{)X4Xw0O;6n|-v zh%?&*w0hRd6IGfF@kL~F;*#ruU(^umR!lq~DHH?#o@+9cDSDKX^5b8B*uo#KsP?7N zi->y^`R7}#t=ZbY4%ws9rUzw2uNY;nJ55RQuOhaZI@@Qf28?hqoM=#bYTGqtHaf>IfA#AkmiMl{^On@=>K11pIs3_ni5j=Ya6wcP z?%rSrsW|5V0a5kl+1s->k5CpwLge_3NneiR#kBz8p`PW8gmAdqSn`@X6q?gGH+NCu zcUGT$d?Q=V%}HgjXAHdxfYC1%_fsZHWHm=Gz!qH*9~p(;8jt@Zm_h9!6lEM2q_g6f z*P2__t>@Pw5n^giaj3`L|F?hrmxDy~3gRjv2-#kF_0`pxGq0^Keg4HDj(3BnZ@#%R zoLNvQ0Z=*w6SMiDOFr$qxo{5gBmpt_SSyZmu7)V&6b6}f?>?gD&ZDPR+b^GgdS`We zi`=i)aLdMVNhJH%|N3A5=ZleBY)IoKp)rtV&6?~+g#m0aU`U}O-P(6-Is|HBU@oWM zw(hYd#QjX8lwP8jNx>e4&&Wd{T3opjbqe?eGKzT=KR4>?V)$bvn)m*Nuk zk?H^Xo{Zk0>0;h%!2umT2s@;R+Urq#ns9V;N3Syv(zdnzNK?IAgMxKIVnzxvC+08Ybgjpdjk^;y(d zIf<(j@6XSFwt6w$P#bserYknLxHqxTCb1$OaLJ1oFAUrvMpOY@7IDLgw8_X|4Vljy z(9|3_lnA{To}O#>vPA9P65)M9f5E+yKn7{3CjQ<{x1WWaUi-Qn;A6{Ae)5y8@4ffl zb2%=zrZ_#9r+Qn!vMm<1^}qaA|GNWk{*#~lU5l~HVvaQ`>W2ylb>WSc)buDZ%d81t zB#uzpm}XJ@gV=ncSBzj;py&uO=y2Rd*5PfF6Vd!NW z2lQ!crR@qk`eJpAm9c(*^2tZ_rFjV`nC4$D>Q@;i?`&w*47*tJ+2s(dFePGe1Vv7f z%Au6sPpUwwhTDrFxEvpdDv+_InZUJ!) zBcy7P5&Oo^RnHI*Kr4b0;X0ehX&&vVgZRC4vM~SV2FDQ$dA)7Kt(h7Nwod%nPk%aM zm|#);rJre&WbvT2Ql^XUERTkHndCrRjkXMo;Cz$w6GufHwnboe1|QDfh!~N#&R@9r z;NA!S^AGC!&D2=K=0lAlt{%rU)FpfJ+H0>pN$GdZBhQq6-=7^g3?PE(4q}gkC5ayb z^`gL|SacX{QD<3e0E93L9D>YfFG#?$uYzv8yB9CntmkH|_qCbCEg8{K_?;E%{@}0w zwmaK9J*qd*)q;(!$%k2}2(hlAk8DISR~Aw2;%p~y==U_Lc>sBsc|3zaBW`;=MAGfUUk z7Z(DN8lBvIy}7VM@xmn)*PD%t(h(Q{9>$5UH77^v|AWG69;WNvxO6p$EkQ3)0{0~Q zqrykioj7C7yN#aY$MZWJiev4FgI!8D?9BuPj=V21?sMd2&5 zIERA=z<`{-0r4r^2owT=nA{2()f^M000#KJqzfOaUkGB;J5Eq$u!&R4$0PFNkN@4j z3*l77iG!q%(g`8AupzrZ@X{aIeq{B__kTWy8HF*x)YOG8(a*bD(Z&@)4DMD{yrlcq z=@CsyBtol53kWA-2QIk^5XDD*|GKrNhZX-3w+k-fy05%c>D#UUcy<2$KOgw^&)PDK z77ce<8^9K7(z%Te!xEr6#wzaO-i;q-zAqMpY-JH|dC|m<^G!a75>`xxL_JUgx!8wN z_@w-@z@SvOLmEo|(}4DI=EnQwD=0SM+9#i$ozRsNCt8pI;6@a~0;5)&M4vJ3#ue1K z+8ywrF3g$~QhLkI`Y@tm3oA|6#y?jsUm3ul+fY7nL?Q}VMjE z_wH53Hq-KpRj=WjLA~F5@Bg#<(T{$#y8ZBaiumObhs~)#PLUU{Wz8ezanM>jg~^%c z87IC<-z37DZ`+qQjaecuw?0WOh4xR5QN#nB5!;=ID5KkuUP3IyjS1T>(R4dGQ6eC0 zyy`8-nGiAyLU zlkc?v!J;B-w?ahw!tYPC5%77vd~>43><$)Ss%K2;vq=&eH3%8NheTv<3Mb&QY0q;Z z(e2F8;p~VEv(0rPpIT@(aUJn9u0^rN1+T|Nt>8CNELK6O1Lg)NqdyQOIU>KxCqy>G ziEs!Bb94m$kkhaBOnm}0ENm=3FI7a3GxlQEqfJnt_K9ZZX3}_@YgQ;C${Vl0zWQSw?B#p=Uf{knGVCq7+V{oz0T$D?fjv{Y}LPoV3KL^b}NGd+tt6T8hX zjxEcTl@*7YVAj@;&uHh@<^a(W@EI{HrQ0~nWgs+M`kSvap@+!yO1hKCk>{%xB+^0@ z$J4t@s)v0pCz`#nGCDnN{P!yIq2lM$te^Y#?p&QccXsuc|Ly+;*l&(8DT95m!J?Vc zKij}`!*H1m!i;?Q?z`{KgB1StF*haZ_}udU`fvWPtJi=0Pg>k4Tb|ZqQ79Y*i#Ld| zgSYVH=DVdb11JG|wtJvdD(wSMu3oubNXg+rfCt3^;Sf)oq}gU6=N~{n)})h*`AOb- z=k?W}{n=mj{rM>(@!^LbHo;AHz54X*`N+-FF_GGE=y0Y}p6k06TrkFO3d#ihH?u<7 z7xEzyEaV_}0~94yaf@I+j?<*J;QT77P>m@>sx4bvhzfYV#j!~Dt29rXqSxSZH%p;a z;LdxVJhe+0XJpEG#02t){o32}(v0s$k@+XY+U?B0L`>v4SNTy0iMh4u?3S%6p+M-I zZ_UHbLpw6DS1T-p`Tw%_CIEU?<-ztnGs#Rc+4p2JNhTXvAP^uBHU&YcB37vzV%65Q zwzc(dtF5j2VOwi!wSW74t@~D~QnhMTDpU}ZMF@LH0tB*5_HD9EW+pRPX6C=H`+1+q zn~*^K`sv@V^+4u*-{(2cdCs}dy`THsXZp0}?7v9nGum`rUF~e5TaUD14G82>eRR)< zNhM~@oRg9icLp#qh!d3>2BXwBvbS|@YpTzxvu4)Rv0ws_AuuR|B8@`Vxg)2we|vD} znlRo}ywmWoNxZt;pMTk<$*^?)x?yc6>n)v6KAE}5I2F<~UN;;y;7;1HFgM7Ej59?>8?^@|m(dTNmY`Eccw}54qa6!A z>22-m;J6Szl~DCa&8f|}_QBN+vlh78U(;#GL#41Bprq-OV5AAgox72}J+KbLcYV#S zZq|ZKwUrf5kL)9ewlUXX7C-+bLnh6b{Z1qRYl(ykWQ*hqydrSsvfwb z`rt%u+s^UP0MLcQ9`yE6T-VNd@WDq=q1e_6k*OkyXac~AR3~*Z%;avkx(iP!6_`** zB$COYHPYP}rl-sE58Y*_`r{S=rJoCDN~iWtHwm>Tr*f5Em$z$1CiQlb^7Lc+;ISO; zWzSuEs7NDGF|}260LZQFtDI3)R5ea}FLN2tFURCUo8Cbsqc)uD1g;14z)4lPc7t&0 z=yJycJg>cBc!&$AW`;Bghl{M*J>zf_yME$;l}vedBkxruli*!rnS?< zQR1^QEO($Pv2}H;TIwL_GK7ZrxGUDapxCGGu6y1zwq|6RfX$>d7RjAdUD(@kMhHKV z)U_x*c&bB60A1AX3_U>PgA#GG`OtRl0**>d*3IaX^JKi7In;_Z5|j6lNQF7jrSE*Z zHnxR62sgc_u0wgGIzuj`GK8!eW+0|8(-~p-PvO0V8KV9chv2exUM2+|I&K-9+K+Xo zPHRe-LRd%cU-saqNE$#OVuNnSK5UqB9j2c};C?b+25T_^ZOCl~R5HI06p+%J;v@j# zkQq3fMai)X;!q!TRo>Vo5ycgDC)*%O)dkh17V`IMaJO#QkOtTwR4X%exMtIHa3_Gm z4q#$*@yX#e9_8$cX@eD+cd|Q@%ny6Q_$VU+MuQX{N!N$}d>rTAs|S0+uIiu0s)oF| zuj*L+SMRsKPPXcn$kjldi8vH=4+BLc85{%g+}FUqex#sIfLxD3P1ED$zVS@C1i*J| zTQTwJMWa8e7$T1xOM=vE<@%0`h@SPSw?^q;c1iVik!8!~P1#QqdAp{Op&SsA26#6J zGMw@6!XD~+@Lmv|pim@$u3XhLJzP2=wEy%NxmR5~49$u;*~)NwSq_*REiEnFI{-7F zZ*XQMj<7gH$d2LrIuG=UDG}T&L?bCdI$X8I2 zqSDqzJbHVHOB@DH_&X!p>7#LEJ@f$?ocN(+)`hG(EmJi7sI~@;1~|*?O8Dxf8$+z& z4o-M5zuC;0EtwopHPNjV&%fa8{yT44SLUstpLDJ$`FT3Y$gfArlm$6BP_jZ97UR`{ zSTaI=F=2AI&2W&GK0quaT{|Qf$3q3Dml!f)7o?P4Zx<6Z9PTZ0 zc?`wO*>hs>*eUVdyY3^&@u--+{~+ms)+;(tSO<|8m~$0Dy2UNcse`+oq59(D=V1(G z0p?a-&IZLX1LB%-9|`uznvF49?h0pKy?INF?e33tcw5Hlr6DQ9PLQKfHB7Lga_wX+ zv)DxD(GL?q{&j7eVmAmpTF%u;@FVJ78{V#QNSYzteX(`d-gs!!R@e=3bJ$|@2$^jd zjr0JSHt*PzhZPy>vXdkrZTzc2>UF}6Sr&{v#;NgrG(^>cin+T>N5znMoby9RHMGYC zr=NzZgcIP&r!~)F7xveqgmL`x;&~isL?i(!twiej&wdC^M~OCN>sE3#A7+()s0UXy zg4Cml?c2)&BFBlt*koqfDZ3#iiz!xzBayofqgK`uUV_TAX5*GTytfFo!NI~jDACq$ zVXXr=NdPrS+UXP9V>IL5f-1UaBlq}kGUuKSZs6P>`nDYybTaOxiwCk^6AH7(a4IoIMQ_fOqV| zi>RvZI*`{#xu9T_<&@WP^Ge8wYi4-CDc!>Q|0ha_QBN zu^(iJYDcbP(3WbG8QblIM5fF4sWofi90XJ1u`2dY!$m>(DGRI)yjksBUkcLt)Bvu|bW|C%*xK!>8Jk`1pMsH85eo6rt6){$Bj zN@X>X-|EamP$!D`v01ZcCSbH7X3xUoK$#9Myp%$PBCQu(T% z(dXiyQMl_}*U$jmhDul0hs|OG=qiC6hpEDq+ku zNSGRk#!CM4fxNGQ$DV#TEGzLC0PgG8g(*kVqcq+aFgToR2pXdYA*jA1oMF;59iw`G zdWD8h9*;fH5wE}Mq9m5wi6?tM<&uura_xB0zIXA~tD}Qj^>Qz5&VW13*(<^1A^6m-Vleem`mvx`(vuyiho$-G4 zz2|E0x$jF98t~V=CI-RT9>YlI&I0)rrQJKe6~u@b?=xK zPx7O>bJgF=>gBcav%LNv`!tM375MzK7Q`oh^gvwLM6fGkHVclQdIwdrbsiWgQm+#L zb#4p!ncMV2VoMoOptny~^LVr!adaeh4uwz@{#N#}prYIPKI1B{zy5l@X7SpwDw&t9 zRBiZksix9SdY#SR+_f(TZ>dD$?YBVuBi3NYX>)Vj{hUm<)dz%3@Y~tX%mx z2Am<=zU>#~7Z5l#2ozcowirm(y0I-T!k8aFehTUsYf#vEJw2RYFku{P@MOIb0<4O%S_%SM3)&0a+4SP$unpym+{PkhKvIvyyV#MI# zto#$Sh+$}ljDS`3GJZ?~a2KP-Y&QnEhIB8~?>d82txHe$s^@)ZJXbT+V_sVILs9Hr z8b41~a_h2nPFCT+@O8(YDlPCSV8!oefz^KnP-qUs1{Pco;*Hz3Gn2~eNSK18n24uN zQ^Une7nOBp=!SON!^DZi?%|ni|v6>W%oTQSW5KCOt1VF-xKHkM9P%k zX{}N!qNhgbf(=uqSxQ5w65fy7va>(Kr*Z4*<*;Kej!m7~oT{0UM`KDg%k>!71I*cL z{FPkb2!n7B_CQz4m!ITQuHtHJ$z4uVEj>Zj;buAN6V>~9U;A0&ZP~VCPn8xp6|mwr z-=B@a{5;@L_U~u$F7YnL;0+^kquBaEoERx^4SiAt)62IXFQYCl_w%@*Z2)L%>w3JB z^&FHnk0|bz%t5_s)rwfWaA9_{fB*iHNRl{OT3X7`e%E0JP^&chtMM%Z&oq1}l_VHV zeC-G&j2=d*HaA2;?XJ|i7E`24B}|_CgYjVW*64R9dp@dJ=jKklWURpu1}}wYVBRTE zP3w;R@z_(_W68p)(KJridw63yG8q>&n!`L`&N|BNN=Q-Z$cl|8JK7g?TU_E z(30_OE)ts~LbrV%cC}$mv**l;nX_kQH2E#J+#EZ0wZ$dRzc>!;*pOY<=#S_ecun6BNf$Fq>K_KiN-Y*SIB#N3oC}8I5N1J*NGrJh(wP=AB%zpBD#v}0+MS5hMA~! zxyWb`o#7DfW$_G>No0Yk#lyi9)%|$Jckh1b&UNvjzg!+4zkW&l-pfvZMjgfOAAfsQ z-15Z@@yK^a#o{?S5`6OiUy5;I@!|Emqh$h{wMMZB`+uk?Ig}(Dc6G+5Z+<*J@{=tf z4|xH`F^zbDg1LwVBjPJBo*l2eY#z}OaNM60G)h9=+1?%Nc67#)IRx9LL+Ag{;497O z3XUd^>tH#8HKa_YqSOH{Mu`~zWjvhwYFykk^S_bpu1h}hAREFSek7BOTzu&z8NTI- z6j_cM{hlD+-`d)m_Izcj#VUgG7?rFH0Z439!nhwMLt`ol0@`rnse+M|oc^)Wic04G z4EJdpyW|c^JMMmaW5QI?oa9Wq#KM`2ok|xMIG+opeXgS$ef3Qc5}_UqZ&ET6Nl63cFqBmVm5mc>VY&>FuoV?^Bez9n(@2QP~s{*O!Ji|<|>SB@MU zufP7`c<5=OqbX_UI2QVBx660>yDTLfPIT{RoukhlU(crK8j;O?@r55e5f^^oj`;qA z8}rc;CP&*jIv=Mp?((@3Uov^hf+@+ERli)QHt5o|Ku@VQC$sJ9S~h;njv1b`^0DQd z2K{85HhV576U<_lrfW7vhZigTrH9O+_|BG=LM3w@hMze^ua^=gkS=AP5|o=aZ#MWY z!~3zRvMk_5+7t%p`65p%E;mORROrgEu0JOrkAHy5^Ykk`Y3_*YC#v{x7r~8$usnAu z^zp#BEA(=oIEuvOHT(+ryNlK7vQ3e}2^7J~L6!IXEJuH``}yn%pM=AB^CX3J+AOKJ zZX-am0yw2{b$Pb-tLs&Nx38A(Kd>S0SlJdYiDp7Jz4ARF$Ck9v=bgAR1VES%C8;nXe2lb5TW?qu{(!hkuIt+gy|xl=B#Aqfb4BOD~$?8K+X5P|;hU7xR8B0l14V@rY_gM@0g?b-1^Y zPI9?*8#n}tq#KPR8)NbO$?>AIrY0#^{~LEc9qYDt#BaT95%FKzKLr+@zMvB<#-*c33Bfg0$)vOK+&vE2Mby!!cbV*KdFxOv(7w0o|;bY7f0dwfd8 z+gEIj2Uct$3IlKEs9|yWIn(08`Nu|JJleV^maW=`XKHUYJp@nF1&gM}^A@6F1DpF+ z?}*zU+Zro2;>u-H)(;=sh6n2aF5HHA-KBGL4(Te_x5Pt_ZzGoQ0CO^wcTIoByUM}Rkc zxIq$(EPh8IY>k$dmb~B}g$e&sO&A~;laZsZ)mB#f^*EF+wir?2l&Wc-q2YqhIQ-r2 zgfxMgwu#;vGprc$?M^}|+<-s#HCTK`_upaF6Ahe`aPX{L`6D9YcxS)&!PvCZXL8n-V4iEmjSUw-3R@vASGo51|U zJ)7dkKi(EsoY@rTK}@!3|33D;Rq@$dHWG3^DE|Dqa}yza>76UL#`Rx(BD&s$7D)XP zQIkq}_Ni_A#m;oms?vC!7nC9Toa%A{>u2R8&Ol4kGHj8Ydx|v-hb=H_~Gv^jmvpg+3$Sm zN&Xn)wqbvFTrz!P#@>w@Tbx(q{{FG!U;wD^YC-Oa8Nqss3!ZKhFfiC{530w)NMf>X z?P0`Wr4To%ldD9fyjl?=)=BV|1Osf3saLjf%%_o^2Fw}#YKou+0_8ka*R>fXin|HD zpOMOta1q3403*64T+x%PJh98&c1M+~V_tF04*^Kt(D<8Wo8vG3ef=@_${!0S5Y-Bk z$hwt_H()z_bJ_Ozz)NSw>t8fKCgO&C6mQy}e(lkC;}@34{H76c-n_~2-WSe_AFtdM zpS@#kEaA5xcp9X?@rkxrFsm`X^XRtt-K%?uU?%i}@{Rk6q@7qF*Ph>;#8OIw5_adz z92c!0ygYvV;QDye-!G3p`sEq%_E#*%j?|)-O+=Y}G zf!aNu$l-r@^MaJB81I6sywXo^qZjQHFG+v4M| zm>(}+Is=a>!IdEJ-AJe3`sx$$*7GLB`(Af$%$zhLes|Npc>5QY#asXRu~-J95Y8oL zR*$Lrd*Tg!nuNV#79tt*U?Z2)ImLmoM8O;M>;5GpPrRlF zycCiW93Z(j3zPc2^-2_>GIo}TTsmu1ZBjR%CL=iIf{}7r^YB=_bW|ZlvWGm)Fck53 ztwwV6LC6(~X~lzd=Tk)Pj%kROT|6u1fvA=jENY6!*6xZQJ+d-Z!VM*ub7xP87~dH8 ztl6D}a$3{K_z@DI6OYO$wy@r}tut=MW_aTj^WqV_UN=0sJKlOxQ_Pz_F54`aPUR~f zLkY*2F|ILYPsFa+M#|Wc^)Yh--z#O!#@)PsPrUn=rpBwDKbQSE#f_I=GAI6h#rF96 zsy*>LoA$)`g;SCXmV{Wo$LQR8sR3p*Al=HwPx6_>1A$&SYgD}N+H=|KU%+0vdvFb~ zV;k^g5NpQmSa5c#?zampeIgc^iDq2ymFYaIKj9$Gpcx zkCsZ*ix}rW3Fp|*7{!nOv|&`g%Dn-kZ-!_(Y8G(K)qA%as~hTGwv!$}>e8Xxb-P$J z(w&$4WY}lnKy(hMtGh$77HQ-Cl5FY3NlPLHlYQxeiSgc7EIQ^HpLc)E>pp%5&?vGk z+R$#e@Xe?~mrWfOV@DJ&UDYf(-Ndoz_T%bf1&OCS$*3}E?6COsl{4cVpL#4Fcw!s- zH-^Rki)!@ld86afr8DE2&pnuWy99GDI)1cv$5q!&iD9T}rF5z8yhLm0#zED@2GdIk zXFR^D18}@_0_->xGazP(MU_(fY&68VU_5;_7c~0!GfD+mO{3Z4gSxYBH^yKN9^QT+nvj?uyKPOp`QO*Zco?sl{kQ9#M9P&+XdkxQ zZI5n>e|~6Nd~*xzlkuPK9&T{XL%Ykl>|vbg72|?-TUoluaQf&rwk+_jzrU+B-gnnV z!4pGx*B;+BmefsUBjrOU`SiTXv2G;9PVUVmj^fNsiNb^<#m-IB62oAVTNnbvS|D31 z++nJ{gt0;X*DXeWv**)NC%E%ca@z~t3VuEqIuQbn#VkPQqfJQl_6fxqQ@ zbQ(;8bFY6tSlq{OB6K_Y+Txp&XCo&f3~MCt ztir#dZp0L%$ZIDz#@8NcV+Ubd%$;mf2ka-1bUo@$boIs3S>zJ{S#(XF-ZC!UbIIiR z@T0q8)>C_9cGHk}!P(PnJ}y)Z!4~?&51xvj>^l^HclnH%0+)Af;}{N}wX6O(zVY?3 z8$%m1Na^C;dYDGc9Ts=2Z;w~(=t$MX>rZdl8{cV#DK!rTMuk-L`thX!q`&UM8S&i} zyW^90x5hcM#>FLgshmy0VCd03c%Xi=a$CIa^3$Sa;;})l1FjJ;Z4_R?3#N~Z&;MI% z)PY=!fJ1fJhXgWZleE1VuOS=V=sql0o$A=>ZQj|W&{H`fM>ES zqp(AtH*<7+>O1QL=$-Igr@F`~-1W3d3?@{OVHO1ue;5lHm?_irL~3zG zdq+YuuYuW5$xoU24(KPBM>5p(l?@O_l?_vZ_^3(-6)AQ~y-oPLd$Qsw(@kk^TUPR! zw1bFP4Js*I39@6y_Vj~`fF@rvAFunRO=NM%{9*XVtzX058DqG8FPcEyLj^JH|u)n-97w>-2tuD@ebELc1?&YWAg zghd9k#$U?X#a}JhHS^+( z3gRA5kiuHTeA)Re@y8qX#$WvFn)v0<-XHH;IxQA7*dBmuqaGZGNFr4p8}DtiQoDTDU*o87XPNOQBXIx4&(1o-i zxWvSmQIXMzW(f(ieWB+mFmg!K%AGgjE?X9 zU`u@N?dK=NL@+%>?|8xNcBKeuKCd60Xuqa;tFHgkV z{?|jeko)4M|Mh}+={e2uhren`J-1ZW`Fyr_`q%J;!nSU*UjRR+4zRIYT@|!z*Y0oJ?-UrlVEmF9EkcCx)s?g zYJCL(EtoMbmf_NU@3$Y1_u|2d&J_tie8cg%>lPxRiuIgpFP|5y+q&a3Ki(Xlxp7^@ zjG^&IFPRz3xwacP4@nibX#06EpFg~AZ~WB{TH~uX-ySiGX!gImD!pRM-+6xg0p7Pi z`sdXVpIcSDYu51ivtODSb092B*~g-_XZ|(PT{TR%Fn+E))j{>ry)G_qh+js>gQml#zIRktvBuh9Ok?yYQ0v=^Hirwc{x@W{s(w|LX68nyNq1+v*@1 z6;S_4P<3Px8I1l{yI|>yMxOn`s~=rIQE>nd@nhrT|Ie=?!eLv_QaTXptprxiZ63p91I8|G+POc@BpIFy znI*Ex`P%k&kwl_9_QJ^~;j)~Bx;BavbVa=5rNq`fUF7`gj?-rr9H(qYhe0cge`cu} ziy{16MTk2CdWQDwqfJ6t>`Tiej(>mvEjk>$w{;JB3E;|OG5RNsA3?r{qy5i{C-_s{ zcO4wt_mGLdjiUfrTbYUzVj8aB{T6| z?JSUP-AlrG)MEQI5;fGZKU+~E$RHnFwK~4|!)4Kg;cs}0i;?1yXUzEBoM}pJv!-g- zxQMBz78a2SFf<<|FmaT5>iOZfzIx`Pci!3#j`xG(hw%*e;_OnBR-*KtY)^lJ4zZ*7 zDf^w2=MR#cdEYn!M7b_J1S6tvJQ)S0R)MNmEJE?kL4}=y)Ung%{c1<2bYaO8#mrKV zURIED`KFV6jvyL!5#0LOiiU8xf^I!Il$`}8=>^jhR$T;CY422DZ=#<6EC~!pPfV)qbEheYEaqn8@g1V_{4Kck)XK2kYn=Jbo@_K?v2Q=vyHL8&N^06`N`Y zstEhyUG=G^4cy?1V{-1Et7yO*r>Hl~1S|H@bX3l%gkyriJfDc=5U&}GsS0Xx4&BUV z`8Oel$s&zK8#iuBzO@pqJm49oS(}c^o_@b(86azcQWjJ)zvcyV(iXxJ4;dHTcc30< zr#uM9oV^~IU?7{hubc9GlW6jehVi z4+Lh{rH)%qne)I}cK~P3Z9Yv*Zpv6Q3`uNC7;(|4dz}ZJoqLMGmPk%t%5@mKebQ)U z23o?W)ZeV1C(B~>`8_E{@iv^_5{74Qm=MiJ-3m}-LF`M(<9CTliZ-+1L5zNV^k$wh zEl>LEi&jti*A7*6>xA{}^~vgZJ?~ZO939~^n>txLWgnjH*=M#^Tq)n5pH-F0cOCs4 z@LyHcdhV}f`_??#)-#_g>OJ#%d8K?-9i_U>^1h#CofCal*E_au1^!hPp85Q#jlIBX z`oVuD>eGfXMU+V#^}gy@G9xKynftEH->e5sd)k9xJ=VlPV0T@*^kJmExhV$nlI_oZ z{Ml1u$tX^JN|*{$%HP$7frfwjo-6J&SNc;#5%89k=}(3kNU8SB7rXMRs5L{QUIz^_ zskfd%xPfOsc8o-(La0mGsO5HSnWtJe$D+9{`K%qQF22l(`$hTh34w}zk%Lb{0l!rD zz5e)yEqTPcseZe#am}Hu#-eGEQUtWwPwof}eKAM^aaloWqGZyp5eL2Ry5K@`D?f4P zt>9Z4{R24f%Uy@5m?$y87QQh(&1s_buW=Dd`d~ zAQqFa{BYUw_|c=Q@f1P?^+VI4q(WzCmiCF!C9dkbf?qOnH6fFjOHfLiTxoS}GnKD)Ni8@iZXJYJ-2Y+*7@u)_ ziJmeO_T@pgK*=^-wDjZ!H6S$|cLN{mrDfrm0?rTMKlV!~L?~WM`X~ve%uD7orDU;E zv8SI9Z6h!hgC@aHswhDq=mAQ$Qx3pvGJOanf4k0M;%STLF)C@?z+)Oz)rg#K(-NfUdSK>++X^4l2JGkIY zY*CMvqEkr~%rv|bfL<^UBK9P?F*uoYW9RAJM8;0?1WYqE;0<&C{k4-Q1BubG5xacs2;NIl>`10H!D{$ z#1@%%E?OcfJpab?MaOeij)!KMctyOc=bm;=Pd|&Y9D8B%_l+Aia)QL9B&tX6TxL@w zt1P5~KXfY_8);~aZe_{ zbB7@UPpANAK$yRBt<=F-Jh)U}xMEPsbuejgAqKTyTZIqsqqmpn+fkT{+d z%5m*Dq_%UaogP|kU>7BIRJm~Jnv9x?ftE@dRWO%9Br>zFs>+?Y^t{+HX>2@t=S}@J zBS-d+B4&n=uYs-kg2yfUsAU6?DhURG&|mYK*Sux`6%b1`l?9xE%C5(V^iG6?;1PQ| zoHHawhiw!t6oa`Xu&~a(k4Q^xe+-pxC6CZl@Suv0Jypmy@`dgm6rVG-KZP*jj z*o@~PNI!LUYGGO4%_n3-8{e+XOu+ZlE)~5EVW|_ zwM_$pFn<=zwGZ8$UF>J!k`pNaW8tN0X=yQYOx~*wzAOm_ z+)0F>yICX_zvsouI!u1o<529?N7Vx1Rn3$Vo<&$At47j*iP=$!L2sE2dDu?bxb9{X z|K(9;T$SJ?8YkUdh(B#{;&n6(yugmr+sc?u*qrx#)3<*7biAK^?XP1`%&V_kl(AoO z>DH}#<7@YBj93531M!p35uVQec8B-} zuU&+SUD&cGYO8Fc`m>nFVpCXGS4YMmPHUc)>v$VCZc3X)72l%*&AO`kpHc%UlMCZW zA$MM??Iiz((1s#?RONPY=#M6HL6l7#8QLS<&uk6{d3gl zuhh%cO(?Y=zlSO57M6m|W~tGoH$&u;KnA&i%s$v#{x9s6!p&R@ zVif=RHf|Em;2a&{Q>1b-#EAT~$|;tdG~46Axz(y~HOm3-#NOBu8FDr?~arpY|i+_$Q4z0X=e4QkevOYJ_z4B2%>*31LW8`>!Tz%g37*-W}e=)mDm$5zjR#NvqiWIowj48>%g?$qBGrOJh zQ+-*umHn%JZ+T5-$R?cJJf~2za`p4o&z$JHwIzb>tfkB%VYup<1Y(9tBd>RE-@!SV z?J;rc)I15z4oWB^i7e?MWF|L<5$HQ^JUNxOZp*V_24Nc?=B!UQ#2sKQ@=!PDdCnjo zIKjP7tr%)A{WnlF`i;hiXw0Nkh@FbzUrLx98c);^m(yPwJN_PMh403PIUprUv3sph zspL+W^h_%1RWFDSkRY4lVF9MDCpY|Q%UX6X-pQW(J%st^ zE_M4M0*wM31%cmB?yoynZI5e7ThxroQxbl4zf0(;8Xdq5 z>)OR3#v&mN=UwMdA00n>Y9D7`(m#rXV(9)Y4{wf*>`*<#Geg-Tu;{eO@d5}+1SsF* zR);%~QY-1lLB?mUw|Q)bcoB@nO=Y)`L1y{7-AFi)jrFuI+_EwwvtP`{yJiv&mPnQ_ zewIJlDk7|>N4rYDX(KrRxF(aBH!-iOP>o-H}u17bpHc6wdvT zYi7msPM;i8CXJ4<7@D`i>0bS%hvSR)Y>0E`PhmsVv042S0K7sS{-54>c3knvW${n< zZq0u|iljHs9~&=SIDxIqlLit&y!?Wh@hIt)ZoFf4{1u7rKJ?N#@me^&eV164uWyTM z|7k@m8aXIF{N{7Wb2cf11HW?1s<{4ptucSn%J}fFEzNy85_*vL>`N6bqA z_2u!V8&>2_$csq(v~@>&yp1G$FP=9l{wKsgY25JGj70x;GHIGqd-A9uvH1@#i`yUF z9B=&Uig@MhQSt6;&Lr*9U@~zQQu;*wE&E-53L4>~t#KGaP}MT*%9D>RUQd<^;N4^8 z!sdhtlak4Gvp>cIy$<0x+Rui#+{=&F(u2LSc=35f)=TnHbhLY%JkEiN?FqzCero#k z2pez=er7lFh5V_|2GvmiDi{6XcFdY}>(-U4{FPe+A4xD0gX))qO0O5cl^(rxGBf)d zGDD{%D%BcaX2$i@^{MCYqCRUdVjB(R%eiMSPbKW%9wpN8=^prUAH3Hsm$2n{38{>} zvausRhF**1$<=&I-p@b2jB+L_#p8ecg1B}0mbiK4j@Y=hJ-+bZHq?m?5wl0c*RGx$ zuP}!gAsA<&&fLkK_UP!1X&~0Ts$(Tqk|;1XcgGuleF6LKXB3TtM6bB?w7CBM9dX}= zeX*YGopaddE&>Pnyk5CzVtnAbB`nI7(?B>mD%^X|nHV3vi5$w0Y=U4;2Vwf-4$`m! zytoKX?%w%Qy(?aH^sl2t^vCL52jc3#d8qJ|Iac=dn`hwHE@+AmV6UknZf4ixT~E;O z(e?2w&!3Zd!hHON&d{RGUDU$E8PanhHh+?CWJ7MCOXkCK{LfVD=Fe zZ&0vKDH*uO-4FAa$X%Sbsx;!6g^SLPp+qk~zG^uKDcu#PpK*3vece0armudw-z@^8 zvBz~wpQtcC=)LBs(f^?jeaJ&$6W)~vJiZJn_qdDVihEfk5>`xd^3nswWSWmG2?L~T zAmvSl#H3A=)e^bYMOC}>j)?$L2P!@sx?>T~rwe#W+Zf}jVfB)8)J#$#RX#V)P=G^AA6JwPL=4SRD>{s`VD_B3xiqo$&_+&+ zK$48+?4rz%w=Z^XT$Kj@AaHmRQS=WkyFc!{FIW1*1C{o5b{+#%!~18=ngw1Sy?m6l z9qqVDFqAUjLcbfxYK9LV;uD#dEa#REdcLKT=H#cXLZfm3XWp>>RIjYeHLV&W1azNr z*fIlzL(-zp0?m{-*4Nk8i^TeA%6Ccr{mQ>y7QcMn`1s;WX0wN63jr`kVOmi>42xtvy=%*l#(x^uw*d zCJJ}o{PCrHr+pksm)cJdiIh3qnB$R1BEe{)i{HQIEV8{c$EMA@{B0bNG@Xk@08x$>_z%6B*Q)kVb|_mF&0&6GzPpUCy(Jk*WnP+ zhSv45doL07qsGP|_E4ik%=pfK+d0E# zT+_^W(TkoR-~9BWbW=+v-O71B43RE46M6#;^d3A_%uKnavCT z^aQ+QzSzY@F(T~`T2N9bIYd5Tl+s2!1tL(Y6bqD)754?AQmPI_u?un^)j6LL(4~D- z>C3Zz=ux}l$z7-vb@6J}9Im=(PO1;HNt4v(qRGi7tTNK4H}8!$#{kCi`>{g|sBijIMOqaB9@-SS}>>a`Bu&477YSy^8`jXS)!*4o2 zmi^|1aSnObZdkE1+DIT`N#+T09e~(Uli*tUzO3*Ze{@TGu8=t*bT6B;yMr`Ie&4fq z4>$%^fm7?(ttB_!&h(BcWwdjKlNPqO_Yk?e_eUr8$iDUtJlx<^9c}eOIDK_7a?E6> zDP}J^C(b*6X>PlxOL%}?f~WfwiN)`nWY&+F;&)3@|A2%Mz)qfGsB|lPwub94!}(95 z(M#q&{@iCkU5)&HM1>2PH4=ba1?kfd&|R7J^@dUx6D*-5kwydgaFsT0Hmmnp-tBK) z(SupXDY-Bhg5E%yR*O2PRc)&7Hj zPZknVpk7Ok-z6OXpm%KRzMi-h5mAO{b9)tTADEJdxSAvZQ^)z^m){o&N`l->o+mDRdPo)tB$z z8GrK4RS2=(IE^vgj$8YK za8g+mt;1%l(d+gcg=P~8UWeWBNbBDC%&nW^t3QAJmF-1Dc=0~+P8JAWEkH#f%17LN<_eOc&P!Z?3a{jpt3o&~y|19%tejxD5I zap%~-CD(t&#k1p+tf9Q~-_{mKS{N1t49+3T{@=gq3{oT^IVl&OHZk6@WMaJg(9fUiWlN3d)ucTK~&uzpU3U|=F2%^gh?ykn~k32 zk1P0-nwv?9HG+gHTcdfp>AMEwF5VvpaCz?|fO0SCrScpYB#R7O6Ty8lVpbPku`y#z zBHJnu-l`H1lOey_?WHJ|-`ipNQb1pP2<+kd#phh+ME_lG1%l$E~Bc zOe9b|r=d#Sf{1iKqhG^rr5h2)*rD;Gx}pxi&~_wpY4(A2ERq7BYdBuR?E24!aOL^-4>eDk?((uoI3It@Me#?k*q`~!bb2)56*FI(k12-f`6b?jQ$c`@_I=yRxIZ(KPwU@RWg}LQ5rJ4rM5`A_ELNncjRXN2m8rET1PBW zysD-_7D-r6tS?BzAK)mde6=c>e(|Ajl2d?dzSMdm^Dq$OjN|f`&1tR*bIIDr{wW75 zS2U5H|5^&|e4VQ1REXMt)umL^y_RssfiSFT zOtc&qKv7*UpQlZuz5Vyo7RR__`}TNz^;#qd-pE6wNWvv9e(mk*#tTQ*eTc)Hcb=9! zqop~$W$x5!%*9JQ=+LhcNvSghsRB#qH0AD0|21Rk1RNNZ<5%$LO_?&buoJ2}YG{l_ z)1*oz6J=O1sT2o&qT*r>$nDLnphVHvt?$cB`I(Y0W5KAwJ>^S=%_vd$?mz7w|9Kyg zlr~F>b$$;5K%N2Rr*EmJMTzNDivYIk+5gHXANl)aW2$bulpNMA>zChc_jnZ|-&fUs z`HXF*lr8&GRmXdDbD)&{_4D{r62(oAu4%A68y#1ii7&PB?yC(i&e8kg!=g2+lGW-{iYu42ei@f76u@{b`0E&wSi zYIu)9mlA>UqYol7BH7Fwhgd8WkQs;v{VGJ%%k_@sIfL9(vY6X8b4l^t`u0Iuv985y zr&8>C_P_G!Nc>%n>ABh{pD*i|&wBktrMms{nX+ElmcPq(%6sK!S?6T!TkmD(OpVXH ze`&mdvoS5F2#TzGviIiA6a1+jkGD_uy#19aWpLy`%s(<<2loE;-qox?;-CPTid%2nm~nYM4Zyy+&mpyW@zTZ8%y|$ zr;Lq6C95AY91j`NroJ&+@Q_WKIX{MuL=qp&UI+rUseacUEv>Ds`6;m^gUDY;Z5S_} za6e2&D;J>x_~gybQEbc^gqo#?EB*ECWigISua$2$yiCGKNdeXuK*KA9S4}-s+r|TN zJg1{ZYElYu%}r$^;T9XQCEN$6ajYlFiTdwU9PX?ssC@jBqsetGKMm331OJ!(kyxJI zx+^x|qOK)3^8^+bckS7ihqyL369`&+INAxEY~RJH$f{K^=pAi4)5tfDY~1*!3~hm% zLqt8`YEPFqu6tvk2=aPhRHF1K-kfk>0(2gLhbZ&VpmAzon%miNl8BK>zL8{789 zSC*}c;nQXiiOd!X2x9VrGl&b@6RWpvRBFcCV zxK_@oDB>u~LneyQ~^>Q|8wMycVpPm-u1adO)+@6mu) zx+rflshZ!IbR7WxcA>JtgwR9<%OxbTBrGKszlTGN-&wsq))4D70llPDrUl zph~YwaVembR2JJ8$K2cPJ0(o}$5$xZ1y$~0e;M|Z&siCJHu$CF_~Fc3dgPj#oeg`tqFFaQix*Qjj6-J}B&m$p-#&6oMdcQ}7~S=PPqUSlbeqiRivVXKtz{EcJyztkyE9QX(>t z-{~7|sv=o0w`uUjeir=|sKxsWIPtyW8TGpO;e!bWFgV-gcV*PHQ83qo%n_{eU*hK^FQBW24kC;qF%ew;32f)Tg8iml6o9@0#^%03@LXUcp0p-WlV%xAiiNbnLt?FYZp%)UY&zU$* zwDi7_y5{M%NMr@m&=!****h+rDg>uQ?tzGgveU1RNCab{Y}0r+;pj-+_MNVH+7l5( zVws8kk=dw<==~8UzC$mcSs{IgYO-T+yd&YPwxyv9pmGc{9<$b~=IW938KWg6HVHvE z_&#^h7EpKIiY?^UNo~M!RmSVP)hxJG;qm_Ji7!2QY#Z7a@Iw*l)@OHB3>_gb}j9tgrGfIq9@ikzw)(V@@1ld@>)$P>aEy z1n0c)?k)lOKcfFKe{$vu-Ja^K02V=`*$ z6%(5TSK*ZI?1QZXOt_u3Ku(mV^X2#C?mGl^gTa|8(w4$yCtA2{Lm zXK<~4cpMMBUw?+FN9CHvUgdfcW07kgA-9!%S4!{*T+y(g`Xm|=#(1~`oK2F%$3&%9 zkiPitdWqgHGB!DVvDE>IBh#VnR0oM|G8clq5;n%Ci4@80SxgZ59Ah#SekWW(TtkYC zn$R<3yD23A3a?GXO{QVH@Vb5o#QuOf(Z@J-&d@5K08s?zo>HZcmC{r(C0rKvEWZ8_ zh%BKUW~^llp-9nBoxy#=k?VbE9b8L>z`TpR&a;xGP>*R7*b7UUk<8PRrBixBP~v<& zQ6u(VB&K5pPE}yw8L3Kc_hXr&xD)B(o|k$|0k7+swTPefti|k8`q1}!@J6Ym92{Iv zUNabF7j9~Kxr8gMC3s5*(aQOy@~0IqnPZHu?UZ<}yV=PRH7rU8k#s0rIaL7aJAdwM^o;^R0DF{%i&J*O z_WhER!Gt)0B9f^?i;3o4Opqeiz`e2^gZ6Yc+O`NLQRqQY?QpM!+{@%}syEJDA~Zmh z@RA!+&k%F%G!v?;O4Ji#?mJ};W+3qhYX$Kj#v@D)(*M-KnRx4nG!kd^1Qpy`B;&mx zYce0Zz;D%BiO_bXf@JUm~(^5{1Yvp^0D?@A)ke9C*o;%A(DZ42y+Lzo*)z zdc*?~X!eI?Ir~a%Qoh3@B4jWEvydJIbM(EbVK7d|rLAV$&WH7~pQ$4tj@#9(^cj4ZG zHEY)Rtd))yh|zTz2Q850j2i9T==Y6eCUl|>fuNQH5JUqArucP_jN)4^E-hOLH+NOi&G2YAI0g@`3;#!XD1SY{USqCONe5 zp#S#mFn!hCE)u9h)S{C0@GglbNgTx( zi>(^@4j=a!`fiI7SoR--J0-6Y1^D}Ji}yr$`zk@pcn;$6Qgu~=$nj-(gV?*Tji|lq z*u8gv`Ey^tYPx3+Id>xnhq3sKl12$-;HKj+J(J^5+R;hiZKx0SH-D9M;%`ThDz>Jk zi{rH^?zk+~GJjJT=25exVEM%j|GM+c17TSJYR=!T!<40`uba3?v&IxaanRiiO2Qb- zr0e;S^C>|Z3AL^P>4rimBm+p@xgHxt0&?qVat0<@pes>q>wqc{Uxt_um!65>Cbdxi zck%>;|FlOWRE=i2my@7WGdRz^6mmSd$q~lsqyZNd5~Kvk4FHEgU`9xT4oseQ0+K~> zOF&nhlBI5GI70@2&jS%_}TZ8q+_C)wyuK zB>I8?i>#H|4h?xtc*$==A$L3^ zVH{SaQk?*~$O5C9CU6l~WP@RQ0c{LMr8-RbdSmX`BR?<3z7k62A%P#JzY?bHALJ-& z4NBV_HG1TL)DbBp4xJJOr!5R)31F~X53dfLWDK+kUd!z~8Ea6V9IilIIi3y*k)M|* zmlF|_X=JT}fjCJiMd@2*!V(edw7(cnPCUu%RNK<)M<4W(c~2N--nSCzfM=?-P9uy+ zWCWuVA;GZhr+x8R@xbSuU#}&S(U(&7HjXK~?tR#hNGSuA;6&zr(9z3dd zNWEU-(UT_k^qf!TB2@wFp_XewNLxO@mWtqRc*At_O(xG z%RQ0b`9G*#=~y5-C5>r=l?2w8kUZK#-B9VR6zP;X0cW4x!+w6FMzktz&psW7Sqd`= z-v4~YzWI<6$$klFrgWfGl3KP*y<*q%rlJ&zW%1qpFtsFWu7Nw(?AfzNQ2D*K zzJFNVp+lW9VfLaSqo&PzC$8B+4oWWD4I*lHFpj80eQJI1q4?3i-W*#tZe@Qu147jq zgvv95PL3WkJXYTJ5Q!C56Ge)&!HDbZ)&qiilLj4w1pp&4z~n%x8J)(jfrQ!*av=dA z5Jgg@h)AMZBXH!3auPq~sL6dX3{zD@kLd^bNk*9JgLO>JLvvZzLqr8+N5}r;RH|}L zXi7lpI^l&BP^{YrIit^Nz!oZr6QbSHi_~*r*Y->goNnP0s|@!1l2^1C-hW1mkrgM^G# ziRKuDr(;hT*mvzGek&22AIEQzi8vqJEXGB%5=W`FWi8%e9bv~5(NhY4Bv9Wkk)#yh zrUa&gMPgC)S2}ef4YYUF8eFt=-hFQ)%+fVMnS+iO?PC*R*nc%0dX)dAB=?>4-7)Yo z7(0EzJb<{4JbK?xJ{fIWuqzt+M>jV1(KgFCb^Y|Ck2T5u+itrJFxSM7e)Oa4x+G^& zlBD=4Jp*1W1JV3$;e{+^G%y%e_FW`m(28S5mOxlVLV=t9^;QrOBaem0PCC}Xe)z5f zob7@1*#mKnoI5^-aP+{pzVfX&fFzhOjznurLN5lKX>n|Be`h<0O@3YOOO$4B7x}em z^i&Ca_eUsN4+2E(i7wjiL{Dws*AC!FwWID2QhR?ewuVX0l@LCoI(G!5-o2|WxtSu| zHdWCiOg&I0^jacBL4dY}MC-oLyHPs}sDG3}^#Ib6y zD?5gOpf05LLdd0U)xi7xu9}y~Eei6ylLlzgc2PCR>KXQB{t6BL;}iK^U##@gTj1{>3qVV^ zGL6<$#83?et@l}98(DkkP)F_Tb1rC@G<*I#LAF71F_Fyh1Kp^5+065uuYE5ju)1oP zLnrA%bA3fo$PDN=SC`c{?@r7ks8&6FJu#JZpsFeElB>b3X}0$Ey@*&QvH?O-)OrrP zNUG|vo%bkShY>3zP~aKqGSr(R;_lwJm%S!q5_vQxouHinK_n5ddbN}a2Ux2SfD*fq zQ0zM?N&*p2XB2X$Oe3_K&s%Lc)mp!rJEwNoDKBxE!1Pw1{wiw|~VI`rs9wGwjIs+fRSno)Xjw znTXzcyi*tnE63qHr8A@gL)%i?`Ochw%*v~txa_iuQrrygQ!95kpG_p)h{MXUa8+qSvf(uZ{6XE97iouxuW zrns?>=_NzL13drjsquw)#tsmEH!Ho-bPD0alEm4$+nrll)$s$5RnCPl! zt1J>ydr88}{}`jlDCd>4f@#@?9xj7a3lfs6D=iE4P!*;`bm1?NI1bx$x@AKCmOIPD z(%s5uO5D6gwIm{mQty&p$U^YEzbMl0_J@%u4CYuUIXU=Q^|BmlH%z$Tdlh=(4fQJj*dp(g(M zOaBy0FE}?AoOLdU&nh}Sb}iUa`IFa5^*3ZB%bz` z6CsC|Sqw&BmIG>Nid=b5Ny@~F01})oYTvE;DxPHo0rzZI&gZ*Eppz>_JWy8zvh7q; zK-59BD^eeHbsa>=&>`;I2fy2faFPM|tZs4b5Y?@OH)Ho5_D6lHaR2@vdXK4laViyDL*ytEm#b9}eRt=dyaM2Slc1A;k(eF`jVi5E-F zBqP2Y!lR_lu97Fd;7Zxj~R}nKTIR0Tv8R+Ig?V8x7eYSgw%H-S_$L}MP%Qn zx~*r_V=%ObTn4c}iJ1&qNs4pCI_sO5P|BRPq^%?}ae@i>I26 zIC2(g&_T&5)Y&wowH073+$cg0;BEO#@qU|O5V&28KFy*uiNVqR#NIfvh_ll{m|g9= z6BuY}xUSJ*nb1K1_#k08PMpNj3j%d92_jZ@4uE$feKZ19`}Vf)E!q&Fuv7YaQJau% z5~6D}_F0>#0YLF++F^=ybC2~w{D71WU+8 zRmY&@@mY~moa9F~rR0=}7?dgj7vonI<5{jHano)Q9j;2K%ohTBUeKQ74*d^oVcV!*M z0i|2nd&ezY#`VxeS!5Mi%8R8+R$kXPEr6t%j>DiTgVBYoOIBTS2!oV+Z)3fs0b^eP z9A-Vlk_erD{l-uLVo?Aj*Sqm>%_hfH^W3=^IN3D96Ln>%TNb8WXAW}ZlqCPVO;J-8afGz`9>D7)W=P5 zErJQu;k++ZFRl;4$TYl0f4?GM&g`PBDxE5Vl0$XHmGWAp3jfKq8&L5QndrX`hSK9C z;Y(N|g~_!I+LS1|Aq3%Qq_=&SSW1p9!Sx?P{bBOKWeP|K1K@b8tmki|rnT8@Lrj*( zik$W(nOhZ6<;Fa!smf{0A7Qb!Jg-!^NYp-KyMEaBL76=gsl+whb=gOscQ3t!?93{? zP*T$+E#XP12VrI@k?4zU%DfzZ!8mx1IwP@1)l!rIGB1h3AWC1QL%{PUeV5)?pY2ig z0x5-&b6!Y$!e3Ck68tcEhk1$GIWF*=rmsPz{2dNI)h>o8nOWOd=P zqIuEc(a@NFPFb=8HJ4p>8P|C)MK77T$wm;BOQ{*zz#0q#QWZ-#B^L!s4V~9h<6t_- z2W6*^Epnp*U=GAdcQA_o#b+*v$xRb!6LHAm;b;(XU*|r03)e@zk_(#%K^@iO4|Fr9 zo~oJy(#ZK;|4|f+SR#l=yvc=}Z6`_ZSmTf)V!4A!5m?D}0bC+3fb=tmbjZFcLN@CqwB#o+z{c%mkG^uh)xqs^6AdFkL70(*?B3C~QfM&D( zG@|*f^f_>#;FOL*^~O)%pX*&9r+pRSR9EbWs)sPw>m(5?tsIv#?6c(>haA{2A>r;6 zOE}_127pp8)yC|TYa@kA$gtfIeheMR)l znKQ?`H4=*jz+`Qyu^WS4(zAg^7A?^sqIKE5(YAISlZV(A1CA>`>`Su>T=$Cr6Ts1i>2#|o}x(vgT>4WI6$ZNam^m=uaCf4w` zu(NG1h(t0g|H)mApOYw6lkJD&^tVK5ps0=!)f|@q8mXHLcyuC>o%hK&ijWz-o`tIC z^BICfTc)B?O-%I;m1u45^P|M!3wYPNL6zR`Y~HL$V+A{S#xu9w6wI;R4=hm$LTm~^p_Nr4|}Jmkn`JFlOBZr z2Go;!)DbzB;ov=OyW-K??ub3xcgGP7_`@JZN)Ml+`N~J}CN2RB|0dTA4&xa?uG~>G zrbd^z0HVu5R9WP{b+~`|PjKTLW_w!d5Kxc-j?>bDe%XJvDFhr=(v0dGELUjTd`ck;yJI99iO3B8Z)-W4t7i5wEB#Fm0G3O{5 z0rPMG8@Lh8LWhaOD*Wx43ykzSC9n*}aVud=wWO*A8%dntOA@tqtT-Zp%OH}G0%Kq8 zSdvN5zWiV8FC=VIOn<8HoUkW6C}L{)J;#+-`BU03^u0ef`&Uj;F7Kxy)Z0sbTdf${ zc2MrK??oCczx!^^Jl_%%$Bu|L)F(x?03AXPMMS_((ln5hK``C~kk5L`)jU#)PHCAQ zhd}DOUN~%~8nutb!k=o5iKo>+<(!5|sQQSoatmv^UUHa*wRJq3U4#>nhA|;>F@f)j zuH3eqVD(m=7fK>syCO|;W8Atus8=GS9BvHBu0>MSLb<7ZrZX9v=4y9oXGkn^GL3$v z)hL*X-au6X7g<#sheOaJoJO#c&;?jIeS<*Znu?5ESR@iLT;MZuT4U8n-t0T$O$7Ho zZ8_H5ivwaLT!4=Vm1+oMl9TJE7l8|%A5{qg6J`>rW0HXL5MJg-m%7Y|N0MmM8^}JF zK92uO29tA$J;>O#6U779aP$I-T`~fuDd$UuDh!iwm?_mt`>vX;CsRUG5@`=g^mXJN zb9-?T3n0-RQw_5niFgd|WeG>dlWTi0P)|{iIAnyDVIIrJTu3DPo@CsrsDhY^Nh}p` zCou_A=b$W=GmxGUt*j06^{;<@fM`mBVGKp8*s_7jXA)BXFh~-!MU`hHr&@KRsy%eu zZSnM)O)-@9l!$pvWnMnyD!W`^Agl#k?W=x(KLvSb@BCe{N z@R*_0)jjGY?#46a#EV3FNfhl)h(_Ul>?a)&+9j$po=D{c9waE##0PRjjZ_yvwN*Sb zBo{#m(Q%ShX*$|D+7G1GO)QdX(5oWIROEgJ2fF@~>W>o-p$-Dtx^5+?Tx)@I$stuE z3~krG>E)mOmT73XiX=+LQg7GDuRT&Av9oDkwT~QgBaRAnaVJ><&=!#Zon#5eSUB7A znN(Sra0vhm$;njuw0E~BVknUrO15G2wUGfX!b*&`kv13=goj1sF?8PXh;%L%7e#fj zuq{L`$HqjU3D~yYE|?2*BlEDL1gtu#(?x=_xHcpadd#;B)OTp3q|F9Ali|>(f~kWt zjt}^CLC|Kul!&!oJ!Q;iL@DthJz~^L!k|s1hx_?;3`xkU(~c|Ef7bXUIPpuI5Ar1ogw_8uXHAWuooFVwZ==!#w^JKdOk%8?{?e{&1m=p5SXqcfvC!OL$E2!~w%14|76 zPF2vsQCXtys6;FCo3|Ck%$LI39ha8tufN`VdB2n}UaaAt_iH2=CTYOv$LVHQYU2MR z>`#|1yOIOHbKe{DJO_Zl6p2JmOp-}jt5mX5tAvtFUu2S*KGi$$E#fIu&(Pf;TGl3$ zNu`nsHL*#Siex6mB$)|fNKAp4=Q-}}|Ihb5kw{Wzy@4C&oIS0zeEICYe6`r-Z_}1~ zxBvh^07*naRQ|tzv|Rh;C(Ge>-;x4j(hdh?UW*@|dTn{(cW4)Y0YSyAfsV)KXq*!tJ;(4#wNo%(gbB-&jHa5BKl; z##W)`#P0^cBZ(pgvuyxvK$5=_5rEt*q8!J=dFa{H1CvD^L6`u~dGH`^H_n6l0Fe%M z4Wl4k0Ne6nk@ayTgh*mT)J6L8ZaTKY=_c3&021W1Vb7>6^|40>fgz`fg+P{2<9NpU zvRYeIKlyIj*y_HANnGnfI5GVd{_ zodf;uI>HnbG;Z7*^RWPsZJ;5H0+LRj8@09=wZc z3Q!F#*sI~jLE;4W#?6g{u)KJdaHm$2e(*_O16@*aP4(xzu!iYT8pcjMUhq+$^rgmU z9OJehLSN&9fo8@!s$tTNy+TTAU*GLxx}8^c+Uj0z<-1p}0`v0iQn7o6zp0&TuL#DC zd&evw>-*f$XE(1K&E#WlbD&(uaVfOz1}?{uG3U-N?|kEf}*t1yQz94N^c(GoRo8u1*}bo30=Kpt1B2X8eNuEnpp`l+q0|_+8vEEP-HW))iy8|Y z+=m*^8n|7hNe|B$z;boxClO~(Hq2%tIaj7alfi7>yztg?Z~5b`ep8gp;O_rL^5t@6 z6(+BYekW`mW5=bDFdu#Nkv=$fH~YinqYRN%oR4dnm^yc^Uzei#A8wyqzI(qNtB#~I zfAZ0?b>r@`{mas2PDTtDGxW}!D6p4j=UO^)d&Gb8?xnW-J{yue%8qGr6OWG~f)lA~ z&nhndxNPN@>EDNn_#X>6N87gUM(SX-cp`-3%c+nMP)UtrVHEBN;hsiVIH!m%#D@qx zP>@gH>(Q;7L!j=#(Iy$sL^jZwjJ`dsPX{7S@7`oN&k}>~H)-RF?s@t*!r4eR$cAW# zK$5B}*I%6z`oori7h~rH!y~DRoC>oiXh_GiHP6(aKpPUq6l%xVxYjr78YV$fxklA7 zw$=Dv5qvm)^Me_@lr~{>z3|BvqNT1igT3QGa3-;^I*F#yJAqeu`>QiB%UuY zGH;mZlXeRu0VnWS-@ruwk7s*ga0rij%QmEiAl8k>(QTt@&wVmJa!B#Mj#LXGWBo7~ z$4RF5bIhkgei01<`g_MK2}7L!(|`I;zkLH7a_nxMh&5*P|K6bs%YS^~2g}X$?MG!7 zpUB7lMy}!gqR=(IFOIPP`Pa+tFF#)nlt8)jW`-uDs-oe(yck8s+u)v`zri*uzMfeEal%Cn*dLTZuZ9*2UL?` z91xccp{5~qg-EB*j_TFqgA?MpRe|XApC2nwSYOx;Ls1p7pEWR^58edHI3b zp;EImsg2swE(edS4#a>tQBe`4L%av0^A7MEf+QikXAFEWPc_sZ^EcTDz0-X(j*Utt znbvru_|J<6;;a2~Wwl}E^oC%1{@0~qza?FGq_&RM(VWWlvTY0wom$RT)#UlMY~7L< za|s_%W2%WvPA=K{%fUC!F1sQ4P6K~>FVRLnvY{BhIN>gvBxHd!2o0K2v71Fmp=?dEW`bFR@PrE!n0rj`5+NkQL}1v z&ihUhK-wYZVGy|dDh0v6ArBLyvN=d)Y8y2f;m%mDYEGZ! zB=UYz*uhp5yW-JvKSCe|hOzjp5Bj*y>6&4&Q<|2%Lrw&$pL?E{k_B!xk5fDH0vFWY zOPbuQwsgT#mn&DUEd9;x39dP6V}8#MMt{dtGVlD>-g}yX6#&QDgmbI7$;&d5w{ss` z*1EsnRF$V!Z&kA_n{_RiDi&xd1`xvHO2)2#WWL3##(Zy4m*YxRY6rHX44 z4y;l*0*qMv=DaZndq?$_rU*tITy{4`ztk8e37$$P9qirQj8aAD?f`E>O%6R5=Qdm7835+H``RJ8$$7R{S&jY$X{6{q)(ZAC>%t%H2WP6WTkhdbJTUW^9;Oev?v!lvMQ4?jl@A`Pi%?14>; z#PcID!!mY<^Q4BDlO++P-SN_pwCP@%0Mt-w6TRQFo5F_AcPf|{QIR!bDuS$-k?J?p zFkVU+<~vx}5Xsn9TWm#ibtSi{mJyuUK!Ex~9VDs8&WX7mtIF!`QS;HVi~6*cip+T- zkB$`L>R*dXhHH(9gr#a>R)XDZJW|t~yRX63*OdvF)6HSq@wBO3DgGM?!$aop|0)hM zC$C(&;`t$-x88co9x+2%!GDhHrNZ2OVdvV6@S?9TLgE*3yE_F9_h(cc%V4KtgTQV` zO3h$z?3(z1{&ETv6xD7}DBQ6<24fzSkmqGmVyk;%l>>Bz`CdHC&^*xg25rT+bs$&n ziKIaLgdA&2g!g}WeR=)8*Oy=9X?v_xQa%j804VAh_wTcIu@c3W-aUvMLXLRu9t0!p z10wE5AP^O2g6sl)AOXP(0)326 zghxt1B1GxojmL;Y(lCig7W4QZNPT*oEBHm**qzGOpw>PJX*eOMSft3TCJkAPL6l#` z8Y-A}4uoV>PK2iICou)w8Pez{$@nm$UDM~;g~6tGU^YAL6>6L#6=Qx>-js_bS*lQW zYHc#WkHi4Z+w5r7a1K6Z2c?$v zEH&^^bIHkYtiDpwNIohZ2};RD)W%6Y>m!h^DK#V|f&oL4Xw>0})38GW;(9c#CwK1L z`O2^9>HF`$zws9D-7?)?FYcY$ieUWh>*nq37&Au#?Yng1#Qv}D-{1G&y!Q`J{PiS-q%JtHm!wx zh!v+a`q8r!)4V`b6^MoVj;d9ET$f8`vLG0Qqf0}Kv1xh+p_n9G5O=1kAw1%A=iu{?Aamm-PIVS&O9hvdAot^PemIbmln}X z1i*++ry|N{FGHM4H9gOfaQDuQsoK7;0MzAgUR%zeeX;!P-P*5OC3Q?HMx;0sDwm7o zGYO;LH+CG<BdzbFq9OF2 zhwy^H0=_t>>$o}3-^5*d7BjNV$kf3OHug>t_fW5(P7h&`Lf$1vtlpO;;M7t~h)Ts^ zzuPXxD^qE#wWEE^2=PxAM$bWBg-IamPKhEI54Z8CWnc_uwF99sDiV?%C2a>RNPbe~ zaV~zu0iLS=xZg4l%*@}z#tXJ!(V%B8J#RcF>`B@6q@=m^JBy}&eRg{|vgcM_P9&02 zpocK1WS1{r-um>@PnRoKu5{OC61ShV&}z#h zXK1HRy$q1g8jR^Ycs$i5)o6d4Awft3IdbY)!OryL*7c9h*kp1P-~_wrwx!%H_j3+Z zfuJIP8KaeAdXy0;-|LIN`NeYg(=V1gUw^Y)`~35EqxyPzceBa`?(7D8{Tkc^wQ2}CS7<$AZ#v8 z_uju}c`LPTP3O3m-NyYn(ksAA3nw8T6hDHja>J+tCxRJ-LJUW;wN4((ixyH$HO%h6 zaOQMT=DcO~l?2c~oObkb>TQVVf_BEH38s)|wa;YYhRF2`f-ray1p>#FJ2CTw2@Dge z?+t2@n7&UsQJ2J%NHXo3so zGTz$mMbPrvRu$9CtQiZKfp={jI{75K*5b%jXux}a=Frf`OZIJ}-<#%$SmwqLKl~68 zZAHy~Z^wb7h(qmYeqj4AZhv&>$EV-^gX7yL_TRo)ET&*01X2lv=i+&PT&g(RY%8Jd zTChdNk$nL+F2kcH;P~M2{V7zj(^~H%A&i8+yN~b9<~KL5e_dH7h`lZfL!|d3(w7m| zqcUhee(+`7H~T5XvtP;+-0gPA93k8}TPz{TG(Px8rzC91rVVO`B+(m5R76Dun*d^5?{+b! zjjDs7Ot`ioF;5jI0`9Nx2a^PnLwW8d@EY<>45D@+8Z~Yu?$oNr)rrv`^lNqF=E3Wo zicYxqbZgon9^z+bDAY|N;Mm5Axo|^6*40ax?jQWkB@d)$!3eU8Dd``i7}Ud9s^Q6n-$?tRoHQUEStT$n8hMH-RN5FGQ-zURS9VG&HgcYnq; za0m+GTyr{Dn15s792n-A#3hZy)>5NiT>sUl|Lpe1fA#eE!L#+{!AAYssV*N-?*9De zKMy2Rm#m*PHUF;vY>V`N{PD-zc?R~SlF3fqm#1w1iRHxp();)QSJ^QC>A4^N?8)sX zhYc#FVNys=pFF)hFX54Xd8+D|&-0%*?K7a;R-kb}c3$pZZtr`#+}w$4TdWqE3aIT5XoZ=k^JhvfJhJ~-ahm{^ z#Jc^T|77{-d`q32!WPMbxxcEc0k;G66rX!ZLH0YiJch$ zryz!NxsKE8Q|80U@gQBuCwW&8CK*s$fla@l`ow6B7 zH?anUGRRST+NI9nvfdBT8O{2R0SHV|e^$o_%RGrvf2dN%r7zT6Y6+<}Oedn;AQ5K+ zLPEf#!g%C*o)W`THeRjT#YnV|FsNZ*fq=Vl`Z{COO6N%fo;iJa7z2U8Bo#Z?IA{d= z?D?64+65D88Y00k^xJpL3@o(mo*HOwR|z~4tFev4p*E?J-MA8Gt?P&WP^;^BXO<_Q z{j2|#4RbFWM#S`an!?N0^uN4(`SMOS>P~SOL<9>Qud534a%XGQi8 zeqJo0$xJ$&c<0Qrd#VAYHT2MObL++O%LwI9pFa$+oocO$1DU*=M7z{C z^59X@=Ts`+@iXN_-OTRDmAn691e1f{Pzi`c`zN1&Hj|Ir;eZg8kq)5#!?j#95hf64 z4bBscgh-IXL~=C)HcmXE-ut@Gm`Q~}=C1p+=nN8A<;lDCtmjFpZXIq5(dhT26YlAN z5Y$1EhyBheAb_c2=Zn_GP}B5N0Q2mTGh>5Lqn`I}ZE>wTaAk-OX>ro0#U3!Tnal36 z$q~l~=>^%vlC+HwAuU4D2lme(8RV)zkkxw-KX_0{sY4dJjk6>zfHWa-5T~^-Vms7v zupT!!?%#i4${h`kT-4$G^i%)M17g5n0NDI^hjZfysQ=(M6^nY16M}?7MASgVOh{F8 zLb8lwrFV=(uWeAmu-Hslk(x9uj%IT`KFxkn`EqYf|K{{+^uPMmgWoQKv00)lZJ+=~ zuIjQx&(?4Q+GJGJ&!#?+GTR}&cToGN1_%bg9gss%Qqm>BZ**RW z!}xaJxwGd7x!EItY|^M%bG>)q?A)uoXKTd1z+y;f7B(KF*jz-)OGCFlm;qa5&%J!C z>5IwMr?`t4gSnd|(k32};I=QCd^&qFXY36s9>RxE2XiE_5fPz=5et=$?cde_$ZZ}UT0?==8!3_6>pl8mXi-4-B)@n~o1Hq9@ z`T)j=W!@K2L;lm@3Tc1|keUyJxtPtQ>ok7-)Q|D()qmrm4vzg}p6k!X8;L;8DI!69 z#-`sRxqHrg%=K=uJN+S{R$FNe6<{!2%}<_~v5qyp-)rW$eEIUkV8mgrWUjDdw3VA6 z_^t+zDt}uae)!?MfR_xX6udmvbs@NuCqt+JuVYlK0~OacJKUQ0Z{1y<6@;Tl>fDP8 zM?b4z-;HNCm+L!~agEbmZ(vUv$dM5F(vx)C*Dozw-@Uxth;#kXAOGQU3U1yUWju!9`}7A63f+DIMJD-kw^Ebo%Zat?u->_^25 z?xun=ki||O6t4n1M1;WJy!7@=EF?DRmL@wO6SYO;AD6_LO_uji^%(V|j~CE{z>suo zgr0@yjziUCTNh_>_a2Vl=zVI09qYTD+b|!tTBta| z#0iA<9JSVxj`1!wIns&W0#@9X#2IrWFlgxJBG&4ieys!%wI@AT$@1L-m=Py0oR!J{>{lPVY9 zY#pXhubW-K@o$${qHVqR-g_>C+uSz<8&$u{u5Ti-4|g+$d+U+ZsCRPH-tR)fXE~bgm1a?j zf9~La_wSY)t=>GG{bRz6n4rWZrbGSH*C8YT`~DAqwA_rl-VF(^=ast^7+$nM|Jn6x z%kMt^?bM7aPV$6BaFCn*f{P>KQKwQxp2pp9?Lo}k-qa!zfYbn4lOrn>Qb9Jz#3c^7 z5yQcV36Xi?+0e_5fj=!gABg&P`!xAAtGmjRCVtkmvRU*uGWyw zuxoDMf~)H9sBYaWeFr@D9Z$s!MqH@4v14N_hqJv?XO&jvvDIOsxCnS7mX)Yi`*CX4L3B(2G4xD;8_B1i z_RnGSadGR%8AieXf?eYA`jOoz$z9_>=4 zy%TwiC$X_MsEt>-z}09`y=7ewLnZq=3&>phdn(zS{PsUm1v2{AQzVRtdt|0waV%#H z$Ab~ds0MZXS^l&!!YVL!=cVc_4J2YY*Ls-e*&5Fy7y=E4Jb3;>v7XPDU;V2;TMm5x z;^Yb8HU=_Bv%B|gCVI6Wid7`#zWM6Q+|vcMBHCsk4_Op?HsAgAo6GXO@8*oiW7EU4 zAg#A>K@;^P!8FlRR2@55O|gm2D;rCK5Yh*>>R&1vLKUr^BSMSpQUcNk(>L`qYU4OK*?J60jW*ikcK+3#wv=k z7mEeS z5-bF35g3j=_8tZjg9+;=FszMZNnyKT%OHTfB!l{5n4Cp<2on)f_t;Ybe+UZl!WGT~ z_L}xdTU_7vBKokCC-l+dY@p7c&4!lIfaoo?@M27b6N3{1k&F$j4ykKx&MuWq4;7i<+-}*B^s9J zpFVy(kXV6@;B4oc>EUEl7H)EO9mH~-J#(b?Wd;boNkO54Q71?UTy^3#^y)aI!H94}2yM8B z$80rXdGw^$@QR6_RO_J0CK0JohePB??UryX>2o;8fCEC0&fZ)h0D(%zyFO4$rXP(T zj3D&sDLN6d1vtnI#x`5!jXP5M3&#jJJb8M%ey#ajY!zEQ>aX#`3k+(z^MbzAyqQIF z5s{OGY(I&tG==l$&X2=jJ1s8P=XErlz2N@# z^?TQs!WGU;-2`@wRj38rD6 zZqVN(Y5x4(In6 z)Jcw;1hmrj`iB+#fyA-jID)kroPfX${LtzarH4*(E#RI28E z*iapxLhCUV{o<fpqzczpb;sCG-a#^h|D?WjBbPX-2DV_rVKU?BW^hTbX`DSn9qQa%iw-cs z(4fOCH|pm@99y&~m64bs;s4g<%a`?VjtJ5Bref>YZeq~>w@cYys<8Pe57kcU84_+DF1oT`%zr0wdS#>KvR95QUjd0G*9x97eo zz2=M3TjZLt0W>zf@(FSs0$rP4Z@%m2dO2e+E^@XuPbOLJJWcFpES>+IOOxR&s~AC< z;DJvM**zC39W8o1dTrlvod+Qqhkzu>F)TwIh(@Q^D+GbdWL4LPe)Wdc#)Lsr zbD}R3KIoGjWv<{q;v=y$C*0bpHCvfySbG1b*)aYX{j!y>T)8r+xKYVGv^nIG`Th!5 z@2y_6#t`!HO@P2B|@5o)#K2x7)>A$SGD`rY$X!g1apM6n{$IoCk{fISS&}PAl3t;TD4nO zw(07T;#gQC>G%U;JyySY<~B9Uz+;wDcTElHXHOptv4WRpx-HCuRBZo`s8@tnfMgb_eMmWJLW-)j!owKaTIX3D2ez0MxOU8pd_iYHq zkL^wh)=Y^^>zZ+&{&ovox?U@Z!Io4?8+m@PxXZ1plk9jX0;#{twMr?StPZoJOo7AQ z?8N&w?p3(r%<`yJgx}o1wwyY0digBd=1~AmSdC$;V|`tZzD&=Yo0F?eG?JxrudcZ} z;=SK{E;YGt9I5c$>#r{_%SQt^y6glR^K`YCbB%3;V9)l;<0_TodE1YN)M5&XX;2~f z>mdPWfkj=ASI-2$#Ak3z6HUA$bZ%QJXec@aIkrHP0BON)(qo!z!+=zF?HzlsXT48N z1IPW;k#YIEktxz?#hCqw8NSMM;c)r*+w)PK(l4nK}l50vYRzT)=Y3;tnOa7y~dkOWn?lTxZy zT68wV(lgXF3~1I0X(O1i;lPB-&Q4^TaVvxKTAqs?lr%b6<(m3UTEF-1cV^tm^pYm} z5oZ`j3`RHZ?Rsh~h!ZYMKRbsJuZU6u{Xf#ZS;8E_uv7DHYptT)R|h82F<5u`^5r3L z5@yD}ch`nsOpL$`V%epV@vn=)xNr56t$uu!?e9Ln7l*ptjHnBe|2yIVJ}FQ>~F zJ5sv+iIyTWE}!PqxUh3(;xISw-dHYW%Y5F%eUfUV;WW(oR~rW5mSy1&O2jd-%mC*SG_^0G6J2|K3sAij(D)%)&2^ zg6XcHrN53|G{-9&W^-cs;DZm?FPnY-c2_T%^>OV=cK)s9*0Z|>cdn0(qLcY7stjYdnO7TdJ3vlw zD+B;ZQsYr=PZnzc1Tdl=U>SQ5Z^NCQM@X|8F+}l<$(hNm^+QQm2Ko6Zl%D$61X44s zD=`K(9qij5GIKJ>B7o2g>X}Ltop>D;FYb*{x!D!Vh75H4!vz#^R)l*mb#PU8ir3U{ zh&x`OIQ`**w4|BrU<7umWf2J3qA+u38w<#6!QXcMm6ru^AtFK)|Df7Ym)I|moP-uM zRIiz2WMhyD`f1We6>V;vQ!k7pyLj=n=5Do@)}++trmS4T<`ppLhiF%ve`x1y&X16-fVZV64H8p{r5^L*@qu~I6=#|-dfkg z%u~x0Y2NyykN48eHLS~R6J{aFteEU6DiSq_ zfefjnc`y7@GJ97@f#=wG;N^iug&zmmw`~;yK8F zJOg^*gpq}~)FSa(sV&`69nZ<7_wE?dw9t_8y0%)`-kWl}VF( z1z8aj8^xrXK&coen5s)PQ$tu*fyHG!Wsh4lhjU61$z#y<0-7O!u`zlX_K+WfOlCny za4Z`}RGb8L&KTsbu?KM5Ici(~#@1-;7y^$T!r@6mz@!5s`$Fmvr-{LLU!DAdV!Q*xwL4?cZky`ZdRvJn~ zhET>6*}dDv`mDf}{^OnED2P|l!BIy8s4$0X4%dcgIu8agjC#(a7D($us%H$N12qi- zMp!@xbVtdelsOr9n$-|VQiR>KKjUB8M6&Ds_Uk$FRp*Q{73J6uhjfg zv*_!!#IQo*@^*O29({Rxx%l7xe%vh}UA%$F{U2W_gz0zA} z7*J|Gg>0?MKi)#JAOH66jM{bl!W+qD`X(}4jka}+oymB-e(V17{Rm|@7xpuVzvoJT zd{iSyWl8O$fX0PN5ae*`BanIrN=UyR;z%A#(v*u~1sg;ociJm=-AXAt0 z8{(hpz6l&FnWZk1ZZJTG>!ftS3V-3l4ul-?SU{f`Q6sG|&`XydQFoUAMK`=l5@sD>I z`lL%L*>2o%ZW4rXTzKov^uINrcQ|f*H?D=No;!7MxmT*n(Hc1T+uvPY{@XuWCn^N{ z`p)&`pWps$21h`$h9KbP=;sV<9iU$w4er!yCyQeoujcZj<-Onft>yav{nO=d|MIUU z$Qg9t>b!?{<;C@~$(o2G1xj0wHuehuvIU6im3!r8ZNebs81hX9WHrgQQ@GiJFWiXk z?{l+WgIZ=&ATFJ$YT30>y;2qKB%!D-()OtWzViqvTqjzN>p2h-q%q0+o~2fWeCmN| zOJA)0ca07|oH%Yjc1MU}g`$3*hFEcH#yD>DL+#<+7XRIMn+ zrX7<%Di@{|E)Bcw6A{ut^bKBei@z*3hd8w7Im~GKTK@vyWN4TpN4DRT7Hh6vVJHbR z&#t$;Qpx;uQ#Hu$ZzWy!E)QO2A7qF%QTM*cg?TA}hd_6$X1UWsueUC})mjbF>J!V6 zpZuVdm;hFs;!ucu_vVe|&mR72`BIi;yq3p%8d--pZESjmh#Jpy&iaq@@4UO*$`fOG z03G~0zx{j5-~RibRZ%nGW~*!t4$+j?+}C%O3va%WKfmCc=b9wy0K~#!iF&^opg2Bm zW4-!4lV|cHAo*wlh=QbwRBX66AXBXvs60Sa9X89GE!`!-Ai)}ir$e_nQ;ONjae|QE6~ksVd&ZYlpj$fRLD4W5RZO7BL|-hO6;NOQ9-36si*Voj+ zNt99ii~0(;#fTX7D)PVy;}y+^4Pa#4VAel_OmnXH3m0gQI){+itPal?DS35pk~k6= z^XfgdY~HycnvH~!t~`zIEg+i*^Bj>lTnKZ#^`rL&QEpeP4|ltG=C#?vVyEheM_Np_ z^}{!p?Yvt%x5^LN|9JWM;nmh@mV}t^`F?q1)2Q*RU0q*V*GA3iykqWZR*p1z4+8e% z8wLGB&T|pNrGM~~<*T3mblHEV5>IhDZweM+-=XEJ&%bId&D-d5sFDg}Ob`VipT|W3 z`*8QNUvNxKDo%$0=<;j@CviM()H`uBY6Nuv@py(Y59lNgx3KCqvKt`$y$o>Dhi=a^ zW-_2zm!gtaQBAPtu?wjQU-XptK-WHWb8$blnWEspj>lf#Pwk0#(YiBm^I%ASU z3Nax_L^6S){_B(9>=CNtkrwXZy!UREG82K3ZnwHl8e=RyIAcQC4$o2b4wVl`(yhB1 z7mw;*cHJOruywz2&tLCHFzknJ7|B9<-^fNWSu!x(uirHnUFiF|Bt+l9AHy2=a^q3k zK~R`2CCE8yZf)6s$-Ek~8sA`wgfKtHCYY%ahe1B8nr4umtgOc4u7t6$WdCYYa_51JWYQ9HfuH{Q+%OoDjJl|AYz!)l z-Qak&BvMjwMy>7L94L@kNex|$MbzdFkAofU;fLb1^-*A0$Yj4t+?z~oD$Kr z5yeU{-#vEW(D%;0_Xk5A-Wre&9%(S5wr2`{z46-e$jqxf#&-a zOZpT1x|?fr*17B<2qfZJgXj##oe+xZ0l68c)C;xAyl1il>Uq;KT%XPh@Wbuv`YbX_ z^^sD3r049a=ABfmjT=@y1PBM(5N%=*sR)Q!9W(dh)|>#V=d7S(ePc8~j9cI9Z&Z`s z!-WmYAOT{Z+_gUA-*XO90X2uJaWML=l!RCqkszl`Z0nU$SVk(yOS^EkI>xo%jU(A2 z=UHj{=Id|lshV=`R>?=|K8&$}LA*7>iM@(lHphml`wQourcOd5-<0{J$a?H%%^Co5H?&uN&rAjecIUs<))e27E^D zfhN+H4LcQ^c-lTB_kQ}fQFQje@zc3$PZi~VvHa?Ox@(=qY4lh_)4-;cPIP(Hk{9hy z|6Y!R-)gP@iT2LCTShe3G2& zRFLjx&@*sJNSszsPu%19nJU#Z>GvPDX;cUTX>m!M{CMgr1oD1JZ-6)_rZo0RNT5=` zC_E>^AWg`_uAs6(jHyo+th9+^KD^P`I&a+!2}Rn?`*75d&|zKw;dVn{OFWG8LoBKn zH@A&+NdbGmtW{Vtp6jD`^784|FpZ=SBG~^t!s|Q^&W;&|YR>wjda?tlpOYy8!RsTq zh~>y4*totM&~h%u0zUiG1iXSR$Gxs%5Zj9iNlm6kNyU-)Y4_|WX$B-^Ch~IiMz!b~ z1J9j4ZI}c}GPX~6z(u|q_}`K!X)V-sga`SI13__Kh)caXiob9x#{egkVx-byxRoQq zS9Z+C=zsOx-^ra(pn1fc8}40C)L*WVIuKu9o@C5DietYl-RSjVB?tfJ>hj`vYSF<~ zR~D)NWh*W}ZX!$h5{`8rX%j1378X?BtJpHOB zpCu)VgES%M3TS@z@yE-x|MRbxeR<6QY^S8qx4-xO#P{jt%ZJaGYXvh8Ru%L83#XS~ zT)kFY;!)`@wtw3599ER3-LrRX-RJ;Z~lZ z>&qhG$~K`RjY2Hn86u2`dHkdUv7PMi2u=vsbwt6zfH=N%dojQ50e6lHc*!$Ts2+%?8 zL(o=Ks#l<2BoQ_1C}Ir;-m70U2EP#!E`L8FnX!)~JhYsyje9Ye8>x6aXH>b1%@5eI z=hRU<8Sa6J`>1=?{eu-X72GfpZzR|Lt=d8)nXZn9-jY+D>ny@NMV+-maioI}RM&7dP7e;d|dZ{NA}Y|Dak{`yVxF zPfEhvF6HEW>%&|0P-MSE#_A`ZNWwf#)PH#I%jL_K5SQ3IgVk9*8N!)?X|^w2*HiY! zgF6-K```X@`T4*7>GF%uzO2Ik^|EsBB+cSNaaP8*3H{Ocf3SS^#pla|d&M0h$fK{l zzP$5;AH?mgnoRUp8_i}%5c|CJmN<>neJTk=;mRagc$`QT$_uZUYq%8T2V@AvlV%G( zeT2}mZh6usAlXDxrzVBGJJ<-2WVn2s7Waodo+Y&=&#OtkP|#Q1v*El+P2gbbSO7Ls zDMT5G*7<`GH{_#sK@13_9lsgbT+MWTa77eU6OII`Bs+k;=FfOG3&O0l94AAtGY);3 zcLgIAX5??(ODZE?#0gGtPk%870YPfx>s9*J3z(a&0-8R5)?3?9?_` z`uDfLSpN9o&5YV~XV&Swp_kO*8In_*FMH>955he0Mqfopm}%uhz5}o;ectMg==e9%Lf1HWNvWlSjrNMjX_p zSyE6Ci`wLV2+i{+#U3%aZ)~9YuMc!_NQ?9HQb7*y8+#*y1a_OEvcC`#wdzR(;-D_g zg1MO2TkpOzu)4{GolS@!j;00Z?~&feYX)}K+WUMKVX5tGVvk42B(o$DeUgvH^*fR+ z$!lE>$#?$3nn{3>eEId)D>0=>+{t5xXbyMY0yL`V^;HNOS6>D}7;3m|yB@kZ@tDR_sMj=6CwzJ+TOZjZxGO6C%A?R0+?kxYW>z{?hafdp%nx5Pm&NwV(eehaRC`tSa90;%8s z(Oa{=zQ~V_1PlTk^=$C#6G@WTX|%- zZ*kXyNfNczP=otaEfH|zfss#T947WyNDU$P7bQm&CX7yO!P2T8SbL&m)Be=FmKiq^ z1SOEi$pC?E<9)w#I5R?E(@6AmuR!9nHl?!S(yC3#jX3DJ)D#9hp2_QE!`j=jzk?OG zspSQ;24+vPO!1Dc=^qI}ReC+wJLdr|D@u<80DM4$zk@X=0QJfyO<4%T)wyd)JL(VB zQXlO9={+RuPFc1SD@qN0ku<%ZCU7Q|j-v)sk_II@|KNVhAQ~7ajLc{4f#1D{)i+3j zX&Ym)Ig@;~-L!~HEk8K$#v21ywvG(rM~|v36Y-Hecavn$$7)^uo^ivYVCnrNEk;7R zJDi`-{=py!9(@Fxj@?adWkFlV`|rO$sr_u2D_5?}Isa@3rgxJ(TjLpk6yJ*WH`ZCx zzjeIo;afHQ(lX^H{N;;u$pfikafyco!w!a=cS6?x<#AFWWF;k5zO~n0eP2nW-!l#a zLqPuD;|Qct1hU>|&;g)(NT02W8SKlr-;K-MX<^#=?2{@wWk*##yWIPU(O4*>dn z|C&mF*h04Yyq!<`RO-~(xE}F;H%Tc$Q*2(wCUs6nnCu%I9Zbb;s6OKv>k}L~YXky$<`Aj&jtp?~Ft4tMClPw@aF7}+o~+~7 z@2(Ckz%6xQz8mKb0`2qiL#4)aK*u>Y1he@)pWh;uxpDV+ z5Xcj{{p|4WlS;Q9sRU6~^OmD;y}ca#&ij>h4JeuQPeZgndHD76=dGwb)L?!yb$Zk0 z^yAk(n33=GXn;@`kUs*N-tcnZhKQ#)O$)2u{LcC1__>oIODW|Mz>zqHQnJrm-gBVI zIZ%m9u4IXWCt3meu)^o(Se0o&HtZ^Xf+rhj?$YHn0@%HrH{ zukCCU*|oShPHh6u#woc*iT2B7RC65QbR@tqf!@b);CTqi4v>5I`fG=mivp}o99slp zkZx2sh)LQ(JjlB)G^?*ouviWI>qhT*5@IQ{dOEi-dqQwd!3fKcrP3fO(txx>sK83K z(=QQ!s+HKt#q;7hYYNfM{+LJ8EI_KCSx{rIQQ5}0-oK{2jARZLf|d1bY$EfczwE4D zSdLwuLxdN?TdXF*(R<|dNqxbXU&}>(t<|Fftx-;J%`wvRVl|{575J8Z^j$#^H6jik z$P?Sx4z$bm2Ag>75dTyi>Lhg1F9+SmuT6m0xnToEfWM*)_*T!mPj6f5AC*4N8-tmq92%##sApXqb*;u)FjmCf^z^B?Hy1h=F<0sAQI9Ykg51m|x!*lFI;r-?YZubrTV@?H^7M&GOxg{?PQ{sQGEL@}AL-Kr$7GM1w@KC)jz%Qe_b$ zN6KUnGzxX$Fd!KMW>a8TYCWRheBt#Hdm$}I=#BKWds#pk33NAy&V!i4JE>=2Zco!w zc`k3YtmKwdn+^nJUgm&1^@%t{{Q5Y^-Z}W?+*U9|NY?zrr@-o%%C7V6@BG7t*$_vU zUah#))Yg?NR~CQtHxp12+HS7ZVutBG)mHZM7~t}BUmhkvynQVZe`~pQ|IYGJ>-qoc zV4ezbkzTga_S*Wqe5Pc*wx0dXf8F!#1J~MBFSHAu8iHzR^M%*nsm@eJY(Quyv^XdG zqk?>pI8JpU)diO)Zr41oPItfi_O*TBR~er-$CDFD=gB)z;-*S3IJS5}Fbp}YH!0Dt z`yKRp5(Of97bGEZhI55@L3EIN@+;bquf_G5ET;JdL5tLYy6V{-R9=upw&4`h7@=kq3#J3|j zLE&%04eO31XmT!Cu5JC)^r=sgeJYv-V4jyGsb&I|^mxdxpdUJ*KHdqYl1{-|_Qk|= zB1Xj9E!~$!5F9qdLV{~(gb6LByD%wP4&yFgZGK&uW22H~qfIdw8T^W1taA$&_l^if z;BwmR6q5A^V@M%?+dq2iAD(*ajdy=``0>5N7wXu9RI_V!{=-tUo0^IK6LN@UppjHC zj90yJe!VaaJFmgtyzZX$SUcChiBC0^Pv*LQ?cMJzhXd4+ChBh98zTC6YtLtgYq^E$X``Hy# zHpFUWCTVABx7qO@!bVV}i1P@8SB}&ILy|}_5mJ`~6RGDFqcVfFzG(xTFcPX60(duj z<#_6vwMuLh8RGiIlM07OG{pnM>`|pTRY+T@NCPL=dd~)bz-lP24{`)y%qjnL(=Z|p z_kB`n%80u9NB`<~umAD?`f9t2?u5b{G~Rsb&NMS^^aJ3U=PhxVeGPWsr=Nc6n)xj8 z=|rFRx8M5FKR)&5dq4Tv_T8I@55}ecHZJ(ZgK~~SXh?!9Yz`0q`q$=cpIw+~=>Goq zbM6}oHNYm8KI%N=@ZEb}hMeb;F6Z8UC+}M>&7#JWK3+V?doa`^8QdufiScK%Y}!N# zcI{-3yk5%8ts7r0w-e{$I4|OAVOm6hphfyuL-UH6>KBbFo|o!vNjo^W); zBNk!p3*hs9k;*Fv%k~Lzc*t;C>Ha29VUAhX9tWM^Vq6!<1c4EZ$UH)Wy!v%KLOEYw zNgy`INTP^~bYKueKHe&A`R-X6-iXvph31BD)* z6=-W_Oe>Q^iml==HyZFS@8nasQx8~Q&f?($|=2J!Xw-rOs%LQ8uq^aY6ga9Xb zuR@@^8I&iJI0s3M+{I_kTwH$iPUUkF?SJ{nC(F&$rQ@f{VQO-5PzE~0QmC9QBBu;d zQq@l8$@wZH)paAadeRbFs+?isc(SP(-S^tpQ;f=%cXGhWV(naBlPFJm%H1b-OR>MR zyz}OzA%dH&8}dBkp10?0oLi*ZB!h$V4;u@DV{}s`Ac1%eA|g4)3spaGb+%6Ksj(48 z$4`Aaf6DUbBKvt5pN4eSmhfOfK28R^GH_a8W}F%821tQEwaa}s^PG~Zhhiv7-O8u? zCIqG$EAMK&B*?TEo}S9R{LY(ijq8@P!aTtQgrE!*6^+V@$sjZYZ|)$wYg9C$8We-aqk|1V--~eD}`F zm)9~&=%KdUOrE^5Vcfi2$$s(2hT&G@F_0Q_CqT>*ekyFS!~OT#+2vPKts9giNRx`% zS6;E+z8TK6M`WkR?;o`!H)wztgCOQTH<9Kh%0BFnf4n)V2Ru}`!EANceK_=kY>eAU z1YGPyn>InRCw5e>54=XUxOkYZy`5w+*)Q6U=HA_s4Qu=Uy+=u!8%7^QWvQvr}iTEJW&FVD>7zt)F!*-NPV$3o`D~V4orCD zAfv1V@f`M*6d#?y46M2LF4b*@$h<2gm49Y!%Aua4PKr@bk*?p^yU(129gpjm*w46k z`%S7r*!`qZb9OZ5#U7-dJ;_#6li-_R>lqSFJPDqBSsm+7fAy;fG-T@eVK@=fqwbfP zF)rZDDnaGb!4Xp$r$A%F2v+wue!y$GGHFDhlS4qg6B9U5X1nokBpyJZiIFm}9pfH4 zs2?3-jr&Ft-rf3E<;$rWg2^A z{bxUW{_^=@y5*zt#J>Lg^W}cQsW7@eg%mm;;`qOrS@socfIJXi#P(#Oo$hP39R%D@ zr|v#>gj9D~$<#3789*6rvR{Y(>#hVolMkt79{<%ZKAM23wzon&w#=F1RfdVkw&U#0 z=0um@%%g{xpN3>IoTajChwS$n1MUnFMd{fE+Jw-fE5|I9Xx$i^`Y~1ZLqbGys9m3N zL6aj-%LE^05Z7llgEhLTNI6JdJGiN_nJ~INM}iVdW4H!4NF)!;^&ys!j(ZqEh%t$* zi^gLZW^k4V)G;1I%F*PGrAk?lW?c!%LS1GbKveCIBOR4Fig_P zcvaA3vzNp*r{tsXbODX}x6M>)2 zRvYbBKm&+*^`yo~)&dM8UybVM7FG9!7PIQ01y2VD=N0M<7<^O?Jig)K+oxwnQuI}vsp;z&2{YgJvJiaVidf{5iT3vhY@Flosbq8I^5x58 zcp@4{vFqZN)^|T`@ly6d17Y~R$mYO#p1nLhNpQG9U7WrVnE*0CZi3}s;iM+3{sh2? zp~>Ysl&LCaVS@Pko84@S5(*(^#Kq{tu^v_XiZ7obYYh7X&Y`w7=lQ}BsW> z9)eqJR!&wulI}7o8tKf<>bOH6hk!Yc;5WO0Ob7vpV<}x=XH=a9_$=>o_+}XW2tK2AY5Y7hqRhKGrOZ}zSe|@v; z>h8x`Mbhmq07j$Qg)r8X+(v{5Il^IYVNA1fG8mJzw|nlMo_E>#IkK?-{(-tW zI}i66flU>S-4n;pZmGyPfw_9{GUlsOkPr~2=2H_P`npr$ivt1cNJ)+iI35#T7w%Nj zhU$R8h*bzQOK~Ao6Jaoi%1?9P#_R<)j8?cjebTij9in?}J^r1`mxrr;^tXT8;<6Gi zn*i?T1BY@Bf@_=>WtR8`5J)UhKm4aiU0a3Zi%rpVr@Gt2plITz~ZqlkP0ln5tg zbG!DyZq}moEQt&5`uTbp#E^%IJ07^;&tv8~x3*j`eH|Bg^96zTr4pY#&pVbMr9P9A z2+%mGS2(@+_)!U_D-)4 zZwO}8w95LczqGkQA3Ycw>)%`nThD=znvjlLov;B&lZeYe{NNY%$q=qAXn-S{2O+!O z%A5e35#Bk7?!~y=tow+Fs3zVwTs|VXcYj?wvbv5_3A*;u?qwAQ*y9@$2-7anZGzr; z=k1=iCB@<8^Iv_@#}%I=m2!a_JzM_qfAOD}gI0~M`XQ^=vf%gMdvE!E=`CMU zCqg7#4G#oy#78*d)jGhu4Su+d2f|oD!Jq9`5da^4$i`boSy(F^=O^ z00rm3lEf_wAO=B&0(Ve?2ia?j zE#W+MlKYoE3RNb_w6^q%WYS(XZ^3O@*D<;7qRyR6gTNea=4sV8OonQ!xZIt4T)y5LISsA@0ya%wbvyK2m#lS+N2W|hx1NZ+K}XM{vBV+>VB zAEcmCkTf{TcB?e&e}J;DNHw=Y9QwMyeR)=b*Kk44QgLRjMuUHpp+_1GFKBYcc@TX< zFo}nBd!rxEN_R=VeEY38> z5GUu-{PSP@VmyEPCIK6ofGM=fBFo9)K z*%n|^Q$s9Zbs<%3GH5&JdF@GE$FZqU?$!SDh?sML3dz8J8H@x8hX~`gDv^q%;OIO; z)QWZYWXK4vF{|Jtwf=BB$cdrjwy;C99-Y4iSC8=cm3|L`ceEBx7gv zeJ5h4%3(Cd@7{H%wumiQ9cXTjAI)tafhzOL5ikVV7_ z|IosF@4dGbv4o-Pv5_#S>eZ1;dA`?yIUf*SU6(d8zVNsW3BiDq9A`pTM52<2e$yo( zNKxJOYMuhPE@_`<1y=Q`C`_hlN2K5 zo`*aDZd-{rF21>3Klj!0bp-}5y?c52=&u@6(&69yn}56f_~B1RIxtG<`d_xr;`MXq z$HlB&0XY!DHE}_96$e8dt}+|3?hU4II&m-+v@gJDf7^Jof`j|Y#g5Y$c7XQ zH4X%({gV-yn9{@Y(4_28J*}sQ(05D0_bf>RE~L-F12)TzDRoXe2>n6nG4jb=-pI7CiX6Yfy`vGQ}Ip_^a9Vtx!wz^pMSqLvkbG-G|tcRJ0_H3B#mWFPre#m&IqEI;y27m{_ z0k%RG0B4dU@ZpdM13(VO`Nx0^zi}6nh!^30GpTV79B3}oGS7_|fwDlW9h5rOTQ?->k?fei-iHpF%-RS4%sln4|-S@Ag1 zwK1EbBga?U=3c5Vcrea|4AfIKR%6rTFyMY$$FHclci7%S9A?TpHP*YSU5bN@G)>A= z^Mooert!=U*7lE1Hg?j+cMM=u`1*rz^i{w6I=5~f^SM_9V@}0 zbRa5#qv}93h=9m=Mi~15%V>ppfCU)qW=HIaRG{+6X8VLVm4I1TGn|_4t4|l(F5~!- z6U#sNzx`zSRVlQhMU5VrUmCZRoQ?9>p;QNxW6Kek#utdfm|Z#;3_&z|3n zp<>?p1yOs|ykow1k{4CslL<%YcU>O!zI#EJJN}go)9;D+_vxq~UgK|b%xjIpv9(7< zuWm>z%>|V-8po>xmtaf8Vu#A982|);b#J(q1x0`;lJA_&d_=EtKf1o>>BRzWI5dvF zav*lXYTHmRNEpO`;}E+C+e+hLy0G(*jqx|qtmhwBNSo+BP#TT@#2f_nEUD$m`H%k5 zf3{q`c5nIo5C3ZU_#gaYIT;5#TWvFCdmyPGV8!JzM+N?j36W3mv@wi^Qe*gvOz@$W=55q` z*QXyG9Ug;){`9WH2bE&3I`Nyt;`gVk4YQjKLoIXjJiH+oKM>9G!3XOu%8=4uQP15I zmyQ(~TejBhS9-NrLsF)c2p$jW%kex$I0O|anos1fK}e}1heKk3)9FEs0QRVrnIkqk z_q+tk;FxHZF>EXEY6kRPZJ2P+AhP&Z+;Y{QB?aQFJ6-3y189~OL$$|>Rjh-@l2Mr;llAkD|8_W2jZaL*XUub?C>W~UFujOW@4saB(JHEVeJ);)~FNHtEGA6ldB+LQCpCL?IOQFYA z#W@ay4W3z<(aPZ&-IZCK=k>#SnHg}#IL&axg6m2N7P4 z4DqZs*}P)T8^iq9I9z*W^LNX7R~v^_h#$jtd@H@*Kwf#tawyb5$A=$&IAdeOygK$| z)ulJy*aBo3vEn7TE$&RT-VbQuz)V7OFo^rSow!H>$$U5-P9g8e1X_;(Y3SV~4WB$o zuCKsaZ0Av_29H{;vR35#@1>26~ZeA`{ zmpManyLUh=Yh%tvOs67v1Y_skt4S9K#&+QP^(RhpIon75GM*ZJ7fd|Xb{=QC53*2a zs6U8FIVgyZGhza>wRsanZ91Ckm#TTK2sW1~`@?f!MXiNo`i-z~N0Nx1Z;miA>HO3) zi>SboDyRL&&&zX5B58MsH7VYYfvdT+hUsK&QO^*~izEQAq1Y4KMhvGWhB=){;=C5Z zVu&OHrww?`!mIix{RL4EDa0k!Fw-ViHZE_z`l;3ar?&aFx~{2wGzLuSe5#{NjpNOq zh(GDfF7YlI&eEtzRq-ophs-s24l#OZZLwq7cgDREOSi$|-ZA}S@cR!(?E;1luG2SN z{PoeBmR;J_<;$1n?3IKFgMV}UT?w-r!T6i&A%z!s^Bj<#-cBN}1IvF4z zJrbWmxaD$94dc<|zh<&!V3Rf_iQq>{Z?UM_$BH-9}+ ziW-5#y-r<7O59FO;Q6w)T_t(Z|3gP{S+3aCjmnO&Digua)*DSWt_%SM;}AANAbIWj ze71CbeZ77AK}7O=-g)8tg~nT~B4QWtPu}8WG66y!%OJ9dbOvn0tMJ4?+XU1p`8&xyKvB2y}FkRDAs*_L~n8@>INq$VC zmss~i0;3aSntnBZi0Icv`AD2jtCR%Tj zNtS@kurpD50%!srQ?$*{CJT;`5XSt}2eS(C=hWv0Z?u6?? zB*y*5<;dlH{@l^!hm~pi+5h{`mwo?b+_AA7&V|VnC#Epu7ScUw5=gT#LYw?|tGxwz zRo>)&yPBh}TR_!G?eA-R`{Jy0cYDhq#Pekx3nD%& zm}tx-w}eT7UKJaSkAnc`o^+%T>sh;OVJckCTiK=uD@~>Uh#e-Z+CqrmIKYb2MQ{;} zNOo|eLa{5%1!*9)#Jr8IfonGgm2b2=Ql{s2p2iIJ93tytuT+|xIg>Tsc%|Wh*{sS; z(vx1iXd@|mC$Fl*yz4&|3J!6IP(8IXPKvac&%XM6#;&T5UQz{3vt(4#pII#xiuTZ} zX50od?)sjXQ@DV^;#M=#J~~$8pgWqh&~Xk*)aku2iW3pex4mRr(FRccJ(XKqyKIPM8^2`=oz}U=7S;i2l?CqjxnxNxC_q0VIXyz8+iQhxPQoG;KSW|R%XD{ zXRRmiyFrmAfIFKIb#4sEnj4YdxDG}PxRrJw>RPl8U~!!|S_w;3I37CEtykq0%ZNPx z=JFRm{rPg?@}*ct1Re2C0%8;ObqIPW>ZI$RKYDs3z?Vg(ab$?dCZR6k#%vo1OG0s2 za8z(uNY|)S!|@TjRgP?8k-MO3RaL&ECu4&EQ)#u_MWw6-l1%`C#k7aL2!kjLnQT;sx+9=Y(mVG zt07?bQM;j_>)gZRkf|@@u}hP9rOJii4j7>z$gMphAYBnOkEnQ%?{iacBt4BqSzfT! z#`9EdaV~hlW@bO0h)C>OFhvZ*9k@ZdlYs20jm^6E;=PZxKQq=~xFHhEf(LKh;X3SC z%@19lMB?dV-xVY8qemNm{bY2^aplUD?GLkEKK=C5DGwWhZ#9wI>6H6+!bVjM_aD7* z_`ARLdw)>Wc0aDFSHvh4M0+^?q*ycn6EQ^>N`II)gh2B+n{#> zyqJc8dxy_k`SBqsUDg1vetk7$S@XGY;5CgTXF%830Jz+<4A&kVV2mdxhl6X=Mg+;O zxN)!Ia&h$E`n}&7ZZ0MMUfZPK%rQVcpdylDkZcg9zA@S_mXa=zW&&}@jelRexSVU; z#@@}YA$4Rnh~|@2_IEM48$BMf)72k#FNB%wMKUw`v;68}z&OX6lsvgg5VP9S0(@_qcWMq$LZ*nDl0Srm|VESD!T7PdVVJ-_JHdX!)qdAfaeiOO0io=3WGl! zka%;Xi=02(4$O^|>NctHt@eDg%|i#cO&%%dz)4pxNyW5B6S66ER$ic)z}Owf5f}H@c)oNJtfB zr?4MZj~%teq}aK5HI8LtJ6^OZ)OruDWlIIvcB;0h7UOwqX{c4UZNHgxITDk>?RP2@ zTTPGP7+Cv4;ttmjHpZt9VcQ_JAfzNmK}jmJd^{?tzLET-!)OWhkF&%9@h84kpV)3B z6wesq!nmg4`b4TWAww*Xn#(#Q7zABghtoaNy^Q~h=g*CY&(?onbT4VT+91Qx=6x&S zA+WNwg9GM5k`7}D!#SCD%tP(m3O@Q=7uLC|>gm{f^$~dB1*$-Jqf*EC;2hY_n0gR_ zdI4w7yl7{3Agk`))(#hT;fr z;cm5H;#8*Z(Fuwk-deZ7CaOt@^LdkIFB1a}5Rh5iLyQKY((!wAfHL*50_3v~d z&)gyxbEZAr7$WPp!WLAT`}*8(2ag6n|6hCe5^L9W=865Bd-M4l~Il2$GRTuZNl_4USUfSl%$?CzhpULum=Ggn!@~M@CxxkCD z-TR#2YUVLH*Kz*{AL%i5vov=q$gsm0Cgb*+WS02b55pv*Wx^Xxxy>+Y>_=fo8C!pC zcn)5SLm-_R=ITSld;3hL%r&IL4TgaO`5kZM&1a*TH)EilB_|;$gw_ekAeA{|fuqLp z&$Dy!Cn;eTbVR~@pKt4{LP#1 zg|ahdidK8=3$LY3F)LGkWK)^#hEwZfS{ZBc%ssftE0qKGvH(;0m=p4AlB8UO^?c&Y zl~`_pd1x%-nX~o;rCz%q^Cg5brju!SczCRsmR$1pB2b(%!(m`?>U&u!Kq`uHt*aH9_KE2|XA=6_)LTSNeJl6HIdDjD zi*d1AKW1ZF8W5)0Uw!S%U#_?D^4pht?llG>2p`0Iz&v$k0ar9rg*R!+Ol|a2e-d4nnn2t2pNjM{875d5*Rsn@%Nk}u+L<%2_WgX$ zP#(aqvVel*Kk%(+;_Y9}4Lzh0kCWDf5Z zO?C`3q@HWh1~d^@vjKcwI_@yfaWeBMkkZw!AsU_*5+0*40l6+u$26pdjg?}<6nT&G z0jF2be>&>_$?EN_*XqDGdBDRPRTCtTJ19eW2g$FUJWDC4a9B?7Kyr&XdzyTm0~zQ? zN|K&0W$BG@?$MW`U1)&2F~zu`ok?&bCp}uuW1`a>#KSPzn{U6>GYQNEVFaG9&ToWS zdDp;6Lm`TGZwOdtVT=ygQ!lNftu!(m)ukUsFJ6+GroiwRLmc9_2y`x>9NWoxzlKvK zG~TvLm#$m{(J;N>TYq3|Th&caE6WJE!Yn`{(2#3QvN|t}`J6tJ@=7Nu6CGtpP@?Aa zppCjKaxXBXfy%N{`A)1H@bjJ>2PM0x(`xIDPQo4-#D`uUY} zWo65F$X~qRx16usaDvFyO)?%PSDEQ|%#yHfAajp|rwX5B2?k>CWL+A;1bdiHbzBg? zJ3<@3m^bMZl9o9J*~S&uu6__{OnS#X7@2?wrkTg10(DFcoj|+1{r1~!sF`<&BH=Ng zS#g?%3)BoaDQ3YV1gS?lZd+ETu} z4*RgN%Tcc0&CWAp?Wo-3E6j4yY=c}eE`jiTv~A~`l3tv15UfmYC20pOqVGEA6v1Hm zk8`$}&u9TI+TOI4`Q`_=#(3Jpjm+pHY|9{Ug+TmTNx_O{-)NSaWEU=6*zm%oOP5BX z{M~4n1S(-2ug-yq%QxP5Ln2|TgImZYYsmu0UNnS;0Sd>HbUt{Kz)0mxHX2lxh#iA; zvq;oICN4WxNnTzJ1dXXWz*`zH-hF-Q`AR5jt9<7LLF)XPeqkt#u%Cr_%s_TGX<=V~ z2gpGP2DaS9`m$M1IWFlq6C#SEd2&AVud-Yw^F!bK*0z(h>tkTVQr-pV^R4an?P2D`uZXqL}M5A*PN6Vy1RtG0>Li(q_&8D*_x< z3&94!uVkF|sW2l=ZQcl>!}D&w#&-K&4)Mr8ZsO4~(F%*?WQqu@=1Ex1;-sVHl&$@& zfjLjchNr1`jSR3K?&TAD9cLuH{AnMennaJzTnNz`Jo{b;=$aD zOiq4fDckt(N$BTZ+D^N4{a-W^S}^wHOlVmtV=SX$YDa^`YB3|otEgSRjiZm4Xxfhs zYQaRgfx)FdjG_-*uv9q24a_wB&TuOm!?dNBGluueHJA27<7OUa)F%3)t9Z`q!JYNp z7Q!U!*u`M6cH&UYI)eRfMt)}4Cnb`GCHDF2OG>Y)#|;Awz62$>Gk`W?Z0;OdbjCXKI51t z>(sckf01-cwdrYoxy%oPl7?Eg|yZ=^6w0nsfk?eyKw}1e-N*L#GXC&uk}L2@UJz&hb*^ z9Srxg8k{x5v_s&S6CR29gUBXr>AJSydobb%!)y^FWnh8~9HZ6CJ^7NQc&Ww-Y+F}7 zWU;P*Y~khlM?d%kDVfiVqp zFWwtPKa5>Ty3#CMsNHiB0@6b!@-Ub?!&Jk^Kz$6>m22HsC#-D84KX1U$X6!hkZMjJ zVe0LMfUCh$4koHr$kG)9Q}#bbGb8P}Qq%Y&8VG^W>%Yu*X5M=Hoz;yYSB`^j7}<p3I;U|nq+0N8i+JX@C!_-VL zxTGn0my8b__Q14s1{WzvL*z?um5?+`niXe3_Jzc>O5vK78Y6L2POl`ucp&iyvFUA6 z8)eYiL0L^oT7Z*)Cf?TUj1guixSO~&Kw$_xnzH4mJ$3jbjd5*1`kFk`kQt1c`i+AE z4;V3CW>hO6t!%e5)|v%%zzL@ejRp4RNnYb0ee9hT17C0_(T!+-+nxz)D-6~#d@MWa z^hV&L-MT0@d51OyMM*Pp!~LDsCnUwC9Rp7fRR7d<<;s=5heqoiyELpX$v6u>(OI+_)ufDtbS|-lAXfhJowi=v1QU%yC-gXhpK8)hgAd^9Ikh=5f0HBJ0LdW z6{f0AmJjoQ$zh1n*@KTh^oM>h&LJq_LVW&&!83LX9L5Ya6A>i*q)))<4C+C?OWm#g%j`^F?IGQup4T*fb+dp-Bu zr*prvK7aOnkjcHA)v*BzQ$2Y?n&f!U*!tE5QPmDSFqiQpC%gn}ZKOE@nuKkw!~1!^ zAb=N(DMxZ>IL&j%I3mxGcjDO4UWkW=<7^XYq^*z`!T?e#)VDDb$%foX1fB9P{$9IdL(ls zS?~nMol8N)u|t&0v~l7lt^43$tn4N{eD_2P;TbVAZ^yFycm ziGC)g{5Z@nkfpBH54m6qJgK<#=Fj%`Vb;+w04s3ulDW585=Y#Q>ry5z=kwGs$=HN3 z72FSQJ+ucs(y28b#5BpqsZ@+`T4WmPz&?$Bl1^hI=CRU)YGtn2M@~{0$LL65((`n= z>ujDbrd0>~Ar8+Zqf1`q3!*W`a55uP%pRSSSrPE?K}>=W78sRXNl6_i?S5AIG7n#S z^_9%HKU$rRr)(#42YXpidOV*sr>-Bbf6a ze3`SzPFaMH@q@J0cu7MN!@KdF3*q|>6D%fT@Mt9f;zOw9s~^U6UO>k$5gdI_pZR7B zCxv%)SutHLmb&2BZ49ahBQ-RQL5ql#Fp~y;#1Wu`nlC0Zv1^VeOusz3?@R{Uu+McT zEYsEZL^HFKv1b;LrtW0T>^?fQQsU0)2N`2H?2seEk+q+D?enWw^>diU`EJg_Rx$jg z8W8t=z@C6{9gO9Yx}>Z}E`-kP zS?^c{5T;CC%XNPCv!B(Rd+oEYri{!Hg~(_mWs>?P$nHUOnDJyjO}>9DsyulgWhWmQ z@F*wlJLLQ5sW=j{Oyj}bTdT|Yq@S7aiu`oAc?Rue{va$wWR(D>VAoGa$cNFu#67dj zupiUjz6GBIf|bQ%8#b?^6Zy@8>kh(zse>cN zSjIkoePIQMg|6pce!1rRv1p+OkBrR-puhr#he!7M|$R@n52jWeIkMer(RSxkt^N(L*9??zZ0$+^jv+V^9xrMq-igu}5MSgw=$g@UwI zn~aN?Kn|Wb8Jt>QXDL3d33d~T%CW|7cI-HXbLsF90S$$^pE%$!Pds7SFVVh%e>S|1 zt|K7rW^(EkOh6#Q59Um+z{GTB0tW}lW9f|a#(-TXm-k+&DA|Ch>ZbKra`UiUqxZ{B zB~E3!lxcf`WjP9vLKJhJ;4yab$?@aI9Ew8I#dDf=a2O~P%%%{=l!i@owm3vPrVwRa z&jMNpeV{XV)_*PxZ;M7aw6r<)1#JO*CJ0>yF|n-H7cPv0{Cu*{@_x*soQ;NAI7nC{ z=DEt9=~q#%M>~%Xtb#pqB#ngh5Q~Ptn60_gwfPH#PnrO~ofUw|9rek>e9~Co8o^*g zduT)m8Z)Kg?E5seX4|HmAhSp~8YHE&Ap$WmNzZ0bXdo>NG5AIcmEAdp)IJ8{8I)#K zqopfv|Mbnc{IX}~C7;L}o8U0OK?v`q7ha0nH{Pyv$}3s3L?SZ>5FqW?jt?w164p*k zd6@piz|cW&>NmcL3>)T97~ecqJ&Orrds~%ka~mdOrrBPNnS2SEt!||=?bzi*Aut+U z{Uw%^hv;Z6^$UxUQ^}0T_j2Yz2hD*?9`g}nbuQxONEi(7qrHf{DBmIg06+jqL_t&y z$s$B)xy#M}z~TH92?5A0jcKJx(%#$037;fayoeW&yZF5IxePxO3KAZ~HYipG%fZC2 z%r?8xu5%^0HnB8}b=A*N#A<1@f7_>KytPXgEqrw4} zT-zp@_se4rrhEFm=aPIg=npKL?DL^bmvUje^|7q%6sV&}RsdKihkHMa3ByjM8r_dB z6IVN@>2#$ z(@jy)G~A5{%{WHqBSORo{=Jla_Dog;KwOyi!)y5tPS!yABp^?jfphnrhk$skI1CVx zIUM)lkg$X%hZ2U-bO?cA1-HREvz1=N#8%sy>?GUeI}(9{KnR86Do9Y59=8OBz^VBY zL>MC)djSVP_`fKh2+}dyNfWc-%Am>LzDs)hlcYmb5|iYX@#rsvg3u5SO@!gv(X5mZ zUIl0flR)X1Cnl`{gR(6h(uXp%jI?o@$q5+c6utqAe)4a`Bp;*;%TG&MW}a&@CQ8A~ zKI7WG^oeiLxClU5!6PT%ICEPcFfrw0;(C{G)GKG6(~qfQXwbk-TTL1#tQ>i@%`!1w zTu@T9^lkaGN@fnEo)O4AD zI#HZNgE)ED>|q%jst_uz11?`1JDNIr#BGSMgq&}8(q6t%f_QJ;ycWV8<0+=$=@SmP z2yuq-yHz1@A#C_C#zClv)(kptVOKdMjCp9CnzFfa2@NvuW)8EM%U)braNH{uqV91 zvvn1faVsCB9}jq74Nopzy0pqq+=gLho@RLCjW@R6^E}uuo5&8V2}`Xdq#h6vFON=` zHlDT{C71PVB#zp4U!UA;So&;n)Djl;Za95I9{jl)9K(;O1fTu_nuX zd?|S^+JNu@79rr%BPHU%+*2#l=d?3HV|meq&t~nSen=Z>b!MQxR4=>_L90K&4UBB|mE9*$?-AI}p+;}b1BwzkJzxVgE(dP)wV3NotD4s3SP{W;MV&S6B zp+TG`PY%%xWwdnAlujz{fz?48LbbO=<4HE1f~mwC_sogCN~kavWP(YDvuAahu$p*5 zvcaMbqvE-tpU)B#OFFC|_~G~dD$=g&E0UK4lrKyicu0R`T)TQT=2XnRbRPQ}qVB{C zbM^geIbAYq&a#x{co-EEoXVF0tVE`bhGuR6>RUDrCk!A=@5`gHQlLHF{8MGIv7Lg>X0#NPYDa9!LuT z6F6n0v{}3##({g!%w)tUhh3#SX`K>CUij9x=#tRGjFGL94anfPgRvEQm`(og2mUsOFJNqjD6i$xF8RFvYA5%J)ptu~g}}Qc@aX zaIHG-LCjSKNN2S(f>g*gldh9>x{HL6URrC>g42X?Mlj!oEAnwBB)PfmLBXKxRj%gu ze)az9g-_>{$E*nOp;4Q$n1}lzv?tlod15E_@$F1BW=Y4rTRDIt3m%_D)4iYB`nNI= zyqSqH^9N?1_i_&K!!FHul24ldqF>+QPB+j7vvJt9tl+LkFxrP%f+6j;w9d>~0%q?m zL^Sb;NQ|F|K7V}+q%$JxsLeq>CaM{!orBtc^FU@5;Dd40p&>+0~pVqy}W;2LFP zPQq)vhmaD6$(XV(j7b`&;{HfwOsgMliDnhpt50Bp&Dbo>42=3Gj+h7q8olGQl&5?e zjakVo>{jlag+K_>%BN#tDC2{;_utQsRx7;qwb2-65XYpnQ1c-DZ=ve@A6(5hfPUHU z+q@Y1gY(i&($X3j-ceuL0k0=QD*>>01Se);71SBAXqaUTQygsn;U(L?rk5<5URA5r z>#x7=-skL1=sn`S_s?cGnt|pA8P^!lj?eKKq{k~1Kz0JyP>W+Q4{!)JzPNvP9KO(* z^Hf#I76P}}&Ng982g!93Xi(DlSI$lC13HW{)HuRBl|iwS>@kvfT7q57=T5sQgY1cyiLg@JagxK0{U z)u3AkSfQj$8jF-5y!^Ms1wO?Q4j61|JFe%h+e(=6o_8i*$7<;>#6to{@2u8|<3=vd zQ{RI0QD)NJ3gP!-w5g8+g*VH0Y?#wW@<|iBO?`rodmq!@zCDPPw$g5re=kdZTo{uE z<^}t77WF#SzuUx(y#fJm-D~+SDL40(_b~Gi)L_T#gwplwC1Oc9v_w0!*+nQ=_Vj+r z#7sVPr7vl;(r5aXwc|NWe%1xuYv$M=|M4Ghcq3sJ)bx^Ibt!`zmqEYFQsd z2@`)h!gUIZvZzv>YrJAF4bO@tHjv3F;6gAQ1?jUQ7K1s--&X~0-1x9Rhl*pOGuiuM zAgX@*;_W@ZA4xV;IE2Prix#NsJgbY(#0j9ij+*L3U>K7WLkt+e-W#64J2|`T>NN~z z-wC|LJIJe(0>KA#!jD<&{Ebg4TtH*^d!vmudBqL#I}UnWL6?ie({_kQkjT; z=e>7p@-Yz!Y&c=QS*D~elbB4u>mP)E0-wIt=B|tnT>2xtwYe5+YHiRjaPAGuW8Z~M zh6zlYu(=mTyyf|8UuWt|xDi7j3dpNUOFj~ieahCy43L8G+2T%*vG&ZDxh%W4>edFJ zyFv8r5EdKNN0yi_2HuWmvg=Ss(hd+yQ#pqWkpdVK2;Zpel+h(0fx#JEk3w{2zk*mpMi$pYaZHQSsJsVK{e7dQOC~qH7`@eWiJ9!S3SCR0{Uv$MPA5d~W@P zoCDzZd`!qXEduBKQu6y5`_OO>x-%AnBV#)zjRPAj0)>BbI|$9$WK2;Vj5tWwV=)&o zy@^Z^)wGCqF@Dg_Bk7Klf#-z~?QF z$U3v1XM|UCB~a3cv_1_?Yw1&7K}_oO7ET?EDo$Tue)TJRc;q4olZW6S`$ILQo#DYk zQX&4}$Cn5&riGeJC^#cLTrWlYyc9uY=Pk#_XI}YqHl2+x+&LJehpzzgoTajo+^%b)1p85uX(B@1u=nS&*qCLc|W}A(3?wd!7U$1$?!O1Z{_8 zwd1}r0wSi`4`Qf$F6J^y@^sQF1WnR2|DYrFI>C6x|%)v>-43gW@(0_C-T{hc+E~dXR}w}Odcwn)T^^12qP%EhAi6j zao)i|io9o_nm}2N_-h7ut>V5D`X*;3+4 zBc97@f}YE)&yuhtl<7HRM5~TzE9D_ff|47#LMUY_mj=Nw7JCkJIRZ{WG;i)LGx6NG zwn^+~@)(X0pnFYWiIQI1Kp?F#5|82iFvkmLUkIGGv1i{*#*fB)CHk~~AFagP{rsz+ zDZSncoW_bwVsz0uf}3Mm#7h(P(;cagFvCpC5axg%I2xu$#V*^F9k zNsHK+G|>#NWT{GCo3`JQ3}Tf}f+aBU+izhKG&X*a-EmMdJjj5PSwOdX>Ai{pcDrJ~lyl3TdBD5*l%D4x|u-f<`RB-9* zGtrVqGfts-9dO~uSQEs?Z#AfR{e|;_8*JeSP(_pZ~1K{_2y>5N6?lFbi7u>lh~Yd1+AHauZ7#{{Q z5ygJI^6oFkgd9W$>0?lAjwOT6XbWZ3gbBeN&39mQGKQ=~OdjS7!caCz-8qSLtUMjy zmr&E95CY=*AOk`OGY`QevSq-|KI)n;UuTYk^CC6Eu*L^g64Q>PEAxdmjKeza&76N6 z;`-Gu-|vT$NIwXwxu#3N6vBmOV>9q@v$u_DpLg1mV}qd4HVX%9wj@s74!OgScAIk1 zn)PSOB3x!J6R3mcCns;ewZo8A;mro^(M#aX_2tNEgQl#sj-usu)mNaO*N2 zWi2QheEN?xM?uON_&M6SB&M(WFp_xgWcdyH;fFH@Ll!3~k5*A822>_5tMBs|XS^7v zhZPah-inFFQ9?sFA&7a#lm642Cfq zsn1zrJ2ACNqZ^-TFX2Pllg3ZdPTLqF-lAn=nuRFfkL#Uw*JewGf`r74qh-O(-LGx> z6O&cbB)xeNxaHnPU=KocOzqp(oOc|i$TQ}b$j5;#OOj3>kGYs+4nE|m$(6U#O!De~ z%xE{MI85+x=YAQNL&6~-cA~!X&O1X>)2``P`-?7Ce{vqHj|&HKK$IlTW|e1yS;+_tXO&0mA;#vvX8ALBPig=eU4!= z4Lsb+!bk>gN)3is7imaJ={ypTs;wkh%mE1Zg=4_udfe`Axk<3m_a52Aga~q#VSN}T z(jiPd(uBzeIvoWjt(D z(s^f3W*K^jf{-z$v+nF@y2O~oXWdhI7%v0qG?!Lb`{rEQz_c3Dla@0V65>zY4k)Ls zcGIqt5jc=!#+)PN!MzBV)PXVy4V|nHl|yr!jf-2^`i2>!9Utbj&zhdWmGyh@l?-8) zc0&m>`lI>$eUf=UbobcNNAn8OXx4erN)U-Y2vaq&BCf@&$hl$Fvg`d{<|LsAGJ>SE zzV$JGy1d`;BtOhD!#5gcv^v2V^t0XUI-7~sIkPdV`?Do679VYasCT0!5Hsnk@g2)V zszY`eBArCdlR9<_BD`{ZO4VQkWoSeU)kYz_BRQlFE)WkGHIPOlW#yL#av2yQgET7$ zOqfZ_?vW325CO&_Q6PJiAL78oLE4GHgAv)#w9|h0*qG!*%(Bxb9n@zvv=1hgUTd~- zkM1T7Gs~EU+D9_NNVW8H%l0V`3}B)RaUSGL1Sc(*DN*Hb(%R%igF4vHoC^ntv%@-G zN?RUhLQ*}BU9yhrUKl1+T4}2o?Kh6o2i5)|;4~!R(Ik)ucL+Oz;Y8l;`QdQq);4}J z&LQB;PcUbDlBhJ%J{SUV)C^2pFmT6bDqa`~v#EkkT9JbByYD72=YP<2u=@GC@2+mX^(Me`m1E}d$m`3OFQ~&KHRd3Kt@gdjO9L>G2U6@w0ILTp9eNNdwD-UXlGdA%wmRZ* zzK|sgWOLI(=w74}ro&`30n-6Oc*@2i%dzaAr%auXBF$-$h}(7?^9dvV$_XYR_L@dv z1al4!lQ6M(CSMFt@5B3%rZLMxEg4igg(jLHM8ll1VARQq%otMYgLIGsG46vUKMVZ! zvMRuxbKq2%!Z@TS=%?(n`9k#Zz<52T4Q-%8M9IahgAhvF9p>PIeJ6)+td2iioxhV$ zn#b&;Cr-o}5pr3b4KpKp_PKpTKYRaL_U+`f|KQY7wwC1Z65b6SXgYgA;0*qlN?7BrOI|Ae^$4X4Uce6{8lzyB(dp_-Sd=z5u3W?;s6{3wqS-qG#9F=n+yj}BI2B49k1c%4m(LX32z4T<$$27A}8-&*~h-}++f zqNc&2UMAQ#zWn(zAlnq8xJoNAQ@C*rMl#@am*$Pj@zY20{NC4ps|-L|lVChYdfoVd zsiXre7Q~pe5&|8XatvVk7p)9_`{!5k1?HQp@BIGPYRYLJ*a-{f!ZdYscH&?zE>ve zfdNN6rko|~9K#xU5`o;aotL!i6B#WCeKf+YsbG34=OE?C<^Izty@`14jxX0OSQzJ3YiV%1I>&!wk&F&SWoXetzZM zmiO&%{!Y(fQ>Q$moOrn^ElJ8i64=#~DyqfQ0YVpI#E|c2tsCa~5C7ditoBBX^2#HP z=jLc|{(w=Wviv;fVvgO9bT`o)t7i2_|Ms_&4+)NVaCmP!^NaxzvRFTsg0O`nDs+Xv z`OYs_U%&9V)gS#ke}MBNq=s3ZsF5*Q0*F8D592OEt)_1ZnDrADA7%>Ut+(D@y>az= zK8AHJ?ay4*?WD!@X@~msn`6Q_SaM}8PUl=Oi|EaTSr&&_!v@vnF%gAkxy#gd3kO$c zbo{t5f-S(1JWZhI&cr2IB9M){&$1889;oj~yL1!)*{eE12SZ#vYDurmA~9(YL^~%p zu0f^;DaWmR^;%AMS7yrb)iZb}y-7V0Bz8M0u$4)Zb}|VxDMx+-Sdz5_nsAa>guF*G z#&BmQg3%@}mw_(E$W!CB<8jQ%wm8qeYM^`_Hm|O&E0K?~)eS%3H^8M$$Fh#JHR+5o z;K~IC6L^GxI50QdpX6&9fu+o%;J{GaCQKb|P@iI^!F}TMxA?t8)^ zfT(k!31##r@p388`N=$z_0*-$OEZbr7In40z;ZL28X3E&m!k^aX2Q^KUcTIwu|N8oHw!bOw9F+LYU+50 zC!IME?R^lVv4sI7W>)m$+~2^+D3!v+`P7z zFn>K|VdnR&vPcns@s~g99WfS`wnW{-KLzK;M$=3r#9Hst?{I$oNJk*g!ddv_NW^p$Cy7$abl9Oma;{^slykOH=1`TLLmq1KlzhC@j<2a z>#x7Qn+0e)@sw4hW=+je%LHEgoo_w=^>6;&e-#yb>V8gH2^QLMT}Be5SaHh*j3_n0 zJi;%c7VT9xz_V}=A`Ix6AP`8)bPqdMX+VMugGR)p42?C&elBJO+xVSpH&)kE?wK^| zyv36lxFQ$}IR~Og8IXf9><;8Lvu}l$&BYJ@I7@qI1cQFdXFkZPfER*nj9nLb;Kele zGZ1y>q+nVEq!^A+3vhgaUpOzD~Z7j}1_#G*nZdtb@KWt0Yx_QEu){5-d*?gDo5^SHa5DGR3l!Z1g| zFuR}s>hC`H#ozrm|5>)&zMRggv1*c#RAc9N-a_*b7R2S5W8lv1u`%pyKCC1d=oq3V zSrBLr#4PTMne|P3$^h(bjN%S6{uwNDc^a7e*5SM`3L;e_CWtQRzY=<+3@O*ed@0+7 zDb$Z}F(-A6z#zApCF!aS5i&!@d!9{nq6w>~jaQzFOW09K+TXQQVcz?^WGP>IaOoVT zg83TlU~0JQc(5V@V;%USZNNbj*=j&|ScK}hrsVDfXtEV2mE4JkV~niv%(ITGT0Y;? zaL%Y-^>AP2N;r!^9_B28qn~tWQjGco3#JFpba<#!`3WjKV6F>WK7x$w)(u7W2 z2Aa^0Kdvy#ettViz)Pm|gRI{<@O{d8U47?`C!hQJ@4bCw=h(}2mnId>!SlgP;ofBD zAMIQNuhSTyJ$ZbqgR30(RLx=mBJ+#npLVQ|31J9JGB97INsv^thh)MCK@=p_yObpp zR4c-USmOZ?h!273T)#II|PBNJ8Fr}tBO zrW~svkM%k_p%j^e0oupOrh^F)KQl{Oc-QVpq{4Wqs_lb!jNP$U>i01vn(igXUGZ8i zbn)m>KAV9t(nkG_L28nwFpP>;^f{rYue(?`aVD(Iubl`ZS+UImFu8p{^wI_f7O-~$ zZtuyJ^{uOq;}@k{S4VQ7d{*Zlgjw>IMs8h$XSU8I6JYUWn8k-MZT_Fh`;pAJ2W?k= z7<22p$JWQc9Xr-q#t0Y)(15X~2vs;z)Yjn8NReiF38aC*tUm&%Yc&WdGB8~7vu`ng zr6iDI{Sc%>TxWq}l9&u7Y0yC3wL#jHIF;Usv6P;4*5TaG;&*l|%nSpE0M$JP-lG#} zAN%py#GDJ9kQ2{?ep92_Q5xAkMW)q2oY+R279r)BCZ znvU>1awTF$X4bJLp0U%bK+!wI4JMa(miJ8cszc9A)Zg9jB2rkzJptWv;y43FBE5s$L!G z@Ic2QVIs^}$(wM5!7L%QFcDKvI}l}$bV|dGkKpB2nCR7Qc6P-DzrHe;xvId_)U;;<=Db<|2A&nY30+^zioxA#Jyl zR^M2upw2SGBK&-z8f?bKx3W!wu%@lfK9|oSMhNO#%oL&x?lXBFRAAgJ8G1d{J-mAm zHG1o#FOLOA81-9WnB@Z6SgkA|$f98cu0Q|z&#yzk>!`Dxj9rFsd+ylo~Hl10DqmEfO#2M78hxy>L0$FESPo^&TaYwiarA~^peK4{T z^irgE;Gj9!QxO(&Si_fi39XXPn;W^SZMP%T=&&s-R;lh3#VXN22++2mtA*^`zrT0xvtK#!_K*I>TW4N6_m7XAKJ#B5WYD4kUE>u(2~7PxOv7M;dBX(L z@#{3qrK9g;C2u8RO4cEytRM4Xdw@v_AP$;|w56hrbv$DN8i$GGtgJ3mS4PrUbEyPD&ls?bo@7JyQN~ zq4Ve%gE6-paA;pUSk32jnGaM3mWYAiVT_S55y4?O4(5{tBM}?{EKHo#@sxFdoA#Nt z7Os)QsW6-aDYit+QBrMLp|p(slHNMKabWpy1gK}7xvZ|R&hfJFgHV~VelBIY2oyw1 zsEv8A;Ym~msm}tapg;?OudAk8et-PRx)D=WlFVC6Bt91RQz zeMM+?RRDnz8iG^i*6@;Yl8tk{jUUbZxr|#5!UJ81o4!<8Ce`=D=sS<^KlSM89+{uy5q_eWL&$xvthFMN$ecI8iAJefqP&o$fMQvcIsh9=`8_V+- z&5`udc3Df{Bur>u zU$&3Ilr}bvF9W0>Hcu_?l0aeLp_Rn5;Gbroype$NO%W;SoDd= z5n&lN-m#rHx0)1Q#Jjn-ZobYSjy8 z#)bqGD?>WoR_T<9;V~+w&)K;1?Ycbwsh3tS=OiQW5`y~ag&ahJ7AjP8hbsb$(*l0r zFq3fqZJ6b!tCQ#QP5XO$`2^&_xpU{B{ould3%y^wc(L~(z);b+4x40~m_;QW%tOhe zvNB}Y+rNJO-6to{oqO*4fA+usPv81`|Ivkv68^J$_wVdQlI^79nqOzQ5H@1&$9>YV z7T|Tzof%!kL*uYnxfNY<4djHW^MYV_kErP3gCA~ckviVz_;!y`!Rd%}4DIIZ;@Z5J zG|0iUlNc+_!XUyCq)tb0!FM(?<(=>U1%` zVgc2u!*QYCFcrM3D`**vcIM>X3%lob^Et+U^s68Ii~sf9xmQnKzy1rIKpD^?z&*J9 zk)tcGn@e1;rP}clq^HddLc!|{e0H)-X7|dKE8dAUm^%`Hj*{-Vj=lPgZ~udQ)BfL& zM9Tljwu6Hlsipo%$soeF4b?WJvh3+}0qIbl5e%hOokvOIsp9=$Lwb@yXJV=%DEUYl z*BETuCha{DFr)1Jg>3!CB!g^aX&2j`)RWY6&9df;2^VQMOpFweQV`&jz6j1X=2;DG zV+>Me4D-};lt|^t%WW=?jsx$6xn@V|Mi|aG7z+%+#j7*Stx8!Ooch`47^!2Dz|XTb zVJ>_r+ue`W)^*x0Z=DpFFNhEZ9_eTbxRVyHBuC_k3$8_U+_v;#&CR8J3@wu~;FT8Y z1>F8iG!*2$g?r314NHS~F09E%yTPAJn`qZs8q%kogo1cN2pv^ZDX(ya*}_1CSD8Ju zq<^)Qrg5fO+dE(iU+?7$CMVYUBH2HAboCei`IW!^{=Ji#8o2+#2N-5!ip8DW3Co0O zSU^QZQ1a3E9?qV+k|^=(or@PQuCq*LC*Gr-NQZUQ*^vONT%hEZP*LQ+T*Yk|I7aL&^{MGAhP2IDz;Rtd$#C(;`;~O0Fez2d zm`>v;(3v`<#F~30SLz@!Pn`}Sr0l|4LW-KFf&2ZcLR32_#r|Mqu}=DRHGHM(`O=|8;jgFpYT zQ(VrSJ(nfd*UKz1-SQ}pZ@8e{$>ngO__}|xsVv_?Pk`0 zCl&98pmtLMRk3^Wze&N zrBiL{bgE8PK($eb$H^Z~e_<{SCK!@KCmCQ@(gexLHi#fZ3h9GLbc#+NjslXMq+t$# z$#dsJ(z!uqI~!Az>N*t+U?J5pCn?SB0Jo(bEd&v&GjY6On6HNlG6(WpLeKLc)@YBE zLwg~nnnYnPTbetUkg^f5f=OJa3fK+s<#DH9AXmqg_o97EgRYmj#(GSc=iJCD09?h35>lo^1}!1i`i37dI^lA$7Pv$`HvpJpRL?orl zfRJj2OeRZ_8idZy6OUL2;l(SI!gxq-WEbA;tQxjxGD0S%kMo8zc1XF_eU%sof_qNZ zShYKt0+Z-iL<+1&SvE7gE+Oc2j)8P4&9@fQmc;8c3_$`Gw_ze_5IX`M(sF21MC<3$ z1{H9{+N%-j>lR(35@Q-=kdmD<3OtJUB{SieS9-WXD7N+*b173>3Q7JTK=>ti;K-gB z;L}(o;5^$6D^0(hlQ#SIWwmt50l#!Z>gVeT88FjpG!6lye9Y;hX~BevNq!ZXpazWc zD?D1}nD?^%*ce0mn73y#Gmk-f0Wv=f$Sv<9U31)oX+zM7Ps$WL+ej=g7{{uSVj0Hg%sXCL|~_gZ@wgDelk-W)CUIY=FcvRca=ING#G) z+9AEz;A5L}U*5pp{^41$TsqbFYxp7iEw)JKD{nRQUjvJ&_( ztNI1ujK?r3rk9roX}FcgkwFgiqa_@R+f)2QK;TpvLPQ9pvhq#bDT9)UR<72-81mC} zH{yg)7s6HE(GZF=0XQ^hS2Ny41^s}xq&8w!?jLkLLwt3w= ztdpT}&MFJjlwlIvd$@8ZJJZTAISq36&i?-H$$R&9?q^eaJX%K{-s%@n?Uz1&5LFOH zICAv#>7Qad87=8u-&yZVd# z%|N}Uo#Y_=n>U-bWhN%QrpF?Rxpb2*<-6|PyjldjaQ@YN`nBa89DU(@+j=^64ewQx zZvG_afmIHtQWqGb`=Y&Wu1>#j{veXkSTA5^+?Bf0oWR<;l4nfzoqi$hdlb{OB@Q@Z zdL0}+dTM=7-qD7XF~&}hZwfmfx0jmpRrJSq500L8s!Q7QC~kBn)zQ?aEJPUsOa3PZcdx$NHny$^7xkx%HJInsu)G{Sl`;Z*%Y(U?h6{`> zgY=hg!kd?aqp>3H37>`KuBEg5$AKH(T*6N|{x$cTSF^+MvBSn!>$ExeThbj%OCk^8 z@bSIu<;ivG{1<|NCpo+RQNFjDlL1}n=QvQZ4J^ZyJJlZ0jPrJnpFMy4;iKE;DV~HO zo`jkAb4J}BX318p4G{opT#T*Pj%0}X85+2S;sVEVj0WqL^5C+40I$+ zvlBpeLOeV1QtX}>-;W`J*2g1_L7z*Rv)uXaJ}(H^j-TP~AB*Eca4lsI1Vo4zU{*D z{8ac>nZoDQ`j)htF!hYJMN81=&ZRt`W-lD_K2^u2`v)=3^4y!w!&bY5xgz~OhKokz z&(q~U{eC!Z=GnSu(&e~;*(T^W$g@eCyidWqi8vHK%XFXD#A_g4f)*II^3Hs}X+5*- z+y{dQ2pwf)1Ao;HOWZy)i&pUq?QUz6YL_Sgo5Ut_Z0A*~>!Uix`yt|60-JIf%XqdZ zb1}^jNf{t_&&;wJCVcx{_)L?>)tZL~BQ1Afygut?PN(nrGl7)1ULkjBX1;l!@rUvY zekxxBmOt{ko|R`wa`*<0gXB9%p2BoE!8SbGakDOAzox#{aX9Z*9yoalZ_ zveY^IMw$amlBp2w+AzRkg6-$?E&DN_XWS-UzG#)rxJ5x}gPXKZT@!gv1#Z8@mVp{L%~U(lJd8ry17^Mg!u~hWv~`J}aSdMLH{k-4uM<>F z@CknorCBfUPa#14$$oGMhL$M3D{-^#mXRQ36z-&XD(_N>$H}1D~i!vYgev!=u~hyiewE-;ZWFpjiy=^S(MXZb7Tn z_~H&<=2L#{l>%_hDqPs#%nC&(@=o8_ZQ&T)}qaK4=!G!<&rMTV8$__ zscUnBhcJhU=PF`6EQt2F$3?LZfWbRXA|xr zS7F?$uY{^>-Fm2v@YJ>>-+IEQeDy7OnS>6GmeE>LkN8=hum!iXosHMG3;czB=AF1z z<`UN1EOVxt%#!!XI0x2(g}#)>^qTo6lX&lQykXTqh5})h10M`q%6;kv#-{?dUbcbW z3jXME@Jd_}e1W;9c^1_+HH}~z1>-n4Lz#zvq8k?V*l#`xSgy5&l92}UeFJR5*QA8I z$gMQ}mPa(1MV6a1i$s~_%sB7L^u5l5$Y(>EY#mpYc$-e&$8wrPVp z1TJ_hK~1=4+ycYQ+w==wCOq5q&vd;jL)lw!3U5Afv+P-y$QkC@wUutRZBySYUpjTn za<=idg^x|XBtQJDh>7coA8B0e3lCf6Hf`#gVWM3#Py16q;OcpK$?MfxG6LN^p;KR+ zUMbJ~?T1lJfL5!_a5MRHzC{_iWvfYZokd;EclY^|Z<=DB8=gs_ z9$6D^o_R`4X;hE2kucBV3TPTEsMpf)O}+$f(n%n#a-MZ<#VL1F#w;I#5#G#usGLon zrJPN@GymayTlLMT-}wHlyt5u~Z9k{b!j{#w>k!DnjLX~!4OSe^Jh{(yY~TmfC)GF8 zi&viVpV5d}=HaM@Pk3hJc9}D5!V1n@pHyCx&+-oC*=~>ge)&4wD=QQ1-f5GCNvym- zFvlWI7-i1ldu^D9KPt$e2N$?e;SB&$}??%=~l3wQzNArxWISR+#V! z&y1fii;G5`ZGR@?&ibX@hQa$R&-1Lq^Srj}c~(4W>e`OmuH#wloON#Jc~;nV{Df!T zXZpi;@xol&a5Nx)W_xD78SZ{K-+UK$xU3nsgde02=KgyJwoE!*UEW%C%=DsBl!tki zWnY`L3EqB|>=UmN_b0|aBVt=Bi)Nx3+gKIgeKFNMx`bKv+!vmHk|5A zLmT@^&s*cA?V>i%^0^L`L*ld!;oE6E&#;+C{_Qm0=Vid?Il@4Bo?EW4PrA0t+J2tt zXV`q-f}`bc)hWrQKKV#df@mwxET;Ea_Os$=+|00@M%?mlX;g)s_pR`mt+-7bxSk@s zLunf?Z2Ma3Xt~1Y`*xbG=cmdSzR*y^(b=L&`aYRNI%~t0G5Ds8(DEk^?&bN{d9i2u zOQ8_a=KwUlW=5|41?b%juxPUWJTLEK3OxY@gBzoc*c44?10i<|MAeA3N0 z&okc=zNup=r}<|3C9G*YPZ$A=nE}C=SqDN=$&EW!ibo~`47i?-%jIwUcW9}y6w7VzImVd=lg88_g|N9JMFK_KkNCVGR4oh zXQZ9|JFEE^KAw?hlV-auOP}exmgT2$?4Tb zGi-)$rOy|sh7QUu0003gNklJW7@=_&i*5A0L;fL)?NGOanm*;sG=sDM>?7j>}@c6N7EBywh1)fdXS%-k_x|amo za5qW*6vmYORNPWd!?vD3u@e{AHf>z$o41dZvx)c!pEKy!;%p0^3H!{OsHgg8)21cQ zgip9@=5M|cwCR`m>b@ywdESouSQ)dQCM@nV!;G8nxzD%>(^k~qKK?BR{uTrOpJCwt Y0s!87noge-J^%m!07*qoM6N<$f<57cSO5S3 literal 161615 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 z zuhBrnE?We89~^}}5U`K2AiLb&F4)&F;Z`cpFvI7d9nC_7p~k9m5C!n1 z(ONlDs8T-ZexReG0?;q^P^QVMrIFMW0+!^fi+0`|eIvyaR2Xf&?Ok9l8{5Ej$b#W= z{Gm#$({S=}5TaXV@BjPAw z)k!XK=8Og7zQj5gN(1X>Lcto0Wfd)vv9(q>wgb@DRBIxHW*bwujR`pCV$gqa!sGWg z#v;~WjOWj3md-Q)zrGNdpxNQezlguo!syRkG>`cUA5}J~j`r+=Ii!F^aPrqFt+bKh z5fg6;ut1f+2|w6A5>#X(XLpaoECMz&Jr#N>(AD6u>VQJ2gF|?Pw%y%>%#KSr8%m^) z%7H-B<9Ki&@T1Yt67or`5&O4^oyLa-!*{>+UFIWBho;5Mx1I|-x7YE}aT)nL;Tr~r zIj*loY;eraVvahAZS=hl8+~D93|1R7)%x~NfWL16!q=Y$j^qYD{sQy@kVHTGV9eIZgL@YMw?!wi!!GsHF8j8>x7bVmDh#xG_;S(nGj z)5Za69B(_u2E4BT#}1%I83OoR7A^re<#JACpkm)iqNOtr{0LrxuEId9soAil3+JS^ zW7a60?59dg-fQu#3#;w8T(;q*NpJ~CXfvuaFvmb;efCaC#3&4 zDg4YPvk;P93tNByC$!hWNdpGlgWj{#&ph?lqs{?c{zNP|9beiO2(&`&Cyo~ z)H1BOOpwa`4hImovi2DrnFFJ6QBU9wHNeQNgl^)#Io7o2;oVSw9iS)&nYu0Sjk4mv zdm#C!c=)a3v_J|t6xN>idcA`df@>6Ef52;y5QBd#k12C||BZu8iK{6S#wzTWMOU9| zG6p<>7B^vF7SybmW5&r7M0YHLZmF|jXGlk5k=QdIvDU#m+9-yX#1mLT_AJIfBy$dn z55wltABDHR`UYUuR(R{TzY#wD;a>Ro!)h3v-Uu@<60e~I%{1BtsjDTLVFPx{Y@Qen zC43BOAfl(W`kW1GFeTcqBSa|Pjk|)?G2Y|a^E9YcP%65fT1wX;wij@Dq8`u?ETC5( zABj%P>$%XNH(H6s#l<)u=Hdkx-=7MMPargYOHj0w@;`xj_H>adCWblBgq^~K(t$5% zfU7$qfYRM7abZ@ON4GKKPpIg!dHV!f4M^rH;eh=7FwloJd}Eu=(1y47KDq6tgzmu=803|{f5R?HtUMap$-^-qhFqWyD6#>r zCr9#NgJNq7ZCRk$YD&{X!-u1NxmJT`{u8myGyaR`&rxVrxhe#eLypH6 zVI_hIjSEe&#_@E#zjQ+x5-yXV3Jz@L#U+8xJ07+K85yhKDs26IEwFtn)@!6$QZfoC zJ-cY}Sz^qVB!+_3`Aiw0z$&qHra^w9fy0OY zj!0!K%*8`v!dDcprvf7xIsRJmyxPwPCofWL)CJD|R5z*Cp=tIJ`0a*|*ilrr@TlyBr$e*FysM=V$Q5CP-nPhe)rkS0CAl^WohI?zCySfMW5 z1g|fJ>ohz+6)GeUo~&<1_QT99E)Gf{i`&;j1)2&;NOZ%Rh#GH_=9N6VK{2o&>orPy zE~<(9V=XyYXNp3>v3|j#^Cd$~z6}pB8o7#A+fQ5%@20MjUv*;us8WGX5XS(L|J?eC zZXgj#EKVlz;maJl?CB;4KO0Wi7Z0!2Et&Q}@*UU3V4dw^{Wt?$j@xPMLh_hP<47PB z3Y70`7o%ERnj(`Mv8|jxHhw~9vtKR?`%i2pqQD@$!g|;M=Urw219w7}F$B7zMm)Ru z@x#ys&F!_T*TOSzOorybJzPzA84z42BIvc?UvmC9??By8<%NUr z;Ro-9xw*?QqjZHwFxHPT5o>&8G(5g{m%~NCxV0O4$)2@nIq>V0B*G+G@RVS>fQ!=u z^;3fdtgr2bj_Z?TtFRI%(q0yA7dNI0|GU6FRLi1iIXvuDn(oC>T*q7nffCw5x>WLX zj3U1~6BuJH(|QpOL@?TcHqDSIC{W!#=1?tmfEBBtJS?mnj_O_T^v>A{fvaeu!C|wepLMfNf!P?N9Z)n*lu(BBG0pT& zhU7gmr&y(Z@M&p4y*Z|li5JVVe|D4F)tfHZXJhPz@Ua19aEbg9*VFD#+9){iby~Ht zh43TnAasmLNx`j*;2k=zh*oo|Hd~hxn@>K zZ6Mshr_bB2%R=uEo0z*l+S>@#2_{jE42QX?aoUs_AhfU)*6u%qhq*s?T6X}d{!MnN4SG8|`nqwT9yn$3 zJx)YqLqoN-#`G_&aX;=_oj58p`#cR-DgiVt$bk&5%Pt%MRkU?(;bV$kS3+j;Qphty zCLuKv+CP;a4yhWGjf+2}4Pq>kyxX4OA@=YRnQ%`C8~Qg=Eb3* z#IIkcgpeaP1|6`=z}I73uOXO)Bp6iti+*;dPZBb}JlRq*?36dC*I>nCw6Y}MpS1JH@DQBJ4EWq9t92JM3Nm&7 zxC_RUH^Zl`zZ;e_m%_-^%V zCZC#0gx~tzXTvMEoOb3wohQ8i7MoqeNA3?>xC@mM@d6d>wKb9rTTgJc_$;!06%Jh6 zY#G}91O)JDi$<^}Gf7VNsr4L(VsbNVW3}#rHcn${ns7h24v42hTbTL#Z1h}UF6AjouvMLe(mn9jHCG*!}4ri18lN6aFL6>oIG;xh}n@7u^ zg#FTLEZBDTk_7|iq&0ECRfbq8LtK+1cFl4ih3pGMYO^Ly;>IM0wTpG>CI0Cm?cReo z&`Uhk%fanMxpYCPgzaNUD{ETc42uVMQHVRRUG_nk!YmoxRQ6N=r}#4y2)&S(cavt$ zqZnIQofDK>=@^g>Ng1t!)VX!M77_5?zX*f^38Xw0s0X^JKD-2ZvdzhKra?mYPvc#X z(dz{8%QWULh*Hjp{1Bq9Sfp1R?6y2_qV&grTts2<-(2O>N8;_b-}V;@QR0HV-=C51 z$lgD8xj#2`W$^dtV*nLn@P)?YVCWsx+4#w2Xnx)U6i9WJX)B?9^*UprE1`SuGlH<= z@DTId#o{M0-x)|Pvba7Kw0^#mOcngb1Hk($XxbJtNeTpbSp>7pqEyI+NzW=u5$dtlpKC2lEEx0vAYQ7^=xKTOMr_Nz?XpfniDn77bosbo^ zZUKHa)9luZKF@q5tR={J3Bl)D8GZ>wf?5rTT+_D3LmrF-?kI~!ezP22B~v#@TkFo+ zs>+hz#-(Q)Scyz(^%P44)1#aUB|9ofok^(zB};&!r#f^>g2jM z`MXm_jiiYoVs|3e&TEdyUG}TN2gxGYLW%fg+;J-24p>Vv1MszrMa(+Re4TY5S%KsV z4PxtK=VvGPoCEga1Z1gb&*4hiuM%93I(lm5>!KQu{&U!+6^?zJ2wh#5X#8eEFGjqUY=-(UD-vzi@%%zYQkf83qO z-f!Zoy|J;;MlQ54@u33qp`iS2kN7+$EPgj*?Lt&o5UboC$QJqRV}fP!Frlx4`@;~M z11LnNzcmy7lP^ue60W&0Zl|dFD!*eMPVuE(xQ(Tl5!Ta(Z zMt4t+g`O!!M&P1pRlGz2dad0(Tm&>U>D>bkct4ZJP5~{pNFFRgZZ`)Cx*PwtZ)`dW zab5qN1_6Cs=K&6I=XVwpakZj!ylCDmRYQCh{8@dh6`{{^nSx*R=BGU$WnQUN$W>p ztB}sBFot&B2uloNo(jhoVi=!O27d06otvHLx1Ik|t#C05;N5UKwMx6}nv9K6>v@xqS zvRo%rvrmD;ln8j6EShssxUbMnGsgH7!8`u>?4@~_W0RnYyw21xG!TAYNUecXX7op%MepFisRQb0*%kyIl56zR zg_!|Iwzsp2yP;MDmT$1jVd@2!CRui*kfKY_Q5V)`GW`3jpPgmGm~5ox!d{YCij5Py zrLv0JT~`bDQ`}sV_c9CBCf!cDDiCajwG9BJNTt0%@4okgaOds694g`qF>#%^+!z2(1DYF_%N9w53R=C)7>oqZ>p{qL87XARiYC$2 zQ3;?35@>G=qgDPkP-C&%)KY`J{MN{ZXzl1Br7sU#mTpwDa6Q?9P>7Hp{*8-dvP7_| z(0f}B5-2#C6dW;VE4=ZBtURZPv~9RqjPrmbUkM4%1{#@;;uQ;{ScS!$;Mh( z0U`gH$&_=W&sM#)Z~J!LoCXQPG*jvdB2&i-e2aDC`w&yxXj5f2|N zkf~zIFje->{*f@C&&eC@?;sS&bCN|prk_6t*KY-_W&iiU*huta`zII-imPUAqLTnv zxP0U)hJtB>jG3F4!Y%CK=aK1|kf+r*OYXgIh|E$ab)P;2>s^>4A7K45mCymdKqs`Y zofAD+0yHgV+`}#dq`m5gK zq5Ay~Nrr%d0|J!8=QzTReYCV5ULaiHJBfSKmEf$50{@eTLvD>U>7d{-vIZPz?-W(#v*jXG!tR{2)LZd@&-8KZ=KN_ zkGDP#*XM3P&S--fHUY+<*vzGcLFqWx#rqbXQseisT{_FsB5RU3c9+^+l|8mFYO$4N zCz%1q8AE>28t4ty2T!GjCDj-8l=TSx2ZB^3*iT`pOo!WYyhj4ZjAjOm*!_nOvHlP} z;-()n%Fjs;U0m~EAB}=Mf7$_gB5T(s9o-Tf2BBeLHZC4br5QXX6F{P3{3D zIjAsa9@qptC%9JR?R(K$TwwI~35<(CWTNYi3X`OboFkbN+GeS*oRW2GcNW6P)MV%% zV`H%#3CypiUE*uPI9ww0>zEtNsC^A0g9quWIUyrudT|(6!4pBV}}L%{fN zQK+Qnbpnfa`@eY@UPJRGsof+F`hd!i`UQQ^ffkgfOV>+iPa2+?g&8Gc93Z z6e=fR6~IOH_Kb5cxE$p8V=o37q&ikN$NP{p4%@16uK!F~vG(3Lag51}gjNUo)i!Yo zCzO5|=3k;f_yCw-gwI323pMTp>o77tilqi~h9;LGW_58B!tyD!G}$eLUN#m}u2qDQ zaF=UEcp^T0?x?-9eRWDThM&~9AALW$tE zHl&p(Q;VW;J+=hvs%qgKCTvDaSIf%2iYh}x9gZq*#u=cXA|37_vFR3W_&$8nMXs-t z`0VFncQRi8WvV^=20o>73tMeo6duHrU#Qih0Y%tcy9k_R9Q+{PhM(oMzW z05NVSE@5xqdK41s)RC-`%y10)xe{-Y4Sf3W=cjcT|0tmpT}YBY`vSiB>@(>zYi*`1 z&jv+}Ma)77Nb!#gUgJRG8<(~ju2Y)~tI=)BpcxKB3R>0^4y--yE>I7E$s@o%B2E_upwEFG_{qev2ICTBy z4YFWE5a_kS+EI<{%Wil)B~@!7ya_PV)N+=Jeg{?iq*x@h=`g<;Q#Z@qpwrg@LS_H_Xo zl>4j+0QUH8*5KE^3PUD*$c)dJ#u_X=x)WA5ABG}Bkena-B{4o4VR?-wD4bWgCOxbyK^NLN@W1mI7O(qSH#vq%i!i?`u9CIu?o#lfcsyHu7DkOBdF34vl3YGj* zV!9$k5cEDrcZ`H`tR;|}!D1mSS{bb)Uka1Kd{oOg*L}>dJb(hX$|2j?r&$kQEs4^| z;j{J?4#M?GSU+=H;lWY^2A$sU{0)k-Fp$;}wAz3562;#RViYn-HTI-qGt6~*jmI$m zC&F|8^?wu=kN7(h2$Q6FD_9+B1H?9Jg4)!lVV{5g#Ub z9$QCz$~EGCyMJ}El^rGpx){foT<1Md$iy&?RDAa8l`!5nibsop(K~d?&@9I;9#E4q zj%CMqTe?z@6ht68%}&zAIoc?U(aNC**RM{-Hr)m&+&3KCPGs(PG{`Yzk)Fqs#q&!4 z7mAkFVN5Oi_`*=wC=X8s#!~-KM9|G`ZwX(mtR4WDN3<97SBAK z&Uh?QSIHA2NTWK4&>342Yhp#n^<$k53255{woPY~u<_22rxF-ro@Z`MMm$*E>=lL5 zu}fq_An-mUXJ6~4EqWbx6NnsoaS0AMY)CgP&}BX&6(-T>yJ)8UI*0(Q=B;O6p?Js$ zjQ9T%ZCm6}2s6hOBnjdD3m$C|K$|rpxT1AokON3CuR+lfXCvDjrUVC{fF%lxt|)^% z$$A0lp+~5Nka0RgF*O{PPLo*1!LYNu7s{LW!^j)M98^9pk4532DLfq7YtPmCwLh`$bVmQS$YPVIExRKnt-hwUIyVR(Xj6wW-=MxV7 zR(NLQt6^qfn)I*Ai1-SA1{N)zfg!s8Yln~mZ!wU#g@vN7w8dGeVzs(JOpK2)B@X0= zBQI8&Ft^9xB;%wU<35@#tmF`=I^4ei3L}f6IH9e*hfdWHRy7#W((uEDu*9FWF#kT9 zB?B7=Dn0G#*PqiwU9>1)e&(4lJvqmXro+tCwXpu=2`nI71PEYU`*3<=G(1>k5Yf^K zm+(Qj{rFK>!{l!N^ltdluYHA^BN%6KJ4j*5T`cI)6h@aha{k`2Z~s4A?-e9zdY$Qg zX)1kXd2hR`{kR^0GZ=UfpeF%}WGr_TL5Wg?HY8q15xUj|5xSBtbSZ5}iqKw2v8#;@ zaW_OUL@q=S0Nu<07(d-(+EjO!_f?r$>8djIJYQD!G`L8hr(Bxf9Q&U4oKqu#JBBK= zg>sY;t^z_;09v*NV2GAsh=nA(4R~R@n+M_A(gejuVtf>7go_;WCBvP@qc~F_&xYMX zIl&D%310-`FY%GseUeI;QoN6aO|n1=c1Pjf#>4R2-}p@!3DxlKy-y+ocwvb`?I1G; zAaOog-NE{mV(eSw1_^7E1%&1Ztpz~JR+wdVnDja_w~P0&M`Td>n`h#rvdVVwfxBvC$Ko)^s!+!uG?Jp0008OG5H?Zngyr!{*w|-RPmYQGB-0RaU}`XbZl^~-F#Ld_dEg78lWR{kmSD1z`$d8c1Jw7 zRGtX;kKYQd$A@8zwsO}QrkLe+aI!@$2oL}nC~#b3lS2PM-mo5q$=MSOX2}rFB2v_G zHbR5Y?dlSqsmT@uJS=vcoQmzug!cvR+c9kux6+0a!ZqkB{_EA^N3^HC7;UD@Bh8O{;RMBwqM}0 zZ(Lanr^kC?c3?7Gow**iu!ehao0tW~LmJOE!Zc%p+Hl48S&GY@BisT9qa!&2rG+9LP>j7<)9K{;1L0I3m?UjSne(g0|1eLRkZkq(QR$Sb!4 z9hvJ9v={&@mR59yy`BHXm&@V*cG6HVly2VQLG|xFFZ#h09%q&Aap>b`1c80WFjwopsAfavjr^&+HE`--3 zD)bCgH~gMq<;Elq%Dt#vTfA`skB>G&vBrI-K4+MSog-v}{{;y@LHl&R) zG8Mq>6@LABC|Q44nOYV#%_r(zVh)3V^GMvib2qHK%)-^hIjj)}MzVVb&0-6LYH0f? z++JD=-y|0P{`!+}nRV37`4L#huzpDxjW}x*IaSnC!X1Jd26I=!$a7e4ggHM8^f%1@ z6Owbi#R7%PK_KZgg3EbF8pPZP?v@kIad9SQP(p}|_h=codU*{F*bt5aIM;B3_kK)Y z$&0_hxX(EXmGpQJW)r@Ubd$q$po!?++{9}iP8FKRG%K(7S)sQ>s3y`h!yR-yYUZp! zEn$*SA{!=AvJ6DcQ))9c@}U*HZ53KfeQyncpjQYsKo@T%)Ex5`F@7riDRVC%+l3o9 z!tHtXy)bz2jyy3?!XohPPHHs#;tSK^OSgt8+Wr`5B@u33S)hgcVdxM7Wk+VPuoNp1 zt`F}pB!m8%sR;GPjG=W7a*8l-0;QD7Z!Ro!Y`GzW=PeNW z=1{J)yuMqY2Zl1rYO!^IT-ltE=sdP&CzvQxA8#M57%R%&pngF^sM;VO@;u! zcfT2m?5M2FFK|QjE?7!#9+_}tDW~j6rD8q1ybP0oO>2uN&5s|4oSv3W!f^gL{N{_V z&}6U{)*x|u{*S6VfIGB2pezkQ78%E0y8$fzlS2k`Fg|J!??c*v;$wfQgCq${OuW0~ z7+U0W@{l}u zq+2|7!j3~X8gyeiPuot?6Lxb}DKbl)v4BgG!96E=CpXrBxzi@T2L{10Tu0ph1Q4`q z&U37fuMt+LVrdjd`F6^UXs1P30R0G)3-H(zWJ#cf*Bc-jK&1ZR<7edGKMIKTL$-cM z_A@V%t=uo%=wbW-mXdbE<&b#c^RIFvK#%sR?2~ktfr*EJ=VX~Sh)t7TeQrjFMT1A;#)v-@`D{FTuuy+hZ{E+!^iiZa9KDpgg|C=4U(TjG%D)@;fJf0@Sk9v z8=z77Et3D0iBMtsw^v4Qz$VO4!9_Rd$vLT_h(JM2gxtRa%J?J%!P-EX9Wv~?9O8nL zObP>MnKX0lh3jE;hx2*w^^jn^YF9f%lAEAXoxnnO317fHd44LqPZ;vGg{APDH|pWf zYJ^rSjs5cUw^{MWLZscFQikvjQn}tLgfYCXyJ7}AtiWjFC3eC#q?5?R6z zZjFaW6e&WLfD~EZ^1Nc-4hmjmv-IuM ze7N5vjAHIU3X4pg5D#x34Rsd`>NVf%Q2_tL@|*A z4ni(p64n49VHn4FIxE>mKIYqV$RJ!OPL*iEkxT>-TzkMJp#RDt;qo@}vos8vMi|W> zvv`#fG8d1V_wQ1Ww2wdT(d2I}4YpmrgR>ZDTCwp^hOJHo>Vm*d5=Is{M$TUQ!)Iy4 z3CZ}^_cHMp7yr3vQT8Xr;i-pFgD#%Z`(jT&gD{?Y7+-LEp2f8iXOqyo_UYi@1kM_n~VpgdltGTsLAjrspFU%iKZ)(rGT@V!K-)mE?3u z6u;S^zuu8WyzU$nOUT;}Slg{rqGKpa+%$$DA7c2dln)b*#j&<{3VUaogw8Fj_;K8q z={g{_gZKadKmbWZK~zBogedS@LoB>?x>)x>$RlqJQIq~zt;33-08v1$zyHOasstgQ zjOc+u<|&g`lvn}Yrnu-j_aeWa1X502vVVs$x)@Fy2F+137{xp@1tPG5vdFkDvO&)J zmi;g_3r{9Y(E59vmDbVJl;LLJ|*?#C@k6qqKBuJ~uFu_#=AW(?f8=1_(}*pB{$Y zfBilQ89XHlagWgM`&=`tw=TYssAzF&pD^R(gvvh_e4hNoQ0suYLmDc@#LOftbZP;F zT@GoOU6>(9A|T-6Z9is>1w#8gh{Z63x$S%RWARc>nI20v^SzJX3g7tV*XgUNhBw}L zBRqsUa}J%Q!D!a6?xn)7L6>-e{3DHkZGF5N%B&sF-&_I&pzWE0WFB_wcxj$0HoHf# zST6lZ10P#G&Qd2Cw~$D9&_bZvSY~7t7?#<{2ZyoKbBrmLc?`oxkH{NdFbRUz!1dOlgZ%;KI5B?^6=M@CwY>OnDi^t^1Pqxm& z|NMUgm`uY0W_FrnPUjY{pUj~QAzYt5iRZG;QP-}DB=`6xo0LTpm&PUmZ- zu>>SM6kc3Bj=2Z8Hbp?JHm`{bim3LdxelKa6MRhFBSm{}3xV2YvF$l50!fQylKqjP z38V!*C2whwYg$Ej=9i4&wT&l?P+CQ5T(w7pfq^)tz2THFdjJD!uZ;?|OPhlYdos#- z=XgCy$M`$p9$~N^XTY$T|51{mjzXAa-G%dZAcx-0y)iDi_0gMAKzNG0)R6(Fd^Q0h ziXe0&vNVpQjZDciQPk8gQgRR;>yZh5eO{1k&HHJN1_V;wrfyh+W!vKbb zA6zh&pN3>wDIv5!{nI}cR#qnBKc~h>gXcIvMY7?_;(Xjo*##d@f^N+~mADTLVgPPI zn&McR3r8XmU8F9*1f64QntuKrs^w58Ui;EFp?)lchmU}4OdvIq;O4q$?h9T3YB|>O z5JF}d;$4~Luw5?F_J<$fH7KaDlxcnS;}{;axM0U82jmy`!>1p;3kF{ffAW9*JqXHt zc_LS!W{aZ7S>4Q$nTTnXpWFXIRI(BDjRp2<(ubt)d{%hE_?!s&Q&%8d5_q z6ZkwtN~Naf4a|SYT0pqywuyC@0wK3eXJaFDVA8PX@+qNgIc$bTCDuXO29P6iG0e1r z-z9m6A40ClHAQ30t4aV)rgQ*@)PL|ge105lMVRPbn_~uW?CtJ_jiYV6p2q_m&GqjJ zWkUqbLWe4Hyk(HY4<5v%KMo^L4Gkq&8~?O5pHB?7?4vY(8y|gzA+PBsgq8b$z%3>E z)lPIJK8}x$6Ape59YMrH4vh{>h#6$sWQnll94m~T#~fykkgCdn?~~oFFgwQ#U}0At zH?H1{YZTsm{XKq?2*UUWFTR?I zwH^z0dZ+@Z(;J_7=P?=+qXCCUahE&z?whQ+*bmFMZiQFLe>Qf%8lF7aXY&ChQK%k! zyVWp>GTyp|_b8LdmTppCA<>5h|MuUnVl~^;na(&51dbevsEcFA6!UtEz&Q0->+)Wt z@dU^1;qd83oegkUSCa%nQ;UZ3&m82Zu_%@yy#m~99&a(}6vg2%lPHI=evbYdhh-S@ zaPecxW0;0I#R#I!d!7Jr43ezpxIgB9*39zUQ@MaNEC|uY{glq0E76luC{FPKh>GYN z3Yo{k%k2{d%cHP*tr~`?L4mRe?MF1u0;ru4=hW-6gk*zEl&LV3#r1=dUZg5!h!ENw zH!t8bioNiRDVSNR{TUe2C5%Lhl86XnhVyrDiVufW8hWV*{=B@roLF65_1m8dEBj>s zril7bS^Pf!GEvhR+EmsG`*bo20_;}s5QI%rRV)yRALXJj6(LBT%2^%Z_T2k20t_KM zEet(9LH9;Pq9EVAHXUB11vz);T`prX+?ZYr!!)=7v4!Fa(DfQi zdp6iGut+|I7vuIs_JZ5cw5A!X>eBcMjMyAITs{a}gjjJGCGNdQSn`nWO* zn_0Gfb*KW2m0Anlg2!wE>{&M~_1I7yl~czWuFG$7>~_ zkbL`>zD7gY9h#=@gu`7_ywVIyx0%W8T0)49mtS_q0E%5HgvZIG{}u2 zp!fs4ttgZ|B}OV|97}=smf_nVe5vfB=yN=W!s{{NtRs}Vgu~nx#F>4ZAcLQxc`*Mt zCK7(Ew;+m0V3z0k?n=0WK19h*;hS|h$0izu zpwK56DBC5RKq-hYKpiEgv84QeaJ0#L@!5n<+uM)%9F!XnWPSZhfL z4OEGy`i~1`Nf33ZN&edZe3tb0pJ;XS`1rU>`)5+65hd%d9lx@;(#>xbcBB;&@AyfmH_!LWx zUdQCm6Le?CE(h#z1q=@ggO%pyIC|FPQ5LPUw;bAViihYBqiY!_aKRHOl0N$iUhemJ zZ5fYt?fOdi=&irwC?Fv2JP8Ygjzf5mHkQW=Ie=2ih&|Ucf@sL(Aq z+`W-GXcP%nF`PkQEMaZYbDajE12qa3GqpM=afaEWCnWz+%vIvJ0mj0*Ua(R%Veb+y!keNY?i9L6v!0{~NWxBdSFIILkSF2hRRkIf zyF)*{OTURl7Co~Z(1!ee?pTsMxRAe>$e@8AEs z@Y>72!ekvdb`+ya7|AjP#1!611kOTh%Bhe@|@ZxjaL#iJcVMP z00uAVjfhopAXx5DU7Edtc*-b15s-zowTIkeCoCbK}KeQjBvMgn-0_o z@fw801Jv7k(|zO(f_@4>;92l3F>H45{r*`TRHs9D`Y`DyGz%z=lazXH=Yk2qZI2IM zpav!2jdh=)_ea(0Jq2(BbfY|WC4Bj-zZ5=y^NZmIN^|GvFTxlaUS?Y4$;l?Iphw{b z(p2R}mP@Vh+yC9~g*&Tj;cx!rd!fvV?>fXtXO5+C?Zb5VaXq8ga7RiK!k;s-vIuh4 zKk(4XiHz9gS74%hi_b!GSv(7)fZEOPEnSXy`=5V&KYVHKN+`YfmGCd{EZ_R-FNP^< z8z27thvD6a?}SYhZe(vJeBtIx+&BdDkRj;A-$^cZ!X6GTq~7bCgwsNs%3N%h!}9Pg zZqQ!XY1|JRfD~O=vX^K_7-CI_h+qabahJU(!_a3&ZcQVcpm2l~SzLb&MLWU+Pfg`v z9H3<&V2Q2!pm)3B-lreZ_W~MYUk6;8fB6?5gb6I)H!nw9Oo()Yej|#zj9qmE(PNb5 z|NCp`DwR~N zXn=Xsd0M}n4Ob^8+Zdus&Tzpa>PP2}^X0s22RjHHbb5wPMDvAUd2Niy5YsRX+ag!^ z4F;Z*1EQ?lj{5JT2SAlnM;)CEHDX!h4= zOxF~%i;Afos9cy?vqMRe8s!$0_MUtywj>VEi_xTwRZL=jdl z5z6>I4j4)V!{&;U%oy7Y-#=Ij2A1@ zTcG1G6Fy~x&n?C;O>GmzVqFV-#?e0Q%PT8k>@{5X5C4MjYC2>=$&Tnb$<7eN;-=j> zb4fK3B^l}GS(ziIP;uw zhE)hgv>1@#HcwrVL;PYshNVq_5>_By{@{n-^O`bL1PGeM80ig%xyA4Vc5Nwr8ou|F z8lVID9NBGyV?Ep>>?L9tn;Hy1x`R@#K?NZM&NH~9fW@uyoFd3m63hC|k9R^5GUu(Y zu$`D$q@$PU+W|hUDnx|QtieHms1q>{+U;u&ohVab&v4#nSo|E}3J#xE1*T;ZZcC`t z`#QeJA?yXvr!=5RZ|w;ktA&{`US{Yb=WT(P%gVK+c+C5a!rrjIB|9Q4+@gJfvA~3h zDpjop9SQ3cw}(Oa(lgbmQ@LNqD8M!V^OGFc$1qKWQQ(~;4ID|X0|0`@Zvrlfu9+&7 zk<~az19@?tvS5-qDen$)iz0LW6+JJ-;4RoGcOKl0_kn3X{gr(XVS6PN|6tPpb3-zc zo%jbrvIHSne3Slvc!A1;hXG9i8MDXW0218m<#M?8_%wWY_wDedul*wJ2jKM_e2Lh2 z2%`@&oA=;Z z5o*GQwm#FM(tJYyy2+iq8@vij-OFYLEwWLt?m|pbmA0r|?%Ay4vXh z%z`Oc0JN5HUCzjdWDp24Bv1_D3gyXhU3v0OH<8Jlb{2z(o^1D1t{)=iBf+Nd&Jh+# z@};9<{aySE|GCf&#R%!{J)%O$n|biyLBGm>@h86MwkTSc`H)G_6mAVY7__r;l5J*! z8Pq%8C(qipwuv9E;W3L?hZ8So2(SW77@1+54smyl_;L`6`g1HF{Q?QyDKwW&`ZwBi z@6i|;1__-~)H^0PNla@P%{UbifyWZPG(SrWPgqE`7F)yoUMwxi;sVD7|Am{tc9@0P zP-1=EkMDjMZm|z$6twO>N0>a=Air2b2)F@o+7eiub4DBG$u*p(mEiNE2%sq7EnHv@ zhVaLTH-S(ZN1rjJzD);d5#{R)P=y8>O_OjZ*h#szzsqp*5ftq(O!1zjh3CTe_83CJ zScDHA-4EM@ka-ZHgj5vve0ES=sT@|y9fx}5%B8Texf9j^NHS2)he=w0?VH~U)4#bKwy)B!6_X@TxyEQ$zz z0hw_utnJBhZ6bHa0&*H<5hY6#4pynPoO9ner1&?N-?kXA5kUrwgO9kkhCn|&ax&YPBdx)OtIQj}>^O#Fv;|nid5PSHY!l4Mo2Xfg! zK($QU6y3(18-?#?ND(pe1Q&xu5}3l#NrH7EUiPe%xgcq@z6knsiCRhf5%aXTAsL!} zI`EUquyV&q2pRQ;Afr&!0-W;UN`o@>9pm2`T&<(Qjac~~#5+W{!L${(a_!tlV7SrQ z6Pm$ZS_-pN#s^>^MXDP^O*%jO)C&YB9$}3V@ zUaS0^9v_D%AY_S2yM}<@wMDNm3?}C;c$Fo7QYEa$V3-G;VFYRrR=po}5UA?uld!ya zGfdEFX$~}mcaBYSoU?gQ8rXM$;io19O>e2 zp#*|I@wV`H8VCtT>*Po5_Cvv8Irv&~8z=5GP`rv;l94w_pE(Sw9x%o6w@@CZ?g&e7 zY;4DYBU}cQu50g?((v>l0CxHEWklh#Uq4ltr_bWG{TxQE@=Z!-C11gkN%B_W@GJw; z(hP-=UeN*_Y2$uC&w($2RS}3m;&~$07)$1H*^|r;n}vD&=->Q#m`zWGc?zH27B z4J^(gbcPX_toDj$aLb%#ND=PkDO8Gr)Ih3+veO&^R+Fn{#oOC$*kHm~a%2w5>_GH7 zVcF~}HxXd05&aZrRMjEZ^Ztpj0a-K6dlukQQH22~M`_71S|q2|W%QU)ppg_4M5!MR z;mDvM=o5Dfft*}mkU2avDdrSvOM?``u-xv5cV?D7J!y)aDd1i^4ozM%6zrUabM_AL zGTw!ymAsh~^nKT3Zpup7CnvJSwo1)ufN;h2=bm2@A&_!HfJ10=N)AS|)%#BnQnoBF zPSJim#g#4+@}ThK5MI+V*F#%x5?F+?)TJx2%ODU1*NVMEzs*0~b1B{3-|J;;2X8R2 zBhE=iGFRxs>ihiD% zhhZS);|=1)5*W}nd1nJ+r!^Y_q*$eQ5Tn+_wcR3JhF*0HM1?w?GZr#gj1&ddCM^~v z3z5=v@KV~K7BxXm3wfbTjSO`SZ3qip2If7LK_Q3DX21&5dqzeH|Dek}*!?M=`7@8W zAIAMi()%xFjVu3A1fD942|vH|4~YxnrJ5zI4ArQIPoHpMun9bago}ItXgjpoGUf{h z(C8d_fXi!!xO;;jP%|$-ANIlFUG8c?apfytV?Ht`@V9S;#uBkE%|C#IxNrm;YrO>w zX|}Wr0n>evO?v&05x_dufrXZ_0Vtv)Sd&wbpdxUx?apz9;1EdEM|Z=^@SDJSmjC^_6ahWcYz~vd9>0hkjWW>d=0K2Wizayr=MEy@UPBaEkHH!{YYPf% ztGy9kdg)cpV=%n^*4rEil)A+rNr5!p zQI?vc^pxwTp%@)5qD&AWSH*+`IE|d*yO?Piq;kAym&P)!F{QBZkQ0f=O@jB? zLp}Bu_8&+$K8E$m7r)@=4O|QtqD%NR4wz8FDrN``4><>qesPe+v!E_RSgAJ3o#7_8 z?Rl|sM-8Hh6-0(XcKDC7MV_FLv{fFiONKb!4OiaWBtnraGDh`2bIy;=t`=vEN0arb9P+1New9@ahis zbK5``qm@oEc8SkZEd)EvZJKzReNa=MTLy6xJ8p1N5rRp#@qg9YkT3VH?I+9=ELuP=Xb-K zufH4qhyU?^MF2D59?fGBuHmL#csstT7?2RTEP0TII4y?5G^OY%jK>^*h;G}?qkuZMd;O%L*dg;?{N-6=Ai>-)osSGMo5u?eMD132F9ST)(i4scXY-mhU zc<^W)_?V%KqcD;gZ&fGE%pos1awyS5!IpDuc0E*g?5!>nc5O!7!6I4y3ZiFr^Dk zx%!W8r;>o3tg=KQTV7sHtgfzh%n{t<;eo)DkE$280=kZ;#XAXu(JP>IkwBoQ2k z=HS61dGXQvszp~iL|o!0a^rgsE*RbdS>+*8)BC-`t0MVh604m+$sVq4#+HFB7Q}*N zi_X5E0%eAEcEOWlEm2%Ohgz}t?XQF^+%i{K9KlhBM44FE zfPi>>uDtFLwv(C34uR7$~H1Z%yb`CIeV|fJ~CsdR!#QQdwn~(;wKB3y* zI6IE(NL;HfGdW`}!qk^zyjwbhl5qTXx#qct*smD=vGg8+$J6kc&V7~ljfqOLwzeKFzp?~cG>K9Gv+|NG`Nty$uDuJI*1-ywxUmZ( z%mQ|)5iT+V1lxi@C%jmtXy-$6oK%Ls;6MA}Prv6I@;3i*!T>kliK27?*x3f z3IblHm0Dr05E|;8jv%CVi4Y`5o}+A0Q1K@6$Z8N#OGTh*EWRjI8IROq=9q|`iq>IK zECeb3PX5DnY{>!uz3dQvw-};WA`-|!%sT^6p@PIQS>GW~A*zvwCZJ+cZ%asxHi`kx z;hgX)jmK2M+MH*WyeHv6Mr5FdA<)j`K+bmdXtR*S%eD4?j)2O#2<-G|+Y1V0N^DE+ z>_cjd4^xw8LNcZ9XLA^!<@m&B|0BI$x{ObrnBYTj$w>swq1;D=Wo0_)Cb&pRZj!G5 z3opDBZcWccKnJ{}~XwGZ+AimoJ5t>sPUYK#ExEFI|2qY*Qfn+>IOIz17w5 z@e@`qY;K3v?b~!`;t22{GMAGGLW-IPRZU`XLKkk7%4v8etSo9~?}cMy3vkFf!09oY zz|Bi>uN?^i(rh z%+ytm{1P;kZ89?~H#tTN6l{rRy3M^O@%_rIn6SC6#T>OZ0E`n(UHj+)ry?y4EfVuK z*9kX@Y;f+}3#l`j5pzp{0s_vM!<;dQv4Rm+7LTb7obp*j#5|XAN<%Zeg$xOcohT(7 zMB(wp`6-S=k|_29R>moL6+lT}{Cbx+UggjJW5RD(#&6=?!3M_%3fX&|Zpg<4QV_rY z>^}_cBeBz4R8F~Akoopj*Xg_*3E%m>Uk)$NFNe#_1#VM_+&kQ60Vq3TEQ)a>o!sH7 zw8;rAygeKJkM6yD-`m9F!di&x7^h=mxe;3Ao|X0ci(}`j$80!dDo93yAo&;u!baS9 z1<5`|#NVYj^7IPCXx%M2`E9)ox}79#;I zW*y7xaEl~n)HV!r73T{$5;o1eV+)z%)TulM2cSzSIR>gefp=D;^`T1JK?};f*TH*| zv4+9>8M=ACBTRTHaUN1yd=C%YK6=OaI&8zKs3km$X-a|Giq9z+vhuyd-gB^v2U%NU zH|wnJ-uzr;Y1P{LdqgPPc%sL=26hLbS{f#Rv!64-$AJ4dMF+-1@c~H`ahsf&VV=Mw ztJY`2(&829PZKB&O6fitm?U{}9*^INrqhhywQF^cHtafi@Q_)J~?xE>XcRgkSpR z7sJ^LFNY%%ecM)TQT`$xr9@X_9ZQ+zCc8{D4u^{$&AnGBJ=XZoU-lF^e%Qq^YHwY7 z>T2x%^SyEX=k{LZ&nCk0l?V&hLd1snwTlby5GoB4cjJCwEGNPr{@#BSZoqTvS#9E9 z6xpr8S~h7LR;bY+!X@Hv!Ul<-1H|_hyqsfZSkSNth#)uV=&Z{Cpdi;0Y9+}mFm-Xc z@&89=2Pz{QP(=_-wQX#Ub2-1rS=$ zM>y_;Ba5`Yar#byeV7!1X|8qXcZUM#B#mun9LF&V?|O)|!cIPRD6fv~Y=)X=)M4~U zZh&^Y>o`L`#wJHma@scVVpi637!%ncEui>Qe&6PxwE>%`pQNe(95M^7-h{_UJ5o|JN;YaVh!|S<8Pi4^8CA-VZ%TZ}$D?bx?Jq^jChf$k!K|C1` ztk}^3`B_MoI5}=4>LhGVL3H#`iK_3^2rDe0byI{6gLs#jB~BC(aZN!Tr2^}SY9Q_% zw@Qr&QzMTi81bRU@ca02yyFgbIegpCrnT^DpsD6Q+`Jt;XmFt z`a7N^&B8HEuCp_7SI`Kj`C26w$Ag^j#5~OzURmKy-Yd->$FVsS7segw0H>_S;Db!= zJzEp~NY>oo`zVym?xb*xW^pHaYz%jP;%5${`sg(OZ9nOn) zN6BSN&&KQRf+MYdgQ8v*NyaFNXB*xvMtfWrc0gOthw1gY8bBTA~S=Ye;%kyg<5yhmsb5e(GU(LVU6> zz#UobOk7~n{GNB?!GxIZ!pw3U08yfi)D_%iAjmGQsQp0)T5EThbSM~EpLRSFcbyY- z3=$y(EzUk%UlABi-Fx`ekMIA}((@x1!?g;({wv=OZ@x*FBK#k%3F5@p&(0{m3d`H` zKs*CwbdpF0l1*_s)b>Hs1|cHu z5+)-Qco1|6;lQY+^%!grV^I0%$UM%Aa0WR(?;J-n9JWPU>Lal2(_>Me3Y&!^R<%lM^W?V0xH#RaGLrNq5 z0eEz6JWvNOUPhS>3F|0{%XN40Ryjhn(UB?YG5fTeQ%58hAar)>h3>QTq{n^4LKgUYHNuBRDKYuyQ&CFv}!Q-h`8_8Ht zIgo;5jYO`NA()V^%CE)pi1Y<9Um|W#L3A`+)B}lj*;?!TW%+bFaH{G92s(m9V<@M0 zMiS2UG&U8FU81RrejIK!=VGCjho`UNcnpSQTmYF0Drl+i%3S)aw zk_>{CfqHZ$oE+FrY{M4=F7SM`!Z4~x4i&{uE?k$s!Wta68oMdS8HjPtknl80JU_F< z?ZPmy#w0OWegXuRv*pr(#z7mJoyM~evehs!LgxgSkULpnm>-K#hqDaE@jmPHXITq! zlI9x>r?fE7h;BrPqBm^i*deTI|2YqDlMi$wp(Z`8^7non|M1KU;RxaG)qbQZA|8fW zR-#>QWL&6ac1fr^9xW2t86fMx5M9`Idb$VM+1cnK&#uZ96~~+4&zM0hcM|OvXP;q$ z<_xpGoMr68BvfXInJ9Ycv} zMT?I3D@;hduh)BN6-z*}{xjjXu3<%9tE|UKSP!6qJPn$rbxv?Sa@>p@p2~Vq4y#`T z9_`SJ(ZrLf08Yy}qBh`A!pS8CK-vg72{nS)Ktz$#^G6D>J^Y@}l*nnqYynXgK?iDn zp4{gP-2U$J986!?ovbhFdSah`{?f2sSklw^9!e zPlu6luPM7^h9>czK(MebZ1Gh&>h!v+p!jHxjcdbeg=?Ew?c*ahc#+F&;q5nA4QORu zBcsKTXlp^!$TH7du_5??;}fHCc;P^nPF7auu>lH$il^4VFiB^)JPp4KDia}R0|rL- zoN$S2QR8|US{JBq8Si`jvsC=MaPq45RFOmGP!7Y>xDq86Jh`_ZgD%3V;1M0VVgXjT zT*kpUN;Om}GTMr*cCZ5q01mfrUFNz|l`nI1dGy)J{k)ypKbTtS3IAy?3#sw3Sg;!9nkXhsxZ<9yK*J~A#tLNKQ%C&Ej&UkmTP z^EwxGoQtpd^@9c=L6v8=e71LGLwu;bFF;BDJ}g z(F+*r@Sa56{LyN%ihzicM`;1Qqxy+6JjXtXqe^q z_s=m_qx2~W3Fna~8@d`OhdY3VVK*1>Mo-r7A^ZqD@VD`e{VNtRTYR2Ng175Wm}QoY zFt%IhtSO}!be{%MD|)?%m@1SKiWnc?*K6wBh!!=TOo^$O7_m+lw2$}pVWq$KUGKl7 zB}5Bj(TP0!dnMk7<^QCJK<~$=|Bc$!3-7R6y!`-4pBC2{$1RF}<}q1>AVY^;FBS)$ zrEXv$&9e|_R8m3(f8B)AdbY-um*b7{NCj^Pm=4DKtN6Y;|jZNZ&fNxy+HVpt%S{W z=qb=|&S~5mgbKpq8wRA`3-=$chO5`-u?g_#n4jPt&LU`1lOZ6sUmUWlz7Bn79C}a% zYaEmB#1UbcMNh(PM?n!@OQf~;#DRXIX`?*f<~ze{bDRtY(;}(i>XAiTj!rw)ruEmt z<{>dxLpl%nP8;%P!3Ssf-eDX7ArwmmP8ujwhEV?;1ke$= zRp9Ro`Jo-LdGe$pa~!G;MknUn+}~t07rjVBw1=eWmm+fLFosGFpreVC19%VeNRh=f zUb0SvaeVv)BS?W4kYVk9FF)_|B{_|!k3OgJB3<$3JVnXkC>ew|uDh_~^4`6BzA)aw zivlR>LP*B^oh~;qkA<>aVykMFLSB;!pow#yeu^^`!|y%WSQY1aR$^6-K{^x{=6hk8 zt~5RnWFcIhz#;X7M#RNONgSTPFU`)xpRI5k7Fub4_M!DNQC(V`LNWLTYZ)yx@1u26 zp(6bRWXwvjQ$}2h1~S2#ODL6APdM$G`r^vSu z4yR7`U|iy0gv$Zj1?DbS*4Rx`dBj{Y&eh3|d=&B+uHL?k!aTqN1L4Y*ieahhY4VFz z)Pz z#+HX1R(@=RWEu}Vz`*qVeb@F8LZxZm;v)x`QS7k2V?2SNjWw$2Nz5Y(F;4YeOYfu~ zmd&#vKt2~-FG9<$Cu=cO%OTtvk~-eWA$^k*i{vVVT^QFcaIeCdHB`g6x@J)J!2ys| zwR#*5X*(zZJKN>yawfYoMc}G%+&0*IGeF*U!e`qXmAg60NUHl>FTygI<_W^~vGR59 z74sS_$^z@VPJMgpm}WeND8lHju~j0E2OXpCBVss257)>bH5p0`?l;}J-3<@k*zL2G zpXM-82zvifEuIRScj(zi*Q&nCA~l9boEl^6sE>5IME7TzTZ_P8S-3;U5)^VSwu!O? z#8Z~^w6F+@o%xMIXC1?jG*75gUA?lhf)H~f=z27CQ!iDMo}cOcY)Iro2+)3YFrx6w zzx*pCktY%Ij*k$|?j(QO1ELF_999O4)X z10)K>YhzMUtAy8Zlx-Jl4G6%I&{bx z3giU^@}HfJ4c7ZTB-x(kT9&cG73d`UtX!ns8dkb6Yz9TK4rSZ2;jf_`R)G7+v7#JY zlo&GWkxkBvc&q{l784&aI9!`F2w8z}53g5dTS6u|K?r7l410kHpH2ynhsnVT%)NHd zMHjYrAw3>0&psdKr>|p(Wm$}JU-E!Y%T(?ch!92?B)>@HGR*`a;C|j~D7VZ}jZ+WQ z(~qMtBjnT=c8t3vk0A=`Ws2=ha+;IMu9x;%VTwO5FE9Jm>HYB@@NIlf&zx%8xm(}; z?sxr{=#wwwE1vleF@Cp>MavKeiy#@^q-YQ_?l&}RF$u(dBDNbVU~<0<%TyLGIQJgw zKo|rea^>oBxbwk}`Mv0i53Q_^o}$F}=ch3$uWhV%7Ib6f`i=0t@BO=o{Yw}B?18{> zGkuJV!bg()cTt%>L-1RmcQ_AD5-&*DpoNO2p644{<$$}*VI(k0hl%rnv1k%A4VB_L z23{EJH2k**H(STSKp;3dtZSOkB^m^rn|W4&5lT%ydl1Vx&fb}G!VQ1+UG&N$EUjI< z#$=aI9^yd&2n-v=>&OE{$h=Ie zObqH69>nWwk-pDXCWndQ_)OBTU_K4W{9{6eks9;N5DaHB@x&PC+3kfT;NZkP77L1YQ!Yzd4Euq(^Pyog^lzaIRA5Ae0J%qf3!>j*Ed9 z)qRYx#YTBv82|=W5|UetPK|`+=O$5@PY?y!ie9^uK~? zR10?>exLD6pN8YJ?NDR}8A%M`55qsK4bi8c;hazK@&my44miJ*B?JMn%`rrQ7uH z&RPn+DwP+!GNX$!W2|g+h=*RzDLm}*8D%y#?G4VQ1As=pc6mSgEa4M+AMD&cIobue zo1zzI2ZLKDJY(JsKig7#iX7>QPTbeYD!wJk8=FtoqIVxdNehrWkD)4M>}2nQ(rIg`krv{te)w* zctL*%#>J0*={nR8PL484i!$gBU6SZa6#M~B*kYX(;0C78_}4rk!i-$J0+trn!-eg| z{&6Y{H);q-@Aiw&hd=qZe}Y@5w!lT}`Ir82p@eD#4;iU0DD4pXMU;o%iR;U|>chwq z1>K98f=Xf{Dp^tMpT_GYIKC)5*88*Fn3MvotrFV>c%sV)v=}-o|og; zbfhAEDURF5Df{Ey-0aFZo)JICq1?vKUBXlc4;t%B0XjXVqR#Ug43YDAE$*F@%jNmp z7Qf5W_s;elgsOLWqZ#CVIut>5g$Wd2Br=s84O1)WaR2D9nHBJWf9ohC$3RE}03McS zAhj~bY=HWP7PozV818NUb-1_pHwerm=P9}*6^3dzUe3Ir%Dt@YQo)DDpQH$3fi(w9 zAc5lL$u}~<`!X34@Xun83n9$_5VwkUOd@|wXeV8$2}{{~JV3*q9@3(1tIGX@2IK4p zSGgZBWt7wj%#-MX{O$*tIB z&^%__6(~YCU`-5Be=6a%nxJu0DE%I76m@bR>KdU=p0~^Pxv}OHbJV7ylE-;%@X+!w z8ZwjwgvjqakQ&2-M7`H6+53_Ic6A;yU!cZ#gLvc56h=?tA0jozkj#ffwAc?5e+nQa zGYN-Mx4GyhyE2y@6d{o^i+5THd2C?5#dCcYV-tevvn z@9(+R6I9g?8Cb#uea<~Ye@cP%5J~!!+6bHdP3M9ph(wc#JvBO39r7XnD~&-B%60K8 zDjGd|g;86zQ;ZEH&CwAcUFRT!xD8Na0Tx0)FQH^Y))*${H8dNnLSc%(x!MV{unTC9 z%ack7yso=paT4_Nm|+`|AW`O#U!mk;U>c@5i{ zIi@2T%0$3K#kw&Jrse!(BdqQ|2sJ1((g%%54Kp3vcnphJfJZb*4wff+K-hAQm$g5B z*u5_NEr-V{(koxV>y&6p%X06=#~J&|@4Il{g!@g-XPK|ynhmd)#;=2NDqv&ItQH7> zZLHAO@eu7KV|jtN4dn+2X?Y06+jqL_t(ao5ibCn~y_y~W+l%}vWKoge(*2mI(!f97EVf3N^#K%2keKaPs^529rBgj|gN7Y(Vf0Qe}; zB)-(jiMAFI^b99aqFCvTY=VI!U#J*+MX0bBh@;EU>to15T_CmrBe}>x4C!vaa4Wp^ z(>GBLgpA}lzStZItKWaPN5p=VE|yNOW^C)DN3H2UtM@ev8z4*AAUbC*5-Z%?XmhCq z*1mwU#+-zUFA67|tA&#)V?I--W765ZdQ9^OdnTg7^K)E-4g74AoGrSt0R#_JL^)MG zYQ8W!y)}ephNXJlxhV!_Fxwbg0vwE>mADRsa16|4@JBC?*yJZKXq$QmH1Bw9by_I! zW8CO2!k>r}Ba7oO2iTNc8?1#7H-F65HYS_YcGyvQHO%2{mgX)aq_7C6vafA^5bo~% z0OMtsB(N}v?-^*I_n_HAsQJ2gydUm9dYzeJYz$uhW_az|KVksmVie5w*#V4*{cz{; zParpL@)~mx5G~HDL`gw_q|C(4Gp4_+gRsR74M5ON?&{LMctWF@BdzK!CS8(h?H~`E zhqQ51{m*3qLEybb9v`yw;oS#t{8#`yN9Y7=`G8O<2hp+uQ+sxLh0t-2V`Nz_#o9({ z7YNL>6^Ij1!8gElM6aJXo3}-#xDm8YNOD zB!u07-1?~1s-XCBmO@mF<>lpsg-ajkhWUN`{mN7GPVd?3eIbs&LmO7c!2qD+_S|F@3G;%$Lxt2vo?kXSC zQxX{p?pgF$o1kgVPczgztO0o=R7L3EB7iEa1=t<}NXQYwF3;Bxn3rKVc%57+Kf~DllxDH&5z1NO zIub^$?cKquGDRm-f%3y*s=c>D_ZsKB&j54kR(4E2*m*CkAH0u3$@kLo0`bBwZ!&4r zNiX~4FaOK;Uk|^%_?_@a|G^(HMRdiE6TB{cGF-zXsGr7aqHsNYboXx=e??dUN;N-u zBjz3r6fu`4yh#Ds(w7rMGOFx{So+fj=R-(tolDZ>0A45yc;j#i@9`-)P&$L5#oIwD z3fFHAMN0lDwUsVy0a?(jG!XGH^kgbfH_R%0$kj~KBAm%WR%*k=D^=P+%KHGRG>2?qPsNhM=WGisUF_o9)&%zK04nnH$GR=z~#s zbo5Txg=BfoP;%kY6RzprP9m&t?}w`ktUn}?pJ0*EFmtg7fw?#7Y5&9L{~-M1Z~y0E zwmi>J^Hu0K77ZEPSKZ>A2o(WKY7Fi^IfhtEKfm>;Vvf*<&^1l?mnIkT{&e7zO_T3( zyO}gP5*|HBGhGMYQVfKL>={$1M_P_@#vt{fXfkBIo!XbA}W8Im$Ar4gYvv(PE*B!so}D5+^E~ z06C8Ni3URtk2;Kk^EM-{MyH|KP*~j9Cy&6RF*o_i z23yKj>tTKGBwU+WVmb~(%DE4hX0A~0Ae04MXkz)zt85FtcIkGwwD=0=O6>xHZxFhi z9IeAb$c4KbKjHJaeryOhXux^nnpPR6Vu$TI+pia=Nwz6|K4c5F*QrFIQ;=f-9$f*M zxOQ_PZ12bhcQ2--O3_<@4dkG~g)xBG++#lvT)Ih$j?PyWqA%y?Ik#Z|0#Ps4&eM)D zfTzi%XE40XXl8)Q0g7HMPJoVKbWz$7a=o!J==)3os<&Y)ldDL$ym|E%n(GLqLDZI( zVc1hkYEesS09Z6=kG4R31WB|1AX-xNp4MUbHs%EuE-xZ4|NdDW=8ymQk2#S<;v3)i z2EUIo`xGUcCBZ`mVUCEZAb3cUydH6E3wQFvOvsEt?+ZmL7 z83!tX11wr3!4m#N+H}<^y@Ph297HdcjEOaC;0T*+4fe7blCj4#Dw|hA#mf)^31(>h z?Rod1%GUi16k3!^u)ti!`b3KBQ$q;PNw^*Cm&%YofIN+qmJzgf5PVp^+>#MO*GtzI zqr&7!gzf#X*ee@A>p285)HM-@J0$Z*Pr~Hri&$prMT%^!RZ&C|0S1Jr|zryc;TeZ-keweiqcG2LFBqgQ6`G$+b&bi=h}QQ@M+gXrdrh z0DvMabSYL+YTT9De^`f!xAj8)`>?Wd;=T3J_b~A%U5|(WuyW$wy?cp1qzqaV|89ch zx@+4!-9RgU3cvzuPBKjFEtNgT!59*yNO0{{K#w?SEIfMVRQ47Wb+LYnf(b4}i8$4V zNptiscnnb~!wxg4isvJ?4)DA#$>SMJR4E#UQpbjm$a9UwLqmirHauBq zOn zhUf>mhn~(ZQiVk$VGd#=-Dw*tx(8(9iMLB}L9%>)%7KDh6!&+|&QFFBM$jH%mGd;_ zxl^T0EPu|;A0m`W1MjBJ$FRWHP;ioAypEyY=HdNVkW2uF4Ud3k6%iT=hc8}zo_d6~ z!78f;$5F~AjDS776`VoX9H$tQLBgZvNe#u8&QItE;<<;wkCx#X0=^tG6x>Z?lf#ag z1x1TAeb%5%FTku81$9O<&^n~u#pUNPV8{&j2Cg%?a1oGWhigd;fs#5UbacFcH(iMB zAr99-0=Nce%=o5;Mq7f^quxqCoB9at2qjB+bY<4DyUy8mEN}@W8iBKRNMl`u$_>k+NcM;rD7F!5!X zQ`$?3%NW!>k9N^zh>#~~ATkLinC4l=$)&hZRI0tjw;V!krC87-S<1M&s6=?BIlt#sJ_lXt#6dvp1x^t`) zGO=iOn>r-DOK8&~*>)3GCv4(15eu56npo%TP>L?psqppR`f~WU|Jz%HbI?dI0=CvV zJewQCF;b+XC9q9`T|XnCZZVn&Av%X*(`FBkqgr?NcH-X5-~Zy*4o>_VKu|w;yv*?XM|R5uAiaVgNIyC z0E8m>RGJyw8I-i%CVZvVm7px)=-38K?bwCOYZEBtB)vjK1|e-T8{nh~O-5y4_8vAi zD#g0fyCy^G)XB@?gH4d2DX=!TwsmOVctD9Eq>>#Q z=`Wnm)XZ$SbZLdZdGdr}^wZlV2%N?5Py#Fj5{Vb&LgA6BgbfFW%%t+4jYlMVl0hvr zHmDoaQQ!!BbCcql2NKFE^pF;zmWg2vc-Q4hk~<6JW7;EW?~WU_BT)dv_GSOIh{Jsk z0SdQU+0|HvC2L~tK#Pgdm2h?O)i74L8VQ1vBUb?fAQQ45r9)`zU~>CS&^`ng565rL z`MHZk){p66q-CRmmpGR(j#3TNbCSXeoHF#n9+EW1V0+_1`1qrD02MajhfNbIo4c@X z0uOO|*a~+(e8emeP^<1}*knz5IG+yh-#H+xLm(+^)=`2EXoQ13WFhC1k~0fomg{~% z&rO<^hjm`AUfY@4u4mIclYg+lgP+kiaHaCv2v z?b!@!A*VE)IfYnz2#M3kMIxu9R%#dKeXUfE}H*n?srL?C>IBHTqBCD=Bz zh0iFaHED3l5&ydAlQ5qe2Gk5(q;9gy36>f4nW8noM?7JLC5B>teeZJ9R4h>y zY&IT2u_dI_L0X^`v4ZQg4`sX|DHCsSjF9)HBys}?<4pW}L$?t)j{gMVl5y+%>Oc*r z{74IyzMWKbY5UroNw%ALKkVN?0%IM*qN(g%!$pUplQzT}kIyl*NRp6tK)B>}wFD82 zn>p`uEVmOKlacm;rR5`L>E#$qKH!`Hc0mxCMjTU4bE+oBM!>@zHHVBt$__*2IX?<@ zHo8?QibiCQV;aUly|8ed>q{~X&`>$w3}-CxZ8N}6_HhHjS(u|slWsB>+j?zsDC_Lx zQaGF?l;$3-Z$gh@q-%*#^3%spP(q4)6$*+ty0*gyVOKm{Wy`?+cKFsezRda4sJ2rH zci(>yMyFXPK1O>sEzxHTj<;7QK_gq4HSUA3g>yxRRWPuF*~Y07oHRUl1-g!XJ1*Ew zlV^;vQvQtM>>=|GG>8ru;neW>askOJ8yH6n_9;obgEclc|AvLJ*Z4c$4MlZtkK>iP zERU_>Wu*Tb4Hbqc>{9FMQZ%*xRH@U8gOX27&4qGyj?dcVZ@p2m{P6ERE~qj7{Q98{!LWCNz5v+UZqN$n*|Ku9it+vEXEh2Ttqy) z4uwZ}L3+>uNrT`HiQRC3-)u@HJ>SAtmlDrH!mm=Zt^d!4rR`4=UKo~i8q5fAAa*hz^tt1vvCY1dQ1d&P+#&nU_$$2xl zgBdUkvl(O32INR3XwGB%ST4DUCk6n3anNY)B99O)DW0y8zujMBp%+s@Cop!KAbW#^ zmKkKh&1U0c6M#DyVR(2KbIEvZ&%^Lhaq^`R&@+Y0DF6Pg?_mtb68!Ub2^9v5{50u@ zE`a!i!~~naT;XgFj3^T;Zz%k5ae0JLpd4vKLV$D3fS3j8s<3EQ*yZ2>%#9F@T*FMan@~w%q@`mnwH)V@8*2q61Av1A2H7M zuf89aN!CxOMI1m*OfaZUPiWs!oqr-kj&dzJ=!}AU!{$F zb8|O*y1fdQZ4nnEhIsIU_+oM*+wA+s4{sxKuXZ8KTnN=>0V( z!{ge^zsFc%>r3*-h6q=QW#hJh?HwxlWXa}O*(?Slwa-O{PsdcEVR~0=7_<&&VKz_R z8{3>QI)-P;Qi2+k?b7>|Jt#0I43}KuIT#GW(N+~>N>5J~uA3l=Eey6cC>znmbJvBH zB^vYX&y0$_NcSe6300p>*sL|6RYujC>=na3bh7^fHN z9gsGfnXtIT;%Z0_RpWU|FkVX*?FcOZdLj#n7NN?tvpO`}&Aie=Os10@cpN~%C!Jue zO~O@pSqOs8&NL>)k7$&DL2OsX6Cm@1NKU5*aNzmUZQP{ANn-h!@ylmQy+N<}$MrFU zL(se_XDCkL4uyp4tWN1?Hk4 z32@R796l?H@v!jNpvE&u9A>?$jUhX;ID}Ce$CAr$`{=oMHIXl&oEe=9 zcuuhNmj_jhXt|?eDEq6ctNuPdE*wex{#g$bxnvY+qK5%i zzIb}*g3bye#H8PXR)Y^SSJzD|TneV@ClmGvyggD)a4!jl#^s5v6BO-a$DUI=Q23a}kkSPL=S1oRZjkPhKAI*sXkw8=@=<1 z)Ey6=w`}p*zKc$5lEB!Fms@p=W%CE zh7jn4iJ#<>+>_;%IgSU#gs)Ym(M~vDSk``*4qoPy#}7k+&BsS5z|ysaP(pzoKU&2b zBC62h&8Z56n6JP8lW_THh7}?Vr=P+*LxVY>-vkXM%ytMk5dRL0;hArQ&t1KZA`FK| zPjkuoT| zd&Rvho~OseSI^B@xy!L>4HF1L3Ty2y$v9?;9Ir;(?Y;Y}eBvXlFL67*S4%DY*@X#k zM$IKfxF`x&rS5SG`LauqPw!yya}YExIRZ<<5RkBOe4O5P;`(iBDjvTUJ&BNwkAYy0 zkCJ%9r{euB8a6Rrwoey^$Q7KRX-x?wJ%oofP6%71-MIrjW_*$WAU4{_Zcs|Ni5D9-g1YAP?Vy-tw5i7|S%hG1P(qBC-(Lv|2_g+= z*IH5C+qWNqIF^v6>=*gzBvgFy;)(cg4bgyLIGDIMn<5eybfn8>Yin=kWy8O zWS$8)(gj+%3(Oh~!?8m0)oiL^(N~t-i?NZURGZ};GXuvYpG_cN?F5 z1*r9Bzx+J?%m4X*1tOgRQ4>gEZCnS12BGK(UT}Ninvo%I(W(9dt7q(GL02B39R*z) z93_UB8>O~~xCs8%H7Xs4 zICLjiqY)_j+nZZhgcYnfxFmw4pS6+{vW2P52YPf>j|I^iv z)7G=i^iRL{U!~uE^?UHhum(Ct+oSJE7I(A?m< z_t|GX3terSo?p9u4e>Zf@M+p!9>v-%!0f)w+K#24{bZR#01C{pc%JEhQEkZ|lBF&P zj3*@?mjWYveEB;w{eB;v%=vxhIrq{OVW3jSxMF8$BU=+W_i&P!rivfS`N3pEu*6-k zfrIFiS#N7X8nATj$mnS47N)XKL<)=3G6vvwELmk``3IW8?^)e63EDEs=1WacOZ(7r z_>kTb2~HLT!@wV$bVXxr`URlwc}Ktq4v7R$hlFa~q}WVMP=Sa`F;*Q*SD;l`73$zx zs|V$UP0=`TjBfA;AV}7t`#HQAYCg~`!RrnYbr%84Aw=h7=?_SX)nRA1xcLTtww6>> z&-x1m2U8LVmTjLn!6*@Ya14USx|~*@JxWj4?&CUd1@M6fgC&<*0&4(4J41Mei<1Pyd@dlt zE`y7sVjgymkOb>M)c~fPypRx%QenxP*P_E0krFaKXBC z!=IXQElHjN6`!)lqo-HXfAi1&$Mh1}ds)PmW|+prk>sClDnGLh&UI;{2#dJlZ{PlA z`WOG%f0_RIxBpxIwuzI9TSqIX3~_0J&kfEV-oYZM;5XjD%9ai&Z|M`3qlq zOWwVl4|AE5gf{jIh8pAVyVKJ{Av98D%qd7FJV8?raWlh6 ztRveKs^s)WtW>1 zPL!q0{toXLnZP~dx@;Nif$59uHueS`BAb7~0vB-gY-HHRukIr7;{WGtycuaNt^Bt` z1W44)wGm;HFv_w7oGB1t-MPe6d05A|JL_93$PrL8pWg>t!VaPryqEsB?xv*x=B}(k zStkZ~^Q#aKX&Yn^UI(U+m<2RVfM6ViD~n&=qGtbu{$smny1DU5tP)%9d@$1PqRqpYOPy;3u?u!MdANJ2?j|IY^z z=agutR7|t^>9oF9!^@ylW2k}>VUCQ}mAyA@@X9OK(@%c%k%}&ZH`Ue3T-Ni8kooU# z%EQDjF+HBe5FQK2R##U;vRLbQ5W;X+teE51bS*^j5WE2s4(eigxTH)2ePRv#pS-UI zH{``@k?TjB^t-BXNO37>j(xDRpH?0}xQr@UkhVxN{~M-6%7^xZ)f_VgNoX$FM_>;ui>P&ru3Xj(|DWK1EX+{S8IYtsacqLDT6k9i%+ak-`z_ibbDJcnBrfF;?A zx7KuLZ--1ct%cx5p=ULuXj?nE82hZkAed$|5k&687PAfniu>aAT7SWWXWRQ^^0(8q zTZ@$5lE27}r2^X0x)s~No^#L-peYIIIu`s2U0DPyX2L_ocf?mzx4Jtgt@`s8bA zpK*f%114BUsr%pS9`O93=meS@DuQ>;57Hzdwrb*+EjV);V)7PN>fIO0Wb6D*5-ZIxn zSb*!?hC`;p%0T09(dtRCYLH!)=Qm&j$2i?Aa2%(R&cVTYeD8novH~sk`{$2%w!Tk1 zv?}^)e9iLY46vH#)4yl&JF^_R?8McH!ppaA+$j=}9O7?_PS^p_v+LnC^Y2t!U7rGn zHK1CcKud_Nhc6KD>k17KXy&jMD9-fR=MU3opZx;u1(^>GWDUDXL8&%Zu8dImNtPWS z*0xIa2za!-487wMG=?)u*Z|!(G<*kb@{L!o!V`kd!8O@j;~1C6Aid{q_6o+N_DJ~` z89VYlu^27Xo}FwgB~bEvwJhE~J~z)*W69FipLf)@_or-oj}{`eZEDWFJ9H>$?6`Lo za|F0yVFh`8%(mBx@I2vXCl;@7>u=Nhc?Z4~=%OXk=eVp|K4Ua#_+C!|%UR@K0Zse( z*-l!V8z&*?cnH}HY8oMS3ahZJ zagdPgHXejsIFE6y28lU`&0RsYcgU@4f6TSD=|ymX<=6*^>1QpD$)~6sCMydtuW7_b zeM`N$j}WsK@Zz3rJc;|V-K`+V87{o=u+7=G_aC#Sw4x#va4y+Yw3PE>R{pH>2&>Kb zL%e~bll3TP=+fP@kJ&p-6ibnOO8=nfUJi?}M#g^%;oZSyr_z^Pj-6?0drX^NN##ih{Ngx&Rw*h+A?b7`SlPQJRX`M z%@V@uOv@R9-BDaTv*h-!GFaB-GmOXq14~P(z%*vX<4_xjmq&Zr#_P55xX)EUPB@76 z0Z?%43v34(v+nj(yAbh008DyyYyR$x^4xh20#=4=aU|R+vCk2&i4lS#YM5xj2WPWr z_z<4OSfnJBmb0|kQ~0olk9wH)#V5p=Yj)iLj}Q{K{QO9TeOuKc{iwzc9K>z zfLXLku1#E0;9Agim_RsA1e~J5U9zrH)NxGshuP%N3&r->00;t#eFq3ot!qP!L4wUX z3)+ie^o0%Ui3hj0s`d(k8y z7Q)1%_itLjSTVR+AWW{!cy$67i1Gmr&Xwt#ShQEt&p-MA$C>@65Gzk77|Sz${^?KC z0u$!WTO%Y@L8fLI<{kLDi(Em@)|DoLVAM0oSo=0uW|3VyST?gfG<1Sn_Ra8 zwAk+go)5&*k^Z?THj~hKOs0Q=7^wjIw?~7J)vYxc3VmsL^Vew&tLo!<0ojYQPi`^J zz9`ur{m~zFlnoytFn)9S3%~b4{1RUcf}-M*{hL6OUZKa+A;^i?hn~A7yk_@pZNwdL zpnJ9Lwg^(=ol`$E0#(J}xrLTCHt3DU2Ii%SK~T@3=0~H8a6xc+IWRWHSY_JTHjwow z$xQ?9K@P+;L8gZbx#j9jG+I`W!4-p@3X4E3<+SELTnyn*lT-TiCJ_(Ov{F>;3*cez zU;#z*jJfPdW|NINV1^bevg}$3-orzrb3D!y-k_Kar)^8pQUS87gKeP@rUGH zkVupcLW6+U$X(<)-20h<^zE}n4hy}#xE{%psyHh=hq;HLEY0)~&J8l|(K-rOXqW@s zffe0{g5a*$J+wa59PhP=A}kVM_r`EVzYNH^$9_At&l z*2PB%iC-^ME5Ff~EdH*O9FMzq?`EL9&^x)5+1S{~;*wcmnZ`S18;93otu_ZVTqmwccvV6mCMfL!rOH?kNHC|QkPGQrD{fYP2zRMMLQ}UaDlfTa z3|9z`F4X|=tBw6eutYJpCI_PdpL&$mJp;ImHpx>!O1%I0L>0|O0?|AY@syMdgHNMy zwYUP==Ia42-Ub2vON%pT_~G>E{=?LQLc(gqHdcY|C(!((#DI}!8X%tqgTiZ637m6S z`*44c%!g0{kYmd55F9={AgU^f8*qU{F7qgm44kp)*+~Qhnh7^n23_mN3lRA%QZgxw zzp=`k`;l3c2-DI~nxnw;wwtYzNq@Hf40yf_i<`kt72Isrx(I1=h3lumG3NrJDK#(^ z+9uVHaDynV*d(UdIn))T<0PEl+QxRc#=m~NoYqK2%RoM7{KQZ{-Cy<~loC#O4;}I> zmUlO?EZlK)wCuF8oG47$(dVE^dL{eEz|rhc7iIPN`cHwIJJ7JkX~JG59H0RR=VWgW zIuc56m{dikuTAmU=J~Jw<;MHi@zaw$ABc{l^QCQ;y0~PxYjgJH6E(gRqzLLmV6ZTm zAO7%%83G;!hOGV(&CLe0B>l487QH+O`bR2#g@x-2cW7dfYvTu(SSWKGCy*g^eTejE za|2fgNiUJWbRMEjz&+^7t~r!ETDTvxE{oYAI`{59Ov{fRaR{nt83l%g;SdaBVH#`g z^u6!DoUSg-Lb%+IV7QKzy8D+O$M}LQ2hk!fdbOpm-MX5tEr1G%Qt^75x0%r{m&Z7i zxDdE4b%NFobn-w;IP7X~HL!uWt(6SYr^d$vq%ckq9LN)Um@Kthy-1r0ND-MPM9&MZ z#jf|~XldIs={6bkn=re;wQ#Pyu;?I`z?v1Ll(j&^6V!`r?eA0mi#uY1@ZpzVhC4R} z6{SLefB%bn1khB4G9|2Yj-?=$8(>ySiFFxMgI<}Z@kBMIvWZOgV?bI34zelk+YmEaB;+7sWb(^cLLqF1J3<)|Fet+7qCh&j{f{z##pV?y zT$v%LBsMx{sn}=HQUYm`*xLxgDa6n=GhxmUTwOI|*8>jyxiwOF8k?IW8>x}8M*!?W z#=J{cqDm7NOKOlM9%XVwji~>y+ToK_EC>SbEv4$jpdB*4fjXXg0EHv9# zBOb=XIXxGgKxg>H`3#^kMKfZr3dhY>khPR?a?tD$nsGBd~j^w{l}l~ zx11u#M|Dwn9R&u@s(agi*kD7)*oQOi^LZ3 z_|TO(I0XXDXj+07FoTsoY*UttTgt9M){LVXR&o!->x2NlfIvE{<@k^aPgo7d)byL{ z7=f%lfMqJkW5XA|ATB*37Oc)qVWCmW&}l5xvtP7p?>I*lsU;tNouNbJfj|frrY}Q_ zBy?4aUTdq{(1%9aX%;eRlhTmBwoUp3IDmX989AZAZ-QaakW4lOEV?Fm{(XoApJvWH!L4Tab#l^+Q!I+29n3%jY&JKa$u=*l7GZ|eoUm;3nJq$vV8N}zovZr}& ze1L#Y+RF$FS}s-5HZ-$$}JI`nV2!jZXPI zJH$naLGuC#p;h(sASqH0-XXYcA!G)60|uQOLIRz5jT|miBnZz;4>;g`g-k6T%2J7G zr~R0a#-ZzJnJ&d;ycb%&h^3HxXpvX+O2b9;P!Hfw<=XRT{0UV3G!g`!uVSffzG2K~V>}tsd8ko2dL;L84dWcvLt-BV)SWM3&2qSYuHnq|bjnh) z(4b?BXrW`ypV4pm_1A9GA!ZFhLm8rY`%zfs2?&w&1F(^J9gA^7*UX#;6@FoK;X(11 zsqepdY7%@1E1M@D^9;HR9dc%`Qku|A%U^U;brL~&X7`ziG&f4Dqctb$#%V(7c&?x{ zaV@*Mw8M#qseVSdL*Bi7nCZWE?OObZu*CC1VEo~^(1fr^jWOtv#&7oX=$z zKs1LIL=zy@vQ(Uh*aWH@W`l}a85Y{JB%Py$Ry0_b%`2X+`%~Z$xoA?~b>rr*Ec7mj z1eWAV_5)dyPD0}CtsxfKCI{q7@ca2V4z$^GJ^(AD`IquC>vigfV|Hb_Qs_z0Z$b>x zB6iV^BR1iy)6{N|VBNUE%1q0DJ=CIk3YN_mEEaQZ%o-o#TT9b7_9`O;-j^Ly!UXbK z1u%RRUgJdUBHDCeVJ?z{4RRMM0rNeR2tW;uoQH!}LTQNN;q5`=ktIRLd#u;u64ifv zmF1AZTKvwpzMKB+r;l(Q2*6pF!wov#V=%`Uo;m>3dcvC9x=Mv(LlQM}Lk<(h-}?A+ zbqbfxl4;hAR;x!en`q-YQyfm?@); zFKv05Vl;9sFW2^8Ibz!@QFFLI=y;o%HJMtHi-1So1qr{gL$W-s4nZ24)Fg z$-NsaR&lSM1aWo-SM(a|Wq$6~&ABwOg3`>HjRief*}rq$+4(x#4T!}Sq+Sx8#2U!agdU8-%p4m47_9* zOIaE9Ao4gfXG8$%=nOYiT15qGR3+H7{$6pC7kP#Ya0u;#ncf_hA!<4H)9ve5ap4fk z+BO0CFk=%2qgkGbORvqrt~SK;`wW)DS@xp@*8D`l7E^oaMO~EGJOnqio|2UomI_ZQG#1PLG@Gn-QN3fef~YdjuV*XFNs5no}o6;c2NYug<*+t2#!?l6}UMG$;46p{1o>xWF+B1NXlJfD3$o_SNy(mu%TpENKp=lWFuVksU*LXOibR{fl!FT<(|M3;#V?;d z#!cLZoVXZyvlXvCoTyB24yx%9?q+Gc1dCyTGjf3&H_dg@myG5X zgDNIKo|`Yvq>UZ&M)@W~Z@DWRqY|ahSC&8pfvrceCZ|}wL*Dl)^qjx-Tfa-c1c_j{+zdrvlMfZMwP>|wpVPRhU_4zM< z<7X`lF3V9!-VtS>Sr7}grX$vzMdDl8e)E_lmm6gfmS#DiWDZxI-dr(di`{X&fn~XN zSP>>|p^e7Km6Xf#WM*aRa)j0T1{Z8W0e4A_+vT-qpg@CYBjM=^i##_EbjjaaRF>Kq zaeQ_vRp6>Q9My_S4^qj}Y1#rwLAR{Aj0LfQw*I#8uK~LUL3nwcHbHW`%G83?2xLV8 z6&Bqs8y31WDgk}vPL8+-U%gJ!ut1HAmQr-gT-3=4nP!*_9Z)%^N$d0X5%fFa-1x>A z%YwF3g62WpCX|fz>c)4`YL;uaVfYDd&%*owIhzwe1CT)S3&go0D07V0HsJ3=h_oU( zXee52>v@E;yL{F;kaQLSmbr{X(eVFOV#S=VdL=kP~vo%+nR}Bg7|FD_s>&_EC#cr%A=i2Dujs z3?0ThGdn|aaVOoliHn9d>ceE_QC`NWS*9$HVz~x^hn;jiin|;=vazn_w3ZgW~|%wYcHig z``Q0RzN??GV5jQ{LK43IaD;z^T+c>ewRP?Vwe{{@y)yMzS}hia~Z?svpAYvCBurW4b>gq^3 ze)btu2&pR8Z-c~fsPhyXMUxKH`6+n+3BW{-W@_iuxD27WoJGSGji*Jv#*6U78cV`RdK|qksLsz`MIe3}Scs0l-=lo|D7Z+a$jq!@lF?4xhVbtsd{r<}s!}ube z6pw*{S-u`ajVYiluowu2T`ya(F%4qPaI3)$Eu7;q1O_f*B}!uQNxqO3eOeVM)((`- z@g8lm>BtiVy2rFqY>tH3XHY*7C}ODr zOnddlHQb#II+hUF60g`Zxh^x5)7&^a4Aja4?>#o{<;%u<5NwKlg!U9R_7I778G8+q zy>>>U_jZ8gv^cJWhP>c)&Wkr8>YEp7aIMQFC~!p5QHXnP{t7OYd?>6P0;olili=Z$ z$>4aua}K3e)_^YTqTkxZ8J2)#XBjuqhjg7`GTOEhu{LB1x5j{GlQu** zfZU721uPLw1xdyVVsIlIXeV0`0%%6yrSi)ZZa^X4cFJ%E}V!KE~wr z8LpztCb8PPC?}J#dG>D|M)4qJ%SRw*5*oKQJlG(6xIv?M38PpgK_U~51@>TTdlltj z|7_4XdNn%iF*$XwkJiQLcV zs8b`(!2_akA;SUEvqv9=RXKXjR@Nw7#xPHaV+{IbDL5v3q*DmCfc9ckK+s66#qBu2&1|WPT|R1QZsO17x|i95fT9 zDhBUUcTxn)GH(5C{?BtvTmtR#S>}F(zkB2MdhXOFfzKN#=i``1aSodM7_X;u5VOQ`F$yW_x`c zEXU&McScqli1dVHopasQa*{J8SlVr}%EGqLfDs4bp6H_d+5dBw zfN<@)2!b{K)_vee|9V}yHgK+^yk-d0XpSCt>AgxCV{ACtil z1glxK!WM(&92Ny3)6#EIJO4gL-pL%uqvbF7dx?X5ObiEUleIs^3gk#sZ=>YK@emv) zB`<8BzH$ovHhe>i!usj-dAOBLAAb4;O*_UYcsrtAhMAn~No{Kj;RR^}H0eO-Z4!$) z5@dkCt*p_Q1$IH69teUrZLD4%W`r%h6sB(1L1q6Z!%YPz~)GFr{S@ElMj|2vev_~Hx32>g=n?6-^~ z(fo8=B(Wz&I^Km>E{N3!nZbmc0Q#pko1@ntib?UFAu!v!>hG< zgvgUWjj-Wr;b^gghO#FA=fC=Z-*GrGBX%4ie;T=xVGhY~l_Vb(h_l+POch(nCgI8+UNMjnHJ1&)F+^DQW0 zoy?Fm6|AoqUI+B80&-;i$iM)vdA`KL+`exEnALl>QMk)a%|yW9gJjcnPfqGm*%<}S z!rEZ`XqD_f+PGRBNq_5|uY$-?;!TU8F?t;fK8%fyr3%%fS@J24oUnk6NpZM71l|a# z#bBa={lMVaD|4WjtO;@41WbY^!du|P#7w1r&`yU`jxOAKJH3Im`m?+L2bK&AN1U@TkJTYx_4wfy zko7Hg9+q{uXeb2ky|w{*NNs+LCV=1iov-q`S@vp+vrtT1o;NKaNo1>p+YDmr5}W-3 z;^;Tu_}l6BTes6kKU%hHjK|MM?40CFla~JD5pv+)E(PZD7wO%1-!*>GEcwE&C>dxG zf3HV5=RCN)+OUo9ZVB!Mo0kE-aNM{-ltPmsb6dhCIfn~o1aGdv$~p^%oXTZ&CZ_?R zs?&J|x5OqBX@P^lLBoAv6clak(P-kXB-92WUuN)aJGdX?2*diLMUF|KxIV@P&i!;E!6+4ux^aBixM|Q$8<%{a0eyIHu!r3>n68Mi`S)~uYkpn|JDTz7@{-g zDZW~pb;zQ0xLb(Kbid1i4Ic>cG)@dgnI*Iq|ao!B^WD1H0Q zIVyLJcbG#{!5zl}=5W1g02>Q)3wRZ{r(3xDjAuE*>nK*60}$wBKK$^*AYTF}>y|-7 z3NBgZ>PuIPb5|zrkVK4j_(LEW>>n_%5T^x8NO1(v_Qt|Y^F5wB{;;+D2pQw*Jq$4x#oT&G=nV|kr6mU95C-v^b1 zgJQ>e>tw8;bW(tvEAu%PiaDRroXHSSut9$h;NZ0!Mh~p*lp^*)P;}#j5_OkCnE*j+ zZEb^;$Gx+Ev-j7}@AdVqSQOH>e_8{Jwz;~NcGfpyZJ({Igg}iE%vXV$Js>!INDxRJ z=#bs+qcf+UhpQ;a;ph)({2p4)H^M3s$0cE%3*3ig33=Qw&;Tqx!j1dvp6EWu2ohp7 zb5jM9u0=Za^hhBH0H1+>%6eL1N~3X-rUD!`1(7*n-vr}0k)Q^9V$3A<2C?NI){Ql= z@wq?&yN$r~$M}vcoUmbXD|U8q_>rCVjrr`ARxx3UOLu@bGdDX+@)jlv7HgCy9t+d6 z0pyt4=to%p;#VKxMUu0sLQ~?LdcH=OrK3AH3YE)dl5F#NZF%?or=M=NNkZebpLXF- zUTke`b&c2Mli3*NZ{m{aj(PTtVZz#IWqg>p9HORQ%&maQ*JU!7!AhVBRfSgQHE_G2 zPO$k6H2(=SbmDEd5>L)~@zlzIk{uI#+gRM}d_P<(YfBm&mJ>4Ya8iQ8j64Tv%DreS!!4mS_kC!sl@~vQT;S zscc07i&B8AQh}2%WAZZcU+yk^n4l zSW}tLgSv^QzZPeaD zsM^fy?B`H_ut9|-@l8LTN*PwdF7cadV+`cv=~7%2E7Kf ztIJgYLacMc_Pjl31B@1Z2Xir^T}tK&T^~h^il8{Y`P#E}{yWR&V}8+ch&)>0DjNqz z<3?j*8w7$ViZs74oA#lHU&n;seCc}n=oh~NZTUX33B~1vPL^ma=WX`mRyllhe-~dH zpZXN)gt?+fK61FLHMl-Q!@hLmW(Yd3M5)lI8w)Euudqnb$)U*XAs~CglYR=LB6>x${tn8O)u4%S zsFfQad-)t!%W)lc6BVQw#f>{k|wSEzF=;9b`2M@9uSqBkIvrp@ZJv;)bbkWAmia+vD~G z&DTUbi87hZ_U+fVsq|xW${c2MAM61Fg7#r^vko%CC6LdPqm%qk|Kk6|LgCvVK0^ym zr$6|oe~^YqN*?WP$MaS;nCc4;X?A9k1Q^if)ur&&ZDBM&e>L2ZL#PvZwBs3C<_L{+ zf)?{oS^Hx1y;0B`>tPIvU3gs>dzoov^vRn%M-{Dx7GCY@a&dU2^=nOR+9NbV1^>!+LhK*j#V-Pyh5!yX0X)SYnU- z&+~`Bq@B`n=Caz%pZ(h~sKfE`Issftx31j?lfMm0VPC5@u8mr;k4$hIq=+>KfpORl zJ-yHf!$5y+0<|W?b7VD(_c}@2@#ujX+!&Qnpg)V zVM7p3Y*?jmtvKj**UWQ(?8Yc!=xWw+J+w+{Fx%mlpqki{$<212rBl<&xQ4cRGX9fV zQ$a{%YO}1=QpqMTHlkh#%b*~NrYS2P>r*s(7Er;QO^fzRX8AoF5mRv;dLDj$20*~) z_H!_@xM_C2aUV^rddQ8hB%TT62;B|?ZVbav*L@T&xAV)y#0)NMgQ{83FbcvYtJf&J-zGcAqdR-*)KTTq2iY{Ll5DIUr?E@oJn|ZrZ6&$4Oyf0Z1HFWEN2AH+!VPmP*1>=TKy@CdX{7- zNE&YcL}dqs=`dPc^41=WG1l129+wgE2>{3QPB`MZ?>u+Q_*^V8`|0D-C6lfkzm(E^ z`9RvbWj!@)zYHO5|CNbvBxYC zH{}Kg+bjpVmBk?tL`w}$E~XMyfaCmq4%BJ_D{_GLO>O*V5?At$xlMC7Zr!FvU80(e~!JD~_M+uTpL&q23tR>}AW;juJ8N{SQ99Fi*JY|nu} zf^Y$Bk)%KllYcU4*n~J4g>`|h^&nu8Gs&B6*x73ge$o|FgGCn=1(EOVTGPkjwq>t< z%%V4ef@XaZLLhjdTL-?;L+AKhn}XO(TxN3~;V`z)8tNIC4zS6ct(eYHMjU|%+>Jd% zHSJVt9Cu7&+J0(s-V{{R1B3ANWL2NQN7E{fRi|J%ETW{Cfy2EYvexycJ)B`CXMnQ( z{qb2Er}%4>b#TnY9sR zrX@NA`MLes2?(LgirIVu@sr*HwC-x0LgAv*OqbS5O&S=Q>nV@V;I=&=$5Tw-d-r!! z{~WVbAAXYl?T>%O(#l%SbR9cx7~)yykx>>*vs?;`zkK168T8+!7G{H_rBCLc<;n4N zm=fhQ*T@?TU$?^y;aP={Hc}n z^xlJX|G`J;vrj)tEB7Bn0oVmr>fXm6vzdA7zHw)ua&*yr1$?|H6lzU1QzAX;XrWsUZ_=eF}D}76t~98C=l!vb=T)BRY4Pn6R#uh?Kg&>EO3*hiTeL)aykmvOc5eHggExM!2 zWlW_o1~P{r=^hDM^b(X<0@h!5NyX*P#iRoeB3->;8i1H#Vt9Wl4RJH=ZS5h@lBhTZ zVGK33W>z^G`^a_kk0YROmGNi`Qm z%)!#X4=x$PwntKN*MIAK>GOwA(pz8udV2L6-%MBDd?U@?c!}a7==R$rpdi|DV#o)a zfsD=Znc(VB{PlAmfB69F4Fi3w(>AzdGrX1#o3_Vd?+}1zIEX+@xIV^J{2sMt>m;?D z)?|>4w#?VyQ_XHb9%vDQT@pISO~Wz6lmmz3S~-$WS3>KFR~W@(F({V9Z41;3I{ojG zi8eQt<#R@Gv$|Z{;m&4Sf3l3QN+{*f@Uh!RK1R4l&Oi8* zhwtwn?l2v*5ar4AkLy;e)ef;vcWG%!q3Jvq7IxyVEKG*LMuADUZrzGJjFf%@exAd> z=Z*ZPN3by0@6`92xltC(3zp8W`E~%R2=Ydx6 zr04|Fry%oOrxutG!uR3tI64MPd~fo%pFP&9Y8iAJr>4gFOk8k;U4b^vQ)$Wx(Sr}u|NG$Qgbc71I5w55 zm9+WrDV(`^C^lF@sxDWbZGe7e&L?N4-(UXdY3sB=$=gv&3)A83cTwh|Wm028F5+hS z4|f?4)mc{4^T&Vu$0142e;;4)76|%NcYb1mg?EDp?$6ZVyJ>?~K?7)a^B?;MHdMgR zCy-S$X@%6>W{4x`WuXR`@#skFGwxJPXLjAZMjoGd7-2a0{6TvBvtOmJzx@pY%_`g@ ztPBhRyD>__Q|l?L@`Kc<2bf$GDB2F|#pg(SvFYCk2Q~`<@!T8`2SdJ^)3+oU1|5SV zY;MM+sx>9D4~)xP2(`6Lf{?EU8?Uoeyy^wL_X}C9)hcQ8L{z7nw@qk}-JykRc z#yLt&%L_&l!fdsylaB3>-*$SVZmx-7_Q3p-Yb$guAJ6VGm?>5lV1Ru!Hc{XS`H3qS z?|3?#n!Dtl2)xZX`MT*!0R_4WuMOlAS8km=o0evLVvIAkfk2~V*xTCvMtTOid3)+M z<1ET)VjqYeD>XGYMnV$wa}@=M%w4N4k>Dkjkf*`n+Fn}Or;NKuKBm4)3oDRa$~#_v z{cYBM7g+yUoN>6DnZDlG@kpicOKD;OE2CUq#4(ow6EE^Ve~mk1gJyoqRYc%Ff*;5{ zMA~)M@i99f8WWh@K{Bw%^vBXo5t%y2Epw8U#aRdS?a-Dcy)sCD-x(SeO>GRYvbxIQ z1T6w#Bi^M!!6D$m78-}ng(Nx0=4R8&OY_kXuZ`KCo2Rihn(YXZo?7-o)q@5$!z`p( zq&#&XaxeJ0RN#r=6tN<@FlYR;W<)p0L!(Plx56?k9`z^qS883)jR##0RMvxowl#=1 z`+Z6rt%!TJ`RAfiAbDrl+~t6u|&}ffQx~9Kkf-|OTd<2QcMx3@vi4z> ztk>v$sR(q@6kc6cn^R~dQI2s6HX)vLT4>q`k65Ieo7o zTx%_tus9=(%qlQVV%Bewie81qQOI z!SmA`2<(2klAA{HFdS)z(ge(lGd!C(J+<0SY7Y_;Q1|lX`h9qU03Qq#dbqriz5+k3 zLJO#gg{gFFaVc$4y72MxC#l$(pafzg?R~TXJDzIJVdz_M)e4;FM9n2yo(W~Wk$wC^ zqv4YM<|BTGs{E_RU4nj)fh>L-TamIL23br~mPPMlBeIyN;v28Ob!U2fGB?0th$zhh z@g7on*n|~pM||f`T7GM<-i_K?91^qVIS7`gG?d;Y9x?cAgSa?1QX`iEwp_)$e*W3L z^a$;81txAD3A+FAVVWZWImrx@W9FJTVp~F>`2z!F;}A8d`34&$4C4k^lahlZ7+Q|I zP^c_lbtr2aw9BBkr-2bTcGrU;>Zi5yp(fTf(@hhimLlP7c}o+d#K>ne^Y8nHAgN0c zBHK>kiidD$V;>I9udRi! z8UOeYPS$l+kX)Z(l!4Yjs8~2&3u!{xuRd%JV&iu$lona|xyWmEM{UL~y~V_;gR6$B zqz-6yJ_MjJfOW$&;(p1Ap=i%I8xGX6{LW4}D=S;EN0tTjk?-k{sxTDT;G7)VD4kx( z3Thd8R*9<8gGLQj`%^5|A%mP!T3VcqGt;3>YzZZ3=OLnKl=gXA-&{NIYZcyq@XKYm z_-G^yB4c{Xi- ze}{nEM&A?)0XsYEkVu9XaWVL-TjXbOSa4Zb3)a&^yhXO%1fumWb-EEoA7HeigIeL} zaVY!Kt=C^=6Z+D_#}CujzxmDdgYW#ODYLf;eILd#n)jIGmVqHCY445snn7p^z?&ry z5NYetp#{I(g9RwY>p1*qcuNmBC9#=!3uKNtu+D|#?}5Gm8S6tk3p0lXH;_Fym}R4n zfO!=-8v&L{9vVoSKeCgF6NW7r@IXoEB}*4J1Ks`=D$CK{}}Z_#mw>vR^3r5Ij= z7PiQ}s_blCWzT8%L>OOT6x2C`3^|O8ZNgJf!t`i?{tUk9Y-XJ4a>PB`w4|bW_z1Zz zE@7jD3$*h~2{xOohL?N{OQ*(#+PVZg#PM9doH1r)h?79a0FNsE*p zXX_+Qar--M?v*&~SD$^B%F`36fIKYRg!9PZX&lixh`4JAw{Qn`yN_Z1clF_6eCHM2WYI%Kp zJHT8rkYi{p&sDe$s7*Sm)pd=uI=W!EMhz`(}PVQnIIlQ8QjwHpin+l1| z!Uq|8+sFM1DSPd{)-`jjgrZGy@*xP36`pjYm6SWh)iUG1Hf)gwPZ_k>`bkK{Cv*-Htc!#dh83(uBuo)o* zW(XVfXYzM=B)V?gzYQF%MwK!&H9n0XQB%d|I79OYPX?KVtHycMWknd>!!~0NJH$pR zIR|rfXqZtZl(0`jo}8Vd1#dytZ0;D}@lvkqjIe@BP9J^oGmm!nxO?m}T*fakRO~W_ zdGEdVd`>(r1qRElLCHwIq`v+z+ALi@DckF8o@p}wFKRl#2B9%iM-4ZsNcI@{^ISDkZ&X6dRh6A`&MYO*fSCmJP!vRGK zSDVe0@Tkk+J?q}IfC@8MIl%r)U5Kux8<&alN{@ z@~#evQ@CvQ1>sdVcpoV_$5=#>J>5~=RRvUSuaH@S;S>NCp3jxSgGLoAs&|kbNO?8<;j;n#}hjpAe?keELZBH$iUID z797x1P@+L99M?A1pc!mIcBDY5Ivsqf2J_OnY|JAF8W%l?Wg+bqIf-E!dz-{Oron|3 zelK5J3XSSyuPg^*fn1Az^$?qM1_C9G{>UI2WM-WDf0Juws}&l_f?5#~7P)G6(l_%i za3ICpBw7Js%d`36TWeXkyB-pT#zkXFqZc@6qnRb#i3+KO<&d2-P*iPhAZ;w8#wYTL z%(rnIXB+4o%c>PKE?}cMC%Bx%82HpD&_Zl-p5vNa3lFmbCIK@LHlSMbJGx;oM?!0t zuux7oQ_!@Aa>_hFcB{#7&)%m8)D~6>*s;(y&$9*wJ;D0|tJAE`T#T-r!MU-B*XDi2 z^`OPWrQy0B&U+))A?;vnYM4WQnjr{B z<2ob8xWsZ`iG>w{ceC^@7P|!m?FJRFQiGr~><0e&B(*WyXfHGpTG(8Pe!87s`asI; z8&=@C!+s`$W{=`-fgqFXHK;UiREO1!nc?}pAlE>6Sa_5}RspfmN^!cve0$(5@{$85 zMZ_$-E{nAFEC5g!)w8t z*2U&`9(+gGnHw?7Z|_CjRf(AdtDRZ}^YNfg>UTB?j3JY%E)I%q_gr3Cu?!oowwl^<KD#@1*$~ z*VATeB|W>pf+taB&rrtf-A6xJ_K4HjwMYN*hu?e{!(0jnzkfmR_ntHFz4u=7-;EnL z0@Waf=|cQ_E-dt2#x<}LiM@CaYcwdJjpq_7a zJFm3RD4g}scKYFU1a82fRM$p79D(rQNg`C=f+7~podQ_Z!*&N z4^{!nMwCs;i3d=tU?&?7NEg8|PAIaO&XQMH)bbw0CO$nh3=S@yK5>GF&-YfN74qhc zdag2tiG@g7H9k2IS>pln?&t)qw9;wK#jnZU4k706*4^I(n0C3=8jF-o0>^B2&1enCWdH(hq^iTs57K{*8+k*&u z2uYL0=PY1}XdNrbawvO)SdKoqDz3N7Bx_goD6P_2$7bGvlb|eUO|Pv?053-?YG!yp15_P< zVO8BTEmXrM64uD@-X0DSF`3A|#!fmSXE+1gOD}tF;#4&)dKG~p(jCuEdMM}9vF5hG-)`mF8-*X{>vdLQ$ z(QCj6@5ibI`+~mM0IBikUx&QS_FA2Z21|_i$fu{21#I9wR5*V? z%&pJsBXyp})ibF&CjY3X;Z3Y@9=TjJFk0B(i>9DxX$eY@$`uMlqdVDf?v>rM zNt|<7Jn+7>gwNXI5KC=w%;05hi@v+4k4M^^2WJs$RzYY40sI`^4%e%Qg)*ODhZy~F z@5MuA;3{M)b3uY;WqgW_CFa7V6Nqpu-yVmyE=?kY3?Kwy4iJJh@qPpVMBjAl1R)eK z;~D*CyWB(>v(m#uD`iZfV5lV2+6tfATt#wB{AR2b%n4rWh!1J~W!BTVGQ!RV->#8e zW_s~foC5?7>U<<}ImN7q0d+^A#1#;nkV&As*dV`T`GOWnA?2-D4uB5MfTJyRHSJ7e zfG=a)oQaCTWTpsRfGlAh0Z4?@C?nUis3U*^3g*zxZ0AHazJP1rhiP=klYiR>w%@ko zoEY#F1*gLF0NA~#$+c$415J@2t<^|**zt@sz&ax}Y>T_JxX2)-`E-BvajG-gqd|k1 z*^#mH{CVkrT6?(FDinq-QI0$e$@(tHt#@|$k8k7q7ctC>(aO&={jm&~r>H=CKC&-! z3L#E}=^QxI#%dlk$0kI%E}BdiLS}La?V86Ou>pcvTsK`#(I_R(bKvI&!lP&|a~uwW ztyE2HHBxO;lS>g7nxqOH#D?KYtZV@89jk*o!=V=h5Ym<-CFEF!j-hX?OI74hN4FCa zWC98vM%@}K4V@a6;Q+`;sDrdgC6TkGN*p3aQ9$&y+3mPD4}!-9F^jKw4iQfY5_qWX z5nyA#6BL8jcnGW-^nZjbckCa^%xZTFBJ zL48rH+7m1wTNYd@h)9?OM@|*m?YWDFuWfEYmt=?-N_Rr-q~6VP7(|fHuyneHY9cpP zG)tGo9t75hxCx4ZzP?0DGs8A+(A|-EsC%M&A)n0qGH%f-WntPLi!`Z`x%Ld3s72H* zk@iwVG5G$6#29LRHLR;EEbclRXXx@-d*Z=AK>Mn!;?Q}{(9F6*3XMrVwQ-AJeU)UV z*XT4hh0}E;qT;i9&o#H?>)L##H9<0pJtSH@t(2eJ%SSP66?bb7h})RSgRJoSelo8u zGSeN4zRtX-eG0q>-BTw)YxPEn`-Hk37$v~swVQNR8L7amG94udcP5V3MWOV$&XmdL zO)RL~w3;Xi&Wjz5>}PjCF<7Iy&-cEkr3FCsTz3h^gFUY87@&)&`_{EHCgtiQC~PT4 z9h9TQ-|#vRKt~y7$?=%U-=)5(X<`{=Fha*r9VMHDgyrL$RZHdcmp}d~R=14aIDfyk zT%+QWbVI4s0TB(-<+Eqcx*HoCCN8`F^Gx};M9HjK_GhUvAyu}^v;&~oYj4DdjWMET z0kq3}gk(rP6c^VjIp?jLD{-+ZOzhQ%k1|&d@8KTMEeOct)u-HyNEL^R!{JGveiEIRkPJ#(+1k29|=7V}U&&aX2}cR!e$d&9`_>7P*;3 z)Kpo|FQr_Vc!cYeR^P=XkjLd=@}Ur7kGMwMGHP8o5A+0s1j(T)xo8}4tyvEytrYY0&5il%j>PsRI|&$^WFprbi0ChidA;nf)@Og zPWeUFLLumf-$vg??g1hy$Yz5)$N=j##I<`5=3&h2E1bHiS{Uc%=q5@#!mg%kGnNcv z`PfhCP5XOW;hNew{S=Kq${ZQ%{p&uTLvG2Hin5QPuBasfcqN%U7H7pO&qL5LCg8<1 z2B|xzFp@JoCy1LMk-FdexL{SPQjhEsgasd^f16Ft4=L!spozU6fPsGo5TQlifx${C zefRtC(9DHCX_-BlWEslcNdHHhrD!p>xVV^}JbBW!$3+~BzwVOxON9ouvfpMDmdlDu z*v=td>~s3`(|h=W2?TGiQgkZSZISpOezCk8%NL}=mE6{+-WBh zDfGgmqDlqa0E?w86*kxxDbiOqQ!k9@7&#fes1kf?G!-Y`F&1h{pO>Q%htG3S8pKXY zhRBJ+M)?Uj^3Dq+-D~yo$b> z7h%zQ>h1}cWB^f&fp$qA50WO(S{NWZWa^AY?oICh9I!?NOeVlKNyu7lmusMWfzCZr z{sl3t9Wq7<$_)3d8+CzDAg^Rouu!s2MF{aySo;IIV%ABP z5068mfiBhIo=Wh|&hUY!E5wB$ZMyU)oPh%rqOD?e*SefJDz^|eV%Qd72Hn3dXk=cU zs34puF3LIfh#BqJe~x978R2B+J>cf~S?2Lz0e3%s!df$wfU3*BGH#<t&3Zs7$5J%pR^_qIw6l!=pMcH0cU_ZNvro@-JtMnLdN8}B(e&3wi=ra1&i zFHo({a}Cm6EnB1J_*`Q$4_XCHCx1$zGIkKyaL}p2yZxcG z=L$57L++!EunB^A{a%l*75@*k(F34xqI1G+F|fC}hrBrRNh%D7KKVR_)IeWrZBI9q zl-67q*|EF*bhFwv2~Ix8J_i+Qpn}_mRg)!oihzSD!hV;A14PcWg9`Ao-wT$U!Z_hnrhNow zi0i3Hg5@4_T5I;){8_%3Ip5toj=p61d~`*nFJ&WKGUAsmonAc-m;YQ=&U^0>0>ig{ z&4`eJ68OD;?_=XK3e4>rFPCn=dFxKSaYTa?ktq_8P-ARDCLLmaZh-@U*29g_|94JG z6#zgIqX$>I|MuQ?xCp*^`1x#*m*jW@VP(SIIA|7y8PFb6UK|#Ojd24#6bgg+5%Vi* zQiEtjF%F)cEAwc3_7V-r=5yEvS?ocOD+OjBZK-CKfh%pqiCI;86)T(`aBEz&I58KK z4VA`jEEN3!w2W+q=#VXgWEcAy$6l0qKYuUMq`TrF@V*r;HGo>*cC5x!18RDHuaz~R zmSrGtA>T`767CZ&l3i`gvIp!7lH_D(2ht8A&~muK73S~y>RyMGocKKBFAjrKIYsOQi9dKCi9$;<=H1V@8XA78G>%9-%Uw52n0A>ep@+a$Q7b`!^ zzIbj=DOuk>**pL6qtD)NuTh0${#u`qkKych3`MXo#xa)ywX1!`6cE2Eb8=8Q4g_`PaalZ`H- zoiEkuB1s}Z`s#5g*d3id`!2^YB^ELcFB;UjD6BSCh}eMxYc^bXbpQdd;&2bM>(wgR z4YV1z5So-1g;43f*gV{Bcq^7+>2iw5;#2D0Y5hCsd^It#}v%<>v#LO92yi*TB>^gXl! z2Ik64m%q0xU*MubdvpK7>+;)JST;si%fMc3&*4;~a!JYb+34H z!VBILQYscS4i{GRgmtx?z*xvQ3rPr#uf_Kx6)+R4vYq)htPr;ws#ky{0&YG}0aBsZ z4oc+BjnOIdMJIwAbF;Yv5dH@Tr;FeWp;?plotq?%2z~em>9Ns zVjRNj0AYqmc(;hL_{3mjH;#2BwSx3WBlff5xifpD`wt^AxepMV_<`M?9Dp zV3#BFtQOQd1k%AqYb7qw$`@!R>qOjWV~Qa_2ep{?NBX#?d1q%kt*x!4D~neV5YQPk zg67yksZInFO%nF4R42mEJ|ugrn}Y2?n=xpI`kM<52TGO$ZU(xDKtPFM;gvewC0#v< zpt?2YlcZ&cw4p#^qoO&vi=#T`VSFS2Z9g)Zx@uV!!~sd!41PcX3mSdU@Z-Z3Ls-i| z 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 z z3eL_T*Y{RPIgimktl!@OdZShsDsREiWQb!1W$rz_2t} z21jzJoxP?QU$OqyYRp_&FUsRqNslCe^8yHqZjRStV;~ViwA^fc5&`Zs3zz^_Ngz~M zgDUqi2H~tx96<=|NA$Wa=L3K!=g)dc{c9^p0r%4TVM<=~g6^0_Xp82KG+Y4szW~H( zoCJm*#x$D6`!1w^kTy3x&xvv@gtA9GJ_IOuXY2Uvzu!7KIiJku@wHNvWw_Z~uCN%r zthKeZ-X+BnFURd0U3#Brc6@Vu2#+C4aP>4Eq)q|i*5qXN(az!eotfOfIJ>C)1G;7V zYApRw&qv?c;-QPG*0*NhfFS9B)S_-O`_TtuCuqtd)jLX@V<({Jd`^vG5GZ4fL=_Ok(de}+?JF?x!UzO)z(ZV{ z5&@QN(UVlLpTF@O?v*Z>wH93|HL4@#+<>|)ycYpM`Esg=Fm7Z-0~53KsEqUHm^#-3 zansnlV%%ofC#iq6ys$W}dj2ZKgW`Old=xRIB!k zoC16`UJ!3qZ62}K2ocGR9(cAUT37AoYvRoMASHBH6x6&aM_ftAaSWU7LRh_F7NB)O z-JA}+a;+K&u?62Qgo=)ApJ21LK^SPc3*0|^JFJT-Y(R}#KfWtvvVe6l%jR%dEv$oT zdkGW*R;@+nXNIwUX2ulYbM9A%%6*QEt`i3m#Ghu<*fKGG;{}dK5gHUi7YK~!?sybq zWC6S?o-&L*atFleYDi_41d|DYG;7!+oy>CK^jRMic}=W{m1-)i%sw0-R|~RyKJ}1uHyHL%6OgiT&B0t3OGz!<(Dr% zB0pY6Mr34UeL$4~;*S!AQUs`^;-p;Xz$pu6R&%3wJ<)(oMR!(jFVs2AzT zK3tSV=@!zp+x-pHz|TPv*99OlOn_R>Y9>oPMzSB6Tl&uKZ?K+Nk9CC$N*AmeeRDV7 z16P(Q8)Vz|xSo6q9W1ZLkovhX>&<2)0p@gH#(feI+X1B=EwzqiBV1odXZ`aU5LwR^ zjs<&2>Vl8F!eEpA@LC8)8iSI)f?`Nzv;?W0tr3UEEv%aD)J$JIMJf8)5pM4pc0IonKkw$6H*oC|Gc7st?%&SPAvS-t0?dX2ddmI_) zvwrysb$U-O4q5aplULEKo4Ia=dR<>9>c)9`D1jOV7ZWVgFexm6Frh9(`3g^ZP!$Kc z`z0DvQ3YRC-U;#rx?UaBhqT+K;6cRO1Yvi!2QfK$3xFc)$P1F~3;kAD2`|8Z}1wfEcx@cH;j{QZeI@dGD( ziWeeIAcao~iT8yMrWlpR%QXEzL2?jA0YH}VfJyty;qY@P$oCH5Uy;bM&j_)kl1fy( z-~E8{y<*@#i?CSNP^JgY{5Vo1&E0r+BV#R03VEl@5!B-)Gax5CLNnJ{_Lx~DjLy8Joe7}N8+~3@Ngup?aGS}Zs7)}mM z=dyoNdZl2>qb9N=FW6e1@V`?)U#CYcgNCsEa(+#uHSzS74_SUbPf8E0SQXjD#>RrKf40GAHS^e4Bl{RPPK z(}#nVC6MK6V`F177z{*!$?ooMJim)b*>~6W{?ajIr>VCQM)e4 zB|EdmSr@5;lADXz_*54S4PJDWF8RBpUn|XKda-AMC^&tw0cTlyN>Tp4kVQYr8RVpQqf5d?0<1HM)dTA8!U1n}s zQ%}a8fVi@Q1CY-&Qm!5LK*Ed>eF&Z~pt(p3$yA5>*_R$D>!Ic>va8vkk#d&ea8}bJ zA0jcR6qAHHVOrd0kCt|FJR1aX&8V1LBy%FaJn$4K69FBk1obY8ptqnfjsYdCOSC^s zQ-NTvw^Ztsom}EO9DBmf{_6KJGr=vYC#T>4(Leq8Z=g;qU+(YoVHP9?w1SHBs{~!V zHqN+k4TAVa1rF+-A07jMAwzo~kL0@hr7PxOcLGZj30UnIg$Jy+|W%90QF7+bviU^~-zg z^1gxNdiGCD8v)#WT!k}u0NboOOP4Rr#10#T6b!b{iGkTT5J`kn5cAcuXMrs4l_(y6iH7kI zMAERJ8XsyBdqtjBDk&Vw;;~_lSg;NX$sm2@(Q${X)=EVXwYI&sUaBay)K;5TGS!k$ zG<|Q44QMnOL{2A3``*2qm>iJ~st$Akb$49{WCWhb&K8$CEEE3WhadgpAJc888jF9S z6scmx5GP+T)~P5THqe2};R-R)8wd~{{{?|4NCQaXwT?Z6?h` zsh4#Qe;r1?K~mQpp|eG~v6Bvkkk1t>HOUHiLk3XHQHJ$;F z&*?-p3>-Y63C?7tL{b$R^}JNZ^p4R9ZQfv04=s*Zk7>xguQs(T6SMdw>ni8SRVX{t zLQF)OE($>h`RyxB^~!GEW#ji4R#%N?ilOdICU6%brN^JwkYKv)a0ZL)8d1G3*)4?* zM~Z`?V)lcZiJBT-CeH*jPqJZnfD1bhTRDbxbsb|FbPZbtT!KqKNW}eC;2ROFS;)q^ ziP>n0YFu$!I{kb;`pX}F^vR!-;(~AAEy&`z{TS1Pj~(mUB2(zqws=W=xP~Rm0G}r2 z;J?KOhVksN>kpM2UuhTsq;YZ^A-`VQLv*$GjtGxQkGyhpn6_lD|Xh01*R z;fE7M%;U$8ANy?t=+nYr4}zpIpDpyBAC7;(6@LG`ym|S1OP${DBJO?2*JlP`AW4!L z{C)JgVsC_5M#Bv9`a9@_og%_K%MeK#RxMq;@2mXKnuy{(D zU|Ez7LS%poG$s&LP((yk^3^0z-~n{%>i&WKM4j=gP`S+-Y!fm0Ce*?GlS6o3rHl74 z1P^l)B4cU70CBz4TqA&ou!PveVgjMnuw-gs9IM&`WpeEyQaPwEK%fg) zy1Ud-yJ25EMJh+mds=ltps<4al;@gMVe&HEhX{}Eq4cSgbq&o8R>SlmR5*O}qu)h7 zlSzhN>xfMI!{OuOlan7k{`%?Pe)8$ppFh~VwLZG&j6jw^6mkWkpq)I1ZB-p+A~8_; z*zxZ^42EI&#t!$_ZuX6EFf+nP*a6czA`ZcR-Y!(8hi;jEC-~~OvIu4CA5HaguD-pq z^{Xf&erNqw_qSnF-e;reA!5A&VpR@dGV74_8773>sehMQ@Q6;=)KVX;Pz>s3oa9(z z6UQ9U-9-Il2|jg|1!-spL)zB~a{#NC<>FFSVJaO`$%H}5!cp1#8N0?(5u4?KFXi+e zgc^XTo1B3@MQimrv#(mVZkk#r_fVXP<+%}O0M89I_k2J;ls~l*=0|gu>@aIO6E1Kh zS2oJQ-|aC#8KhyM1K7D}! zL8#QXxo}IJLmV@Pmeqt9}~R@bA=EK{nG9jlgL-QySv<1wKhf_Yyy$+r(UI0N`#?@U%P7vQ=&R# zh&XMPfi!_I#KjY=?4kx82%~|F@%W_28qK&+LZ#2#Gtx1oFZEH|T0~i|cLhP?whqA{x0JO?UgJvuh9Wu&CEUF>qAx960k;h!5!M_S}L9mouc21G5 z^?_pquMMf zfyCR+I{-Kh0~{LT7;!RpwX;h9JlV6s9zzE%RK*^>?-dyoU>`q0dS|^h2^+Bn!kVSC z5tNEH&{`*L1!=L5X99>a4DEzEjDL23^4s*I#R7~A zy_ONAjM$311R+o*>x@rMP6Aoj%@=Wk%9Ljy3LKSTbCHE`DcD?>;Wd@%z?yZ-;-Af* zE0IPdSp;diRHRD>d1G1c4vI$XK)^`4T?Wp8K{#P1+A6w{sP|n=-z!U+av* z%PReMeHZBkdM zmaahJG19uYHCb~?!jQ7~OL#nI+)WLy!^01mQm;%~O*7O6XwAFSM#MoF&|`grPBJF8 zrt#{fCCqq&c!o`U)-_UU<1X?I9cM#Y>FFFkOy;X$>94~RrcWaLAI|c0rhV-|P$b0p z&5f$cnUFT>5p^wfew{abbLuL54DKdS-m*+df4eUdUb_v}J^LuyQ28 z#HT;mvJ5l4ey`II#U)j&Hv*BSPs5PquXG3tfBBb{G{5l?Y?_k4d1ibof26PTML_v? zQ+S=G<+mOa@=dIJD=uEMUhTLn%kX)1tkOpr)%#2v3AazO|C(gh$?y!Q%g8#lpH+JE z&gA!<^v(AWe%d9*J82s=PDhwUR}gVRK+v@9d-eHU@>H3yl=x z8w7B@qCzFtw~R4PnQ=|L`JgJzx=!AF#%CtcIo8PI-;IJzPLSb)-W;PcGqFR4q% zb&YJA>8V_eR9z^KOrh8RWxlA07td;Rx^l*6Tm+Z+Cfq=I<5s>%TmNgN@seBf%yfX| zlSjjCb=L5kUPoM(9WV$IM%0@$GkHrHW}EBk_}X6*M>*|q-*wip_P6q6KhCtTq=`ob zx9*E(QyOS)A$6FyCx(isRjI)7J6EMg9_= z@ljreS$5Sn^XRzdCHf@tE8;Bu5Rs*PMW1QfG}4u}W;v#f@W?c+Ta=w`vHyhaXKl67 zerozB>nHrGUvi*_2v!(b4(S_shLyg}c48oZ-MQC6ZT&N!Nps?fdKr)|VV3s>S$I$X zL|rh(m+)l0vi^xAzK0)aSWqCB0!;jz@w%UB3;5~7I?e=CFLkA>;Md+MuDCxig^}zT zq%A3piKQqaP8Y-xX8UJ!gh3v?xW@N%ow6C4?@eV1?>I~NG!lQNiMu?6Q>Q62N|UC< z`7TWF>(m6Ou(FJRYXZ{x$TA{*1dz6ZQ-YfO`QEg_G7K#J#$#d|B3;InI%M8RU-~8M zQQHD?ZxB5Qu zElf~-k4W3<2a{wQ<69dboRZF0juvk@p-;Tx98O2;mFCIc7(_wxw-{6Pr((87?4L?31zp4pD3{#NRy@-n^g!V~_SMkLI3RD@@JGO~u5VOdw}iMt72 zBu{v)Jav1_?{5Lg7bb9@#=F#{Ac>my6Zcq51EP%G#n+F^=k)FRdxkg9Ux+2E0LQ?K zkv2t|s2uTz`}3q)q(MT`flqAgJHc1ufM;+;)(bzEJ>ymn@pb)I=)b$r$*pP9b>G~O^>U5^OhU$!UnWw_6FzI->X4J+eH zxO$F_Ik0+seD?ZyJr;@XYg9atL*xNr1YILb?Kkd57a#k^*f|mPtZcL_nq*C(fbWG> z)2lN~t><`A(iWcbkHuFS42*C|Ck>6*oBY*!sRq^f&8KU@nGhaj7+$B*pJAED{B;`N z)45>OUsQ$k2i%OG_pD*n{!E);`Cio{;8$guq$$sQ&Z164Rh|SB&xAcMKI1Y&oyNHG zu4+_FcD`5PnJxO3IO{bt@LFjj-mu!0G6JsQ`Cg}~{4?+kFJmae9cP7-#Csx%>7*)- zQ+^E$#`2Aed-MDF2XghVOa+6 z(Km+Gzf4!kYTA&DKA-1L~ zOPmHam0j?Mi!d6LN#j{aq<(>zCZDM}ZCvB8^GnfE+QA2M7HP`Obi&u~EW^m`po z49oB;eeCJvyYcx0e&j8Aa`u>kYnp_aPwQoPmg&>5gkxO(+T~`r=`)}Hgq`UPtHKjr zq|0)u{B@lJZWR}G1y-b~;R`2!B|h3zm78^};n#U?gk6;rb-B68=RUfjtvf;6zyE zzwslMx;1Sq<>liVoF?LRe`e4d`>d)@);;qQHS>L%HkCYCKf`sIKk`k3n(vaYJ{vg2 zU&md8k>4rn;xjX3T)y+nxU5qZ^^NzN9{8pQ{?B^gzW}}S%v6(0sB{1T002ovPDHLk FV1nY*;|Kr% literal 143374 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≪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 KMNUMnLSTY)z@R7q diff --git a/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_1.png b/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_1.png index 869d01a24c4b10327f6711c4a0fa57cb033cc271..12260bf4b1a7069f3c9d29ce91678458effd01f8 100644 GIT binary patch literal 197496 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�I;|0PrCW8m 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 N002ovPDHLkV1mwM`?ml9 literal 253706 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 diff --git a/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_2.png b/WordPress/src/main/res/drawable-xhdpi/stories_intro_cover_2.png index bc84edec4be2ce5e8b143f3f6416aa3b2737ac2b..c76abd7dc35d228459103d03cf4e769f84e2744d 100644 GIT binary patch literal 199284 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 z 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

      hz0>eciA)b(T21_tPiOCVT3SWCkDFq7 z3R@|^i^ zf$K2B(sLb;A3tto69fn5s3@k}wgc`)R~_9H_mR>aIFQo&M<0DeZB?OIl~Am~awa)$ z!=8HdpZ}$DAS8^h%bT7!@n~|Q#wOnZd+3Bql;4LrA`t6PV(B}Vo^e(Uj;T&i=*)dN z%4u~zEOf+}7vtN2wf9)xP=_=DccsK8#;ZJGoyx=4vqYe@UZXIEYl+)%gS!hj7|Y{- zb5*fCE7OQ_as(pwiC911hhjl1+NKHwb*!E~ywh>gsYUg{z}MwU3%x8AmYSTh6FH?{ z;!y4(8zO$W;+HLLuu@pO#)POn;Lhi^u`^h%Fhlj9>od2?SY^5G;Z$Rh-nNd7c$l1o z+roH9n7$8YRA{-XFHiGlF`$k%XpIozLVQqXT{ii&N#XJ7Q>?$suP@t$RhBoXy)VOG ze#S!lRNxZyJBg>CIq`1gTfMCAX~;=g{#Ivx^ZAuJatMpFYUgpT@%n*pb@u}xz}nX- zmh0d&{0-X0wK?mm&&tK=TzFN&qpy$8+h7ZI>(6?4B}!kG)iH1}N!!TUzjOV?$Mx-F zurI;paqrV8EVRFav0~vc>Ln9$Klq)`rWQg{dxwHp8ZL3VKs=Hipw;J{IK(?e(jA$c zKrYw{5eY5WoEp}Ogd3^V`Hbg0c*A}O(!qv^ENfB>$A5Ebquj|7@b`F@<6;U{rU5bm zt0LIy*C~M_a_EXeE*EF?(zunzryC2T^Z8jk%g?{xC4VKNeLW(qnpbgla_|(Nh6C5> z`g8#YgZvA1Fg*4j3=jAo^L8-!vIlKZg4Ng8!B|{c_E5{R;u7C&2-@|TY z7cZ2BNu<nA{`1s#{-2Wf&&8zf~LvFP8}`quVgC$iuD%Yw4Kyv|MwqmWKHTRqF%cL} z`VTHoAE$3`YdcrgSpFmwN*MaS?!t_d#{&XVS`36rx>*-XjzFk|b)2MUm`wE8o$1ul zdh6Y{q%;tkt|T6elkR?1PN5{qM(jU?t5AQh)UU36k6Z`i3PFLxZU|lB5vy|fEx`zz zjm|3`8^ykbFd&~xis(hphl65UJa8?#W@NZ8M~^e7vAj~~bPCI00Q-FH-O6<5h>H3B zDlRP}8>4V=8cZp0AOWw$!9@K_X$Id4*JybTrasKBQd=u*5&x6#KCZRHSo#!jIV4_fnM`vytpzopHCbb})pyIgCm=8dpgT1_EE0`Mkzq(#njzKjYf>&I**E*| z-v!wu5I*i$eE%)R3t_!%#}U3!WRJlRuPHc6dD^UFY2t-}VeG8OnWcpjA%u_N?ygs< zJyyiQgfYOEOFO`2geUyB{xHCS$6*PlBXz7Sp8!XZm`~y94*iIE7vc^2xP~EKrS2w~ z4#H3b9MiXLzeGu?Ks00$hmxPkI{G*eJILJzH2$KBiL%t)9&(HEuqq0_JpO?$So(q?z&kHy5@VCIQ@Oh`U!qL~w!(z9k zRd|qZYjxHef-^o*cdNIBAuixSS`9DZ&f|*z4Hm1DwTY#-`uRG#IBZLg1Hh~{qBp5)4`FG2|}{+`ej+= ze!b|pk|k~;4fF4bl`d}vafO%+V8LNMD5t5aZKd{DBfK~W1i3>eLR!Q%yR9jdoz&Lj zYcCJXMkLCTypw~WpA{6&zU&Y$O~p63tt`|9Y4L8Cm9ObNOeHv9yS|pzo`!47L+g_) zFOTCAzCG;m3NS6f=j&0bXQ-SQ*ORxo)`tU+K$G9n^ z=?6GY&#L45J`9Il1IN)nb=gu{uB3@?lh^BTAcKPZ0h{1Y#<-Bdo-^K+8=<0$i^HdM z!UYcf;M5?LT<}d0+Rsif=A4w$`n(YbgHE2L(s+keCB(yx4z78%0j@z__8#)*K_ktp zGZ;MF1_R<~_#mFk*T?VcWcgcJmKJgBmX6Z6*`=}c{y}XP35A@5ajWaUC8yYa7F# zzf2j z;bbQN`&*E|g*(LCD#b;3DKGbJ19|y4cX=PnuM`LM)$dzl=~vwm#`r(h*VjA5+lX+L z+QY|LRreLR-kQSGSo@6N&*E;4rNMXY8(ULwgzsAscLi9trrLNUU&EjEdBd~)@5hQh zZ5(l2VVucx4NrZqp>C1fMuz!+^6DA?*Ow<8b`x*|UZ1oXq&MGc|`)`Hkh9g`)ULO`3tAB>P*L~aqJnJK{ZM+6tu^xl6r@|)kTB=9LbAZFK zy5qkqX8?OCjSu&OVhqkwek<@W`E4SsZv)@nv3{|C#5=+^(Z@>vW1pXgv_9Mu4Ziy^ z7w)QX|Npx{M4X2^J_AS6b0+p~R5Ll^0VoX0ofBESZGSlX0`Nr|wm8P^h@X^6Bn_blGV%9ZjmRxf;C%C``wXAgb;5f(oi zIJWXGckS6x|16bJsAIh<-%?(yV6^a1=dt{X_zQJeg_8kZJq{-DbEi6#>L26z@>k$y zDIeD^cfxPLZR|sRpZ9&r6NvPRc-ZB~-8cRkEOA`L>#+2x3P`D4yd}0Q5+?lj`KN&N z(!DCY5O=9edm20|@~jNbF_try6K0dxY2tFRSpSHZkVjwUSR42@3vufe>~kF^lqDDo zZBfPl0e;_q>QbF7Yz2<%F?b4f8Vj#Vc(t^?Pq;p^vb{=e#dm`sO@xi% zC>6f@^3wziX{w$PCxy055f8Dfi90#imT)!&V*%b04q_guu%sBRvxg&^9A*Z%+_Qg0$86h15f0000F|9yuXlH$mw$r7c-e`Ff9L`jj%CUIpMHR={gtx(p*7E%{>ouICx8bv>( zaD$?N>@T&87A;&jmnLvwx2lm!u`ZOHe#jTWcIpDje29bS%slV&{Lk5EU)Emtwf5dbzkdDt_3PKKU%!6+`t|GAuV4R7 zySRNwMEc)+{7rX$Gv3F2ysO`9J*^z|=U3&Hy0ZLIFD>79`~5`yQyqWuPyWgARQdk= zs{hefYUQRr#Ql5yU156F*Q+_3;7WJq@lIQOr>)bR-fQ=&oqKRv=I{y*bf;hUU`9{i z+UebUIB|jV6K=P0QlE>ZjsHemm&mgMupz)$h-$>AzccVV%8p((p4}r%l+Sir`LUL{ z_*~Vu68w|>e;ETq-%!^Daop=uj(vf_6>P@^>`ySd2j`19%66CeUFWVp&o)~9V_}>V z94>yZZH+r{n8vfr!OLKA7mwC{_jmMJZ@-V}2^_t`v+)FDvnyaqVC?^OzD^7RfWxGB zpwlu5`uPKY;16u={zfygZ1>(L;Y(^AhR9IwV6?QGi4Q}y@v_4}%wt3KU(egWgH!+7n>y?Ow*Uf;@;)^V@z zKY_d3!tgI~t>X>8W8Svjr+avK(MH#Fh|Y}gAO1_8R^7)Pz-|q&+wcC}zxyG6Kg0+3 zrjOqH#3w%SY`xz<4Qcb8wT^r5>N7m=zwgzv_6KEp`%k^Qwy$+vz~afzI~m`-_MWQi z-aE_v?VZ%q=k;Dc0ml`FFPpEcciv%tw%*1)xL>{dPT_J74)?}%g>y|{Z0Pen&F8|z zxiUxp;k)kGk)8YY&lM0sI3UJn@p&GI_57Q^`J3&dzwx&|Tkb#WW$-S(`@1NQ?nKX^A zQY~u!71KBY`ePsa*em*J_g+ze#=TeC^LITyKE6xu>F@Zwg1_TgzxPTn-+t$Pyo37t zbNy&P`g?1e>u0HF`d;g42>!0->*+Yr>+Y~z@Zeo*-!A$&)$J3DA_2S)E+o!j`wwGh*fA{jee!UMEto7lyegKcFc5!ckNr&N8 zAD;UA)fK*1FnwZ<-U;kqUHbp(%iaO3mic(He1C5pFY0LRzWNl5dfOLpxEjO6V7dTZ zv_ohr6EmS=BK*YXAL#lo!-cx%m-x8W`v=qDzxVh49>4zj>$uOy;OWz!{0OKVHZ5bCEpS1%vs&;~E%q>nY)vp%-IWIgM>=u00P z^|CR(gkLM);m)ley`NdGw|iB`#XL#7#|>uIXTTjVbeJw0@9+BeL06)5bubcn_q*RMzxHdt#`^uf_r1^F z`PrZSS?TW!>=@?ulmEU$H~%0EgwcUu8fvzXe#p%h1rQ${=3_AYi@*4b`Od*G_%omR z%o>8C_Dvu7zz6sXU-*K4)A2nK6g7bVhTrfT=!;+c;@v)e{nvjz{mQTWN&-a7$E*=1WOdo_3K9BJ7;hgW^M_w1>1?MisQq})5cP}hOK6D)drt=!bUey=c$%icMd zk9}VVBWd3f%tQ|Qqo6-&pXpthiD$IB?c^y4nxUf^rO5$zt#R1Rjkjw=~U zFqQoVh#JHI9(53|Mo_^}`RG5bC| z#H^}Q(>g|b*KDv*^Z1|ofj{?MuROf(+vwq4-}P*aZ#`J=`;RK$-&^XC9NLz|OdY@7 zpyMc4eWAIN_B0fwsBgEw?Og+tSl6x?ub0z$g3Co8h+QGze4j4cw}hVHk5wV{jdMJYVQXu_d`f4o!QIkCOEWyf$QLKDOgPh&C0<* zsLg2FG3&jjE~a;WW!ZykF-#WyDC6jU4mDL?ym-N3qv12Y`4fNWwcq;N{zpIb@a)we zIuu@G7B&G?#9Cmg5sY9M`Ws|1=!$4-%#4X(5De$!^s)$zk8wtB{NALuwHGs4TL)pU z$YlKq0^p1Ctw$I+OA!l@Zekwxd@BUsgP1u8tT7OMHiBv1M9Z}Pfl89-iZGP8o$1{O zGD+LqgDGo0AX+dZ5He9Q-qfEv-!P)B5${~{CihTRq+y|tbED+paaZBGC-YG_N)Wj9 zPZ^)VPA0tAW!CT633Zxhk(-rc9*MUJt9I=HgB?tUClTLpyU(Tf-tX_mgy|xi)S0Lx zthF+2@8BE1wBKI*^Cx7!_|LnGHh5%|3J$v?SKWH(hLGK?lD+kTy-v>R* z5C8BFgNbzVd-8fG4219e-M`n*P%e18-G(|I|6Bjacfa;c|DAv8UwnA>t{-w47g9MZ z2%_ne1>Vh0d>j&gUnG7>SDMD`weMNxo^4kl@tL^E2!u`2ZB!EaO5->t>4Zd>ft9Hw zvC-345@xTn(YX`a$ihIv5o5Vglj16QDF{`HA@@3Gm`E{P;l>G!{HzZBdnlswC~4m6 z8+4va;x4(VaZa}WTDwB@G6fpMChSaBJA`Spaq*s|hOjX_NezI5x5|Xr!G9+WfiB>J znv&>KGnU4Ld-)m0Gn#P1$NxgXJ@Edb4D7`6vHx|I6+9 zyZ*)FPuDm?;(>6TzIG~W2MDyc<|G&h8}muxm5u}sd>)+0WY?h{kHJ&tpMpp-CZdqq zGon$`0W_X(sMTsl z^zlfFxS;0HPN1$kE0HuUd;NsB@=>WKw|Ez0z?i$~(wQeiqpF^qC0fvKbyb=w!xLQT z0^YsvotXKuj3m*bZJW=DiOuH6EtyW#95T=GxyB6U0VZ*6mebTP?Z*qH6_-{NYL=Gx zrMJHN_x{YM{_-FFONVK*t40!LjRYeBW67Z_!+=ku;q8+QWY9}4sg;oyX;Fu1e-7qx zgq3Uv8Vb{T52w%gJ-_!~`ZEu&y!xjPmCu-mA*giXORy|$de^`-xII_3d9bUd>Eoav zI7p9H9h+@JXNv7VgK$)uYMDXtku%dl*~`hLWT7!x|5d_&tAJhf@C z82;f;C2M|7ZTph7UC_~DdX!ZVZRcF(vh0o zObe}ogFvcFlE1mZi?ZE#cj*VnJf|QAv1(ALPl<0^<|JXOeUxfrv^LSX$^YjZ?lecd z!lJ_&V@gRB_Zkx)F|S+44WYabJnD04 zV$l&z1{;UTGLCrm__lBRzMtmt@LdI(_-`DL(rhzF|sSo(8Ux9fz(GovyVr%{L0IL=I|tL=r@UAl($ zu@Xmnf9p((o?;}FQXh40AxV3`YS7Z&r#4&ONg%!z<#U@|lk28MwxycT7^x9%+`K7# z9w#q7*r_HFRv0X?-u}`t*Rqzrl9Vq;+V~AlGHY9U1<5NGPox76RU_ShlgI;EP@b)d=^xJ;_kHmxRFljJJr|i@tI%6*@6OoEK+~p!qu@_!` zv#L3oAf~??^H8(JG>?OMY(Mxv{gFStJ$vTQ?WtJ6}Y^DT;RK|nOF7!?R~iF_;*J4wl?FWZiL#x#%j%r9}hoDasR5MHQ*$u}9~q)z_V`sR$ecdi(9K{Hs6pZ~T$} z9g#=W74(PeK_fIf6`#@^5sB1{y$$X1`uov92+ZS%DXSetAO7%%jYfibj34;HKmP}x zAIxK7X+$T^-lgJbQbeT<)c(%BaSsG<_lB2JDFwBbWPOK9vyqYnsc|r0Nbxd{R!J~P zK0Zq)KjV0tk0=jH7)5W?K@o_^$grK{b!pvz- zss^=<7}MBuY(8!5A$&%NClA`H`qX$7kF_pMb5Q*8tDCDGE)Pav%oU zO$~l&1MNI}c+Wro$shdlKSWLQIGD#|?P^MfY9UJR@QK*;%QX*Sq9^a?cW57z38R|F z8*jWZUVH7e@h#u+$3FVeZ}`VQbqw|!dQeGn(nCU04cOE@9<%fm$w|#iAX&u;`);?3 zD~HgpKEyM{2}z{)0!pNCm|iUhxFYVWiyN`61awcrnx=fAcAn~{=8OfSjBuad>KcrG z#$}a)0!B3Mkah(wxv#&!_k0qr@G3PqsBMgvu!eb(R7x_rtm{;#KFM7H*T&x%QM)4z z*1NR)55H5LCg7Q5UjZ|TqS=;vlc#ZIi!pC|Xdo;ttg8&B<%U_cqveAb(Qo9D9F3mf ze!SBWcBLU{W6Jin7*kI+#Y_GDrVWX_`M3VokABB5{jGodSC0N_cI)j>1a{3{Jrsle z)1UtIq>W^6JVW)=%##`j73~q6EL7ae($}>PP2c^?`;j99i!<$45rWqwh%J6 z@kXm$+RiMQTq?~PjU#1utoDB8@4=^gJ_nLgj38+n{0WZkh<1&X^ey2J4#0??Uct;^ z9pZa>MyG4lmSW_SQ+5Gr!nVH$SWR<5G_}paETOG6ZhYzo_m9vNT0LdU^4zC!F;K@Z z9oh$f^SA%e$KUe!o&P~edZZmEi4YQPdQQfq+CnN$ zy=$u4K$Fx|J5!1<20 zp(fg`4ZtDX>{kInk2V)%vd%)xCmHMlqT`#x($Zg|!<=gF9*lgarkbOjror@PQfLQE zk;`B{0GK%3w3m1vc6XY>`935z&oJI4;o@Exm@3p@Q38XgQqwDEg^V$zMxfP=v%e&N zK?^Y#{G4}Wpqs|+_af_ascS}?5kuKyEXc93auOQB@%zQxn}n~YT6)e?6_H3YNDNAC zUG}p>9q_7onA7k7!~ft%KKALq`IBFafu~PIwUFn}pUXk#do|IEQ`jOxMCpzs}fsjHYatB8IPGk=Os9{r8>eTK;2-QE~<<@&!NDcja zP;hZ6c6$-7TSo*5uWIh?n1ow6t(=iS%F^W|w7(p!?cJT=7zmj}8KE#MSTi%qhwo7h zvWU~P%Zo)zMuzz2@l)P|M!;0xshwSjA(uW|Wbxv*6Mp8>6o)SaCoqM0hbg4B)ZYnq zz=H_+BZ~aeLX@rzjtp;aT-x5?7USU33Px&B=tI-=n%`(NsSFjNv{lZ?#3Zq)gj&~j zbAGwwk`S*%-ZZW$Y~A{3(MC+3;qO*>uUX4XwRWfV3-GnbQwwR2?4#sdSEzf2$$Ys6 zOLW!{KmPIW`(qTS6|`*EVZ!iRZ@q;!Hgz%4C^cWCFBF)=`s~HlN5uR4K6zNpLuP z3B7oDc$mVgeeel{Ze&wv6Co=0Kv4IeI97BWp*-!9lKP~^3rMJ`FcXOU=Hw?r9~1dx z!ay!wHjT(7=h2s~2y4xpy-J_Y-}_vjG#`wOox8x~(g>%n_;~g`9H{33(;Dr%diGBI zCe>scCxyf&;9Q5VbL+HD`r zs8B<{_iCJ`XwC^H;g8~Te~({p{^(!)f!|812ziyzL^AcAYI6D{O^sZ#uI7D3-;;^x zYFhPuy#M|0AMbnL`}ljm_y77`+qV5?HBBskAPQ#E3<24t{%#yR0oS_Nr2@BsPd*BA zd*1RLR2kUapQps^*`HSTqQ`AHK0k zTC^la0&`pjUHx;I?SNNf8mTebkUBFdT*LPk^RBr}9GWh3QSgpmvWK>E2*U8`UHV;^ zr+IBp-v2-RCwgIMVcVATu*TJlaSWk#@_qh-}IfPu#1PdG6)r# z2mlPCMuJiT9thmNUF!%{(4aT$>H+2;|9eii94!f6Ochf7=u}w_rfU9iZxGhdXq+bKff>;|#whGl_8& zgF{tN@6p#5K9)A2P6hrq2q(>epdFU^*~EZ=uw{1Df<`w#!|~7X~6P=kaQWIkzf`vm%BLajj@D?1O8H)Vjsh+@BWS7sz1N(>%Pt+sah?ZsZz))$-a?zL z$Xjq9NO9I6n9+zt{|hB7wUJ;XT}{sw1e!1veiujq*zH*I&?85q+4U%!^tK{aGS>AI zkCRd=XL3K14K$5%K} zl$(7#+w)gV1Npmu_wU+1&S z8FqBmoox&=qlz21h)?vzYCz~9WQrqub>yUe2G&Zv)BQmi3duMWx${sT?Lyr}RqKIV zQVz`3=0ec74wy4_yBRgJLdw1~OW|IB+``eb&&DHNN`nY>dqVFPz6j)BM6`x6Z`#%# z_a&JG=ls^ZTb+{-V%H90o-{fpVdf=psE}CpJ>gEdE=ZC-_T8P5@UIlCXzGV+hHAz? z`<8=-`B#7SS5*Vq+g6J99UFsDL}4%UKpq;<^XU)%;1Akw-6l=Lx5_+lwY?n2(J()3 z55L(Fx3JWQXc=264d%g6tCF7v<^DOX5HpLS&nXlxO#b68wPL#d4 zE5~4rRo;J=27)y2eb!o?0Yo_q4>FwQ%19))Z=;g<=8JI;oRxtq3W-Rz!rrHZ)hJB!aJBpa;n45 z|2oHo+A1*Tox%4CDQZwnnn+26rZV_$Q}LP7z9rD3Nf^$Rau~-gTk1%&t3M(LMw0PS z>*LJydcv8RGE_unjEei)R1QE%y@aG7GO5>kd&`AAKuKy68bshwbAc6QoECH6534t# z3q47S7gmJ)l~QY|T|lyS%W&0eF$t+K8!kx)G#aK!tB{uKLlZO9XQkGR!ft22`U{!D zArIi7thtdknspsf)lE4+VIsDS=hDEsIyVZbwa+_GF!J$@jGXLyJ=4n%j0C-b{;{ghvRhdjx(U@}xpWab<~ zGO-zqzxo2{w{uBFo3p`LU#|s{Ka;$G@U5BMoSRI22Qi7=-Tal2eSujrYqYdn;RLn* z#=dvUN;#p%JK|;%V-sEz#*;L{3+-k&6Or(50I&47G6cX(0ye63__%h0ZMzdfxq7)N zvmeCoby5l*30rGt&*9PfZnmt$0|B1GKY~Fx+&ISKzC^B+d!|~L$7eNNPedqak-&_h zlI7DilUFnvn+ElY!JX*pvM5V9v-b8@dbGJM?uq%SkZufyB*IudqEgNvglFB<8NSLh zpM#SrAU%|AZDiVdbBcyKip5dhmr6^|z6K-6kY5a|meiM41S#L0suo@gf_BF&#uH4f zYYAL|nB11YG?{w8C)fF&pL;}nM)W@xZ*gOO%)|?$=n;&X+BuS!a1FFNaAY`CvAzieO=%bAutqQ2vHy21aQ-Lw~BrW`ouIrz%8MqTNbg zobcq|s1>mh92h%QZi<+LQyIix_<#ICdg}UT|GB>uspmDOOi4e!|DS*14?X$*|Ktz< zNMAYN(W3$Qx*!#)#J6;+kMe=g0$Tv_h^*>)N_Oy891j5?8DjsbKlP{V6sqG}PoA`U zrzni>%=`<#@C&-6w~?URMxox=y~BG;Za)P<25z8BS03AbZ}zIUp$K|h_T^O7$^ZmM zEO0U;NF7T1ut{a2{2TrmCeQ^4F;+%22_&fkc47&}!n5iQy(CSYG)d6Z z($`*W-i9(#_k_@x>SkvweQi%4vvk-I03K=QzO9w1!xYex2KP=}>7$ANdi^6d(7*ya zqDIJR;!y4r;>^l@DUH;rn;}G{;Y{NZN}^dE-u>s^p2JjiW+sqk-k!{`ktD{gpqI7} z7;Ix6F`iY>U0u1q$|6YBB-vw~%Tt%HDTB$kC3B{5SeNP9=!%QUcYM}wb(ZS&m9Kmy z+fZ5$=8;`IA~6(urUHrWy7GYxUH_sl=&=khUcAubC+Y3C-=;Y2jo$m-_flve$vlGh zr^g?5tTZG#hvFJiBxSp9?}X(5&3w`0{td{TZTXEn`XQf3f4E7~sDFfN31FuJ4`_#f zM7Rww7)}bh*!$8asYolwCFN-K@7jV#xGgB-a7ylygh||U6M+Pc*#iHAXffbqYihcQ zO!`ndBQxyV#TZepBayQ8-Sp;(xdZkb5hwHfi!;2Y5Kt0xs4_b*5{4-5A>=y(%uoYc zlTwkKF0iJ`+68zC$y8!=W@J(sbI|akJ7haU2p>J06&9gXjhnIc< zPxTz9-tmLJ%~hcq$k7hJ>s{~C!>#P_Dx5&s>9{ix##Zi!_5qrbk9_1Kqj4kar!tQt z#B%`WE2$0$1PSFd2h2F;VxMg9RU7fmXuHx=W$f65Ak)%Hpb3no3`;N{X&(MS7Vh>e zoLCNQFdww->NFAL!5$g|_Mj{+AYF{c*ev&j;HQ8RS&@)E%m+Al!C=9O(u&ft?bmRU zMp(tc&j_-<+w0&-6Jes+-oVR53jwajh16U|(49G*ckQJ#OPpV_aT;@SGN<72uYgzM zSb%j6kkQn1;b@IDle$aXeh-ApU3X-(StdYqBl~CkPE8O+uovVEha!}H!OvcO^*O!q zcfL$N@e}{iVG3f|WDVK$z(@eo-~Zab{@3Zn;rICd@B8)>^Qa5VTN%nNoT(8XoRU1g?-m=#MkHQFrnTLpU7IJLWD>JBtEnRcNn>(Fx4v;`f77_FZCRrtSOp`Ye42DArBrDvLy&*)66|B<!WW0`q_ z>E5ukYZzHS!jXKPe?x6Pye-bfie;t+BZIo%#+$?#?fG5&bEOe*?9x`+m-nfirNfkY z7Cg%k;$*>e(k{LKaw(Lq{yz1r!-y#JD5&9WZ#R>~*w?%$2yfUv(tubo3DrE5dFb^6 z-}fE%{o|kdn}NDvt|D}A%NNfRKkyy&`@iqEU)E*)AU7EeF2l3F8S8jLAbIxj zo?8#B4@6oH2rn<^6()@Rw%sy?Ljrgj zOY)~~=TUiqg{L+hC}BG@mqeS9Ns{orKFRIrkc{M|{NFv8gDldOLrQ`<81N;Mxe{we zN_ap_7O7i8QbKx!RHN{^1m;NtgY&kC5;Z5_zJzM=Qk@y%nn$-`z3Gyc2Df;>uUcOJ zJ`tJD+g>KZzOcyiJE0XMQ|D9=VD?a|)NOu~nRUk5%!L&<e=ZkS2v_sq4-Pb88x9QaS*snP`~D2M@^Or51>`+xVfRK0$vRb2cVrr% zN%CmIjoqTe-jgT;LY~Nop~^`TTW?EXa$HKS`;vTy0Ya?7bi@%(kCU_yk?jWJM7PCy zAx`OywF+2mTbd$2sh%hEz~9(U6l*-%w-C)AZczxP3EtOZc1EX;zeTg{E~(FT46U*1D4c;BPKX1J`86oomMDe16LE_nVJb34r~YFxkfBc*yz;^Ov!_{W)<6W%HF`OC+9=HF-!V772bnOcE6 zQZvCAff-w@I=-5#@PAlT_3(itZGZmrpU*C9HmY918>)I*NTq%EOrB{A!=sUh!&cIJ zYW{5hs~`F+pPkgk!Evxrg&Ot!&| zWImwo)wu~N*!JLCB0^;9g>5Z3+>cbg0Z!)SAyPCeQ-2tfBS<}$OkdZ}3p=hO63KR& z&Z|{C{l4${xV`_AKl6)Jj!tja>I(t>y`TJMtM4a1_4D@ko_Os{P@S-pTMZodw%F!^ zD44f|i3Qk6OkIVi`}qDpf8hr{`qi&~RR^RlVSMlRJ`ssYi8|$hM3M+jrcx)W=6YB{ ziJo(-r_a6l=9~6ncyA|8k4Z>L$cqTf`Sh~;gv7m`v+dfsa7z1-gtY~qP|F8vjfONg z1n8cBae@!$spAMI##GBdqrR^~BZs8P7{A?&1Cj$C@H-a$7BlZEdw*IC%O%&KGHE!* zB~pl(nv3Ncc=Ur$aso_|3JPFKMWt5N$w`a3VmCo(nzsw4)3pLx`!Pv~-kZ6%Tr=S9 z6LC6<5#f?l9Cxs31Ag1V+_VIE(YQI0ds9rSuj_O%%{Z^3#{`(~vZm&Y;?pLS*{WLS zPyNh)9FEgb^Bwi5Ut{;Y_@mq}npT9hT?3IuXgvherI-luqTy3RQYyeG$XbascQ7fZWvTv0w18si_N4A{o1HA%H6@Dt z9Vg7LZKOrryF@YHDX!EJIWbBBpGo(pu8f)j&BSx5F6?6LM8_ zjScU?NI3jVgt?XMC-4kJRuQRSvN99izI*pF}!K3c?&dS-2I6pE>u{@4c8D zx1@L=J2WRNgG@vz!XEwaY(C3@zV`-yQ=4NRu!454jZf2|Z13$d2{g+=0K>&SDhZBy zy_pv6z_}^e1gpGU=Yyr-NDgu#4`DQyWfU&P5d zExb$`1Qh1yFkdKgx)8=yErh}cl9T)T>#vJ`;^6JPpA1AFXc{{gwb+kCjUjL$y@GjY zqoR%KWNv-ZcyApKq?1k%mCI0r3vnith=$wFFr}QN!KDR~6O&F6uH-E^ILs1BU^ApD zQHC4A)Y2*ym)b6IBp2=Zic2`n8k0zHNkth#!lZPuQ0bnre|tV8)8a)+>p^{$;Ry{U zlI`|AnGJ{EC^HbjAY)lLhqNhEV=t%=ChKYW31awQ+D(pynE` zHNxiN)|jMH109fdti$jHX*k{iM;Ty?K@EUDke7KN591DOU@RWabq1|D7RTRXw`JG% zv5C1kI<>Vc=`9v7quRvAsGD-nOdHdniD=Wo$u1p0IL05?*T`(qwt1jO)5*X*tP?zK zBUu#pO{KDy=%^BA(TJ#60m?1GL{lxjD7&tY#i^l7!D-n#O0{ zp7tqqaM(VuVG5tK$ zNoGF_FL3D>3vgtfUqp@);!?OI-11u(nvrpqz<9}T4#w!5KYFv$jrJfCeic4J*YNp`PVXoNy*v=zWwO}BrP^_AxfWv4Q_i&=h@?15Lyr=39 z1vi6Qrs>>s;Hd^fOQ_D7g9M^FvOXNop0TP%`|*7+3f`^EGh;H&3?2sF^YVtQ?91n$ zlfR>kMt7@z2$dID@iGY02T+JR{mJRf=sHh7|QWPs(aQPZ2$+mqLN$1-B1bd6P0MTnlLRfDz z@Y2Vzg9L4UJ3PCKz~_-C`0C{}T$iqU(c0g5;|+77(!!S_0+WAFc_2|BD?=t~>FY=bAnciV7G`(tb*ZLbX7#XS%X%z!8ln0hd#p(-^QGce{61PD_GCd0Jn z#~^zLJH-#F5U&$n2e7wiecB);In`XKr63wYN_K4C(akM5A=M)<5#OH>HTKEqVPt3& zyi3~FwXyUlY0(hE>QO1L$5KF|3^12z0l*oNILw~V2y&l}(a?lv<^YB=kgE|eAOfQ; z?Fswcp5BMRm^79~r0xE789H63L!)|qRP)rCh%uo)R+@!s$RO7R=;&gi+%@hm=4-rQ`s3S?r?P< zh-RQ_s3-g&c5ed}Q%M)4q>aK`0V$N5(FT%{?^45UqA2dWgLDuMkM6sn?l?EV!{JvP#(OUVW&D!3cZ-9(or``Gvv>8F?wq$HQ%ssgIRvpG_m= zSe*&9qLZJ9a-b6RsdH|FMle#=($zH)3i`wDGoq~3`zvie0YWnfm@^l}kJq4rNsNob z*v|0tLjCvt?)P&WLaJPxD=nob*5OLC(Eso;F=bSyMk5iik*N>;?=uXEI;<=LLsf@5 zn*X&w_XBqC-}xK=8U6Xc`2V-x-}_I0>%kO0?sXjh{mlROKOwBnrqDf_7i+Qu?2yF=&t>=nbs_y{F(pz&SE#ZBcBz zpc+VLB9D)csz_Lcy3NNi)+1nf;Y8IOkmCV2=3$k>2NIhpn-8S+0&!_C+50w`!l9H% zt8Fjo&TxPNVZlVaF86Ct91ywAqyrwip4!CY5hPCdDq?U=DsQc?<)BO@u>qQcmN#ll zC)~jUL?iC+c+rrxzS~qT1PrN`+Y0p6bfHzCKNCVDe4R`AB_*TfA_Q@x&1vxz0mLKP z=ag8*#Jhi>79|2g8+*jTi98&XjW`odT)Tr`5#*ZZljTIFu(5uKm9Fz;8fd7-N-lpDa{wx_kHqP zt&N@vkD7ZXlU`Wj@ArZhV`6ve!kuW&-t=dh({;Qry1uP34@1-Nfmj|0*2x8{u=|}h zyP5(gYF-h>wRo^5muaKwMBT(!cVH_%rgkO_^y8R7we?4sBjy+#RAvc<;}L2#)hS|T ziZoNe*RFW=u?bl?u-dkWZJhuh=SWCRLfr*$EgMyIqJnVH@@P_LXBTP+BIz|5NYv z55_rfkyw2xxOCIb{T=z)dsIpeZQ@($d%x$~^46z*=5NwZ|69M9nsY|whBKz0{42je zKlw91pXI;*c=!8%-?vRe%KcZH0JJee5@2>Gq1xsh&evdCdTBx^*0+TZgy2NQrKdAQ zUEJsNv@5$Z5al*;CJd_yqnioo=U^h%>o`jSb41nk(K;-tYJ)(5EP@G(3ZOJJ*t=6K z7^#GRC15k{^#ASawjY1Fln$0TJRcj;$a{~ zlZ=&E#yPl2mFANEjsuaR4@rnhX@_!_7t>0h)zo|!64uSDN=s=#rPAhB37;jBi8$BH~qG(u@PC-6gR(CaV&lj#SXIY9MND=(dJh=<)H z1y0t1zNE|}G!W@wT&%|JS*W(R7l%_Pn8Pl05Fh*rdvHX@i3@2$P1=H}f^jG_!e-6R z6x<;?MrjTY&;qDzLa)j<`$?YN`_bE4fbH5zECFcP%_;R;pBWCsU|@|H(wP^-?h-5) z88&I*no?6cZD;wAe8dw$(1j$;k4d(ffb9wmp)YWpC2_Fk&OErGT>dfI!n`@m?TN2K zbs}9v*;pp#R*aldm~@P=I>sEaA%aiL$8^>tVhk4=$?BJ3Cc4%}8XiO)wHR$Q!Qz`l z0f$-uZe|`o{d4rwhxP%YP3@R-k`wNF|0h57bMzBG{d1RfjmbGblDSs@&tsw~G+yQO zTB9&}skPCSGxnj{lk`Fkds5m(X>7}OT)YbtBDw62u)*h8h!j*U6OcS!_HQ&!??>XiJ4CNUzJ z%xB2e<)A{q8vhlZVEAR6a%>0rV?=-W5B(Dajc46RD4`Ewn%ZjD&?q}%xV*R1 z0r@N#P-*xz?T^qva+>vMhdAD$)4zf2N(0FPx|mKcEa%rtQ`xmKRck1KYZ}0C>2C>M zf}||Z-EjN*mJ$fz#_VBF1j;aG!ilD(U%`B8?}`x#N&6(>lDQK_ZUT9-Sx5mu1Mo!n zaBs}awI7PUL~j{{SlNaXNSQKMp^gj)#ht+r!`T^~?1w|8cCw9fjB#lyDYetrz$u=4 znWoYZm^cutw3LxaY{b(LT)U#CAzd&JT$ec~fO7aptUi81W9kg7CB@OC5d{C^h=bV} zx^$g265>^>(3c--oB@NYrS7XH!r|Y^=fv3`v~%*okZTXW^E-bF{m%d1H_~_hj(@~b z8@&A>a`g*_uTS6qt|Qv=T}S!f^*evd1@q{02ft7G-HLh0x%@J&Ha^{15PwVz0{ej= zsZ>8|zDU`Ar(M~NJh2W&^FZJOL8avD@s<5TQgBV-` z&TwI>dH@Vlu7B`M)ucY36oG_;Mj*2UYS)OkxipwV+JK72%2bxg!8fEc7wfZ2fk5ZF^_J}jwx{eFl1Ky2ZhEJ)sBIpT9+=x}GYu=aSrZV*bbv$*Y z9v84kQU+{VTkvC1_9D^%gr;zE9;Mmj3KHqy>pGh&++gF0W)vDuX@d>UT|5IuU|4px zi|I<)IbArn-*$TG6~P1?Ku>+;?Rfd?#&BX!6$(Z@LJJ5UcuM&{=TRd0#3TEA-;U?{!(E?9}VU_e|W)@0nf;HXPx zc&}Wx8A(yCJO~up$KK&bM60SF6(%F<7soRkm(kmw+6^Wm-5zXZlbPx0WbOyG;*ydJ z``eDT`n8<6$N*&-)B7uoTzix_96UBc*6;mhpWE$4{Qbh#67AB~IFSnv+c-$EY;y*Z z=M#rx)DEZ8`lQaBk#=l}1q84Y+^Ef%n76=9kA*^lA>14tsIfGr|F8UCe$PjbuiL>u zUK}{};)t?h?~fOU1|kO&vA=b7{x^Q(H}2uuNW?2;@n}Hz0*TpCwS^G_Rue`S+Ng(C zohi{nRtL<9s3=tQ_$2cXKL^B?N+V{iZ<9m2U58DGh zd-lvf56|h@_WXFR-~Mb1g4f>ePC-&^{6t$Ma$D zckdXoqhy-XD}2GF5f)e#s7SNVaT6zW=-Lj$pcwbhBL8wzQ$ zw%~?xF(Hzo)88BKud3^_S-JT6Pk2{KC(1~8xV+_5WtBbfV z2&Hq z{on^bXh1_cI{&(kp8ye8nKzyfp!T^84T5?VZo}8MLD=@6 zG6Dj77yD^IS|D{C6V!XnVfXK$;(~b~XF-Ts9)#b^m973~61*dcMB03e1q4b&hyYLn zUG7y82nl};`naS2(Kepv%tgD+;Eek+N$yT`R&S{M*feIk~>tnozyu}ia4^}8jNGA*KTa@$DD zoKc$xPE>?(u~JXDl~lfTd~tfj2PP#J)un1VYIkIGr&P-UMVp!N%7*5K*DRYNp{pJaoQOvSJN93G_-HP43 z&1)`{&q)%O-MQ7d85jZ=A|}j1IBfx6Uyw!(j-`rIan^FnDh_BFL=KX*1yEznJ!PPLr4OjF*D zM{hR5X2$i|+)PpPLcb5wW*nx?c;@DYIZ&G!0;i~Nw-^gh%}28NvoMwP`PLyF zSuW7z22blR#x^oqp2sQed4aSu_i1+5G?D$*|w#OFDrbV@lfEp;=*XQu+XWy6~Y4rm| z+gK>T?IqC9kk zP}isTWT~@{`wA~7jj_SW`n+X(-LGPr0U^H#XBmc8mUUFmnd|op+B31y44MbF4WaV< z7Pp~o6Q@kM(|=UqQ-%U>VFY4b#*cZ z00P&0w_8nsA~%x9_GCOkkWGd21zbWj)mu~Dhq5O#a!$<<5gAF5kVbcB+Mc%y2^j zhb)nd11_<{9C7Xt*V{F}1529Uw=gXSSHj_F46q;QRX!t%ND3{CeD)K;SGae$cI(cN zg<@`sDeLb)_kaE$eDu&jZU+;wUD;oI?X?$Q`qGyyHqoOn`Z+WZ(W4#i?#jMik;a-m zkCl4dv(~Ou($q921ovuC&OOJj3RcL=wURV35&%_&*|l6W%`^%8DANcc7?&fQ7${tj z4Nz#(X!E>;rlEH1?Ih75Wf^vAYkn-!tHTI)<7U3J2dpq|*v@#KLhg!)ravOWAbaP8 z7jmVfe!U#(EfyA0Eu|l$a%#rNl|Wgp&prO`L+lgC_&e2#@(HaBrhtY%fH9XwHy4ws z{q^e41tIW@x#=1s9Qwvs4K;Q*6%(#vCIy(LF_Xlma9YB_4^5ZF_XG(X$J#K7esO49 zyAU5)v=^Bg@Anil1Cl8LD`)`I_2WMO*=Tg&P3IGCtNNi*qdITh7 z&TveQtApj0b`6PY<*ZT2K4~;N2eM2MV)wNWB{J+0J~rBIc4?cG`TYVHfxGR2SAZcj z7FoDsr~8RefY9R6tvdTFS$Ah?NfgyBnRe>VvwPY77-JbrY7LzLMeY*s1VSRhS+1CG zNAP0wU7|A;Uo9p>0S|6kPwPjl&*l~p;{c}RaBLL~1a3gU=`}#KTyT?23rBdk9QYC& z1et$gAI2;;eh4i?8VyLA9%+6X!;cN5beyB+BnF)twZmbz4)V^iUu%tf58*f^+QE&> zbQZWY2Sl)#?u%diVzPNPVKfS(>ti&@l&|&!(F>ai#Y$Z3ucosGCo1vWkpa?Ef)*mq zo|8q*e=rHfP!CfO_X+G=H8?INUQ0&S7UU*OkZv~FW=4%sBtgn8>vIc6()lY?RE)e1 zWXI~)6kRF+kZ(F%j=Xih5nl@vj3TBJw(Fi@m}U}Csm?Sp##%cub)uzYLOM@fw4TI! zf;K>m&5P9Las&)c8dFtxmsw1v?A7!51|!dnikA1+`q%q1F~FGjy*7rbm>8v_S#~B* zzABu>`)hs3S>ma1({flynw;X)ByNO#STUEBFbzX#gb%{#dULIjWHwcZ6JLCN(N61A zNnzj*V%1QZO467Y81Vu-2J_Ipel(Pe6BzXK`1rW4g_)*x60f=|d;HWWjQ!A1PG1Xy z{$m#-?~ugixk8NOoDmXz)M~}iJi^v=OLC$`1=c@(bLEkfh3ZT+?U_Om z=?SOr$n6ioJg70-#ylc6p8YlH1p--<&_=>7f_;eqaL7rUU?wELg#cj6C>Q#>UVSdR zIdDRr`K87<7ueomP`$n0F8pac<|995I3QY6->G%9H9Y|Hy2WB45Y?H_#LdBr72;TZ zyc3ewd`HFFJ4evYaN5|$Ja6z(NqSZbPP=+lm@N4Y{$Ht^rd^ zKR{x{$M;D^HYfb55Vhl`9P^nbogm~ z#yDcrU#wfWjM13QVLX^{mDr`vFgd~=0PWyI%7bL z9+D@NLOW`VC;dj#P!`Njy7Er1V-FLiFX!jS$2=Eif)ajA z3E10f5DBT*y)Es2){R*~X@gi|;{t9Wi&TY{fln(T_2dy_>UN z9LM_>_w5~I;5Nd=*-ZmGSv5wSc`4K+Xh4jb6V=DCID=a|)Jt|r>7B{$C!DA;i%@a5Zdf0&t9C4|c{eg_*L`#OTxPy93i{Zc`vo(u&iZOdAT}(71ke=CSOT>?qp{ zYYvEhAKa$|{&L}9DeMPgyn1-%ToDtjJgSM_WR!hpTnAqb)FMvrn>7sFw$T_ zbq_d)ZCTQXL3G0Ds`XA^pZXA&hBYSgwwt=w&qWix41-7Dn$|xlhtX}z5QTYse6$BR z7ls<=$*tg-GrYDs@4QxE$ysHZddHM$=Qzp|4oLV)hHxWR|G=&{;$mLxss(wPb1hTe zM;)D*(l>rYu*ZL!bB>c}B@xOA)*Yxt1l0v@#7Pt4S)Yk$J&g?n#b|@UFeJ8etTF^u zd=#=5vtlSZA+=?xOA@}hePbj3(Gc(IXpMVB>CD2Dt@vWT#^e*?##}hJs^sqdo2Szm z+PKdc*3aa3qM7*aeX@MQvwnNPpry`pLnO3?djnjRK($k?>n&)%}%Le7<2-vuaWUU ztdWv36iC8}85E%*ijljP8x;4ulRHU|AYvTHIdU@s)E)Ih%8~CAK}q0yA^reuW6YgAT0x8K;N_P{0aw$L^ z@I{w(T>j0_sH$&+?=!~hdx4)gHZ>!9E<^;W4A?#(G|o)a>%ziOg2o-@>^O>41dr$- zs#E?jTKan7_)hJoK2m*kJR%@5+U=~tmbCRWXM zce+8^Fo2NF8xV*_B-9RfB1(o+C%HKUm=FS!R2iihd34gdw`vzebV3YVdn*d2W9{vf zlj&OE9?Ph&3ET9js{r!D!%Mvx$>v;Y5*qI|J=2=ME>+4#G;Dx>JZ(Q%pY3}0gjQvcK>lm)?>HOHPf(I9DiDX$xUrcv= zz+|RftX9vOAQScV*I!2^y;ri>NhYm}*eYaIKX+JWXXLaeyIK-I-ix&K^&REZ9^s)^W6JGG|lOywswLaC2nQdvPFHmwuo|x z4$J#pAoMUhsu<(m9L{rd>g!T=w6P(<&_ELEwr?UPiLbc{)!Oa#OMBgseW0%P_89x+595PG5~1n~qGCWY%T^ z(M1ioDd!}{I*UFDbiSOs(tXJgm9A0?zmq809h4oxy0n|5$>`h^(v4#AUTHe0XO_&> z@wK-ZOA74e;(n<;Oyyg&;tEFh!l(Va-+xNNp33&<4@trfug>re7zuut4ob0q$es)) zFv3z?M}|Ft3+tFl6PhnOG6Nb2BfZ|?na2ya{w7?S3M0^10y%5*r2eBKd-2*OtniyJ z#&C5d)1s!S1WnZ6-Uqaf4Tr$(uI7Ly9Z^z~H={|yH@KJ3>DQrwFf=X(`2CKd^rd(51Q%U%Pj-U z!(-Y@lL@0mv4ivRj+AP64YU|LVJ9a&b^O8h2q~u^wPnZHCCAT%C zKA9Yv>0%}^UlR00fRn~9iTszml`kYG)6>$3yY8V+?)852`g<-J zKjHr>{8;D7i^*l3BbGJT-)-}!i zFlQyaktBzm=kme4xFg^3vbmc~Y?J7uj6+Rr9Fg_xhme(1zca!$39U5H$`e`><*>1_ zwb(XlVd}Ummzqv$eAHkK`Vd-}OTj{jE*S}c>84^FP!_PHHcrJ79BrvrB$8Rg_1Uv$ zqMJe=&*k~^=e8Ob=^dRuF82e8g6qZY({94_XzMAtzY^b|v(1;&!#wF~>S)|^_I5A5 z$lkO`XY__Hxw(WNW3H%(30b39LwRbCN?nr+Z6rxDA+*zaxdw(f|DGA1SzTMuHu+8< z(~?<6nZ4R4DscEX!w%kkZxGwZW8WJmr6#SSmQECnVe~cP$IRlv6SYS>O#Ddj8A%RK<*XRyAIZ(0QB!sNh?S6UQi zYHE$bSb>Q7<`paRSNi)X`C!YEcL-Su^;922POp;K)GoEqS^~aU4=&* z*=E$Wg*QL*JnEe^ca{Zl_URFqNRSekWW($7dZRy03{K-2XJ!N#jbI?15plql<6}og zXxpP;?h?G(A$-GRNSINaGDwLd#njM8vfLqV#iHTgB5Knz@%{b=$ zyox%l@1AgH)B;C*ruW;@a>uob7WO$Rq3Qi3FbjI|-Qv5aSO+m+P}~_AT_8mxI&fnke_vjn@9fMd)v^K35N%21TB=UDT?0)Y-wc?7_|@i-_5lp%FtA6)uuJ}W93+^_ zL|jZK0kvUmPcwshIF_1k!;`LJ%ZZ?1iSZ12Z)RT1!^^7q(sv|_jnl0u%>mP^MPT$~O1%;Q_Y%o$ zT68Hd?kiV1RA5mif(F!sYpQ9^Gv{POrb5_H8{#f%FbLQl$?PAHX76B;#1oyc#HJU4xB5!=f#?<6mfH2X&wY+jv05d^M^+r_3?zFM z%lYZ?@zGY}MNHUxOdj%4N2+QdT_T2=NgT1FfkC%6N5_T}U{<09!OopD#L$hH&6mQJ zP{ffd5aqP}8$8*8#Llcn*58>I+M}*80lTjH8wHRdyOz27y^ashp`@YTa`B!D{aYs% zy3Z8&PJix2h7;Vd8i2!T8I_=`mg_b{*_<(l{{D~c4fylrxvY6 zyHol@2Zp|cEHq6h!CDwKVGxBe4WvnT+vtSdLDj>D-8q^7YbsiQwk`r%9hN-RLy1@j zSvtbIe_iiy+{2m2-wH<+o3W26$0VhfJrT9H>Hqb09qH>x;8AKovnsn1a!JMB7B{$D zF%Q&xwG&u>KT9)DaO&{A`jl4T=EaT6yy83RHTu7WKLQ_(fY`!EDh&mV=dLQNm%t9zY=mUyZhHA|+ z>cE1+?)Tv4Kk98!5;I3qD+933OqtVMTHiUChroo1mG-I>*e-;zm8m6>!7r*7N+0i4 z7}vCqz5)-I?ntJ4g2cg6mc7OqUUn|$b&RRb&MD!~z~#WLGOK(X@w{KbPm`#;eGpNc zeG;$W5M-ia1VBcdx$?l38{o>!k|@Tluc*nzP1D<45|6~>l3=MfF%`?1MGi?Ls{63x ziD~tEI^!vYXwF)^ClO(mVJIDbYkJQJ?ak)#7OMDCXj>O~HIrg(7x&S3Zez%(My$zE zWUJ@}8{?uj4HyGSPoYG0qACOF{aZ6p zqf3uHCvV+Ket|wxAOWqtZ?i2-207H?7$^#9$q~mnzp|i zl>U!?REw5^%i{6z(bmJL`GS)g?rI>}7P$%Y)?07cid-tl_HP?@5`;Lnganq8=b{h( z{#CK`0)3;$Nxd(L;U)`CT`Qp|$%C>#5oO_^0N?f6i|wtU2_cqy-LadR26IEEHeNG1 zizv7eIVM^EyOEsQ#hD<~V23vB8O;t(qD~+)B3>hTX^m+&Q%AOQT>w$n3>eHW9Ihag zxD{g=PYMh$jH|1J0P2Kx!AUH|$k?NPAY10UZK7}Y{6aJ1Ju^kTd&NBT-X2U=a%`?H zaNs3g+cKaOc|!d3+(~3TaxekIW^wbSv`Cp4eT{&U$!G_$8kgoGqDMG9JUsLr$%M{) z;O?HN6nmnc@{bai4M}f2HP;3Zk{O=sM9N^%eM-0i)2l0UCrzj5 zzvp~JnUG4Ju8hrud`}Ehf5mN068D&BgD#^o@-VVE-+)J1F4w16;UnSVO;C;njgMH*fM=1 zYdEP+9RG6vV1kM6Fet6E5KDwk%ri9*Fd%9IQgFM17dI-Q4BGMiSRIb)ick&YVo%f) zD3sv2N%v_j3{05FM72VQ1*89JCt)qjdKus>PPEVWuFAz=sWAY2UUntJnY0!Cu@lbM zh*kN{sqM?xUto7LwB-p;b#E+v;8VYg5raX(nTV)E-<2%uLrsLfWnSWO*J0LGLUg4&c^Cx7H}Yl8Sf~`Xqqw3m zpr$djm^#Cy0~w(rH&GfA$7Hze==mbjV&}zJ7Q&e(%g5WFVO5a(IBRjaw{vUiq+T~~ zA?IWc<30^TIo(H>6ePP)IFm(0Zt9R@hx=OpMGzRc$}Q8 zFiW_qkj&oGRx?Dvgt?C!ib78QU?g*+xSHsi9JWoaT zsy>}z>jztwKE!YP{2SJ>{JxWuz++RYDt z&mjl3d|x?t(}1FjRQ?2K65L8A%B_AFqDh)`N!m4wnFUlkeoky-fGyHt^+;d%RpD_s zF;jcerbjVRZ`T*;&4Q=i_xm?mO_gdtN3rx9Kh}Et1%|cLS#D7}Z1KD5W{<9!R_jFX zWAgfD&8bQL#yo7^<69cxQoze0<1b<^YoCu+i#r zSsA3iUTGOG*ETSKJqNbuc_%A!LEXaSJJXQJZ?-dHwB(L7=xPV*AvL1)!>rtai3NE{ zc#QzMsvq*K^}Qrj(oVFKBd{OUb`Sj`^?rm=pHHl4Xkffbp9=)-;bNY9TOnXDl{lAo zI-!VbELb|*?oD;~wnFO7nh7nmCM5vCfSH<=+ZgroGT@qwxG~VtIs2m5l?K4`+N&(( zx}nGJVeV220k5B^Nsfj-HTSCmvNF7`jlj#-(;6ldp6`X&dt2A^RPWCH^7&#~*04^S zhDY^84S;Z>Y7|EONO!J20hftnxp7E*`ktu9rIhP-&U?3|RSRiEiC^g~B1(+}Z%K$@ ze`ZRj+4TD!5;N7>DuMdb53y|A4mg$(FY+*glKG5m*>}2T)GHEpvv7VVkhxTv=&Adfc4$>Rw?7dLgLw&Izu5T# z;gQ|MeV~3oyqbesx2g1Le zgFZi(Y~f-aC$nqrYGzDRH+6^_`&@j9Qo^=TT5hkf&p4q05#1Lx6UlHcOnfY$5{aeK zd?40zG7$Y6URE6K024+J+SMDn-C19)myqQd%AH{p3WGreeFWm!Vb9{j%Vp+*iRA>9 z18JKG1=7gcFpg{904G!i@k*b4r&(@^Q%tGmo~9emX?i`slhIIXqA|qj0mSbZz|PQ^ zxUFI>CPrNEjxkPBZoRIMaV^`WVhx`Y20-}!j)sP@53M`OyI~I)lD2Rt>V_U-+X+@?S7pnql9| z^?KJi&307Kg`b3S{%FE4z%iYwOkLG;y(^xttHq;ji7gEc*FfWk3B!j8BX7O+mNlu{ zo$_Kots00y6(&r0UXj*nXGS2|1SU-Gxj{vUF)o^>sxg<`eo8`oGw}lUv{2Q@ zZCvUo9%YLMX-+2Ddhs1fU8Uga^qUzl)i?g(9Y6i)PumMW z_G3RLolnrBf#9ZHU>?eabRUp*tV3VUU&tsmNnMf`x0LA~2~V_C{TPiIHNY$rWLz|u z7blW65C@YIYT67M^hHFu(Q{{V$*Bcv7pl(LUafc6tC7b9i;j?3@=huBM>vIjY+b_K zyH;EJ9x`?fW+haNDU-;e*J~T=Z)0*28(D@4#!Use5W-LPx!>!5&%2-F$(+ft$9&fK zBNqs$|g z^V_|nv57xyO%J%8~wVWm9S>L%BbnGBUv}zO8&zk@9^Yz}!ye{E7 zJ;UF=27ewa`bAULYrf+Ej6Wi4nQ??F4su5(E$SGtikgyn;dW;GuhmZ1*Wl>E(_vp+}Os{To`RRzmK%l(W5YScRhJ3>>#aF z)}CqO76IYl=uBy&F0>OGL8(x_y0He5l_m_5Ed*#@eC`3KN z!yyK{i3=tZip23Aj-Vj-zcqY;w!3G&cs9y8JZTe^4>EY(bh-DpYiYv!H1_F=_WL!h zxTfNls$sOFE$ut}o|ek4Or!-?s>|JkSuf=}AN$zHB6V-{iNP_z4y*+=#ivl3eeFym>S{NiCV-ZdhO*3AcSl6RU_+yk!Rd3cHif4) zX5!);>1tj8(X{spt6TaX=6d#J4A4YM)3|0Pbn)JL57&r&Bk&v7$`n^Zo=gUU@StUk zlw*~Pew-OYXBx$5>a~>sI`b%JD^z#9a}QQ_-$Q6?)if>NPbS`&Is5EouUK-yq_^%8 z!Pja67F1LV*h!VQ?Cmheri@{t)a;XqSoI@uXX?8+L-Ks0wuGQ*-qc_cM_V>xa}!20 zQ7`hqdNSGNa(*xjEakULO_;XGWob?kXR2sotNmGhem=~fD%B}E#^jzF6kBopO($!(Ep;1$Ng0RlW>uWnW z$Dz-*w$y!M@n|6Dd?8xG(C<4+`}cY;9j7BRB2MpL)!AWO;|;_JB%kZm-`8W@Z#0D{Q44mW}1m^wSj{ z;wGR{ax=tn*JdcU3s{*k7@0?+oI1-DTPTI5Lm3cS*l1q|_lZw@f?t3Ab(BeUeNudT zC$N}KO&I+~Y*_O^4kv038@8Kp*~0jnvGxM|Eqd--`f&_Pa*@%TX)dzU{KD&K%S*^cQF z(;_$^D^25A+bmH~bnU(?6c8%KxJ>){jLSapWn1M8ZPij2g8r%OXv$GE8fx`wId!7q zaBZb+Jc}L4`0?@4{to7W9m%qi6FWsNh%TnnZ*`*T_Xj@k0sBU%N4XX{VS8b6IFE>n zi2x8PVc~s(R04cWVyW|0)7Wo5;jt9Ph)ik~C5|{qZKRtSBI)Ry0KZH=r)}$%CSo?` zfbw7-_Mf!-9d$ZCf~0M;cP0vKzh4Z+&PNG2OYbXzgc%F----_$E#^hGO0+y7xV#2o-H9Qb3Qj=J=-@^0VTnT4C zl0Y%%ZAW%1jAI>Qlc6+W+McLjRoRCeZxpb?dTb@mg;9^}7ryWXj&n14f>G-r7=prQ z)5yhMz)#OK*OK_HPkM4uugi}f@%NbA_fX5i+Xk_iD6Z`bSA@#*afh!7EZg;3%3LAf zHBuHV0}yV%62)E?txhTpi-YU5AmTC&#pLFXOl{W5?JHqM`-Z%2IX&GYU^>Cg#y3ez zx+M6QX$+@2+x3)l^xk{Dt*dwLt*7bN-H69UABh`Nq{g6=De`2=T-9~&-kfplLeYf; z*Zv)iTp1HfFmU#ICpY=#Cedgze~m_!w)As5e!rNGHnf*C*DH>2$#Y?_D?853rp5zK zn<^uW8+jm;iKCU{cc?wSmlp;I&lh&Xa#wZ4y&6GLjgfOwo7O_9BQ$kQ@}-nU3EAfS zgdF5PuJw2EK^|CT(;aD?zL31vC$Yf`v0dFj*G-Z=q!#CK2kBqoc@r7x#7jJ5i(Tu& zGn(5rsRNj1=_icK=P=vSsl=XD_ox!?CT3l?i(EK9HQ-c32px0Pn@wbBXLr@twK zB_d5KGdFFj2)^ElOpT^-jl`d79Xw|g#@Tb3Gz6(lo~iJu`>;|lN&Qa0U(=esf_;XG z?1kr6ul-xT*Mwv9mr0~G>@7`UuaLdpqcm;ocgvkY6h^HJRT9)hi98VQUDZUg_1?XM zr7RCbnaII~xI0ty<-YkU96LRA*j4@>(KrUPyUJJljy7hppisBrypfvF3a^a?DQiJK zpv}{UIDN5E>lfN?8yWXV4@pU5i=$(Sc_6SvnUVPq8@Z|)1MLLJJ>jmNfq955L@5+E zz#LrT0Q2Y)O_nfp5s(yRL?_TS?42U>i}9LVafs=*Ol<{x;m4s)Bvoz>UAAlQ%`HGc zdpiX1h^;fLNCWZd>i9F=OX&=uM06b)>Y9Sz>#_xV*c5Xs{4JAfhKVt7ya1|>`h6~A zSJND0F`k~wlwb(hV<~^qV&gK#boLq#;L;b(Mi^J(EU5kQ@exU6MG*}zCI*5W5M?6B zJXUtZBv2PG*VW6XZDp z!N|DjKA3RM*^M%s-@rfYpTRu~kmp>Kq&odyZBTfCV?4G(m=^Um>jG1YSNN3haq8dt zdsgRZfi2H-(y2av_kCj19~Je^XZP1F#*9+eP|qHJI_Hg z@4ga0kq&~=8||BY<2szEeE5`XL!ow%oGinb20mdU&V2x^^qg8;>RKkDM%#IH9agvtFfVTRryIPNS8W(~%<%}Kq z4Q5qlO*y*|ZoRiRrTaQ|M30ebD-)giucyB>B_WNPjnK^z^0SAdRhkC%Nn=lb5!IaYDR>_@!#on)tObE5zD=7NFjdoYMSgauH#m`4gW=VB#ujEU^2q^YK% z^@Vb4K19<5O|$hQNF1h(mh3ncXyOg-$ev(n`@PJQfs+>02ZCd4k%@|&uvm>dvFB+& z5d1s}S|2nM6(`d{1HrKl`*JKE>X?z&9YH81K!7GWJVG&&(3E2e3Q`shqUFh&M(Eg> zO+3$jP@xov{$i}{rhkDu6TyelI({yG=Nd%`Hgm`)aGN#vLLs6x)3RqOy2RXK4D_TO ze{au_^__daSDSv4`b3vZqrbB~lsk>vdwo+Ny$`?0$%nwaZgk_nrTT+RR?G`#${;D8 zC0Z%xHSQhShpGMu^Qxw^rN(RrP{llvG>5kI#TR|v(O1NBoLF~h{TJ7C(t1&14y_}d zn{alber|XZz6{T5b)24dWV7}fXLc|IJiLzd*+jGl2f>+trJ1ySHEtx0n)09;i26f6 z_`wfi9=Q8HuQE}guJjqkZ|nVhxOU|kV4^Lj9|*x=LWIPuOsJABsgWQhl^2QMGeqNq z`=+9$M7}y!pgtX`AjO?SLpsF-rpDuHE)K))D{pyWAt@QHZ#^-I+Lr&Q4Q>9xiN<12Y9?V3SWEb7nX6rs zn68*nV_4CiP*>q8oohDOo(AnIL8^DF#3d>w;m@mVsk$?R0)L#CQ)41tCnotmv7hcs z%bcV@zMh+qHh5dky{h$#df)rzW0Bk!709`Mh>PKQMkP&-%dC$b=IO(Vxd4*)B&m(K z5seE2J)QyX?M{@?ER#s@B(o8%I0+MTTr)^}HIlNpOq5N>EB&*#-#2sSGYB;tpvEW; zKZe}g=?Ow^?w4+jmnY>R{HVQ^9gq7rgv-Z^vPm4b412cJo9ybWr1}mK# zbwg-C3PD{xS4F*hvl0a&bdi3B*I$y3M$qAz; zKVT~BHMJ8`nl8%GMW4K=r03nuwmnn#2c%*{^bHzJ5JWPK(fWI04pe@X@x&OTu4ML% zEaPae5dj$1i5Wq9#<$w@52k5gU6iE59P@;ARhBpx+CiF0Qxt`W$IMLX*)`BD9>$22 z0d5qGc~8RRbWp&Vd5iD*c#%E#i%G`8i$({=$W23KzWk&X#}`X01VU?7>OHh=%v#|C zG-$$0iz1c%%U}L-q#N48S&me8%|@4&($S-|4*Pu4oTvx)k%Qwv12IrGABcUc+T$nF z!G@D`YDI-b+~Hh8vL`}U*7${*Samj*7X$1%2zYKs-Akc`V_oy?qiMkPpMbqQ} z+43RHT=Im7cYFlBeE%&^l)0({No$p=&-GhCuwZU(>gj3C2&d~x+tpkcW1PlwWx`yQ zxgPnDiWQJk(QA-CH34`j3m}aUl*f#$>7!Jf3 z_q~=^fYBJBtKGw|X;XBBajmD=f$;Ey+TXewSHD*Va^*x-Z)=W4J+W`U{WhaQoE?EE zjJfzmbjAMJoe&?kd7`ceEM8*jlNyB3i|=hGC7JswTfNNzBuk`8O{ftEQ8>hcG3Z3Z z@@u4ZCmW_Pg}g&EkxR}TU0o2qGToqj{|XjQF(AGulQutd_#RSRXBlb#o-~^~e|Lnw zy4U}fHoUdID<>(K{93Pm@2C$*>emQn zlU4-XzpkYGQy+V0R2Uo%=&Q1`Q~4d#%d@(D@4Zr~m$BR_Z!m%O!?PAiJTul+W9s$T z3S9M*T&%?HeZ_C9Pv><&>UQEQW{fIU*x}>;x)tA>iGhT+WGo#o`ghY*0IvmpeJpcs z&FXuTY$r9B;Eh&qS+HF)rqZM|tPCP(8YYbW##SD2z5NLV?-SqCKxBf|y(^R^_xS|eOx=HiMctEXSHJtc zH4J=JUzQ1msV%JeE3Nr)#{Zw3pcUS!8`5r23l}EW{u`} zZ%Yoz368V2hWQK4P>^Qt(HNqdBRBW&Xtw&ipS!fo)0$l8edxNgw{j)eiuC;r^>u0@ zSuhZL4H^ix^5~alp>p%!uO^J9t6EROj0uqEj%2+;O=ahG;8)Th2gS4iqE^7}?E4uM z9|`p`Opd#VjEOw8S2yiWq`On9oJ6soT^8a_g2EHiS)0Dc2(QkrZ7-c*&>po;1MDcz zSw`>((v+#K7A*vtr7N}m^}pown=ho@)#YG6OaBriH1*k6zfzin%Di_uhmq|!m?F_M z@3rQoG>DTUzSY+yaN?3`6OHK!)|@a=odH9W=1?du^DskWg*k-xIuAm=3>IOc+=?@W z_h%D~8%$Tm6^Lu-ukq5$tQ(VDll~vMovT!MsslWaAH48*BnPdZ2V*w&IG(Z8|hGm zs$UL9jjiuTU-m5kd_ZGA?wMajF?^$pwP!sUU9L#MJgyj9s;X4U1M$wtuy%bWwKi2^ z3I?%H@Uw|uwq}G%U19O6dya~~+=N+SduhHbZA|S=e>)CXKFg4T3tYY1eR8%)xP1)Hy5>GpL&c4EJ0~}=L-*hup?D1cP$WvN8dVY-(;S+_GmC_ft?Qu{674xK zFWYu7+hjUFi+)Y;U+TEG?&kz|erL?&a{PCmUH*==e!!x`#PK|$A*uC%DDk_U<~&{Xzz9;RIy8`cA+Gyr%& zhre4bcJT(J!mCY*)V>Ncmdaxj>zIH{YhUa*``+OYm9T*$+{ExnkT1%Ljbf9y!zt7^ zegV)XHVQ;-zLGr(VWCx+uT3?jGqJR!Frs;as;$w~c$i?FU#}(^5Nc_Pijm+OrWpFE z^_Y536mS}$%1)bXOl_=8=Sa~= zX6erhc2UYRTRWa;D*o=;D2_$VK@ibZcsQU00Av(KFI|nR-|7R=M6&RKSc7W9eEj1d zm*aDW$MV~md42bfGMue_9{%5d_W$?U4j2b)*p0zBAbOHvpfQu+AwL>XQ+vO^yYtf7 zkR~}wx^r@nE-hDzI)b7`x{}h-ky&=!j7kQf+8zF935;?*7K9qcEp*0HFyfhWp0U{Y?jFLR32X^(`V4c< zV>%@IagQ$ay+8iH`R{-9U?4A!KXvJ_e(&)cONoW16zAzfch7}sBeGQXo{btuTUsKS zhgCxy1jct&d#VYz<0G>ijJ}f=x3Z^=b0jpIs6QnT6|!GRuM?5eEQzc;<2uGa*AWtz zt0tb>gl$`%eNHEBV84yOG0NPsuolucqXY4Dly$(+!c($d>x!wkK5)LeB}(& zzekJkAoI^`Qi?ep-WOz0Rth<{fy*?Wb!I7$#2k_+ig01{cXs;uryRoY6Nxjf{@Hv? zwlS0SvpYql)iatym6D0B@UL=b2c^MZi27#2rrru?@>h^S!eDDKfzKk-zuTIsElkNg zMq?p@+#h3_^YvcLTVrNK4X2}?&gcLi#|2-+2Hf`iB1+$&)g^&DRO|#q4^4t#auHy% zU(CmhyAv!HpP1I)c4bc=NMFwX_~@%~BNNq9*;ia#e_J2*g}?K6{?7K9&wK`bhGYAI znkn;d{Mmo!vz-I-GEt7xlHpB;lnO~%5`^-7>wV+E83M%Q1y@h0<($YQ{@$fUA6#(y z%q@t=d(8NRj1z*{eq?t6PnLKW|ISvC=Z^_AwhaWI|#vpT1svTHH9bZ zTpgZOt)#Y6(z(Xxs{i?&_3xelnEQ!Zn|t^^d<%ipYMTi(LA2~h7c-%)Baf-(e*95e1AaR*$JtC4( z2v-5zACRjV{WID+32d7;M$3duDa}p7&L3@iU47f70+@%xDe4B|T%iDSpN8y%DQ$z7 zkKY6G+R}CQ)t7!w&lE+D6|jD!2F?@F=CIt||KpT&&Nn3&zD;AdXqBWE)1P1AMJ1fY zSfDi!r{uNrwk4(&sQP$`AjEjNwJ~dtoKd6xx!{$r66fP&YL~h&hP%(jP<6 zP-J3cGZT`D!R4IC#zDGanMaHUO=rtAZ6sIJ@~qK8o5+3_RZX#4K{RGRQ>mi(`_dlHN@&KcQ~%F@m*#QJr^`mYKapTY zU_#ejfQC2Kyl6m99J`CXR?4qYGdcS#>|v@EORF@gt@E=Yyb`XZePkr81T(F`FAYfM zo7A)q>hHH=vNE#hjUyBEwy7o4BtqNTaRx4M&iKHd8jYJ55?V>XuEQ;sQe+_Exc1v^ zIdp7PBq@NgPjk}*5BiS5$pxGOxSV(8rTB#^bUFW*zx-vqn2YJ~{AYjmXU|hiPdicd zaBVvuSDmPDzx}pp6<_+&m+VE=K$MA0#DXN1#+myhtt$RZcqNH(dyhJp;G}YU9AP#{ zv(z#Oj9^B^426oZa~ha$Jnxg#do<&OOZYJ+b7dXVdR;M(l*mQN{pn>{qU-inCefc2 zQDXez^x_)WIL!g&7!mc#K%&rf#A-1SY&wF_x(VU!=17{ux9|jn$<+BaTPir_JF`8h z@ThCN36p5EtNtmhf-#g_+Djvh{YGzCk41n3&vnaab>Ve?U!QyAB(!Fx5>VOseWL!o z)x+c{Ex`#LLeYNgyoP%dE)VdRks3bd^b4h^DBR(D`y0n@gti~Z2S4~h3+49xQ1$Am z?A!>$TZ&4Qd9=$4X!40K=htg5hR`NiTrAx<4rob;9U;jNz%JwWJB2C9Y@H^CW?)7CZfA-JB!?}+nvqmyTG46&k zd*^x4cWk%km-yn?mEzm78lBI+ha z@f9npdxY#`_xr(Au-bob+fYC|=^C)Lu|GGC=LG3MwiHFzMRGqT=3e{-IPM=>dq zC}FykPpZKx;qTjp)*h{XHxkKMbG+7!Q{4}QmMQ9!(=`w?Vbsftj8yCeKs0NrdaQ${ zySfHaDmr`yS63l==ZZ3SD}Hcj6&-1SrVrr zlcsVWY?p>r*Igzv++oH|?Dko@(sru;8CkCSc(2{MM>!vzsVB4=-i}6uSa*RkIDzjh z2xjJd#eC1^$bA@hc;G$L1(=(bkNaE>TZa$ET6xHvoeP<-*FaJw_oYaDM;3O;Onh#Gc?gwhBW(`R-FCdAr!h$>Bz92Ko*D|Aq5G}1r|*SHZSV5gq_pAg zd*V)hOC^S3GSTl$1cSyr?%-yOC*i70XO{^ET_e#p_nUkFI5hD8#lP^oK6=!v5tkRg z`m4X%6Up!$&^Se5?0Z^`i`|C6UDOAnapHEgB{UE_8%9l-442(o!k!G{0wbsqL0rl> zhAdJSDqtY3Ny0HEW&~D=f90|-OJmcYWgnm4DP)+gSdb(n6EXL;+@{|NUi&G}nSh8T zt=1;^)TqqNhMQf#zPpU$D%6bcm8m>=jWTV@&gO|}Sg{L#k#r^_uIBU7rkAVwxgNx~ z6Xod868H=-1}e>?_Z>oAXwqP+eX%1H-~@$Pl-hzjkwO!TvD3UoK#f6c=RFC(h}G_s zS0^em*Q(?dJ#!&f^>M;sZUc@UXnv9eGu)FR(5EfT7bb+}BM-zX=_k|aJ>3uFl~-QT zeNiVF5&;*xak&--@Ou9Ixit`(sNe#;RMwEQKQ3S*xn=c7bi_?>b^0l0CR9j--#e`k zZ(f8T>XrC<+2y@)zieLf@Y?vsrE1>GoHZ{BGi^*re9{K^y1tZvh75FW*9*;ki2rgp zQi*)rhuG#w|E};`MR!VTWRf%o{D%ZXoR~+VV9i@+4r3w)&_*+(*onGc7@2WuaLi#z zd!H)7j>;dvq0*biyKQc+*g_MP(9S?$Vn91A%|V(L7?>zhn)4nRsv?!naN8%% z)?D{hJF){)`80+;Mnn=^2G$ss9z+?;t7{k-vmK>KJmoQDp2^XM?Y_<<%dOfQhvX;| z*84>-Zoa2(%!Tb>CpE8F)eU%8b}QFGPx>8E7IUy#E)vCQaJTSr6!XA}@L{{5RkDaI z^DyCiFcxJ}*v(9zKLD3E$7KhyC!t`KIm~@&0g9{n>=(?LOhC*1Ackuk7W5guoIsC@ zcs8g4AzlTJuhk2d2h!MeHEv|0CNr4?aX3e;ZOue|{q@)3^Wga24hAv~PK8X=hadl! z|HfxK1IcS#4-$^fS|;yUaFV=4ml{g;I+&FMu2cg|_`L{A-V20voOG>620!`E`s`{` ztg}5|hzzOsGSi~pC%TWI_ntlVKA87Cb0#}I_a@+Vp-T5G)v5n<=UN|tSuVsN5@v+z zn)|dx1i`O?M#7=#-6^J%QJ9#6WXiky48Tb2m`T+V@X3=7wQwKb+kvs@%ZzFRe z4xgNEmC2z+pu4X2d3}>pAKDc!?G*!C1vfkf<>I-`Hs|lYHR2VMT*u$9bxA-kfA85^Ze<4k z+Erg<{@q@k>scab?8LT4QSLEd*<0Fos}BrAu$E^JVvhE`2SxODKOLuNAG`Js)I3eK zY9=?YC3YnvBOTL14%6lK_6zqp<>_|%QQGoK_Ei?f98{hRh}IMKJj&{L4f zG`cBMgR^ctjJuJQizpa1ehR1dDqN;380+5F&*-HZh^DOTyRn?#o`%&iAw_5(6H;C7 z%1)&XPFG_dmPi(nn=?_;eW__-RrVC>9N5}&SFOWaJsJ?&CL>ve2&H4HGW)K8xeyf> zKa*TByAFK`Z?0WleLt<@LWnqak(W}@_h5t5{a&ux^0FdD*tJZ5?XN6#5nN0}Cv&#H z$4k?t$w-G!67ybKR^Gn$3Axj7*{8%b4fX?>cHdCj4rU^u0__r_h1M9%rTcqo%Yd3s z5cd}5ik)=-!rR&7)HsOySs~)wW2LRboM2Y4jW&U=&|c!FF-Xm)7uUM+CYU*VPS8~2 zAyL;XFb^b||6#{#F6uC}75^x_2Q`_RS6@umE^go1cvvSBK|S1iS+_KN^UXI|8~EDS zzQ%97@rLcnu3Mhzm8tA}W)@vatL@iS>Czb}Bo|E*sp{&sALVCa-P}CQ$;}I4NaUj4 zivcrdsGRRQQ{}FfurjGLf#Q9dh;q`Z{MXc{tMZy9i$&9&T_QfD(ttQj9 zF~>9CrDBp-OpZ<<;9wrP!4SB<1r053YMRH6V?5j*2tFWL=a9;gFgT4$kb)yOL9Oq; zaGwTY&CtQ9^u&9*`2k((^FZE*WVDQOXE|vwGtb^p8^|(FfWO#c&pe?R@ za|PbuY4Ifh_GM2Ls{^~2QDZmb6*V2xcI)-LXeWkPUlp_z7#<=8+nXNrKj?b|nXn?byalioY4s@Z9J1 z$|;vw)6hO{O}#u5eZ1d&60RVe%W^Ddzf%WICd3HUl&JVLH|^s-BRXp@(%!9HAk-DZ zp3IP0d96B;n1pR5y9VOYZY*Q*%CoxOZ)pN0b`;MoETxBN4REoCt&e3ig3VY7`fFux z;S`nhk5J%>EozItjE9z=6OoqeCsX1>cSc${nzfI;YkI>YI(`Td*KY3^Yt~DXK-BAo zd7hYbo1-kh$3oN5v~S6G@Y-evW)*Cp@eF8zcy<1sHWBNa39UYmNoU1|LVCq&Tr2qD z4}UltzzN=2!I(E}$;r@#ZyUD*mP4BubI1}%X|R-FBoratHuv3 zHv$m8gkRyH=7Z&2s4rp<6J|H!HUhu7iGdKi`7a_As-aG?-KQ4kJC!!NzleGeQNi|q z$G_Xd13i2Gj2@mp5I;NWwC`sJGkLHu?ReO7iv($PVjjyZgoaTt#gUxb1M7Ae$7h>1 zqT<}%ftD>Iw4d!L&H?SBw^^nPpesake})TQO_8uL@fHGDzaO?7BehfrT(O~$Ro0XS zoX`+Ww~o-AD2%SUi^HYt(seH%_`nBrQJt-U0bT+r^vZoN#*DOn6yaD9n&X{Ov<9S( zos^WzD`R*#2K(&U!6@E!d|rK^=g&7|d$+fDdiIsK>8oE+L>$?nn<8k$VR}a;CWH8# zKQa+qM@Z(UwDij{B`jOpxp|D-$?uRtma40y>(oDNC>?q+7(@0s>Z8$xikFer*4p<* z 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 Y1)_U6y=(kN8vp Date: Thu, 3 Dec 2020 09:57:15 -0500 Subject: [PATCH 028/144] Handle back button tap --- .../org/wordpress/android/ui/ActivityLauncher.java | 6 ++++++ .../ui/jetpack/backup/BackupDownloadActivity.kt | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index f0ea0803c37c..17af868645a8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -44,6 +44,7 @@ import org.wordpress.android.ui.history.HistoryDetailActivity; import org.wordpress.android.ui.history.HistoryDetailContainerFragment; import org.wordpress.android.ui.history.HistoryListItem.Revision; +import org.wordpress.android.ui.jetpack.backup.BackupDownloadActivity; import org.wordpress.android.ui.main.MeActivity; import org.wordpress.android.ui.main.SitePickerActivity; import org.wordpress.android.ui.main.SitePickerAdapter.SitePickerMode; @@ -1294,4 +1295,9 @@ public static void viewPagesInNewStack(Context context) { intent.putExtra(WPMainActivity.ARG_OPEN_PAGE, WPMainActivity.ARG_PAGES); context.startActivity(intent); } + + public static void showBackupDownload(Activity activity) { + Intent intent = new Intent(activity, BackupDownloadActivity.class); + activity.startActivity(intent); + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadActivity.kt index 2e59baddf45c..ffd4043d7c94 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadActivity.kt @@ -1,10 +1,11 @@ package org.wordpress.android.ui.jetpack.backup import android.os.Bundle +import android.view.MenuItem import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders -import kotlinx.android.synthetic.main.domain_suggestions_activity.* +import kotlinx.android.synthetic.main.backup_download_activity.* import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.ui.LocaleAwareActivity @@ -30,6 +31,14 @@ class BackupDownloadActivity : LocaleAwareActivity() { setupViewModel() } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + onBackPressed() + return true + } + return super.onOptionsItemSelected(item) + } + private fun setupViewModel() { viewModel = ViewModelProviders.of(this, viewModelFactory) .get(BackupDownloadViewModel::class.java) @@ -37,7 +46,7 @@ class BackupDownloadActivity : LocaleAwareActivity() { // todo: annmarie temporary start val fragment = BackupDownloadDetailsFragment.newInstance() - showFragment(fragment, BackupDownloadDetailsFragment.TAG) + showFragment(fragment, BackupDownloadDetailsFragment.TAG, slideIn = false, isRootFragment = true) } // todo: annmarie - decision pt: have activity/frag pairs or use the replace fragment approach From 5a0017bf11d2d61e4313abbca480199b09db6697 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 3 Dec 2020 09:58:56 -0500 Subject: [PATCH 029/144] Remove hardcoded icon in layout --- .../android/ui/activitylog/list/EventItemViewHolder.kt | 10 +++++----- .../main/res/layout/activity_log_list_event_item.xml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt index cac254251141..5fee37730d02 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt @@ -35,12 +35,12 @@ class EventItemViewHolder( summary.text = activity.title text.text = activity.description + ColorUtils.setImageResourceWithTint( + actionButton, + activity.buttonIcon.drawable, + actionButton.context.getColorResIdFromAttribute(R.attr.colorPrimary) + ) if (activity.isButtonVisible) { - ColorUtils.setImageResourceWithTint( - actionButton, - activity.buttonIcon.drawable, - actionButton.context.getColorResIdFromAttribute(R.attr.colorPrimary) - ) actionButton.visibility = View.VISIBLE } else { actionButton.visibility = View.GONE diff --git a/WordPress/src/main/res/layout/activity_log_list_event_item.xml b/WordPress/src/main/res/layout/activity_log_list_event_item.xml index b602d73f59d4..d96ef71e7bef 100644 --- a/WordPress/src/main/res/layout/activity_log_list_event_item.xml +++ b/WordPress/src/main/res/layout/activity_log_list_event_item.xml @@ -31,7 +31,7 @@ android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="@string/activity_log_button" android:padding="@dimen/activity_log_icon_margin" - android:src="@drawable/ic_history_white_24dp" + tools:src="@drawable/ic_ellipsis_vertical_white_24dp" app:tint="?attr/colorPrimary" /> Date: Thu, 3 Dec 2020 10:01:44 -0500 Subject: [PATCH 030/144] Expose backup feature --- .../list/ActivityLogListActivity.kt | 9 +++++++- .../list/ActivityLogListFragment.kt | 18 +++++++++++++++ .../activitylog/list/ActivityLogListItem.kt | 12 ++++++---- .../activitylog/ActivityLogViewModel.kt | 22 ++++++++++++++----- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt index 3e8776686e5b..23f386174df0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt @@ -5,13 +5,18 @@ import android.os.Bundle import android.view.MenuItem import kotlinx.android.synthetic.main.toolbar_main.* import org.wordpress.android.R +import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.LocaleAwareActivity import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.posts.BasicFragmentDialog +import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.viewmodel.activitylog.ACTIVITY_LOG_REWIND_ID_KEY +import javax.inject.Inject -class ActivityLogListActivity : LocaleAwareActivity(), BasicFragmentDialog.BasicDialogPositiveClickInterface, +class ActivityLogListActivity : LocaleAwareActivity(), + BasicFragmentDialog.BasicDialogPositiveClickInterface, BasicFragmentDialog.BasicDialogNegativeClickInterface { + @Inject lateinit var backupFeatureConfig: BackupFeatureConfig override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -46,6 +51,8 @@ class ActivityLogListActivity : LocaleAwareActivity(), BasicFragmentDialog.Basic } override fun onNegativeClicked(instanceTag: String) { + // todo: annmarie - this is temporary to expose backup feature + ActivityLauncher.showBackupDownload(this) } private fun passRewindConfirmation(rewindId: String) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt index e0d2890a9a6d..a6417f187f37 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt @@ -158,8 +158,26 @@ class ActivityLogListFragment : Fragment() { viewModel.moveToTop.observe(this, Observer { log_list_view.scrollToPosition(0) }) + + viewModel.showMoreMenu.observe(viewLifecycleOwner, Observer { + if (it is ActivityLogListItem.Event) { + displayMoreMenuDialog(it) + } + }) } + private fun displayMoreMenuDialog(item: ActivityLogListItem.Event) { + val dialog = BasicFragmentDialog() + item.rewindId?.let { + dialog.initialize(it, + getString(R.string.activity_log_rewind_site), + getString(R.string.activity_log_rewind_dialog_message, item.formattedDate, item.formattedTime), + getString(R.string.activity_log_rewind_site), + getString(R.string.backup_download_details_header), + getString(R.string.cancel)) + dialog.show(requireFragmentManager(), it) + } + } private fun displayRewindDialog(item: ActivityLogListItem.Event) { val dialog = BasicFragmentDialog() item.rewindId?.let { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt index 1f4761acbf6b..e1be37eff895 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt @@ -4,6 +4,7 @@ import androidx.annotation.DrawableRes import org.wordpress.android.R import org.wordpress.android.fluxc.model.activity.ActivityLogModel import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Icon.HISTORY +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Icon.MORE import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.ViewType.EVENT import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.ViewType.FOOTER import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.ViewType.HEADER @@ -13,7 +14,7 @@ import org.wordpress.android.util.toFormattedDateString import org.wordpress.android.util.toFormattedTimeString import java.util.Date -sealed class ActivityLogListItem(val type: ViewType) { +sealed class ActivityLogListItem(val type: ViewType) { interface IActionableItem { val isButtonVisible: Boolean } @@ -30,7 +31,7 @@ sealed class ActivityLogListItem(val type: ViewType) { val rewindId: String?, val date: Date, override val isButtonVisible: Boolean, - val buttonIcon: Icon = HISTORY, + val buttonIcon: Icon, val isProgressBarVisible: Boolean = false ) : ActivityLogListItem(EVENT), IActionableItem { val formattedDate: String = date.toFormattedDateString() @@ -38,7 +39,7 @@ sealed class ActivityLogListItem(val type: ViewType) { val icon = Icon.fromValue(gridIcon) val status = Status.fromValue(eventStatus) - constructor(model: ActivityLogModel, rewindDisabled: Boolean = false) : this( + constructor(model: ActivityLogModel, rewindDisabled: Boolean = false, backupFeatureEnabled: Boolean) : this( model.activityID, model.summary, model.content?.text ?: "", @@ -47,7 +48,9 @@ sealed class ActivityLogListItem(val type: ViewType) { model.rewindable ?: false, model.rewindID, model.published, - isButtonVisible = !rewindDisabled && model.rewindable ?: false) + isButtonVisible = !rewindDisabled && model.rewindable ?: false, + buttonIcon = if (backupFeatureEnabled) MORE else HISTORY + ) override fun longId(): Long = activityId.hashCode().toLong() } @@ -110,6 +113,7 @@ sealed class ActivityLogListItem(val type: ViewType) { THEMES("themes", R.drawable.ic_themes_white_24dp), TRASH("trash", R.drawable.ic_trash_white_24dp), USER("user", R.drawable.ic_user_white_24dp), + MORE("more", R.drawable.ic_ellipsis_vertical_white_24dp), DEFAULT("", R.drawable.ic_notice_white_24dp); companion object { diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt index 7b963fe44dee..338de40972a7 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt @@ -25,6 +25,7 @@ import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Loading import org.wordpress.android.ui.utils.UiString import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.util.AppLog +import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.util.config.ActivityLogFiltersFeatureConfig import org.wordpress.android.viewmodel.ResourceProvider import org.wordpress.android.viewmodel.ScopedViewModel @@ -43,6 +44,7 @@ class ActivityLogViewModel @Inject constructor( private val rewindStatusService: RewindStatusService, private val resourceProvider: ResourceProvider, private val activityLogFiltersFeatureConfig: ActivityLogFiltersFeatureConfig, + private val backupFeatureConfig: BackupFeatureConfig, @param:Named(UI_THREAD) private val uiDispatcher: CoroutineDispatcher ) : ScopedViewModel(uiDispatcher) { enum class ActivityLogListStatus { @@ -124,6 +126,10 @@ class ActivityLogViewModel @Inject constructor( } } + private val _showMoreMenu = SingleLiveEvent() + val showMoreMenu: LiveData + get() = _showMoreMenu + lateinit var site: SiteModel fun start(site: SiteModel) { @@ -178,7 +184,13 @@ class ActivityLogViewModel @Inject constructor( fun onActionButtonClicked(item: ActivityLogListItem) { if (item is Event) { - _showRewindDialog.value = item + if (backupFeatureConfig.isEnabled()) { + // todo: annmarie implement expand/dismiss the more menu + _showMoreMenu.value = item + } + else { + _showRewindDialog.value = item + } } } @@ -235,7 +247,7 @@ class ActivityLogViewModel @Inject constructor( moveToTop = eventListStatus.value != LOADING_MORE } eventList.forEach { model -> - val currentItem = Event(model, disableActions) + val currentItem = Event(model, disableActions, backupFeatureConfig.isEnabled()) val lastItem = items.lastOrNull() as? Event if (lastItem == null || lastItem.formattedDate != currentItem.formattedDate) { items.add(Header(currentItem.formattedDate)) @@ -265,7 +277,7 @@ class ActivityLogViewModel @Inject constructor( private fun getRewindProgressItem(activityLogModel: ActivityLogModel?): ActivityLogListItem.Progress { return activityLogModel?.let { - val rewoundEvent = ActivityLogListItem.Event(it) + val rewoundEvent = ActivityLogListItem.Event(model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) ActivityLogListItem.Progress(resourceProvider.getString(R.string.activity_log_currently_restoring_title), resourceProvider.getString(R.string.activity_log_currently_restoring_message, rewoundEvent.formattedDate, rewoundEvent.formattedTime)) @@ -295,7 +307,7 @@ class ActivityLogViewModel @Inject constructor( private fun showRewindStartedMessage() { rewindStatusService.rewindingActivity?.let { - val event = Event(it) + val event = Event(model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) _showSnackbarMessage.value = resourceProvider.getString( R.string.activity_log_rewind_started_snackbar_message, event.formattedDate, @@ -307,7 +319,7 @@ class ActivityLogViewModel @Inject constructor( private fun showRewindFinishedMessage() { val item = rewindStatusService.rewindingActivity if (item != null) { - val event = Event(item) + val event = Event(model = item, backupFeatureEnabled = backupFeatureConfig.isEnabled()) _showSnackbarMessage.value = resourceProvider.getString(R.string.activity_log_rewind_finished_snackbar_message, event.formattedDate, From f03518711ecc73877d6e545bc2955b156f0ca669 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 3 Dec 2020 10:02:06 -0500 Subject: [PATCH 031/144] Update test --- .../activitylog/ActivityLogViewModelTest.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt index fe173cad7043..6338d3d970dd 100644 --- a/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt @@ -38,7 +38,9 @@ import org.wordpress.android.ui.activitylog.list.ActivityLogListItem import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Event import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Footer import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Header +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Icon.DEFAULT import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Loading +import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.util.config.ActivityLogFiltersFeatureConfig import org.wordpress.android.viewmodel.ResourceProvider import org.wordpress.android.viewmodel.activitylog.ActivityLogViewModel.ActivityLogListStatus @@ -53,6 +55,7 @@ class ActivityLogViewModelTest { @Mock private lateinit var rewindStatusService: RewindStatusService @Mock private lateinit var resourceProvider: ResourceProvider @Mock private lateinit var activityLogFiltersFeatureConfig: ActivityLogFiltersFeatureConfig + @Mock private lateinit var backupFeatureConfig: BackupFeatureConfig private lateinit var fetchActivityLogCaptor: KArgumentCaptor private var events: MutableList?> = mutableListOf() @@ -84,7 +87,9 @@ class ActivityLogViewModelTest { true, null, Date(), - true + true, + DEFAULT, + false ) val activity = ActivityLogModel( "activityId", @@ -107,6 +112,7 @@ class ActivityLogViewModelTest { rewindStatusService, resourceProvider, activityLogFiltersFeatureConfig, + backupFeatureConfig, Dispatchers.Unconfined ) viewModel.site = site @@ -215,9 +221,9 @@ class ActivityLogViewModelTest { private fun expectedActivityList(isLastPageAndFreeSite: Boolean = false, canLoadMore: Boolean = false): List { val activityLogListItems = mutableListOf() - val first = Event(activityLogList[0], true) - val second = Event(activityLogList[1], true) - val third = Event(activityLogList[2], true) + val first = Event(activityLogList[0], true, false) + val second = Event(activityLogList[1], true, false) + val third = Event(activityLogList[2], true, false) activityLogListItems.add(Header(first.formattedDate)) activityLogListItems.add(first) activityLogListItems.add(second) From 02ddf99e9b0d6746f36593ffd9fd79360fbc37ed Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 3 Dec 2020 10:08:21 -0500 Subject: [PATCH 032/144] Fix lint --- .../android/ui/activitylog/list/ActivityLogListItem.kt | 2 +- .../android/viewmodel/activitylog/ActivityLogViewModel.kt | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt index e1be37eff895..73c0e72fae10 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt @@ -14,7 +14,7 @@ import org.wordpress.android.util.toFormattedDateString import org.wordpress.android.util.toFormattedTimeString import java.util.Date -sealed class ActivityLogListItem(val type: ViewType) { +sealed class ActivityLogListItem(val type: ViewType) { interface IActionableItem { val isButtonVisible: Boolean } diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt index 338de40972a7..7ca5a107290b 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt @@ -187,8 +187,7 @@ class ActivityLogViewModel @Inject constructor( if (backupFeatureConfig.isEnabled()) { // todo: annmarie implement expand/dismiss the more menu _showMoreMenu.value = item - } - else { + } else { _showRewindDialog.value = item } } @@ -277,7 +276,9 @@ class ActivityLogViewModel @Inject constructor( private fun getRewindProgressItem(activityLogModel: ActivityLogModel?): ActivityLogListItem.Progress { return activityLogModel?.let { - val rewoundEvent = ActivityLogListItem.Event(model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) + val rewoundEvent = ActivityLogListItem.Event( + model = it, + backupFeatureEnabled = backupFeatureConfig.isEnabled()) ActivityLogListItem.Progress(resourceProvider.getString(R.string.activity_log_currently_restoring_title), resourceProvider.getString(R.string.activity_log_currently_restoring_message, rewoundEvent.formattedDate, rewoundEvent.formattedTime)) From d7cde1af0d8a6bda56369432f0273582e0208c61 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Thu, 3 Dec 2020 16:31:46 +0100 Subject: [PATCH 033/144] Implement stories handling in the ImprovedMySiteFragment.kt --- .../android/ui/ActivityLauncher.java | 20 ++++ .../android/ui/main/MySiteFragment.kt | 20 +--- .../ui/mysite/ImprovedMySiteFragment.kt | 75 +++++++++---- .../android/ui/mysite/MySiteViewModel.kt | 87 ++++++--------- .../android/ui/mysite/SiteNavigationAction.kt | 48 ++++++++ .../android/ui/mysite/SiteStoriesHandler.kt | 105 ++++++++++++++++++ .../StoriesMediaPickerResultHandler.kt | 91 +++++++++++---- .../android/ui/mysite/MySiteViewModelTest.kt | 39 ++++--- 8 files changed, 350 insertions(+), 135 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index cd04f2bd9407..38b80c97cc3a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -13,6 +13,9 @@ import androidx.core.app.TaskStackBuilder; import androidx.fragment.app.Fragment; +import com.wordpress.stories.compose.frame.FrameSaveNotifier; +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult; + import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.analytics.AnalyticsTracker; @@ -97,6 +100,7 @@ import java.util.Map; import static com.wordpress.stories.util.BundleUtilsKt.KEY_STORY_INDEX; +import static com.wordpress.stories.util.BundleUtilsKt.KEY_STORY_SAVE_RESULT; import static org.wordpress.android.analytics.AnalyticsTracker.ACTIVITY_LOG_ACTIVITY_ID_KEY; import static org.wordpress.android.analytics.AnalyticsTracker.Stat.POST_LIST_ACCESS_ERROR; import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_DETAIL_REBLOGGED; @@ -1037,6 +1041,22 @@ public static void viewJetpackSecuritySettings(Activity activity, SiteModel site activity.startActivity(intent); } + public static void viewStories(Activity activity, SiteModel site, StorySaveResult event) { + Intent intent = new Intent(activity, StoryComposerActivity.class); + intent.putExtra(KEY_STORY_SAVE_RESULT, event); + intent.putExtra(WordPress.SITE, site); + + // we need to have a way to cancel the related error notification when the user comes + // from tapping on MANAGE on the snackbar (otherwise they'll be able to discard the + // errored story but the error notification will remain existing in the system dashboard) + intent.setAction(String.valueOf(FrameSaveNotifier.getNotificationIdForError( + StoryComposerActivity.BASE_FRAME_MEDIA_ERROR_NOTIFICATION_ID, + event.getStoryIndex() + ))); + + activity.startActivity(intent); + } + public static void viewJetpackSecuritySettingsForResult(Activity activity, SiteModel site) { AnalyticsTracker.track(Stat.SITE_SETTINGS_JETPACK_SECURITY_SETTINGS_VIEWED); Intent intent = new Intent(activity, JetpackSecuritySettingsActivity.class); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt index d26d690f56ab..9fddef16110b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt @@ -22,12 +22,10 @@ import androidx.fragment.app.Fragment import com.google.android.material.appbar.AppBarLayout import com.google.android.material.snackbar.Snackbar import com.wordpress.stories.compose.frame.FrameSaveNotifier.Companion.buildSnackbarErrorMessage -import com.wordpress.stories.compose.frame.FrameSaveNotifier.Companion.getNotificationIdForError import com.wordpress.stories.compose.frame.StorySaveEvents.Companion.allErrorsInResult import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveProcessStart import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult import com.wordpress.stories.compose.story.StoryRepository.getStoryAtIndex -import com.wordpress.stories.util.KEY_STORY_SAVE_RESULT import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop.Options import com.yalantis.ucrop.UCropActivity @@ -126,7 +124,6 @@ import org.wordpress.android.ui.quickstart.QuickStartMySitePrompts.Companion.isT import org.wordpress.android.ui.quickstart.QuickStartNoticeDetails import org.wordpress.android.ui.stories.StoriesMediaPickerResultHandler import org.wordpress.android.ui.stories.StoriesTrackerHelper -import org.wordpress.android.ui.stories.StoryComposerActivity import org.wordpress.android.ui.themes.ThemeBrowserUtils import org.wordpress.android.ui.uploads.UploadService import org.wordpress.android.ui.uploads.UploadService.UploadErrorEvent @@ -1194,21 +1191,6 @@ class MySiteFragment : Fragment(), snackbarMessage, string.story_saving_failed_quick_action_manage, View.OnClickListener { view: View? -> - val intent = Intent( - requireActivity(), - StoryComposerActivity::class.java - ) - intent.putExtra(KEY_STORY_SAVE_RESULT, event) - intent.putExtra(WordPress.SITE, selectedSite) - - // we need to have a way to cancel the related error notification when the user comes - // from tapping on MANAGE on the snackbar (otherwise they'll be able to discard the - // errored story but the error notification will remain existing in the system dashboard) - intent.action = getNotificationIdForError( - StoryComposerActivity.BASE_FRAME_MEDIA_ERROR_NOTIFICATION_ID, - event.storyIndex - ).toString() + "" - // TODO WPSTORIES add TRACKS: the putExtra described here below for NOTIFICATION_TYPE // is meant to be used for tracking purposes. Use it! // TODO add NotificationType.MEDIA_SAVE_ERROR param later when integrating with WPAndroid @@ -1220,7 +1202,7 @@ class MySiteFragment : Fragment(), STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED ) - startActivity(intent) + ActivityLauncher.viewStories(requireActivity(), selectedSite, event) } ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt index 506cc68ff9cd..961e448419bd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt @@ -27,35 +27,40 @@ import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.TextInputDialogFragment import org.wordpress.android.ui.main.utils.MeGravatarLoader -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.ConnectJetpackForStats -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenActivityLog -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenAdmin -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenComments -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenCropActivity -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenJetpackSettings -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMeScreen -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMedia -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMediaPicker -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPages -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPeople -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPlan -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPlugins -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPosts -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenScan -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSharing -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSite -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSitePicker -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSiteSettings -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenStats -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenThemes -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.StartWPComLoginForJetpackStats import org.wordpress.android.ui.mysite.SiteIconUploadHandler.ItemUploadedModel +import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStory +import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStoryWithMediaIds +import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStoryWithMediaUris +import org.wordpress.android.ui.mysite.SiteNavigationAction.ConnectJetpackForStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenComments +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenCropActivity +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenJetpackSettings +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMeScreen +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMedia +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMediaPicker +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPages +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPeople +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPlan +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPlugins +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPosts +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenScan +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSharing +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSite +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSitePicker +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSiteSettings +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStories +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenThemes +import org.wordpress.android.ui.mysite.SiteNavigationAction.StartWPComLoginForJetpackStats import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.photopicker.MediaPickerConstants import org.wordpress.android.ui.photopicker.MediaPickerLauncher import org.wordpress.android.ui.photopicker.PhotoPickerActivity.PhotoPickerMediaSource import org.wordpress.android.ui.posts.BasicDialogViewModel import org.wordpress.android.ui.posts.BasicDialogViewModel.BasicDialogModel +import org.wordpress.android.ui.stories.StoriesMediaPickerResultHandler import org.wordpress.android.ui.uploads.UploadService import org.wordpress.android.ui.uploads.UploadUtilsWrapper import org.wordpress.android.ui.utils.UiHelpers @@ -82,6 +87,7 @@ class ImprovedMySiteFragment : Fragment(), @Inject lateinit var meGravatarLoader: MeGravatarLoader @Inject lateinit var mediaPickerLauncher: MediaPickerLauncher @Inject lateinit var uploadUtilsWrapper: UploadUtilsWrapper + @Inject lateinit var storiesMediaPickerResultHandler: StoriesMediaPickerResultHandler private lateinit var viewModel: MySiteViewModel private lateinit var dialogViewModel: BasicDialogViewModel @@ -201,6 +207,27 @@ class ImprovedMySiteFragment : Fragment(), is ConnectJetpackForStats -> ActivityLauncher.viewConnectJetpackForStats(activity, action.site) is StartWPComLoginForJetpackStats -> ActivityLauncher.loginForJetpackStats(this) is OpenJetpackSettings -> ActivityLauncher.viewJetpackSecuritySettings(activity, action.site) + is OpenStories -> ActivityLauncher.viewStories(activity, action.site, action.event) + is AddNewStory -> + ActivityLauncher.addNewStoryForResult( + activity, + action.site, + action.source + ) + is AddNewStoryWithMediaIds -> + ActivityLauncher.addNewStoryWithMediaIdsForResult( + activity, + action.site, + action.source, + action.mediaIds.toLongArray() + ) + is AddNewStoryWithMediaUris -> + ActivityLauncher.addNewStoryWithMediaUrisForResult( + activity, + action.site, + action.source, + action.mediaUris.toTypedArray() + ) } } }) @@ -314,6 +341,10 @@ class ImprovedMySiteFragment : Fragment(), } } } + RequestCodes.STORIES_PHOTO_PICKER, + RequestCodes.PHOTO_PICKER -> if (resultCode == Activity.RESULT_OK) { + viewModel.onStoriesPhotoPicker(data) + } UCrop.REQUEST_CROP -> { if (resultCode == UCrop.RESULT_ERROR) { AppLog.e( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index 05fb33e55013..cbd807a8e35a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -1,5 +1,6 @@ package org.wordpress.android.ui.mysite +import android.content.Intent import android.net.Uri import android.text.TextUtils import androidx.annotation.StringRes @@ -22,6 +23,7 @@ import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.AccountStore import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.modules.UI_THREAD +import org.wordpress.android.ui.PagePostCreationSourcesDetail.STORY_FROM_MY_SITE import org.wordpress.android.ui.mysite.ListItemAction.ACTIVITY_LOG import org.wordpress.android.ui.mysite.ListItemAction.ADMIN import org.wordpress.android.ui.mysite.ListItemAction.COMMENTS @@ -39,30 +41,30 @@ import org.wordpress.android.ui.mysite.ListItemAction.STATS import org.wordpress.android.ui.mysite.ListItemAction.THEMES import org.wordpress.android.ui.mysite.ListItemAction.VIEW_SITE import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.ConnectJetpackForStats -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenActivityLog -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenAdmin -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenComments -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenCropActivity -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenJetpackSettings -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMeScreen -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMedia -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMediaPicker -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPages -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPeople -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPlan -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPlugins -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPosts -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenScan -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSharing -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSite -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSitePicker -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSiteSettings -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenStats -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenThemes -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.StartWPComLoginForJetpackStats import org.wordpress.android.ui.mysite.SiteDialogModel.AddSiteIconDialogModel import org.wordpress.android.ui.mysite.SiteDialogModel.ChangeSiteIconDialogModel +import org.wordpress.android.ui.mysite.SiteNavigationAction.ConnectJetpackForStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenComments +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenCropActivity +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenJetpackSettings +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMeScreen +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMedia +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMediaPicker +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPages +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPeople +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPlan +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPlugins +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPosts +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenScan +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSharing +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSite +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSitePicker +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSiteSettings +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenThemes +import org.wordpress.android.ui.mysite.SiteNavigationAction.StartWPComLoginForJetpackStats import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.photopicker.PhotoPickerActivity.PhotoPickerMediaSource import org.wordpress.android.ui.photopicker.PhotoPickerActivity.PhotoPickerMediaSource.ANDROID_CAMERA @@ -102,19 +104,20 @@ class MySiteViewModel private val mediaUtilsWrapper: MediaUtilsWrapper, private val fluxCUtilsWrapper: FluxCUtilsWrapper, private val contextProvider: ContextProvider, - private val siteIconUploadHandler: SiteIconUploadHandler + private val siteIconUploadHandler: SiteIconUploadHandler, + private val siteStoriesHandler: SiteStoriesHandler ) : ScopedViewModel(mainDispatcher) { private val _currentAccountAvatarUrl = MutableLiveData() private val _onSnackbarMessage = MutableLiveData>() private val _onTechInputDialogShown = MutableLiveData>() private val _onBasicDialogShown = MutableLiveData>() - private val _onNavigation = MutableLiveData>() + private val _onNavigation = MutableLiveData>() private val _onMediaUpload = MutableLiveData>() - val onSnackbarMessage = _onSnackbarMessage as LiveData> + val onSnackbarMessage = merge(_onSnackbarMessage, siteStoriesHandler.onSnackbar) val onTextInputDialogShown = _onTechInputDialogShown as LiveData> val onBasicDialogShown = _onBasicDialogShown as LiveData> - val onNavigation = _onNavigation as LiveData> + val onNavigation = merge(_onNavigation, siteStoriesHandler.onNavigation) val onMediaUpload = _onMediaUpload as LiveData> val onUploadedItem = siteIconUploadHandler.onUploadedItem val uiModel: LiveData = merge( @@ -376,9 +379,16 @@ class MySiteViewModel override fun onCleared() { siteIconUploadHandler.clear() + siteStoriesHandler.clear() super.onCleared() } + fun onStoriesPhotoPicker(data: Intent) { + selectedSiteRepository.getSelectedSite()?.let { + siteStoriesHandler.handleStoriesResult(it, data, STORY_FROM_MY_SITE) + } + } + data class UiModel( val accountAvatarUrl: String, val items: List @@ -393,31 +403,6 @@ class MySiteViewModel val isInputEnabled: Boolean ) - sealed class NavigationAction { - object OpenMeScreen : NavigationAction() - data class OpenSite(val site: SiteModel) : NavigationAction() - data class OpenSitePicker(val site: SiteModel) : NavigationAction() - data class OpenMediaPicker(val site: SiteModel) : NavigationAction() - data class OpenCropActivity(val imageUri: UriWrapper) : NavigationAction() - data class OpenActivityLog(val site: SiteModel) : NavigationAction() - data class OpenScan(val site: SiteModel) : NavigationAction() - data class OpenPlan(val site: SiteModel) : NavigationAction() - data class OpenPosts(val site: SiteModel) : NavigationAction() - data class OpenPages(val site: SiteModel) : NavigationAction() - data class OpenAdmin(val site: SiteModel) : NavigationAction() - data class OpenPeople(val site: SiteModel) : NavigationAction() - data class OpenSharing(val site: SiteModel) : NavigationAction() - data class OpenSiteSettings(val site: SiteModel) : NavigationAction() - data class OpenThemes(val site: SiteModel) : NavigationAction() - data class OpenPlugins(val site: SiteModel) : NavigationAction() - data class OpenMedia(val site: SiteModel) : NavigationAction() - data class OpenComments(val site: SiteModel) : NavigationAction() - object StartWPComLoginForJetpackStats : NavigationAction() - data class OpenStats(val site: SiteModel) : NavigationAction() - data class ConnectJetpackForStats(val site: SiteModel) : NavigationAction() - data class OpenJetpackSettings(val site: SiteModel) : NavigationAction() - } - companion object { const val TAG_ADD_SITE_ICON_DIALOG = "TAG_ADD_SITE_ICON_DIALOG" const val TAG_CHANGE_SITE_ICON_DIALOG = "TAG_CHANGE_SITE_ICON_DIALOG" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt new file mode 100644 index 000000000000..0fe49680291d --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt @@ -0,0 +1,48 @@ +package org.wordpress.android.ui.mysite + +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.ui.PagePostCreationSourcesDetail +import org.wordpress.android.util.UriWrapper + +sealed class SiteNavigationAction { + object OpenMeScreen : SiteNavigationAction() + data class OpenSite(val site: SiteModel) : SiteNavigationAction() + data class OpenSitePicker(val site: SiteModel) : SiteNavigationAction() + data class OpenMediaPicker(val site: SiteModel) : SiteNavigationAction() + data class OpenCropActivity(val imageUri: UriWrapper) : SiteNavigationAction() + data class OpenActivityLog(val site: SiteModel) : SiteNavigationAction() + data class OpenScan(val site: SiteModel) : SiteNavigationAction() + data class OpenPlan(val site: SiteModel) : SiteNavigationAction() + data class OpenPosts(val site: SiteModel) : SiteNavigationAction() + data class OpenPages(val site: SiteModel) : SiteNavigationAction() + data class OpenAdmin(val site: SiteModel) : SiteNavigationAction() + data class OpenPeople(val site: SiteModel) : SiteNavigationAction() + data class OpenSharing(val site: SiteModel) : SiteNavigationAction() + data class OpenSiteSettings(val site: SiteModel) : SiteNavigationAction() + data class OpenThemes(val site: SiteModel) : SiteNavigationAction() + data class OpenPlugins(val site: SiteModel) : SiteNavigationAction() + data class OpenMedia(val site: SiteModel) : SiteNavigationAction() + data class OpenComments(val site: SiteModel) : SiteNavigationAction() + object StartWPComLoginForJetpackStats : SiteNavigationAction() + data class OpenStats(val site: SiteModel) : SiteNavigationAction() + data class ConnectJetpackForStats(val site: SiteModel) : SiteNavigationAction() + data class OpenJetpackSettings(val site: SiteModel) : SiteNavigationAction() + data class OpenStories(val site: SiteModel, val event: StorySaveResult) : SiteNavigationAction() + data class AddNewStory( + val site: SiteModel, + val source: PagePostCreationSourcesDetail + ) : SiteNavigationAction() + + data class AddNewStoryWithMediaIds( + val site: SiteModel, + val source: PagePostCreationSourcesDetail, + val mediaIds: List + ) : SiteNavigationAction() + + data class AddNewStoryWithMediaUris( + val site: SiteModel, + val source: PagePostCreationSourcesDetail, + val mediaUris: List + ) : SiteNavigationAction() +} \ No newline at end of file diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt new file mode 100644 index 000000000000..8b6eb5de2aff --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt @@ -0,0 +1,105 @@ +package org.wordpress.android.ui.mysite + +import android.content.Intent +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.wordpress.stories.compose.frame.FrameSaveNotifier +import com.wordpress.stories.compose.frame.StorySaveEvents +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveProcessStart +import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult +import com.wordpress.stories.compose.story.StoryRepository +import org.greenrobot.eventbus.EventBus +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import org.wordpress.android.R +import org.wordpress.android.analytics.AnalyticsTracker.Stat.STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.ui.PagePostCreationSourcesDetail +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStories +import org.wordpress.android.ui.pages.SnackbarMessageHolder +import org.wordpress.android.ui.stories.StoriesMediaPickerResultHandler +import org.wordpress.android.ui.stories.StoriesTrackerHelper +import org.wordpress.android.ui.utils.UiString.UiStringRes +import org.wordpress.android.ui.utils.UiString.UiStringText +import org.wordpress.android.util.EventBusWrapper +import org.wordpress.android.util.merge +import org.wordpress.android.viewmodel.ContextProvider +import org.wordpress.android.viewmodel.Event +import org.wordpress.android.viewmodel.ResourceProvider +import javax.inject.Inject + +class SiteStoriesHandler +@Inject constructor( + private val eventBusWrapper: EventBusWrapper, + private val resourceProvider: ResourceProvider, + private val storiesTrackerHelper: StoriesTrackerHelper, + private val contextProvider: ContextProvider, + private val selectedSiteRepository: SelectedSiteRepository, + private val storiesMediaPickerResultHandler: StoriesMediaPickerResultHandler +) { + private val _onSnackbar = MutableLiveData>() + val onSnackbar = _onSnackbar as LiveData> + private val _onNavigation = MutableLiveData>() + val onNavigation = merge(_onNavigation, storiesMediaPickerResultHandler.onNavigation) + + init { + eventBusWrapper.register(this) + } + + fun clear() { + eventBusWrapper.unregister(this) + } + + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + fun onEventMainThread(event: StorySaveResult) { + EventBus.getDefault().removeStickyEvent(event) + if (!event.isSuccess()) { + // note: no tracking added here as we'll perform tracking in StoryMediaSaveUploadBridge + val errorText = String.format( + resourceProvider.getString(R.string.story_saving_snackbar_finished_with_error), + StoryRepository.getStoryAtIndex(event.storyIndex).title + ) + val snackbarMessage = FrameSaveNotifier.buildSnackbarErrorMessage( + contextProvider.getContext(), + StorySaveEvents.allErrorsInResult(event.frameSaveResult).size, + errorText + ) + + _onSnackbar.postValue( + Event( + SnackbarMessageHolder( + UiStringText(snackbarMessage), + UiStringRes(R.string.story_saving_failed_quick_action_manage) + ) { + val selectedSite = selectedSiteRepository.getSelectedSite() + ?: return@SnackbarMessageHolder + _onNavigation.postValue(Event(OpenStories(selectedSite, event))) + // TODO WPSTORIES add TRACKS: the putExtra described here below for NOTIFICATION_TYPE + // is meant to be used for tracking purposes. Use it! + // TODO add NotificationType.MEDIA_SAVE_ERROR param later when integrating with WPAndroid + // val notificationType = NotificationType.MEDIA_SAVE_ERROR + // notificationIntent.putExtra(ARG_NOTIFICATION_TYPE, notificationType) + storiesTrackerHelper.trackStorySaveResultEvent( + event, + STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED + ) + } + ) + ) + } + } + + @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) + fun onStorySaveStart(event: StorySaveProcessStart) { + EventBus.getDefault().removeStickyEvent(event) + val snackbarMessage = String.format( + resourceProvider.getString(R.string.story_saving_snackbar_started), + StoryRepository.getStoryAtIndex(event.storyIndex).title + ) + _onSnackbar.postValue(Event(SnackbarMessageHolder(UiStringText(snackbarMessage)))) + } + + fun handleStoriesResult(siteModel: SiteModel, data: Intent, source: PagePostCreationSourcesDetail) { + storiesMediaPickerResultHandler.handleMediaPickerResultForStories(data, siteModel, source) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt index 0e3fd3cd563f..98e94844607e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt @@ -2,18 +2,28 @@ package org.wordpress.android.ui.stories import android.app.Activity import android.content.Intent +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.PagePostCreationSourcesDetail import org.wordpress.android.ui.media.MediaBrowserActivity import org.wordpress.android.ui.media.MediaBrowserType +import org.wordpress.android.ui.mysite.SiteNavigationAction +import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStory +import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStoryWithMediaIds +import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStoryWithMediaUris import org.wordpress.android.ui.photopicker.MediaPickerConstants import org.wordpress.android.util.AppLog import org.wordpress.android.util.AppLog.T.UTILS +import org.wordpress.android.viewmodel.Event import javax.inject.Inject class StoriesMediaPickerResultHandler @Inject constructor() { + private val _onNavigation = MutableLiveData>() + val onNavigation = _onNavigation as LiveData> + /* return true if MediaPickerResult was handled */ fun handleMediaPickerResultForStories( data: Intent, @@ -21,24 +31,60 @@ class StoriesMediaPickerResultHandler selectedSite: SiteModel?, source: PagePostCreationSourcesDetail ): Boolean { - if (data.getBooleanExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, false)) { - ActivityLauncher.addNewStoryForResult( + if (selectedSite == null) { + return false + } + when (val navigationAction = buildNavigationAction(data, selectedSite, source)) { + is AddNewStory -> ActivityLauncher.addNewStoryForResult( + activity, + navigationAction.site, + navigationAction.source + ) + is AddNewStoryWithMediaIds -> ActivityLauncher.addNewStoryWithMediaIdsForResult( + activity, + navigationAction.site, + navigationAction.source, + navigationAction.mediaIds.toLongArray() + ) + is AddNewStoryWithMediaUris -> ActivityLauncher.addNewStoryWithMediaUrisForResult( activity, - selectedSite, - source + navigationAction.site, + navigationAction.source, + navigationAction.mediaUris.toTypedArray() ) - return true + else -> { + return false + } + } + + return true + } + + fun handleMediaPickerResultForStories( + data: Intent, + selectedSite: SiteModel, + source: PagePostCreationSourcesDetail + ): Boolean { + val navigationAction = buildNavigationAction(data, selectedSite, source) + return if (navigationAction != null) { + _onNavigation.postValue(Event(navigationAction)) + true + } else { + false + } + } + + private fun buildNavigationAction( + data: Intent, + selectedSite: SiteModel, + source: PagePostCreationSourcesDetail + ): SiteNavigationAction? { + if (data.getBooleanExtra(MediaPickerConstants.EXTRA_LAUNCH_WPSTORIES_CAMERA_REQUESTED, false)) { + return AddNewStory(selectedSite, source) } else if (isWPStoriesMediaBrowserTypeResult(data)) { if (data.hasExtra(MediaBrowserActivity.RESULT_IDS)) { - ActivityLauncher.addNewStoryWithMediaIdsForResult( - activity, - selectedSite, - source, - data.getLongArrayExtra( - MediaBrowserActivity.RESULT_IDS - ) - ) - return true + val mediaIds = data.getLongArrayExtra(MediaBrowserActivity.RESULT_IDS)?.asList() ?: listOf() + return AddNewStoryWithMediaIds(selectedSite, source, mediaIds) } else { val mediaUriStringsArray = data.getStringArrayExtra( MediaPickerConstants.EXTRA_MEDIA_URIS @@ -48,18 +94,17 @@ class StoriesMediaPickerResultHandler UTILS, "Can't resolve picked or captured image" ) - return false + return null } - ActivityLauncher.addNewStoryWithMediaUrisForResult( - activity, - selectedSite, - source, - mediaUriStringsArray - ) - return true + val mediaUris = mediaUriStringsArray.asList() + return AddNewStoryWithMediaUris( + selectedSite, + source, + mediaUris = mediaUris + ) } } - return false + return null } private fun isWPStoriesMediaBrowserTypeResult(data: Intent): Boolean { diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt index e335ccb468a3..51e746f7e4eb 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt @@ -36,25 +36,24 @@ import org.wordpress.android.ui.mysite.ListItemAction.VIEW_SITE import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock.IconState -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.ConnectJetpackForStats -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenActivityLog -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenAdmin -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenComments -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMeScreen -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenMedia -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPages -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPlan -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPlugins -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenPosts -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenScan -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSharing -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSite -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSitePicker -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenSiteSettings -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenStats -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.OpenThemes -import org.wordpress.android.ui.mysite.MySiteViewModel.NavigationAction.StartWPComLoginForJetpackStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.ConnectJetpackForStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenComments +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMeScreen +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMedia +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPages +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPlan +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPlugins +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPosts +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenScan +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSharing +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSite +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSitePicker +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSiteSettings +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStats +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenThemes +import org.wordpress.android.ui.mysite.SiteNavigationAction.StartWPComLoginForJetpackStats import org.wordpress.android.ui.mysite.MySiteViewModel.TextInputDialogModel import org.wordpress.android.ui.mysite.MySiteViewModel.UiModel import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.ICON_CLICK @@ -89,7 +88,7 @@ class MySiteViewModelTest : BaseUnitTest() { private lateinit var snackbars: MutableList private lateinit var textInputDialogModels: MutableList private lateinit var dialogModels: MutableList - private lateinit var navigationActions: MutableList + private lateinit var navigationActions: MutableList private val avatarUrl = "https://1.gravatar.com/avatar/1000?s=96&d=identicon" private val siteUrl = "http://site.com" private val siteIcon = "http://site.com/icon.jpg" From 1abd0f6847138189b55739895981a600846eaac3 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Thu, 3 Dec 2020 16:32:54 +0100 Subject: [PATCH 034/144] Cleanup callback in MySiteFragment.kt --- .../android/ui/main/MySiteFragment.kt | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt index 9fddef16110b..11b794f60050 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt @@ -1189,22 +1189,21 @@ class MySiteFragment : Fragment(), uploadUtilsWrapper.showSnackbarError( requireActivity().findViewById(R.id.coordinator), snackbarMessage, - string.story_saving_failed_quick_action_manage, - View.OnClickListener { view: View? -> - // TODO WPSTORIES add TRACKS: the putExtra described here below for NOTIFICATION_TYPE - // is meant to be used for tracking purposes. Use it! - // TODO add NotificationType.MEDIA_SAVE_ERROR param later when integrating with WPAndroid - // val notificationType = NotificationType.MEDIA_SAVE_ERROR - // notificationIntent.putExtra(ARG_NOTIFICATION_TYPE, notificationType) - - storiesTrackerHelper.trackStorySaveResultEvent( - event, - STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED + string.story_saving_failed_quick_action_manage + ) { + // TODO WPSTORIES add TRACKS: the putExtra described here below for NOTIFICATION_TYPE + // is meant to be used for tracking purposes. Use it! + // TODO add NotificationType.MEDIA_SAVE_ERROR param later when integrating with WPAndroid + // val notificationType = NotificationType.MEDIA_SAVE_ERROR + // notificationIntent.putExtra(ARG_NOTIFICATION_TYPE, notificationType) + + storiesTrackerHelper.trackStorySaveResultEvent( + event, + STORY_SAVE_ERROR_SNACKBAR_MANAGE_TAPPED - ) - ActivityLauncher.viewStories(requireActivity(), selectedSite, event) - } - ) + ) + ActivityLauncher.viewStories(requireActivity(), selectedSite, event) + } } } From 15d4f82bc536885f74c9f95001c10b838bb00083 Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Fri, 4 Dec 2020 17:14:17 +0900 Subject: [PATCH 035/144] Update stories lib hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 42db044d6666..8ae4d190e586 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 42db044d666608780b063cfcf7cc3cefdeca5f6b +Subproject commit 8ae4d190e58680bd94d236c949c9f7e112da20d8 From b56f049740c5bc7b66e7b207dd71c9216044bcb4 Mon Sep 17 00:00:00 2001 From: Ceyhun Ozugur Date: Fri, 4 Dec 2020 10:20:52 +0100 Subject: [PATCH 036/144] Release script: Update gutenberg-mobile ref --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 6fed9ea5c5b8..b412abde5fc1 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 6fed9ea5c5b8b5fb87afcf4c1dc060e5e08f6e7a +Subproject commit b412abde5fc1529c39977e7514ce876b4a465f73 From 72df33327af3df1c18b9f7e20e4db2a7715ddc64 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 08:29:41 -0500 Subject: [PATCH 037/144] Move to recyclerview --- ...items.xml => backup_details_list_item.xml} | 19 +++++-- .../backup_download_details_fragment.xml | 51 +++---------------- .../src/main/res/values/backup_styles.xml | 16 ++++-- WordPress/src/main/res/values/strings.xml | 7 +++ 4 files changed, 39 insertions(+), 54 deletions(-) rename WordPress/src/main/res/layout/{backup_details_choose_items.xml => backup_details_list_item.xml} (65%) diff --git a/WordPress/src/main/res/layout/backup_details_choose_items.xml b/WordPress/src/main/res/layout/backup_details_list_item.xml similarity index 65% rename from WordPress/src/main/res/layout/backup_details_choose_items.xml rename to WordPress/src/main/res/layout/backup_details_list_item.xml index c5d154d40a83..c5c2e0d9fcd6 100644 --- a/WordPress/src/main/res/layout/backup_details_choose_items.xml +++ b/WordPress/src/main/res/layout/backup_details_list_item.xml @@ -4,26 +4,35 @@ android:id="@+id/item_container" android:background="?attr/selectableItemBackground" android:layout_width="match_parent" - android:layout_height="?attr/listPreferredItemHeight"> + android:layout_height="?attr/listPreferredItemHeight" + android:focusable="true"> + + diff --git a/WordPress/src/main/res/layout/backup_download_details_fragment.xml b/WordPress/src/main/res/layout/backup_download_details_fragment.xml index 77a2a9cd9588..949e9da4a3cd 100644 --- a/WordPress/src/main/res/layout/backup_download_details_fragment.xml +++ b/WordPress/src/main/res/layout/backup_download_details_fragment.xml @@ -54,56 +54,17 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/backup_details_action_button" + app:layout_constraintBottom_toTopOf="@+id/recycler_view" tools:text="Items included in this download" android:text="@string/backup_download_details_choose_items_header"/> - - - - - - - - - - - - - + app:layout_constraintBottom_toBottomOf="parent"/> diff --git a/WordPress/src/main/res/values/backup_styles.xml b/WordPress/src/main/res/values/backup_styles.xml index 33aec340e943..10ca523ccaea 100644 --- a/WordPress/src/main/res/values/backup_styles.xml +++ b/WordPress/src/main/res/values/backup_styles.xml @@ -1,10 +1,10 @@ - - - - + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index d2eebe9e60a0..4b2dd7cd56b9 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -3310,4 +3310,11 @@ translators: sample content for "Services" page template --> Choose the items you wish to include in the download: Create downloadable file Create downloadable backup icon + + WordPress Themes + WordPress Plugins + Media Uploads + WordPress root (includes wp-config php and any non WordPress files) + WP-content directory (excludes themes, plugins, and uploads) + Site database (SQL) From 545d8b5fdb6339c667b2412bbd3f6680f871d972 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 08:30:13 -0500 Subject: [PATCH 038/144] Support for available items for backup or restore --- .../jetpack/BackupAvailableItemsProvider.kt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt new file mode 100644 index 000000000000..88ecc4072cee --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt @@ -0,0 +1,61 @@ +package org.wordpress.android.ui.jetpack + +import androidx.annotation.StringRes +import org.wordpress.android.R.string +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.CONTENTS +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.MEDIA_UPLOADS +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.ROOTS +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.SQLS +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.THEMES +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.PLUGINS +import javax.inject.Inject +import javax.inject.Singleton + +/** + * This class provides the available item choices for Jetpack Backup Download + */ +@Singleton +class BackupAvailableItemsProvider @Inject constructor() { + fun getAvailableItems() : List { + return listOf( + BackupAvailableItem( + THEMES, + string.backup_item_themes + ), + BackupAvailableItem( + PLUGINS, + string.backup_item_plugins + ), + BackupAvailableItem( + MEDIA_UPLOADS, + string.backup_item_media_uploads + ), + BackupAvailableItem( + SQLS, + string.backup_item_sqls + ), + BackupAvailableItem( + ROOTS, + string.backup_item_roots + ), + BackupAvailableItem( + CONTENTS, + string.backup_item_contents + ) + ) + } + + data class BackupAvailableItem( + val availableItemType: BackupAvailableItemType, + @StringRes val labelResId: Int + ) + + enum class BackupAvailableItemType { + THEMES, + PLUGINS, + MEDIA_UPLOADS, + SQLS, + ROOTS, + CONTENTS + } +} From f029b32e6baf3e34739a48413728d0751aa7b28a Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 08:32:14 -0500 Subject: [PATCH 039/144] Add base uiState, hook up adapter --- .../details/BackupDownloadDetailsAdapter.kt | 66 +++++++++++++ .../details/BackupDownloadDetailsFragment.kt | 42 +++++++-- .../BackupDownloadDetailsViewHolder.kt | 32 +++++++ .../details/BackupDownloadDetailsViewModel.kt | 92 ++++++++++++++++++- 4 files changed, 218 insertions(+), 14 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsAdapter.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsAdapter.kt new file mode 100644 index 000000000000..62335f4ca729 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsAdapter.kt @@ -0,0 +1,66 @@ +package org.wordpress.android.ui.jetpack.backup.details + +import android.view.ViewGroup +import androidx.annotation.MainThread +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.ListItemUiState +import org.wordpress.android.ui.utils.UiHelpers + +class BackupDownloadDetailsAdapter(private val uiHelpers: UiHelpers) : + RecyclerView.Adapter() { + private val items = mutableListOf() + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): BackupDownloadDetailsViewHolder { + return BackupDownloadDetailsViewHolder.BackupDownloadDetailsListItemViewHolder(parent, uiHelpers) + } + + override fun getItemCount(): Int = items.size + + override fun getItemId(position: Int): Long { + return position.toLong() + } + + override fun onBindViewHolder(holder: BackupDownloadDetailsViewHolder, position: Int) { + holder.onBind(items[position]) + } + + @MainThread + fun update(newItems: List) { + val diffResult = DiffUtil.calculateDiff( + BackupDownloadDetailsListDiffUtils( + items.toList(), + newItems + ) + ) + items.clear() + items.addAll(newItems) + diffResult.dispatchUpdatesTo(this) + } + + private class BackupDownloadDetailsListDiffUtils( + val oldItems: List, + val newItems: List + ) : DiffUtil.Callback() { + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + val oldItem = oldItems[oldItemPosition] + val newItem = newItems[newItemPosition] + if (oldItem::class != newItem::class) { + return false + } + + return oldItem.label == newItem.label + } + + override fun getOldListSize(): Int = oldItems.size + + override fun getNewListSize(): Int = newItems.size + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return oldItems[oldItemPosition] == newItems[newItemPosition] + } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsFragment.kt index 82aab974ee0b..a16cea123042 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsFragment.kt @@ -5,15 +5,24 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.backup_download_details_fragment.* import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.ui.jetpack.backup.BackupDownloadViewModel +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.UiState.Content +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.UiState.Loading +import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.util.ToastUtils import javax.inject.Inject class BackupDownloadDetailsFragment : Fragment() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject lateinit var uiHelpers: UiHelpers private lateinit var parentViewModel: BackupDownloadViewModel private lateinit var viewModel: BackupDownloadDetailsViewModel override fun onCreateView( @@ -30,24 +39,39 @@ class BackupDownloadDetailsFragment : Fragment() { val nonNullActivity = requireActivity() (nonNullActivity.application as WordPress).component().inject(this) + initRecyclerView() + initViewModel() + } + + private fun initRecyclerView() { + recycler_view.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) + initAdapter() + } + + private fun initAdapter() { + recycler_view.adapter = BackupDownloadDetailsAdapter(uiHelpers) + } + + private fun initViewModel() { parentViewModel = ViewModelProviders.of(requireActivity(), viewModelFactory) .get(BackupDownloadViewModel::class.java) viewModel = ViewModelProviders.of(this, viewModelFactory) .get(BackupDownloadDetailsViewModel::class.java) - setupViews() - setupObservers() - // todo: annmarie - if something needs to be passed to VM, do it on start - viewModel.start() - } + viewModel.uiState.observe(viewLifecycleOwner, Observer { uiState -> + when (uiState) { + is Loading -> ToastUtils.showToast(requireContext(), "Implement loading") + is Content -> showContent(uiState) + is Error -> ToastUtils.showToast(requireContext(), "Implement Error") + } + }) - private fun setupViews() { - // TODO: annmarie implement setupViews + viewModel.start() } - private fun setupObservers() { - // TODO: annmarie implement setupObservers + private fun showContent(content: Content) { + ((recycler_view.adapter) as BackupDownloadDetailsAdapter).update(content.items) } companion object { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt new file mode 100644 index 000000000000..7fe7cd0fdef2 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt @@ -0,0 +1,32 @@ +package org.wordpress.android.ui.jetpack.backup.details + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.backup_details_list_item.view.* +import org.wordpress.android.R +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.ListItemUiState +import org.wordpress.android.ui.utils.UiHelpers + +sealed class BackupDownloadDetailsViewHolder( + internal val parent: ViewGroup, + @LayoutRes layout: Int +) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(layout, parent, false)) { + abstract fun onBind(uiState: ListItemUiState) + + class BackupDownloadDetailsListItemViewHolder( + parentView: ViewGroup, + private val uiHelpers: UiHelpers + ) : BackupDownloadDetailsViewHolder(parentView, R.layout.backup_details_list_item) { + private val container = itemView.item_container + private val checkbox = itemView.checkbox + private val label = itemView.checkbox_label + + override fun onBind(uiState: ListItemUiState) { + uiHelpers.setTextOrHide(label, uiState.label) + checkbox.isChecked = uiState.checked + container.setOnClickListener { uiState.onClick.invoke() } + } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewModel.kt index a1f5e0e65a7d..5b9b1e7165df 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewModel.kt @@ -1,15 +1,97 @@ package org.wordpress.android.ui.jetpack.backup.details -import androidx.lifecycle.ViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.wordpress.android.R +import org.wordpress.android.modules.BG_THREAD +import org.wordpress.android.modules.UI_THREAD +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItem +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.UiState.Content +import org.wordpress.android.ui.utils.UiString +import org.wordpress.android.ui.utils.UiString.UiStringRes +import org.wordpress.android.viewmodel.ScopedViewModel import javax.inject.Inject +import javax.inject.Named -class BackupDownloadDetailsViewModel @Inject constructor() : ViewModel() { +class BackupDownloadDetailsViewModel @Inject constructor( + private val backupAvailableItemsProvider: BackupAvailableItemsProvider, + @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher, + @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher +) : ScopedViewModel(mainDispatcher) { private var isStarted: Boolean = false + + private val _uiState = MutableLiveData() + val uiState: LiveData = _uiState + fun start() { - if (isStarted) { - return + if (isStarted) return + isStarted = true + + // todo: annmarie - this is a temp name until useCase has been added for record dets :) + getData() + } + + private fun getData() { + launch { + val availableItems = backupAvailableItemsProvider.getAvailableItems() + _uiState.value = buildContentUiState(availableItems) } + } - isStarted = true + private suspend fun buildContentUiState(items: List): Content { + return withContext(bgDispatcher) { + val availableItemsListItems: List = items.map { + ListItemUiState( + availableItemType = it.availableItemType, + label = UiStringRes(it.labelResId), + checked = true, + onClick = { onItemClicked(it.availableItemType) } + ) + } + // todo: annmarie - swap out the placeholder for date from record + Content( + description = UiStringRes(R.string.backup_download_details_description), + items = availableItemsListItems + ) + } } + + private fun onItemClicked(backupAvailableItemType: BackupAvailableItemType) { + // todo: annmarie update the checkboxes - keep a running list of selected checkboxes, so + // they can be persisted on rotation + (_uiState.value as? Content)?.let { content -> + val updatedList = content.items.map { itemUiState -> + if (itemUiState.availableItemType == backupAvailableItemType) { + itemUiState.copy(checked = !itemUiState.checked) + } else { + itemUiState + } + } + _uiState.postValue(content.copy(items = updatedList)) + } + } + + sealed class UiState { + // todo: annmarie - add error/loading states - what SHOULD happen if I can't get the record? + data class Error(val message: String) : UiState() + + data class Loading(val message: String) : UiState() + + data class Content( + val description: UiString, + val items: List + ) : UiState() + } + + data class ListItemUiState( + val availableItemType: BackupAvailableItemType, + val label: UiString, + val checked: Boolean = false, + val onClick: (() -> Unit) + ) } From ea80a5317f65907a691ac377d4a793c01f026b96 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 08:32:34 -0500 Subject: [PATCH 040/144] Lint fix --- .../android/ui/jetpack/BackupAvailableItemsProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt index 88ecc4072cee..14a7e0ae98ae 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt @@ -16,7 +16,7 @@ import javax.inject.Singleton */ @Singleton class BackupAvailableItemsProvider @Inject constructor() { - fun getAvailableItems() : List { + fun getAvailableItems(): List { return listOf( BackupAvailableItem( THEMES, From b08311d71b79cf8a0990d03ef2525dccae6120b3 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 10:49:54 -0300 Subject: [PATCH 041/144] updated stories lib hash and bring the upload string up for translation --- .idea/compiler.xml | 15 ++++++++++++++- WordPress/src/main/res/values/strings.xml | 1 + libs/stories-android | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index d9c7dcdd7264..d990b2800f03 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,9 +11,22 @@ - + + + + + + + + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index e543f3d4310e..b26571258569 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2982,6 +2982,7 @@ errored Change text alignment Change text color + Upload Delete story slide? This slide will be removed from your story. This slide has not been saved yet. If you delete this slide, you will lose any edits you have made. diff --git a/libs/stories-android b/libs/stories-android index 8ae4d190e586..db4bf9006ba6 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 8ae4d190e58680bd94d236c949c9f7e112da20d8 +Subproject commit db4bf9006ba6bab5ac699522c94afb09c63e40bb From a67a8a69d8c9b50a65dac392946dd499a1a02c1d Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 08:55:13 -0500 Subject: [PATCH 042/144] Add test --- .../BackupAvailableItemsProviderTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt new file mode 100644 index 000000000000..83d0b5043f89 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt @@ -0,0 +1,29 @@ +package org.wordpress.android.ui.jetpack + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.junit.MockitoJUnitRunner + +@RunWith(MockitoJUnitRunner::class) +class BackupAvailableItemsProviderTest { + private lateinit var provider: BackupAvailableItemsProvider + + @Before + fun setUp() { + provider = BackupAvailableItemsProvider() + } + + @Test + fun `when requested, the available items list is returned`() { + // setup + val expectedItemCount = 6 + + // act + val items = provider.getAvailableItems() + + // Assert + assertThat(items.size).isEqualTo(expectedItemCount) + } +} \ No newline at end of file From 34cde4ea9239788e27726c95730df11bf57e0cbe Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 11:20:19 -0300 Subject: [PATCH 043/144] Revert "updated stories lib hash and bring the upload string up for translation" This reverts commit b08311d71b79cf8a0990d03ef2525dccae6120b3. --- .idea/compiler.xml | 15 +-------------- WordPress/src/main/res/values/strings.xml | 1 - libs/stories-android | 2 +- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index d990b2800f03..d9c7dcdd7264 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,22 +11,9 @@ - + - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index b26571258569..e543f3d4310e 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2982,7 +2982,6 @@ errored Change text alignment Change text color - Upload Delete story slide? This slide will be removed from your story. This slide has not been saved yet. If you delete this slide, you will lose any edits you have made. diff --git a/libs/stories-android b/libs/stories-android index db4bf9006ba6..8ae4d190e586 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit db4bf9006ba6bab5ac699522c94afb09c63e40bb +Subproject commit 8ae4d190e58680bd94d236c949c9f7e112da20d8 From 93935f203dea6f970d1c1b77ecfa09fee33a7883 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 09:20:25 -0500 Subject: [PATCH 044/144] Add tests --- .../BackupDownloadDetailsViewModelTest.kt | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt new file mode 100644 index 000000000000..0617fe9d8b01 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt @@ -0,0 +1,73 @@ +package org.wordpress.android.ui.jetpack.backup + +import kotlinx.coroutines.InternalCoroutinesApi +import org.assertj.core.api.Assertions.assertThat +import org.junit.Before +import org.junit.Test +import org.wordpress.android.BaseUnitTest +import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.test +import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.UiState +import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsViewModel.UiState.Content + +@InternalCoroutinesApi +class BackupDownloadDetailsViewModelTest : BaseUnitTest() { + private lateinit var viewModel: BackupDownloadDetailsViewModel + private lateinit var availableItemsProvider: BackupAvailableItemsProvider + + @Before + fun setUp() { + availableItemsProvider = BackupAvailableItemsProvider() + viewModel = BackupDownloadDetailsViewModel( + availableItemsProvider, + TEST_DISPATCHER, + TEST_DISPATCHER + ) + } + + @Test + fun `when available items are fetched, the content view is shown`() = test { + val uiStates = initObservers().uiStates + + viewModel.start() + + assertThat(uiStates[0]).isInstanceOf(UiState.Content::class.java) + } + + @Test + fun `item is unchecked, when it is clicked on`() = test { + val uiStates = initObservers().uiStates + + viewModel.start() + + ((uiStates.last() as Content).items[1]).onClick.invoke() + + assertThat(((uiStates.last() as Content).items[1]).checked).isFalse() + } + + @Test + fun `item is checked, when it is clicked on twice `() = test { + val uiStates = initObservers().uiStates + + viewModel.start() + + ((uiStates.last() as Content).items[1]).onClick.invoke() + ((uiStates.last() as Content).items[1]).onClick.invoke() + + assertThat(((uiStates.last() as Content).items[1]).checked).isTrue() + } + + private fun initObservers(): Observers { + val uiStates = mutableListOf() + viewModel.uiState.observeForever { + uiStates.add(it) + } + return Observers(uiStates) + } + + private data class Observers( + val uiStates: List + ) +} \ No newline at end of file From 4732cecf659ea54bd5aed22609eba2e87015481e Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 11:23:24 -0300 Subject: [PATCH 045/144] updated stories lib hash and bring the upload string up for translation --- WordPress/src/main/res/values/strings.xml | 1 + libs/stories-android | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index e543f3d4310e..b26571258569 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -2982,6 +2982,7 @@ errored Change text alignment Change text color + Upload Delete story slide? This slide will be removed from your story. This slide has not been saved yet. If you delete this slide, you will lose any edits you have made. diff --git a/libs/stories-android b/libs/stories-android index 8ae4d190e586..db4bf9006ba6 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 8ae4d190e58680bd94d236c949c9f7e112da20d8 +Subproject commit db4bf9006ba6bab5ac699522c94afb09c63e40bb From 140f273b4475d13c3540ce06cb7dc022b211560a Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 11:38:53 -0300 Subject: [PATCH 046/144] updated stories lib commit hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index db4bf9006ba6..83c5a1fcba1e 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit db4bf9006ba6bab5ac699522c94afb09c63e40bb +Subproject commit 83c5a1fcba1e5a0a59ca12e827653da40b9467ef From 18d8ccf4bba748d5c73dca39ef17a8f755bc617e Mon Sep 17 00:00:00 2001 From: Ceyhun Ozugur Date: Fri, 4 Dec 2020 15:42:05 +0100 Subject: [PATCH 047/144] Update gutenberg-mobile ref --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index b412abde5fc1..3000ec02cdb9 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit b412abde5fc1529c39977e7514ce876b4a465f73 +Subproject commit 3000ec02cdb9a2c9176e580f63a7767af6376fe4 From 266dd7368628faaf4f716f4e8d6641bf3462322d Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 09:42:39 -0500 Subject: [PATCH 048/144] Remove unused backupFeatureConfig --- .../android/ui/activitylog/list/ActivityLogListActivity.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt index 23f386174df0..7cbec273f02b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt @@ -9,14 +9,11 @@ import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.LocaleAwareActivity import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.posts.BasicFragmentDialog -import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.viewmodel.activitylog.ACTIVITY_LOG_REWIND_ID_KEY -import javax.inject.Inject class ActivityLogListActivity : LocaleAwareActivity(), BasicFragmentDialog.BasicDialogPositiveClickInterface, BasicFragmentDialog.BasicDialogNegativeClickInterface { - @Inject lateinit var backupFeatureConfig: BackupFeatureConfig override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) From 7cfd0eedab767c62f72c854077e4b12132a45add Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Fri, 4 Dec 2020 16:15:19 +0100 Subject: [PATCH 049/144] Update fastlane/Fastfile Co-authored-by: Olivier Halligon --- fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 978cf887f692..a65ba4ab7815 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -241,7 +241,7 @@ ENV["validate_translations"]="lintVanillaRelease" # This lane builds the final release of the app and uploads it # ----------------------------------------------------------------------------------- # Usage: - # bundle exec fastlane build_and_upload_release [skip_confirm:] [skip_prechecks:] [create_release: ] + # bundle exec fastlane build_and_upload_release [skip_confirm:] [skip_prechecks:] [create_release: ] # # Example: # bundle exec fastlane build_and_upload_release From 52adb7f67790ea7c7b113d8e121faabee847bc4e Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Fri, 4 Dec 2020 16:15:26 +0100 Subject: [PATCH 050/144] Update fastlane/Fastfile Co-authored-by: Olivier Halligon --- fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index a65ba4ab7815..7b4e5af08859 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -255,7 +255,7 @@ ENV["validate_translations"]="lintVanillaRelease" alpha: false, beta: false, final: true) - android_build_preflight() unless (options[:skip_prechecks]) + android_build_preflight() unless options[:skip_prechecks] # Create the file names version=android_get_release_version() From f1411930806a043a65e656b99fe4d1d2563cfddc Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 4 Dec 2020 16:24:02 +0100 Subject: [PATCH 051/144] Fix unit test --- .../android/ui/mysite/MySiteViewModelTest.kt | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt index 51e746f7e4eb..9f5e73f3933c 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt @@ -36,6 +36,14 @@ import org.wordpress.android.ui.mysite.ListItemAction.VIEW_SITE import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock.IconState +import org.wordpress.android.ui.mysite.MySiteViewModel.TextInputDialogModel +import org.wordpress.android.ui.mysite.MySiteViewModel.UiModel +import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.ICON_CLICK +import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.SWITCH_SITE_CLICK +import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.TITLE_CLICK +import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.URL_CLICK +import org.wordpress.android.ui.mysite.SiteDialogModel.AddSiteIconDialogModel +import org.wordpress.android.ui.mysite.SiteDialogModel.ChangeSiteIconDialogModel import org.wordpress.android.ui.mysite.SiteNavigationAction.ConnectJetpackForStats import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin @@ -54,14 +62,6 @@ import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenSiteSettings import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenStats import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenThemes import org.wordpress.android.ui.mysite.SiteNavigationAction.StartWPComLoginForJetpackStats -import org.wordpress.android.ui.mysite.MySiteViewModel.TextInputDialogModel -import org.wordpress.android.ui.mysite.MySiteViewModel.UiModel -import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.ICON_CLICK -import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.SWITCH_SITE_CLICK -import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.TITLE_CLICK -import org.wordpress.android.ui.mysite.MySiteViewModelTest.SiteInfoBlockAction.URL_CLICK -import org.wordpress.android.ui.mysite.SiteDialogModel.AddSiteIconDialogModel -import org.wordpress.android.ui.mysite.SiteDialogModel.ChangeSiteIconDialogModel import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.util.FluxCUtilsWrapper @@ -83,6 +83,7 @@ class MySiteViewModelTest : BaseUnitTest() { @Mock lateinit var fluxCUtilsWrapper: FluxCUtilsWrapper @Mock lateinit var contextProvider: ContextProvider @Mock lateinit var siteIconUploadHandler: SiteIconUploadHandler + @Mock lateinit var siteStoriesHandler: SiteStoriesHandler private lateinit var viewModel: MySiteViewModel private lateinit var uiModels: MutableList private lateinit var snackbars: MutableList @@ -118,7 +119,8 @@ class MySiteViewModelTest : BaseUnitTest() { mediaUtilsWrapper, fluxCUtilsWrapper, contextProvider, - siteIconUploadHandler + siteIconUploadHandler, + siteStoriesHandler ) uiModels = mutableListOf() snackbars = mutableListOf() From f7b24c5a80f2d0a334f8d7f8ad91b3fac3acbbec Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 4 Dec 2020 10:27:48 -0500 Subject: [PATCH 052/144] Fix lint: --- .../android/ui/jetpack/BackupAvailableItemsProviderTest.kt | 2 +- .../ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt index 83d0b5043f89..a75cc4983026 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProviderTest.kt @@ -26,4 +26,4 @@ class BackupAvailableItemsProviderTest { // Assert assertThat(items.size).isEqualTo(expectedItemCount) } -} \ No newline at end of file +} diff --git a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt index 0617fe9d8b01..ac8998c742b7 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt @@ -70,4 +70,4 @@ class BackupDownloadDetailsViewModelTest : BaseUnitTest() { private data class Observers( val uiStates: List ) -} \ No newline at end of file +} From faff79b8e4a0f6887f60409e29b44c59906de8b2 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 4 Dec 2020 16:30:02 +0100 Subject: [PATCH 053/144] Fix lint issue --- .../org/wordpress/android/ui/mysite/SiteNavigationAction.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt index 0fe49680291d..5bd73dd66318 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt @@ -45,4 +45,4 @@ sealed class SiteNavigationAction { val source: PagePostCreationSourcesDetail, val mediaUris: List ) : SiteNavigationAction() -} \ No newline at end of file +} From 2d21cb123459b2cacb6790de80ea1bd385a49db2 Mon Sep 17 00:00:00 2001 From: Cameron Voell Date: Fri, 4 Dec 2020 10:59:30 -0800 Subject: [PATCH 054/144] Updated gutenberg-mobile reference to release tag --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 3000ec02cdb9..6fed9ea5c5b8 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 3000ec02cdb9a2c9176e580f63a7767af6376fe4 +Subproject commit 6fed9ea5c5b8b5fb87afcf4c1dc060e5e08f6e7a From 1f6134d3d283546aac209f289f8e63ed0ca5c704 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 16:20:34 -0300 Subject: [PATCH 055/144] updated stories hash lib --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index 83c5a1fcba1e..cca23900bcbb 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit 83c5a1fcba1e5a0a59ca12e827653da40b9467ef +Subproject commit cca23900bcbb2d31974481e216db93e0920494c1 From 46dfca527d84d3757ebc5a0948c753f85510eca0 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 19:22:05 -0300 Subject: [PATCH 056/144] changed flow for remote media from WP site to be copied locally before feeding the Story composer --- .../ui/photopicker/PhotoPickerActivity.java | 7 +------ .../ui/photopicker/PhotoPickerFragment.kt | 4 ++++ .../ui/photopicker/PhotoPickerViewModel.kt | 18 +++++++++++++++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java index 70b3c4eb9646..bdccb881bb0c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerActivity.java @@ -325,12 +325,7 @@ private void doMediaIdsSelected(ArrayList mediaIds, @NonNull PhotoPickerMe if (mediaIds != null && mediaIds.size() > 0) { if (mBrowserType == MediaBrowserType.WP_STORIES_MEDIA_PICKER) { // TODO WPSTORIES add TRACKS (see how it's tracked below? maybe do along the same lines) - Intent data = new Intent() - .putExtra(MediaBrowserActivity.RESULT_IDS, ListUtils.toLongArray(mediaIds)) - .putExtra(ARG_BROWSER_TYPE, mBrowserType) - .putExtra(MediaPickerConstants.EXTRA_MEDIA_SOURCE, source.name()); - setResult(RESULT_OK, data); - finish(); + getPickerFragment().mediaIdsSelectedFromWPMediaPicker(mediaIds); } else { // if user chose a featured image, track image picked event if (mBrowserType == MediaBrowserType.FEATURED_IMAGE_PICKER) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt index 00a764baa0f4..d29c219bf060 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerFragment.kt @@ -474,6 +474,10 @@ class PhotoPickerFragment : Fragment() { viewModel.urisSelectedFromSystemPicker(uris.map { UriWrapper(it) }) } + fun mediaIdsSelectedFromWPMediaPicker(mediaIds: List) { + viewModel.mediaIdsSelectedFromWPMediaPicker(mediaIds) + } + companion object { private const val KEY_LAST_TAPPED_ICON = "last_tapped_icon" private const val KEY_SELECTED_POSITIONS = "selected_positions" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt index 548ca7d91d30..03f62cb4105c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt @@ -1,6 +1,7 @@ package org.wordpress.android.ui.photopicker import android.Manifest.permission +import android.net.Uri import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher @@ -16,6 +17,7 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_W import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_WP_STORIES_CAPTURE import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_PREVIEW_OPENED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_RECENT_MEDIA_SELECTED +import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.modules.UI_THREAD @@ -41,6 +43,7 @@ import org.wordpress.android.ui.photopicker.PhotoPickerViewModel.BottomBarUiMode import org.wordpress.android.ui.photopicker.PhotoPickerViewModel.BottomBarUiModel.BottomBar.NONE import org.wordpress.android.ui.photopicker.PhotoPickerViewModel.PopupMenuUiModel.PopupMenuItem import org.wordpress.android.ui.posts.editor.media.CopyMediaToAppStorageUseCase +import org.wordpress.android.ui.posts.editor.media.GetMediaModelUseCase import org.wordpress.android.ui.utils.UiString import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.ui.utils.UiString.UiStringText @@ -75,7 +78,8 @@ class PhotoPickerViewModel @Inject constructor( private val permissionsHandler: PermissionsHandler, private val tenorFeatureConfig: TenorFeatureConfig, private val resourceProvider: ResourceProvider, - private val copyMediaToAppStorageUseCase: CopyMediaToAppStorageUseCase + private val copyMediaToAppStorageUseCase: CopyMediaToAppStorageUseCase, + private val getMediaModelUseCase: GetMediaModelUseCase ) : ScopedViewModel(mainDispatcher) { private val _navigateToPreview = MutableLiveData>() private val _onInsert = MutableLiveData>>() @@ -478,6 +482,18 @@ class PhotoPickerViewModel @Inject constructor( } fun urisSelectedFromSystemPicker(uris: List) { + copySelectedUrisLocally(uris) + } + + fun mediaIdsSelectedFromWPMediaPicker(mediaIds: List) { + launch { + val mediaModels = getMediaModelUseCase + .loadMediaByRemoteId(requireNotNull(site), mediaIds) + copySelectedUrisLocally(mediaModels.map { UriWrapper(Uri.parse(it.url)) }) + } + } + + fun copySelectedUrisLocally(uris: List) { launch { _showProgressDialog.value = ProgressDialogUiModel.Visible(R.string.uploading_title) { _showProgressDialog.postValue(ProgressDialogUiModel.Hidden) From 13807d182e8a8093b8e7e81e1b3342ffba82d6fa Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 19:29:12 -0300 Subject: [PATCH 057/144] removed unused import --- .../org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt index 03f62cb4105c..8617ba0a0044 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModel.kt @@ -17,7 +17,6 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_W import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_OPEN_WP_STORIES_CAPTURE import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_PREVIEW_OPENED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MEDIA_PICKER_RECENT_MEDIA_SELECTED -import org.wordpress.android.fluxc.model.MediaModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.modules.BG_THREAD import org.wordpress.android.modules.UI_THREAD From 8b2c56c0ef6b2f44b98547945c014bbfa0c3c7bf Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 19:59:07 -0300 Subject: [PATCH 058/144] updated test --- .../android/ui/photopicker/PhotoPickerViewModelTest.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModelTest.kt index 1c1fdcec10a2..56dc9d16aa64 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/photopicker/PhotoPickerViewModelTest.kt @@ -29,6 +29,7 @@ import org.wordpress.android.ui.photopicker.PhotoPickerViewModel.PhotoListUiMode import org.wordpress.android.ui.photopicker.PhotoPickerViewModel.PhotoPickerUiState import org.wordpress.android.ui.photopicker.PhotoPickerViewModel.SoftAskViewUiModel import org.wordpress.android.ui.posts.editor.media.CopyMediaToAppStorageUseCase +import org.wordpress.android.ui.posts.editor.media.GetMediaModelUseCase import org.wordpress.android.ui.utils.UiString import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.ui.utils.UiString.UiStringText @@ -50,6 +51,7 @@ class PhotoPickerViewModelTest : BaseUnitTest() { @Mock lateinit var context: Context @Mock lateinit var resourceProvider: ResourceProvider @Mock lateinit var copyMediaToAppStorageUseCase: CopyMediaToAppStorageUseCase + @Mock lateinit var getMediaModelUseCase: GetMediaModelUseCase private lateinit var viewModel: PhotoPickerViewModel private var uiStates = mutableListOf() private var navigateEvents = mutableListOf>() @@ -71,7 +73,8 @@ class PhotoPickerViewModelTest : BaseUnitTest() { permissionsHandler, tenorFeatureConfig, resourceProvider, - copyMediaToAppStorageUseCase + copyMediaToAppStorageUseCase, + getMediaModelUseCase ) uiStates.clear() firstItem = PhotoPickerItem(1, uriWrapper1, false) From 732e45280d2e03907f6efae08a7ef34ce3bf0a30 Mon Sep 17 00:00:00 2001 From: Mario Zorz Date: Fri, 4 Dec 2020 20:20:14 -0300 Subject: [PATCH 059/144] udpated stories libs commit hash --- libs/stories-android | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/stories-android b/libs/stories-android index cca23900bcbb..e4be91f690c4 160000 --- a/libs/stories-android +++ b/libs/stories-android @@ -1 +1 @@ -Subproject commit cca23900bcbb2d31974481e216db93e0920494c1 +Subproject commit e4be91f690c4fac8fc94dfc3ac287fbb66217497 From 431766c9eaf0fc9f1f79aea102ae8a729608f37b Mon Sep 17 00:00:00 2001 From: Alex Forcier Date: Sat, 5 Dec 2020 09:03:08 +0900 Subject: [PATCH 060/144] Update gutenberg-mobile reference to release tag --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 6fed9ea5c5b8..5d7a4d2cf496 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 6fed9ea5c5b8b5fb87afcf4c1dc060e5e08f6e7a +Subproject commit 5d7a4d2cf496abbcdd0e5a2a2bf00a3a6bc00d6f From 681df63b5a59fd5920c02bedb917964c6335ec1d Mon Sep 17 00:00:00 2001 From: Jeremy Massel Date: Fri, 4 Dec 2020 22:51:33 -0700 Subject: [PATCH 061/144] Send strings to translation. --- fastlane/resources/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fastlane/resources/values/strings.xml b/fastlane/resources/values/strings.xml index 732fff4d611c..b26571258569 100644 --- a/fastlane/resources/values/strings.xml +++ b/fastlane/resources/values/strings.xml @@ -2958,6 +2958,7 @@ We couldn\'t find the media for this story on the site. GIF files not supported One or more slides have not been added to your Story because Stories don\'t support GIF files at the moment. Please choose a static image or video background instead. + Story being saved, please wait… Capture Flip camera Flash @@ -2981,6 +2982,7 @@ errored Change text alignment Change text color + Upload Delete story slide? This slide will be removed from your story. This slide has not been saved yet. If you delete this slide, you will lose any edits you have made. From 034ccd9fd5c09c26cbaa14116f3a4a494ef2f851 Mon Sep 17 00:00:00 2001 From: Jeremy Massel Date: Fri, 4 Dec 2020 23:17:28 -0700 Subject: [PATCH 062/144] Updates translations --- WordPress/src/main/res/values-ar/strings.xml | 1376 +++++++++-------- WordPress/src/main/res/values-bg/strings.xml | 4 - WordPress/src/main/res/values-cs/strings.xml | 5 - WordPress/src/main/res/values-de/strings.xml | 20 +- WordPress/src/main/res/values-el/strings.xml | 4 - .../src/main/res/values-en-rAU/strings.xml | 6 - .../src/main/res/values-en-rCA/strings.xml | 9 - .../src/main/res/values-en-rGB/strings.xml | 34 +- .../src/main/res/values-es-rCL/strings.xml | 6 - .../src/main/res/values-es-rCO/strings.xml | 63 +- .../src/main/res/values-es-rMX/strings.xml | 63 +- .../src/main/res/values-es-rVE/strings.xml | 34 +- WordPress/src/main/res/values-es/strings.xml | 1220 +++++++-------- WordPress/src/main/res/values-fr/strings.xml | 47 +- WordPress/src/main/res/values-gl/strings.xml | 8 - WordPress/src/main/res/values-he/strings.xml | 20 +- WordPress/src/main/res/values-id/strings.xml | 20 +- WordPress/src/main/res/values-it/strings.xml | 9 - WordPress/src/main/res/values-ja/strings.xml | 20 +- WordPress/src/main/res/values-kmr/strings.xml | 9 - WordPress/src/main/res/values-ko/strings.xml | 33 +- WordPress/src/main/res/values-ms/strings.xml | 4 - WordPress/src/main/res/values-nb/strings.xml | 16 +- WordPress/src/main/res/values-nl/strings.xml | 34 +- WordPress/src/main/res/values-pl/strings.xml | 9 - .../src/main/res/values-pt-rBR/strings.xml | 101 +- WordPress/src/main/res/values-ro/strings.xml | 34 +- WordPress/src/main/res/values-ru/strings.xml | 34 +- WordPress/src/main/res/values-sk/strings.xml | 5 - WordPress/src/main/res/values-sq/strings.xml | 9 - WordPress/src/main/res/values-sr/strings.xml | 5 - WordPress/src/main/res/values-sv/strings.xml | 32 +- WordPress/src/main/res/values-tr/strings.xml | 20 +- .../src/main/res/values-zh-rCN/strings.xml | 9 - .../src/main/res/values-zh-rHK/strings.xml | 20 +- .../src/main/res/values-zh-rTW/strings.xml | 20 +- 36 files changed, 1789 insertions(+), 1573 deletions(-) diff --git a/WordPress/src/main/res/values-ar/strings.xml b/WordPress/src/main/res/values-ar/strings.xml index 5ab0107ff5df..09c197e20cda 100644 --- a/WordPress/src/main/res/values-ar/strings.xml +++ b/WordPress/src/main/res/values-ar/strings.xml @@ -1,78 +1,100 @@ + اسم الملف + إعدادات مكوّن ملف + فشل رفع الملفات.\nيرجى النقر على الخيارات. + فشل حفظ الملفات.\nيرجى النقر على الخيارات. + تحرير الملف + نسخ رابط الملف + اختيار ملف + اختيار نطاق + جديد + إعدادات Jetpack + Jetpack + متابعة المحادثة + تابع المحادثة + لا يمكن إلغاء الاشتراك في التعليقات لهذه المقالة + لا يمكن الاشتراك في التعليقات لهذه المقالة + خطأ في جلب حالة الاشتراك للمقالة + تم إلغاء الاشتراك من التعليقات بنجاح + لقد اشتركت بالتعليقات بنجاح + تم تلقي ردّ غير صالح + لم يتم تلقي أي ردّ + مسح + تطبيق لم تتم إضافة شريحة واحدة أو أكثر إلى قصتك لأن القصص لا تدعم ملفات GIF في الوقت الحالي. الرجاء اختيار صورة ثابتة أو خلفية فيديو بدلاً من ذلك. + ملفات GIF غير مدعومة + لم نتمكن من العثور على ملفات وسائط لهذه القصة على الموقع. لا يمكن تحرير القصة + تعذر تحميل الوسائط لهذه القصة. تحقق من اتصالك بالإنترنت وحاول مرة أخرى بعد لحظات. لا يمكن تحرير القصة - ملفات GIF غير مدعومة تم تحرير هذه القصة على جهاز مختلف وقد تكون القدرة محدودة على تحرير كائنات معينة. - تعذر تحميل الوسائط لهذه القصة. تحقق من اتصالك بالإنترنت وحاول مرة أخرى بعد لحظات. - لم نتمكن من العثور على ملفات وسائط لهذه القصة على الموقع. - تمت إزالة الوسائط. حاول تحرير قصتك. تحرير قصة محدودة - التخطيطات غير متوفرة دون اتصال انترنت - يرجى التحقق من اتصالك بالإنترنت وإعادة المحاولة. - حذف - التالي - تمّ - تجاهل التغييرات؟ - لن يتم حفظ أي تغييرات تم إجراؤها. - تجاهل - النص + تمت إزالة الوسائط. حاول تحرير قصتك. الخلفية - اضغط على إعادة المحاولة عند معاودة الاتصال بالإنترنت. + النص + تجاهل + لن يتم حفظ أي تغييرات تم إجراؤها. + تجاهل التغييرات؟ + تمّ + التالي + حذف حدث خطأ أثناء تحديد التصميم. - فحص - مرحبًا! - لا توجد مقالات حديثة - العثور على بريدك الإلكتروني المتصل + يرجى التحقق من اتصالك بالإنترنت وإعادة المحاولة. + اضغط على إعادة المحاولة عند معاودة الاتصال بالإنترنت. + التخطيطات غير متوفرة دون اتصال انترنت الاستمرار في تخزين بيانات الاعتماد - حاول متابعة المزيد من المواضيع لتوسيع البحث + العثور على بريدك الإلكتروني المتصل متابعة المواضيع - أُعجب <b>Madison Ruiz</b> بمقالتك - لقد تلقيت <b>50 إعجاب</b> على موقعك اليوم + حاول متابعة المزيد من المواضيع لتوسيع البحث + لا توجد مقالات حديثة + مرحبًا! + فحص قام <b>Johan Brandt</b> بالردّ على مقالتك - تخطي - اختيار - اختر تخطيط الصفحة الرئيسية المفضَّل لديك. يمكنك تخصيصه أو تغييره لاحقًا. + لقد تلقيت <b>50 إعجاب</b> على موقعك اليوم + أُعجب <b>Madison Ruiz</b> بمقالتك تم فتح قائمة المكوّن القابلة للتمرير. حدد مكوّنًا. تم قفل قائمة المكوّن القابلة للتمرير. + تخطي + اختيار + اختر تخطيط الصفحة الرئيسية المفضَّل لديك. يمكنك تعديله أو تخصيصه لاحقًا. اختيار تصميم - أضف تصنيفاً جديداً - التصنيفات - لم يتم التعيين - التصنيفات - إضافة تصنيف - التخطيطات غير متوفرة بسبب خطأ - التخطيطات غير متوفرة دون اتصال انترنت انقر على إعادة المحاولة عند الاتصال بالإنترنت مرة أخرى أو إنشاء صفحة فارغة باستخدام الزر أدناه. + التخطيطات غير متوفرة دون اتصال انترنت انقر على إعادة المحاولة أو إنشاء صفحة فارغة باستخدام الزر أدناه. - أخبار الويب - باميلا نجوين - الطهي - الفن - زراعة الحدائق - الموسيقى - السياسة - أفضل عشرة مقاهي - أفضل المعجبين بالعالم + التخطيطات غير متوفرة بسبب خطأ + إضافة تصنيف + أضف تصنيفاً جديداً + التصنيفات + لم يتم التعيين + التصنيفات المتاحف في لندن + أفضل المعجبين بالعالم + أفضل عشرة مقاهي + السياسة + الموسيقى + زراعة الحدائق كرة القدم + الطهي + الفن موسيقى Rock n\' Roll الأسبوعية + أخبار الويب + باميلا نجوين لقد ألهمتني أعمال المصور كاميرون كارستن. سأجرِّب هذه التقنيات في المحاولة التالية الحصول على الإلهام - مرحبًا بك في أداة إنشاء مواقع الويب الأكثر رواجًا في العالم. - باستخدام المحرر الضخم والقوي، يمكنك النشر أثناء التنقّل. - شاهد التعليقات والإشعارات في الوقت الفعلي. تابع مواقعك المفضَّلة واكتشف مواضيع جديدة. شاهد جمهورك يتزايد من خلال التحليلات المتعمقة. - مواقع لمتابعتها + شاهد التعليقات والإشعارات في الوقت الفعلي. + باستخدام المحرر الضخم والقوي، يمكنك النشر أثناء التنقّل. + مرحبًا بك في أداة إنشاء مواقع الويب الأكثر رواجًا في العالم. فشل تحميل الوسائط + مواقع لمتابعتها نعمل بجد لإضافة المزيد من المكوِّنات مع كل إصدار. لم يتم دعم \"%s\" بالكامل زر المساعدة @@ -80,8 +102,8 @@ Language: ar اختيار الصور إنشاء مقالة قصة تُنشر المقالة كمقالة جديدة على موقعك حتى لا يفوِّت جمهورك أي شيء. - اجمع بين الصور ومقاطع الفيديو والنصوص لإنشاء مقالات قصة جذابة وقابلة للنقر سيحبها زائروك. مقالات القصة لا تختفي + اجمع بين الصور ومقاطع الفيديو والنصوص لإنشاء مقالات قصة جذابة وقابلة للنقر سيحبها زائروك. تتوافر القصص الآن للجميع مثال لعنوان قصة كيفية إنشاء مقالة قصة @@ -96,35 +118,35 @@ Language: ar الاختيار من مكتبة وسائط ووردبريس رجوع البدء - بواسطة متابعة المواضيع لاكتشاف مدونات جديدة - فتح الموقع الإلكتروني + بواسطة يتعر وسم هذا المرجع بأنه بريد مزعج عدم الوسم بأنه بريد مزعج وضع علامة مزعج + فتح الموقع الإلكتروني رفع وسائط بتنسيق gif رفع وسائط المخزون رفع الوسائط - ابحث أو اكتب رابطاً تحديد عنصر + ابحث أو اكتب رابطاً أضف رابط الهاتف هذا إضافة هذا الرابط إضافة رابط البريد الإلكتروني هذا \"لا يوجد اتصال بالإنترنت.\nالاقتراحات غير متوفرة.\" - %s محدد - %s - تقليدي - قوي - مرح - عصري عريض + عصري + مرح + قوي + تقليدي عادي تحتاج إلى منح التطبيق إذن تسجيل الصوت من أجل تسجيل الفيديو - استعراض العناصر - تعذر إظهار هذا التعليق - الميكروفون + %s + %s محدد الحصول على رابط تسجيل الدخول عن طريق البريد الإلكتروني حسناً، لا يمكننا العثور على حساب WordPress.com متصلاً بعنوان البريد الإلكتروني هذا. + الميكروفون + تعذر إظهار هذا التعليق + استعراض العناصر الإبلاغ عن هذه المقالة مرحبًا بك في القارئ. اكتشف ملايين المدونات في متناول يديك. حدث خطأ داخلي في الخادم @@ -132,116 +154,116 @@ Language: ar ⁦%1$s⁩ المزيد من العناصر اختيار تخطيط ملحوظة: قد يختلف تخطيط العمود بين القوالب وأحجام الشاشة - إخفاء - قد ترغب في إنشاء مقالة أو قصة إنشاء صفحة إنشاء مقالة \@string/contact_support - عرض مساحة التخزين - حدث خطأ أثناء حفظ الصورة - عنوان الصفحة. فارغ - عنوان الصفحة. %s - تعذّر حفظ الفيديو - العملية قيد التقدّم، حاول مرة أخرى + قد ترغب في + إخفاء تسمية الفيديو. فارغ يقوم بتحديث العنوان. لصق المكوِّن بعد + عنوان الصفحة. %s + عنوان الصفحة. فارغ حدث خطأ في أثناء تشغيل مقطع الفيديو الخاص بك لا يدعم هذا الجهاز واجهة برمجة تطبيقات Camera2. + تعذّر حفظ الفيديو + حدث خطأ أثناء حفظ الصورة + العملية قيد التقدّم، حاول مرة أخرى يتعذر العثور على شريحة القصة - إدارة - تعذّر حفظ شريحة واحدة - تعذّر حفظ %1$d شريحة + عرض مساحة التخزين يتعين علينا حفظ القصة على جهازك قبل التمكن من نشرها. راجع إعدادات التخزين الخاصة بك، وأزل الملفات لتوفير مساحة. مساحة التخزين على الجهاز غير كافية حاول حفظ الشرائح مجددًا أو احذفها، ثم حاول نشر قصتك مرة أخرى. + تعذّر حفظ %1$d شريحة + تعذّر حفظ شريحة واحدة + إدارة ⁦%1$d⁩ الشرائح التي تتطلب إجراءً شريحة واحدة تتطلب إجراءً - جاري الرفع \"%1$s\"… - تم نشر \"%1$s\" - تعذر الرفع \"%1$s\" تعذر الرفع \"%1$s\" - جاري حفظ \"%1$s\"… - عدّة قصص - شريحة واحدة متبقية + تعذر الرفع \"%1$s\" + تم نشر \"%1$s\" + جاري الرفع \"%1$s\"… %1$d شريحة متبقية - غير محدد - مُحدَّد - خطأ - تغيير محاذاة النص - تغيير لون النص - حذف شريحة القصة؟ - تجاهل + شريحة واحدة متبقية + عدّة قصص + جاري حفظ \"%1$s\"… بدون عنوان - حذف - تجاهل نشر القصة؟ + تجاهل لن يتم حفظ مقالة قصتك كمسودة. - ستتم إزالة هذه الشريحة من قصتك. + تجاهل نشر القصة؟ + حذف لم يتم حفظ هذه الشريحة حتى الآن. إذا حذفتَ هذه الشريحة، فستفقد أي عمليات تحرير أجريتها. - إنشاء صفحة فارغة - إنشاء صفحة - معاينة - إلتقاط - الملصقات - صوت - نصّ - تم الحفظ - جاري الحفظ - إغلاق - تم الحفظ + ستتم إزالة هذه الشريحة من قصتك. + حذف شريحة القصة؟ + تغيير لون النص + تغيير محاذاة النص + خطأ + مُحدَّد + غير محدد + شريحة إعادة المحاولة + تم الحفظ + إغلاق المشاركة لـ - إعادة المحاولة - تم الحفظ في الصور مشاركة - شريحة - قلب الكاميرا - فلاش - قلب + تم الحفظ في الصور + إعادة المحاولة + تم الحفظ + جاري الحفظ فلاش - امنح قصتك عنواناً + قلب + صوت + نصّ + الملصقات + فلاش + قلب الكاميرا + إلتقاط + معاينة + إنشاء صفحة + إنشاء صفحة فارغة ابدأ بالاختيار من بين مجموعة متنوعة من تخطيطات الصفحات المعدَّة سابقًا. أو ما عليك سوى البدء بصفحة فارغة. - اضغط على إنشاء ⁦%1$s⁩. ⁦%2$s⁩ بعدها، حدِّد <b>مقالة</b> - إنشاء مقالة، صفحة أو قصة - إنشاء مقالة أو قصة اختيار تخطيط - مقالة قصة + امنح قصتك عنواناً + إنشاء مقالة أو قصة + إنشاء مقالة، صفحة أو قصة + اضغط على إنشاء ⁦%1$s⁩. ⁦%2$s⁩ بعدها، حدِّد <b>مقالة</b> الاختيار من الجهاز + مقالة قصة يتطلب تحرير أيقونات الموقع على مواقع ووردبريس المستضافة ذاتيًا إضافة Jetpack. يتعذر العثور على الانتقال السريع بين الصفحات ذات الصلة يتعذر رفع ملف.\nتم تجاوز المساحة المتوافرة للتخزين. تم تجاوز المساحة المتوافرة للتخزين إضافة ملف - استبدال صورة أو فيديو استبدال الفيديو - المتابعة باستخدام WordPress.com - تم إزالة المكوّن - اختيار صورة - اختيار صورة أو فيديو + استبدال صورة أو فيديو اختيار فيديو - إذا تابعت مع Google وليس لديك حساب WordPress.com بالفعل، فأنت تقوم بإنشاء حساب وتوافق على %1$sشروط الخدمة%2$s. - تأكيد التسجيل + اختيار صورة أو فيديو + اختيار صورة + تم إزالة المكوّن أدخل رابط موقعك الحالي + المتابعة باستخدام WordPress.com + تأكيد التسجيل + إذا تابعت مع Google وليس لديك حساب WordPress.com بالفعل، فأنت تقوم بإنشاء حساب وتوافق على %1$sشروط الخدمة%2$s. بالمتابعة، أنت توافق على %1$sشروط الخدمة%2$s. سنرسل لك عبر البريد الإلكتروني رابطًا لإنشاء حسابك الجديد على WordPress.com. سنستخدم عنوان البريد الإلكتروني هذا لإنشاء حسابك الجديد على WordPress.com. أرسلنا لك عبر البريد الإلكتروني رسالة تتضمن رابط التسجيل لإنشاء حسابك الجديد على WordPress.com. تحقَّق من بريدك الإلكتروني على هذا الجهاز، وانقر على الرابط الموجود في الرسالة التي تم تلقيها عبر البريد الإلكتروني من WordPress.com. أدخل معلومات حسابك لـ %1$s. - تحقق من بريدك الإلكتروني على هذا الجهاز، واضغط على الرابط في رسالة البريد الإلكتروني التي ستستلمها من WordPress.com. - تمّ - العثور على عنوان موقعك - المتابعة باستخدام Google أو + المتابعة باستخدام Google + العثور على عنوان موقعك + تمّ لم تشاهد البريد الإلكتروني؟ تحقّق من مجلد البريد المزعج أو البريد العشوائي. + تحقق من بريدك الإلكتروني على هذا الجهاز، واضغط على الرابط في رسالة البريد الإلكتروني التي ستستلمها من WordPress.com. سنرسل لك عبر البريد الإلكتروني رابطًا يسجّل دخولك على الفور، دون الحاجة إلى كلمة مرور. - إعادة تعيين كلمة المرور الخاصة بك - إرسال الرابط عبر البريد الإلكتروني - إنشاء حساب - أو اكتب كلمة المرور الخاصة بك - أدخل عنوان بريدك الإلكتروني لتسجيل الدخول أو إنشاء حساب WordPress.com. - البدء التحقق من البريد الإلكتروني + البدء + أدخل عنوان بريدك الإلكتروني لتسجيل الدخول أو إنشاء حساب WordPress.com. + أو اكتب كلمة المرور الخاصة بك + إنشاء حساب + إرسال الرابط عبر البريد الإلكتروني + إعادة تعيين كلمة المرور الخاصة بك حدثت مشكلة أثناء معالجة الطلب. يرجى المحاولة مرة أخرى لاحقاً. حدِّد اسمًا لموقعك يعكس هويته وموضوعه. الاعتماد على الانطباعات الأولى! تعيين عنوان موقعك @@ -268,61 +290,60 @@ Language: ar الضغط ضغطًا مزدوجًا لتحديد الخيار تخصيص التدرج %1$s · %2$s · %3$s - الجميع + كاتب الصفحة استخدام تنسيق GIF هذا تعذر تحميل الصورة المصغَّرة للوسائط - هيكل المحتوى + بنية المحتوى + الجميع أنا - كاتب الصفحة تجاهل لم يتم التعيين + تساعد الوسوم على إخبار القراء بما تدور حوله المقالة. + تاريخ النشر + إضافة وسوم رجوع + حفظ الآن + إرسال الآن جدولة الآن نشر إلى + وسوم تاريخ النشر إلغاء نقل إلى المسودة - تساعد الوسوم على إخبار القراء بما تدور حوله المقالة. - إضافة وسوم - حفظ الآن - إرسال الآن - وسوم يتعذر تحرير المقالات التي تمت إضافتها إلى سلة المهملات. هل ترغب في تغيير حالة هذه المقالة إلى \"مسودة\" حتى تتمكن من العمل عليها؟ - تاريخ النشر - تاريخ النشر هل تريد نقل المقالة إلى المسودات؟ - اختيار اهتماماتك - اختيار اهتماماتك + اختر اهتماماتك + اختر اهتماماتك انتهى تحديد القليل للاستمرار منشور أُضيف إلى سلة المهملات + مجدولة + تاريخ النشر قراءة إشعار الخصوصية لقانون خصوصية المستهلك في كاليفورنيا يتطلب قانون خصوصية المستهلك في كاليفورنيا (\"CCPA\") منا تزويد سكان كاليفورنيا ببعض المعلومات الإضافية حول تصنيفات المعلومات الشخصية التي نقوم بتجميعها ومشاركتها، مع تحديد المصدر الذي نحصل على تلك المعلومات الشخصية منه، وكيف نستخدمها ولماذا. - مجدولة - الحالة والظهور إشعار الخصوصية الخاص بالمستخدمين في كاليفورنيا + الحالة والظهور قم بالتحديث الآن %1$s · %2$s - فتح قائمة إجراءات المكوِّن تجربة تخطيط بدء العمل - إدراج إشارة + فتح قائمة إجراءات المكوِّن النقر المزدوج لفتح الورقة السفلية التي تحتوي على خيارات متوافرة النقر المزدوج لفتح ورقة الإجراءات التي تحتوي على خيارات متوافرة - الصفحة الرئيسية الثابتة - صفحة المقالات يتعذر علينا فتح الصفحات في الوقت الحالي. يرجى المحاولة مجددًا في وقت لاحق تعيين كصفحة مقالات تعيين كصفحة رئيسية \"لا يتوافر أي مستخدمين متطابقين\". \"إنَّ %s مستخدم غير صالح\" تحديد صفحة + صفحة المقالات + الصفحة الرئيسية الثابتة المدونة التقليدية يتعذر أن تتشابه الصفحة الرئيسية المحدَّدة مع صفحة المقالات. - موافقة فشل تحديث إعدادات الصفحة الرئيسية، تحقَّق من اتصالك بالإنترنت يتعذر حفظ إعدادات الصفحة الرئيسية قبل تحميل الصفحات يتعذر حفظ إعدادات الصفحة الرئيسية + موافقة فشل تحميل الصفحات اختر من صفحة رئيسية تعرض أحدث مقالاتك (مدونة تقليدية) أو صفحة ثابتة/ساكنة. إعدادات الصفحة الرئيسية @@ -339,6 +360,7 @@ Language: ar عندما تتابع المواقع، سترى محتواها هنا اكتشاف المزيد ما الجديد في ووردبريس + إدراج %d قص فشل التحميل إلى الملف، يرجى المحاولة مرة أخرى. معاينة الصورة المصغَّرة @@ -347,10 +369,11 @@ Language: ar اختيار الوسائط اختيار مقطع فيديو تعذر تحديد الموقع. يُرجى المحاولة مرة أخرى. - إدراج %d المتابعة فشلت إعادة التدوين إدارة المواقع + بمجرد إنشاء موقع WordPress.com، يمكنك إعادة تدوين المحتوى الذي أعجبك على موقعك الخاص. + لا تتوافر مواقع WordPress.com الجديد تم نسخ عنوان الرابط نسخ عنوان الرابط @@ -359,14 +382,12 @@ Language: ar إدراج المتابعة نسخ - لا تتوافر مواقع WordPress.com - بمجرد إنشاء موقع WordPress.com، يمكنك إعادة تدوين المحتوى الذي أعجبك على موقعك الخاص. + نقل المكوِّن إلى اليمين من الموضع %1$s إلى الموضع %2$s نقل المكوِّن إلى اليمين + نقل المكوِّن إلى اليسار من الموضع %1$s إلى الموضع %2$s نقل المكوِّن إلى اليسار الضغط المزدوج لنقل المكوِّن إلى اليمين الضغط المزدوج لنقل المكوِّن إلى اليسار - نقل المكوِّن إلى اليمين من الموضع %1$s إلى الموضع %2$s - نقل المكوِّن إلى اليسار من الموضع %1$s إلى الموضع %2$s المدوّنة إنشاء لوحة التحكم إعداد القالب @@ -389,127 +410,127 @@ Language: ar فشل الوصول إلى محتوى الموقع الخاص. قد تصبح بعض الوسائط غير متاحة الوصول إلى محتوى الموقع الخاص فشل اقتصاص الصورة وحفظها، يرجى المحاولة مرة أخرى. - تنسيق الصفحة غير معروف + فشل تحميل الصورة.\nيرجى النقر لإعادة المحاولة. صورة المعاينة - لم نتمكن من إكمال هذا الإجراء، ولم ننشر هذه الصفحة الخاصة. - لم نتمكن من إكمال هذا الإجراء، ولم نقم بجدولة هذه الصفحة. + تنسيق الصفحة غير معروف لم نتمكن من إكمال هذا الإجراء، ولم نرسل هذه الصفحة للمراجعة. - فشل تحميل الصورة.\nيرجى النقر لإعادة المحاولة. - لم نتمكن من رفع هذه الوسائط، ولم نرسل هذه الصفحة للمراجعة. - لم نتمكن من نشر هذه الصفحة، ولكننا سنحاول مرة أخرى لاحقًا. - لم نتمكن من نشر هذه الصفحة الخاصة، ولكننا سنحاول مرة أخرى لاحقًا. - لم نتمكن من جدولة هذه الصفحة، ولكننا سنحاول مرة أخرى لاحقًا. - لم نتمكن من إرسال هذه الصفحة للمراجعة، ولكننا سنحاول مرة أخرى لاحقًا. + لم نتمكن من إكمال هذا الإجراء، ولم نقم بجدولة هذه الصفحة. + لم نتمكن من إكمال هذا الإجراء، ولم ننشر هذه الصفحة الخاصة. لم نتمكن من إكمال هذا الإجراء، ولم ننشر هذه الصفحة. - سننشر صفحتك الخاصة عندما يعود الجهاز متصلاً بالإنترنت. - سنحفظ مسودتك عندما يعود الجهاز متصلاً بالإنترنت - لم نتمكن من رفع هذه الوسائط، ولم ننشر هذه الصفحة. - لم نتمكن من رفع هذه الوسائط، ولم ننشر هذه الصفحة الخاصة. + لم نتمكن من إرسال هذه الصفحة للمراجعة، ولكننا سنحاول مرة أخرى لاحقًا. + لم نتمكن من جدولة هذه الصفحة، ولكننا سنحاول مرة أخرى لاحقًا. + لم نتمكن من نشر هذه الصفحة الخاصة، ولكننا سنحاول مرة أخرى لاحقًا. + لم نتمكن من نشر هذه الصفحة، ولكننا سنحاول مرة أخرى لاحقًا. + لم نتمكن من رفع هذه الوسائط، ولم نرسل هذه الصفحة للمراجعة. لم نتمكن من رفع هذه الوسائط، ولم نقم بجدولة هذه الصفحة. + لم نتمكن من رفع هذه الوسائط، ولم ننشر هذه الصفحة الخاصة. + لم نتمكن من رفع هذه الوسائط، ولم ننشر هذه الصفحة. + سنحفظ مسودتك عندما يعود الجهاز متصلاً بالإنترنت + سننشر صفحتك الخاصة عندما يعود الجهاز متصلاً بالإنترنت. + سنقوم بجدولة صفحتك عندما يعود الجهاز متصلاً بالإنترنت. + سنرسل صفحتك من أجل المعاينة عندما يعود الجهاز متصلاً بالإنترنت. + سننشر صفحتك عندما يعود الجهاز متصلاً بالإنترنت. صفحة في قائمة الانتظار رفع الصفحة - سننشر صفحتك عندما يعود الجهاز متصلاً بالإنترنت. الجهاز غير متصل بالإنترنت. تمّ حفظ الصفحة محليًا. لقد أجريت تغييرات غير محفوظة على هذه الصفحة - سنرسل صفحتك من أجل المعاينة عندما يعود الجهاز متصلاً بالإنترنت. - سنقوم بجدولة صفحتك عندما يعود الجهاز متصلاً بالإنترنت. - المظهر - فاتح - داكن - تم حفظ الصفحة عبر الإنترنت - تم حفظ الصفحة على الجهاز جاري رفع صفحتك تحتوي الصفحة على عمليات رفع غير مكتملة للوسائط وتم حفظها محليًا + تم حفظ الصفحة على الجهاز + تم حفظ الصفحة عبر الإنترنت اختر مدونة لاختصار QuickPress تعيين بواسطة موفّر البطارية + داكن + فاتح + المظهر لقد أجريت مؤخرًا تغييرات على هذه الصفحة ولكن لم نحفظها. اختيار إصدار لتحميله:\n ماذا يقول الناس نوفِّر مجموعة من الخدمات لمساعدتك على تحقيق النتائج التي تسعى إليها. ألستَ متأكِّدًا مما تحتاج إليه؟، أو كم تبلغ تكلفته؟ يمكننا توضيح الخدمات المناسبة لك، وإبلاغك بالمزيد عن الرسوم التي نطلبها. ابق على اتصال من خلال المعلومات الواردة ادناه. نحن فريق صغير من الاحترافيين الموهوبين الذين يتمتعون بمجموعة كبيرة من المهارات والخبرات. نحب ما نفعله ونقوم به بشغف. نتطلع إلى العمل معك. - سيرغب الزائرون في معرفة الموجودين على الجانب الآخر من الصفحة. استخدم هذه المساحة للكتابة عن نفسك أو موقعك أو شركتك أو أي شيء تريده. استعن بالتوصيات الواردة أدناه للاقتباس من الآخرين الذين يتحدثون حول الأمر نفسه بأسلوبهم الخاص. - والت ديزني - ترغب بالعمل معنا؟ رسالة التحذير - المنصب أو المسمى الوظيفي - اسم المشروع - سالي سميث - القطّ فروزن - الخدمات - إظهار محتوى المقالة - الإستراتيجية - رسالة النجاح - الفريق - طريقة البدء هي التوقف عن الحديث والبدء في القيام به. - هذا هو محتوى النموذج المُضمَّن مع القالب لتوضيح ميزاته. يمكنك إزالته أو استبدال كلماتك ووسائطك الخاصة به. + ترغب بالعمل معنا؟ + والت ديزني + سيرغب الزائرون في معرفة الموجودين على الجانب الآخر من الصفحة. استخدم هذه المساحة للكتابة عن نفسك أو موقعك أو شركتك أو أي شيء تريده. استعن بالتوصيات الواردة أدناه للاقتباس من الآخرين الذين يتحدثون حول الأمر نفسه بأسلوبهم الخاص. USA - رابط لـ - يعرض معرض أعمالي المشاريع المختلفة التي تم إنشاؤها طوال مسيرتي المهنية. شاهد معلومات الاتصال الخاصة بي أدناه لنبق على تواصل. - إظهار المقتطف فقط + هذا هو محتوى النموذج المُضمَّن مع القالب لتوضيح ميزاته. يمكنك إزالته أو استبدال كلماتك ووسائطك الخاصة به. + طريقة البدء هي التوقف عن الحديث والبدء في القيام به. + الفريق + رسالة النجاح + الإستراتيجية + إظهار محتوى المقالة + الخدمات + القطّ فروزن + سالي سميث + اسم المشروع + المنصب أو المسمى الوظيفي معرض أعمال + إظهار المقتطف فقط + يعرض معرض أعمالي المشاريع المختلفة التي تم إنشاؤها طوال مسيرتي المهنية. شاهد معلومات الاتصال الخاصة بي أدناه لنبق على تواصل. + رابط لـ فلنتحدث 👋 لا تتردد في التواصل باستخدام معلومات الاتصال أدناه، أو إرسال رسالة باستخدام النموذج. دعونا نبني شيئًا معًا! دعونا نبني شيئًا معًا! خوان بيريز - Dr. Seuss - راسلني عبر البريد: <a href=\"mailto:mail@example.com\">mail@example.com</a> - طول المقتطف (كلمات) - ابق على اتصال - الإلهام - هاري، إن اختياراتنا هي التي تظهر ما نحن عليه بالفعل، أكثر بكثير من قدراتنا. ج.ك. رولينج + هاري، إن اختياراتنا هي التي تظهر ما نحن عليه بالفعل، أكثر بكثير من قدراتنا. + الإلهام + ابق على اتصال + طول المقتطف (كلمات) + راسلني عبر البريد: <a href=\"mailto:mail@example.com\">mail@example.com</a> + Dr. Seuss لا تبكي لأنه انتهى، ابتسم لأنه حدث. - المدينة، 10100 تخصيص - وصف المشروع والأعمال المقدَّمة. - <a href=\"mailto:mail@example.com\">mail@example.com</a> - سيرة ذاتية قصيرة مع التاريخ الشخصي والإنجازات الرئيسية، أو حقيقة مثيرة للاهتمام. - وصف موجز للخدمات التي تقدمها. + المدينة، 10100 إضافة مكوّن فقرة + وصف موجز للخدمات التي تقدمها. + سيرة ذاتية قصيرة مع التاريخ الشخصي والإنجازات الرئيسية، أو حقيقة مثيرة للاهتمام. + <a href=\"mailto:mail@example.com\">mail@example.com</a> + وصف المشروع والأعمال المقدَّمة. +96692000000 شارع 10 العام - رابط الموقع - غير متصل - يتعذر الاتصال بـ Facebook العثور على أي صفحات. لا يمكن لآلية النشر الاتصال بملفات تعريف Facebook الشخصية، فقط للصفحات المنشورة. - منشور - مجدول - محذوف إنشاء مقالة - سلة المهملات - عدم الوضع بسلة المهملات - غير مقروء - تعليقات - متابعات + محذوف + مجدول + منشور + يتعذر الاتصال بـ Facebook العثور على أي صفحات. لا يمكن لآلية النشر الاتصال بملفات تعريف Facebook الشخصية، فقط للصفحات المنشورة. + غير متصل الإعجابات + متابعات + تعليقات + غير مقروء + عدم الوضع بسلة المهملات + سلة المهملات النشاط المقالات والصفحات عام إضافة بطاقة جديدة إضافة بطاقة إحصاءات جديدة - تسجيل الدخول إلى WordPress.com - إزالة الفلتر الحالي - تحديد موقع أو وسم لفلترة المقالات - مُحدَّد - تحديد وسم أو موقع، نافذة منبثقة استخدام زر الفلترة للعثور على مقالات في مواضيع معينة + تحديد وسم أو موقع، نافذة منبثقة + مُحدَّد + تحديد موقع أو وسم لفلترة المقالات + إزالة الفلتر الحالي إدارة المواضيع والمواقع - تسجيل الدخول إلى WordPress.com للاطلاع على أحدث المقالات من المواقع التي تتابعها + تسجيل الدخول إلى WordPress.com تسجيل الدخول إلى WordPress.com للاطلاع على أحدث المقالات من المواضيع التي تتابعها + تسجيل الدخول إلى WordPress.com للاطلاع على أحدث المقالات من المواقع التي تتابعها معاينة القالب استبدال المكوِّن الحالي إضافة إلى النهاية إضافة إلى البداية إضافة مكوّن قبل إضافة مكوّن بعد - متابعة موقع - الاطِّلاع على أحدث المقالات من المواقع التي تتابعها إضافة موضوع + متابعة موقع يمكنك متابعة مقالات حول موضوع معيَّن عن طريق إضافة موضوع + الاطِّلاع على أحدث المقالات من المواقع التي تتابعها المتابعة عامل التصفية تسمية الفيديو. %s تحرير الفيديو انقر نقرًا مزدوجًا لتحديد المخطط إضافة كود قصير… + كاتب المقالة إنشاء مقالة لقد استمعت إلى جميع الإحصاءت لهذه الفترة.\n بالنقر مرة أخرى سيجرى إعادة التشغيل من البداية. لا توجد إحصاءات في هذه الفترة. @@ -521,7 +542,6 @@ Language: ar متوسط منخفض   & %1$d %2$s - كاتب المقالة %1$s، %2$d %3$s تحريك الصورة إلى الأمام تحريك الصورة إلى الخلف @@ -551,39 +571,39 @@ Language: ar تعذر علينا الوصول إلى موقعك لأنه يتطلب <b>مصادقة HTTP</b>. سيتعين عليك الوصول إلى مضيفك لحل هذا الأمر. تعذر علينا الوصول إلى <b>ملف XMLRPC</b> على موقعك. سيتعين عليك الوصول إلى مضيفك لحل هذا الأمر. تقريبًا هناك! يتعين علينا فقط التحقق من صحة عنوان بريدك الإلكتروني المتصل بـ Jetpack <b>%1$s</b> + تسجيل الدخول باستخدام بيانات اعتماد الموقع. تسجيل الدخول باستخدام بيانات اعتماد الموقع %1$s الخاصة بك - المتابعة صفحة الموقع - تسجيل الدخول باستخدام بيانات اعتماد الموقع. - يتعذر علينا فتح هذه المقالات الآن. يرجى المحاولة مجددًا في وقت لاحق - %sk - %sB - %sM + المتابعة + الإعجابات + اكتشاف + تم الحفظ + المواضيع + المواقع + %sQi %sQa %sT - %sQi - المواقع - تم الحفظ - اكتشاف - الإعجابات + %sB + %sM + %sk + يتعذر علينا فتح هذه المقالات الآن. يرجى المحاولة مجددًا في وقت لاحق يتعذر علينا تحميل بيانات موقعك الآن. يرجى المحاولة مجددًا في وقت لاحق - المواضيع مكتبة وسائط ووردبريس - بدء الكتابة… + فكّ التجميع + الترجمة + العنوان: + أنقر لإخفاء لوحة المفاتيح + أنقر هنا لإظهار المساعدة تسجيل مقطع فيديو التقاط صورة أو تسجيل فيديو التقاط صورة - العنوان: - الترجمة - فكّ التجميع - أنقر هنا لإظهار المساعدة - أنقر لإخفاء لوحة المفاتيح + بدء الكتابة… إضافة عنوان الشريط الجانبي إظهار القسم - إعادة تعيين المكوِّن - مكوِّن %s. فارغ مكوِّن %s. يحتوي هذا المكوِّن على محتوى غير صالح + مكوِّن %s. فارغ قص المكوِّن + إعادة تعيين المكوِّن إزالة التعليقات التوضيحية ثمَّة مشكلة أثناء فتح مقطع الفيديو ثمَّة مشكلة أثناء عرض المكوِّن @@ -596,17 +616,17 @@ Language: ar الانتقال إلى الأعلى لوحة النشر المُسبق الخاصة بي معلومات حالة المقالة الخاصة بي - تحريك المكوّن لأعلى لوحة النشر اللاحق الخاصة بي لوحة تعيين مستنداتي نقل المكوِّن إلى أعلى من الصف %1$s إلى الصف %2$s + تحريك المكوّن لأعلى نقل المكوِّن إلى أسفل من الصف %1$s إلى الصف %2$s - أيقونة المساعدة - فشلت عملية إدراج وسائط.\nيرجى النقر على الخيارات. تحريك المكوّن لأسفل تسمية توضيحية للصورة. %s إخفاء لوحة المفاتيح فيما يأتي محتوى اللوحة! + أيقونة المساعدة + فشلت عملية إدراج وسائط.\nيرجى النقر على الخيارات. الضغط المزدوج للتراجع عن آخر تغيير الضغط المزدوج لتبديل الإعداد الضغط المزدوج لتحديد صورة @@ -618,25 +638,25 @@ Language: ar الضغط المزدوج لتحرير هذه القيمة الضغط المزدوج لتغيير القيمة باستخدام شريط التمرير الضغط المزدوج لإضافة مكوِّن - الاختيار من الجهاز - المحتوى… القيمة الحالية هي %s + المحتوى… + الاختيار من الجهاز الشريط الجانبي للتعليقات التوضيحية - إضافة صورة - إضافة صورة أو فيديو - إضافة رابط - إضافة فيديو + حدث خطأ غير معروف. يُرجى المحاولة مرة أخرى. النص البديل - إضافة وصف + إضافة فيديو + إضافة رابط + إضافة صورة أو فيديو + إضافة صورة إضافة مكوّن هنا - حدث خطأ غير معروف. يُرجى المحاولة مرة أخرى. إضافة تعليق توضيحي - \"تم تحميل القائمة بعناصر %1$d.\" + إضافة وصف أنقر فوق الزرّ \"حفظ المقالات\" لحفظ مقالةٍ في قائمتك. + \"تم تحميل القائمة بعناصر %1$d.\" + الإشعارات إيقاف التشغيل تشغيل يؤدي إيقاف تشغيل تنبيهات هذا الموقع إلى تعطيل التنبيهات المعروضة في علامة تبويب \"التنبيهات\" في هذا الموقع. يمكنك ضبط نوع التنبيه الذي تراه بعد تشغيل التنبيهات لهذا الموقع. - الإشعارات لرؤية التنبيهات في علامة تبويب \"التنبيهات\" في هذا الموقع، شغِّل التنبيهات لهذا الموقع. تمكين التنبيهات المعروضة في علامة تبويب \"التنبيهات\" في هذا الموقع تعطيل التنبيهات المعروضة في علامة تبويب \"التنبيهات\" في هذا الموقع @@ -658,23 +678,23 @@ Language: ar لم نتمكن من رفع هذه الوسائط، ولم ننشر هذه المقالة الخاصة. لم نتمكن من رفع هذه الوسائط، ولم ننشر هذه المقالة. لم نتمكن من رفع هذه الوسائط. - المعاينة غير متوفرة - تجهيز المعاينة… لم نتمكن من إكمال هذا الإجراء، ولكننا سنحاول مرة أخرى لاحقًا. لم نتمكن من إكمال هذا الإجراء. تعذرت معاينة مسودة فارغة تعذرت معاينة صفحة فارغة تعذرت معاينة مقالة فارغة + المعاينة غير متوفرة حدث خطأ في أثناء محاولة حفظ المقالة قبل المعاينة - لقد أجريت تغييرات غير محفوظة على هذه المقالة + تجهيز المعاينة… جاري الحفظ… + لقد أجريت تغييرات غير محفوظة على هذه المقالة الإصدار من هذا التطبيق الإصدار من جهاز آخر من هذا التطبيق\nتم الحفظ بتاريخ %s\n\nمن جهاز آخر\nتم الحفظ بتاريخ %s\n لقد أجريت مؤخرًا تغييرات على هذه المقالة ولكن لم نحفظها. اختيار إصدار لتحميله:\n\n ما الإصدار الذي ترغب في تحريره؟ - لن نحفظ أحدث التغييرات في مسودتك. حذف بشكل دائم + لن نحفظ أحدث التغييرات في مسودتك. لن نقم بجدولة هذه التغييرات. لن نرسل هذه التغييرات للمعاينة. لن ننشر هذه التغييرات. @@ -683,95 +703,95 @@ Language: ar سنقوم بجدولة مقالتك عندما يعود الجهاز متصلاً بالإنترنت. سنرسل مقالتك من أجل المعاينة عندما يعود الجهاز متصلاً بالإنترنت. سننشر مقالتك عندما يعود الجهاز متصلاً بالإنترنت. - جاري حفظ اسم المستخدم… - اسم المستخدم الخاص بك هو %1$s لا يمكن إلغاء هذا الإجراء. اسم المستخدم قد تم تحديثه بالفعل. + اسم المستخدم الخاص بك هو %1$s + جاري حفظ اسم المستخدم… تغيير اسم المستخدم - الأداء والسرعة - عرض وتغيير إعدادات أداء Jetpack الخاص بك + أنت تقوم بتغيير اسم المستخدم الخاص بك إلى %1$s%2$s%3$s. سيؤثر تغيير اسم المستخدم الخاص بك أيضًا على ملفك الشخصي على Gravatar وعلى عناوين الملفات الشخصية عبر النقاشات. تأكيد اسم المستخدم الجديد للمتابعة. كن حذرًا! أنت على وشك تغيير اسم المستخدم الخاص بك، والذي هو حاليًا %1$s%2$s%3$s. لن تتمكن من تغيير اسم المستخدم الخاص بك مرة أخرى. - أنت تقوم بتغيير اسم المستخدم الخاص بك إلى %1$s%2$s%3$s. سيؤثر تغيير اسم المستخدم الخاص بك أيضًا على ملفك الشخصي على Gravatar وعلى عناوين الملفات الشخصية عبر النقاشات. تأكيد اسم المستخدم الجديد للمتابعة. - معطّل + عرض وتغيير إعدادات أداء Jetpack الخاص بك + الأداء والسرعة المزيد - صور أسرع - ملفات ثابتة أسرع - الوسائط - البحث في Jetpack + استبدل البحث المدمج في ووردبريس بتجربة بحث محسّنة البحث المحسّن - تحميل الصفحات بشكل أسرع عن طريق السماح لـ Jetpack بتحسين الصور والملفات الثابتة (مثل CSS و JavaScript). + البحث في Jetpack استضافة الفيديو بدون إعلانات - استبدل البحث المدمج في ووردبريس بتجربة بحث محسّنة - الأداء + الوسائط + تحميل الصفحات بشكل أسرع عن طريق السماح لـ Jetpack بتحسين الصور والملفات الثابتة (مثل CSS و JavaScript). + ملفات ثابتة أسرع + صور أسرع + معطّل مفعل مُسرِّع الموقع حسِّن سرعة موقعك من خلال تحميل الصور المرئية فقط على الشاشة. + الأداء التنزيلات ملف تنزيلات الملفات - المنطقة الزمنية في الموقع (UTC) - المنطقة الزمنية في الموقع (UTC + %s) - المنطقة الزمنية في الموقع (UTC - %s) لم تُسجَّل إحصاءات تنزيل الملف قبل الثامن والعشرين من يونيو 2019. - إغلاق النافذة - افتراضي + المنطقة الزمنية في الموقع (UTC - %s) + المنطقة الزمنية في الموقع (UTC + %s) + المنطقة الزمنية في الموقع (UTC) سطح المكتب + افتراضي + إغلاق النافذة تحديد نوع المعاينة مشاركة العودة للخلف التقدم للأمام - سيتم نشر \"%s\" خلال 10 دقائق - مقالة ووردبريس مجدولة: \"%s\" تم جدولة \"%s\" للنشر على \"%s\" في تطبيق ووردبريس الخاص بك\n%s - مقالة مجدولة - مقالة مجدولة: تذكير ساعة واحدة - مقالة مجدولة: تذكير 10 دقائق - تم نشر \"%s\" + مقالة ووردبريس مجدولة: \"%s\" + سيتم نشر \"%s\" خلال 10 دقائق سيتم نشر \"%s\" خلال ساعة واحدة + تم نشر \"%s\" + مقالة مجدولة: تذكير 10 دقائق + مقالة مجدولة: تذكير ساعة واحدة + مقالة مجدولة لا يمكن إنشاء الإشعار عندما يكون تاريخ النشر في الماضي. عند النشر - إشعار - إضافة إلى تقويم - إيقاف - قبل ساعة قبل 10 دقائق + قبل ساعة + إيقاف + إضافة إلى تقويم + إشعار التاريخ والوقت - يرجى إدخال عنوان موقع ويب كامل، مثل example.com. - موقع الويب على هذا العنوان ليس موقع ووردبريس. بالنسبة لنا للاتصال به، يجب أن يكون الموقع مُنصّبًا ووردبريس. هل تريد مساعدة في العثور على البريد الإلكتروني الذي أنت متصلاً به؟ - المُحرر - طيّ - توسيع + موقع الويب على هذا العنوان ليس موقع ووردبريس. بالنسبة لنا للاتصال به، يجب أن يكون الموقع مُنصّبًا ووردبريس. + يرجى إدخال عنوان موقع ويب كامل، مثل example.com. تسجيل الدخول باستخدام WordPress.com للاتصال بـ %1$s - %1$s: %2$s, %3$s: %4$s - المقالة المشاهدات - تحميل بيانات البطاقة المُحدَّدة + المقالة + %1$s: %2$s, %3$s: %4$s تم طيّ العنصر تمّ توسيع العنصر - %1$s %2$s للفترة: %3$s، التغييرات من الفترة السابقة - %4$s + طيّ + توسيع تمّ تحديث الرسم البياني. - تحقق من عنوان بريدك الإلكتروني - تم إرسال الإرشادات إلى %s - تحقق من عنوان بريدك الإلكتروني - تم إرسال الإرشادات إلى بريدك الإلكتروني - طيّ + %1$s %2$s للفترة: %3$s، التغييرات من الفترة السابقة - %4$s + تحميل بيانات البطاقة المُحدَّدة + المُحرر توسيع - جاري رفع الوسائط.\nيرجى النقر على الخيارات. - إعادة محاولة الرفع - إدراج رابط - إزالة الرابط - http(s):// - موافق + طيّ + تحقق من عنوان بريدك الإلكتروني - تم إرسال الإرشادات إلى بريدك الإلكتروني + تحقق من عنوان بريدك الإلكتروني - تم إرسال الإرشادات إلى %s إلغاء + موافق + http(s):// + إزالة الرابط + إدراج رابط + إعادة محاولة الرفع + جاري رفع الوسائط.\nيرجى النقر على الخيارات. فتح الرابط في نافذة/علامة تبويب جديدة لعرض إحصائياتك، سجّل الدخول إلى حساب WordPress.com. لا تتطابق أي مقالة مع بحثك بحث في المقالات - هذا هو المكان الذي سيجده الأشخاص على الإنترنت. + هذا هو المكان الذي سيجدك فيه الأشخاص على الإنترنت. اختيار اسم نطاق متميز + تتضمن جميع خطط WordPress.com اسم نطاق مخصص. سجّل نطاقك المميز المجاني الآن. نبذة سريعة اليوم كل الوقت - تتضمن جميع خطط WordPress.com اسم نطاق مخصص. سجّل نطاقك المميز المجاني الآن. المشاهدات هذا الأسبوع الرجاء تسجيل الدخول إلى تطبيق ووردبريس لإضافة ودجت. لا توجد شبكة متاحة @@ -789,106 +809,106 @@ Language: ar أضف الودجت استغرق تحديث تفاصيل الإضافة وقتًا أطول من المعتاد. يرجى التحقق مرة أخرى لاحقًا. إذا قمت للتو بتسجيل اسم نطاق، فيرجى الانتظار حتى ننتهي من إعداده ومن ثم المحاولة مرة أخرى.\n\nإذا لم يكن الأمر كذلك، يبدو أنه حدث خطأ ما وقد لا تكون ميزة الإضافة متاحة لهذا الموقع. - يتعذر تحميل هذه الصفحة حاليًا. - تحقق من اتصال الشبكة وحاول مرة أخرى. الحالة (غير متوفرة) من خلال تسجيل هذا النطاق فإنك توافق على%1$sالشروط والأحكام%2$s + تحقق من اتصال الشبكة وحاول مرة أخرى. + يتعذر تحميل هذه الصفحة حاليًا. تعذّر جلب الإعدادات: بعض واجهات برمجة التطبيقات APIs غير متاحة لمُعرّف تطبيق OAuth هذا + دمج الحساب. من خلال إعداد Jetpack فإنك توافق على %1$sالشروط والأحكام%2$s - تحديث كلمة المرور - تمّ تحديث كلمة المرور لا يوجد اتصال. التحرير مُعطّل. لإعادة اتصال التطبيق بموقعك المستضاف ذاتيًا، أدخل كلمة المرور الجديد للموقع من هنا. + تمّ تحديث كلمة المرور + تحديث كلمة المرور جاري تسجيل اسم النطاق… تحديد الولاية تحديد الدولة - رمز الدولة - الدولة - العنوان - الهاتف - العنوان 2 - المدينة - الولاية - الرمز البريدي - تسجيل اسم نطاق - تهانينا متابعة يجري إعداد نطاقك الجديد <b>%s</b>. يقوم موقعك\n القيام بحركات بهلوانية من أجل الإثارة! - قمنا بتعبئة معلومات جهات الاتصال الخاصة بك مسبقًا على حسابك في WordPress.com من أجل راحتك.\n يرجى المراجعة للتأكد من صحة المعلومات التي ترغب في استخدامها لهذا النطاق. + تهانينا + تسجيل اسم نطاق + الرمز البريدي + الولاية + المدينة + العنوان 2 + العنوان + الدولة + رمز الدولة + الهاتف المؤسسة (اختياري) - يتعين على مالكي النطاق مشاركة معلومات الاتصال في قاعدة بيانات عامة لجميع النطاقات.\n مع ميزة حماية الخصوصية، ننشر معلوماتنا الخاصة بدلاً من معلوماتك، وإعادة توجيه أي اتصال إليك بشكل سري. - التسجيل بشكل خاص مع ميزة الحماية من الخصوصية - التسجيل بشكل علني + قمنا بتعبئة معلومات جهات الاتصال الخاصة بك مسبقًا على حسابك في WordPress.com من أجل راحتك.\n يرجى المراجعة للتأكد من صحة المعلومات التي ترغب في استخدامها لهذا النطاق. معلومات الاتصال الخاصة بالنطاق - الرجاء إدخال عنوان %s صالح + التسجيل بشكل علني + التسجيل بشكل خاص مع ميزة الحماية من الخصوصية + يتعين على مالكي النطاق مشاركة معلومات الاتصال في قاعدة بيانات عامة لجميع النطاقات.\n مع ميزة حماية الخصوصية، ننشر معلوماتنا الخاصة بدلاً من معلوماتك، وإعادة توجيه أي اتصال إليك بشكل سري. حماية الخصوصية - إدارة إحصائياتك - التجربة الآن - تجاهل - جديد + الرجاء إدخال عنوان %s صالح اختيار النطاق + جديد + تجاهل + التجربة الآن اختر الإحصائيات التي ستراها، والتركيز على البيانات التي تهمك أكثر. أنقر على %1$s في الجزء السفلي من الإحصائيات لتخصيص إحصائياتك. + إدارة إحصائياتك جاري جلب المراجعات… - جاري رفع مسودّتك فشلت عملية إدراج وسائط.\nيرجى النقر لإعادة المحاولة. + جاري رفع مسودّتك رفع المسودّة - حدث خطأ أثناء استعادة المقالة المسودات + حدث خطأ أثناء استعادة المقالة تاريخ سابق ليوم: %s لن ترى إلا الإحصاءات الأكثر أهمية. أضف الرؤى الخاصة بك ونظِّمها أدناه. اجتماعي إحصاءات الموقع السنوية - تسجيل نطاق - والآن بعد تثبيت Jetpack، ما علينا سوى مساعدتك على الإعداد. لن يستغرق هذا إلا دقيقة. + مجموع المتابعين تعذّر تحميل اقتراحات النطاق كتابة كلمة مفتاحية للحصول على مزيد من الأفكار لم يتم العثور على أي اقتراحات - مجموع المتابعين + تسجيل نطاق + والآن بعد تثبيت Jetpack، ما علينا سوى مساعدتك على الإعداد. لن يستغرق هذا إلا دقيقة. إزالة من الرؤى + تحريك للأسفل نقل إلى أعلى إعدادات عنصر الإحصاءات يجري نقل المقالة إلى المسودة تجري استعادة المقالة تمت استعادة المقالة يجري نقل المقالة إلى سلة المهملات - التغييرات المحلية - تحريك للأسفل سيؤدي نقل هذه المقالة إلى سلة المهملات إلى تجاهل التغييرات غير المحفوظة كذلك، هل ترغب بالتأكيد في المتابعة؟ - ليس لديك أية مقالات مجدولة - لم تنشر أي مقالات حتى الآن - ليس لديك أي مسودة مقالات - ليس لديك أي مقالات تم وضعها في سلة المهملات + التغييرات المحلية نقل إلى المسودة تبديل إلى عرض القائمة تبديل إلى عرض البطاقات - يرجى تسجيل الدخول باستخدام اسم مستخدم WordPress.com الخاص بك بدلاً من عنوان بريدك الإلكتروني. + ليس لديك أي مقالات تم وضعها في سلة المهملات + ليس لديك أي مسودة مقالات + ليس لديك أية مقالات مجدولة + لم تنشر أي مقالات حتى الآن يرجى تسجيل الدخول باسم المستخدم وكلمة المرور الخاصة بك. - المقالات - إجمالي التعليقات - معدل التعليقات/المقالة - إجمالي الإعجابات - معدل الإعجابات/المقالة - إجمالي الكلمات + يرجى تسجيل الدخول باستخدام اسم مستخدم WordPress.com الخاص بك بدلاً من عنوان بريدك الإلكتروني. معدل الكلمات/المقالة + إجمالي الكلمات + معدل الإعجابات/المقالة + إجمالي الإعجابات + معدل التعليقات/المقالة + إجمالي التعليقات + المقالات عام هذا العام الموقع على عنوان هذا الرابط ليس موقع ووردبريس. وبالنسبة لنا للاتصال به، يجب أن يستخدم الموقع ووردبريس. - جاري التحقق من الرصيد المتاح للنطاقات فشل التحقق من الرصيد المتاح للنطاقات - تنصيب الإضافة - لتنصيب الإضافات، لا بد من أن يكون لديك نطاق مخصص مرتبط بموقعك. + جاري التحقق من الرصيد المتاح للنطاقات تسجيل نطاق + لتنصيب الإضافات، لا بد من أن يكون لديك نطاق مخصص مرتبط بموقعك. + تنصيب الإضافة + ستتمكن من تخصيص شكل ومظهر الموقع الخاص بك لاحقًا + النشر في: %s جدولة ليوم: %s + نُشر في: %s + تمّت الجدولة ليوم: %s الأسابيع الأخيرة معدل المشاهدات لكل يوم المشاهدات الفترة شهور وسنوات تحميل المزيد - ستتمكن من تخصيص شكل ومظهر الموقع الخاص بك لاحقًا - تمّت الجدولة ليوم: %s - نُشر في: %s - النشر في: %s اليوم أفضل ساعة أفضل يوم @@ -910,51 +930,51 @@ Language: ar لا يمكننا تحميل الخطط في الوقت الحالي. يرجى المحاولة في وقت لاحق. لا يمكن تحميل الخطط لا يوجد اتصال + التبديل إلى مُحرر المكوّنات + التبديل إلى المحرر التقليدي حدثت مشكلة أثناء تحميل بياناتك، يرجى تحديث الصفحة لإعادة المحاولة. لم يتم تحميل البيانات تحرير المقالات والصفحات الجديدة باستخدام مُحرر المكوّنات استخدام مُحرر المكوّنات - التبديل إلى المحرر التقليدي - التبديل إلى مُحرر المكوّنات تم تمكين محرر المكوّنات خروج تم استكمال %1$d من %2$d + تنمية جمهورك تخصيص موقعك الخطوات التالية مكتمل (%d) استمتع بمنتجك النهائي! رفع أيقونة للموقع - أنقر على %1$s إضافة صفحة %2$s لإنشاء صفحة جديدة. - أنقر على %1$s الخطة %2$s لمشاهدة خطتك الحالية والخطط الأخرى المتاحة سيرى زائروك أيقونتك في متصفحهم. أضف أيقونة مخصصة للحصول على مظهر جذّاب واحترافي. - تنمية جمهورك - لقد أجرينا بعض التغييرات على قائمة checklist - سنوجهك عبر أساسيات بناء موقعك وتنميته. - قم بنشر مسودّة مقالتك الأولى. - أنقر على %1$s أيقونة موقعك %2$s لرفع أيقونة جديدة - أنقر على %1$s الإحصائيات %2$s لمشاهدة مستوى أداء موقعك. + أنقر على %1$s الخطة %2$s لمشاهدة خطتك الحالية والخطط الأخرى المتاحة + أنقر على %1$s إضافة صفحة %2$s لإنشاء صفحة جديدة. انقر على ⁦%1$s⁩ الصفحات ⁦%2$s⁩ للمتابعة. - تمكين مشاركة المقالة - معرفة المزيد عن أدوات التسويق وتحسين محركات البحث SEO في خططنا المدفوعة. - استكشاف الخطط + أنقر على %1$s الإحصائيات %2$s لمشاهدة مستوى أداء موقعك. + أنقر على %1$s أيقونة موقعك %2$s لرفع أيقونة جديدة + قم بنشر مسودّة مقالتك الأولى. + سنوجهك عبر أساسيات بناء موقعك وتنميته. + لقد أجرينا بعض التغييرات على قائمة checklist لقد أضفنا المزيد من المهام لمساعدتك على تنمية جمهورك. - إنشاء صفحة جديدة - ضبط الخطوط، إضافة صور، والمزيد. + استكشاف الخطط + معرفة المزيد عن أدوات التسويق وتحسين محركات البحث SEO في خططنا المدفوعة. + تمكين مشاركة المقالة شارك المقالات الجديدة تلقائيًّا على حساباتك على وسائل التواصل الاجتماعي. + ضبط الخطوط، إضافة صور، والمزيد. + إنشاء صفحة جديدة أضف صفحة للمحتوى الأساسي — تعتبر صفحة \"حول\" بداية رائعة. - إزالة الخطوات التالية - إزالة هذا - تصفّح القوالب - واكب التحديثات لأداء موقعك. التحقّق من إحصاءات موقعك + واكب التحديثات لأداء موقعك. + تصفّح القوالب استكشف العشرات من خيارات التنسيق واعثر على لياقتك المثالية. ستؤدي إزالة الخطوات التالية إلى إخفاء جميع الجولات على هذا الموقع. لا يمكن التراجع عن هذا الإجراء. + إزالة الخطوات التالية + إزالة هذا تهانينا لك على إكمال قائمتك. عمل متقن. جميع المهام مكتملة! تخطي المهمة - تذكير طي توسيع + تذكير تحديد الفترة التالية تحديد الفترة السابقة %1$d%% من المشاهدات @@ -970,8 +990,7 @@ Language: ar إنشاء موقع إنشاء موقع البحث عن نطاقات - هذا هو المكان الذي سيجده الأشخاص على الإنترنت. - اختيار اسم نطاق لموقعك + هذا هو المكان الذي سيجدك فيه الأشخاص على الإنترنت. لا توجد عناوين متاحة مطابقة لبحثك حدث خطأ أثناء الاتصال بالخادم، يرجى المحاولة مجددًا حدثت مشكلة @@ -998,6 +1017,9 @@ Language: ar لا توجد بيانات لهذه الفترة إزالة موقع من الوسائط يتعذر علينا فتح الإحصاءات في الوقت الحالي. يرجى المحاولة مجددًا في وقت لاحق + فشل تحميل بعض الوسائط بسبب وجود خطأ في الشبكة. + لا توجد وسائط مطابقة لبحثك + ابحث للعثور على صور بتنسيق GIF لإضافتها إلى مكتبة الوسائط الخاصة بك! مشاهدات الكاتب الكُتّاب @@ -1027,12 +1049,9 @@ Language: ar مشاركة المقالة إنشاء مقالة لقد مرّ %1$s منذ نشر %2$s. إليك حالة أداء المقالة حتى الآن… - فشل تحميل بعض الوسائط بسبب وجود خطأ في الشبكة. - لا توجد وسائط مطابقة لبحثك - ابحث للعثور على صور بتنسيق GIF لإضافتها إلى مكتبة الوسائط الخاصة بك! - العلامات والتصنيفات لقد مرّ %1$s منذ نشر%2$s. ابدأ العمل وقم بزيادة مشاهدات مقالتك عن طريق مشاركة مقالتك: لم تنشر أي مقالات بعد. بعد أن تبدأ في النشر، سيظهر آخر ملخص للمقالة هنا: + العلامات والتصنيفات كل الوقت %1$s - %2$s المتابعون @@ -1051,10 +1070,10 @@ Language: ar المتابع إجمالي %1$s من المتابعين: %2$s البريد الإلكتروني - إدارة الرؤى WordPress.com - لا توجد بيانات حتى الآن + إدارة الرؤى لم تتم إضافة أي رؤى بعد + لا توجد بيانات حتى الآن قائمة تصحيح الأخطاء جاري تغيير كلمة المرور… ينبغي ألا يقل طول كلمة المرور الخاصة بك عن ستة أحرف. ولجعل كلمة المرور أقوى، استخدم أحرفًا كبيرة وصغيرة وأرقامًا ورموزًا مثل ! \" ? $ % ^ & ). @@ -1068,6 +1087,8 @@ Language: ar السابق التالي تم استخدام %1$s + يرجى إدخال موقع WordPress.com أو موقع ووردبريس مُستضاف ذاتيًّا ومتصل بـ Jetpack + جاري تحميل المراجعة تم تحميل المراجعة تحميل تم إنشاء المقالة بتاريخ %1$s في تمام %2$s @@ -1075,36 +1096,34 @@ Language: ar لا يوجد تاريخ حتى الآن عندما تُجري تغييرات على مقالتك، ستتمكن من رؤية التاريخ هنا عندما تُجري تغييرات على صفحتك، ستتمكن من رؤية التاريخ هنا - جاري تحميل المراجعة - يرجى إدخال موقع WordPress.com أو موقع ووردبريس مُستضاف ذاتيًّا ومتصل بـ Jetpack صورة رمزية للمستخدم + الحجم الكامل كبير متوسط صورة مصغّرة - الحجم الكامل السّجل - في انتظار المراجعة الصفحة المحددة غير متاحة + في انتظار المراجعة ليس لديك أي صفحات تم نقلها إلى سلة المهملات ليس لديك أي صفحات مجدولة ليس لديك أي مسودة صفحات لم تنشر أي صفحات حتى الآن بحث في الصفحات لا تتطابق أي صفحات مع بحثك + حذف بشكل دائم نقل إلى سلة المهملات نقل إلى المسودة - حذف بشكل دائم تعيين الأصل عرض + محذوف مجدول المسودات منشور أجرينا عددًا كبيرًا جدًا من المحاولات لإرسال رمز التحقق عبر الرسائل القصيرة — استرح، واطلب رمزًا جديدًا في غضون دقيقة. - محذوف + لا يتطابق أي حساب على WordPress.com مع حساب Google هذا. لا تتطابق أي مواقع مع بحثك لا تتطابق أي مواقع مع بحثك تم تغيير أصل الصفحة - لا يتطابق أي حساب على WordPress.com مع حساب Google هذا. تم حذف الصفحة نهائيًّا تمت جدولة الصفحة تم نشر الصفحة @@ -1122,44 +1141,44 @@ Language: ar عرض موقعك انقر على %1$sعرض الموقع %2$s لاستعراض موقعك مشاركة موقعك - اتصل بحساباتك على وسائل التواصل الاجتماعي – سيشارك موقعك مقالات جديدة تلقائيًّا. أقر على %1$s مشاركة %2$s للمتابعة أنقر على %1$s الروابط %2$s لإضافة حساباتك على وسائل التواصل الاجتماعي + اتصل بحساباتك على وسائل التواصل الاجتماعي – سيشارك موقعك مقالات جديدة تلقائيًّا. نشر مقالة انقر على %1$sإنشاء مقالة%2$s لإنشاء مقالة جديدة هل تريد بعض المساعدة للبدء؟ موافقة أبدًا + لا، شكرًا متابعة مواقع أخرى انقر على %1$sبحث%2$s للبحث عن مواقع ذات اهتمامات مماثلة انقر على %1$sالقاريء%2$s للمتابعة + يمكنك العثور على المواقع التي تلهمك، ومتابعتها للحصول على التحديثات عندما تقوم بالنشر. تخصيص موقعك انقر على %1$sالقوالب%2$s للمتابعة انقر على %1$sتخصيص%2$s للبدء في تخصيص موقعك - لا، شكرًا - يمكنك العثور على المواقع التي تلهمك، ومتابعتها للحصول على التحديثات عندما تقوم بالنشر. اختيار قالب + أنقر على %1$s القوالب %2$s لاكتشاف قوالب جديدة تصفّح جميع قوالبنا للعثور على ما يناسبك. انتقال إلغاء ليس الآن - ليس لديك أي مواقع - أنقر على %1$s القوالب %2$s لاكتشاف قوالب جديدة المزيد - أضف موضوعًا هنا للعثور على مقالات حول موضوعاتك المفضلة + ليس لديك أي مواقع لا توجد مواضيع تمت متابعتها + أضف موضوعًا هنا للعثور على مقالات حول موضوعاتك المفضلة + سجّل الدخول إلى حساب WordPress.com الذي تستخدمه للاتصال بـ Jetpack. إعادة المحاولة + الإعداد + يتعذر تنصيب Jetpack في الوقت الحالي. حدثت مشكلة - Jetpack - الأسئلة الشائعة عن Jetpack تمّ تنصيب Jetpack - تنصيب Jetpack - تنصيب Jetpack - سجّل الدخول إلى حساب WordPress.com الذي تستخدمه للاتصال بـ Jetpack. - يتعذر تنصيب Jetpack في الوقت الحالي. تنصيب Jetpack على موقعك. قد يستغرق هذا الأمر وقتًا يصل إلى بضع دقائق لاكتماله. + تنصيب Jetpack لن يتم تخزين بيانات اعتمادك وستُستخدم فقط بغرض تنصيب Jetpack. - الإعداد + تنصيب Jetpack + Jetpack + الأسئلة الشائعة عن Jetpack لاستخدام الإحصاءات على موقع ووردبريس الخاص بك، سيتعين عليك تنصيب إضافة Jetpack. لا توجد سمات مطابقة لبحثك ما الذي ترغب في إيجاده؟ @@ -1170,20 +1189,20 @@ Language: ar لا توجد وسائط مطابقة لبحثك هل ترغب في تسجيل الخروج من ووردبريس؟ لقد أدخلتَ تغييرات على المقالات التي لم يتم رفعها إلى موقعك. سيؤدي تسجيل الخروج الآن إلى حذف تلك التغييرات من جهازك. هل ترغب في تسجيل الخروج على أي حال؟ - لا يوجد متابعون للبريد الإلكتروني حتى الآن - ستظهر المقالات التي نالت إعجابك هنا لا توجد مشاهدات بعد + لا يوجد متابعون للبريد الإلكتروني حتى الآن لا متابِعون حتى الآن لا يوجد مستخدمين حتى الآن - لا توجد مواقع تمت متابعتها + ستظهر المقالات التي نالت إعجابك هنا لا توجد إعجابات حتى الآن - استكشف المواقع الذهاب للمتابعة - لا متابعين حتى الآن + استكشف المواقع + لا توجد مواقع تمت متابعتها لا توجد إعجابات حتى الآن + لا متابعين حتى الآن نظرًا لأنك مشترك في الخطة المجانية، سترى أحداثًا محدودة في سجل نشاطك. - لا يوجد نشاط حتى الآن عندما تُجري تغييرات على موقعك، ستتمكن من رؤية تاريخ النشاط الخاص بك هنا + لا يوجد نشاط حتى الآن إنشاء مقالة إنشاء صفحة رفع الوسائط @@ -1199,20 +1218,20 @@ Language: ar يرجى إدخال عنوان بريدك الإلكتروني للاستمرار، يرجى إدخال عنوان بريدك الإلكتروني واسمك رسالة جديدة من \"التعليمات والدعم\" + ووردبريس لم يتم التعيين البريد الإلكتروني الخاص بجهة الاتصال سجل التطبيق تذاكري + هل أنت متأكد من رغبتك في استرجاع موقعك مرة أخرى إلى %1$s في %2$s؟ سيؤدي هذا الإجراء إلى حذف كل المحتوى والخيارات التي تم إنشاؤها أو تغييرها من ذلك الحين. إرجاع الموقع الإرجاع قيد التقدّم الإرجاع إلى %1$s %2$s - هل أنت متأكد من رغبتك في استرجاع موقعك مرة أخرى إلى %1$s في %2$s؟ سيؤدي هذا الإجراء إلى حذف كل المحتوى والخيارات التي تم إنشاؤها أو تغييرها من ذلك الحين. - ووردبريس استعادة موقعك حاليًا تمت استعادة موقعك بنجاح - زر الإجراء في سجل النشاط تمت استعادة موقعك بنجاح\nتم الإرجاع إلى %1$s %2$s يتم الآن استعادة موقعك\nالاسترجاع إلى %1$s %2$s + زر الإجراء في سجل النشاط إدارة تلقائية احفظ هذه المقالة، وعُد إلى قراءتها وقتما تشاء. لن تتوافر إلا على هذا الجهاز — لا تقوم المقالات المحفوظة بالمزامنة إلى أجهزتك الأخرى. حفظ المقالات لوقت لاحق @@ -1220,16 +1239,17 @@ Language: ar لم يتم العثور على نتائج قراءة مقالة المصدر المواقع - تسجيل البريد الإلكتروني تمّ إرسال الرابط السحري - بدلاً من ذلك: + تسجيل البريد الإلكتروني رمز التحقق - عنوان البريد الإلكتروني للدخول - عنوان تسجيل الدخول للموقع - رابط تسجيل الدخول السحري - تمّ إرسال الرابط السحري اعتماد تسجيل الدخول + تمّ إرسال الرابط السحري + رابط تسجيل الدخول السحري + عنوان تسجيل الدخول للموقع + عنوان البريد الإلكتروني للدخول + بدلاً من ذلك: انقر على %s لحفظ مقالة في القائمة لديك. + لم يتم حفظ أي مقالات — حتى الآن! تم حفظ المقالة عرض الكل تم الحفظ @@ -1238,7 +1258,6 @@ Language: ar إضافة إلى المقالات المحفوظة المقالات المحفوظة تم الحذف - لم يتم حفظ أي مقالات — حتى الآن! تغيير رمز الموقع إلغاء إزالة @@ -1262,16 +1281,16 @@ Language: ar قراءة سياسة الخصوصية نستخدم أدوات تتبع أخرى، بما في ذلك بعض الأدوات التي تنتمي إلى أطراف ثالثة. اقرأ عن هذه الأدوات وكيفية التحكم فيها. سياسة الطرف الثالث + تساعدنا هذه المعلومات على تحسين منتجاتنا، وجعل التسويق أكثر ملاءمة لك، وتخصيص تجربة WordPress.com، والمزيد كما يرد بالتفصيل في سياسة الخصوصية لدينا. سياسة الخصوصية + شارك المعلومات مع أداة التحليلات لدينا حول استخدامك الخدمات أثناء تسجيل الدخول إلى حساب WordPress.com الخاص بك. سياسة ملفات تعريف الارتباط إعدادات الخصوصية جمع المعلومات - شارك المعلومات مع أداة التحليلات لدينا حول استخدامك الخدمات أثناء تسجيل الدخول إلى حساب WordPress.com الخاص بك. - تساعدنا هذه المعلومات على تحسين منتجاتنا، وجعل التسويق أكثر ملاءمة لك، وتخصيص تجربة WordPress.com، والمزيد كما يرد بالتفصيل في سياسة الخصوصية لدينا. تم إرسال المقالة + ليس لديك حساب؟ %1$sالتسجيل%2$s تتطلب ميزة المكوّن الإضافي أن يكون الموقع في وضع جيد. تتطلب ميزة المكوّن الإضافي ربط اشترك النطاق الأساسي بهذا المستخدم. - ليس لديك حساب؟ %1$sالتسجيل%2$s تتطلب ميزة المكوّن الإضافي مزايا المسؤول. يتعذر تثبيت المكوّن الإضافي على مواقع VIP. يتعذر تثبيت المكوّن الإضافي بسبب قيود مساحة القرص. @@ -1283,6 +1302,8 @@ Language: ar جاري تثبيت الإضافة… تثبيت يمكن أن يستغرق تثبيت الإضافة الأولى على موقعك حتى دقيقة واحدة. لن تتمكن من إجراء تغييرات على موقعك خلال هذه الفترة. + تثبيت الإضافة + الإشعارات إرسال التعليقات الجديدة عبر البريد الإلكتروني أسبوعيًّا فورًا @@ -1290,10 +1311,8 @@ Language: ar مقالات جديدة تلقي إخطارات للمقالات الجديدة من هذا الموقع أرسل رسالة بالبريد الإلكتروني تتضمن المقالات الجديدة - تثبيت الإضافة - الإشعارات جميع المواقع التي أتابعها - المواقع التي تمت متابعتها + مواقع تمّت متابعتها جهاز قراءة الشخصيات مع وجود إخطارات الأشخاص الذين ينظرون إلى الرسومات والمخططات %s في %s @@ -1312,10 +1331,16 @@ Language: ar إضافة %d إنشاء وسم الانتقال إلى أعلى + الإشعارات + فتح الرابط الخارجي إظهار المزيد صورة حذف تشغيل الفيديو + تشغيل الفيديو المميز + شعار الإضافة + لافتة الإضافة + اختر من وسائط ووردبريس فتح الكاميرا اختر من الجهاز معلومات الدور @@ -1331,27 +1356,22 @@ Language: ar صورة الملف الشخصي لـ %s علامة الاختيار جاري التسجيل باستخدام Google… - اختر من وسائط ووردبريس - لافتة الإضافة - شعار الإضافة - تشغيل الفيديو المميز - فتح الرابط الخارجي - الإشعارات فشل الاتصال بـ Jetpack: %s أنت متصل بالفعل بـ Jetpack تراجع + تم التبديل إلى الوضع المرئي الوضع المرئي + تم التبديل إلى وضع HTML وضع HTML معاينة حفظ كمسودة %s تيرابايت - تم التبديل إلى وضع HTML - تم التبديل إلى الوضع المرئي %s جيجابايت %s ميجابايت %s كيلوبايت %s بايت %1$s من %2$s + إذا كنت بحاجة إلى مزيد من المساحة، ففكر في ترقية خطة ووردبريس الخاصة بك. المساحة المستخدمة الوسائط تم وضع علامة غير مزعج على التعليق @@ -1367,11 +1387,11 @@ Language: ar تحرير الصورة اختيار الموقع حساب جديد - إذا كنت بحاجة إلى مزيد من المساحة، ففكر في ترقية خطة ووردبريس الخاصة بك. تم تسجيل الدخول كـ تفاصيل الشخص تفاصيل الملف أزرار المشاركة + الإشعارات القارئ أنا موقعي @@ -1379,7 +1399,6 @@ Language: ar المساعدة والدعم الترخيص ملاحظات الإصدار - الإشعارات تم رفع الصورة الرمزية الخاصة بك وستصبح متاحة قريبًا. يبدو أنك أوقفت الأذونات المطلوبة لهذه الميزة.<br/><br/>لتغيير هذا، قم بتحرير أذوناتك وتأكد من تمكين <strong>%s</strong>. أذونات @@ -1422,7 +1441,6 @@ Language: ar لم يتم رفع مقالة واحدة مع ملف واحد (بدون عنوان) \@%s - %1$f، %2$f إنشاء موقع انقر للمتابعة. تم إنشاء الموقع! @@ -1433,44 +1451,44 @@ Language: ar لم يتم اقتراح أسماء مستخدمين من %1$s%2$s%3$s. يُرجى إدخال المزيد من الأحرف أو الأرقام للحصول على اقتراحات. حدث خطأ أثناء استرداد اقتراحات اسم المستخدم. هل ترغب في تجاهل تغيير اسم المستخدم؟ + تجاهل حفظ إضافة صورة رمزية تسجيل الدخول باستخدام Google تسجيل الدخول باستخدام البريد الإلكتروني - تجاهل البريد الإلكتروني موجود بالفعل على WordPress.com.\nالمتابعة لتسجيل الدخول. - إرسال البريد الإلكتروني - يعني تسجيل الدخول موافقتك على %1$sشروط الخدمة%2$s. جاري تحديث الحساب… + يعني تسجيل الدخول موافقتك على %1$sشروط الخدمة%2$s. + إرسال البريد الإلكتروني إعادة المحاولة إغلاق + حدثت بعض المشكلات في إرسال البريد الإلكتروني. يمكنك إعادة المحاولة الآن أو الإغلاق والمحاولة مرة أخرى لاحقًا. اسم المستخدم + يمكنك دائمًا تسجيل الدخول باستخدام رابط مثل الرابط الذي استخدمته للتو، ولكن يمكنك أيضًا إعداد كلمة مرور إذا كنت تفضل ذلك. كلمة المرور (اختياري) اسم العرض إعادة المحاولة إلغاء حدثت بعض المشكلات أثناء تحديث حسابك. يمكنك المحاولة مرة أخرى أو استرداد التغييرات للمتابعة. حدثت بعض المشكلات أثناء تحميل صورتك الرمزية. - حدثت بعض المشكلات أثناء التحقق من عنوان البريد الإلكتروني. - حدثت بعض المشكلات في إرسال البريد الإلكتروني. يمكنك إعادة المحاولة الآن أو الإغلاق والمحاولة مرة أخرى لاحقًا. لإنشاء حسابك الجديد على WordPress.com، يرجى إدخال عنوان بريدك الإلكتروني. - يمكنك دائمًا تسجيل الدخول باستخدام رابط مثل الرابط الذي استخدمته للتو، ولكن يمكنك أيضًا إعداد كلمة مرور إذا كنت تفضل ذلك. + حدثت بعض المشكلات أثناء التحقق من عنوان البريد الإلكتروني. + تسجيل الدخول إلى WordPress.com قم بتسجيل الدخول باستخدام اسم المستخدم الخاص بك. قم بتسجيل الدخول عن طريق إدخال عنوان الموقع. - تسجيل الدخول إلى WordPress.com + بحاجة إلى تحديث + بحث في الإضافات جديد شائع لا توجد مطابقات مشاهدة الكل إدارة + يتعذر البحث في الإضافات حدث خطأ أثناء تثبيت %s تم تثبيت %s بنجاح تثبيت الإعجاب إضافة موقع جديد - يتعذر البحث في الإضافات - بحث في الإضافات - بحاجة إلى تحديث أنشئ موقعًا جديدًا لأعمالك أو مجلتك أو مدونتك الشخصية؛ أو اتصل بموقع ووردبريس الموجود. للحصول على إشعارات مساعدة على جهازك من موقع ووردبريس الخاص بك، سيتعين عليك تنصيب إضافة Jetpack. هل ترغب في إعداد Jetpack؟ صور \"بطيئة التحميل\" @@ -1502,14 +1520,14 @@ Language: ar تعذر تحميل الإضافات صفحات الموقع إدارة علامات موقعك - هل تريد حذف وسم \"%s\" بشكل دائم؟ - جاري الحذف جاري الحفظ + جاري الحذف + هل تريد حذف وسم \"%s\" بشكل دائم؟ توجد علامة تحمل هذا الاسم بالفعل + أضف وسماً جديداً الوصف العلامة يدعم موقعك على WordPress.com استخدام صفحات الجوال المسرّعة، وهي مبادرة تقودها Google لتسريع أوقات التحميل بشكل كبير على الأجهزة المحمولة. - أضف وسماً جديداً صفحات الجوال المسرّعة (AMP) تعذر تحميل المناطق الزمنية اعرف المزيد عن تنسيق التاريخ والوقت @@ -1526,11 +1544,11 @@ Language: ar حذف رابط خارجي أيقونة الإضافة - صفحة الإضافة على WordPress.org الصفحة الرئيسية للإضافة + صفحة الإضافة على WordPress.org هل تريد بالتأكيد إزالة %1$s من %2$s؟\n\nسيؤدي ذلك إلى إلغاء تنشيط المكون الإضافي وحذف جميع الملفات والبيانات المقترنة. - جاري إزالة %s… إزالة الإضافة + جاري إزالة %s… جاري تعطيل %s… حدث خطأ أثناء تكوين المكون الإضافي: %s حدث خطأ أثناء إزالة %s. @@ -1543,8 +1561,8 @@ Language: ar نشط غير مفعل نشط - الإضافات الإضافات + الإضافات فتح الرابط في نافذة/علامة تبويب جديدة رابط لـ حدث خطأ. @@ -1609,8 +1627,8 @@ Language: ar إضافة إلى مقالة جديدة يتطلب الأمر صلاحيات من أجل مشاركة الصور أو الفيديوهات عنوان IP أو نطاق IP غير صالح - هل تريد حذف هذا الفيديو؟ جاري الحذف + هل تريد حذف هذا الفيديو؟ هل تريد حذف هذه الصورة؟ تفاصيل المستند تفاصيل الصوت @@ -1625,8 +1643,8 @@ Language: ar اسم الملف عنوان URL النص البديل - ضوء وميض الاتصال بـ موقع + ضوء وميض جهاز الاهتزاز اختيار الصوت المناظر والأصوات @@ -1679,12 +1697,12 @@ Language: ar يظهر عنوان موقعك في الشريط الموجود في أعلى الشاشة عندما تدخل إلى موقعك من متصفح Chrome. ما عنوان الموقع الخاص بي؟ هل تحتاج إلى المساعدة في العثور على عنوان موقعك؟ - أدخل العنوان لموقع ووردبريس الذي تود الاتصال به. رابط الموقع + أدخل العنوان لموقع ووردبريس الذي تود الاتصال به. تم تسجيل الدخول بالفعل إلى WordPress.com المتابعة - أدخل كلمة مرور لحساب WordPress.com الخاص بك الاتصال بموقع آخر + أدخل كلمة مرور لحساب WordPress.com الخاص بك طلب بريد إلكتروني لتسجيل الدخول يبدو أن كلمة المرور هذه غير صحيحة. يرجى التحقق مجددًا من معلوماتك والمحاولة مرة أخرى. طلب رمز تحقق عن طريق رسالة نصية قصيرة (SMS). @@ -1713,10 +1731,6 @@ Language: ar مسودة في انتظار المراجعة نشر - تغيير الموقع - إزالة الموقع - يتعذر فتح منتقي الموقع، خدمات Google Play غير متوفرة - الموقع الآن لا يمكن عرض هذه المقالة إلا لمن لديهم كلمة المرور هذه المقتطفات هي ملخصات يدوية اختيارية لمحتواك. @@ -1725,9 +1739,9 @@ Language: ar الوسوم الاسم اللطيف المقتطف + لم يتم التعيين المزيد من الخيارات الفئات والوسوم - لم يتم التعيين الكل أعلى مستوى التصنيف الأب (اختياري): @@ -1751,9 +1765,9 @@ Language: ar تغيير حجم الفيديوهات في المقالات إلى هذا الحجم التمكين لتغيير حجم الفيديوهات وضغطها تحسين مقاطع الفيديو - جودة الفيديو - الإبلاغ عن خطأ تم تحميل المسودّة + الإبلاغ عن خطأ + جودة الفيديو الكاميرا مساحة التخزين تحرير الأذونات @@ -1779,14 +1793,14 @@ Language: ar عرض زر \"إعجاب\" عرض زر \"إعادة تدوين\" إعادة التدوين والإعجاب - نص فقط الأزرار الرسمية + نص فقط أيقونة فقط أيقونة ونص حدد الحساب الذي ترغب في اعتماده. لاحظ أن مقالاتك ستتم مشاركتها مع الحساب المحدد تلقائيًا. + جاري الاتصال بـ %s هل ترغب في قطع الاتصال بـ %s؟ اتصال حساب آخر - جاري الاتصال بـ %s إعادة الاتصال قطع الاتصال اتصال @@ -1811,12 +1825,12 @@ Language: ar اضغط مع الاستمرار لتحديد العديد من التعليقات اختيار مقطع فيديو من الجهاز اختيار صورة من الجهاز + وسائط ووردبريس إضافة كمعرض إضافة على حدى - وسائط ووردبريس - عمود 1 - %d أعمدة إضافة العديد من الصور + %d أعمدة + عمود 1 إعادة إرسال البريد الإلكتروني أرسلنا رسالة بريد إلكتروني إلى %s عند اشتراكك للمرة الأولى. يرجى فتح الرسالة والنقر على الزر الأزرق لتمكين النشر. أرسلنا إليك رسالة بريد إلكتروني عند اشتراكك للمرة الأولى. يرجى فتح الرسالة والنقر على الزر الأزرق لتمكين النشر. @@ -1846,11 +1860,11 @@ Language: ar متوسط منخفض تم الرفع - محذوف - تم الوضع في قائمة الانتظار فشل الرفع - جاري الرفع + محذوف جاري الحذف + جاري الرفع + تم الوضع في قائمة الانتظار جودة الصورة تم إلغاء جميع عمليات رفع الوسائط بسبب خطأ غير معروف. يُرجى إعادة محاولة الرفع تنسيق المقالة غير معروف @@ -1910,40 +1924,40 @@ Language: ar تمت الموافقة على التعليق! أعجبني الآن - المتابع المشاهدة + المتابع لا يوجد اتصال، تعذر حفظ ملفك الشخصي - لا شيء - يسار يمين + يسار + لا شيء تم تحديد %1$d تعذر استرداد مستخدمي الموقع - المتابع المتابع عبر البريد الإلكتروني + المتابع جاري جلب المستخدمين… - المتابعون عبر البريد الإلكتروني المشاهدون + المتابعون عبر البريد الإلكتروني المتابعون الفريق دعوة ما يقارب 10 عناوين بريد إلكتروني و/أو أسماء مستخدمين في WordPress.com. سيتم إرسال تعليمات عن كيفية إنشاء اسم مستخدم لمَن لا يملك اسم مستخدم. إذا قمت بإزالة هذا المشاهد، فلن يتمكن بعد الآن من زيارة هذا الموقع.\n\nألا تزال تريد إزالة هذا المشاهد؟ في حالة إزالة المتابع، فسيتم وقف إرسال التنبيهات إليه عن هذا الموقع، ما لم يتابع مرة أخرى.\n\nألا تزال تريد إزالة هذا المتابع؟ منذ %1$s - تعذر إزالة المتابع تعذر إزالة المشاهد + تعذر إزالة المتابع تعذر استرداد متابعي الموقع عبر البريد الإلكتروني تعذر استرداد متابعي الموقع فشل رفع بعض الوسائط. يمكنك الإنتقال الى وضع HTML\nبهذه الحالة. إزالة جميع المرفوعات الفاشلة والمتابعة؟ - تم حفظ التغييرات العرض رابط لـ كلمات توضيحية + تم حفظ التغييرات تجاهل التغييرات الغير محفوظة؟ إيقاف الرفع؟ - تم إرسال الدعوة ولكن بعض الأخطاء قد وقعت! - تم إرسال الدعوة بنجاح اضغط للمحاولة مرة أخرى! + تم إرسال الدعوة بنجاح %1$s: %2$s + تم إرسال الدعوة ولكن بعض الأخطاء قد وقعت! حدث خطأ ما أثناء محاولة إرسال الدعوة! لا يمكن الإرسال: هناك اسم مستخدم أو بريد إلكتروني غير صالح لا يمكن الإرسال: اسم المستخدم أو البريد الإلكتروني غير صالح @@ -1955,8 +1969,8 @@ Language: ar رسالة مخصصة دعوة اسم المستخدم أو البريد الإلكتروني - خارجي دعوة أشخاص + خارجي إرسال رابط مسح محفوظات البحث مسح محفوظات البحث؟ @@ -1964,18 +1978,18 @@ Language: ar البحث في ووردبريس تم تعطيل الروابط في شاشة المعاينة إرسال - إذا قمت بإزالة %1$s، فلن يعود هذا المستخدم قادرًا على الوصول إلى هذا الموقع، ومع ذلك سيبقى أي محتوى تم إنشاؤه بواسطة %1$s على الموقع.\n\nهل لا تزال ترغب في إزالة هذا المستخدم؟ تمت الإزالة بنجاح @%1$s + إذا قمت بإزالة %1$s، فلن يعود هذا المستخدم قادرًا على الوصول إلى هذا الموقع، ومع ذلك سيبقى أي محتوى تم إنشاؤه بواسطة %1$s على الموقع.\n\nهل لا تزال ترغب في إزالة هذا المستخدم؟ إزالة %1$s - لم تنشر المواقع الموجودة في هذه القائمة أي شيء مؤخرًا - أشخاص الدور + أشخاص + لم تنشر المواقع الموجودة في هذه القائمة أي شيء مؤخرًا تعذرت إزالة المستخدم - تعذر استرداد مستخدمي الموقع تعذر تحديث دور المستخدم + تعذر استرداد مستخدمي الموقع حدث خطأ أثناء تحديث Gravatar الخاصة بك - حدث خطأ أثناء تحديد موقع الصورة التي تم اقتصاصها حدث خطأ أثناء إعادة تحميل جرافتار + حدث خطأ أثناء تحديد موقع الصورة التي تم اقتصاصها حدث خطأ أثناء اقتصاص الصورة التحقق من البريد الإلكتروني غير متاح حاليًا. يُرجى إدخال كلمة مرورك @@ -1983,15 +1997,15 @@ Language: ar أدخل كلمة مرورك بدلاً من ذلك تظهر للعامة أثناء تعليقك. التقاط صورة أو تحديدها - سيتم إرسال مقالاتك وصفحاتك وإعداداتك إليك عبر البريد الإلكتروني على %s. - خطة الخطط + خطة + سيتم إرسال مقالاتك وصفحاتك وإعداداتك إليك عبر البريد الإلكتروني على %s. تصدير المحتوى الخاص بك تم إرسال البريد الإلكتروني للتصدير! جاري تصدير المحتوى… - لديك ترقيات متميزة نشطة على موقعك. يرجى إلغاء ترقياتك قبل حذف موقعك. - إظهار عمليات الشراء التحقق من عمليات الشراء + إظهار عمليات الشراء + لديك ترقيات متميزة نشطة على موقعك. يرجى إلغاء ترقياتك قبل حذف موقعك. ترقيات متميزة حدث خطأ. تعذر طلب عمليات الشراء. جاري حذف الموقع… @@ -2000,49 +2014,49 @@ Language: ar النطاق الرئيسي حدث خطأ أثناء حذف موقعك. يرجى الاتصال بالدعم للحصول على مزيد من المساعدة. حدث خطأ أثناء حذف الموقع - يرجى كتابة %1$s في الحقل أدناه للتأكيد. لن يبقى لموقعك بعد ذلك أي أثر. تصدير المحتوى + يرجى كتابة %1$s في الحقل أدناه للتأكيد. لن يبقى لموقعك بعد ذلك أي أثر. تأكيد حذف الموقع الاتصال بالدعم إذا كنت تريد موقعًا ولا تريد أيًّا من المقالات أو الصفحات التي لديك الآن، فيمكن لفريق الدعم لدينا حذف المقالات والصفحات والوسائط والتعليقات الخاصة بك.\n\nسيبقي ذلك على موقعك وعنوان URL في حالة نشطة، ولكنه يعطيك بداية جديدة عند إنشاء المحتوى الخاص بك. اتصل بنا فقط لحذف المحتوى الحالي الخاص بك. - ابدأ موقعك من جديد دعنا نساعدك - إعدادات التطبيق + ابدأ موقعك من جديد البدء من جديد + إعدادات التطبيق إزالة عمليات الرفع الفاشلة متقدم لا توجد تعليقات موضوعة في سلة المهملات لا توجد تعليقات في قائمة الإنتظار لا توجد تعليقات تمّت الموافقة عليها تعذر الاتصال. طرق XML-RPC غير موجودة على الخادم. - الحالة وسط فيديو - محادثة - معرض - اقتباس + الحالة قياسي - صورة + اقتباس رابط - ملاحظة + صورة + معرض + محادثة صوت + ملاحظة معلومات حول دورات WordPress.com ومناسباته (على الإنترنت وشخصيًا). فرص المشاركة في أبحاث WordPress.com واستطلاعاته. نصائح للحصول على أكبر استفادة من WordPress.com. المجتمع - الردود على تعليقاتي - اقتراحات الأبحاث - إنجازات الموقع + اقتراحات + الردود على تعليقاتي الإشارات إلى اسم المستخدم - الإعجابات بمقالاتي + إنجازات الموقع متابعات للموقع + الإعجابات بمقالاتي الإعجابات بتعليقاتي التعليقات على موقعي %d من العناصر عنصر واحد - تعليقات المستخدمين المعروفين كل المستخدمين + تعليقات المستخدمين المعروفين لا توجد تعليقات %d من التعليقات في الصفحة تعليق واحد في الصفحة @@ -2052,11 +2066,11 @@ Language: ar موافقة تلقائية على تعليقات الجميع. موافقة تلقائية إذا كان لدى المستخدم تعليق تمت الموافقة عليه مسبقًا تلزم موافقة يدوية على تعليقات الجميع. - يوم واحد %d من الأيام - انقر فوق رابط التحقق في البريد الإلكتروني المرسل إلى %1$s للتأكيد على عنوانك الجديد - موقع أساسي + يوم واحد عنوان موقع ويب + موقع أساسي + انقر فوق رابط التحقق في البريد الإلكتروني المرسل إلى %1$s للتأكيد على عنوانك الجديد أنت تقوم حاليًا برفع وسائط. يُرجى الانتظار حتى تكتمل هذه العملية. يتعذر تحديث التعليقات في الوقت الحالي - إظهار تعليقات أقدم تعيين صورة مميزة @@ -2068,10 +2082,10 @@ Language: ar استعادة تم حذف التعليق لا توجد تعليقات مزعجة - يتعذر تحميل الصفحة الكل - لغة الواجهة + يتعذر تحميل الصفحة إيقاف تشغيل + لغة الواجهة حول التطبيق تعذر حفظ إعدادات الحساب تعذر استرداد إعدادات حسابك @@ -2079,20 +2093,20 @@ Language: ar لم يتم التعرف على رمز اللغة السماح للتعليقات بالتداخل في سلسلة المواضيع. عمق الموضوع إلى - إزالة - بحث معطّل + بحث + إزالة الحجم الأصلي سيكون موقعك مرئيًّا لك وللمستخدمين الذين توافق عليهم فقط سيكون موقعك مرئيًّا للجميع مع مطالبة محركات البحث بعدم فهرسته في الوقت نفسه سيكون موقعك مرئيًّا للجميع ويمكن فهرسته بواسطة محركات البحث كلمات قليلة عنك… - سيكون اسم العرض افتراضيًا لاسم المستخدم الخاص بك إذا لم يتم تعيينه نبذة عني + سيكون اسم العرض افتراضيًا لاسم المستخدم الخاص بك إذا لم يتم تعيينه اسم العرض العام - ملفي الشخصي - الاسم الأول اسم العائلة + الاسم الأول + ملفي الشخصي صورة معاينة المقالة ذات الصلة تعذر حفظ معلومات الموقع تعذر استرداد معلومات الموقع @@ -2147,14 +2161,14 @@ Language: ar مستويات %d خاص مخفي - حذف الموقع عام + حذف الموقع قائمة الحظر احتجاز من أجل الإدارة الروابط في التعليقات الموافقة تلقائيًا - مؤشر الترابط ترقيم الصفحات + مؤشر الترابط فرز حسب يجب على المستخدمين تسجيل الدخول. لا بد من تضمين الاسم والبريد الإلكتروني @@ -2164,22 +2178,22 @@ Language: ar التنسيق الافتراضي التصنيف الافتراضي العنوان - عنوان الموقع الشعار + عنوان الموقع الإعدادات الافتراضية للمقالات الجديدة - الحساب كتابة - الأحدث أولاً + الحساب عام - مناقشة - الخصوصية - المقالات ذات الصلة - التعليقات - إغلاق بعد + الأحدث أولاً الأقدم أولاً + إغلاق بعد + التعليقات + المقالات ذات الصلة + الخصوصية + مناقشة ليست لديك الصلاحية اللازمة لرفع ملفات الوسائط إلى هذا الموقع - أبدًا غير معروف + أبدًا لم تعد هذه المقالة موجودة لست مخولاً لعرض هذه المقالة يتعذر استرجاع هذه المقالة @@ -2191,22 +2205,22 @@ Language: ar حدث خطأ. يتعذر تنشيط القالب حسب %1$s شكرًا لك على اختيار %1$s - محاولة وتخصيص - عرض - تفاصيل - الدعم إدارة الموقع تمّ + الدعم + تفاصيل + عرض + محاولة وتخصيص تفعيل - القالب الحالي - تخصيص - تفاصيل - الدعم مفعل - تم نشر المقالة - تم نشر الصفحة - تم تحديث المقالة - تم تحديث الصفحة + الدعم + تفاصيل + تخصيص + القالب الحالي + تم تحديث الصفحة + تم تحديث المقالة + تم نشر الصفحة + تم نشر المقالة عذرًا، لم يتم العثور على أي قوالب. تحميل المزيد من المقالات لا توجد مواقع مطابقة \"%s\" @@ -2239,287 +2253,287 @@ Language: ar تعذر تحميل إعدادات التنبيهات الإعجابات بتعليقك تنبيهات التطبيق - علامة تبويب التنبيهات البريد الإلكتروني + علامة تبويب التنبيهات نحن نرسل دومًا رسائل بريد إلكتروني مهمة بخصوص حسابك، ومع ذلك يمكنك الحصول على بعض الإضافات المفيدة أيضًا. ملخص آخر مقالة لا يوجد اتصال تم إرسال المقالة إلى سلة المهملات - إحصاءات سلة المهملات + إحصاءات معاينة عرض - تحرير نشر + تحرير غير مخوّل لك الوصول إلى هذا الموقع تعذر العثور على هذا الموقع تراجع انتهت صلاحية الطلب. سجِّل الدخول إلى WordPress.com للمحاولة مرة أخرى. - المشاهدات الأفضل على الإطلاق تجاهل + المشاهدات الأفضل على الإطلاق إحصاءات اليوم مقالات ومشاهدات وزوار كل الأوقات الرؤى تسجيل الخروج من WordPress.com - تسجيل الدخول/تسجيل الخروج تسجيل الدخول إلى WordPress.com + تسجيل الدخول/تسجيل الخروج المساعدة والدعم - \"%s\" لم يكن مخفيًا لأنه الموقع الحالي إعدادات الحساب + \"%s\" لم يكن مخفيًا لأنه الموقع الحالي إنشاء موقع WordPress.com إضافة موقع مستضاف ذاتيًا - إظهار/إخفاء المواقع إضافة موقع جديد - عرض المسؤول + إظهار/إخفاء المواقع إختر الموقع - تبديل الموقع عرض الموقع + عرض المسؤول + تبديل الموقع الإعدادات - الشكل والطابع - نشر مقالات المدونة + نشر + الشكل والطابع التكوين انقر لعرضها إلغاء تحديد الكل - إظهار - إخفاء اختيار الكل - رمز التحقق + إخفاء + إظهار + سجّل الدخول مرة أخرى للمتابعة. رمز التحقق غير صالح + رمز التحقق اللغة - سجّل الدخول مرة أخرى للمتابعة. يتعذر استرداد المقالات الناشر: تعذر فتح التنبيه مصطلحات بحث غير معروفة مصطلحات البحث + الكُتّاب جاري جلب التعليقات… جاري جلب الصفحات… جاري جلب المقالات… جاري جلب الوسائط… - الكُتّاب تم نسخ سجلات التطبيق إلى الحافظة + هذا الموقع فارغ مقالات جديدة حدث خطأ أثناء نسخ النص إلى الحافظة - هذا الموقع فارغ جاري رفع المقالة - %1$d من الشهور - كل عام %1$d من السنوات + كل عام + %1$d من الشهور كل شهر - %1$d من الدقائق - منذ ساعة مضت - %1$d من الساعات - كل يوم %1$d من الأيام + كل يوم + %1$d من الساعات + منذ ساعة مضت + %1$d من الدقائق منذ دقيقة مضت منذ ثوانٍ مضت - المقالات والصفحات - مقاطع الفيديو - إشهار متابعون + إشهار + مقاطع الفيديو + المقالات والصفحات البلاد إعجابات - سنوات - مشاهدات الزوار + مشاهدات + سنوات جاري جلب القوالب… تفاصيل تم تحديد %d استعراض الأسئلة المتداولة لا توجد تعليقات حتى الآن - عرض المقالة الأصلية + لا توجد مقالات بهذا الموضوع أعجبني + عرض المقالة الأصلية التعليقات مغلقة %1$d من %2$d يتعذر نشر مقالة فارغة ليس لديك الإذن اللازم لعرض المقالات أو تحريرها ليس لديك الإذن اللازم لعرض الصفحات أو تحريرها ليس لديك الإذن اللازم لعرض التعليقات أو تحريرها - أقدم من شهر المزيد - أقدم من يومين + أقدم من شهر أقدم من أسبوع + أقدم من يومين أعجبني تعليق تم وضع التعليق بسلة المهملات - لا توجد مقالات حتى الآن. لماذا لا تبادر بإنشاء واحدة؟ رد على %s + لا توجد مقالات حتى الآن. لماذا لا تبادر بإنشاء واحدة؟ جاري تسجيل الخروج… - لا توجد مقالات بهذا الموضوع غير قادر على تنفيذ هذا الإجراء - حظر هذا الموقع تعذر حظر هذا الموقع لن تظهر المقالات من هذا الموقع بعد الآن - تحديث + حظر هذا الموقع جدولة - المواقع المتابَعة - تمت متابعة الموقع + تحديث + لا توجد مواقع موصى بها + تعذر إلغاء متابعة هذا الموقع + تعذرت متابعة هذا الموقع أنت تتابع هذا الموقع بالفعل تعذر إظهار هذا الموقع - تعذرت متابعة هذا الموقع - تعذر إلغاء متابعة هذا الموقع - لا توجد مواقع موصى بها - موقع القارئ - مواضيع تمت متابعتها + تمت متابعة الموقع أدخل رابط URL أو موضوعًا للمتابعة + مواقع تمّت متابعتها + مواضيع تمّت متابعتها + موقع القارئ + إذا كنت عادة تتصل بهذا الموقع بدون أي مشاكل، فربما يعني هذا الخطأ أن شخصًا ما يحاول سرقة هذا الموقع, وينبغي ألا تقوم بالاستمرار. هل ترغب في الوثوق بالشهادة على أي حال؟ + شهادة SSL غير صالحة نسيت كلمة المرور؟ المساعدة - شهادة SSL غير صالحة - إذا كنت عادة تتصل بهذا الموقع بدون أي مشاكل، فربما يعني هذا الخطأ أن شخصًا ما يحاول سرقة هذا الموقع, وينبغي ألا تقوم بالاستمرار. هل ترغب في الوثوق بالشهادة على أي حال؟ - حدث خطأ - لاتوجد شبكة متاحة - لا يمكن استعادة عنصر الوسائط المتعددة - عنوان بريدك الإلكتروني غير صالح - أدخل عنوان بريد إلكتروني صالح - تم إضافة التصنيف بنجاح - إضافة التصنيف فشلت اسم المستخدم أو كلمة المرور غير صحيحة + أدخل عنوان بريد إلكتروني صالح + عنوان بريدك الإلكتروني غير صالح خطأ في تحميل الصورة لايمكن تحميل التعليق - لا تنبيهات - حقل اسم التصنيف مطلوب - حدث خطأ أثناء دخول هذه المدونة - حدث خطأ أثناء الإدارة حدث خطأ أثناء تعديل التعليق - بطاقة ذاكرة SD مطلوبة لرفع ملفات الوسائط - المقالات لايمكن تحديثها في الوقت الحاضر - الصفحات لايمكن تحديثها في الوقت الحاضر - فشل في إحضار القوالب + حدث خطأ أثناء الإدارة + حدث خطأ لا يمكن تحديث التعليقات في الوقت الحاضر + الصفحات لايمكن تحديثها في الوقت الحاضر + المقالات لايمكن تحديثها في الوقت الحاضر حدث خطأ أثناء حذف المقالة + لا تنبيهات + بطاقة ذاكرة SD مطلوبة لرفع ملفات الوسائط + حقل اسم التصنيف مطلوب + تم إضافة التصنيف بنجاح + إضافة التصنيف فشلت غير مزعج - خطأ في الاتصال - مسودة محلية - مقال جديد - مدونة ووردبريس - سياسة الخصوصية + فشل في إحضار القوالب + حدث خطأ أثناء دخول هذه المدونة + لا يمكن استعادة عنصر الوسائط المتعددة + لاتوجد شبكة متاحة + غير قادر على إزالة هذا الموضوع + غير قادر على إضافة هذا الموضوع سجل التطبيق - تحديد كمزعج - تحديد التصنيفات - حدث خطأ أثناء تحميل المقال . قم بتحديث مقالاتك ثم أعد المحاولة. - ليس لديك تصريح لعرض مكتبة الوسائط - نص الرابط (اختياري) - بعض الوسائط لايمكن حذفها في الوقت الحاضر. حاول مرة أخرى فيما بعد. - تعلم المزيد - الشبكة المصغرة - إعدادات الصفحة - موافق - غير موافق - تعديل التعليق + حدث خطأ اثناء إنشاء قاعدة بيانات التطبيق. حاول إعادة تنصيب التطبيق. + هذه المدونة مخفية و لايمكن تحميلها . قم بتفعيلها مرة اخرى من الإعدادات وأعد المحاولة. + تعذر تحديث الوسائط هذه المرة + مدونة ووردبريس إعدادات الصورة + التغيرات المحلية + سياسة الخصوصية + وسائط جديدة + مقال جديد + ليست هناك تنبيهات…حتى الآن. + التخويل مطلوب + تحقق من أن عنوان URL الذي تم إدخاله في الموقع صحيح رخص البرمجيات الحرة - لم يتم تغيير التعليق - عرض في المستعرض - إضافة تصنيف جديد + تعذر إنشاء ملف مؤقت لرفع الوسائط. تأكد من وجود مساحة حرة كافية على الجهاز. اسم التصنيف - يتم حفظ التغييرات + إضافة تصنيف جديد + عرض في المستعرض + إزالة الموقع + لم يتم تغيير التعليق التعليق مطلوب - إرسال إلى سلة المهملات؟ إلغاء تعديل هذا التعليق؟ - تعذر إنشاء ملف مؤقت لرفع الوسائط. تأكد من وجود مساحة حرة كافية على الجهاز. - وسائط جديدة - التغيرات المحلية - إعدادات المقالة - تمت الموافقة - هذه المدونة مخفية و لايمكن تحميلها . قم بتفعيلها مرة اخرى من الإعدادات وأعد المحاولة. - حدث خطأ اثناء إنشاء قاعدة بيانات التطبيق. حاول إعادة تنصيب التطبيق. + يتم حفظ التغييرات سلة المهملات - مزعج - مزعج - حذف - تتم الآن الموافقة + إرسال إلى سلة المهملات؟ إرسال إلى سلة المهملات - معلق + تحديد كمزعج غير مصدق - إزالة الموقع - ليست هناك تنبيهات…حتى الآن. - تحقق من أن عنوان URL الذي تم إدخاله في الموقع صحيح - تعذر تحديث الوسائط هذه المرة - حدث خطأ أثناء الوصول إلى هذا المكون الإضافي - هل تريد حذف المقالة؟ + تتم الآن الموافقة + حذف + مزعج + غير موافق + موافق + تعديل التعليق + محذوف + مزعج + معلق + تمت الموافقة هل تريد حذف الصفحة؟ + هل تريد حذف المقالة؟ + إعدادات المقالة تعذر العثور على الملف المراد رفعه. هل تم حذفه أم نقله؟ - محذوف + مسودة محلية + إعدادات الصفحة + نص الرابط (اختياري) + بعض الوسائط لايمكن حذفها في الوقت الحاضر. حاول مرة أخرى فيما بعد. + ليس لديك تصريح لعرض مكتبة الوسائط + الشبكة المصغرة + تعلم المزيد + حدث خطأ أثناء تحميل المقال . قم بتحديث مقالاتك ثم أعد المحاولة. + حدث خطأ أثناء الوصول إلى هذا المكون الإضافي إلغاء التحرير - غير قادر على إزالة هذا الموضوع - غير قادر على إضافة هذا الموضوع - التخويل مطلوب + خطأ في الاتصال + تحديد التصنيفات مشاركة الرابط يتم الآن جلب المقالات … - رد - تم وضع علامة إزعاج على التعليق أنت و %,d آخرون أحببتم هذا %,d أحبوا هذا + رد لا تستطيع مشاركتها إلى ووردبريس بدون أن تجعل المدونة مرئية + تم وضع علامة إزعاج على التعليق + غير قادر على استرجاع هذه المقالة أنت وشخص آخر معجبان بهذا - تحديد صورة تحديد فيديو - غير قادر على استرجاع هذه المقالة - هذه القائمة فارغة. - شخص واحد اعجب بهذا - انت معجب بهذا - مشاركة - ( بدون اسم ) - تابع - متابع - أضيف %s - تم حذف %s - لايمكن نشر تعليقك + تحديد صورة + التسجيل لايمكن فتح %s لايمكن عرض الصورة لايمكن المشاركة + هذا ليس موضوعًا صالحًا + أنت متابع لهذا الموضوع بالفعل + لايمكن نشر تعليقك + انت معجب بهذا + شخص واحد اعجب بهذا + تم حذف %s + أضيف %s رد على التعليق… - لا توجد تعليقات حتى الآن + متابع + تابع + مشاركة إعادة التدوين - التسجيل - أنت متابع لهذا الموضوع بالفعل - هذا ليس موضوعًا صالحًا - القوالب - العنوان - الوصف - تفعيل - النقرات + ( بدون اسم ) + لا توجد تعليقات حتى الآن + هذه القائمة فارغة. + الشهور + الأسابيع + الأيام الأمس اليوم + إحالة الدعوات الوسوم و التصنيفات + النقرات الإحصائيات - كلمات توضيحية - الأيام - الأسابيع - دوائر - مربعات - الشهور + مشاركة + تفعيل فشل التحديث + الوصف + كلمات توضيحية + العنوان عارض الشرائح - المشاركة - إحالة الدعوات + دوائر متجانب + مربعات + القوالب تجاهل إدارة - تم نشر الرد - %d تنبيهات جديدة و %d اكثر + %d تنبيهات جديدة متابعات + تم نشر الرد تسجيل الدخول جاري التحميل… كلمة مرور HTTP اسم مستخدم HTTP حدث خطأ أثناء رفع ملفات الوسائط اسم المستخدم و/أو كلمة المرور غير صحيحين. - كلمة المرور تسجيل الدخول اسم المستخدم + كلمة المرور القارئ صفحات - لا توجد شبكة متاحة المقالات غير معروف + لا توجد شبكة متاحة تم موافق الرابط URL - النسخة بنود الخدمة + النسخة ووردبريس للآندرويد المحاذاة تجديد @@ -2531,24 +2545,24 @@ Language: ar الاسم المختصر لايمكن أن يكون فارغًا خاص العنوان - التصنيفات الفصل بين الوسوم بفواصل + التصنيفات جاري حذف التعليقات بطاقة الذاكرة مطلوبة الوسائط - حذف وافق + حذف بدون - خطأ - إلغاء - حفظ + النشر الآن الرد - نعم - لا + تشغيل معاينة - أضف خطأ في تحديث القسم - تشغيل + خطأ + لا + نعم إعدادات التنبيهات - النشر الآن + أضف + حفظ + إلغاء diff --git a/WordPress/src/main/res/values-bg/strings.xml b/WordPress/src/main/res/values-bg/strings.xml index 06745b9fbb98..8faf5b26510d 100644 --- a/WordPress/src/main/res/values-bg/strings.xml +++ b/WordPress/src/main/res/values-bg/strings.xml @@ -144,11 +144,7 @@ Language: bg Очаква коментар Лична Чернова - Промяна на местоположението - Премахване на местоположението - Не мога да отворя избора на местоположение, Google Play Services не са достъпни. Публикуване - Местоположение Сега Само тези с паролата ще могат да видят публикацията Откъсът е незадължително кратко резюме на текста. diff --git a/WordPress/src/main/res/values-cs/strings.xml b/WordPress/src/main/res/values-cs/strings.xml index 68678882d1ec..e4b431b202b2 100644 --- a/WordPress/src/main/res/values-cs/strings.xml +++ b/WordPress/src/main/res/values-cs/strings.xml @@ -471,7 +471,6 @@ Language: cs_CZ 1 příspěvek s 1 souborem nenahrán (bez názvu) \@%s - %1$f, %2$f Vytvořit stránku Dotkněte se pro pokračování. Web vytvořen! @@ -758,10 +757,6 @@ Language: cs_CZ Koncept Čeká na schválení Publikovat - Změnit polohu - Odstranit polohu - Nelze otevřít výběr místa, služby Google Play nejsou k dispozici - Poloha Teď Pouze čtenáři s tímto heslem si mohou tento příspěvek přečíst Stručný obsah je volitelný ručně vytvořený souhrn obsahu. diff --git a/WordPress/src/main/res/values-de/strings.xml b/WordPress/src/main/res/values-de/strings.xml index 877f7577c24b..d8e74d3d7fcd 100644 --- a/WordPress/src/main/res/values-de/strings.xml +++ b/WordPress/src/main/res/values-de/strings.xml @@ -1,11 +1,20 @@ + Mindestens eine Folie wurde nicht zu deiner Story hinzugefügt, da Stories derzeit keine GIF-Dateien unterstützen. Bitte wähle stattdessen ein statisches Bild oder einen Videohintergrund aus. + GIF-Dateien werden nicht unterstützt + Wir konnten die Medien für diese Story auf der Website nicht finden. + Story kann nicht bearbeitet werden + Medien für diese Story können nicht geladen werden. Überprüfe deine Internetverbindung und versuche es dann erneut. + Story kann nicht bearbeitet werden + Diese Story wurde auf einem anderen Gerät bearbeitet und die Möglichkeiten, bestimmte Objekte zu bearbeiten, sind ggfs. eingeschränkt. + Eingeschränkte Story-Bearbeitung + Die Medien wurden entfernt. Versuche, deine Story zu bearbeiten. Löschen Beim Auswählen des Designs ist ein Fehler aufgetreten. Weiter @@ -32,7 +41,6 @@ Language: de Scrollbares Block-Menü geschlossen. Überspringen Auswählen - Wähle ein Layout für deine Startseite aus, das dir gefällt. Du kannst es später jederzeit ändern oder anpassen. Wähle ein Design Tippe auf „erneut versuchen“, wenn du wieder online bist oder erstelle über den Button unten eine leere Seite. Layouts sind offline nicht verfügbar @@ -294,7 +302,6 @@ Language: de %1$s · %2$s Öffne das Menü mit den Blockaktionen Probiere ein Layout für Neueinsteiger aus - Erwähnung einfügen Tippe zweimal, um das Bottom Sheet mit den verfügbaren Optionen zu öffnen Tippe zweimal, um das Action Sheet mit den verfügbaren Optionen zu öffnen Klassischer Blog @@ -460,7 +467,6 @@ Language: de Geplant Veröffentlicht Nicht verbunden - Website-Adresse Die Facebook-Verbindung findet keine Seiten. Publicize kann keine Verbindung zu Facebook-Profilen herstellen, nur zu öffentlichen Seiten. Ungelesen Papierkorb @@ -960,7 +966,6 @@ Language: de Vorschau der Website anzeigen Es ist ein Problem aufgetreten Keine verfügbaren Adressen, die deiner Suche entsprechen. - Wähl einen Domainnamen für deine Website aus. Fehler bei der Kommunikation mit dem Server, bitte versuche es erneut. Es ist ein Problem aufgetreten Ein Problem ist aufgetreten @@ -1410,7 +1415,6 @@ Language: de 1 Beitrag mit 1 Datei nicht hochgeladen (Ohne Titel) \@%s - %1$f, %2$f Website erstellen Zum Fortfahren tippen. Die Website wurde erstellt! @@ -1699,10 +1703,6 @@ Language: de Entwurf Ausstehender Review Veröffentlichen - Ort ändern - Ort entfernen - Die Ortsauswahl kann nicht geöffnet werden, Google Play ist nicht verfügbar - Ort Jetzt Dieser Beitrag kann nur mithilfe dieses Passworts angezeigt werden. Auszüge sind optionale, selbst verfasste Zusammenfassungen deiner Inhalte. diff --git a/WordPress/src/main/res/values-el/strings.xml b/WordPress/src/main/res/values-el/strings.xml index b785f77131c3..890c9dbeda85 100644 --- a/WordPress/src/main/res/values-el/strings.xml +++ b/WordPress/src/main/res/values-el/strings.xml @@ -284,7 +284,6 @@ Language: el_GR 1 σελίδα και 1 αρχείο απομένουν (Χωρίς τίτλο) \@%s - %1$f, %2$f Δημιουργία ενός ιστότοπου Αποθήκευση Απόρριψη @@ -451,10 +450,7 @@ Language: el_GR Προσχέδιο Εκκρεμής αναθεώρηση Ιδιωτικό - Αφαίρεση Τοποθεσίας - Αλλαγή Τοποθεσίας Δημοσίευση - Τοποθεσία Τώρα Ετικέτες Σύντομο Όνομα diff --git a/WordPress/src/main/res/values-en-rAU/strings.xml b/WordPress/src/main/res/values-en-rAU/strings.xml index 09c8cd68b57b..24c21a074fb8 100644 --- a/WordPress/src/main/res/values-en-rAU/strings.xml +++ b/WordPress/src/main/res/values-en-rAU/strings.xml @@ -340,7 +340,6 @@ Language: en_AU Create Site Search Domains This is where people will find you on the internet. - Choose a domain No available addresses matching your search Error communicating with the server, please try again There was a problem @@ -784,7 +783,6 @@ Language: en_AU 1 post with 1 file not uploaded (Untitled) \@%s - %1$f, %2$f Create site Tap to continue. Site created! @@ -1070,10 +1068,6 @@ Language: en_AU Draft Pending review Publish - Change Location - Remove Location - Can\'t open the Location Picker, Google Play Services is not available - Location Now Only those with this password can view this post Excerpts are optional hand-crafted summaries of your content. diff --git a/WordPress/src/main/res/values-en-rCA/strings.xml b/WordPress/src/main/res/values-en-rCA/strings.xml index 5852c8066d79..d4bdcc8bf259 100644 --- a/WordPress/src/main/res/values-en-rCA/strings.xml +++ b/WordPress/src/main/res/values-en-rCA/strings.xml @@ -41,7 +41,6 @@ Language: en_CA Scrollable block menu closed. Skip Choose - Pick your favourite homepage layout. You can customize or change it later. Choose a design Tap retry when you\'re back online or create a blank page using the button below. Layouts not available while offline @@ -304,7 +303,6 @@ Language: en_CA %1$s · %2$s Try a starter layout Open Block Actions Menu - Insert mention Double tap to open Bottom Sheet with available options Double tap to open Action Sheet with available options We cannot open pages at the moment. Please try again later @@ -471,7 +469,6 @@ Language: en_CA Published The Facebook connection cannot find any Pages. Publicize cannot connect to Facebook Profiles, only published Pages. Not Connected - Site Address Likes Follows Comments @@ -964,7 +961,6 @@ Language: en_CA Create Site Search Domains This is where people will find you on the internet. - Choose a domain No available addresses matching your search Error communicating with the server, please try again There was a problem @@ -1413,7 +1409,6 @@ Language: en_CA 1 post with 1 file not uploaded (Untitled) \@%s - %1$f, %2$f Create site Tap to continue. Site created! @@ -1704,10 +1699,6 @@ Language: en_CA Draft Pending review Publish - Change Location - Remove Location - Can\'t open the Location Picker, Google Play Services is not available - Location Now Only those with this password can view this post Excerpts are optional hand-crafted summaries of your content. diff --git a/WordPress/src/main/res/values-en-rGB/strings.xml b/WordPress/src/main/res/values-en-rGB/strings.xml index 171854b49eef..ded4ea4d3c73 100644 --- a/WordPress/src/main/res/values-en-rGB/strings.xml +++ b/WordPress/src/main/res/values-en-rGB/strings.xml @@ -1,11 +1,33 @@ + File name + File block settings + Failed to upload files.\nPlease tap for options. + Failed to save files.\nPlease tap for options. + Edit file + Copy file URL + CHOOSE A FILE + Choose a domain + New + Jetpack settings + Jetpack + Following conversation + Follow conversation + Could not unsubscribe from comments for this post + Could not subscribe to comments for this post + Error fetching subscription status for post + Successfully unsubscribed from the comments + Successfully subscribed to the comments + Invalid response received + No response received + Clear + Apply One or more slides have not been added to your Story because Stories don\'t support GIF files at the moment. Please choose a static image or video background instead. GIF files not supported We couldn\'t find the media for this story on the site. @@ -41,7 +63,7 @@ Language: en_GB Scrollable block menu closed. Skip Choose - Pick your favourite homepage layout. You can customise or change it later. + Pick your favourite homepage layout. You can edit and customise it later. Choose a design Tap retry when you\'re back online, or create a blank page using the button below. Layouts not available while offline @@ -306,7 +328,6 @@ Language: en_GB %1$s · %2$s Try a starter layout Open Block Actions Menu - Insert mention Double tap to open Bottom Sheet with available options Double tap to open Action Sheet with available options We cannot open pages at the moment. Please try again later @@ -473,7 +494,6 @@ Language: en_GB Published The Facebook connection cannot find any Pages. Publicise cannot connect to Facebook Profiles, only published Pages. Not Connected - Site Address Likes Follows Comments @@ -971,7 +991,6 @@ Language: en_GB Create Site Search Domains This is where people will find you on the internet. - Choose a domain No available addresses matching your search Error communicating with the server, please try again There was a problem @@ -1422,7 +1441,6 @@ Language: en_GB 1 post with 1 file not uploaded (Untitled) \@%s - %1$f, %2$f Create site Tap to continue. Site created! @@ -1713,10 +1731,6 @@ Language: en_GB Draft Pending review Publish - Change Location - Remove Location - Can\'t open the Location Picker, Google Play Services is not available - Location Now Only those with this password can view this post Excerpts are optional hand-crafted summaries of your content. diff --git a/WordPress/src/main/res/values-es-rCL/strings.xml b/WordPress/src/main/res/values-es-rCL/strings.xml index e9d693764c57..51e6e00a4882 100644 --- a/WordPress/src/main/res/values-es-rCL/strings.xml +++ b/WordPress/src/main/res/values-es-rCL/strings.xml @@ -116,7 +116,6 @@ Language: es_CL Buscar Dominios Aquí es donde la gente te encontrará en Internet. Hubo un problema - Elige un nombre de dominio para tu sitio No hay direcciones disponibles que coincidan con tu búsqueda Error al comunicarse con el servidor, inténtalo de nuevo Hubo un problema @@ -548,7 +547,6 @@ Language: es_CL %1$d entradas no subidas (Sin título) \@%s - %1$f, %2$f 1 página con 1 archivo no subido %1$d entradas/páginas con 1 archivo no subido %1$d páginas con 1 archivo no subido @@ -837,10 +835,6 @@ Language: es_CL Borrador Revisión pendiente Publicar - Cambiar Ubicación - No se puede abrir el selector de ubicación, los servicios de Google Play no están disponibles - Quitar Ubicación - Ubicación Ahora Sólo aquellos con esta contraseña pueden ver esta entrada Los extractos son resúmenes hechos a mano de tu contenido. diff --git a/WordPress/src/main/res/values-es-rCO/strings.xml b/WordPress/src/main/res/values-es-rCO/strings.xml index b626381dca2b..499117d25f5e 100644 --- a/WordPress/src/main/res/values-es-rCO/strings.xml +++ b/WordPress/src/main/res/values-es-rCO/strings.xml @@ -1,11 +1,61 @@ + Nombre del archivo + Ajustes del archivo del bloque + Fallo al subir los archivos.\nPor favor, toca para ver las opciones. + Fallo al guardar los medios.\nPor favor, toca para ver las opciones. + Editar el archivo + Copiar la URL del archivo + ELEGIR UN ARCHIVO + Elige un dominio + Nuevo + Ajustes de Jetpack + Jetpack + Siguiendo la conversación + Seguir la conversación + No se ha podido anular la suscripción a los comentarios de esta entrada + No se ha podido crear la suscripción a los comentarios de esta entrada + Error al recuperar el estado de suscripción para la entrada + Cancelada correctamente la suscripción a los comentarios + Suscrito correctamente a los comentarios + Respuesta recibida no válida + No se ha recibido ninguna respuesta + Vaciar + Aplicar + Una o más diapositivas no se han añadido a tu historia porque en este momento las historias no son compatibles con archivos GIF. Por favor, elige una imagen estática o un vídeo de fondo en su lugar. + Los archivos GIF no son compatibles + No hemos podido encontrar en el sitio los medios para esta historia. + No se puede editar la historia + No ha sido posible subir medios a esta historia. Comprueba tu conexión a Internet e inténtalo de nuevo dentro de un momento. + No se puede editar la historia + Esta historia se ha editado en un dispositivo diferente y la posibilidad de editar ciertos objetos puede estar limitada. + Edición limitada de la historia + Los medios han sido eliminados. Intenta editar tu historia. + Fondo + Texto + Descartar + Cualquier cambio realizado no se guardará. + ¿Descartar los cambios? + Hecho + Siguiente + Borrar + Ha habido un error al seleccionar el diseño. + Por favor, revisa tu conexión a Internet e inténtalo de nuevo. + Toca en reintentar cuando vuelvas a estar conectado. + Los diseños no están disponibles sin conexión + Continuar con las credenciales de la tienda + Encuentra tu correo electrónico conectado + Seguir temáticas + Intenta seguir más temáticas para ampliar la búsqueda + No hay entradas recientes + ¡Bienvenido! + Explorar <b>Juan Gómez</b> respondió a tu publicación Hoy has recibido <b>50 me gusta</b> en tu sitio A <b>Madison Ruíz</b> le ha gustado tu entrada @@ -13,7 +63,7 @@ Language: es_CO Se ha cerrado el menú de bloques desplazable. Omitir Elegir - Elige tu diseño de página de inicio favorito. Puedes personalizarlo o cambiarlo más tarde. + Elige tu diseño favorito de página de inicio. Puedes editarlo y personalizarlo más tarde. Elige un diseño Toca «Reintentar» cuando vuelvas a estar en línea o crea una página en blanco usando el botón a continuación. Los diseños no están disponibles sin conexión @@ -68,6 +118,7 @@ Language: es_CO Elige desde la biblioteca de medios de WordPress Volver Primeros pasos + Sigue temáticas para descubrir nuevos blogs Por Este referido no puede ser marcado como spam Desmarcar como spam @@ -277,7 +328,6 @@ Language: es_CO %1$s · %2$s Prueba un diseño de inicio Abrir el menú de acciones de bloques - Insertar una mención Toca dos veces para abrir la hoja inferior con las opciones disponibles Toca dos veces para abrir la hoja de acción con las opciones disponibles No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde @@ -444,7 +494,6 @@ Language: es_CO Publicada La conexión de Facebook no puede encontrar ninguna página. «Divulgar» no se puede conectar con los perfiles de Facebook, solo con las páginas publicadas. No conectado - Dirección del sitio Me gusta Seguimientos Comentarios @@ -942,7 +991,6 @@ Language: es_CO Crear sitio Buscar dominios Aquí es donde la gente te encontrará en Internet. - Selecciona un nombre de dominio para tu sitio No hay direcciones disponibles que coincidan con tu búsqueda Error durante la comunicación con el servidor. Inténtalo de nuevo Hubo un problema @@ -1393,7 +1441,6 @@ Language: es_CO 1 entrada con 1 archivo sin subir (sin título) \@%s - %1$f, %2$f Crear sitio Toca para continuar. ¡Sitio creado! @@ -1684,10 +1731,6 @@ Language: es_CO Borrador Pendiente de revisión Publicar - Cambiar ubicación - Borrar ubicación - No se ha podido abrir el selector de ubicación, no disponible Google Play Services - Ubicación Ahora Solo los que tengan esta contraseña pueden ver esta entrada Los extractos son resúmenes opcionales del contenido hechos a mano. diff --git a/WordPress/src/main/res/values-es-rMX/strings.xml b/WordPress/src/main/res/values-es-rMX/strings.xml index 5ec47236279b..6abc1583463d 100644 --- a/WordPress/src/main/res/values-es-rMX/strings.xml +++ b/WordPress/src/main/res/values-es-rMX/strings.xml @@ -1,11 +1,61 @@ + ELEGIR UN ARCHIVO + Copiar la URL del archivo + Editar el archivo + Fallo al guardar los medios.\nPor favor, toca para ver las opciones. + Fallo al subir los archivos.\nPor favor, toca para ver las opciones. + Ajustes del archivo del bloque + Nombre del archivo + Cancelada correctamente la suscripción a los comentarios + Error al recuperar el estado de suscripción para la entrada + No se ha podido crear la suscripción a los comentarios de esta entrada + No se ha podido anular la suscripción a los comentarios de esta entrada + Seguir la conversación + Siguiendo la conversación + Jetpack + Ajustes de Jetpack + Nuevo + Elige un dominio + Aplicar + Vaciar + No se ha recibido ninguna respuesta + Respuesta recibida no válida + Suscrito correctamente a los comentarios + Una o más diapositivas no se han añadido a tu historia porque en este momento las historias no son compatibles con archivos GIF. Por favor, elige una imagen estática o un video de fondo en su lugar. + Esta historia se ha editado en un dispositivo diferente y la posibilidad de editar ciertos objetos puede estar limitada. + No se puede editar la historia + No ha sido posible subir medios a esta historia. Comprueba tu conexión a Internet e inténtalo de nuevo dentro de un momento. + No se puede editar la historia + No hemos podido encontrar en el sitio los medios para esta historia. + Los archivos GIF no son compatibles + Los medios han sido eliminados. Intenta editar tu historia. + Edición limitada de la historia + Los diseños no están disponibles sin conexión + Toca en reintentar cuando vuelvas a estar conectado. + Por favor, revisa tu conexión a Internet e inténtalo de nuevo. + Ha habido un error al seleccionar el diseño. + Borrar + Siguiente + Hecho + ¿Descartar los cambios? + Cualquier cambio realizado no se guardará. + Descartar + Texto + Fondo + Explorar + ¡Bienvenido! + No hay entradas recientes + Intenta seguir más temáticas para ampliar la búsqueda + Seguir temáticas + Encuentra tu correo electrónico conectado + Continuar con las credenciales de la tienda A <b>Madison Ruíz</b> le ha gustado tu entrada Hoy has recibido <b>50 me gusta</b> en tu sitio <b>Juan Gómez</b> ha respondido en tu entrada @@ -13,7 +63,7 @@ Language: es_MX Se ha cerrado el menú de bloques desplazable. Omitir Elegir - Elige tu layout de página de inicio favorito. Puedes personalizarlo o cambiarlo más tarde. + Elige tu layout favorito de página de inicio. Puedes editarlo y personalizarlo más tarde. Elige un diseño Los layouts no están disponibles debido a un error Añadir categoría @@ -69,6 +119,7 @@ Language: es_MX Volver por Primeros pasos + Sigue temáticas para descubrir nuevos blogs Subiendo medios Subiendo medios de inventarios Subiendo medios GIF @@ -279,7 +330,6 @@ Language: es_MX Abrir el menú de acciones de bloques Toca dos veces pata abrir la hoja de acción con las opciones disponibles Toca dos veces para abrir la hoja inferior con las opciones disponibles - Insertar una mención La página de inicio seleccionada y la página de entradas no pueden ser la misma. Blog clásico Página de inicio estática @@ -444,7 +494,6 @@ Language: es_MX Publicada La conexión de Facebook no puede encontrar ninguna página. «Divulgar» no se puede conectar con los perfiles de Facebook, solo con las páginas publicadas. No conectado - Dirección del sitio Me gusta Seguimientos Comentarios @@ -942,7 +991,6 @@ Language: es_MX Buscar Dominios Aquí es donde la gente te encontrará en el internet. Limpiar - Elige un nombre de dominio para tu sitio No hay direcciones disponibles que coincidan con tu búsqueda Error al comunicarse con el servidor, por favor inténtalo de nuevo Hubo un problema @@ -1393,7 +1441,6 @@ Language: es_MX 1 entrada con 1 archivo sin subir (sin título) \@%s - %1$f, %2$f Crear sitio Toca para continuar. ¡Sitio creado! @@ -1684,10 +1731,6 @@ Language: es_MX Privada Pendiente de revisión Publicar - Cambiar ubicación - Borrar ubicación - No se ha podido abrir el selector de ubicación, no disponible Google Play Services - Ubicación Ahora Solo los que tengan esta contraseña pueden ver esta entrada Los extractos son resúmenes opcionales del contenido hechos a mano. diff --git a/WordPress/src/main/res/values-es-rVE/strings.xml b/WordPress/src/main/res/values-es-rVE/strings.xml index eda7c8de5676..fd8790803f8c 100644 --- a/WordPress/src/main/res/values-es-rVE/strings.xml +++ b/WordPress/src/main/res/values-es-rVE/strings.xml @@ -1,11 +1,33 @@ + Nombre del archivo + Ajustes del archivo del bloque + Fallo al subir los archivos.\nPor favor, toca para ver las opciones. + Fallo al guardar los medios.\nPor favor, toca para ver las opciones. + Editar el archivo + Copiar la URL del archivo + ELEGIR UN ARCHIVO + Elige un dominio + Nuevo + Ajustes de Jetpack + Jetpack + Siguiendo la conversación + Seguir la conversación + No se ha podido anular la suscripción a los comentarios de esta entrada + No se ha podido crear la suscripción a los comentarios de esta entrada + Error al recuperar el estado de suscripción para la entrada + Cancelada correctamente la suscripción a los comentarios + Suscrito correctamente a los comentarios + Respuesta recibida no válida + No se ha recibido ninguna respuesta + Vaciar + Aplicar Una o más diapositivas no se han añadido a tu historia porque en este momento las historias no son compatibles con archivos GIF. Por favor, elige una imagen estática o un vídeo de fondo en su lugar. Los archivos GIF no son compatibles No hemos podido encontrar en el sitio los medios para esta historia. @@ -41,7 +63,7 @@ Language: es_VE Se ha cerrado el menú de bloques desplazable. Omitir Elegir - Elige tu diseño de página de inicio favorito. Puedes personalizarlo o cambiarlo más tarde. + Elige tu diseño favorito de página de inicio. Puedes editarlo y personalizarlo más tarde. Elige un diseño Toca «Reintentar» cuando vuelvas a estar en línea o crea una página en blanco usando el botón a continuación. Los diseños no están disponibles sin conexión @@ -306,7 +328,6 @@ Language: es_VE %1$s · %2$s Prueba un diseño de inicio Abrir el menú de acciones de bloques - Insertar una mención Toca dos veces para abrir la hoja inferior con las opciones disponibles Toca dos veces para abrir la hoja de acción con las opciones disponibles No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde @@ -473,7 +494,6 @@ Language: es_VE Publicada La conexión de Facebook no puede encontrar ninguna página. «Divulgar» no se puede conectar con los perfiles de Facebook, solo con las páginas publicadas. No conectado - Dirección del sitio Me gusta Seguimientos Comentarios @@ -971,7 +991,6 @@ Language: es_VE Crear sitio Buscar dominios Aquí es donde la gente te encontrará en Internet. - Selecciona un nombre de dominio para tu sitio No hay direcciones disponibles que coincidan con tu búsqueda Error durante la comunicación con el servidor. Inténtalo de nuevo Hubo un problema @@ -1422,7 +1441,6 @@ Language: es_VE 1 entrada con 1 archivo sin subir (sin título) \@%s - %1$f, %2$f Crear sitio Toca para continuar. ¡Sitio creado! @@ -1713,10 +1731,6 @@ Language: es_VE Borrador Pendiente de revisión Publicar - Cambiar ubicación - Borrar ubicación - No se ha podido abrir el selector de ubicación, no disponible Google Play Services - Ubicación Ahora Solo los que tengan esta contraseña pueden ver esta entrada Los extractos son resúmenes opcionales del contenido hechos a mano. diff --git a/WordPress/src/main/res/values-es/strings.xml b/WordPress/src/main/res/values-es/strings.xml index e0898006bc82..265cdb71806b 100644 --- a/WordPress/src/main/res/values-es/strings.xml +++ b/WordPress/src/main/res/values-es/strings.xml @@ -1,18 +1,40 @@ + Nombre del archivo + ELEGIR UN ARCHIVO + Copiar la URL del archivo + Editar el archivo + Fallo al guardar los medios.\nPor favor, toca para ver las opciones. + Fallo al subir los archivos.\nPor favor, toca para ver las opciones. + Ajustes del archivo del bloque + Elige un dominio + Nuevo + Ajustes de Jetpack + Jetpack + Siguiendo la conversación + Seguir la conversación + Cancelada correctamente la suscripción a los comentarios + Error al recuperar el estado de suscripción para la entrada + No se ha podido crear la suscripción a los comentarios de esta entrada + No se ha podido anular la suscripción a los comentarios de esta entrada + Suscrito correctamente a los comentarios + Respuesta recibida no válida + No se ha recibido ninguna respuesta + Vaciar + Aplicar Una o más diapositivas no se han añadido a tu historia porque en este momento las historias no son compatibles con archivos GIF. Por favor, elige una imagen estática o un vídeo de fondo en su lugar. - Los archivos GIF no son compatibles - No hemos podido encontrar en el sitio los medios para esta historia. No se puede editar la historia No ha sido posible subir medios a esta historia. Comprueba tu conexión a Internet e inténtalo de nuevo dentro de un momento. No se puede editar la historia Esta historia se ha editado en un dispositivo diferente y la posibilidad de editar ciertos objetos puede estar limitada. + No hemos podido encontrar en el sitio los medios para esta historia. + Los archivos GIF no son compatibles Edición limitada de la historia Los medios han sido eliminados. Intenta editar tu historia. Fondo @@ -34,14 +56,14 @@ Language: es No hay entradas recientes ¡Bienvenido! Explorar - <b>Juan Gómez</b> ha respondido en tu entrada - Hoy has recibido <b>50 me gusta</b> en tu sitio A <b>Madison Ruíz</b> le ha gustado tu entrada + Hoy has recibido <b>50 me gusta</b> en tu sitio + <b>Juan Gómez</b> ha respondido en tu entrada Se ha abierto el menú de bloques desplazable. Selecciona un bloque. Se ha cerrado el menú de bloques desplazable. Omitir Elegir - Elige el diseño de página de inicio que prefieras. Puedes personalizarlo o cambiarlo más adelante. + Elige el diseño de página de inicio que prefieras. Puedes personalizarlo o cambiarlo más tarde. Elige un diseño Toca «Reintentar» cuando vuelvas a estar en línea o crea una página en blanco usando el botón a continuación. Los diseños no están disponibles sin conexión @@ -68,49 +90,49 @@ Language: es Inspírate Sigue tus sitios favoritos y descubre nuevas lecturas. Observa cómo crece tu audiencia con analíticas avanzadas. - Mira los comentarios y avisos en tiempo real. Con el potente editor puedes publicar sobre la marcha. Bienvenido al maquetador web más popular del mundo. + Mira los comentarios y avisos en tiempo real. La carga del medio ha fallado Sitios a seguir - Estamos trabajando duro para añadir más bloques con cada versión. «%s» no es totalmente compatible - Botón de ayuda - Editar usando el editor web - Elegir las imágenes - Crear una entrada de historia + Estamos trabajando duro para añadir más bloques con cada versión. Son publicados como una nueva entrada de blog en tu sitio para que tu audiencia nunca se pierda nada. - Las entradas de historias no desaparecen + Crear una entrada de historia + Elegir las imágenes + Editar usando el editor web + Botón de ayuda Combina fotos, vídeos y texto para crear entradas de historias atractivas y accesibles que les encantarán a tus visitantes. - Ahora las historias son para todos - Título de la entrada de historia - Cómo crear una entrada de historias - Tienes acceso anticipado a las entradas de historias y nos encantaría que las probaras. - Presentación de las entradas de historias - Página en blanco creada - Página creada - Vista previa del diseño + Las entradas de historias no desaparecen %1$s ha denegado el acceso a tus fotos. Para corregirlo, edita tus permisos y activa %2$s y %3$s. - Inserción del medio fallida. - Ha fallado la inserción del medio: %s + Vista previa del diseño + Página creada + Página en blanco creada + Presentación de las entradas de historias + Tienes acceso anticipado a las entradas de historias y nos encantaría que las probaras. + Cómo crear una entrada de historias + Título de la entrada de historia + Ahora las historias son para todos Elige desde la biblioteca de medios de WordPress + Ha fallado la inserción del medio: %s + Inserción del medio fallida. Volver + por Primeros pasos Sigue temáticas para descubrir nuevos blogs - por - Este referido no puede ser marcado como spam - Desmarcar como spam - Marcar como spam - Abrir la web - Subiendo medios GIF - Subiendo medios de inventarios Subiendo medios - Seleccionar un elemento + Subiendo medios de inventarios + Subiendo medios GIF + Abrir la web + Marcar como spam + Desmarcar como spam + Este referido no puede ser marcado como spam Busca o escribe la URL + Seleccionar un elemento Añadir este enlace de teléfono - Añadir este enlace - Añadir este enlace de correo electrónico «No hay conexión a Internet.\nNo están disponibles las sugerencias.» + Añadir este enlace de correo electrónico + Añadir este enlace Negrita Moderno Alegre @@ -126,126 +148,126 @@ Language: es No se puede mostrar este comentario Navegar por elementos Informar de esta entrada - Bienvenido al Lector. Descubre millones de blogs a tu alcance. - Ha ocurrido un error interno del servidor - Tu acción no está permitida %1$s elementos más + Tu acción no está permitida + Ha ocurrido un error interno del servidor + Bienvenido al Lector. Descubre millones de blogs a tu alcance. Seleccionar un diseño Nota: el diseño de la columna puede variar entre temas y tamaños de pantalla - Crear una entrada o historia - Crear una página Crear una entrada - \@string/contact_support - Puede que te guste + Crear una página + Crear una entrada o historia Ocultar - Leyenda del vídeo. Vacía - Actualiza el título. - Pegar el bloque después - Título de la página. %s - Título de la página. Vacío - Ha ocurrido un error al reproducir tu vídeo - Este dispositivo no es compatible con la API de Camera2 - No se ha podido guardar el vídeo - Error al guardar la imagen + Puede que te guste + \@string/contact_support + Ver el almacenamiento Operación en progreso, inténtalo de nuevo + Error al guardar la imagen + No se ha podido guardar el vídeo + Este dispositivo no es compatible con la API de Camera2 + Ha ocurrido un error al reproducir tu vídeo + Título de la página. Vacío + Título de la página. %s + Pegar el bloque después + Actualiza el título. + Leyenda del vídeo. Vacía No se ha podido encontrar la diapositiva de la historia - Ver el almacenamiento - Tenemos que guardar la historia en tu dispositivo antes de que pueda ser publicada. Revisa tus ajustes de almacenamiento y elimina archivos para ganar espacio. - Insuficiente almacenamiento en el dispositivo - Intenta volver a guardar o borrar las diapositivas y, después, intenta volver a publicar tu historia. - No se han podido guardar %1$d diapositivas - No se ha podido guardar 1 diapositiva - Gestionar - %1$d diapositivas necesitan una acción 1 diapositiva necesita una acción - No se ha podido subir «%1$s» - No se ha podido subir «%1$s» - Publicado «%1$s» + %1$d diapositivas necesitan una acción + Gestionar + No se ha podido guardar 1 diapositiva + No se han podido guardar %1$d diapositivas + Intenta volver a guardar o borrar las diapositivas y, después, intenta volver a publicar tu historia. + Insuficiente almacenamiento en el dispositivo + Tenemos que guardar la historia en tu dispositivo antes de que pueda ser publicada. Revisa tus ajustes de almacenamiento y elimina archivos para ganar espacio. Subiendo «%1$s»… - Quedan %1$d diapositivas - Queda 1 diapositiva - varias historias + Publicado «%1$s» + No se ha podido subir «%1$s» + No se ha podido subir «%1$s» Guardando «%1$s»… - Sin título - Descartar - La entrada de tu historia no se guardará como borrador. - ¿Descartar la entrada de la historia? - Borrar - Esta diapositiva aún no ha sido guardada. Si borras esta diapositiva, perderás cualquier edición que hayas hecho. - Esta diapositiva será eliminada de tu historia. - ¿Borrar la diapositiva de la historia? - Cambiar el color del texto - Cambiar la alineación del texto - con error - seleccionado + varias historias + Queda 1 diapositiva + Quedan %1$d diapositivas sin seleccionar - Diapositiva - Reintentar - Guardado - Cerrar - Compartir con - COMPARTIR - Guardado en fotos - Reintentar - Guardado - Guardando - Flash - Girar - Sonido - Texto - Pegatinas + seleccionado + con error + Cambiar la alineación del texto + Cambiar el color del texto + ¿Borrar la diapositiva de la historia? + Esta diapositiva será eliminada de tu historia. + Esta diapositiva aún no ha sido guardada. Si borras esta diapositiva, perderás cualquier edición que hayas hecho. + Borrar + ¿Descartar la entrada de la historia? + La entrada de tu historia no se guardará como borrador. + Descartar + Sin título + Toca crear %1$s. %2$s Después selecciona <b>Entrada del blog</b> + Pon un título a tu historia + Empieza eligiendo entre una amplia variedad de diseños de página prefabricados. O simplemente empieza con una página en blanco. + Crear una página en blanco + Crear una página + Vista previa + Capturar Flash + Pegatinas + Texto + Sonido Girar la cámara - Capturar - Vista previa - Crear una página - Crear una página en blanco - Empieza eligiendo entre una amplia variedad de diseños de página prefabricados. O simplemente empieza con una página en blanco. - Elegir un diseño - Pon un título a tu historia - Crear una entrada o historia + Girar + Flash + Guardando + Guardado + Reintentar + Guardado en fotos + COMPARTIR + Compartir con + Cerrar + Guardado + Reintentar + Diapositiva Crear una entrada, página o historia - Toca crear %1$s. %2$s Después selecciona <b>Entrada del blog</b> - Elegir el dispositivo + Crear una entrada o historia + Elegir un diseño + Cuota de almacenamiento superada + No se puede subir el archivo.\nSe ha superado la cuota de almacenamiento. + No se ha podido encontrar el salto de página enlazado Entrada de la historia + Elegir el dispositivo Para la edición de los iconos del sitio en sitios WordPress autoalojados se necesita el plugin Jetpack. - No se ha podido encontrar el salto de página enlazado - No se puede subir el archivo.\nSe ha superado la cuota de almacenamiento. - Cuota de almacenamiento superada Añadir un archivo - Reemplazar el vídeo Reemplazar la imagen o vídeo - Elegir un vídeo - Elegir una imagen o vídeo - Elegir una imagen + Reemplazar el vídeo + Si continúas con Google y aún no tienes una cuenta de WordPress.com, crearás una cuenta y aceptas nuestros %1$stérminos del servicio%2$s. + Confirmación del registro + Continuar con WordPress.com Bloque eliminado + Elegir una imagen + Elegir una imagen o vídeo + Elegir un vídeo Introduce la dirección de tu sitio existente - Continuar con WordPress.com - Confirmación del registro - Si continúas con Google y aún no tienes una cuenta de WordPress.com, crearás una cuenta y aceptas nuestros %1$stérminos del servicio%2$s. Si continúas, aceptas nuestros %1$stérminos del servicio%2$s. Te enviaremos por correo electrónico un enlace de registro para crear tu nueva cuenta de WordPress.com. Usaremos esta dirección de correo electrónico para crear tu nueva cuenta de WordPress.com. Te hemos enviado por correo electrónico un enlace de registro para crear tu nueva cuenta de WordPress.com. Comprueba tu correo electrónico en este dispositivo y toca el enlace en el correo electrónico que has recibido de WordPress.com. Introduce la información de tu cuenta para %1$s. - o - Continuar con Google - Encuentra la dirección de tu sitio - Hecho - ¿No ves el correo electrónico? Comprueba tu carpeta de spam o correo no deseado. Comprueba tu correo electrónico en este dispositivo y toca el enlace en el correo electrónico que has recibido de WordPress.com. + ¿No ves el correo electrónico? Comprueba tu carpeta de spam o correo no deseado. + Hecho + Encuentra la dirección de tu sitio + Continuar con Google + o Te enviaremos por correo electrónico un enlace que te hará acceder automáticamente, sin necesidad de contraseña. - Comprobar el correo electrónico - Primeros pasos - Introduce tu dirección de correo electrónico para acceder o crear una cuenta de WordPress.com. - O escribe tu contraseña - Crear una cuenta - Enviar el enlace por correo electrónico Restablecer tu contraseña + Enviar el enlace por correo electrónico + Crear una cuenta + O escribe tu contraseña + Introduce tu dirección de correo electrónico para acceder o crear una cuenta de WordPress.com. + Primeros pasos + Comprobar el correo electrónico Ha habido un problema al gestionar la solicitud. Por favor, inténtalo de nuevo más tarde. - Dale a tu sitio un nombre que refleje su personalidad y temática. ¡Las primeras impresiones cuentan! Configura el título de tu sitio Toca <b>%1$s</b> para configurar un nuevo título + Dale a tu sitio un nombre que refleje su personalidad y temática. ¡Las primeras impresiones cuentan! Al enviar esta entrada a la papelera también se descartarán los cambios locales, ¿estás seguro de que quieres continuar? Opciones del bloque %s Duplicar bloque @@ -258,9 +280,9 @@ Language: es Bloque copiado El título del sitio solo puede ser cambiado por un usuario con el perfil de administrador. El título del sitio se muestra en la barra de título de un navegador web y en la cabecera de la mayoría de los temas. - Tema No se ha podido actualizar el título del sitio. Comprueba tu conexión de red e inténtalo nuevamente. Cambios sin guardar + Tema Abrir el enlace en un navegador Navega para personalizar el degradado Navega al selector de color personalizado @@ -277,7 +299,6 @@ Language: es Descartar No establecido Las etiquetas ayudan a los lectores diciéndoles de qué se trata la entrada. - Fecha de publicación Añadir etiquetas Volver Guardar ahora @@ -289,6 +310,7 @@ Language: es Cancelar Mover a borrador Las entradas en la papelera no se pueden editar. ¿Deseas cambiar el estado de esta entrada a «borrador» para poder trabajar en ella? + Fecha de publicación ¿Mover entrada a borradores? Elige tus intereses Elige tus intereses @@ -306,47 +328,46 @@ Language: es %1$s · %2$s Prueba un diseño de inicio Abrir el menú de acciones de bloques - Insertar una mención - Toca dos veces para abrir la hoja inferior con las opciones disponibles Toca dos veces pata abrir la hoja de acción con las opciones disponibles - No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde - Establecer como página de entradas + Toca dos veces para abrir la hoja inferior con las opciones disponibles + La página de inicio seleccionada y la página de entradas no pueden ser la misma. + Blog clásico + Página de inicio estática + Página de entradas + Seleccionar la página Establecer como página de inicio - «No hay disponibles usuarios que coincidan.» + Establecer como página de entradas + No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde «%s no es un usuario válido» - Seleccionar la página - Página de entradas - Página de inicio estática - Blog clásico - La página de inicio seleccionada y la página de entradas no pueden ser la misma. - Ha fallado la actualización de la página de inicio, comprueba tu conexión a internet - No se pueden guardar los ajustes de la página de inicio antes de que las páginas estén cargadas - No se pueden guardar los ajustes de la página de inicio - Aceptar - Ha fallado la carga de las páginas - Elige entre una página de inicio que muestre tus últimas publicaciones (blog clásico) o una página fija/estática. + «No hay disponibles usuarios que coincidan.» Ajustes de la página de inicio + Elige entre una página de inicio que muestre tus últimas publicaciones (blog clásico) o una página fija/estática. + Ha fallado la carga de las páginas + Aceptar + No se pueden guardar los ajustes de la página de inicio + No se pueden guardar los ajustes de la página de inicio antes de que las páginas estén cargadas + Ha fallado la actualización de la página de inicio, comprueba tu conexión a internet + Para establecer la página de inicio, activa «Página de inicio estática» en los ajustes del sitio + Para establecer la página de entradas, activa «Página de inicio estática» en los ajustes del sitio + Página de inicio actualizada correctamente + Ha fallado la actualización de la página de inicio + Página de entradas actualizada correctamente Página de inicio Ha fallado la actualización de la página de entradas - Página de entradas actualizada correctamente - Ha fallado la actualización de la página de inicio - Página de inicio actualizada correctamente - Para establecer la página de entradas, activa «Página de inicio estática» en los ajustes del sitio - Para establecer la página de inicio, activa «Página de inicio estática» en los ajustes del sitio - Bienvenido a nuestro nuevo blog Seleccionar un color - Toca dos veces para ir a los ajustes del color + Bienvenido a nuestro nuevo blog Cuando sigas sitios, verás aquí su contenido + Toca dos veces para ir a los ajustes del color Saber más Qué hay de nuevo en WordPress Insertar %d recortar Fallo al cargar en el archivo, por favor, inténtalo de nuevo. Vista previa de la miniatura de la imagen - Usar este medio Usar este vídeo Elegir el medio Elegir el vídeo + Usar este medio No se ha podido seleccionar el sitio. Por favor, inténtalo de nuevo. Continuar Ha fallado reblog @@ -377,7 +398,6 @@ Language: es Cancelar la subida Ha habido un problema al gestionar la petición Funciona con Tenor - Buscar en Tenor Elegir desde Tenor Sábado Viernes @@ -386,15 +406,16 @@ Language: es Martes Lunes Domingo + Buscar en Tenor Ha fallado el acceso al contenido de un sitio privado. Algunos medios pueden no estar disponibles Accediendo al contenido de un sitio privado Fallo al recortar y guardar la imagen, por favor, inténtalo de nuevo. - Fallo al cargar la imagen.\nPor favor, toca para volver a intentarlo. Previsualizar la imagen Formato de página desconocido No hemos podido completar esta acción y no se ha enviado esta página a revisión. No hemos podido completar esta acción y no se ha programado esta página. No hemos podido completar esta acción y no se ha publicado esta página privada. + Fallo al cargar la imagen.\nPor favor, toca para volver a intentarlo. No hemos podido completar esta acción y no se ha publicado esta página. No hemos podido enviar esta página a revisión, pero lo intentaremos de nuevo más tarde. No hemos podido programar esta página, pero lo intentaremos de nuevo más tarde. @@ -409,20 +430,20 @@ Language: es Programaremos tu página cuando tu dispositivo vuelva a estar online. Enviaremos tu página para revisión cuando tu dispositivo vuelva a estar online. Publicaremos la página cuando tu dispositivo vuelva a estar online. + Has hecho cambios no guardados en esta página Página en espera Subiendo la página El dispositivo está desconectado. La página se ha guardado localmente. - Has hecho cambios no guardados en esta página Tu página se está subiendo - La página ha fallado al subir los medios y ha sido guardada localmente Página guardada en el dispositivo La página se ha guardado online - Selecciona un blog para el atajo a QuickPress - Establecido por el ahorrador de batería Oscuro Claro Apariencia Recientemente has hecho cambios en esta página, pero no los has guardado. Elige una versión para cargar:\n\n + Establecido por el ahorrador de batería + La página ha fallado al subir los medios y ha sido guardada localmente + Selecciona un blog para el atajo a QuickPress Lo que dice la gente Ofrecemos una gama de servicios para ayudarte a conseguir los resultados que buscas. ¿No estás seguro de lo que necesitas o de lo que cuesta? Podemos explicarte qué servicios son los adecuados para ti y decirte nuestros honorarios. Ponte en contacto con nosotros a continuación. Somos un pequeño equipo de profesionales con talento con una amplia gama de habilidades y experiencia. Nos encanta lo que hacemos y lo hacemos con pasión. Esperamos poder trabajar contigo. @@ -438,10 +459,10 @@ Language: es Estrategia Mostrar el contenido de la entrada Servicios - Samuel the Dog Sally Smith Nombre del proyecto Puesto o título del trabajo + Samuel the Dog Porfolio Mostrar solo el extracto Mi porfolio presenta varios proyectos creados a lo largo de mi carrera. Mira a continuación mi información de contacto y ponte en contacto. @@ -473,7 +494,6 @@ Language: es Publicada La conexión con Facebook no puede encontrar ninguna página. «Difundir» no puede conectar con perfiles de Facebook, solo con páginas publicadas. No conectado - Dirección del sitio Me gusta Seguimientos Comentarios @@ -483,27 +503,27 @@ Language: es Actividad Entradas y páginas General - Añadir una nueva tarjeta Añadir una nueva tarjeta de estadísticas + Añadir una nueva tarjeta Usa el botón de filtro para encontrar entradas sobre temas específicos Selecciona una etiqueta o sitio, ventana emergente Seleccionado Selecciona un sitio o etiqueta para filtrar entradas Quitar el filtro actual - Gestionar temas y sitios Acceder a WordPress.com - Accede a WordPress.com para ver las últimas entradas de los temas que sigues + Gestionar temas y sitios Accede a WordPress.com para ver las últimas entradas de los sitios que sigues + Accede a WordPress.com para ver las últimas entradas de los temas que sigues Vista previa de la plantilla Reemplazar el bloque actual Añadir al final Añadir al principio Añadir el bloque antes Añadir el bloque después - Añadir un tema Seguir un sitio - Puedes seguir entradas sobre un tema específico añadiendo un tema Mira las entradas más recientes de los sitios que sigues + Añadir un tema + Puedes seguir entradas sobre un tema específico añadiendo un tema Siguiendo Filtrar Leyenda del vídeo. %s @@ -515,10 +535,10 @@ Language: es Has escuchado todas las estadísticas de este período.\n Si vuelves a tocar, se reiniciará desde el principio. No hay estadísticas en este período. Actividad de publicación para %1$s - Los días con visitas %1$s para %2$s son: %2$s %3$s. Toca para más. explora todas las estadísticas para este período muy altas altas + Los días con visitas %1$s para %2$s son: %2$s %3$s. Toca para más. medias bajas   y %1$d %2$s @@ -551,23 +571,23 @@ Language: es No hemos podido acceder a tu sitio porque necesita <b>identificación HTTP</b>. Tendrás que contactar con tu alojamiento para solucionarlo. No hemos podido acceder en tu sitio al <b>archivo XMLRCP</b>. Tendrás que contactar con tu alojamiento para solucionarlo. ¡Ya casi estamos! Solo necesitamos verificar tu dirección de correo electrónico conectada a Jetpack <b>%1$s</b> - Accede con las credenciales del sitio. - Accede con las credenciales de tu sitio %1$s - Página del sitio Siguiendo - Me gusta - Descubrir - Guardado - Temas - Sitios - %sE - %sP - %sT - %sG - %sM - %sk + Página del sitio + Accede con las credenciales de tu sitio %1$s + Accede con las credenciales del sitio. No podemos abrir las entradas en este momento. Por favor, inténtalo de nuevo más tarde + %sk + %sM + %sT + Sitios + Guardado + Descubrir + Me gusta No podemos cargar los datos para tu sitio en este momento. Por favor, inténtalo de nuevo más tarde + %sG + %sP + %sE + Temas Biblioteca de medios de WordPress Desagrupar Traducir @@ -582,8 +602,8 @@ Language: es Mostrar la sección Bloque %s. Este bloque tiene contenido no válido Bloque %s. Vacío - Cortar bloque Restablecer el bloque + Cortar bloque Eliminar las notas Problema al abrir el vídeo Problema al mostrar el bloque @@ -710,8 +730,8 @@ Language: es Archivo Descargas de archivos Las estadísticas de descarga de archivos no se registraron antes del 28 de Junio de 2019. - Zona horaria del sitio (UTC -%s) Zona horaria del sitio (UTC +%s) + Zona horaria del sitio (UTC -%s) Zona horaria del sitio (UTC) Escritorio Por defecto @@ -720,9 +740,9 @@ Language: es Compartir Volver Avanzar - «%s» programado para publicar el «%s» en tu aplicación de WordPress\n%s Entrada programada de WordPress: «%s» «%s» se publicará en 10 minutos + «%s» programado para publicar el «%s» en tu aplicación de WordPress\n%s «%s» se publicará en 1 hora «%s» ha sido publicado Entrada programada: recordatorio de 10 minutos @@ -732,9 +752,9 @@ Language: es Cuando se publique 10 minutos antes 1 hora antes - Desactivado Añadir al calendario Aviso + Desactivado Fecha y hora ¿Necesitas ayuda para encontrar el correo electrónico con el que te conectaste? La web en esa dirección no es un sitio WordPress. Para conectarnos a él, el sitio debe tener instalado WordPress. @@ -746,15 +766,15 @@ Language: es Elemento contraído Elemento expandido Contraer - Ampliar Gráfico actualizado. %1$s %2$s del período: %3$s, cambio desde el período anterior - %4$s Cargando los datos de la tarjeta seleccionada Editor - Ampliar + Ampliar Cerrar Verifica tu dirección de correo electrónico - las instrucciones se enviaron a tu correo electrónico Verifica tu dirección de correo electrónico - las instrucciones se enviaron a %s + Ampliar Cancelar Aceptar http(s):// @@ -787,18 +807,18 @@ Language: es Histórico Visitas esta semana Añadir widget - Está tardando más tiempo del normal recargar los detalles del plugin. Por favor, compruébalo de nuevo más tarde. Si acabas de registrar un nombre de dominio, por favor, espera hasta que terminemos de configurarlo e inténtalo de nuevo.\n\nEn caso contrario, parece que algo fue mal y la característica del plugin podría no estar disponible para este sitio. + Está tardando más tiempo del normal recargar los detalles del plugin. Por favor, compruébalo de nuevo más tarde. Estado (no disponible) Al registrar este dominio aceptas nuestros %1$stérminos y condiciones%2$s Comprueba tu conexión a la red e inténtalo de nuevo. No se ha podido cargar esta página en este momento. - No se pudieron recuperar los ajustes. Algunas APIs no están disponibles para la cuenta e ID de esta aplicación OAuth. Al configurar Jetpack aceptas nuestros %1$stérminos y condiciones%2$s + No se pudieron recuperar los ajustes. Algunas APIs no están disponibles para la cuenta e ID de esta aplicación OAuth. No hay ninguna conexión. La edición está desactivada. - Para volver a conectar la aplicación con tu sitio alojado, introduce aquí la nueva contraseña del sitio. Contraseña actualizada Actualizar contraseña + Para volver a conectar la aplicación con tu sitio alojado, introduce aquí la nueva contraseña del sitio. Registrando el nombre de dominio… Selecciona la provincia Selecciona el país @@ -832,35 +852,35 @@ Language: es Fallo al insertar los medios.\nPor favor, toca para volver a intentarlo. Tu borrador se está subiendo Subiendo borrador - Borradores Ocurrió un error mientras se restauraba la entrada - Retroceder a: %s - Solo ves las estadísticas más relevantes. Añade y organiza tus detalles abajo. + Borradores Social Estadísticas anuales del sitio - Seguidores totales + Registrar dominio + Ahora que está instalado Jetpack, solo necesitamos que lo configures. Esto solo te llevará un minuto. + Solo ves las estadísticas más relevantes. Añade y organiza tus detalles abajo. + Retroceder a: %s No se pudieron cargar las sugerencias de dominios Teclea una palabra clave para más ideas No se han encontrado sugerencias - Registrar dominio - Ahora que está instalado Jetpack, solo necesitamos que lo configures. Esto solo te llevará un minuto. - Quitar de los detalles + Seguidores totales Mover abajo Mover arriba - Ajustes de los parámetros de las estadísticas - La entrada se está moviendo a borradores - La entrada se está restaurando - Entrada restaurada + Cambios locales La entrada se está enviando a la papelera + Entrada restaurada + La entrada se está restaurando + La entrada se está moviendo a borradores + Quitar de los detalles + Ajustes de los parámetros de las estadísticas Al enviar esta entrada a la papelera también se descartarán los cambios sin guardar, ¿estás seguro de querer continuar? - Cambios locales - Mover a borradores - Cambiar a la vista de lista - Cambiar a la vista de tarjetas - No tienes ninguna entrada en la papelera - No tienes ninguna entrada en borrador - No tienes ninguna entrada programada Aún no has publicado ninguna entrada + No tienes ninguna entrada programada + No tienes ninguna entrada en borrador + No tienes ninguna entrada en la papelera + Cambiar a la vista de tarjetas + Cambiar a la vista de lista + Mover a borradores Por favor, accede con tu nombre de usuario y contraseña. Por favor, accede usando tu nombre de usuario de WordPress.com en vez de tu dirección de correo electrónico. Promedio de palabras/entrada @@ -871,17 +891,16 @@ Language: es Total de comentarios Entradas Año - Este año El sitio de esta dirección no es un sitio WordPress. Para que nos podamos conectar el sitio debe usar WordPress. + Este año Fallo al comprobar los créditos de dominio disponibles Comprobando créditos de dominio Registrar dominio Para instalar plugins necesitas tener un dominio personalizado asociado a tu sitio. Instalar plugin - Podrás personalizar la apariencia de tu sitio más adelante + Publicado el: %s Publicar el: %s Programa para el: %s - Publicado el: %s Programado para el: %s Últimas semanas Vistas medias por dia @@ -889,19 +908,20 @@ Language: es Período Meses y años Cargar más + Podrás personalizar la apariencia de tu sitio más adelante Hoy Mejor hora Mejor día Estadísticas del: No, gracias - Más tarde Valorar ahora + Más tarde ¡Qué gusto verte de nuevo! Si estás trabajando con la aplicación nos encantaría que nos puntuases en la Google Play Store. ¿Estás disfrutando de WordPress? - Entrada devuelta a borrador - Actividad de publicación El sitio no se ha cargado todavía + Entrada devuelta a borrador Más entradas + Actividad de publicación Menos entradas Puedes perder lo que llevas hecho. ¿Estás seguro de que quieres salir? Ver los planes @@ -910,12 +930,12 @@ Language: es No podemos cargar los planes en este momento. Por favor, inténtalo de nuevo. No se pueden cargar los planes No hay conexión - Cambiar al editor de bloques - Cambiar al editor clásico Hubo un problema al cargar tus datos, recarga la página e inténtalo de nuevo. Datos no cargados Edita las nuevas entradas y páginas con el editor de bloques Usar editor de bloques + Cambiar al editor de bloques + Cambiar al editor clásico Editor de bloques activado salir %1$d de %2$d completo @@ -928,33 +948,33 @@ Language: es Tus visitantes verán tu icono en su navegador. Añade un icono personalizado para conseguir un aspecto profesional y refinado. Toca en %1$s Plan %2$s para ver tu plan actual y otros planes disponibles Toca en %1$s Añadir página %2$s para crear una nueva página. - Toca en %1$s Páginas %2$s para continuar. Toca en %1$s Estadísticas %2$s para ver cómo está rindiendo tu sitio. Toca en %1$s Icono de tu sitio %2$s para subir uno nuevo Guarda en borrador y publica tu primera entrada. Te llevaremos por los básicos sobre cómo crear y hacer crecer tu sitio. Hemos realizado algunos cambios en tu lista de comprobación + Toca en %1$s Páginas %2$s para continuar. Hemos añadido más tareas para ayudarte a hacer crecer tu audiencia. Explorar planes Aprende sobre las herramientas de marketing y SEO de nuestros planes de pago. Activar compartir entradas Comparte automáticamente las nuevas entradas en tus cuentas de medios sociales. - Retoca fuentes, añade imágenes y más. Crea una nueva página Añade una página con contenido clave - una página «Acerca de» es un gran comienzo. + Retoca fuentes, añade imágenes y más. Revisa las estadísticas de tu sitio Mantente al día sobre el rendimiento de tu sitio. Explorar temas Explora docenas de opciones de diseño y descubre el que se ajuste a ti. - Eliminar los siguientes pasos ocultará todas las visitas guiadas de este sitio. Esta acción es irreversible. Quitar los siguientes pasos Quitar esto Enhorabuena por completar tu lista. Un trabajo bien hecho. + Eliminar los siguientes pasos ocultará todas las visitas guiadas de este sitio. Esta acción es irreversible. ¡Todas las tareas están completas! Saltar tarea contraer - ampliar Recordatorio + ampliar Elige el siguiente periodo Elige el periodo anterior %1$d%% de visitas @@ -967,23 +987,22 @@ Language: es Cancelar el asistente de creación de sitios Estamos creando tu nuevo sitio Hubo un problema - Crear sitio Crear sitio Buscar dominios Aquí es donde la gente te encontrará en Internet. - Selecciona un nombre de dominio para tu sitio + Crear sitio No hay direcciones disponibles que coincidan con tu búsqueda Error durante la comunicación con el servidor. Inténtalo de nuevo Hubo un problema Hubo un problema Esto nos ayuda a hacer recomendaciones. Pero no tienes que estar siempre ahí; ¡los sitios evolucionan! Cuéntanos qué tipo de sitio te gustaría crear + Conflicto de versiones ¡Se ha creado tu sitio! %1$d de %2$d Crear sitio Sugerencias actualizadas No se ha podido seleccionar el sitio auto-hospedado que acabas de añadir - Conflicto de versiones Activa los informes de errores automáticos para ayudarnos a mejorar el rendimiento de la app. Informes de errores Deshacer @@ -991,25 +1010,27 @@ Language: es Versión local descartada Actualizando contenido Descartar web - Descartar local + Resolver conflicto de sincronización Local\nGuardado el %s\n\nWeb\nGuardado el %s\n Este contenido tiene dos versiones en conflicto. Selecciona qué versión quieres descartar.\n - Resolver conflicto de sincronización + Descartar local No hay datos en este periodo Eliminar la ubicación de los medios No podemos abrir las estadísticas en este momento. Por favor, inténtalo de nuevo más tarde - Algunos medios fallan al cargar debido a un error de red. - Ningún medio coincide con tu búsqueda - ¡Busca para encontrar GIF para añadir a tu biblioteca de medios! - Vistas Autor Autores + LinkedIn + Google+ + Tumblr + Twitter + Facebook + Título + Ruta + Vistas Vistas Buscar término Buscar términos Vistas - Título - Vídeos Vistas País Paises @@ -1020,46 +1041,44 @@ Language: es Referente Referentes Entradas y páginas - Ruta - LinkedIn - Google+ - Tumblr - Twitter - Facebook Ver más Compartir entrada Crear entrada Han pasado %1$s desde que se publicó %2$s. Así es como ha funcionado la entrada hasta ahora: + Algunos medios fallan al cargar debido a un error de red. + Ningún medio coincide con tu búsqueda + ¡Busca para encontrar GIF para añadir a tu biblioteca de medios! + Vídeos + Etiquetas y categorías Han pasado %1$s desde que se publicó %2$s. Pon la bola a rodar y aumenta las vistas de las entradas compartiendo tu entrada: Aún no has publicado ninguna entrada. Una vez que empieces a publicar, el resumen de tu última entrada aparecerá aquí: - Etiquetas y categorías Histórico %1$s - %2$s + %1$s | %2$s + Autor + Autores + Correo electrónico + WordPress.com + Título + Título Seguidores + Seguidor + Total %1$s seguidores: %2$s Servicio - %1$s | %2$s Vistas Título Vistas - Título Comentarios - Título - Autor Entradas y páginas - Autores Desde - Seguidor - Total %1$s seguidores: %2$s - Correo electrónico - WordPress.com Gestionar datos Aún no se han añadido impresiones Aún no hay datos Menú de depuración Cambiando contraseña… - Tu contraseña debe tener al menos seis caracteres de longitud. Para hacerla más fuerte, usa letras mayúsculas y minúsculas, números y símbolos como ! \" ? $ % ^ & ). Contraseña cambiada con éxito Cambiar contraseña + Tu contraseña debe tener al menos seis caracteres de longitud. Para hacerla más fuerte, usa letras mayúsculas y minúsculas, números y símbolos como ! \" ? $ % ^ & ). Nombre (sin título) Vista previa HTML @@ -1068,7 +1087,6 @@ Language: es Anterior Siguiente %1$s utilizado - Por favor, introduce un sitio WordPress WordPress.com o autoalojado conectado a Jetpack Cargando revisión Revisión cargada Cargar @@ -1077,23 +1095,24 @@ Language: es Aún no hay histórico Cuando haces cambios a tu entrada podrás ver aquí el histórico Cuando haces cambios a tu página podrás ver aquí el histórico + Por favor, introduce un sitio WordPress WordPress.com o autoalojado conectado a Jetpack Avatar del usuario Tamaño completo Grande Mediano Miniatura Historia - La página seleccionada no está disponible Pendiente de revisión + La página seleccionada no está disponible No tienes ninguna página en la papelera No tienes ninguna página programada - No tienes ninguna página en borrador Todavía no has publicado ninguna página Buscar páginas Ninguna página coincide con tu búsqueda Borrar permanentemente Mover a la papelera Mover a borradores + No tienes ninguna página en borrador Hacer superior Ver En la papelera @@ -1122,57 +1141,57 @@ Language: es Ver tu sitio Toca en %1$s Ver sitio %2$s para previsualizar tu sitio Comparte tu sitio + Conecta a tus cuentas de medios sociales - tu sitio compartirá automáticamente las nuevas entradas. Toca en %1$s Compartir %2$s para continuar Toca en %1$s Conexiones %2$s para añadir tus cuentas de medios sociales - Conecta a tus cuentas de medios sociales - tu sitio compartirá automáticamente las nuevas entradas. Publica una entrada Toca en %1$s Crear entrada %2$s para crear una nueva entrada ¿Quieres un poco de ayuda para empezar? Acepto Nunca - No gracias Sigue otros sitios Toca en %1$s Buscar %2$s para buscar sitios con intereses similares Toca en %1$s Lector %2$s para seguir - Descubre sitios que te inspiren, y síguelos para obtener actualizaciones cuando publiquen. Personaliza tu sitio Toca en %1$s Temas %2$s para seguir Toca en %1$s Personalizar %2$s para empezar a personalizar tu sitio - Elige un tema - Toca en %1$s Temas %2$s para descubrir nuevos temas - Revisa todos nuestros temas para encontrar el que se te ajuste a la perfección + No gracias + Descubre sitios que te inspiren, y síguelos para obtener actualizaciones cuando publiquen. Ir Cancelar Ahora no - Más No tienes sitios + Elige un tema + Revisa todos nuestros temas para encontrar el que se te ajuste a la perfección + Más + Toca en %1$s Temas %2$s para descubrir nuevos temas Temas no seguidos Añade aquí temas para descubrir entradas sobre tus temáticas favoritas - Accede a la cuenta de WordPress.com que usaste para conectar Jetpack. + Jetpack + FAQ de Jetpack + Instala Jetpack + Jetpack instalado + Instalando Jetpack Reintentar - Configurar - Jetpack no se pudo instalar en este momento. + Accede a la cuenta de WordPress.com que usaste para conectar Jetpack. Hubo un problema - Jetpack instalado Instalando Jetpack en tu sitio. Esto puede llevar unos minutos completarse. - Instalando Jetpack Las credenciales de tu web no se almacenarán, y solo se utilizan para instalar Jetpack. - Instala Jetpack - Jetpack - FAQ de Jetpack + Configurar + Jetpack no se pudo instalar en este momento. Para usar las estadísticas en tu sitio WordPress necesitas instalar el plugin Jetpack. No hay temas que coincidan con tu búsqueda ¿Que te gustaría encontrar? No hay etiquetas que coincidan con tu búsqueda No tienes ninguna etiqueta - Añade aquí las etiquetas que uses frecuentemente para poder seleccionarlas rápidamente al etiquetar tus entradas Crea una etiqueta No hay medios que coincidan con tu búsqueda ¿Salir de WordPress? + Añade aquí las etiquetas que uses frecuentemente para poder seleccionarlas rápidamente al etiquetar tus entradas Tienes cambios en entradas que no se han subido a tu sitio. Salir ahora borrará esos cambios de tu dispositivo. ¿Quieres salir de todos modos? - No hay lectores aún - No hay seguidores por correo electrónico aún No hay seguidores aún + No hay seguidores por correo electrónico aún + No hay lectores aún No hay usuarios aún Las entradas que te gusten aparecerán aquí Nada que te gustó aún @@ -1194,200 +1213,200 @@ Language: es imagen destacada Descartar foto de perfil - Dato transitorio + WordPress + Correo electrónico de contacto Correo electrónico Por favor, introduce tu dirección de correo electrónico - Para continuar, por favor, introduce tu dirección de correo electrónico y nombre - Nuevo mensaje de «Ayuda y soporte» - WordPress No establecido - Correo electrónico de contacto + Para continuar, por favor, introduce tu dirección de correo electrónico y nombre + Rebobinado en curso + Rebobinar sitio Registro de la aplicación + Dato transitorio Mis tickets - ¿Quieres rebobinar tu sitio al %1$s a las %2$s? Esto borrará todo el contenido y opciones creadas o cambiadas desde entonces. - Rebobinar sitio - Rebobinado en curso Rebobinando a %1$s %2$s + ¿Quieres rebobinar tu sitio al %1$s a las %2$s? Esto borrará todo el contenido y opciones creadas o cambiadas desde entonces. + Nuevo mensaje de «Ayuda y soporte» Actualmente restaurando tu sitio + Botón de acción del registro de actividad Tu sitio ha sido restaurado satisfactoriamente - Tu sitio ha sido restaurado satisfactoriamente\nRebobinado a %1$s %2$s Tu sitio está siendo restaurado\nRebobinando a %1$s %2$s - Botón de acción del registro de actividad + Tu sitio ha sido restaurado satisfactoriamente\nRebobinado a %1$s %2$s Gestionado automáticamente Guarda esta entrada y vuelve cuando quieras para leerla. Solo estará disponible en este dispositivo — las entradas guardadas no se sincronizan con otros dispositivos. - Guardar entradas para más tarde - No ha sido posible realizar la búsqueda No se han encontrado resultados - Lee la entrada de origen + No ha sido posible realizar la búsqueda + Guardar entradas para más tarde Sitios + Lee la entrada de origen Enlace mágico enviado Registro por correo electrónico Verificación del código Credenciales de acceso Enlace mágico enviado Acceso por enlace mágico - Acceso mediante la dirección del sitio Acceso mediante dirección de correo electrónico + Acceso mediante la dirección del sitio Alternativamente: Toca %s para guardar una entrada en tu lista. - ¡Aún no hay entradas guardadas! Entrada guardada Ver todas Guardada Guardar Borrada de las entradas guardadas - Añadir a las entradas guardadas Entradas guardadas Borrado - Cambiar icono del sitio + ¡Aún no hay entradas guardadas! + Añadir a las entradas guardadas Cancelar - Eliminar Cambiar - No tienes permiso para editar el icono del sitio. - No tienes permiso para añadir un icono al sitio. + Cambiar icono del sitio + Activar ¿Cómo te gustaría editar el icono? - ¿Te gustaría añadir un icono de sitio? + Eliminar Icono del sitio este sitio - Activar - ¿Activar avisos para %1$s%2$s%3$s? - Activar los avisos del sitio - Desactivar los avisos del sitio - Icono de Jetpack - Rebobinar - Evento + No tienes permiso para añadir un icono al sitio. + No tienes permiso para editar el icono del sitio. + ¿Te gustaría añadir un icono de sitio? + Actividad Icono de actividad Registro de actividad - Actividad + Recopilar información + Política de cookies + ¿Activar avisos para %1$s%2$s%3$s? + Evento + Icono de Jetpack + Política de privacidad + Ajustes de privacidad Lee la política de privacidad - Usamos otras herramientas de seguimiento, incluidas algunas de terceros. Lee acerca de estas y cómo controlarlas. + Rebobinar Política de terceros - Esta información nos ayuda a mejorar nuestros productos, hacer que el marketing sea más relevante, personalizar tu experiencia en WordPress.com y más, tal como se detalla en nuestra política de privacidad. - Política de privacidad + Desactivar los avisos del sitio + Activar los avisos del sitio + Usamos otras herramientas de seguimiento, incluidas algunas de terceros. Lee acerca de estas y cómo controlarlas. Comparte información con nuestra herramienta de análisis acerca del uso que haces de los servicios mientras estás conectado a tu cuenta de WordPress.com. - Política de cookies - Ajustes de privacidad - Recopilar información + Esta información nos ayuda a mejorar nuestros productos, hacer que el marketing sea más relevante, personalizar tu experiencia en WordPress.com y más, tal como se detalla en nuestra política de privacidad. Entrada enviada ¿No tienes una cuenta? %1$s Regístrate %2$s Una característica del plugin requiere que el sitio esté en buen estado. Una característica del plugin necesita que la suscripción del dominio principal esté asociada con este usuario. - Una característica del plugin necesita privilegios de administrador. El plugin no puede instalarse en sitios VIP. El plugin no se puede instalar debido a las limitaciones de espacio del disco. - Una característica del plugin requiere una dirección de correo electrónico verificada. - Una característica del plugin requiere que el sitio sea público. Una característica del plugin requiere un plan business. Una característica del plugin requiere un dominio personalizado. + Una característica del plugin necesita privilegios de administrador. + Una característica del plugin requiere una dirección de correo electrónico verificada. + Una característica del plugin requiere que el sitio sea público. Estamos haciendo la configuración final, está casi listo… Instalando plugin… Instalar Instalar el primer plugin en tu sitio puede llevar hasta 1 minuto. Durante este tiempo no podrás realizar cambios en tu sitio. Instalar plugin - Avisos Enviarme nuevos comentarios por correo electrónico - Semanalmente Instantáneamente - Diariamente Entradas nuevas - Recibe avisos de las nuevas entradas de este sitio Enviarme nuevas entradas por correo electrónico + Semanalmente + Diariamente + Avisos + Recibe avisos de las nuevas entradas de este sitio Todos mis sitios seguidos Sitios seguidos - Dispositivo de lectura personal con avisos Gente mirando gráficos y tablas %s en %s ¿Seguro que quieres eliminar definitivamente esta publicación? + Dispositivo de lectura personal con avisos Importante General Utilizar esta foto %1$d de %2$d Fotografías facilitadas por %s Busca para encontrar fotografías gratuitas para añadir a tu biblioteca de medios - Búsqueda en la biblioteca de fotos gratuitas Selecciona de la biblioteca gratuita de fotos No se puede guardar un borrador vacío - %1$s de ilimitado Vista previa %d Añadir %d + %1$s de ilimitado + Búsqueda en la biblioteca de fotos gratuitas Crear etiqueta + Imagen de perfil de %s + audio navegar hacia arriba - Avisos - Abrir enlace externo - mostrar más + abrir cámara foto + elige desde el dispositivo + elige desde medios de WordPress + reproduce + papelera + mostrar más borrar - Reproducir vídeo - reproducir vídeo destacado logo del plugin banner del plugin - elige desde medios de WordPress - abrir cámara - elige desde el dispositivo información del perfil - reproduce previsualizar imagen - vista previa - audio - reproducir vídeo - papelera reintentar vista previa de medios, nombre de archivo %s eliminar %s - Imagen de perfil de %s - marca de verificación Registrarse con Google… + vista previa + marca de verificación + Abrir enlace externo + Avisos + Reproducir vídeo + reproducir vídeo destacado + reproducir vídeo Se ha producido un error en la conexión a Jetpack: %s Ya estás conectado a Jetpack + %s TB DESHACER - Cambiado a modo visual Modo visual - Cambiado a modo HTML Modo HTML Vista previa Guardar como borrador - %s TB + Cambiado a modo HTML + Cambiado a modo visual + %1$s de %2$s + %s B %s GB - %s MB %s kB - %s B - %1$s de %2$s - Si necesitas más espacio, considera actualizar tu plan de WordPress. - Espacio utilizado - Medios + %s MB + Comentario aprobado + Comentario borrado Comentario marcado como no spam Comentario marcado como spam - Comentario borrado Comentario restaurado Comentario enviado a la papelera - El comentario no ha gustado - El comentario ha gustado Comentario sin aprobar - Comentario aprobado + Cuenta nueva Detalle de notificación %s - Editar foto Elige el sitio - Cuenta nueva - Conectado como + Espacio utilizado + Si necesitas más espacio, considera actualizar tu plan de WordPress. + Medios + El comentario no ha gustado + El comentario ha gustado + Editar foto + Ajustes de avisos Detalle de la persona + Notas de la versión + Conectado como Detalles del archivo Botones de compartir - Avisos Lector Yo - Mi sitio - Ajustes de avisos Ayuda y soporte Licencia - Notas de la versión + Avisos + Mi sitio Tu avatar se ha subido y estará disponible en breve. - Parece que has desactivado los permisos necesarios para esta característica.<br/><br/>Para cambiarlo, edita tus permisos y asegúrate de que <strong>%s</strong> está activado. Permisos Destacados - No puedes acceder a tus ajustes para compartir porque tu módulo de compartir de Jetpack está desactivado. - Módulo para compartir desactivado. Versión %s © %1$d %2$s + Parece que has desactivado los permisos necesarios para esta característica.<br/><br/>Para cambiarlo, edita tus permisos y asegúrate de que <strong>%s</strong> está activado. + No puedes acceder a tus ajustes para compartir porque tu módulo de compartir de Jetpack está desactivado. + Módulo para compartir desactivado. Editor: %s El sonido escogido tiene una ruta incorrecta. Por favor, elige uno distinto. QP %s @@ -1395,16 +1414,16 @@ Language: es Queda 1 página quedan %1$d páginas quedan %1$d entradas - %1$d páginas / entradas y 1 archivo restantes %1$d entradas y 1 archivo restantes + %1$d páginas / entradas y 1 archivo restantes %1$d páginas y 1 archivo restantes 1 entrada y 1 archivo restantes 1 página y 1 archivo restantes - %1$d páginas / entradas y %2$d de %3$d archivos restantes %1$d entradas y %2$d de %3$d archivos restantes + %1$d páginas / entradas y %2$d de %3$d archivos restantes quedan %1$d páginas y %2$d de %3$d archivos - queda 1 entrada y %1$d de %2$d archivos queda 1 página y %1$d de %2$d archivos + queda 1 entrada y %1$d de %2$d archivos %1$d entradas / páginas sin subir %1$d páginas sin subir 1 página sin subir @@ -1422,7 +1441,6 @@ Language: es 1 entrada con 1 archivo sin subir (sin título) \@%s - %1$f, %2$f Crear sitio Toca para continuar. ¡Sitio creado! @@ -1430,34 +1448,34 @@ Language: es Cambiar nombre de usuario Teclea para obtener más sugerencias Tu nombre de usuario actual es %1$s%2$s%3$s. Con pocas excepciones, otros solo verán tu nombre a mostrar, %4$s%5$s%6$s. - No se ha sugerido ningún nombre de usuario desde %1$s%2$s%3$s. Por favor, introduce más letras o números para obtener sugerencias. - Ocurrió un error al recuperar sugerencias de nombres de usuario. - ¿Descartas cambiar de nombre de usuario? Descartar Guardar Añadir avatar Registro con Google Registro con correo electrónico + No se ha sugerido ningún nombre de usuario desde %1$s%2$s%3$s. Por favor, introduce más letras o números para obtener sugerencias. + Ocurrió un error al recuperar sugerencias de nombres de usuario. + ¿Descartas cambiar de nombre de usuario? El correo electrónico ya existe en WordPress.com.\nAcceder. Actualizando cuenta… Al registrarte aceptas nuestros %1$sTérminos del servicio%2$s. Enviando correo - Reintentar - Cerrar - Hubo algún problema al enviar el correo. Puedes reintentarlo ahora o cerrar e intentarlo más tarde. Nombre de usuario - Siempre puedes acceder con un enlace como el que acabas de usar, pero también puedes configurar una contraseña si lo prefieres. - Contraseña (opcional) Nombre a mostrar Reintentar Revertir + Reintentar + Cerrar + Contraseña (opcional) Hubo algún problema al actualizar tu cuenta. Puedes reintentarlo o revertir tus cambios para continuar. Hubo algún problema al subir tu avatar. Para crear tu nueva cuenta de WordPress.com, por favor, introduce tu dirección de correo electrónico. Hubo algún problema al comprobar la dirección de correo. + Hubo algún problema al enviar el correo. Puedes reintentarlo ahora o cerrar e intentarlo más tarde. + Siempre puedes acceder con un enlace como el que acabas de usar, pero también puedes configurar una contraseña si lo prefieres. Registro en WordPress.com - Accede con tu nombre de usuario. Accede introduciendo la dirección de tu sitio. + Accede con tu nombre de usuario. Necesita actualizarse Buscar plugins Nuevo @@ -1592,8 +1610,8 @@ Language: es «Desconectar de WordPress.com» Puedes poner en lista blanca una dirección IP o series de direcciones, evitando que las bloquee Jetpack. Se aceptan IPv4 y IPv6. Para especificar un rango introduce un valor inferior y un valor superior separados por guiones. Ejemplo: 12.12.12.1–12.12.12.100 Requiere la identificación en dos pasos - Relacionar cuentas usando el correo electrónico Permitir el acceso con WordPress.com + Relacionar cuentas usando el correo electrónico Acceso con WordPress.com Direcciones IP en lista blanca Bloquea intentos de acceso maliciosos @@ -1612,21 +1630,21 @@ Language: es Eliminando ¿Borrar este vídeo? ¿Eliminar esta imagen? - Detalles del documento Detalles del audio + Detalles del documento Detalles del vídeo: - Detalles de la imagen Vista previa - Fecha de actualización + Detalles de la imagen Duración + Fecha de actualización Dimensiones de vídeo Sin imagen - Tipo de archivo Nombre del archivo + Tipo de archivo URL Texto alternativo - Conectar un sitio Luz parpadeante + Conectar un sitio Vibración del dispositivo Elige sonido Vistas y sonidos @@ -1665,8 +1683,8 @@ Language: es Entrada programada Reintentar Entrada a la espera - Subiendo «%s» Se ha perdido la conexión al servidor + Subiendo «%s» Mis sitios Mi sitio No se pudo detectar una aplicación cliente de correo electrónico @@ -1683,22 +1701,22 @@ Language: es Introduce la dirección del sitio WordPress con el que te gustaría conectar. Ya estás conectado a WordPress.com Seguir - Conectar otro sitio Introduce tu contraseña de WordPress.com + Conectar otro sitio Solicitando el correo electrónico de acceso Parece que esta contraseña es incorrecta. Por favor, vuelve a comprobar tu información e inténtalo de nuevo. Solicitando un código de verificación por SMS. Envíame un mensaje con un código en su lugar ¡Casi lo tenemos! Por favor, introduce un código de verificación desde tu aplicación Authenticator. - Abrir correo electrónico Siguiente + Abrir correo electrónico Accede a WordPress.com usando una dirección de correo electrónico para gestionar todos tus sitios WordPress. La optimización de imagen reduce las imágenes para que suban más rápido.\n\nPuedes cambiar esto en cualquier momento en los ajustes del sitio. ¿Activar optimización de la imagen? - Detener - Activar Foto de perfil Respuesta inesperada del servidor + Detener + Activar No se puede detener la subida porque ya ha finalizado Título Rehacer @@ -1709,28 +1727,24 @@ Language: es Ocurrió un error al arrastrar texto No está permitido arrastrar imágenes en el modo HTML Comparte tu historia aquí… - Privada Borrador Pendiente de revisión + Privada Publicar - Cambiar ubicación - Borrar ubicación - No se ha podido abrir el selector de ubicación, Google Play Services no está disponible - Ubicación Ahora Solo los que tengan esta contraseña pueden ver esta entrada Los extractos son resúmenes opcionales del contenido hechos a mano. El slug es la versión amigable de la URL del título de la entrada. - Formato de entrada Etiquetas Slug Extracto - No definido + Formato de entrada Más opciones Categorías y etiquetas + No definido Todos - Nivel superior Categoría superior (opcional): + Nivel superior No tienes ningún audio No tienes ningún documento No tienes ningún vídeo @@ -1846,11 +1860,11 @@ Language: es Media Baja Subido - Fallo al subir Se ha eliminado Eliminando Subiendo En cola + Fallo al subir Calidad de la imagen Todos los archivos de medios se han cancelado debido a un error desconocido. Por favor, vuelve a intentar cargarlos Formato de entrada desconocido @@ -1866,8 +1880,8 @@ Language: es Optimiza las imágenes Error de los archivos multimedia Hubo un error al cargar el archivo multimedia - Reintentar Confirmar + Reintentar No se pudo conectar. Se ha recibido un error 403 cuando se intenta acceder a \n tu endpoint del XMLRPC de sitio. La aplicación lo necesita para comunicarse con tu sitio. Ponte en contacto con tu proveedor para solucionar este problema. No se pudo conectar. Tu alojamiento está bloqueando las peticiones POST, y la aplicación las necesita \n para comunicarse con tu sitio. Ponte en contacto con tu alojamiento para solucionar este problema. Busca en los sitios que sigues @@ -1897,8 +1911,8 @@ Language: es Procesando… ¡Acción realizada! Comentario marcado como me gusta - Cerrar sesión Iniciar sesión en WordPress.com + Cerrar sesión Más en WordPress.com Más en %s Abrir ajustes del dispositivo @@ -1910,40 +1924,40 @@ Language: es ¡Comentario aprobado! Me gusta ahora - Espectador Seguidor + Espectador Sin conexión, no se pudo guardar tu perfil - Derecha - Izquierda Ninguna + Izquierda + Derecha Seleccionado %1$d No se pudieron recuperar los usuarios del sitio - Correo electrónico del seguidor Seguidor + Correo electrónico del seguidor Recuperando usuarios… - Espectadores Suscriptores por correo electrónico + Espectadores Seguidores Equipo Invita como máximo a 10 personas con sus correos electrónicos o nombre de usuarios de WordPress.com. A aquellos que necesiten un nombre de usuario se le enviará instrucciones sobre cómo hacerlo. Si eliminas a este espectador, no podrá visitar tu sitio\n\n¿Todavía quieres eliminar a este espectador? Si lo eliminas, este seguidor dejará de recibir informaciones de tu sitio, a no ser que vuelta a seguirte. \n\n¿Todavía quieres eliminar a este seguidor? Desde %1$s - No se pudo quitar el espectador No se pudo quitar al seguidor + No se pudo quitar el espectador No se pudieron recuperar los correos electrónicos de los seguidores del sitio No se pudieron recuperar los seguidores del sitio Algunas subidas de medios han fallado. Puedes cambiar al modo HTML \ncuando esto pasa. ¿Borramos todas las subidas fallidas y seguimos? + Cambios guardados Ancho - Enlazado a Leyenda - Cambios guardados + Enlazado a ¿Descartar cambios sin guardar? ¿Parar la subida? - ¡Toca para probar de nuevo! Invitación enviada con éxito - %1$s: %2$s ¡Se han enviado las invitaciones pero ha habido errores! + ¡Toca para probar de nuevo! + %1$s: %2$s ¡Hubo un error al tratar de enviar la invitación! No se pudo enviar: Hay nombres de usuario o correos electrónicos no válidos. No se pudo enviar: Un nombre de usuario o correo electrónico no es válido @@ -1955,27 +1969,27 @@ Language: es Mensaje personalizado Invitar Nombres de usuario o correos electrónicos - Invitar a gente - Externo Enviar enlace + Externo + Invitar a gente Borrar historial de búsqueda ¿Borrar historial de búsqueda? No se han encontrado resultados con %s para tu idioma Buscar en WordPress Los enlaces están desactivados en la pantalla de vista previa Enviar - \@%1$s eliminado correctamente. Si eliminas %1$s, ese usuario ya no será capaz de acceder a este sitio, pero cualquier contenido que fuera creado por %1$s permanecerá en el sitio.\n\n¿Aún te gustaría eliminar este usuario? + \@%1$s eliminado correctamente. Eliminar %1$s - Perfil - Gente Los sitios de esta lista no han publicado nada últimamente. + Gente + Perfil No se pudo eliminar el usuario No se ha podido actualizar el rol del usuario No se pudieron recuperar los espectadores del sitio Error al subir tu Gravatar - Error al recargar tu Gravatar Error al localizar la imagen recortada + Error al recargar tu Gravatar Error al recortar la imagen Comprobando correo electrónico Actualmente no disponible. Por favor, introduce tu contraseña @@ -1983,15 +1997,15 @@ Language: es Introduce tu contraseña Cuando comentes se hará público Captura o elige imagen - Planes Plan + Planes Tus entradas, páginas y ajustes te serán enviadas por correo electrónico a %s. Exportar tu contenido - ¡Correo electrónico de exportación enviado! Exportando contenido… - Comprobando compras + ¡Correo electrónico de exportación enviado! Mostrar compras Tienes mejoras premium en tu sitio. Por favor, cancela tus mejoras antes de eliminar tu sitio. + Comprobando compras Mejoras premium Algo fue mal. No se pudo realizar la compra. Borrando sitio… @@ -2007,42 +2021,42 @@ Language: es Si quieres un sitio, pero no quieres ninguna de las entradas y las páginas que tiene ahora, nuestro equipo de soporte puede borrar sus mensajes, páginas, archivos multimedia y tus comentarios.\n\nEsto mantendrá su sitio y la URL activos, pero tendrás un nuevo comienzo en la creación de contenidos. Sólo tienes que contactar con nosotros para limpiar tu contenido actual.. Déjanos ayudarte Comienza tu sitio encima - Comenzar de nuevo Ajustes de la app + Comenzar de nuevo Eliminar subidas fallidas Avanzado No hay comentarios en la papelera No hay comentarios pendientes No hay comentarios aprobados No se pudo conectar. Los métodos requeridos en el XML-RPC faltan en el servidor. + Estado Centrado Vídeo - Estado - Estándar - Cita - Enlace - Imagen - Galería Chat + Galería + Imagen + Enlace + Cita + Estándar + Información sobre cursos y eventos de WordPress.com (online y presenciales). Audio Minientrada - Información sobre cursos y eventos de WordPress.com (online y presenciales). Oportunidades para participar en investigaciones y encuestas en WordPress. Consejos para sacar el máximo partido a WordPress.com Comunidad - Investigación - Sugerencias Respuestas a mis comentarios - Menciones del nombre de usuario + Sugerencias + Investigación Logros del sitio + Menciones del nombre de usuario Seguidores del sitio «Me gusta» en mis entradas «Me gusta» en mis comentarios Comentarios en mi sitio %d elementos 1 elemento - Todos los usuarios Comentarios de usuarios conocidos + Todos los usuarios Sin comentarios %d comentarios por página 1 comentario por página @@ -2052,11 +2066,11 @@ Language: es Aprobar automáticamente los comentarios de todo el mundo. Aprobar automáticamente si el usuario tiene un comentario previamente aprobado Se requiere aprobación manual de los comentarios de todos. - %d días 1 día - Dirección web + %d días Sitio principal Haz click en el enlace de verificación del correo electrónica enviado a %1$s para confirmar tu nueva dirección + Dirección web Actualmente estás subiendo archivos multimedia. Por favor, espera hasta que se complete. No se pudieron actualizar los comentarios ahora mismo - se muestran comentarios antiguos Establece la imagen destacada @@ -2065,13 +2079,13 @@ Language: es ¿Eliminar de forma permanente estos comentarios? ¿Eliminar de forma permanente este comentario? Eliminar - Restaurar Comentario eliminado + Restaurar No hay comentarios spam - Todos No se pudo cargar la página - Off + Todos Idioma del interface + Off Sobre la app No se pudieron guardar los ajustes de la cuenta No se pudieron recuperar los ajustes de tu cuenta @@ -2079,9 +2093,9 @@ Language: es No se pudo reconocer el código del idioma Permite los comentarios anidados. Anidar hasta + Eliminar Desactivado Buscar - Eliminar Tamaño original Tu sitio es visible únicamente por ti y por lo usuarios que apruebes Tu sitio es visible para todos pero pide a los motores de búsqueda no ser indexado @@ -2090,9 +2104,9 @@ Language: es Sobre mí El nombre público mostrará por defecto el nombre de usuario si no está establecido Nombre que se mostrará públicamente - Apellidos - Nombre Mi perfil + Nombre + Apellidos Imagen de vista previa de entradas relacionadas No pudo guardar la información del sitio No pudo recuperar la información del sitio @@ -2164,22 +2178,22 @@ Language: es Formato por defecto Categoría por defecto Dirección - Descripción corta Título del sitio + Descripción corta Por defecto para nuevas entradas - Escribiendo Cuenta + Escribiendo General Nuevos primero - Antiguos primero - Cerrar después de Comentarios - Entradas relacionadas Privacidad + Antiguos primero Discusión + Entradas relacionadas + Cerrar después de No tienes permisos para subir multimedia al sitio - Desconocido Nunca + Desconocido Esta entrada ya no existe No estás autorizado a ver esta entrada No se pudo recuperar esta entrada @@ -2191,22 +2205,22 @@ Language: es Se ha producido un error. No se ha podido activar el tema de %1$s Gracias por elegir %1$s - GESTIONAR SITIO - HECHO - Ayuda - Detalles - Vista Probar y personalizar + Vista + Detalles + Ayuda + HECHO + GESTIONAR SITIO Activar - Activo - Ayuda - Detalles - Personalizar Tema actual - Página actualizada - Entrada actualizada - Página publicada + Personalizar + Detalles + Ayuda + Activo Entrada publicada + Página publicada + Entrada actualizada + Página actualizada Lo sentimos, no se han encontrados temas. Cargar más entradas Ningún sitio coincide con «%s» @@ -2238,289 +2252,289 @@ Language: es Tipos de avisos No se han podido cargar los ajustes de avisos Me gusta al comentario - Avisos de la aplicación Correo electrónico + Avisos de la aplicación Pestaña de avisos Siempre mandamos correos electrónicos importantes relativos a tu cuenta, pero también obtendrás extras útiles. Sumario de la última entrada Sin conexión Entrada enviada a la papelera - Papelera Estadísticas + Papelera Vista previa Ver - Publicar Editar + Publicar No tienes autorización para acceder a este sitio No se pudo encontrar este sitio Deshacer La solicitud ha expirado. Accede a WordPress.com para volver a intentarlo. - Ignorar El mejor día + Ignorar Estadísticas de hoy Entradas, vistas y visitantes de todos los tiempos Detalles Salir de WordPress.com - Acceder a WordPress.com Iniciar/Cerrar sesión + Acceder a WordPress.com Ayuda y soporte - Ajustes de la cuenta «%s» no se ha ocultado porque es el sitio actual + Ajustes de la cuenta Crear sitio en WordPress.com Añadir sitio autoalojado - Añadir sitio nuevo Mostrar/Ocultar sitios - Elegir sitio - Ver sitio - Ver Administrador + Añadir sitio nuevo Cambiar sitio - Ajustes - Entradas del blog + Ver Administrador + Ver sitio + Elegir sitio Publicar + Entradas del blog Aspecto + Ajustes Configuración Toca para mostrarlos - Anular todas las selecciones - Seleccionar todo - Ocultar Mostrar - Accede de nuevo para continuar. + Ocultar + Seleccionar todo + Anular todas las selecciones + Idioma Código de verificación no válido Código de verificación - Idioma - No se pudieron recuperar las entradas - Autor: + Accede de nuevo para continuar. No se pudo abrir la notificación Términos de búsqueda desconocidos - Términos de búsqueda Autores + Términos de búsqueda + Autor: Recuperando comentarios… Recuperando páginas… Recuperando entradas… Recuperando medios… + No se pudieron recuperar las entradas + Nuevas entradas Los informes de la aplicación se han copiado al portapapeles + Subiendo entrada Este sitio está vacío - Nuevas entradas Ha ocurrido un error al copiar el texto en el portapapeles - Subiendo entrada - %1$d años - Un año + Obteniendo temas… %1$d meses + Un año + %1$d años Un mes - %1$d días - Un día - %1$d horas - hace una hora %1$d minutos + hace una hora + %1$d horas + Un día + %1$d días hace un minuto hace unos segundos - Seguidores - Difundir - Vídeos Entradas y páginas + Vídeos + Difundir + Seguidores Países Me gusta - Visitantes - Vistas Años - Obteniendo temas… + Vistas + Visitantes Detalles %d seleccionados - Explora nuestras Preguntas frecuentes. Aún no hay comentarios - No hay entradas con esta temática - Me gusta Ver artículo original + Me gusta Los comentarios están cerrados %1$d de %2$d No se puede publicar una entrada vacía. No tienes permiso para ver o editar entradas. No tienes permiso para ver o editar páginas. No tienes permiso para ver o editar comentarios. - Más Hace más de 1 mes - Hace más de 1 semana + Más Hace más de 2 días + Hace más de 1 semana Me gustó Comentario El comentario se ha enviado a la papelera. Responder a %s + Explora nuestras Preguntas frecuentes. Aún no se han publicado entradas. ¿Por qué no crear una? Cerrando sesión… + No hay entradas con esta temática No es posible realizar esta acción No es posible bloquear este sitio Las entradas de este sitio no volverán a mostrarse Bloquear este sitio - Programación Actualizar - Sin sitios recomendados - No se puede dejar de seguir este sitio - No se puede seguir este sitio + Programación + Sitios que sigues Ya estás siguiendo este sitio - No se puede mostrar este sitio Sitio seguido + No se puede mostrar este sitio + No se puede seguir este sitio + No se puede dejar de seguir este sitio + Sin sitios recomendados + Sitio del lector Introduce una URL o tema para seguir - Sitios que sigues Temas seguidos - Sitio del lector - SI normalmente se conecta sin problemas a este sitio sin problemas, este error puede significar que alguien están intentando suplantar el sitio, por lo que no deberías continuar. ¿Quieres, de todas formas, confiar en el certificado? + Ayuda Certificado SSL no válido ¿Has olvidado la contraseña? - Ayuda - El nombre de usuario o contraseña que has introducido son incorrectos - Introduce una dirección de correo electrónico válida - Tu dirección de correo electrónico no es válida - Error al descargar la imagen - No se pudo cargar el comentario + SI normalmente se conecta sin problemas a este sitio sin problemas, este error puede significar que alguien están intentando suplantar el sitio, por lo que no deberías continuar. ¿Quieres, de todas formas, confiar en el certificado? + Ocurrió un error al obtener los temas. + Las entradas no pueden ser actualizadas en este momento + Las páginas no pueden ser actualizadas en este momento. + No es spam + No se pudo añadir la categoría + Ocurrió un error Ocurrió un error al editar el comentario Ocurrió un error al moderar el comentario - Ocurrió un error + Tu dirección de correo electrónico no es válida + El campo nombre de categoría es necesario + No se pudo cargar el comentario + Error al descargar la imagen + Se necesita una tarjeta SD montada para subir medios + No hay ninguna conexión de red disponible + El elemento multimedia no ha podido ser recuperado + Ha ocurrido un error mientras se accedía a este blog No se pudieron actualizar los comentarios - Las páginas no pueden ser actualizadas en este momento. - Las entradas no pueden ser actualizadas en este momento Ocurrió un error al eliminar la entrada - Sin avisos - Se necesita una tarjeta SD montada para subir medios - El campo nombre de categoría es necesario Categoría añadida correctamente - No se pudo añadir la categoría - No es spam - Ocurrió un error al obtener los temas. - Ha ocurrido un error mientras se accedía a este blog - El elemento multimedia no ha podido ser recuperado - No hay ninguna conexión de red disponible - No se ha podido eliminar este tema - No se ha podido añadir este tema - Registro de la aplicación - Ha ocurrido un error al crear la base de datos de la aplicación. Por favor, intenta reinstalar la aplicación. - Este blog está oculto y no se puede cargar. Actívalo de nuevo en ajustes y prueba de nuevo. - No se pueden actualizar los medios en este momento + Introduce una dirección de correo electrónico válida + El nombre de usuario o contraseña que has introducido son incorrectos + Sin avisos + Error de conexión + Cancelar edición + Aprobado + Pendiente + Spam + En la papelera + Editar comentario + Aprobar + Rechazar + Spam + Enviar a la papelera + Aprobando + Rechazando + Marcando como spam + Enviando a la papelera + ¿Enviar a la papelera? + Papelera + Guardando cambios + Nueva entrada + Añadir nueva categoría + Nombre de la categoría + Política de privacidad + Cambios locales Blog de WordPress + Ajustes de página Ajustes de imagen - Cambios locales - Política de privacidad - Nuevo elemento multimedia - Nueva entrada - No hay avisos… aún. - Se necesita autorización - Comprueba que la URL del sitio introducida es válida - Licencias de código abierto + Ajustes de entrada + Seleccionar categorías + Texto del enlace (opcional) No se pudo crear un archivo temporal para subir el archivo multimedia. Asegúrate que haya suficiente espacio libre en tu dispositivo. - Nombre de la categoría - Añadir nueva categoría + Ocurrió un error al cargar la entrada. Actualiza tus entradas e intenta nuevamente. + Borrador local Ver en el navegador - Eliminar sitio - El comentario no ha cambiado - Comentario obligatorio + Registro de la aplicación + Se necesita autorización + Aprender más ¿Cancelar la edición de este comentario? - Guardando cambios - Papelera - ¿Enviar a la papelera? - Enviando a la papelera - Marcando como spam - Rechazando - Aprobando - Enviar a la papelera - Spam - Rechazar - Aprobar - Editar comentario - En la papelera - Spam - Pendiente - Aprobado - ¿Borrar página? - ¿Borrar entrada? - Ajustes de entrada + Comentario obligatorio + El comentario no ha cambiado + No tienes permiso para ver la librería multimedia + Este blog está oculto y no se puede cargar. Actívalo de nuevo en ajustes y prueba de nuevo. + Nuevo elemento multimedia + Eliminar sitio + Comprueba que la URL del sitio introducida es válida + No se pueden actualizar los medios en este momento No ha sido posible encontrar el archivo a cargar. ¿Se ha borrado o cambiado de ubicación? - Borrador local - Ajustes de página - Texto del enlace (opcional) + Ocurrió un error al acceder a este plugin + ¿Borrar entrada? + ¿Borrar página? + No hay avisos… aún. + Licencias de código abierto Algunos medios no se han podido borrar en este momento. Inténtalo de nuevo más tarde. - No tienes permiso para ver la librería multimedia + Ha ocurrido un error al crear la base de datos de la aplicación. Por favor, intenta reinstalar la aplicación. Cuadrícula de miniaturas - Aprender más - Ocurrió un error al cargar la entrada. Actualiza tus entradas e intenta nuevamente. - Ocurrió un error al acceder a este plugin - Cancelar edición - Error de conexión - Seleccionar categorías + No se ha podido añadir este tema + No se ha podido eliminar este tema Compartir enlace Recuperando entradas… A ti, y a %,d personas más les gusta esto A %,d personas les gusta esto Responder - No se puede compartir en WordPress si no tienes un blog visible Comentado marcado como spam + No se puede compartir en WordPress si no tienes un blog visible + Elige una foto + Elige un vídeo No fue posible recuperar esta entrada A ti y a otra persona os gusta esto - Elige un vídeo - Elige una foto - Registro - Imposible abrir %s - Imposible ver la imágen + Contestar al comentario + Añadido %s Imposible compartir - Este no es un tema válido - Ya estás siguiendo este tema No se pudo publicar tu comentario - Te gusta esto - A una persona le gusta esto + Imposible ver la imágen + Imposible abrir %s Eliminado %s - Añadido %s - Contestar al comentario - Siguiendo - Seguir - Compartir - Reblog + Esta lista esta vacía Sin título + Compartir + Seguir + A una persona le gusta esto + Te gusta esto + Siguiendo No hay comentarios aún - Esta lista esta vacía - Meses - Semanas - Días - Ayer - Hoy - Referentes + Reblog + Registro + Este no es un tema válido + Ya estás siguiendo este tema + Temas Etiquetas y categorías - Clics - Estadísticas - Compartir + Hoy + Ayer + Días + Semanas + Meses Activar - No se pudo actualizar - Descripción - Leyenda Título + Descripción + Compartir + Clics + Referentes Pase de diapositivas - Círculos Mosaico + Círculos Cuadrados - Temas - Descartar + Leyenda + No se pudo actualizar + Estadísticas Gestionar - y %d más. - %d nuevos avisos - Seguimientos + Descartar Respuesta publicada + y %d más. Acceder + Seguimientos + %d nuevos avisos Cargando… - Contraseña HTTP Usuario HTTP + Contraseña HTTP Se ha producido un error al cargar los archivos Nombre de usuario o contraseña incorrecta - Acceder Nombre de usuario Contraseña + Acceder Lector - Páginas Entradas + Páginas Anónimo No hay red disponible - hecho OK + hecho URL - Términos del servicio - Versión WordPress para Android + Versión + Términos del servicio Alineación Refrescar Sin Título @@ -2531,24 +2545,24 @@ Language: es El nombre del atajo no puede estar vacío. Privado Título - Separa las etiquetas con comas Categorías + Separa las etiquetas con comas Eliminando comentarios Se necesita una tarjeta SD Multimedia Aprobar Eliminar Ninguno - Publicar ahora - Responder - en - Vista previa - Error de actualización de categorías Error - No + Cancelar + Guardar + Añadir + Error de actualización de categorías + Vista previa + Responder + No + en Ajustes de avisos - Añadir - Guardar - Cancelar + Publicar ahora diff --git a/WordPress/src/main/res/values-fr/strings.xml b/WordPress/src/main/res/values-fr/strings.xml index 4c034aae9a46..2f00e1530e38 100644 --- a/WordPress/src/main/res/values-fr/strings.xml +++ b/WordPress/src/main/res/values-fr/strings.xml @@ -1,11 +1,42 @@ + Nom du fichier + Réglages du bloc fichier + Le téléversement des fichiers a échoué.\nVeuillez toucher pour accéder aux options. + L’enregistrement des fichiers a échoué.\nVeuillez toucher pour accéder aux options. + Modifier le fichier + Copier l’URL du fichier + Choisir un fichier + Choisir un domaine + Nouveau + Réglages de Jetpack + Jetpack + Discussion suivie + Suivre la discussion + Impossible de se désabonner des commentaires pour cet article + Impossible de s’abonner aux commentaires pour cet article + Erreur de récupération du statut d’abonnement pour l’article + Bien désabonné·e des commentaires + Bien abonné·e aux commentaires + Réponse reçue non valide + Aucune réponse reçue + Effacer + Appliquer + Une ou plusieurs diapositives n’ont pas été ajoutées à votre Story, car les Stories ne prennent pas en charge les fichiers GIF pour le moment. Veuillez plutôt choisir une image statique ou un arrière-plan vidéo. + Fichiers GIF non pris en charge + Nous n’avons pas pu trouver les médias pour cette Story sur le site. + Impossible de modifier la Story + Impossible de charger le média pour cette Story. Vérifiez votre connexion internet et réessayez dans un instant. + Impossible de modifier la Story + Cette Story a été modifiée sur un appareil différent et la possibilité de modifier certains objets peut être limitée. + Modification de la Story limitée + Le média a été supprimé. Essayez de modifier votre Story. Arrière-plan Texte Rejeter @@ -21,8 +52,10 @@ Language: fr Continuer avec les identifiants de connexion de la boutique Trouver votre e-mail connecté Suivre des sujets + Essayez de suivre plus de sujets pour élargir la recherche Pas d’articles récents. Bienvenue ! + Analyser <b>Johan Brandt</b> a répondu à votre article Vous avez reçu <b>50 « J’aime »</b> sur votre site aujourd\'hui <b>Madison Ruiz</b> a aimé votre article @@ -30,7 +63,7 @@ Language: fr Menu de bloc déroulant fermé. Passer Choisir - Sélectionnez votre mise en page de la page d’accueil préférée. Vous pourrez la personnaliser ou la modifier ultérieurement. + Sélectionnez votre mise en page préférée pour la page d’accueil. Vous pourrez la personnaliser ou la modifier ultérieurement. Choisir un design Touchez réessayer quand vous serez de nouveau en ligne ou créer un page blanche en utilisant le bouton ci-dessous. Les mises en page ne sont pas disponibles hors connexion @@ -69,7 +102,6 @@ Language: fr Choisir des images Créer une publication de story Elles sont publiées en tant que nouvel article de blog sur votre site afin que votre public ne rate jamais rien. - Les publications de story ne disparaissent pas Combinez des photos, des vidéos et du texte pour créer des publications de story engageantes et sur lesquelles on peut appuyer. Vos visiteurs apprécieront. Maintenant, les stories sont pour tout le monde Exemple de titre de story @@ -85,6 +117,7 @@ Language: fr Choisir dans la bibliothèque des médias WordPress Retour Premiers pas + Suivre les sujets pour découvrir de nouveaux blogs Par Ce référent ne peut pas être marqué comme indésirable Marquer comme sain @@ -294,7 +327,6 @@ Language: fr %1$s · %2$s Essayer une mise en page de démarrage Ouvrir le menu d’actions du bloc - Insérer une mention Appuyer deux fois pour ouvrir la feuille du bas avec des options disponibles Appuyer deux fois pour ouvrir la feuille d’action avec des options disponibles Impossible d’ouvrir des pages pour le moment. Réessayez ultérieurement. @@ -461,7 +493,6 @@ Language: fr Publié La connexion à Facebook ne trouve aucune page. Publicize ne peut pas se connecter aux profils, seulement aux pages publiées. Non connecté - Adresse du site J’aime Abonnements Commentaires @@ -959,7 +990,6 @@ Language: fr Créer un site Rechercher des domaines C\'est ici que les internautes vous trouveront sur Internet. - Choisir un nom de domaine pour votre site Aucune adresse ne correspond à votre recherche Erreur de communication avec le serveur, veuillez essayer à nouveau. Un problème est survenu @@ -1410,7 +1440,6 @@ Language: fr 1 article avec 1 fichier non chargé (Sans titre) \@%s - %1$f, %2$f Créer un site Touchez pour continuer. Le site a bien été créé ! @@ -1701,10 +1730,6 @@ Language: fr Brouillon En attente de relecture Publier - Modifier l\'emplacement - Supprimer l’emplacement - Impossible d’ouvrir le sélecteur d’emplacement, Google Play Services n’est pas disponible. - Emplacement Maintenant Seules les personnes disposant de ce mot de passe peuvent consulter cet article. Les extraits sont des résumés manuels facultatifs de votre contenu. diff --git a/WordPress/src/main/res/values-gl/strings.xml b/WordPress/src/main/res/values-gl/strings.xml index d7d8890ea125..232fdea57fe5 100644 --- a/WordPress/src/main/res/values-gl/strings.xml +++ b/WordPress/src/main/res/values-gl/strings.xml @@ -44,7 +44,6 @@ Language: gl_ES %1$s · %2$s Proba un deseño de inicio Abrir o menú de accións de bloques - Insertar unha mención Toca dúas veces para abrir a folla inferior coas opcións dispoñibles Toca dúas veces pata abrir a folla de acción coas opcións dispoñibles No podemos abrir as páxinas neste momento. Por favor, inténtao de novo máis tarde @@ -209,7 +208,6 @@ Language: gl_ES Publicada A conexión con Facebook non pode encontrar ningunha páxina. «Difundir» non pode conectar con perfís de Facebook, só con páxinas publicadas. Non conectado - Enderezo do sitio Gústame Seguimentos Comentarios @@ -697,7 +695,6 @@ Language: gl_ES Crear sitio Buscar dominios Aquí é onde a xente te encontra en Internet. - Selecciona un nome de dominio para o teu sitio Non hai direccións dispoñibles que coincidan coa túa busca Erro durante a comunicación co servidor. Inténtao de novo Houbo un problema @@ -1145,7 +1142,6 @@ Language: gl_ES 1 entrada con 1 arquivo sen subir (sen título) \@%s - %1$f, %2$f Crear sitio Toca para continuar. Sitio creado! @@ -1431,10 +1427,6 @@ Language: gl_ES Borrador Pendente de revisión Publicar - Cambiar ubicación - Borrar ubicación - Non se puido abrir o selector de ubicación, Google Play Services non está dispoñible - Ubicación Agora Só os que teñan este contrasinal poden ver esta entrada Os extractos son resumos opcionais do contido feitos a man. diff --git a/WordPress/src/main/res/values-he/strings.xml b/WordPress/src/main/res/values-he/strings.xml index 9b95b4639d23..09dae426d6f8 100644 --- a/WordPress/src/main/res/values-he/strings.xml +++ b/WordPress/src/main/res/values-he/strings.xml @@ -1,11 +1,20 @@ + לפחות שקופית אחת לא נוספה לסטורי שלך מאחר שסטוריז לא תומכים בקובצי GIF כרגע. במקום, יש לבחור תמונה סטטית או וידאו לרקע. + קובצי GIF לא נתמכים + מצטערים, לא הצלחנו למצוא את המדיה לסטורי באתר זה. + אין אפשרות לערוך את הסטורי + לא ניתן לטעון את המדיה לסטורי הזה. יש לבדוק את החיבור שלך לאינטרנט ולנסות שוב עוד מעט. + אין אפשרות לערוך את הסטורי + הסטורי הזה נערך במכשיר שונה והאפשרות לערוך אובייקטים מסוימים עלולה להיות מוגבלת. + עריכה מוגבלת של הסטורי + פריט המדיה הוסר. מומלץ לנסות לערוך את הסטורי שלך. רקע טקסט ביטול @@ -32,7 +41,6 @@ Language: he_IL תפריט בלוק לגלילה סגור. לדלג לבחור - יש לבחור את הפריסה המועדפת עליך לעמוד הבית. אפשר להתאים אישית או לשנות אותה מאוחר יותר. לבחור עיצוב יש להקיש כדי לנסות שוב במצב מקוון או ליצור עמוד ריק בעזרת הכפתור למטה. הפריסות אינן זמינות במצב לא מקוון @@ -292,7 +300,6 @@ Language: he_IL %1$s · %2$s לנסות את הפריסה למתחילים לפתוח את התפריט של פעולות הבלוק - להוסיף אזכור יש להקיש פעמיים כדי לפתוח את גיליון הכפתורים עם האפשרויות הזמינות יש להקיש פעמיים כדי לפתוח את גיליון הפעולות עם האפשרויות הזמינות אין לנו אפשרות לפתוח את העמודים כעת. יש לנסות שוב מאוחר יותר @@ -459,7 +466,6 @@ Language: he_IL פורסם החיבור עם פייסבוק לא הצליח למצוא דפים. השיתוף האוטומטי לא יכול להתחבר אל פרופילים בפייסבוק, רק לדפים שפורסמו. לא מחובר - כתובת האתר לייקים עוקבים תגובות @@ -955,7 +961,6 @@ Language: he_IL יצירת אתר חיפוש דומיינים כאן הגולשים ימצאו אותך באינטרנט. - בחירת דומיין לאתר שלך לא נמצאו כתובות זמינות שתואמות לחיפוש שלך שגיאה בתקשורת עם השרת, יש לנסות שוב הייתה בעיה @@ -1404,7 +1409,6 @@ Language: he_IL פוסט אחד עם קובץ אחד לא הועלה (ללא כותרת) ‎@‎%s‎ - %1$f, %2$f יצירת אתר יש להקיש להמשך. האתר נוצר! @@ -1694,10 +1698,6 @@ Language: he_IL טיוטה ממתין לתצוגה מקדימה פרסום - שינוי מיקום - הסרת מיקום - לא ניתן לפתוח את בוחר המיקום, השירותים של Google Play לא זמינים - מיקום עכשיו רק משתמשים עם סיסמה יכולים לראות את הפוסט הנוכחי תקצירים הם סיכומים אופציונליים, \"בעבודת יד\", של התוכן שלך. diff --git a/WordPress/src/main/res/values-id/strings.xml b/WordPress/src/main/res/values-id/strings.xml index 3577ab29e741..04641514ae29 100644 --- a/WordPress/src/main/res/values-id/strings.xml +++ b/WordPress/src/main/res/values-id/strings.xml @@ -1,11 +1,20 @@ + Satu slide atau lebih belum ditambahkan ke Cerita Anda karena saat ini Cerita tidak mendukung file GIF. Sebagai gantinya, pilih gambar statis atau latar belakang video. + File GIF tidak didukung + Kami tidak dapat menemukan media untuk cerita ini pada situs. + Tidak dapat menyunting Cerita + Tidak dapat memuat media untuk cerita ini. Periksa koneksi internet Anda dan coba lagi nanti. + Tidak dapat menyunting Cerita + Cerita ini disunting pada perangkat yang berbeda dan kemampuan untuk mengedit objek tertentu mungkin terbatas. + Penyuntingan Cerita Terbatas + Media telah dihapus. Coba sunting Cerita Anda. Latar Belakang Teks Batal @@ -32,7 +41,6 @@ Language: id Menu blok yang dapat digulir tertutup. Lewati Pilih - Pilih tata letak halaman beranda favorit Anda. Anda selalu dapat menyesuaikan atau mengubahnya nanti. Pilih desain Ketuk coba lagi setelah Anda kembali online atau buat halaman kosong dengan tombol di bawah ini. Tata letak tidak tersedia saat offline @@ -295,7 +303,6 @@ Language: id %1$s · %2$s Buka Menu Tindakan Blokir Coba tampilan pengantar - Sertakan penyebutan Ketuk dua kali untuk membuka Lembar Bawah dengan opsi yang tersedia Ketuk dua kali untuk membuka Lembar Tindakan dengan opsi yang tersedia Saat ini kami tidak dapat membuka halaman. Harap coba lagi nanti @@ -462,7 +469,6 @@ Language: id Dipublikasikan Koneksi Facebook tidak dapat menemukan Halaman apa pun. Publikasikan tidak dapat terhubung ke Profil Facebook, hanya Halaman yang dipublikasikan. Tidak Terhubung - Alamat Situs Suka Mengikuti Komentar @@ -960,7 +966,6 @@ Language: id Buat Situs Cari Domain Di sinilah orang akan menemukan Anda di internet. - Pilih nama domain untuk situs Anda Tidak ada alamat yang cocok dengan pencarian Anda Terjadi error saat berkomunikasi dengan server, harap coba lagi Ada masalah @@ -1411,7 +1416,6 @@ Language: id 1 pos dengan 1 file belum diunggah (Tidak Berjudul) \@%s - %1$f, %2$f Buat situs Ketuk untuk melanjutkan. Situs telah dibuat! @@ -1701,10 +1705,6 @@ Language: id Konsep Menunggu peninjauan Publikasikan - Ubah Lokasi - Hapus Lokasi - Tidak dapat membuka Pemilih Lokasi, Layanan Google Play tidak tersedia - Lokasi Sekarang Hanya yang mengetahui kata sandi ini yang dapat melihat pos ini Kutipan merupakan ringkasan pilihan opsional dari konten Anda. diff --git a/WordPress/src/main/res/values-it/strings.xml b/WordPress/src/main/res/values-it/strings.xml index fbcb353a13bb..e8460754dbc0 100644 --- a/WordPress/src/main/res/values-it/strings.xml +++ b/WordPress/src/main/res/values-it/strings.xml @@ -11,7 +11,6 @@ Language: it Menu del blocco a scorrimento chiuso. Salta Scegli - Scegli il layout che preferisci per la tua homepage. Puoi personalizzarlo o modificarlo in un secondo momento. Scegli un design Tocca Riprova quando sei di nuovo online o crea una pagina vuota utilizzando il pulsante sottostante. Layout non disponibili in modalità offline @@ -274,7 +273,6 @@ Language: it %1$s · %2$s Prova un layout di inizio Apri menu azioni del blocco - Inserisci riferimento Tocca due volte per aprire il foglio in basso con le opzioni disponibili Tocca due volte per aprire il foglio delle azioni con le opzioni disponibili Al momento non possiamo aprire le pagine. Riprova più tardi @@ -441,7 +439,6 @@ Language: it Pubblicato La connessione a Facebook non riesce a trovare alcuna pagina. Pubblicizza non può connettersi ai profili Facebook, bensì solo alle pagine pubblicate. Non collegato - Indirizzo sito Mi piace Segue Commenti @@ -939,7 +936,6 @@ Language: it Crea il sito Cerca domini Ecco dove gli utenti ti troveranno su Internet. - Scegli un nome di dominio per il tuo sito Nessun indirizzo corrispondente alla ricerca Errore di comunicazione con il server, prova di nuovo Si è verificato un problema @@ -1390,7 +1386,6 @@ Language: it 1 post con 1 file non caricato (senza titolo) \@%s - %1$f, %2$f Crea il sito Tocca per continuare. Sito creato. @@ -1681,10 +1676,6 @@ Language: it Bozza In attesa di revisione Pubblica - Cambia posizione - Rimuovi posizione - Impossibile aprire Location Picker, Google Play Services non è disponibile - Posizione Ora Solo chi conosce questa password può visualizzare l\'articolo Gli estratti sono riepiloghi opzionali dei tuoi contenuti creati manualmente. diff --git a/WordPress/src/main/res/values-ja/strings.xml b/WordPress/src/main/res/values-ja/strings.xml index 7ab89f065e0e..64ee39786ffb 100644 --- a/WordPress/src/main/res/values-ja/strings.xml +++ b/WordPress/src/main/res/values-ja/strings.xml @@ -1,11 +1,20 @@ + 1つ以上のスライドがストーリーに追加されていません。現在、ストーリーでは GIF ファイルがサポートされていないためです。 代わりに静的画像または動画の背景を選択してください。 + GIF ファイルはサポートされていません + このストーリーのメディアがサイトにありませんでした。 + ストーリーを編集できません + このストーリーのメディアを読み込めません。 ネットワーク接続を確認して、もう一度お試しください。 + ストーリーを編集できません + このストーリーは別の端末で編集されており、特定のオブジェクトを編集する機能が制限される可能性があります。 + 制限されたストーリー編集 + メディアが削除されました。 ストーリーの編集をお試しください。 背景 テキスト 保存しない @@ -32,7 +41,6 @@ Language: ja_JP スクロール可能なブロックメニューが閉じられました。 スキップ 選択 - お気に入りのホームページのレイアウトを選択します。 後でカスタマイズまたは変更できます。 デザインを選択 オンラインに戻ったら「再試行」をタップするか、以下のボタンを使用して白紙のページを作成します。 レイアウトはオフラインでは利用できません @@ -296,7 +304,6 @@ Language: ja_JP %1$s · %2$s スターターレイアウトを試す ブロックの操作メニューを開く - メンションを挿入 ダブルタップして「下部シート」と利用可能オプションを開く ダブルタップして「アクションシート」と利用可能オプションを開く 現在、一時的にページを開けません。後ほどもう一度お試しください @@ -463,7 +470,6 @@ Language: ja_JP 公開済み Facebook との連携でページが見つかりません。パブリサイズで Facebook のプロフィールに連携できません。連携できるのは公開されているページのみです。 接続されていません - サイトのアドレス いいね フォロー コメント @@ -961,7 +967,6 @@ Language: ja_JP サイトを作成 ドメインを検索 ドメインとは、インターネット上で閲覧者があなたを見つける場所です - サイトのドメイン名を選択してください 検索条件一致する利用可能なアドレスはありません サーバーエラーです。もう一度お試しください 問題が発生しました @@ -1412,7 +1417,6 @@ Language: ja_JP 1投稿、1ファイルが未アップロード (無題) \@%s - %1$f、%2$f サイトの作成 続行するにはタップしてください。 サイトが作成されました。 @@ -1703,10 +1707,6 @@ Language: ja_JP 下書き レビュー待ち 公開 - 場所を変更 - 場所を削除 - 場所ピッカーを開けません。Google Play サービスはご利用いただけません - 場所 今すぐ パスワードを知っているユーザーのみが、この投稿を表示できます 抜粋は、手動で書かれたコンテンツの要約です (オプション)。 diff --git a/WordPress/src/main/res/values-kmr/strings.xml b/WordPress/src/main/res/values-kmr/strings.xml index 0c5af159af9c..c275ee1c6def 100644 --- a/WordPress/src/main/res/values-kmr/strings.xml +++ b/WordPress/src/main/res/values-kmr/strings.xml @@ -32,7 +32,6 @@ Language: ku_TR Menuya biloka şemîtonkî hate girtin. Derbas bibe Hilbijêre - Raxistina serrûpelê ya tu jê hez dikî, hilbijêre. Tu dikarî piştre wê li gorî xwe bitaybetîne an jî biguherîne. Sêwirekê hilbijêre Dema ku tu ji nû ve serhêl bû li dîsa biceribîneyê bitikîne an jî bi rêya bikaranîna bişkoka jêrîn rûpeleke vala biafirîne. Di derhêlbûnê(offline) de raxistin ne berdest in @@ -297,7 +296,6 @@ Language: ku_TR %1$s · %2$s Raxistina destpêkê biceribîne Menuya çalakiyên blokê veke - Behskirinê tevlî bike Ji bo ku Rûpela Jêrîn bi vebijarkên berdest re vebe, ducar bitikîne Ji bo Rûpela Çalakiyan bi vebijarkên berdest re vebe, ducar bitikîne Em aniha nikarin rûpelan vekin. Ji kerema xwe piştre dîsa biceribîne @@ -464,7 +462,6 @@ Language: ku_TR Weşandî Girêdana Facebookê nikare ti Rûpelan bibîne. Bangewazî, bi Profîlên Facebookê ve nayê girêdan, tenê dikare bi Rûpelên weşandî ve bê girêdan. Nehatiye girêdan - Navnîşana Malperê Ecibandin Şopîner Şîrove @@ -962,7 +959,6 @@ Language: ku_TR Malperê Biafirîne Li Domainan Bigere Mirov di înternetê de ew ê te li vir bibînin. - Ji bo malpera xwe navekî domainê hilbijêre Li gorî lêgerîna te ti navnîşan nehat dîtin Di têkîliya bi serverê re çewtî derket, ji kerema xwe dîsa biceribîne Pirsgirêkek hebû @@ -1413,7 +1409,6 @@ Language: ku_TR Şandiyek û dosyeyek nehatin hilxistin (Bêsernav) \@%s - %1$f, %2$f Malperê biafirîne Ji bo domandinê, bitepîne. Malper hat afirandin! @@ -1704,10 +1699,6 @@ Language: ku_TR Reşnivîs Li benda kontrolê ye Weşandî - Cîgehê Biguherîne - Cîgehê Rake - Bijêra Cîgehê nayê vekirin, Xizmetên Google Playê ne berdest in - Cîgeh Aniha Tenê kesên xwediyê vê pêborînê dikarin vê şandiyê bibînin Jêgirtin, kurteyên naveroka te yên ku bi destan hatine amadekirin e. diff --git a/WordPress/src/main/res/values-ko/strings.xml b/WordPress/src/main/res/values-ko/strings.xml index 30c01c8bb43a..db1f54f38bbe 100644 --- a/WordPress/src/main/res/values-ko/strings.xml +++ b/WordPress/src/main/res/values-ko/strings.xml @@ -1,11 +1,33 @@ + 파일 이름 + 파일 블록 설정 + 파일 업로드를 실패했습니다.\n옵션을 열려면 누르시기 바랍니다. + 파일 저장을 실패했습니다.\n옵션을 열려면 누르시기 바랍니다. + 파일 편집하기 + 파일 URL 복사하기 + 파일 선택하기 + 도메인 선택하기 + 신규 + 젯팩 설정 + 젯팩 + 대화 팔로우 중 + 대화 팔로우하기 + 이 글에 대한 댓글을 구독 해제할 수 없습니다 + 이 글에 대한 댓글을 구독할 수 없습니다 + 글에 대한 구독상태를 가져오는데 오류가 있습니다 + 댓글을 성공적으로 구독 해제했습니다 + 이 댓글을 성공적으로 구독했습니다 + 유효하지 않은 반응을 받았습니다 + 받은 응답이 없습니다 + 지우기 + 적용하기 하나 또는 그 이상의 슬라이드는 지금 이야기가 GIF 파일을 지원하지 않기에 이야기에 추가할 수 없습니다. 정지한 이미지 또는 비디오 배경을 대신 선택하시기 바랍니다. GIF 파일을 지원하지 않습니다 사이트의 이 이야기에 대한 미디어를 찾을 수 없습니다. @@ -41,7 +63,6 @@ Language: ko_KR 스크롤 할 수 있는 블록 메뉴를 닫았습니다. 건너뛰기 선택하기 - 좋아하는 홈페이지 레이아웃을 고르세요. 사용자 정의하거나 나중에 바꿀 수 있습니다. 디자인 선택하기 온라인으로 돌아가면 재시도를 누르거나 아래의 단추를 이용하여 빈 페이지를 만드세요. 레이아웃은 오프라인 중에 사용할 수 없습니다 @@ -306,7 +327,6 @@ Language: ko_KR %1$s · %2$s 스타터 레이아웃 시도하기 블록 동작 메뉴 열기 - 언급 넣기 두 번 눌러 사용 가능한 선택지가 있는 하단 시트 열기 두 번 눌러 사용 가능한 선택지가 있는 동작 시트를 열기 지금은 페이지를 열 수 없습니다. 나중에 다시 시도하시기 바랍니다 @@ -473,7 +493,6 @@ Language: ko_KR 게시됨 페이스북 연결에서 페이지를 찾을 수 없습니다. 배포 기능은 페이스북 프로필에 연결할 수 없으며 게시된 페이지에만 연결할 수 있습니다. 연결되지 않음 - 사이트 주소 좋아요 팔로우 댓글 @@ -971,7 +990,6 @@ Language: ko_KR 사이트 생성 도메인 검색 사람들이 인터넷에서 회원님을 찾을 수 있는 곳입니다. - 사이트의 도메인 네임 선택 검색 내용과 일치하는 주소가 없습니다. 서버와 통신하는 동안 오류가 발생했습니다. 다시 시도하세요. 문제가 발생했습니다. @@ -1422,7 +1440,6 @@ Language: ko_KR 1개의 파일이 포함된 1개의 글이 업로드되지 않음 (제목 없음) \@%s - %f, %f 사이트 생성 계속하려면 누르세요. 사이트를 생성했습니다! @@ -1713,10 +1730,6 @@ Language: ko_KR 임시글 검토 대기 중 발행 - 위치 변경 - 위치 제거 - 위치 선택기를 열 수 없습니다. Google Play 서비스를 사용할 수 없습니다 - 위치 지금 이 암호를 아는 사용자만 이 글을 볼 수 있습니다 원하는 경우 내 콘텐츠를 직접 요약한 발췌본을 작성할 수 있습니다. diff --git a/WordPress/src/main/res/values-ms/strings.xml b/WordPress/src/main/res/values-ms/strings.xml index bee8ed6f1f13..7d826b2e20f5 100644 --- a/WordPress/src/main/res/values-ms/strings.xml +++ b/WordPress/src/main/res/values-ms/strings.xml @@ -162,11 +162,7 @@ Language: ms Draf Menunggu tinjauan Persendirian - Tukar Lokasi Terbit - Buang Lokasi - Tidak boleh membuka Pemetik Lokasi, Google Play Service tidak didapati - Lokasi Sekarang Hanya mereka dengan kata laluan ini boleh melihat kiriman ini Petikan adalah ringkasan kandungan anda yang dibuat sendiri dan tidak diwajibkan. diff --git a/WordPress/src/main/res/values-nb/strings.xml b/WordPress/src/main/res/values-nb/strings.xml index 13072c840d40..faf025e89b82 100644 --- a/WordPress/src/main/res/values-nb/strings.xml +++ b/WordPress/src/main/res/values-nb/strings.xml @@ -1,11 +1,16 @@ + Filnavn + Rediger fil + Ny + Jetpack-innstillinger + Jetpack GIF-filer ikke støttet Bakgrunn Tekst @@ -33,6 +38,7 @@ Language: nb_NO Fotball Matlaging Kunst + Å bli inspirert Nettsteder å følge Velg bilder Side opprettet @@ -200,7 +206,6 @@ Language: nb_NO %1$s · %2$s Prøv et startoppsett Åpne handlingsmenyen for blokker - Sett inn omtale Vi kan for tiden ikke åpne sider. Vennligst prøv igjen senere. Sett som innleggsside Sett som forside @@ -337,7 +342,6 @@ Language: nb_NO Planlagt Publisert Ikke tilkoblet - Nettstedsadresse Likinger Følger Kommentarer @@ -819,7 +823,6 @@ Language: nb_NO Lag nettsted Søk domener Dette er der folk vil finne deg på nettet. - Velg et domenenavn for ditt nettsted Ingen tilgjengelige adresser passet til ditt søk Feil ved kommunkasjonen med server, vennligst prøv igjen Det oppsto et problem @@ -1255,7 +1258,6 @@ Language: nb_NO 1 innlegg med 1 fil ikke lastet opp (Uten tittel) \@%s - %1$f, %2$f Opprett nettsted Trykk for å fortsette. Nettsted opprettet! @@ -1537,10 +1539,6 @@ Language: nb_NO Utkast Avventer gjennomgang Publiser - Endre posisjon - Fjern posisjon - Klarte ikke å åpne Posisjonsvelger, siden Google Play Tjenester ikke er tilgjengelig - Posisjon Kun de som har dette passordet kan se dette innlegget Utdrag, er valgfrie håndlagde oppsummeringer av innholdet ditt. diff --git a/WordPress/src/main/res/values-nl/strings.xml b/WordPress/src/main/res/values-nl/strings.xml index b65819ab54aa..5afe5d29729b 100644 --- a/WordPress/src/main/res/values-nl/strings.xml +++ b/WordPress/src/main/res/values-nl/strings.xml @@ -1,11 +1,33 @@ + KIES EEN BESTAND + Kopieer bestands URL + Bewerk bestand + Opslaan van bestanden mislukt.\nTik voor opties. + Uploaden van bestanden mislukt.\nTik voor opties. + Bestand blokkeerinstellingen + Bestandsnaam + Met succes uitgeschreven van de reacties + Fout bij het ophalen van de abonneringstatus voor bericht + Kon niet abonneren op reacties voor dit bericht + Kon niet uitschrijven van reacties voor dit bericht + Volg conversatie + Conversatie wordt gevolgd + Jetpack + Jetpack Instellingen + Nieuw + Kies een domein + Toepassen + Wissen + Geen antwoord ontvangen + Ongeldig antwoord ontvangen + Met succes geabonneerd op de reacties Een of meer slides zijn niet toegevoegd aan je verhaal omdat verhalen geen GIF bestanden ondersteunen op dit moment. Kies in plaats daarvan een statische afbeelding of video achtergrond. Dit verhaal is bewerkt op een ander apparaat en de mogelijkheid om bepaalde objecten te bewerken kan beperkt zijn. Kan het verhaal niet bewerken @@ -41,7 +63,7 @@ Language: nl Overslaan Scrolbaar blokmenu gesloten. Scrolbaar blokmenu geopend. Selecteer een blok. - Kies je favoriete homepage-opmaak. Je kan deze later altijd nog aanpassen of wijzigen. + Kies je favoriete homepage lay-out. Je kan deze bewerken of later altijd nog aanpassen. Niet ingesteld Nieuwe categorie toevoegen Categorie toevoegen @@ -306,7 +328,6 @@ Language: nl %1$s · %2$s Probeer een starter lay-out Open menu met blokacties - Voeg vermelding in Dubbeltik om onderste blad te openen met beschikbare opties Dubbeltik om actieblad te openen met beschikbare opties We kunnen momenteel geen pagina\'s openen. Probeer het later opnieuw @@ -473,7 +494,6 @@ Language: nl Gepubliceerd De Facebook-verbinding kan geen pagina\'s vinden. Publicize kan geen verbinding maken met Facebook-profielen, alleen met gepubliceerde pagina\'s. Niet verbonden - Websiteadres Waarderingen Volgt Commentaar @@ -974,7 +994,6 @@ Language: nl Geen beschikbare adressen die overeenkomen met uw zoekopdracht Fout bij communicatie met de server. Probeer het opnieuw Er was een probleem - Kies een domeinnaam voor je site Er was een probleem Hiermee kunnen aanbevelingen maken. Maar je zit nergens aan vast - alle sites blijven zich ontwikkelen! Vertel ons wat voor soort site je zou willen maken @@ -1422,7 +1441,6 @@ Language: nl 1 bericht met 1 bestand niet geüpload (Zonder titel) \@%s - %1$f, %2$f Site maken Opslaan Voeg avatar toe @@ -1713,10 +1731,6 @@ Language: nl Concept Beoordeling in behandeling Publiceren - Locatie wijzigen - Locatie verwijderen - Kan locatiekiezer niet openen; Google Play Services is niet beschikbaar - Locatie Nu Alleen personen met dit wachtwoord kunnen dit bericht bekijken. Samenvattingen zijn optionele, handgemaakte overzichten van je content. diff --git a/WordPress/src/main/res/values-pl/strings.xml b/WordPress/src/main/res/values-pl/strings.xml index 0244bc5fdbd8..e30463af5f55 100644 --- a/WordPress/src/main/res/values-pl/strings.xml +++ b/WordPress/src/main/res/values-pl/strings.xml @@ -32,7 +32,6 @@ Language: pl Wybierz Otwarto przewijalne menu blokowe. Wybierz blok. Zamknięto przewijalne menu blokowe. - Wybierz swój ulubiony szablon dla strony głównej. Możesz go dostosować lub zmienić w późniejszym czasie. Wybierz wzór Dodaj kategorię Kategorie @@ -293,7 +292,6 @@ Language: pl %1$s · %2$s Otwórz menu działań na blokach Wypróbuj układ startowy - Wstaw wzmiankę Stuknij dwukrotnie aby otworzyć dolną zakładkę z dostępnymi opcjami Stuknij dwukrotnie aby otworzyć zakładkę akcji z dostępnymi opcjami Nie można było otworzyć stron w tej chwili. Proszę spróbować później @@ -459,7 +457,6 @@ Language: pl Zaplanowany Opublikowano Nie połączono - Adres witryny Połączenie z Facebookiem nie może odnaleźć żadnych Stron. Publicize nie może połączyć się z profilami Facebooka, tylko z publikowanymi Stronami. Polubienia Obserwuje @@ -958,7 +955,6 @@ Language: pl Tworzenie nowej witryny Przeszukaj domeny To tu ludzie odnajdą ciebie w internecie. - Wybierz nazwę domeny dla swojej witryny Brak dostępnych adresów zgodnych z twoimi kryteriami wyszukiwania Błąd komunikacji z serwerem, spróbuj ponownie Wystąpił problem @@ -1409,7 +1405,6 @@ Language: pl Nie przesłano 1 wpisu z 1 plikiem (bez tytułu) \@%s - %1$f, %2$f Utwórz witrynę Stuknij aby kontynuować. Utworzono witrynę! @@ -1699,12 +1694,8 @@ Language: pl Szkic Prywatny Oczekuje na przegląd - Zmień lokalizację - Usuń lokalizację Opublikuj - Nie można było otworzyć selektora lokalizacji, usługi Google Play są niedostępne Teraz - Lokalizacja Tylko osoby posiadające hasło mogą czytać ten wpis Zajawki to opcjonalne, ręcznie przygotowane podsumowania twoich treści. Nazwa uproszczona to tytuł wpisu w postaci przyjaznego adresu URL diff --git a/WordPress/src/main/res/values-pt-rBR/strings.xml b/WordPress/src/main/res/values-pt-rBR/strings.xml index b5385eec56f8..c7194134ea71 100644 --- a/WordPress/src/main/res/values-pt-rBR/strings.xml +++ b/WordPress/src/main/res/values-pt-rBR/strings.xml @@ -1,11 +1,100 @@ + Nome do arquivo + Configurações do bloco Arquivo + Falha ao enviar arquivos.\nToque para ver mais opções. + Falha ao salvar arquivos.\nToque para ver mais opções. + Editar arquivo + Copiar URL do arquivo + Escolha um arquivo + Escolha um domínio + Novo + Configurações do Jetpack + Jetpack + Seguindo a conversa + Seguir conversa + Erro ao coletar o status da assinatura do post + Não foi possível cancelar a inscrição dos comentários deste post + Não foi possível inscrever-se nos comentários deste post + Inscrição nos comentários cancelada + Limpar + Aplicar + Inscrição nos comentários concluída + Resposta inválida recebida + Nenhuma resposta recebida + Um ou mais slide não foi adicionado ao seu Story por que este recurso não suporte arquivos GIF no momento. Escolha uma imagem estática ou vídeo de fundo. + Arquivos gif não são compatíveis + Não conseguimos encontrar a mídia para este story no site. + Não é possível editar o story + Não foi possível enviar a mídia para este story. Verifique sua conexão de internet e tente novamente. + Não é possível editar o story + Este story foi editado em outro dispositivo e a possibilidade de edição de certos objetos pode estar limitada. + Edição limitada de story + A mídia foi removida. Tente editar o Story novamente. + Fundo + Texto + Descartar + Qualquer alteração feita não será salva. + Descartar alterações? + Concluído + Seguinte + Excluir + Ocorreu um erro durante a seleção do design. + Verifique sua conexão com a internet e tente novamente. + Toque em tentar novamente quando estiver online. + Modelos não estão disponíveis off-line + Nenhum post recente + Seguir tópicos + Encontre o e-mail conectado + Examinar + Desejamos boas-vindas! + Prosseguir com as informações salvas + Tente seguir mais assuntos para melhorar a pesquisa + <b>Johan Brandt</b> respondeu seu post + Você recebeu <b>50 curtidas</b> em seu site hoje + <b>Madison Ruiz</b> curtiu seu post + Menu de blocos aberto. Escolha um bloco. + Menu de blocos fechado. + Pular + Escolher + Escolha seu modelo preferido para a página inicial. Você poderá personalizar ou alterá-lo depois. + Escolha um design + Modelos não estão disponíveis off-line + Toque em tentar novamente ou crie uma página vazia usando o botão abaixo. + Modelos não estão disponíveis devido um erro + Adicionar categoria + Adicionar nova categoria + Categorias + Não definido + Categorias + Toque em tentar novamente quando estiver online ou crie uma página vazia usando o botão abaixo. + Museus em Londres + Minhas 10 cafeterias preferidas + Política + Música + Jardinagem + Futebol + Culinária + Arte + Novidades sobre Rock n\' Roll + Novidades da internet + Pamela Nguyen + Os melhores fãs do mundo + Me inspiro muito no trabalho do fotógrafo. Vou tentar uma dessas técnicas em meu próximo + Inspirando-se + Siga seus sites favoritos e descubra novas leituras. + Veja seu público-alvo aumentar usando análises detalhadas. + Veja comentários e notificações em tempo real. + Com o editor avançado, você publica seus posts de onde estiver. + Desejamos boas-vindas ao criador de sites mais popular do mundo. + O envio da mídia falhou + Sites para seguir Estamos trabalhando arduamente para adicionar mais blocos a cada lançamento. \'%s\' não é totalmente suportado Botão de ajuda @@ -29,6 +118,7 @@ Language: pt_BR Escolher da biblioteca de mídias do WordPress Voltar Comece agora + Siga tópicos para descobrir novos blogs Por Este referenciador não pode ser marcado como spam Desmarcar como spam @@ -151,6 +241,7 @@ Language: pt_BR Escolher imagem ou vídeo Escolher imagem Bloco removido + Digite o endereço de seu site Continuar com WordPress.com Confirmação de inscrição Se você continuar com o Google e ainda não tiver uma conta no WordPress.com, você criará uma conta e concordará com nossos %1$sTermos de Serviços%2$s. @@ -237,7 +328,6 @@ Language: pt_BR %1$s · %2$s Abrir menu de ações do bloco Experimente começar com um modelo - Inserir menção Toque duas vezes para abrir a janela inferior com as opções disponíveis Toque duas vezes para abrir a janela de ações com as opções disponíveis Não conseguimos abrir as páginas agora. Tente novamente mais tarde. @@ -402,7 +492,6 @@ Language: pt_BR Agendado Publicado Não conectado - Endereço do site Na lixeira A conexão com o Facebook não encontrou nenhuma página. O Publicize não consegue se conectar a perfis do Facebook, apenas a páginas públicas. Curtidas @@ -902,7 +991,6 @@ Language: pt_BR Parece que sua conexão está lenta. Se você não encontrar seu site na lista, tente atualizar a tela. Cancelar o guia de criação do site É onde as pessoas encontrarão seu site na internet. - Escolha um nome de domínio para seu site Nenhum endereço disponível corresponde à sua pesquisa Erro de comunicação com o servidor. Tente novamente. Ocorreu um problema @@ -1353,7 +1441,6 @@ Language: pt_BR 1 página com 1 arquivo não enviado %1$d posts com 1 arquivo não enviado 1 post com 1 arquivo não enviado - %1$f, %2$f Criar site Toque para continuar. Site criado! @@ -1644,11 +1731,7 @@ Language: pt_BR Rascunho Revisão pendente Publicar - Alterar localização - Remover localização - Não foi possível abrir o selecionador de localização. O Google Play Services não está disponível Agora - Localização Somente usuários com essa senha podem ver este post Resumos são sumários opcionais do seu conteúdo, escritos separadamente. O slug é a versão para URL amigável do título do post. diff --git a/WordPress/src/main/res/values-ro/strings.xml b/WordPress/src/main/res/values-ro/strings.xml index 48f470bc27ea..1a8368046544 100644 --- a/WordPress/src/main/res/values-ro/strings.xml +++ b/WordPress/src/main/res/values-ro/strings.xml @@ -1,11 +1,33 @@ + Nume fișier + Setări bloc fișier + Încărcarea fișierelor a eșuat.\nTe rog atinge pentru opțiuni. + Salvarea fișierelor a eșuat.\nTe rog atinge pentru opțiuni. + Editează fișierul + Copiază URL-ul fișierului + ALEGE UN FIȘIER + Alege un domeniu + Nou + Setări Jetpack + Jetpack + Urmăresc conversația + Urmărește conversația + Nu am putut face dezabonarea la comentarii pentru acest articol + Nu am putut face abonarea la comentarii pentru acest articol + Eroare la aducerea stării abonamentului pentru articol + Te-ai dezabonat cu succes de la comentarii + Te-ai abonat cu succes la comentarii + Am primit un răspuns invalid + Nu am primit niciun răspuns + Șterge + Aplică Nu au fost adăugate diapozitive în narațiunea ta deoarece narațiunile nu acceptă fișiere GIF. Te rog alege în schimb o imagine statică sau un fundal video. Fișierele GIF nu sunt acceptate Nu am putut găsi pe sit conținut media pentru această narațiune. @@ -41,7 +63,7 @@ Language: ro Meniul de blocuri care poate fi derulat este închis. Sari Alege - Alege aranjamentul preferat pentru prima pagină. Îl poți personaliza sau modifica mai târziu. + Alege aranjamentul preferat pentru prima pagină. Îl poți edita sau personaliza mai târziu. Alege un design Atinge reîncearcă când ești din nou online sau creează o pagină goală folosind butonul de mai jos. Aranjamentele nu sunt disponibile când ești offline @@ -306,7 +328,6 @@ Language: ro %1$s · %2$s Încearcă un aranjament de început Deschide meniul acțiuni blocuri - Inserează mențiunea Atinge de două ori pentru a deschide Foaia de jos cu opțiunile disponibile Atinge de două ori pentru a deschide Foaia acțiuni cu opțiunile disponibile Nu putem deschide paginile în acest moment. Te rog reîncearcă mai târziu. @@ -473,7 +494,6 @@ Language: ro Publicate Conexiunea Facebook nu găsește nicio pagină. Publicitatea nu se poate conecta la profilurile Facebook, ci numai la pagini Facebook publicate. Neconectat - Adresă sit Aprecieri Urmăriri Comentarii @@ -971,7 +991,6 @@ Language: ro Crează situl Caută domenii Aici vei fi găsit pe internet. - Alege un nume de domeniu pentru situl tău Nu se potrivește nicio adresă disponibilă cu căutarea ta Eroare de comunicare cu serverul, te rog încercă din nou A fost o problemă @@ -1422,7 +1441,6 @@ Language: ro Un articol cu un fișier neîncărcat (fără titlu) \@%s - %1$f, %2$f Creează situl Atinge pentru a continua. Sit creat! @@ -1713,10 +1731,6 @@ Language: ro Ciornă Revizie în așteptare Publică - Schimbă locația - Înlătură locația - Nu pot deschide selectorul de locație, serviciile Google Play nu sunt disponibile - Locație Acum Numai cei care au această parolă pot vedea acest articol Rezumatele sunt scurte expuneri manuale, opționale, ale conținutului tău. diff --git a/WordPress/src/main/res/values-ru/strings.xml b/WordPress/src/main/res/values-ru/strings.xml index b666f251cb79..ac5ba8f7f567 100644 --- a/WordPress/src/main/res/values-ru/strings.xml +++ b/WordPress/src/main/res/values-ru/strings.xml @@ -1,11 +1,33 @@ + ВЫБРАТЬ ФАЙЛ + Скопировать URL файла + Редактировать файл + Невозможно сохранить файлы.\nНажмите для выбора вариантов. + Невозможно загрузить файлы.\nНажмите для выбора вариантов. + Настройки блока файла + Имя файла + Вы отписались от комментариев + Ошибка получения статуса подписки для записи + Невозможно подписаться на комментарии для этой записи + Невозможно отписаться от комментариев для этой записи + Подписаться на беседу + Вы подписаны на беседу + Jetpack + Настройки Jetpack + Новая + Выбрать домен + Применить + Очистить + Ответ не получен + Получен неверный ответ + Вы подписались на комментарии К вашей истории не были добавлены один или несколько слайдов, на текущий момент истории не поддерживают GIF файлы. Выберите статическое изображение или видео для фона вместо GIF. Эта история редактировалась на другом устройстве. Возможности редактирования некоторых объектов могут быть ограничены. Нельзя отредактировать историю @@ -289,7 +311,6 @@ Language: ru Добавить метки Метки информируют о том, про что написано в записи. Дата публикации - Калифорнийский закон о защите прав потребителей («CCPA») обязывает нас предоставлять жителям Калифорнии некоторую дополнительную информацию о категориях личной информации, которую мы собираем и передаем, где мы получаем эту личную информацию, а также как и почему мы ее используем. Прочитать уведомление о конфиденциальности CCPA Дата публикации Запланирована @@ -297,6 +318,7 @@ Language: ru Опубликована Выберите несколько для продолжения Готово + Калифорнийский закон о защите прав потребителей («CCPA») обязывает нас предоставлять жителям Калифорнии некоторую дополнительную информацию о категориях личной информации, которую мы собираем и передаем, где мы получаем эту личную информацию, а также как и почему мы ее используем. Выберите ваши интересы Выберите ваши интересы Переместить записи в черновики @@ -308,7 +330,6 @@ Language: ru Открыть меню действий с блоком Нажмите дважды для того, чтобы открыть панель действий со всеми доступными возможностями Нажмите дважды для того, чтобы открыть нижнюю панель действий с доступными возможностями - Вставить упоминание Выбранная главная страница и страница записей не могут быть однаковыми. Классический блог Статическая главная страница @@ -467,7 +488,6 @@ Language: ru Добавить блок параграфа (555)555–1234 улица Лизюкова 2 - Адрес сайта Нет подключения Подключение к Facebook не может обнаружить страниц, Publicize не может использовать профили Facebook, только страницы. Опубликованные @@ -974,7 +994,6 @@ Language: ru Возникла проблема Ошибка подключения к серверу, пожалуйста попробуйте еще раз Нет доступных адресов по критериям поиска - Выберите доменное имя для вашего сайта Это поможет нам делать вам рекомендации. Но вы не ограничены этим, все сайты развиваются. Возникла проблема Расскажите какого типа сайт вы хотите создать @@ -1422,7 +1441,6 @@ Language: ru не загружены 1 страница и 1 файл не загружены %1$d записей и 1 файл не загружены 1 запись и 1 файл - %1$f, %2$f Создать сайт Email уже зарегистрирован на WordPress.com\nПереходим ко входу. Зарегистрироваться с адресом Email @@ -1713,11 +1731,7 @@ Language: ru Личная Ожидает проверки Опубликовать - Изменить местоположение - Удалить местоположение - Невозможно открыть средство выбора расположений: службы Google Play недоступны. Сейчас - Местоположение Без этого пароля невозможно просмотреть запись. Цитата — это краткое содержание записи, составляемое по желанию. Слаг — это усечённая версия названия записи для включения в URL-адрес. diff --git a/WordPress/src/main/res/values-sk/strings.xml b/WordPress/src/main/res/values-sk/strings.xml index d6e6886610d7..7c0a222b5fae 100644 --- a/WordPress/src/main/res/values-sk/strings.xml +++ b/WordPress/src/main/res/values-sk/strings.xml @@ -464,7 +464,6 @@ Language: sk 1 príspevok s 1 súborom neboli nahrané (Bez názvu) \@%s - %1$f, %2$f Vytvoriť webovú stránku Klepnutím pokračujte. Webová stránka bola vytvorená! @@ -754,10 +753,6 @@ Language: sk Koncept Nepotvrdená recenzia Zverejniť - Zmeniť polohu - Odstrániť polohu - Nemožno otvoriť Location Picker, Google Play Services nie je dostupné. - Poloha Teraz Len tí, ktorí majú heslo môžu vidieť článok. Zhrnutia sú nepovinné ručne vyrobené zhrnutia vášho obsahu. diff --git a/WordPress/src/main/res/values-sq/strings.xml b/WordPress/src/main/res/values-sq/strings.xml index 2a12afb67adf..a5d7a1d372cb 100644 --- a/WordPress/src/main/res/values-sq/strings.xml +++ b/WordPress/src/main/res/values-sq/strings.xml @@ -41,7 +41,6 @@ Language: sq_AL Menuja e blloqeve u mbyll. Anashkaloje Zgjidhni - Zgjidhni skemën e parapëlqyer për faqen tuaj hyrëse. Mund ta përshtatni ose ndryshoni më vonë. Zgjidhni një skemë Prekni <code>Retry</code>, kur të jeni prapë të lidhur, ose krijoni një faqe të zbrazët duke përdorur butonin më poshtë. S’mund të kihen skema, teksa jeni jashtë linje @@ -305,7 +304,6 @@ Language: sq_AL %1$s · %2$s Provoni një skemë sa për fillim Hap Menu Veprimesh Blloqesh - Futni përmendje Prekeni dyfish që të hapet Fleta e Poshtme me mundësitë e gatshme Prekeni dyfish që të hapet Fleta e Veprimeve me mundësitë e gatshme S’hapim dot faqe tani. Ju lutemi, riprovoni më vonë @@ -472,7 +470,6 @@ Language: sq_AL Botuar Lidhja Facebook s’gjen dot ndonjë Faqe. Publicize s’mund të lidhet me Profile Facebook, vetëm me Faqe të botuara. I palidhur - Adresë Sajti Pëlqime Ndjekje Komente @@ -970,7 +967,6 @@ Language: sq_AL Krijoje Sajtin Kërkoni te Përkatësitë Ky është vendi ku do t’ju gjejnë njerëzit në internet. - Zgjidhni emër përkatësie për sajtin tuaj S’ka adresa me përputhje me kërkimin tuaj Gabim gjatë komunikimit me shërbyesin, ju lutemi, riprovoni Pati një problem @@ -1421,7 +1417,6 @@ Language: sq_AL 1 postim me 1 kartelë të pangarkuar (Pa titull) \@%s - %1$f, %2$f Krijoje sajtin Prekeni që të vazhdohet. Sajti u krijua! @@ -1712,10 +1707,6 @@ Language: sq_AL Skicë Në pritje të shqyrtimit Botojeni - Ndryshoni Vendndodhje - Hiqe Vendndodhjen - S’hapet dot Location Picker, Google Play Services s’është i passhëm - Vendndodhje Tani Vetëm ata me këtë fjalëkalim mund të shohin këtë postim Copëzat janë përmbledhje opsionale të lëndës tuaj, hartuar dorazi. diff --git a/WordPress/src/main/res/values-sr/strings.xml b/WordPress/src/main/res/values-sr/strings.xml index fcff1d246526..7b05f8d55b47 100644 --- a/WordPress/src/main/res/values-sr/strings.xml +++ b/WordPress/src/main/res/values-sr/strings.xml @@ -250,7 +250,6 @@ Language: sr_RS Објављено Направите чланак Није повезано - Адреса сајта Коментари Праћења Свиђања @@ -947,7 +946,6 @@ Language: sr_RS 1 чланак са 1 датотеком није отпремљен (Без наслова) \@%s - %1$f, %2$f Направити веб локацију Додирните за наставак. Веб локација направљена! @@ -1172,9 +1170,6 @@ Language: sr_RS Нацрт Чека рецензију Објави - Промени локацију - Уклони локацију - Локација Сада Ознаке Облик чланка diff --git a/WordPress/src/main/res/values-sv/strings.xml b/WordPress/src/main/res/values-sv/strings.xml index d9c59879c0b1..f0a5905e5e18 100644 --- a/WordPress/src/main/res/values-sv/strings.xml +++ b/WordPress/src/main/res/values-sv/strings.xml @@ -1,11 +1,33 @@ + Filnamn + Redigera fil + VÄLJ EN FIL + Kopiera filens URL + Kunde inte spara filerna.\nTryck för att visa alternativ. + Kunde inte ladda upp filerna.\nTryck för att visa alternativ. + Inställningar för filblock + Välj en domän + Jetpack + Prenumeration på kommentarer har avslutats + Ett fel inträffade när prenumerationsstatusen för inlägget skulle hämtas + Det gick inte att prenumerera på kommentarer till detta inlägg + Det gick inte att avsluta prenumerationen på kommentarer till detta inlägg + Följ konversation + Följer konversation + Inställningar för Jetpack + Ny + Rensa + Utför + Inget svar har tagits emot + Ett ogiltigt svar har tagits emot + Prenumeration på kommentarer har startats En eller flera bilder lades inte till i din berättelse eftersom berättelser för närvarande saknar stöd för GIF-filer. Välj en statisk bild eller en video som bakgrund i stället. Denna berättelse har redigerats på en annan typ av enhet och möjligheten att redigera vissa objekt kan vara begränsad. Det går inte att redigera berättelsen. @@ -308,7 +330,6 @@ Language: sv_SE Öppna menyn för blockåtgärder Dubbeltryck för att öppna åtgärdsbladet med tillgängliga alternativ Dubbeltryck för att öppna det nedre arket med tillgänliga alternativ - Infoga omnämnande ”%s är inte en giltig användare” Välj sida Statisk startsida @@ -473,7 +494,6 @@ Language: sv_SE Publicerade Facebook-kopplingen hittar inga sidor. Publicize kan inte kopplas till Facebook-profiler, utan endast till publicerade sidor. Inte ansluten - Webbplatsadress Gillamarkeringar Följer Kommentarer @@ -971,7 +991,6 @@ Language: sv_SE Skapa webbplats Sök domäner Det är där andra människor hittar dig på internet. - Välj ett domännamn för din webbplats Det inns ingen adress som matchar din sökning Kommunikationen med servern fungerar inte. Försök igen Ett fel har inträffat @@ -1416,7 +1435,6 @@ Language: sv_SE %1$d inlägg med %2$d filer laddades inte upp %1$d inlägg laddades inte upp \@%s - %f, %f 1 sida med 1 fil laddades inte upp %1$d inlägg/sidor med 1 fil laddades inte upp %1$d sidor med 1 fil laddades inte upp @@ -1713,10 +1731,6 @@ Language: sv_SE Utkast Väntar på granskning Publicera - Ändra plats - Ta bort plats - Det går inte att öppna platsväljaren, Tjänsten Google Play är inte tillgänglig - Plats Nu Man behöver lösenord för att se detta inlägg Utdrag är valfria handskrivna sammanfattningar av ditt innehåll. diff --git a/WordPress/src/main/res/values-tr/strings.xml b/WordPress/src/main/res/values-tr/strings.xml index 572a26c9cd87..0c4bb053ebc9 100644 --- a/WordPress/src/main/res/values-tr/strings.xml +++ b/WordPress/src/main/res/values-tr/strings.xml @@ -1,11 +1,20 @@ + Öyküler şu anda GIF dosyalarını desteklemediği için bir veya daha fazla slayt öykünüze eklenmedi. Lütfen bunun yerine statik bir resim veya video arka planı seçin. + GIF dosyaları desteklenmez + Bu öykü için medyayı sitede bulamadık. + Öykü düzenlenemiyor + Bu öykü için medya yüklenemiyor. İnternet bağlantınızı kontrol edin ve bir süre sonra tekrar deneyin. + Öykü düzenlenemiyor + Bu öykü farklı bir cihazda düzenlendi ve belirli nesneleri düzenleme yeteneği sınırlı olabilir. + Sınırlı Öykü Düzenleme + Ortam kaldırıldı. Öykünüzü düzenlemeyi deneyin. Arka plan Metin Vazgeç @@ -32,7 +41,6 @@ Language: tr Kaydırılabilir blok menüsü kapandı. Atla Seç - Favori ana sayfa düzeninizi seçin. Daha sonra özelleştirebilir ya da değiştirebilirsiniz. Bir tasarım seçin Tekrar çevrimiçi olduğunuzda yeniden dene seçeneğine dokunun veya aşağıdaki düğmeyi kullanarak boş bir sayfa oluşturun. Çevrimdışıyken düzenler kullanılamaz @@ -296,7 +304,6 @@ Language: tr %1$s · %2$s Başlangıç düzenini deneyin Blok eylemleri menüsünü aç - Bahsetme ekle Uygun seçenekleri içeren Alt Sayfayı açmak için iki kez dokunun Uygun seçenekleri içeren Eylem Sayfasını açmak için iki kez dokunun Yazılar sayfası @@ -463,7 +470,6 @@ Language: tr Yayımlandı Facebook bağlantısı hiçbir sayfa bulamıyor. Duyuru, Facebook profillerine bağlanamaz, yalnızca yayınlanan sayfalara bağlanabilir. Bağlı değil - Site adresi Beğeniler Takipçiler Yorumlar @@ -961,7 +967,6 @@ Language: tr Site Oluşturma Sihirbazını İptal Et Yeni sitenizi oluşturuyoruz Bu, insanların sizi internette bulacakları yerdir. - Siteniz için bir alan adı seçin Aramanızla eşleşen hiçbir adres bulunamadı Sunucu ile iletişim kurulurken hata oluştu, lütfen tekrar deneyin Bir hata oluştu @@ -1409,7 +1414,6 @@ Language: tr 1 dosya ile 1 sayfa karşıya yüklenmedi (İsimsiz) \@%s - %1$f, %2$f 1 dosya ile 1 yazı karşıya yüklenmedi 1 dosya ile %1$d yazı karşıya yüklenmedi 1 dosya ile %1$d yazı/sayfa karşıya yüklenmedi @@ -1703,10 +1707,6 @@ Language: tr Taslak İnceleme bekliyor Yayımlanmış - Konumu değiştir - Konumu kaldır - Konum seçicisi açılamıyor, Google Play servisleri uygun durumda değil - Konum Şimdi Sadee parolaya sahip olanlar bu yazıyı görüntüleyebilirler Özetler içeriğinizin içinden özel olarak el ile hazırlanmış kısa içeriklerdir. diff --git a/WordPress/src/main/res/values-zh-rCN/strings.xml b/WordPress/src/main/res/values-zh-rCN/strings.xml index 5d8f49f91d33..2bc564e72efd 100644 --- a/WordPress/src/main/res/values-zh-rCN/strings.xml +++ b/WordPress/src/main/res/values-zh-rCN/strings.xml @@ -41,7 +41,6 @@ Language: zh_CN 滚动区块菜单关闭。 跳过 选择 - 选择您喜欢的主页布局。 您以后可以随时定制或更改。 选择设计 重新上线后,点击“重试”,或使用下面的按钮创建空白页。 离线时布局不可用 @@ -306,7 +305,6 @@ Language: zh_CN %1$s· %2$s 试用初学者布局 打开区块操作菜单 - 插入提及 双击以打开带有可用选项的底部表页 双击以打开带有可用选项的操作表页 目前我们无法打开页面。请稍后重试 @@ -473,7 +471,6 @@ Language: zh_CN 已发布 Facebook 连接无法找到任何页面。Publicize 无法连接到 Facebook 个人资料,只能连接到已发布的页面。 未连接 - 站点地址 关注 评论 @@ -971,7 +968,6 @@ Language: zh_CN 创建站点 搜索域 人们可以通过此域名在互联网上找到您。 - 为您的站点选择一个域名 没有与您的搜索内容相匹配的地址 与服务器通信时出错,请重试 出现问题 @@ -1422,7 +1418,6 @@ Language: zh_CN 1 篇文章和 1 个文件未上传 (无标题) \@%s - %1$f,%2$f 创建站点 轻按以继续。 站点已创建! @@ -1713,10 +1708,6 @@ Language: zh_CN 草稿 待审核 发布 - 更改位置 - 删除位置 - 无法打开位置选取器,「Google Play 服务」不可用 - 位置 现在 只有知道此密码的用户才能查看这篇文章 摘录是您内容的概要,可以手动编写,也可自动生成。 diff --git a/WordPress/src/main/res/values-zh-rHK/strings.xml b/WordPress/src/main/res/values-zh-rHK/strings.xml index b2daa95f82ab..65e17cc13264 100644 --- a/WordPress/src/main/res/values-zh-rHK/strings.xml +++ b/WordPress/src/main/res/values-zh-rHK/strings.xml @@ -1,11 +1,20 @@ + 一或多張投影片並未加入你的限時動態,因為「限時動態」功能目前不支援 GIF 檔案。 請改為選擇靜態圖片或影片背景。 + 不支援 GIF 檔案 + 我們無法在網站上找到這個限時動態使用的媒體。 + 無法編輯限時動態 + 無法載入這個限時動態的媒體 請檢查你的網際網路連線,並稍後再試一次。 + 無法編輯限時動態 + 這個限時動態已在不同裝置上編輯過,因此特定物件的編輯功能可能受到限制。 + 限時動態編輯功能受限 + 媒體已移除。 請嘗試編輯你的限時動態。 背景 文字 捨棄 @@ -32,7 +41,6 @@ Language: zh_TW 已關閉可捲動的區塊選單。 跳過 選擇 - 選擇你喜愛的首頁版面配置。 你之後可以隨時自訂或變更。 選擇一款設計 請在重新上線時點選重試,或是使用下方按鈕建立空白頁面。 版面配置在離線時無法使用 @@ -293,7 +301,6 @@ Language: zh_TW %1$s · %2$s 試用入門版面配置 開啟區塊操作選單 - 插入標記 按兩下以開啟含有可用選項的底部工作表 按兩下以開啟含有可用選項的操作工作表 目前我們無法開啟頁面。請稍後再試一次 @@ -460,7 +467,6 @@ Language: zh_TW 已發佈 Facebook 連結找不到任何頁面。Publicize 無法連結至 Facebook 個人檔案,只能連結至已發表的頁面。 未連線 - 網站位址 按讚數 關注者 留言 @@ -951,7 +957,6 @@ Language: zh_TW 建立網站 搜尋網域 這是人們在網際網路上找到你的地方。 - 選擇網站的網域名稱 找不到你搜尋的網址 與伺服器通訊時發生錯誤,請再試一次 發生問題 @@ -1395,7 +1400,6 @@ Language: zh_TW 無法上傳 1 篇文章和 1 個檔案 (未命名) \@%s - %1$f,%2$f 建立網站 點選以繼續。 網站已建立! @@ -1683,10 +1687,6 @@ Language: zh_TW 草稿 待審中 發佈 - 變更位置 - 移除位置 - 無法開啟位置挑選器,Google Play 服務無法使用 - 位置 立即 只有知道密碼的使用者可檢視這篇文章 文章摘要是指選擇性手動摘錄的內容。 diff --git a/WordPress/src/main/res/values-zh-rTW/strings.xml b/WordPress/src/main/res/values-zh-rTW/strings.xml index b2daa95f82ab..65e17cc13264 100644 --- a/WordPress/src/main/res/values-zh-rTW/strings.xml +++ b/WordPress/src/main/res/values-zh-rTW/strings.xml @@ -1,11 +1,20 @@ + 一或多張投影片並未加入你的限時動態,因為「限時動態」功能目前不支援 GIF 檔案。 請改為選擇靜態圖片或影片背景。 + 不支援 GIF 檔案 + 我們無法在網站上找到這個限時動態使用的媒體。 + 無法編輯限時動態 + 無法載入這個限時動態的媒體 請檢查你的網際網路連線,並稍後再試一次。 + 無法編輯限時動態 + 這個限時動態已在不同裝置上編輯過,因此特定物件的編輯功能可能受到限制。 + 限時動態編輯功能受限 + 媒體已移除。 請嘗試編輯你的限時動態。 背景 文字 捨棄 @@ -32,7 +41,6 @@ Language: zh_TW 已關閉可捲動的區塊選單。 跳過 選擇 - 選擇你喜愛的首頁版面配置。 你之後可以隨時自訂或變更。 選擇一款設計 請在重新上線時點選重試,或是使用下方按鈕建立空白頁面。 版面配置在離線時無法使用 @@ -293,7 +301,6 @@ Language: zh_TW %1$s · %2$s 試用入門版面配置 開啟區塊操作選單 - 插入標記 按兩下以開啟含有可用選項的底部工作表 按兩下以開啟含有可用選項的操作工作表 目前我們無法開啟頁面。請稍後再試一次 @@ -460,7 +467,6 @@ Language: zh_TW 已發佈 Facebook 連結找不到任何頁面。Publicize 無法連結至 Facebook 個人檔案,只能連結至已發表的頁面。 未連線 - 網站位址 按讚數 關注者 留言 @@ -951,7 +957,6 @@ Language: zh_TW 建立網站 搜尋網域 這是人們在網際網路上找到你的地方。 - 選擇網站的網域名稱 找不到你搜尋的網址 與伺服器通訊時發生錯誤,請再試一次 發生問題 @@ -1395,7 +1400,6 @@ Language: zh_TW 無法上傳 1 篇文章和 1 個檔案 (未命名) \@%s - %1$f,%2$f 建立網站 點選以繼續。 網站已建立! @@ -1683,10 +1687,6 @@ Language: zh_TW 草稿 待審中 發佈 - 變更位置 - 移除位置 - 無法開啟位置挑選器,Google Play 服務無法使用 - 位置 立即 只有知道密碼的使用者可檢視這篇文章 文章摘要是指選擇性手動摘錄的內容。 From add9d8bb127ce496a672627387e2825b108249f6 Mon Sep 17 00:00:00 2001 From: Jeremy Massel Date: Fri, 4 Dec 2020 23:18:20 -0700 Subject: [PATCH 063/144] Bump version number --- WordPress/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 1653ee0a4aea..c5876e33e3de 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -54,9 +54,9 @@ android { if (project.hasProperty("versionName")) { versionName project.property("versionName") } else { - versionName "alpha-261" + versionName "alpha-262" } - versionCode 965 + versionCode 967 minSdkVersion rootProject.minSdkVersion targetSdkVersion rootProject.targetSdkVersion @@ -98,9 +98,9 @@ android { dimension "buildType" // Only set the release version if one isn't provided if (!project.hasProperty("versionName")) { - versionName "16.3-rc-2" + versionName "16.3-rc-3" } - versionCode 964 + versionCode 966 buildConfigField "boolean", "ME_ACTIVITY_AVAILABLE", "false" buildConfigField "boolean", "TENOR_AVAILABLE", "false" buildConfigField "long", "REMOTE_CONFIG_FETCH_INTERVAL", "3600" From 3c463888cc306ef61e6558e759b3ca4328c09c7f Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Mon, 7 Dec 2020 16:09:47 +0100 Subject: [PATCH 064/144] Add logging for stats inconsistency --- .../granular/usecases/OverviewUseCase.kt | 41 +++++++++++ .../granular/usecases/OverviewUseCaseTest.kt | 69 +++++++++++++++++++ .../android/analytics/AnalyticsTracker.java | 1 + .../analytics/AnalyticsTrackerNosara.java | 2 + 4 files changed, 113 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt index fc7fba04378f..1c10e0b1a270 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt @@ -3,6 +3,8 @@ package org.wordpress.android.ui.stats.refresh.lists.sections.granular.usecases import kotlinx.coroutines.CoroutineDispatcher import org.wordpress.android.R import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_OVERVIEW_ERROR +import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.model.stats.LimitMode import org.wordpress.android.fluxc.model.stats.time.VisitsAndViewsModel import org.wordpress.android.fluxc.network.utils.StatsGranularity @@ -23,10 +25,13 @@ import org.wordpress.android.ui.stats.refresh.utils.toStatsSection import org.wordpress.android.ui.stats.refresh.utils.trackGranular import org.wordpress.android.util.AppLog import org.wordpress.android.util.AppLog.T +import org.wordpress.android.util.LocaleManagerWrapper import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import org.wordpress.android.viewmodel.ResourceProvider +import java.util.Calendar import javax.inject.Inject import javax.inject.Named +import kotlin.math.ceil const val OVERVIEW_ITEMS_TO_LOAD = 15 @@ -42,6 +47,7 @@ constructor( @Named(BG_THREAD) private val backgroundDispatcher: CoroutineDispatcher, private val analyticsTracker: AnalyticsTrackerWrapper, private val statsWidgetUpdaters: StatsWidgetUpdaters, + private val localeManagerWrapper: LocaleManagerWrapper, private val resourceProvider: ResourceProvider ) : BaseStatsUseCase( OVERVIEW, @@ -68,6 +74,7 @@ constructor( LimitMode.All ) if (cachedData != null) { + logIfIncorrectData(cachedData, statsGranularity, statsSiteProvider.siteModel, false) selectedDateProvider.onDateLoadingSucceeded(statsGranularity) } return cachedData @@ -89,6 +96,7 @@ constructor( State.Error(error.message ?: error.type.name) } model != null && model.dates.isNotEmpty() -> { + logIfIncorrectData(model, statsGranularity, statsSiteProvider.siteModel, true) selectedDateProvider.onDateLoadingSucceeded(statsGranularity) State.Data(model) } @@ -99,6 +107,37 @@ constructor( } } + /** + * Track the incorrect data shown for some users + * see https://github.com/wordpress-mobile/WordPress-Android/issues/11412 + */ + private fun logIfIncorrectData( + model: VisitsAndViewsModel, + granularity: StatsGranularity, + site: SiteModel, + fetched: Boolean + ) { + model.dates.lastOrNull()?.let { lastDayData -> + val yesterday = localeManagerWrapper.getCurrentCalendar() + yesterday.add(Calendar.DAY_OF_YEAR, -1) + val lastDayDate = statsDateFormatter.parseStatsDate(granularity, lastDayData.period) + if (lastDayDate.before(yesterday.time)) { + val currentCalendar = localeManagerWrapper.getCurrentCalendar() + analyticsTracker.track( + STATS_OVERVIEW_ERROR, + mapOf( + "stats_last_date" to statsDateFormatter.printStatsDate(lastDayDate), + "stats_current_date" to statsDateFormatter.printStatsDate(currentCalendar.time), + "stats_age_in_days" to ceil((currentCalendar.timeInMillis - lastDayDate.time) / 86400000.0).toInt(), + "is_jetpack_connected" to site.isJetpackConnected, + "is_atomic" to site.isWPComAtomic, + "action_source" to if (fetched) "remote" else "cached" + ) + ) + } + } + } + override fun buildUiModel( domainModel: VisitsAndViewsModel, uiState: UiState @@ -195,6 +234,7 @@ constructor( private val visitsAndViewsStore: VisitsAndViewsStore, private val analyticsTracker: AnalyticsTrackerWrapper, private val statsWidgetUpdaters: StatsWidgetUpdaters, + private val localeManagerWrapper: LocaleManagerWrapper, private val resourceProvider: ResourceProvider ) : GranularUseCaseFactory { override fun build(granularity: StatsGranularity, useCaseMode: UseCaseMode) = @@ -209,6 +249,7 @@ constructor( backgroundDispatcher, analyticsTracker, statsWidgetUpdaters, + localeManagerWrapper, resourceProvider ) } diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt index 78b8c0b00833..e4ae32c74660 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt @@ -1,7 +1,9 @@ package org.wordpress.android.ui.stats.refresh.lists.sections.granular.usecases import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.eq import com.nhaarman.mockitokotlin2.isNull +import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.times import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever @@ -14,6 +16,7 @@ import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.R import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_OVERVIEW_ERROR import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.model.stats.LimitMode import org.wordpress.android.fluxc.model.stats.LimitMode.Top @@ -35,8 +38,10 @@ import org.wordpress.android.ui.stats.refresh.lists.sections.granular.SelectedDa import org.wordpress.android.ui.stats.refresh.lists.widget.WidgetUpdater.StatsWidgetUpdaters import org.wordpress.android.ui.stats.refresh.utils.StatsDateFormatter import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider +import org.wordpress.android.util.LocaleManagerWrapper import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import org.wordpress.android.viewmodel.ResourceProvider +import java.util.Calendar class OverviewUseCaseTest : BaseUnitTest() { @Mock lateinit var store: VisitsAndViewsStore @@ -50,6 +55,7 @@ class OverviewUseCaseTest : BaseUnitTest() { @Mock lateinit var barChartItem: BarChartItem @Mock lateinit var analyticsTrackerWrapper: AnalyticsTrackerWrapper @Mock lateinit var statsWidgetUpdaters: StatsWidgetUpdaters + @Mock lateinit var localeManagerWrapper: LocaleManagerWrapper private lateinit var useCase: OverviewUseCase private val site = SiteModel() private val siteId = 1L @@ -58,6 +64,7 @@ class OverviewUseCaseTest : BaseUnitTest() { private val limitMode = Top(15) private val statsGranularity = DAYS private val model = VisitsAndViewsModel(modelPeriod, listOf(periodData)) + @InternalCoroutinesApi @Before fun setUp() { @@ -72,6 +79,7 @@ class OverviewUseCaseTest : BaseUnitTest() { TEST_DISPATCHER, analyticsTrackerWrapper, statsWidgetUpdaters, + localeManagerWrapper, resourceProvider ) site.siteId = siteId @@ -85,6 +93,7 @@ class OverviewUseCaseTest : BaseUnitTest() { @Test fun `maps domain model to UI model`() = test { val forced = false + setupCalendar() whenever(store.getVisits(site, statsGranularity, LimitMode.All)).thenReturn(model) whenever(store.fetchVisits(site, statsGranularity, limitMode, forced)).thenReturn( OnStatsFetched( @@ -119,6 +128,66 @@ class OverviewUseCaseTest : BaseUnitTest() { assertThat(result.state).isEqualTo(UseCaseState.ERROR) } + @Test + fun `does not track incorrect data when the last stats item is less than 2 days old`() = test { + val forced = false + setupCalendar(1) + whenever(store.fetchVisits(site, statsGranularity, limitMode, forced)).thenReturn( + OnStatsFetched( + model + ) + ) + + loadData(true, forced) + + verify(analyticsTrackerWrapper, never()).track(eq(STATS_OVERVIEW_ERROR), any>()) + } + + @Test + fun `tracks incorrect data when the last stats item is at least 2 days old`() = test { + val forced = false + setupCalendar(2) + whenever(store.fetchVisits(site, statsGranularity, limitMode, forced)).thenReturn( + OnStatsFetched( + model + ) + ) + + loadData(true, forced) + + verify(analyticsTrackerWrapper).track( + STATS_OVERVIEW_ERROR, mapOf( + "stats_last_date" to "2020-12-13", + "stats_current_date" to "2020-12-15", + "stats_age_in_days" to 2, + "is_jetpack_connected" to false, + "is_atomic" to false, + "action_source" to "remote" + ) + ) + } + + private fun setupCalendar(ageOfLastStatsItemInDays: Int = 0) { + val today = Calendar.getInstance() + today.set(Calendar.YEAR, 2020) + today.set(Calendar.MONTH, 11) + val todayDay = 15 + today.set(Calendar.DAY_OF_MONTH, todayDay) + today.set(Calendar.HOUR_OF_DAY, 20) + val lastItemAge = Calendar.getInstance() + lastItemAge.time = today.time + val lastItemDay = todayDay - ageOfLastStatsItemInDays + lastItemAge.set(Calendar.DAY_OF_MONTH, lastItemDay) + lastItemAge.set(Calendar.HOUR_OF_DAY, 22) + whenever(localeManagerWrapper.getCurrentCalendar()).then { + Calendar.getInstance() + .apply { this.time = today.time } + } + whenever(statsDateFormatter.parseStatsDate(any(), any())).thenReturn(lastItemAge.time) + whenever(statsDateFormatter.printStatsDate(lastItemAge.time)).thenReturn("2020-12-$lastItemDay") + whenever(statsDateFormatter.printStatsDate(today.time)).thenReturn("2020-12-$todayDay") + } + private suspend fun loadData(refresh: Boolean, forced: Boolean): UseCaseModel { var result: UseCaseModel? = null useCase.liveData.observeForever { result = it } diff --git a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java index 33654f4cbf80..b539ba5017c2 100644 --- a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java +++ b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java @@ -110,6 +110,7 @@ public enum Stat { STATS_CLICKS_VIEW_MORE_TAPPED, STATS_COUNTRIES_VIEW_MORE_TAPPED, STATS_OVERVIEW_BAR_CHART_TAPPED, + STATS_OVERVIEW_ERROR, STATS_VIDEO_PLAYS_VIEW_MORE_TAPPED, STATS_SEARCH_TERMS_VIEW_MORE_TAPPED, STATS_AUTHORS_VIEW_MORE_TAPPED, diff --git a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java index 910843d78033..ccd34a2d72a1 100644 --- a/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java +++ b/libs/analytics/WordPressAnalytics/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerNosara.java @@ -1144,6 +1144,8 @@ public static String getEventNameForStat(AnalyticsTracker.Stat stat) { return "stats_countries_view_more_tapped"; case STATS_OVERVIEW_BAR_CHART_TAPPED: return "stats_overview_bar_chart_tapped"; + case STATS_OVERVIEW_ERROR: + return "stats_overview_error"; case STATS_VIDEO_PLAYS_VIEW_MORE_TAPPED: return "stats_video_plays_view_more_tapped"; case STATS_VIDEO_PLAYS_VIDEO_TAPPED: From 39641c4e417ebc69f8c3cebc9d1d5be1ab2771b3 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Mon, 7 Dec 2020 20:01:30 -0500 Subject: [PATCH 065/144] Update strings --- WordPress/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index dd9691afe571..98eae16376fe 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -3075,6 +3075,7 @@ Blog CHOOSE A FILE + Choose file Choose from device Choose image Choose image or video @@ -3125,6 +3126,7 @@ Edit video Email me: <a href=\"mailto:mail@example.com\">mail@example.com</a> + Error Excerpt length (words) Failed to insert media.\nPlease tap for options. Failed to save files.\nPlease tap for options. From a4bba26869a23d13d0b7c4c782a424dff17bd011 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Mon, 7 Dec 2020 20:10:41 -0500 Subject: [PATCH 066/144] Updated gutenberg ref --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 7c2eb0b3b95e..2a6cc0b3b095 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 7c2eb0b3b95efb1035b90cadac07386d6db6f52a +Subproject commit 2a6cc0b3b0950938432888bf927a2219a4ad0255 From 16032cea9126948bce83eee172ee0eca3fb7626d Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Tue, 8 Dec 2020 09:51:48 +0100 Subject: [PATCH 067/144] Address PR comments --- .../wordpress/android/ui/mysite/ImprovedMySiteFragment.kt | 4 +--- .../java/org/wordpress/android/ui/mysite/MySiteViewModel.kt | 2 +- .../org/wordpress/android/ui/mysite/SiteStoriesHandler.kt | 5 ++--- .../android/ui/stories/StoriesMediaPickerResultHandler.kt | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt index 961e448419bd..c736cd39b391 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt @@ -60,7 +60,6 @@ import org.wordpress.android.ui.photopicker.MediaPickerLauncher import org.wordpress.android.ui.photopicker.PhotoPickerActivity.PhotoPickerMediaSource import org.wordpress.android.ui.posts.BasicDialogViewModel import org.wordpress.android.ui.posts.BasicDialogViewModel.BasicDialogModel -import org.wordpress.android.ui.stories.StoriesMediaPickerResultHandler import org.wordpress.android.ui.uploads.UploadService import org.wordpress.android.ui.uploads.UploadUtilsWrapper import org.wordpress.android.ui.utils.UiHelpers @@ -87,7 +86,6 @@ class ImprovedMySiteFragment : Fragment(), @Inject lateinit var meGravatarLoader: MeGravatarLoader @Inject lateinit var mediaPickerLauncher: MediaPickerLauncher @Inject lateinit var uploadUtilsWrapper: UploadUtilsWrapper - @Inject lateinit var storiesMediaPickerResultHandler: StoriesMediaPickerResultHandler private lateinit var viewModel: MySiteViewModel private lateinit var dialogViewModel: BasicDialogViewModel @@ -343,7 +341,7 @@ class ImprovedMySiteFragment : Fragment(), } RequestCodes.STORIES_PHOTO_PICKER, RequestCodes.PHOTO_PICKER -> if (resultCode == Activity.RESULT_OK) { - viewModel.onStoriesPhotoPicker(data) + viewModel.handleStoriesPhotoPickerResult(data) } UCrop.REQUEST_CROP -> { if (resultCode == UCrop.RESULT_ERROR) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index cbd807a8e35a..23e18bc5bab2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -383,7 +383,7 @@ class MySiteViewModel super.onCleared() } - fun onStoriesPhotoPicker(data: Intent) { + fun handleStoriesPhotoPickerResult(data: Intent) { selectedSiteRepository.getSelectedSite()?.let { siteStoriesHandler.handleStoriesResult(it, data, STORY_FROM_MY_SITE) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt index 8b6eb5de2aff..5e085754ea2c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteStoriesHandler.kt @@ -8,7 +8,6 @@ import com.wordpress.stories.compose.frame.StorySaveEvents import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveProcessStart import com.wordpress.stories.compose.frame.StorySaveEvents.StorySaveResult import com.wordpress.stories.compose.story.StoryRepository -import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.R @@ -52,7 +51,7 @@ class SiteStoriesHandler @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) fun onEventMainThread(event: StorySaveResult) { - EventBus.getDefault().removeStickyEvent(event) + eventBusWrapper.removeStickyEvent(event) if (!event.isSuccess()) { // note: no tracking added here as we'll perform tracking in StoryMediaSaveUploadBridge val errorText = String.format( @@ -91,7 +90,7 @@ class SiteStoriesHandler @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) fun onStorySaveStart(event: StorySaveProcessStart) { - EventBus.getDefault().removeStickyEvent(event) + eventBusWrapper.removeStickyEvent(event) val snackbarMessage = String.format( resourceProvider.getString(R.string.story_saving_snackbar_started), StoryRepository.getStoryAtIndex(event.storyIndex).title diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt index 98e94844607e..854bb695850f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stories/StoriesMediaPickerResultHandler.kt @@ -24,7 +24,7 @@ class StoriesMediaPickerResultHandler private val _onNavigation = MutableLiveData>() val onNavigation = _onNavigation as LiveData> - /* return true if MediaPickerResult was handled */ + @Deprecated("Use rather the other handle method and the live data navigation.") fun handleMediaPickerResultForStories( data: Intent, activity: Activity?, From 124268f447e6c96a294940c6a3aa28bd018df47f Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Tue, 8 Dec 2020 10:27:43 +0100 Subject: [PATCH 068/144] Fix lint issue --- .../lists/sections/granular/usecases/OverviewUseCase.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt index 1c10e0b1a270..ea21786fbe90 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCase.kt @@ -123,12 +123,13 @@ constructor( val lastDayDate = statsDateFormatter.parseStatsDate(granularity, lastDayData.period) if (lastDayDate.before(yesterday.time)) { val currentCalendar = localeManagerWrapper.getCurrentCalendar() + val lastItemAge = ceil((currentCalendar.timeInMillis - lastDayDate.time) / 86400000.0) analyticsTracker.track( STATS_OVERVIEW_ERROR, mapOf( "stats_last_date" to statsDateFormatter.printStatsDate(lastDayDate), "stats_current_date" to statsDateFormatter.printStatsDate(currentCalendar.time), - "stats_age_in_days" to ceil((currentCalendar.timeInMillis - lastDayDate.time) / 86400000.0).toInt(), + "stats_age_in_days" to lastItemAge.toInt(), "is_jetpack_connected" to site.isJetpackConnected, "is_atomic" to site.isWPComAtomic, "action_source" to if (fetched) "remote" else "cached" From 7ba3df7bcd0a0d67b988d6b78619a666bcffcba7 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 10:03:12 -0500 Subject: [PATCH 069/144] Add check for backupFeatureConfig --- .../ui/activitylog/list/ActivityLogListActivity.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt index 7cbec273f02b..9056879358e8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt @@ -5,17 +5,23 @@ import android.os.Bundle import android.view.MenuItem import kotlinx.android.synthetic.main.toolbar_main.* import org.wordpress.android.R +import org.wordpress.android.WordPress import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.LocaleAwareActivity import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.posts.BasicFragmentDialog +import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.viewmodel.activitylog.ACTIVITY_LOG_REWIND_ID_KEY +import javax.inject.Inject class ActivityLogListActivity : LocaleAwareActivity(), BasicFragmentDialog.BasicDialogPositiveClickInterface, - BasicFragmentDialog.BasicDialogNegativeClickInterface { + BasicFragmentDialog.BasicDialogNegativeClickInterface +{ + @Inject lateinit var backupFeatureConfig: BackupFeatureConfig override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + (application as WordPress).component().inject(this) setContentView(R.layout.activity_log_list_activity) @@ -49,7 +55,9 @@ class ActivityLogListActivity : LocaleAwareActivity(), override fun onNegativeClicked(instanceTag: String) { // todo: annmarie - this is temporary to expose backup feature - ActivityLauncher.showBackupDownload(this) + if (backupFeatureConfig.isEnabled()) { + ActivityLauncher.showBackupDownload(this) + } } private fun passRewindConfirmation(rewindId: String) { From a4dfffe3a4168e88e5c91da4a59adff0c953028b Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 8 Dec 2020 17:05:39 +0200 Subject: [PATCH 070/144] Adds Duplicate/Copy post functionality (#13521) * Added Copy Button in the UI * Copy post without the editor * Tests copy post action * Resolve conflicts with edit * Updated release notes * Refresh list after post creation * Updated fluxc version --- RELEASE-NOTES.txt | 3 +- .../android/ui/posts/PostActionHandler.kt | 16 ++- .../android/ui/posts/PostListActionTracker.kt | 2 + .../android/ui/posts/PostListDialogHelper.kt | 34 ++++- .../android/ui/posts/PostListMainViewModel.kt | 40 +++++- .../posts/PostListItemUiStateHelper.kt | 6 + .../android/widgets/PostListButtonType.kt | 3 +- WordPress/src/main/res/values/strings.xml | 7 ++ .../PostListMainViewModelCopyPostTest.kt | 117 ++++++++++++++++++ .../posts/PostListItemUiStateHelperTest.kt | 64 +++++++--- build.gradle | 2 +- 11 files changed, 265 insertions(+), 29 deletions(-) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelCopyPostTest.kt diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 0176053041d0..f15fa97650e8 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,7 +1,8 @@ 16.4 ----- * [*] My Site: Fixes crash on rotation while editing site title [https://github.com/wordpress-mobile/WordPress-Android/pull/13505] - +* [**] Posts List: Adds duplicate post functionality [https://github.com/wordpress-mobile/WordPress-Android/pull/13521] + 16.3 ----- * [***] Site Creation: Adds an option to pick a home page design when creating a WordPress.com site. diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt index ae29191808cf..d8e18537455b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostActionHandler.kt @@ -34,6 +34,7 @@ import org.wordpress.android.util.ToastUtils.Duration import org.wordpress.android.viewmodel.helpers.ToastMessageHolder import org.wordpress.android.widgets.PostListButtonType import org.wordpress.android.widgets.PostListButtonType.BUTTON_CANCEL_PENDING_AUTO_UPLOAD +import org.wordpress.android.widgets.PostListButtonType.BUTTON_COPY import org.wordpress.android.widgets.PostListButtonType.BUTTON_DELETE import org.wordpress.android.widgets.PostListButtonType.BUTTON_DELETE_PERMANENTLY import org.wordpress.android.widgets.PostListButtonType.BUTTON_EDIT @@ -67,7 +68,8 @@ class PostActionHandler( private val checkNetworkConnection: () -> Boolean, private val showSnackbar: (SnackbarMessageHolder) -> Unit, private val showToast: (ToastMessageHolder) -> Unit, - private val triggerPreviewStateUpdate: (PostListRemotePreviewState, PostInfoType) -> Unit + private val triggerPreviewStateUpdate: (PostListRemotePreviewState, PostInfoType) -> Unit, + private val copyPost: (SiteModel, PostModel, Boolean) -> Unit ) { private val criticalPostActionTracker = CriticalPostActionTracker(onStateChanged = { invalidateList.invoke() @@ -112,6 +114,7 @@ class PostActionHandler( else -> trashPost(post) } } + BUTTON_COPY -> copyPost(site, post, true) BUTTON_DELETE, BUTTON_DELETE_PERMANENTLY -> { postListDialogHelper.showDeletePostConfirmationDialog(post) } @@ -168,6 +171,13 @@ class PostActionHandler( triggerPostUploadAction.invoke(PublishPost(dispatcher, site, post)) } + fun resolveConflictsAndEditPost(localPostId: Int) { + val post = postStore.getPostByLocalPostId(localPostId) + if (post != null) { + performChecksAndEdit(site, post) + } + } + fun moveTrashedPostToDraft(localPostId: Int) { val post = postStore.getPostByLocalPostId(localPostId) if (post != null) { @@ -198,7 +208,9 @@ class PostActionHandler( showSnackbar.invoke(snackBarHolder) } - private fun editPostButtonAction(site: SiteModel, post: PostModel) { + private fun editPostButtonAction(site: SiteModel, post: PostModel) = performChecksAndEdit(site, post) + + private fun performChecksAndEdit(site: SiteModel, post: PostModel) { // first of all, check whether this post is in Conflicted state with a more recent remote version if (doesPostHaveUnhandledConflict.invoke(post)) { postListDialogHelper.showConflictedPostResolutionDialog(post) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListActionTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListActionTracker.kt index 3002502577a9..32b7c13b95da 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListActionTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListActionTracker.kt @@ -6,6 +6,7 @@ import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.util.analytics.AnalyticsUtils import org.wordpress.android.widgets.PostListButtonType import org.wordpress.android.widgets.PostListButtonType.BUTTON_CANCEL_PENDING_AUTO_UPLOAD +import org.wordpress.android.widgets.PostListButtonType.BUTTON_COPY import org.wordpress.android.widgets.PostListButtonType.BUTTON_DELETE import org.wordpress.android.widgets.PostListButtonType.BUTTON_DELETE_PERMANENTLY import org.wordpress.android.widgets.PostListButtonType.BUTTON_EDIT @@ -39,6 +40,7 @@ fun trackPostListAction(site: SiteModel, buttonType: PostListButtonType, postDat BUTTON_PREVIEW -> "preview" BUTTON_STATS -> "stats" BUTTON_TRASH -> "trash" + BUTTON_COPY -> "copy" BUTTON_DELETE, BUTTON_DELETE_PERMANENTLY -> "delete" BUTTON_PUBLISH -> "publish" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListDialogHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListDialogHelper.kt index 5a9136a3fee2..c9a6f86982cc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListDialogHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListDialogHelper.kt @@ -18,6 +18,7 @@ private const val CONFIRM_TRASH_POST_WITH_UNSAVED_CHANGES_DIALOG_TAG = private const val CONFIRM_ON_CONFLICT_LOAD_REMOTE_POST_DIALOG_TAG = "CONFIRM_ON_CONFLICT_LOAD_REMOTE_POST_DIALOG_TAG" private const val CONFIRM_ON_AUTOSAVE_REVISION_DIALOG_TAG = "CONFIRM_ON_AUTOSAVE_REVISION_DIALOG_TAG" private const val CONFIRM_SYNC_SCHEDULED_POST_DIALOG_TAG = "CONFIRM_SYNC_SCHEDULED_POST_DIALOG_TAG" +private const val COPY_CONFLICT_DIALOG_TAG = "COPY_CONFLICT_DIALOG_TAG" private const val POST_TYPE = "post_type" /** @@ -37,6 +38,7 @@ class PostListDialogHelper( private var localPostIdForConflictResolutionDialog: Int? = null private var localPostIdForAutosaveRevisionResolutionDialog: Int? = null private var localPostIdForScheduledPostSyncDialog: Int? = null + private var localPostIdForCopyConflictDialog: Int? = null fun showMoveTrashedPostToDraftDialog(post: PostModel) { val dialogHolder = DialogHolder( @@ -137,6 +139,18 @@ class PostListDialogHelper( showDialog.invoke(dialogHolder) } + fun showCopyConflictDialog(post: PostModel) { + val dialogHolder = DialogHolder( + tag = COPY_CONFLICT_DIALOG_TAG, + title = UiStringRes(R.string.dialog_confirm_copy_local_title), + message = UiStringRes(R.string.dialog_confirm_copy_local_message), + positiveButton = UiStringRes(R.string.dialog_confirm_copy_local_edit_button), + negativeButton = UiStringRes(R.string.dialog_confirm_copy_local_copy_button) + ) + localPostIdForCopyConflictDialog = post.id + showDialog.invoke(dialogHolder) + } + fun onPositiveClickedForBasicDialog( instanceTag: String, trashPostWithLocalChanges: (Int) -> Unit, @@ -145,7 +159,8 @@ class PostListDialogHelper( publishPost: (Int) -> Unit, updateConflictedPostWithRemoteVersion: (Int) -> Unit, editRestoredAutoSavePost: (Int) -> Unit, - moveTrashedPostToDraft: (Int) -> Unit + moveTrashedPostToDraft: (Int) -> Unit, + resolveConflictsAndEditPost: (Int) -> Unit ) { when (instanceTag) { CONFIRM_DELETE_POST_DIALOG_TAG -> localPostIdForDeleteDialog?.let { @@ -181,6 +196,10 @@ class PostListDialogHelper( UNPUBLISHED_REVISION_DIALOG_LOAD_UNPUBLISHED_VERSION_CLICKED, mapOf(POST_TYPE to "post")) } + COPY_CONFLICT_DIALOG_TAG -> localPostIdForCopyConflictDialog?.let { + localPostIdForCopyConflictDialog = null + resolveConflictsAndEditPost(it) + } else -> throw IllegalArgumentException("Dialog's positive button click is not handled: $instanceTag") } } @@ -188,7 +207,8 @@ class PostListDialogHelper( fun onNegativeClickedForBasicDialog( instanceTag: String, updateConflictedPostWithLocalVersion: (Int) -> Unit, - editLocalPost: (Int) -> Unit + editLocalPost: (Int) -> Unit, + copyLocalPost: (Int) -> Unit ) { when (instanceTag) { CONFIRM_DELETE_POST_DIALOG_TAG -> localPostIdForDeleteDialog = null @@ -207,6 +227,10 @@ class PostListDialogHelper( ) } CONFIRM_RESTORE_TRASHED_POST_DIALOG_TAG -> localPostIdForMoveTrashedPostToDraftDialog = null + COPY_CONFLICT_DIALOG_TAG -> localPostIdForCopyConflictDialog?.let { + localPostIdForCopyConflictDialog = null + copyLocalPost(it) + } else -> throw IllegalArgumentException("Dialog's negative button click is not handled: $instanceTag") } } @@ -214,7 +238,8 @@ class PostListDialogHelper( fun onDismissByOutsideTouchForBasicDialog( instanceTag: String, updateConflictedPostWithLocalVersion: (Int) -> Unit, - editLocalPost: (Int) -> Unit + editLocalPost: (Int) -> Unit, + copyLocalPost: (Int) -> Unit ) { // Cancel and outside touch dismiss works the same way for all, except for conflict and autosave revision // dialogs, for which tapping outside and actively tapping the "edit local" have different meanings @@ -223,7 +248,8 @@ class PostListDialogHelper( onNegativeClickedForBasicDialog( instanceTag = instanceTag, updateConflictedPostWithLocalVersion = updateConflictedPostWithLocalVersion, - editLocalPost = editLocalPost + editLocalPost = editLocalPost, + copyLocalPost = copyLocalPost ) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt index 547c39d97e4b..d8ec5fe96116 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/PostListMainViewModel.kt @@ -203,8 +203,28 @@ class PostListMainViewModel @Inject constructor( checkNetworkConnection = this::checkNetworkConnection, showSnackbar = { _snackBarMessage.postValue(it) }, showToast = { _toastMessage.postValue(it) }, - triggerPreviewStateUpdate = this::updatePreviewAndDialogState + triggerPreviewStateUpdate = this::updatePreviewAndDialogState, + copyPost = this::copyPost + ) + } + + fun copyPost(site: SiteModel, postToCopy: PostModel, performChecks: Boolean = false) { + if (performChecks && (postConflictResolver.doesPostHaveUnhandledConflict(postToCopy) || + postConflictResolver.hasUnhandledAutoSave(postToCopy))) { + postListDialogHelper.showCopyConflictDialog(postToCopy) + return + } + val post = postStore.instantiatePostModel( + site, + false, + postToCopy.title, + postToCopy.content, + PostStatus.DRAFT.toString(), + postToCopy.categoryIdList, + postToCopy.postFormat, + true ) + _postListAction.postValue(PostListAction.EditPost(site, post, loadAutoSaveRevision = false)) } /** @@ -437,6 +457,15 @@ class PostListMainViewModel @Inject constructor( } } + private fun copyLocalPost(localPostId: Int) { + val post = postStore.getPostByLocalPostId(localPostId) + if (post != null) { + copyPost(site, post) + } else { + _snackBarMessage.value = SnackbarMessageHolder(UiStringRes(R.string.error_post_does_not_exist)) + } + } + // BasicFragmentDialog Events fun onPositiveClickedForBasicDialog(instanceTag: String) { @@ -448,7 +477,8 @@ class PostListMainViewModel @Inject constructor( publishPost = postActionHandler::publishPost, updateConflictedPostWithRemoteVersion = postConflictResolver::updateConflictedPostWithRemoteVersion, editRestoredAutoSavePost = this::editRestoredAutoSavePost, - moveTrashedPostToDraft = postActionHandler::moveTrashedPostToDraft + moveTrashedPostToDraft = postActionHandler::moveTrashedPostToDraft, + resolveConflictsAndEditPost = postActionHandler::resolveConflictsAndEditPost ) } @@ -456,7 +486,8 @@ class PostListMainViewModel @Inject constructor( postListDialogHelper.onNegativeClickedForBasicDialog( instanceTag = instanceTag, updateConflictedPostWithLocalVersion = postConflictResolver::updateConflictedPostWithLocalVersion, - editLocalPost = this::editLocalPost + editLocalPost = this::editLocalPost, + copyLocalPost = this::copyLocalPost ) } @@ -464,7 +495,8 @@ class PostListMainViewModel @Inject constructor( postListDialogHelper.onDismissByOutsideTouchForBasicDialog( instanceTag = instanceTag, updateConflictedPostWithLocalVersion = postConflictResolver::updateConflictedPostWithLocalVersion, - editLocalPost = this::editLocalPost + editLocalPost = this::editLocalPost, + copyLocalPost = this::copyLocalPost ) } diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelper.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelper.kt index 16ee92234bc3..16496be41a02 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelper.kt @@ -44,6 +44,7 @@ import org.wordpress.android.viewmodel.posts.PostListItemType.PostListItemUiStat import org.wordpress.android.viewmodel.uistate.ProgressBarUiState import org.wordpress.android.widgets.PostListButtonType import org.wordpress.android.widgets.PostListButtonType.BUTTON_CANCEL_PENDING_AUTO_UPLOAD +import org.wordpress.android.widgets.PostListButtonType.BUTTON_COPY import org.wordpress.android.widgets.PostListButtonType.BUTTON_DELETE import org.wordpress.android.widgets.PostListButtonType.BUTTON_DELETE_PERMANENTLY import org.wordpress.android.widgets.PostListButtonType.BUTTON_EDIT @@ -351,6 +352,7 @@ class PostListItemUiStateHelper @Inject constructor( postStatus == PUBLISHED && !isLocalDraft && !isLocallyChanged + val canShowCopy = postStatus == PUBLISHED || postStatus == DRAFT val canShowViewButton = !canRetryUpload && postStatus != PostStatus.TRASHED val canShowPublishButton = canRetryUpload || canPublishPost val buttonTypes = ArrayList() @@ -400,6 +402,10 @@ class PostListItemUiStateHelper @Inject constructor( buttonTypes.add(BUTTON_STATS) } + if (canShowCopy) { + buttonTypes.add(BUTTON_COPY) + } + return buttonTypes } diff --git a/WordPress/src/main/java/org/wordpress/android/widgets/PostListButtonType.kt b/WordPress/src/main/java/org/wordpress/android/widgets/PostListButtonType.kt index a058f64bfdbc..a8291b9a07ab 100644 --- a/WordPress/src/main/java/org/wordpress/android/widgets/PostListButtonType.kt +++ b/WordPress/src/main/java/org/wordpress/android/widgets/PostListButtonType.kt @@ -36,7 +36,8 @@ enum class PostListButtonType constructor( R.drawable.ic_undo_white_24dp, R.attr.wpColorWarningDark ), - BUTTON_SHOW_MOVE_TRASHED_POST_TO_DRAFT_DIALOG(15, 0, 0, 0); + BUTTON_SHOW_MOVE_TRASHED_POST_TO_DRAFT_DIALOG(15, 0, 0, 0), + BUTTON_COPY(16, R.string.button_copy, R.drawable.ic_copy_white_24dp, R.attr.colorOnSurface); companion object { fun fromInt(value: Int): PostListButtonType? = values().firstOrNull { it.value == value } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index a666a360ccf6..8417032f8b45 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -302,6 +302,7 @@ Discard Retry Move to Draft + Duplicate Upload failed for \"%s\" @@ -373,6 +374,12 @@ The version from another device The version from this app + + Post sync conflict + The post you are trying to copy has two versions that are in conflict or you recently made changes but didn\'t save them.\nEdit the post first to resolve any conflict or proceed with copying the version from this app. + Edit the post first + Copy the version from this app + Local changes Trashing this post will also discard local changes, are you sure you want to continue? diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelCopyPostTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelCopyPostTest.kt new file mode 100644 index 000000000000..e29dc24b7278 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/PostListMainViewModelCopyPostTest.kt @@ -0,0 +1,117 @@ +package org.wordpress.android.ui.posts + +import androidx.lifecycle.Observer +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.whenever +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.InternalCoroutinesApi +import org.assertj.core.api.Assertions.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.ArgumentCaptor +import org.mockito.Mock +import org.mockito.Mockito +import org.wordpress.android.BaseUnitTest +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.model.PostModel +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.model.post.PostStatus +import org.wordpress.android.fluxc.network.rest.wpcom.post.PostRestClient +import org.wordpress.android.fluxc.network.xmlrpc.post.PostXMLRPCClient +import org.wordpress.android.fluxc.persistence.PostSqlUtils +import org.wordpress.android.fluxc.store.PostStore +import org.wordpress.android.ui.posts.PostListAction.EditPost + +class PostListMainViewModelCopyPostTest : BaseUnitTest() { + @Mock lateinit var site: SiteModel + @Mock lateinit var dispatcher: Dispatcher + @Mock lateinit var postSqlUtils: PostSqlUtils + @Mock lateinit var onPostListActionObserver: Observer + + private lateinit var viewModel: PostListMainViewModel + private lateinit var postStore: PostStore + + private val copyPostId = 2 + private val mockedPost = PostModel().apply { + setId(1) + setTitle("mockedTitle") + setContent("mockedContent") + setCategoryIdList(listOf()) // Using an empty list to avoid invoking android.text.TextUtils.join + setPostFormat("mockedPostFormat") + } + + @InternalCoroutinesApi + @Before + fun setUp() { + postStore = PostStore( + dispatcher, + Mockito.mock(PostRestClient::class.java), + Mockito.mock(PostXMLRPCClient::class.java), + postSqlUtils + ) + viewModel = PostListMainViewModel( + dispatcher = dispatcher, + postStore = postStore, + accountStore = mock(), + uploadStore = mock(), + mediaStore = mock(), + networkUtilsWrapper = mock(), + prefs = mock(), + previewStateHelper = mock(), + analyticsTracker = mock(), + mainDispatcher = Dispatchers.Unconfined, + bgDispatcher = Dispatchers.Unconfined, + postListEventListenerFactory = mock(), + uploadStarter = mock(), + uploadActionUseCase = mock(), + savePostToDbUseCase = mock(), + wpStoriesFeatureConfig = mock() + ) + viewModel.postListAction.observeForever(onPostListActionObserver) + + whenever(postSqlUtils.insertPostForResult(any())).thenAnswer { invocation -> + (invocation.arguments[0] as PostModel).apply { setId(copyPostId) } + } + } + + @Test + fun `when the user copies a post the editor opens`() { + viewModel.copyPost(site, mockedPost) + val captor = ArgumentCaptor.forClass(PostListAction::class.java) + verify(onPostListActionObserver).onChanged(captor.capture()) + assertThat(requireNotNull(captor.value is EditPost)) + } + + @Test + fun `when the user copies a post a new post is created`() { + viewModel.copyPost(site, mockedPost) + val captor = ArgumentCaptor.forClass(PostListAction::class.java) + verify(onPostListActionObserver).onChanged(captor.capture()) + val newPost = requireNotNull(captor.value as? EditPost).post + assertThat(newPost.id).isNotEqualTo(mockedPost.id) + assertThat(newPost.id).isEqualTo(copyPostId) + } + + @Test + fun `when the user copies a post the title, content, categories and post format is copied in the new post`() { + viewModel.copyPost(site, mockedPost) + val captor = ArgumentCaptor.forClass(PostListAction::class.java) + verify(onPostListActionObserver).onChanged(captor.capture()) + val newPost = requireNotNull(captor.value as? EditPost).post + assertThat(newPost.title).isEqualTo(mockedPost.title) + assertThat(newPost.content).isEqualTo(mockedPost.content) + assertThat(newPost.categoryIdList).isEqualTo(mockedPost.categoryIdList) + assertThat(newPost.postFormat).isEqualTo(mockedPost.postFormat) + } + + @Test + fun `when the user copies a published post a draft copy of the post is opened for edit`() { + viewModel.copyPost(site, mockedPost.apply { setStatus(PostStatus.PUBLISHED.toString()) }) + val captor = ArgumentCaptor.forClass(PostListAction::class.java) + verify(onPostListActionObserver).onChanged(captor.capture()) + assertThat(requireNotNull(captor.value is EditPost)) + assertThat((captor.value as EditPost).post.status).isEqualTo(PostStatus.DRAFT.toString()) + } +} diff --git a/WordPress/src/test/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelperTest.kt b/WordPress/src/test/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelperTest.kt index 3011505f5083..fc47bbf757a0 100644 --- a/WordPress/src/test/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelperTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/viewmodel/posts/PostListItemUiStateHelperTest.kt @@ -86,7 +86,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_VIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -102,7 +103,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_PREVIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -119,7 +121,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_VIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -136,7 +139,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_PREVIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -150,8 +154,12 @@ class PostListItemUiStateHelperTest { assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) + assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) + + assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) + assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(2) } @Test @@ -165,8 +173,12 @@ class PostListItemUiStateHelperTest { assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) + assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) + + assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) + assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(2) } @Test @@ -181,8 +193,12 @@ class PostListItemUiStateHelperTest { assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) + assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) + + assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) + assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(2) } @Test @@ -198,8 +214,12 @@ class PostListItemUiStateHelperTest { assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) + assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) + + assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) + assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(2) } @Test @@ -215,7 +235,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_STATS) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -231,7 +252,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_PREVIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -245,8 +267,12 @@ class PostListItemUiStateHelperTest { assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) + assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) + + assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) + assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(2) } @Test @@ -346,7 +372,8 @@ class PostListItemUiStateHelperTest { assertThat(state.actions).hasSize(3) assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_PREVIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -401,7 +428,8 @@ class PostListItemUiStateHelperTest { assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_PREVIEW) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -424,13 +452,13 @@ class PostListItemUiStateHelperTest { assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_CANCEL_PENDING_AUTO_UPLOAD) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_TRASH) - assertThat((state.actions[2] as MoreItem).actions).hasSize(2) + assertThat((state.actions[2] as MoreItem).actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(3) } @Test @@ -763,8 +791,12 @@ class PostListItemUiStateHelperTest { ) assertThat(state.actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_EDIT) assertThat(state.actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_RETRY) - assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) + assertThat(state.actions[2].buttonType).isEqualTo(PostListButtonType.BUTTON_MORE) assertThat(state.actions).hasSize(3) + + assertThat((state.actions[2] as MoreItem).actions[0].buttonType).isEqualTo(PostListButtonType.BUTTON_DELETE) + assertThat((state.actions[2] as MoreItem).actions[1].buttonType).isEqualTo(PostListButtonType.BUTTON_COPY) + assertThat((state.actions[2] as MoreItem).actions).hasSize(2) } @Test diff --git a/build.gradle b/build.gradle index ce8b3a37d05a..a9f370b8382e 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,7 @@ ext { androidxWorkVersion = "2.4.0" daggerVersion = '2.29.1' - fluxCVersion = '1.6.27' + fluxCVersion = '1.6.28-beta-1' appCompatVersion = '1.0.2' From f7af37b0f69ddd091dddc9a19d16fb2d5f0b8447 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 10:06:13 -0500 Subject: [PATCH 071/144] Fix lint --- .../android/ui/activitylog/list/ActivityLogListActivity.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt index 9056879358e8..5b164c628ab5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt @@ -16,8 +16,7 @@ import javax.inject.Inject class ActivityLogListActivity : LocaleAwareActivity(), BasicFragmentDialog.BasicDialogPositiveClickInterface, - BasicFragmentDialog.BasicDialogNegativeClickInterface -{ + BasicFragmentDialog.BasicDialogNegativeClickInterface { @Inject lateinit var backupFeatureConfig: BackupFeatureConfig override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) From 244789c62d162c81b9e7f990e1902dc03c8c2020 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 10:22:58 -0500 Subject: [PATCH 072/144] Fix import for R.string --- .../ui/jetpack/BackupAvailableItemsProvider.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt index 14a7e0ae98ae..de6d1c6feb7c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/BackupAvailableItemsProvider.kt @@ -1,7 +1,7 @@ package org.wordpress.android.ui.jetpack import androidx.annotation.StringRes -import org.wordpress.android.R.string +import org.wordpress.android.R import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.CONTENTS import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.MEDIA_UPLOADS import org.wordpress.android.ui.jetpack.BackupAvailableItemsProvider.BackupAvailableItemType.ROOTS @@ -20,27 +20,27 @@ class BackupAvailableItemsProvider @Inject constructor() { return listOf( BackupAvailableItem( THEMES, - string.backup_item_themes + R.string.backup_item_themes ), BackupAvailableItem( PLUGINS, - string.backup_item_plugins + R.string.backup_item_plugins ), BackupAvailableItem( MEDIA_UPLOADS, - string.backup_item_media_uploads + R.string.backup_item_media_uploads ), BackupAvailableItem( SQLS, - string.backup_item_sqls + R.string.backup_item_sqls ), BackupAvailableItem( ROOTS, - string.backup_item_roots + R.string.backup_item_roots ), BackupAvailableItem( CONTENTS, - string.backup_item_contents + R.string.backup_item_contents ) ) } From 3b2546f277b673bf8025bbe29d8785028f86cc96 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 10:23:56 -0500 Subject: [PATCH 073/144] Remove unneeded internal modifier --- .../backup/details/BackupDownloadDetailsViewHolder.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt index 7fe7cd0fdef2..5f9ed168dd28 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/backup/details/BackupDownloadDetailsViewHolder.kt @@ -10,15 +10,15 @@ import org.wordpress.android.ui.jetpack.backup.details.BackupDownloadDetailsView import org.wordpress.android.ui.utils.UiHelpers sealed class BackupDownloadDetailsViewHolder( - internal val parent: ViewGroup, - @LayoutRes layout: Int + @LayoutRes layout: Int, + parent: ViewGroup ) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(layout, parent, false)) { abstract fun onBind(uiState: ListItemUiState) class BackupDownloadDetailsListItemViewHolder( parentView: ViewGroup, private val uiHelpers: UiHelpers - ) : BackupDownloadDetailsViewHolder(parentView, R.layout.backup_details_list_item) { + ) : BackupDownloadDetailsViewHolder(R.layout.backup_details_list_item, parentView) { private val container = itemView.item_container private val checkbox = itemView.checkbox private val label = itemView.checkbox_label From d1536de5d7a3b237d54d03fa8336482acafd0961 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 8 Dec 2020 16:30:42 +0100 Subject: [PATCH 074/144] Add margin to activity type filter screen --- .../main/res/layout/activity_log_type_filter_fragment.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml b/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml index e64199516a06..8b772ea1e4bb 100644 --- a/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml +++ b/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml @@ -11,6 +11,8 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" + android:layout_marginEnd="@dimen/margin_extra_large" + android:layout_marginStart="@dimen/margin_extra_large" android:layout_marginTop="@dimen/toolbar_height" /> + tools:visibility="visible" /> From b2fb8bad6ec699cf258af28ebbe64667e7c8ab08 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 8 Dec 2020 16:31:17 +0100 Subject: [PATCH 075/144] Update ui of activity type filter fragment --- .../main/res/layout/activity_log_type_filter_fragment.xml | 5 +++++ .../src/main/res/layout/activity_log_type_filter_header.xml | 3 +++ .../src/main/res/layout/activity_log_type_filter_item.xml | 3 +++ 3 files changed, 11 insertions(+) diff --git a/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml b/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml index 8b772ea1e4bb..b0158ae75d87 100644 --- a/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml +++ b/WordPress/src/main/res/layout/activity_log_type_filter_fragment.xml @@ -28,6 +28,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + diff --git a/WordPress/src/main/res/layout/activity_log_type_filter_header.xml b/WordPress/src/main/res/layout/activity_log_type_filter_header.xml index 50cae8341aad..f87e544e29d8 100644 --- a/WordPress/src/main/res/layout/activity_log_type_filter_header.xml +++ b/WordPress/src/main/res/layout/activity_log_type_filter_header.xml @@ -8,6 +8,9 @@ android:id="@+id/header_title" android:layout_width="0dp" android:layout_height="wrap_content" + android:fontFamily="sans-serif-medium" + android:textColor="?attr/colorOnSurface" + android:textSize="@dimen/text_sz_large" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/WordPress/src/main/res/layout/activity_log_type_filter_item.xml b/WordPress/src/main/res/layout/activity_log_type_filter_item.xml index f4496a25be12..4151688fbbf8 100644 --- a/WordPress/src/main/res/layout/activity_log_type_filter_item.xml +++ b/WordPress/src/main/res/layout/activity_log_type_filter_item.xml @@ -11,6 +11,7 @@ android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/margin_extra_extra_medium_large" android:clickable="false" android:focusable="false" app:layout_constraintBottom_toBottomOf="parent" @@ -23,6 +24,8 @@ android:id="@+id/activity_type" android:layout_width="0dp" android:layout_height="wrap_content" + android:textSize="@dimen/text_sz_large" + android:textColor="?attr/colorOnSurface" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/checkbox" From b4a779f3f545e24482e7c4e051cd1073a2f53ead Mon Sep 17 00:00:00 2001 From: malinajirka Date: Tue, 8 Dec 2020 16:31:34 +0100 Subject: [PATCH 076/144] Update string on activity type filter fragment --- .../filter/ActivityLogTypeFilterViewModel.kt | 4 +++- .../list/filter/DummyActivityTypesProvider.kt | 19 ++++++++++++++----- WordPress/src/main/res/values/strings.xml | 1 + 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/ActivityLogTypeFilterViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/ActivityLogTypeFilterViewModel.kt index 1b058d5ffeb5..7e33e79ce4a0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/ActivityLogTypeFilterViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/ActivityLogTypeFilterViewModel.kt @@ -70,7 +70,9 @@ class ActivityLogTypeFilterViewModel @Inject constructor( private suspend fun buildContentUiState(activityTypes: List): Content { return withContext(bgDispatcher) { // TODO malinjir replace the hardcoded header title - val headerListItem = ListItemUiState.SectionHeader(UiStringText("Test")) + val headerListItem = ListItemUiState.SectionHeader( + UiStringRes(R.string.activity_log_activity_type_filter_header) + ) // TODO malinjir replace "it.toString()" with activity type name val activityTypeListItems: List = activityTypes .map { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/DummyActivityTypesProvider.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/DummyActivityTypesProvider.kt index 88401d640dde..52289eed24d4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/DummyActivityTypesProvider.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/filter/DummyActivityTypesProvider.kt @@ -13,10 +13,15 @@ class DummyActivityTypesProvider @Inject constructor() { delay(1000) return DummyAvailableActivityTypesResponse( false, listOf( - DummyActivityType(1, "Dummy Users"), - DummyActivityType(2, "Dummy Backup"), - DummyActivityType(3, "Dummy Comments"), - DummyActivityType(4, "Dummy Posts") + DummyActivityType(1, "Users"), + DummyActivityType(2, "Backup"), + DummyActivityType(3, "Comments"), + DummyActivityType(4, "Posts"), + DummyActivityType(5, "Pages"), + DummyActivityType(6, "Plugins"), + DummyActivityType(7, "Scans"), + DummyActivityType(8, "Media"), + DummyActivityType(9, "Widgets") ) ) } @@ -26,5 +31,9 @@ class DummyActivityTypesProvider @Inject constructor() { val activityTypes: List = listOf() ) - data class DummyActivityType(val id: Int, val name: String) + data class DummyActivityType(val id: Int, val name: String) { + override fun toString(): String { + return "$name ($id) (dummy)" + } + } } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index a666a360ccf6..1bdd9081a3e4 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1025,6 +1025,7 @@ Rewind Site Are you sure you want to rewind your site back to %1$s at %2$s? This will remove all content and options created or changed since then. Since you\'re on a free plan, you\'ll see limited events in your activity. + Filter by Activity Type Apply Clear Date range From 025a3c05e923a6db6059957e7e6ad2ebb3d93fe5 Mon Sep 17 00:00:00 2001 From: Javon Davis Date: Tue, 8 Dec 2020 11:43:24 -0500 Subject: [PATCH 077/144] add accessibility test framework to project and tests --- WordPress/build.gradle | 3 +++ .../java/org/wordpress/android/e2e/BlockEditorTests.java | 2 ++ .../java/org/wordpress/android/e2e/EditorTests.java | 2 ++ .../androidTest/java/org/wordpress/android/e2e/LoginTests.java | 2 ++ .../java/org/wordpress/android/e2e/SignUpTests.java | 2 ++ 5 files changed, 11 insertions(+) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 4d02d3b45f54..4c7c228a8ea7 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -363,6 +363,9 @@ dependencies { implementation "org.jsoup:jsoup:1.10.3" implementation 'androidx.emoji:emoji:1.0.0' + + // Enables accessibility checks in Espresso + androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.3.0-alpha05' } configurations.all { diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java index 6157274feaa6..b4e914ce0d40 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java @@ -2,6 +2,7 @@ import android.Manifest.permission; +import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import androidx.test.rule.GrantPermissionRule; @@ -30,6 +31,7 @@ public class BlockEditorTests extends BaseTest { @Before public void setUp() { + AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); wpLogin(); } diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java index cf76c61a3ac6..576f975571cf 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java @@ -2,6 +2,7 @@ import android.Manifest.permission; +import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import androidx.test.rule.GrantPermissionRule; @@ -36,6 +37,7 @@ public class EditorTests extends BaseTest { @Before public void setUp() { + AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); wpLogin(); diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java index 677abe3f6a09..631d3cd89ad9 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java @@ -2,6 +2,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; +import androidx.test.espresso.accessibility.AccessibilityChecks; import org.junit.After; import org.junit.Before; @@ -28,6 +29,7 @@ public class LoginTests extends BaseTest { @Before public void setUp() { + AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); } diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java index c80af3f7a797..3d23b54f165c 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java @@ -1,5 +1,6 @@ package org.wordpress.android.e2e; +import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import org.junit.Before; @@ -21,6 +22,7 @@ public class SignUpTests extends BaseTest { @Before public void setUp() { + AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); } From 7834aeb69aac08ce39ce4b7dda3bb17e8bf8bed0 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 15:45:56 -0500 Subject: [PATCH 078/144] Add activity log list item menu item labels --- .../list/ActivityLogListItemMenuAdapter.kt | 89 +++++++++++++++++++ .../activity_log_list_item_menu_item.xml | 28 ++++++ WordPress/src/main/res/values/strings.xml | 3 + 3 files changed, 120 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt create mode 100644 WordPress/src/main/res/layout/activity_log_list_item_menu_item.xml diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt new file mode 100644 index 000000000000..2ee08164f51b --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt @@ -0,0 +1,89 @@ +package org.wordpress.android.ui.activitylog.list + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.ImageView +import android.widget.TextView +import androidx.appcompat.content.res.AppCompatResources +import org.wordpress.android.R.id +import org.wordpress.android.R.layout +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction +import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.util.ColorUtils.setImageResourceWithTint +import org.wordpress.android.util.getColorResIdFromAttribute +import java.util.ArrayList + +class ActivityLogListItemMenuAdapter( + context: Context?, + uiHelpers: UiHelpers, + menuItems: List +) : BaseAdapter() { + private val inflater: LayoutInflater = LayoutInflater.from(context) + private val menuItems: MutableList = ArrayList() + private val uiHelpers: UiHelpers + override fun getCount(): Int { + return menuItems.size + } + + override fun getItem(position: Int): Any { + return menuItems[position] + } + + override fun getItemId(position: Int): Long { + return menuItems[position].type.ordinal.toLong() + } + + override fun getView( + position: Int, + convertView: View, + parent: ViewGroup + ): View { + var convertView = convertView + val holder: ActivityListItemMenuHolder + if (convertView == null) { + convertView = inflater.inflate(layout.activity_log_list_item_menu_item, parent, false) + holder = ActivityListItemMenuHolder(convertView) + convertView.tag = holder + } else { + holder = convertView.tag as ActivityListItemMenuHolder + } + val (label, labelColor, iconRes, iconColor) = menuItems[position] + val textRes = uiHelpers.getTextOfUiString( + convertView.context, + label + ) + val textColorRes = convertView.context.getColorResIdFromAttribute(labelColor) + val iconColorRes = convertView.context.getColorResIdFromAttribute(iconColor) + holder.mText.text = textRes + holder.mText.setTextColor( + AppCompatResources.getColorStateList( + convertView.context, + textColorRes + ) + ) + setImageResourceWithTint( + holder.icon, + iconRes, + iconColorRes + ) + return convertView + } + + internal inner class ActivityListItemMenuHolder(view: View) { + private val label: TextView + private val icon: ImageView + + init { + label = view.findViewById(id.text) + icon = view.findViewById(id.image) + } + } + + init { + this.menuItems.addAll(menuItems) + this.uiHelpers = uiHelpers + } +} \ No newline at end of file diff --git a/WordPress/src/main/res/layout/activity_log_list_item_menu_item.xml b/WordPress/src/main/res/layout/activity_log_list_item_menu_item.xml new file mode 100644 index 000000000000..2b3106a50290 --- /dev/null +++ b/WordPress/src/main/res/layout/activity_log_list_item_menu_item.xml @@ -0,0 +1,28 @@ + + + + + + + diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 4b2dd7cd56b9..359b884d2908 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -1029,6 +1029,9 @@ Clear Date range Activity type + + Restore to this point + Download backup Scan From 702f76573e40422f268f398e339ffb35da2f8bca Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 15:47:40 -0500 Subject: [PATCH 079/144] Add navigation events --- .../android/ui/activitylog/ActivityLogNavigationEvents.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/activitylog/ActivityLogNavigationEvents.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/ActivityLogNavigationEvents.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/ActivityLogNavigationEvents.kt new file mode 100644 index 000000000000..f94c470c1c44 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/ActivityLogNavigationEvents.kt @@ -0,0 +1,8 @@ +package org.wordpress.android.ui.activitylog + +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem + +sealed class ActivityLogNavigationEvents { + data class ShowBackupDownload(val event: ActivityLogListItem.Event) : ActivityLogNavigationEvents() + data class ShowRestore(val event: ActivityLogListItem.Event) : ActivityLogNavigationEvents() +} From d6ef5b78382eba854fb533988aeeb62734a3c4af Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 15:48:40 -0500 Subject: [PATCH 080/144] Add popup adapter and render --- .../list/ActivityLogListItemMenuAdapter.kt | 87 ++++++++----------- .../activitylog/list/EventItemViewHolder.kt | 32 ++++++- 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt index 2ee08164f51b..bc6e2b5a8f67 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt @@ -8,82 +8,71 @@ import android.widget.BaseAdapter import android.widget.ImageView import android.widget.TextView import androidx.appcompat.content.res.AppCompatResources -import org.wordpress.android.R.id -import org.wordpress.android.R.layout +import org.wordpress.android.R import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction -import org.wordpress.android.ui.utils.UiHelpers +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.DOWNLOAD_BACKUP +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.RESTORE import org.wordpress.android.util.ColorUtils.setImageResourceWithTint import org.wordpress.android.util.getColorResIdFromAttribute -import java.util.ArrayList class ActivityLogListItemMenuAdapter( - context: Context?, - uiHelpers: UiHelpers, - menuItems: List + context: Context ) : BaseAdapter() { private val inflater: LayoutInflater = LayoutInflater.from(context) - private val menuItems: MutableList = ArrayList() - private val uiHelpers: UiHelpers + private val items: List = SecondaryAction.values().toList() override fun getCount(): Int { - return menuItems.size + return items.size } override fun getItem(position: Int): Any { - return menuItems[position] + return items[position] } override fun getItemId(position: Int): Long { - return menuItems[position].type.ordinal.toLong() + return items[position].itemId } - override fun getView( - position: Int, - convertView: View, - parent: ViewGroup - ): View { - var convertView = convertView + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + var view = convertView val holder: ActivityListItemMenuHolder - if (convertView == null) { - convertView = inflater.inflate(layout.activity_log_list_item_menu_item, parent, false) - holder = ActivityListItemMenuHolder(convertView) - convertView.tag = holder + if (view == null) { + view = inflater.inflate(R.layout.activity_log_list_item_menu_item, parent, false) + holder = ActivityListItemMenuHolder(view!!) + view.tag = holder } else { - holder = convertView.tag as ActivityListItemMenuHolder + holder = view.tag as ActivityListItemMenuHolder } - val (label, labelColor, iconRes, iconColor) = menuItems[position] - val textRes = uiHelpers.getTextOfUiString( - convertView.context, - label - ) - val textColorRes = convertView.context.getColorResIdFromAttribute(labelColor) - val iconColorRes = convertView.context.getColorResIdFromAttribute(iconColor) - holder.mText.text = textRes - holder.mText.setTextColor( + + val textRes: Int + val iconRes: Int + val colorRes = view.context.getColorResIdFromAttribute(R.attr.wpColorOnSurfaceMedium) + when (items[position]) { + RESTORE -> { + textRes = R.string.activity_log_item_menu_restore_label + iconRes = R.drawable.ic_history_white_24dp + } + DOWNLOAD_BACKUP -> { + textRes = R.string.activity_log_item_menu_download_backup_label + iconRes = R.drawable.ic_download_white_24dp + } + } + holder.text.setText(textRes) + holder.text.setTextColor( AppCompatResources.getColorStateList( - convertView.context, - textColorRes + view.context, + colorRes ) ) setImageResourceWithTint( holder.icon, iconRes, - iconColorRes + colorRes ) - return convertView + return view } internal inner class ActivityListItemMenuHolder(view: View) { - private val label: TextView - private val icon: ImageView - - init { - label = view.findViewById(id.text) - icon = view.findViewById(id.image) - } - } - - init { - this.menuItems.addAll(menuItems) - this.uiHelpers = uiHelpers + val text: TextView = view.findViewById(R.id.text) + val icon: ImageView = view.findViewById(R.id.image) } -} \ No newline at end of file +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt index 5fee37730d02..357dcff4a0fe 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/EventItemViewHolder.kt @@ -1,19 +1,24 @@ package org.wordpress.android.ui.activitylog.list import android.os.Bundle +import android.view.Gravity import android.view.View import android.view.ViewGroup import android.widget.ImageButton import android.widget.ImageView +import android.widget.ListPopupWindow import android.widget.TextView import org.wordpress.android.R +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Event +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction import org.wordpress.android.util.ColorUtils import org.wordpress.android.util.getColorResIdFromAttribute class EventItemViewHolder( parent: ViewGroup, private val itemClickListener: (ActivityLogListItem) -> Unit, - private val rewindClickListener: (ActivityLogListItem) -> Unit + private val rewindClickListener: (ActivityLogListItem) -> Unit, + private val secondaryActionClickListener: (SecondaryAction, ActivityLogListItem) -> Boolean ) : ActivityLogViewHolder(parent, R.layout.activity_log_list_event_item) { private val summary: TextView = itemView.findViewById(R.id.action_summary) private val text: TextView = itemView.findViewById(R.id.action_text) @@ -31,14 +36,15 @@ class EventItemViewHolder( } } - fun bind(activity: ActivityLogListItem.Event) { + fun bind(activity: Event) { summary.text = activity.title text.text = activity.description + val colorRes = if (activity.showMoreMenu) R.attr.wpColorOnSurfaceMedium else R.attr.colorPrimary ColorUtils.setImageResourceWithTint( actionButton, activity.buttonIcon.drawable, - actionButton.context.getColorResIdFromAttribute(R.attr.colorPrimary) + actionButton.context.getColorResIdFromAttribute(colorRes) ) if (activity.isButtonVisible) { actionButton.visibility = View.VISIBLE @@ -53,7 +59,25 @@ class EventItemViewHolder( } actionButton.setOnClickListener { - rewindClickListener(activity) + if (activity.showMoreMenu) { + renderMoreMenu(activity, it) + } else { + rewindClickListener(activity) + } } } + + private fun renderMoreMenu(event: ActivityLogListItem, v: View) { + val popup = ListPopupWindow(v.context) + popup.width = v.context.resources.getDimensionPixelSize(R.dimen.menu_item_width) + popup.setAdapter(ActivityLogListItemMenuAdapter(v.context)) + popup.setDropDownGravity(Gravity.END) + popup.anchorView = v + popup.isModal = true + popup.setOnItemClickListener { _, _, _, id -> + popup.dismiss() + secondaryActionClickListener(SecondaryAction.values()[id.toInt()], event) + } + popup.show() + } } From b3889d42201bd559bea5bf008fd495488ae30bbd Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 15:49:21 -0500 Subject: [PATCH 081/144] Add support for more menu popup --- .../ui/activitylog/list/ActivityLogAdapter.kt | 6 ++- .../list/ActivityLogListActivity.kt | 3 -- .../list/ActivityLogListFragment.kt | 35 +++++++------- .../activitylog/list/ActivityLogListItem.kt | 10 +++- .../activitylog/ActivityLogViewModel.kt | 46 +++++++++++++------ 5 files changed, 62 insertions(+), 38 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogAdapter.kt index 0005ff9643f3..64cdda6d2973 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogAdapter.kt @@ -11,7 +11,8 @@ import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.ViewType class ActivityLogAdapter( private val itemClickListener: (ActivityLogListItem) -> Unit, - private val rewindClickListener: (ActivityLogListItem) -> Unit + private val rewindClickListener: (ActivityLogListItem) -> Unit, + private val secondaryActionClickListener: (ActivityLogListItem.SecondaryAction, ActivityLogListItem) -> Boolean ) : Adapter() { private val list = mutableListOf() @@ -58,7 +59,8 @@ class ActivityLogAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ActivityLogViewHolder { return when (viewType) { ViewType.PROGRESS.id -> ProgressItemViewHolder(parent) - ViewType.EVENT.id -> EventItemViewHolder(parent, itemClickListener, rewindClickListener) + ViewType.EVENT.id -> EventItemViewHolder( + parent, itemClickListener, rewindClickListener, secondaryActionClickListener) ViewType.HEADER.id -> HeaderItemViewHolder(parent) ViewType.FOOTER.id -> FooterItemViewHolder(parent) ViewType.LOADING.id -> LoadingItemViewHolder(parent) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt index 7cbec273f02b..6650137d0a39 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt @@ -5,7 +5,6 @@ import android.os.Bundle import android.view.MenuItem import kotlinx.android.synthetic.main.toolbar_main.* import org.wordpress.android.R -import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.LocaleAwareActivity import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.posts.BasicFragmentDialog @@ -48,8 +47,6 @@ class ActivityLogListActivity : LocaleAwareActivity(), } override fun onNegativeClicked(instanceTag: String) { - // todo: annmarie - this is temporary to expose backup feature - ActivityLauncher.showBackupDownload(this) } private fun passRewindConfirmation(rewindId: String) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt index a6417f187f37..efa70d23460f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt @@ -20,6 +20,8 @@ import org.wordpress.android.WordPress import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.ui.ActivityLauncher +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowBackupDownload +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowRestore import org.wordpress.android.ui.activitylog.list.filter.ActivityLogTypeFilterFragment import org.wordpress.android.ui.posts.BasicFragmentDialog import org.wordpress.android.ui.utils.UiHelpers @@ -159,25 +161,15 @@ class ActivityLogListFragment : Fragment() { log_list_view.scrollToPosition(0) }) - viewModel.showMoreMenu.observe(viewLifecycleOwner, Observer { - if (it is ActivityLogListItem.Event) { - displayMoreMenuDialog(it) - } - }) + viewModel.navigationEvents.observe(viewLifecycleOwner, Observer { + it.applyIfNotHandled { + when (this) { + is ShowBackupDownload -> ActivityLauncher.showBackupDownload(requireActivity()) + is ShowRestore -> displayRewindDialog(event) } + } + }) } - private fun displayMoreMenuDialog(item: ActivityLogListItem.Event) { - val dialog = BasicFragmentDialog() - item.rewindId?.let { - dialog.initialize(it, - getString(R.string.activity_log_rewind_site), - getString(R.string.activity_log_rewind_dialog_message, item.formattedDate, item.formattedTime), - getString(R.string.activity_log_rewind_site), - getString(R.string.backup_download_details_header), - getString(R.string.cancel)) - dialog.show(requireFragmentManager(), it) - } - } private fun displayRewindDialog(item: ActivityLogListItem.Event) { val dialog = BasicFragmentDialog() item.rewindId?.let { @@ -231,10 +223,17 @@ class ActivityLogListFragment : Fragment() { viewModel.onActionButtonClicked(item) } + private fun onSecondaryActionClicked( + secondaryAction: ActivityLogListItem.SecondaryAction, + item: ActivityLogListItem + ): Boolean { + return viewModel.onSecondaryActionClicked(secondaryAction, item) + } + private fun setEvents(events: List) { val adapter: ActivityLogAdapter if (log_list_view.adapter == null) { - adapter = ActivityLogAdapter(this::onItemClicked, this::onItemButtonClicked) + adapter = ActivityLogAdapter(this::onItemClicked, this::onItemButtonClicked, this::onSecondaryActionClicked) log_list_view.adapter = adapter } else { adapter = log_list_view.adapter as ActivityLogAdapter diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt index 73c0e72fae10..145a3bd83f0b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt @@ -32,7 +32,8 @@ sealed class ActivityLogListItem(val type: ViewType) { val date: Date, override val isButtonVisible: Boolean, val buttonIcon: Icon, - val isProgressBarVisible: Boolean = false + val isProgressBarVisible: Boolean = false, + val showMoreMenu: Boolean = false ) : ActivityLogListItem(EVENT), IActionableItem { val formattedDate: String = date.toFormattedDateString() val formattedTime: String = date.toFormattedTimeString() @@ -49,7 +50,8 @@ sealed class ActivityLogListItem(val type: ViewType) { model.rewindID, model.published, isButtonVisible = !rewindDisabled && model.rewindable ?: false, - buttonIcon = if (backupFeatureEnabled) MORE else HISTORY + buttonIcon = if (backupFeatureEnabled) MORE else HISTORY, + showMoreMenu = backupFeatureEnabled ) override fun longId(): Long = activityId.hashCode().toLong() @@ -121,4 +123,8 @@ sealed class ActivityLogListItem(val type: ViewType) { fun fromValue(value: String?) = map[value] ?: DEFAULT } } + + enum class SecondaryAction(val itemId: Long) { + RESTORE(0), DOWNLOAD_BACKUP(1) + } } diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt index 7ca5a107290b..7cfe35cb8d70 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt @@ -15,13 +15,18 @@ import org.wordpress.android.fluxc.model.activity.RewindStatusModel.Rewind.Statu import org.wordpress.android.fluxc.store.ActivityLogStore import org.wordpress.android.fluxc.store.ActivityLogStore.OnActivityLogFetched import org.wordpress.android.modules.UI_THREAD -import org.wordpress.android.ui.jetpack.rewind.RewindStatusService -import org.wordpress.android.ui.jetpack.rewind.RewindStatusService.RewindProgress +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowBackupDownload +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowRestore import org.wordpress.android.ui.activitylog.list.ActivityLogListItem import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Event import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Footer import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Header import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Loading +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.DOWNLOAD_BACKUP +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.RESTORE +import org.wordpress.android.ui.jetpack.rewind.RewindStatusService +import org.wordpress.android.ui.jetpack.rewind.RewindStatusService.RewindProgress import org.wordpress.android.ui.utils.UiString import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.util.AppLog @@ -93,6 +98,11 @@ class ActivityLogViewModel @Inject constructor( val showSnackbarMessage: LiveData get() = _showSnackbarMessage + private val _navigationEvents = + MutableLiveData>() + val navigationEvents: LiveData> + get() = _navigationEvents + private val isLoadingInProgress: Boolean get() = eventListStatus.value == LOADING_MORE || eventListStatus.value == ActivityLogListStatus.FETCHING @@ -126,10 +136,6 @@ class ActivityLogViewModel @Inject constructor( } } - private val _showMoreMenu = SingleLiveEvent() - val showMoreMenu: LiveData - get() = _showMoreMenu - lateinit var site: SiteModel fun start(site: SiteModel) { @@ -182,15 +188,29 @@ class ActivityLogViewModel @Inject constructor( } } + // todo: annmarie - Remove once the feature exclusively uses the more menu fun onActionButtonClicked(item: ActivityLogListItem) { if (item is Event) { - if (backupFeatureConfig.isEnabled()) { - // todo: annmarie implement expand/dismiss the more menu - _showMoreMenu.value = item - } else { - _showRewindDialog.value = item + _showRewindDialog.value = item + } + } + + fun onSecondaryActionClicked( + secondaryAction: ActivityLogListItem.SecondaryAction, + item: ActivityLogListItem + ): Boolean { + if (item is Event) { + val navigationEvent = when (secondaryAction) { + RESTORE -> { + ShowRestore(item) + } + DOWNLOAD_BACKUP -> { + ShowBackupDownload(item) + } } + _navigationEvents.value = org.wordpress.android.viewmodel.Event(navigationEvent) } + return true } fun dateRangePickerClicked() { @@ -276,7 +296,7 @@ class ActivityLogViewModel @Inject constructor( private fun getRewindProgressItem(activityLogModel: ActivityLogModel?): ActivityLogListItem.Progress { return activityLogModel?.let { - val rewoundEvent = ActivityLogListItem.Event( + val rewoundEvent = Event( model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) ActivityLogListItem.Progress(resourceProvider.getString(R.string.activity_log_currently_restoring_title), @@ -288,7 +308,7 @@ class ActivityLogViewModel @Inject constructor( private fun requestEventsUpdate(isLoadingMore: Boolean) { if (canRequestEventsUpdate(isLoadingMore)) { - val newStatus = if (isLoadingMore) ActivityLogListStatus.LOADING_MORE else ActivityLogListStatus.FETCHING + val newStatus = if (isLoadingMore) LOADING_MORE else ActivityLogListStatus.FETCHING _eventListStatus.value = newStatus val payload = ActivityLogStore.FetchActivityLogPayload(site, isLoadingMore) launch { From 7920a92006d66351b1ef7a2ef979a8d0825273b5 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 16:06:15 -0500 Subject: [PATCH 082/144] Remove redunant qualifier --- .../ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt index ac8998c742b7..e79e817dc9c1 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/jetpack/backup/BackupDownloadDetailsViewModelTest.kt @@ -33,11 +33,11 @@ class BackupDownloadDetailsViewModelTest : BaseUnitTest() { viewModel.start() - assertThat(uiStates[0]).isInstanceOf(UiState.Content::class.java) + assertThat(uiStates[0]).isInstanceOf(Content::class.java) } @Test - fun `item is unchecked, when it is clicked on`() = test { + fun `given item is checked, when item is clicked, then item gets unchecked`() = test { val uiStates = initObservers().uiStates viewModel.start() @@ -48,7 +48,7 @@ class BackupDownloadDetailsViewModelTest : BaseUnitTest() { } @Test - fun `item is checked, when it is clicked on twice `() = test { + fun `given item is unchecked, when item is clicked, then item gets checked`() = test { val uiStates = initObservers().uiStates viewModel.start() From aca9e7f5758d1007f6d9f89ba5731edececa6433 Mon Sep 17 00:00:00 2001 From: Javon Davis Date: Tue, 8 Dec 2020 17:02:59 -0500 Subject: [PATCH 083/144] supresss non error level messages --- .../wordpress/android/e2e/EditorTests.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java index 576f975571cf..18b633cc977c 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java @@ -1,11 +1,21 @@ package org.wordpress.android.e2e; import android.Manifest.permission; +import android.view.accessibility.AccessibilityNodeInfo; import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import androidx.test.rule.GrantPermissionRule; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityInfoCheck; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityInfoCheckResult; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityViewCheckResult; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -23,7 +33,14 @@ import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesCheckNames; +import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesInfos; +import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesTypes; +import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesViews; import static junit.framework.TestCase.assertTrue; +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; import static org.wordpress.android.support.WPSupportUtils.checkViewHasText; import static org.wordpress.android.support.WPSupportUtils.sleep; import static org.wordpress.android.support.WPSupportUtils.waitForElementToNotBeDisplayed; @@ -37,7 +54,11 @@ public class EditorTests extends BaseTest { @Before public void setUp() { - AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); + Matcher speakableTextMatcher = + Matchers.allOf(matchesTypes( + anyOf(is(AccessibilityCheckResultType.INFO), is(AccessibilityCheckResultType.WARNING)))); + AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false) + .setSuppressingResultMatcher(speakableTextMatcher); logoutIfNecessary(); wpLogin(); From a0e95ad67cbb3b2daf9fd9a842b4b46cec8ca6db Mon Sep 17 00:00:00 2001 From: Javon Davis Date: Tue, 8 Dec 2020 17:03:32 -0500 Subject: [PATCH 084/144] remove unused imports --- .../java/org/wordpress/android/e2e/EditorTests.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java index 18b633cc977c..49b6f64edc7e 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java @@ -1,7 +1,6 @@ package org.wordpress.android.e2e; import android.Manifest.permission; -import android.view.accessibility.AccessibilityNodeInfo; import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; @@ -9,11 +8,7 @@ import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult; import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType; -import com.google.android.apps.common.testing.accessibility.framework.AccessibilityInfoCheck; -import com.google.android.apps.common.testing.accessibility.framework.AccessibilityInfoCheckResult; -import com.google.android.apps.common.testing.accessibility.framework.AccessibilityViewCheckResult; -import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.Matchers; import org.junit.Before; @@ -33,13 +28,9 @@ import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesCheckNames; -import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesInfos; import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesTypes; -import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesViews; import static junit.framework.TestCase.assertTrue; import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.wordpress.android.support.WPSupportUtils.checkViewHasText; import static org.wordpress.android.support.WPSupportUtils.sleep; From 5c026d28363a190f13f143c0517c6a907e384466 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 17:09:45 -0500 Subject: [PATCH 085/144] Add a couple navigationEvent tests --- .../list/ActivityLogListFragment.kt | 1 + .../activitylog/ActivityLogViewModelTest.kt | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt index 342985253027..8fa784870b3f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListFragment.kt @@ -164,6 +164,7 @@ class ActivityLogListFragment : Fragment() { it.applyIfNotHandled { when (this) { is ShowBackupDownload -> ActivityLauncher.showBackupDownload(requireActivity()) + // todo: annmarie replace with the ActivityLauncher for showing restore details is ShowRestore -> displayRewindDialog(event) } } }) diff --git a/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt index 6338d3d970dd..007361ba2bc4 100644 --- a/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModelTest.kt @@ -13,6 +13,7 @@ import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking +import org.assertj.core.api.Assertions import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull @@ -32,6 +33,9 @@ import org.wordpress.android.fluxc.model.activity.RewindStatusModel.State.ACTIVE import org.wordpress.android.fluxc.store.ActivityLogStore import org.wordpress.android.fluxc.store.ActivityLogStore.FetchActivityLogPayload import org.wordpress.android.fluxc.store.ActivityLogStore.OnActivityLogFetched +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowBackupDownload +import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowRestore import org.wordpress.android.ui.jetpack.rewind.RewindStatusService import org.wordpress.android.ui.jetpack.rewind.RewindStatusService.RewindProgress import org.wordpress.android.ui.activitylog.list.ActivityLogListItem @@ -40,6 +44,8 @@ import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Footer import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Header import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Icon.DEFAULT import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Loading +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.DOWNLOAD_BACKUP +import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.RESTORE import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.util.config.ActivityLogFiltersFeatureConfig import org.wordpress.android.viewmodel.ResourceProvider @@ -64,6 +70,8 @@ class ActivityLogViewModelTest { private var eventListStatuses: MutableList = mutableListOf() private var snackbarMessages: MutableList = mutableListOf() private var moveToTopEvents: MutableList = mutableListOf() + private var navigationEvents: + MutableList> = mutableListOf() private lateinit var activityLogList: List private lateinit var viewModel: ActivityLogViewModel private var rewindProgress = MutableLiveData() @@ -122,6 +130,7 @@ class ActivityLogViewModelTest { viewModel.showRewindDialog.observeForever { rewindDialogs.add(it) } viewModel.showSnackbarMessage.observeForever { snackbarMessages.add(it) } viewModel.moveToTop.observeForever { moveToTopEvents.add(it) } + viewModel.navigationEvents.observeForever { navigationEvents.add(it) } fetchActivityLogCaptor = argumentCaptor() activityLogList = initializeActivityList() @@ -380,6 +389,20 @@ class ActivityLogViewModelTest { assertEquals(selectedItems, viewModel.showActivityTypeFilterDialog.value!!.initialSelection) } + @Test + fun onSecondaryActionClickRestoreNavigationEventIsShowRestore() { + viewModel.onSecondaryActionClicked(RESTORE, event) + + Assertions.assertThat(navigationEvents.last().peekContent()).isInstanceOf(ShowRestore::class.java) + } + + @Test + fun onSecondaryActionClickDownloadBackupNavigationEventIsShowBackupDownload() { + viewModel.onSecondaryActionClicked(DOWNLOAD_BACKUP, event) + + Assertions.assertThat(navigationEvents.last().peekContent()).isInstanceOf(ShowBackupDownload::class.java) + } + private suspend fun assertFetchEvents(canLoadMore: Boolean = false) { verify(store).fetchActivities(fetchActivityLogCaptor.capture()) From 6e84f7e0320602cf20fcfe4ef464ad0825762db5 Mon Sep 17 00:00:00 2001 From: Javon Davis Date: Tue, 8 Dec 2020 17:10:33 -0500 Subject: [PATCH 086/144] move accessibility check to BaseTest --- .../wordpress/android/e2e/BlockEditorTests.java | 2 -- .../org/wordpress/android/e2e/EditorTests.java | 14 -------------- .../java/org/wordpress/android/e2e/LoginTests.java | 2 -- .../org/wordpress/android/e2e/SignUpTests.java | 2 -- .../org/wordpress/android/support/BaseTest.java | 14 ++++++++++++++ 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java index b4e914ce0d40..6157274feaa6 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/BlockEditorTests.java @@ -2,7 +2,6 @@ import android.Manifest.permission; -import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import androidx.test.rule.GrantPermissionRule; @@ -31,7 +30,6 @@ public class BlockEditorTests extends BaseTest { @Before public void setUp() { - AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); wpLogin(); } diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java index 49b6f64edc7e..cf76c61a3ac6 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/EditorTests.java @@ -2,15 +2,9 @@ import android.Manifest.permission; -import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import androidx.test.rule.GrantPermissionRule; -import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult; -import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType; - -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -28,10 +22,7 @@ import static androidx.test.espresso.Espresso.pressBack; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesTypes; import static junit.framework.TestCase.assertTrue; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.is; import static org.wordpress.android.support.WPSupportUtils.checkViewHasText; import static org.wordpress.android.support.WPSupportUtils.sleep; import static org.wordpress.android.support.WPSupportUtils.waitForElementToNotBeDisplayed; @@ -45,11 +36,6 @@ public class EditorTests extends BaseTest { @Before public void setUp() { - Matcher speakableTextMatcher = - Matchers.allOf(matchesTypes( - anyOf(is(AccessibilityCheckResultType.INFO), is(AccessibilityCheckResultType.WARNING)))); - AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false) - .setSuppressingResultMatcher(speakableTextMatcher); logoutIfNecessary(); wpLogin(); diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java index 631d3cd89ad9..677abe3f6a09 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/LoginTests.java @@ -2,7 +2,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.rule.ActivityTestRule; -import androidx.test.espresso.accessibility.AccessibilityChecks; import org.junit.After; import org.junit.Before; @@ -29,7 +28,6 @@ public class LoginTests extends BaseTest { @Before public void setUp() { - AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); } diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java b/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java index 3d23b54f165c..c80af3f7a797 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/SignUpTests.java @@ -1,6 +1,5 @@ package org.wordpress.android.e2e; -import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.rule.ActivityTestRule; import org.junit.Before; @@ -22,7 +21,6 @@ public class SignUpTests extends BaseTest { @Before public void setUp() { - AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false); logoutIfNecessary(); } diff --git a/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java b/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java index 77794f35878d..27235a3441ef 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/support/BaseTest.java @@ -3,6 +3,7 @@ import android.app.Instrumentation; import androidx.test.core.app.ApplicationProvider; +import androidx.test.espresso.accessibility.AccessibilityChecks; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; @@ -13,8 +14,12 @@ import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.DateOffset; import com.github.tomakehurst.wiremock.extension.responsetemplating.helpers.HandlebarsHelper; import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult; +import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResult.AccessibilityCheckResultType; import org.apache.commons.lang3.LocaleUtils; +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Rule; import org.wordpress.android.R; @@ -36,6 +41,9 @@ import java.util.TimeZone; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesTypes; +import static org.hamcrest.Matchers.anyOf; +import static org.hamcrest.Matchers.is; import static org.wordpress.android.BuildConfig.E2E_SELF_HOSTED_USER_SITE_ADDRESS; import static org.wordpress.android.BuildConfig.E2E_WP_COM_USER_EMAIL; import static org.wordpress.android.BuildConfig.E2E_WP_COM_USER_PASSWORD; @@ -53,6 +61,12 @@ public void setup() { mMockedAppComponent = DaggerAppComponentTest.builder() .application(mAppContext) .build(); + + Matcher nonErrorLevelMatcher = + Matchers.allOf(matchesTypes( + anyOf(is(AccessibilityCheckResultType.INFO), is(AccessibilityCheckResultType.WARNING)))); + AccessibilityChecks.enable().setRunChecksFromRootView(true).setThrowExceptionForErrors(false) + .setSuppressingResultMatcher(nonErrorLevelMatcher); } @Rule From 673239816786d28e18ecdbd5016b7d3a5557d034 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 8 Dec 2020 17:51:28 -0500 Subject: [PATCH 087/144] Add download icon --- .../activitylog/list/ActivityLogListItemMenuAdapter.kt | 2 +- WordPress/src/main/res/drawable/ic_get_app_24dp.xml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 WordPress/src/main/res/drawable/ic_get_app_24dp.xml diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt index bc6e2b5a8f67..e7e250444523 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt @@ -53,7 +53,7 @@ class ActivityLogListItemMenuAdapter( } DOWNLOAD_BACKUP -> { textRes = R.string.activity_log_item_menu_download_backup_label - iconRes = R.drawable.ic_download_white_24dp + iconRes = R.drawable.ic_get_app_24dp } } holder.text.setText(textRes) diff --git a/WordPress/src/main/res/drawable/ic_get_app_24dp.xml b/WordPress/src/main/res/drawable/ic_get_app_24dp.xml new file mode 100644 index 000000000000..d4be3b26dbad --- /dev/null +++ b/WordPress/src/main/res/drawable/ic_get_app_24dp.xml @@ -0,0 +1,9 @@ + + + From eeb4d081befdba7f474d6a7717909737f3720130 Mon Sep 17 00:00:00 2001 From: Joel Dean Date: Tue, 8 Dec 2020 18:54:35 -0500 Subject: [PATCH 088/144] Updated gutenberg-mobile ref --- libs/gutenberg-mobile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gutenberg-mobile b/libs/gutenberg-mobile index 2a6cc0b3b095..657de733db55 160000 --- a/libs/gutenberg-mobile +++ b/libs/gutenberg-mobile @@ -1 +1 @@ -Subproject commit 2a6cc0b3b0950938432888bf927a2219a4ad0255 +Subproject commit 657de733db553535dce5f61d6aacaaf6e95bfd1c From 9a387cded371dc258b3d9fc6f323fb8250f9a21e Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 4 Dec 2020 18:24:18 -0300 Subject: [PATCH 089/144] Add domain registration block --- .../main/java/org/wordpress/android/ui/mysite/MySiteItem.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteItem.kt index 182464a635ce..7746e096d653 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteItem.kt @@ -2,6 +2,7 @@ package org.wordpress.android.ui.mysite import androidx.annotation.DrawableRes import org.wordpress.android.ui.mysite.MySiteItem.Type.CATEGORY_HEADER +import org.wordpress.android.ui.mysite.MySiteItem.Type.DOMAIN_REGISTRATION_BLOCK import org.wordpress.android.ui.mysite.MySiteItem.Type.LIST_ITEM import org.wordpress.android.ui.mysite.MySiteItem.Type.QUICK_ACTIONS_BLOCK import org.wordpress.android.ui.mysite.MySiteItem.Type.SITE_INFO_BLOCK @@ -12,6 +13,7 @@ sealed class MySiteItem(val type: Type) { enum class Type { SITE_INFO_BLOCK, QUICK_ACTIONS_BLOCK, + DOMAIN_REGISTRATION_BLOCK, CATEGORY_HEADER, LIST_ITEM } @@ -39,6 +41,8 @@ sealed class MySiteItem(val type: Type) { val showPages: Boolean = true ) : MySiteItem(QUICK_ACTIONS_BLOCK) + data class DomainRegistrationBlock(val onClick: ListItemInteraction) : MySiteItem(DOMAIN_REGISTRATION_BLOCK) + data class CategoryHeader(val title: UiString) : MySiteItem(CATEGORY_HEADER) data class ListItem( From 5df48d29bea2eaf21ba011adc06217c68bf86951 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 4 Dec 2020 18:24:50 -0300 Subject: [PATCH 090/144] Add domain registration view holder --- .../ui/mysite/DomainRegistrationViewHolder.kt | 14 +++++++ .../android/ui/mysite/MySiteAdapter.kt | 4 ++ .../ui/mysite/MySiteAdapterDiffCallback.kt | 2 + .../res/layout/domain_registration_block.xml | 38 +++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationViewHolder.kt create mode 100644 WordPress/src/main/res/layout/domain_registration_block.xml diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationViewHolder.kt new file mode 100644 index 000000000000..89ab6b13babb --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationViewHolder.kt @@ -0,0 +1,14 @@ +package org.wordpress.android.ui.mysite + +import android.view.ViewGroup +import kotlinx.android.synthetic.main.domain_registration_block.view.* +import org.wordpress.android.R +import org.wordpress.android.ui.mysite.MySiteItem.DomainRegistrationBlock + +class DomainRegistrationViewHolder( + parent: ViewGroup +) : MySiteItemViewHolder(parent, R.layout.domain_registration_block) { + fun bind(item: DomainRegistrationBlock) = itemView.apply { + my_site_register_domain_cta.setOnClickListener { item.onClick.click() } + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapter.kt index 6fb953d6faa8..afd4bf9e3017 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapter.kt @@ -4,10 +4,12 @@ import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView.Adapter import org.wordpress.android.ui.mysite.MySiteItem.CategoryHeader +import org.wordpress.android.ui.mysite.MySiteItem.DomainRegistrationBlock import org.wordpress.android.ui.mysite.MySiteItem.ListItem import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock import org.wordpress.android.ui.mysite.MySiteItem.Type.CATEGORY_HEADER +import org.wordpress.android.ui.mysite.MySiteItem.Type.DOMAIN_REGISTRATION_BLOCK import org.wordpress.android.ui.mysite.MySiteItem.Type.LIST_ITEM import org.wordpress.android.ui.mysite.MySiteItem.Type.QUICK_ACTIONS_BLOCK import org.wordpress.android.ui.mysite.MySiteItem.Type.SITE_INFO_BLOCK @@ -28,6 +30,7 @@ class MySiteAdapter(val imageManager: ImageManager, val uiHelpers: UiHelpers) : return when (viewType) { SITE_INFO_BLOCK.ordinal -> MySiteInfoViewHolder(parent, imageManager) QUICK_ACTIONS_BLOCK.ordinal -> QuickActionsViewHolder(parent) + DOMAIN_REGISTRATION_BLOCK.ordinal -> DomainRegistrationViewHolder(parent) CATEGORY_HEADER.ordinal -> MySiteCategoryViewHolder(parent, uiHelpers) LIST_ITEM.ordinal -> MySiteListItemViewHolder(parent, uiHelpers) else -> throw IllegalArgumentException("Unexpected view type") @@ -38,6 +41,7 @@ class MySiteAdapter(val imageManager: ImageManager, val uiHelpers: UiHelpers) : when (holder) { is MySiteInfoViewHolder -> holder.bind(items[position] as SiteInfoBlock) is QuickActionsViewHolder -> holder.bind(items[position] as QuickActionsBlock) + is DomainRegistrationViewHolder -> holder.bind(items[position] as DomainRegistrationBlock) is MySiteCategoryViewHolder -> holder.bind(items[position] as CategoryHeader) is MySiteListItemViewHolder -> holder.bind(items[position] as ListItem) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapterDiffCallback.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapterDiffCallback.kt index 8d58fc040942..760ab2b7becd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapterDiffCallback.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteAdapterDiffCallback.kt @@ -3,6 +3,7 @@ package org.wordpress.android.ui.mysite import androidx.recyclerview.widget.DiffUtil import org.apache.commons.lang3.NotImplementedException import org.wordpress.android.ui.mysite.MySiteItem.CategoryHeader +import org.wordpress.android.ui.mysite.MySiteItem.DomainRegistrationBlock import org.wordpress.android.ui.mysite.MySiteItem.ListItem import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock @@ -21,6 +22,7 @@ class MySiteAdapterDiffCallback( return oldItem.type == updatedItem.type && when { oldItem is SiteInfoBlock && updatedItem is SiteInfoBlock -> true oldItem is QuickActionsBlock && updatedItem is QuickActionsBlock -> true + oldItem is DomainRegistrationBlock && updatedItem is DomainRegistrationBlock -> true oldItem is CategoryHeader && updatedItem is CategoryHeader -> oldItem.title == updatedItem.title oldItem is ListItem && updatedItem is ListItem -> oldItem.primaryText == updatedItem.primaryText else -> throw NotImplementedException("Diff not implemented yet") diff --git a/WordPress/src/main/res/layout/domain_registration_block.xml b/WordPress/src/main/res/layout/domain_registration_block.xml new file mode 100644 index 000000000000..6b511301bfc4 --- /dev/null +++ b/WordPress/src/main/res/layout/domain_registration_block.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + From cbd89e4c72decbfb295c7561a0b24f19e7baa483 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 4 Dec 2020 18:35:44 -0300 Subject: [PATCH 091/144] Add domain registration block to view model --- .../java/org/wordpress/android/ui/mysite/MySiteViewModel.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index 89b771422aa0..20536cbb672a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -40,6 +40,7 @@ import org.wordpress.android.ui.mysite.ListItemAction.SITE_SETTINGS import org.wordpress.android.ui.mysite.ListItemAction.STATS import org.wordpress.android.ui.mysite.ListItemAction.THEMES import org.wordpress.android.ui.mysite.ListItemAction.VIEW_SITE +import org.wordpress.android.ui.mysite.MySiteItem.DomainRegistrationBlock import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock import org.wordpress.android.ui.mysite.SiteDialogModel.AddSiteIconDialogModel import org.wordpress.android.ui.mysite.SiteDialogModel.ChangeSiteIconDialogModel @@ -146,6 +147,7 @@ class MySiteViewModel site.isSelfHostedAdmin || site.hasCapabilityEditPages ) ) + siteItems.add(DomainRegistrationBlock(ListItemInteraction.create { domainRegistrationClick(site) })) siteItems.addAll(siteItemsBuilder.buildSiteItems(site, this::onItemClick)) siteItems } else { From a6be03677b73852df3286f9d1acf9f386b256621 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 4 Dec 2020 18:37:40 -0300 Subject: [PATCH 092/144] Add click handling for domain registration block --- .../wordpress/android/ui/mysite/ImprovedMySiteFragment.kt | 7 +++++++ .../org/wordpress/android/ui/mysite/MySiteViewModel.kt | 7 +++++++ .../wordpress/android/ui/mysite/SiteNavigationAction.kt | 1 + 3 files changed, 15 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt index 70c0b1936e12..a257748c9412 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt @@ -25,6 +25,7 @@ import org.wordpress.android.WordPress import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.TextInputDialogFragment +import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistrationPurpose.CTA_DOMAIN_CREDIT_REDEMPTION import org.wordpress.android.ui.main.utils.MeGravatarLoader import org.wordpress.android.ui.mysite.SiteIconUploadHandler.ItemUploadedModel import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStory @@ -35,6 +36,7 @@ import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenComments import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenCropActivity +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenDomainRegistration import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenJetpackSettings import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMeScreen import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMedia @@ -225,6 +227,11 @@ class ImprovedMySiteFragment : Fragment(), action.source, action.mediaUris.toTypedArray() ) + is OpenDomainRegistration -> ActivityLauncher.viewDomainRegistrationActivityForResult( + activity, + action.site, + CTA_DOMAIN_CREDIT_REDEMPTION + ) } } }) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index 20536cbb672a..90c6d92db063 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import org.wordpress.android.R +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_TAPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_CROPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_GALLERY_PICKED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_REMOVED @@ -49,6 +50,7 @@ import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenComments import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenCropActivity +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenDomainRegistration import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenJetpackSettings import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMeScreen import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMedia @@ -254,6 +256,11 @@ class MySiteViewModel _onNavigation.value = Event(OpenMedia(site)) } + private fun domainRegistrationClick(site: SiteModel) { + analyticsTrackerWrapper.track(DOMAIN_CREDIT_REDEMPTION_TAPPED, site) + _onNavigation.value = Event(OpenDomainRegistration(site)) + } + fun refresh() { selectedSiteRepository.updateSiteSettingsIfNecessary() _currentAccountAvatarUrl.value = accountStore.account?.avatarUrl.orEmpty() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt index 5bd73dd66318..fdcc0e7543ac 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt @@ -45,4 +45,5 @@ sealed class SiteNavigationAction { val source: PagePostCreationSourcesDetail, val mediaUris: List ) : SiteNavigationAction() + data class OpenDomainRegistration(val site: SiteModel) : SiteNavigationAction() } From f69daf37a97c383a30b12d240c1e60bc0859d410 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Fri, 4 Dec 2020 18:45:36 -0300 Subject: [PATCH 093/144] Add missing methods to SiteUtilsWrapper --- .../main/java/org/wordpress/android/util/SiteUtilsWrapper.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt b/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt index 7d1a5b3e8ee7..489f4d159016 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/SiteUtilsWrapper.kt @@ -19,4 +19,6 @@ class SiteUtilsWrapper @Inject constructor() { SiteUtils.getAccessibilityInfoFromSite(site) fun isAccessedViaWPComRest(site: SiteModel): Boolean = SiteUtils.isAccessedViaWPComRest(site) + fun onFreePlan(site: SiteModel): Boolean = SiteUtils.onFreePlan(site) + fun hasCustomDomain(site: SiteModel): Boolean = SiteUtils.hasCustomDomain(site) } From 1d8270e6bd9ef9423039f152ace458cbae8d4aba Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 20:40:41 -0300 Subject: [PATCH 094/144] Introduce DomainRegistrationHandler --- .../ui/mysite/DomainRegistrationHandler.kt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationHandler.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationHandler.kt new file mode 100644 index 000000000000..1eb99c12c7bd --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/DomainRegistrationHandler.kt @@ -0,0 +1,58 @@ +package org.wordpress.android.ui.mysite + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MediatorLiveData +import androidx.lifecycle.MutableLiveData +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.generated.SiteActionBuilder +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.SiteStore.OnPlansFetched +import org.wordpress.android.ui.plans.isDomainCreditAvailable +import org.wordpress.android.util.AppLog +import org.wordpress.android.util.AppLog.T.DOMAIN_REGISTRATION +import org.wordpress.android.util.SiteUtilsWrapper +import javax.inject.Inject + +class DomainRegistrationHandler +@Inject constructor( + private val dispatcher: Dispatcher, + private val selectedSiteRepository: SelectedSiteRepository, + private val siteUtils: SiteUtilsWrapper +) { + private val _sitePlansFetched = MutableLiveData() + val isDomainCreditAvailable: LiveData = MediatorLiveData().apply { + addSource(selectedSiteRepository.selectedSiteChange) { + it?.let { site -> + if (shouldFetchPlans(site)) { + fetchPlans(site) + } else { + postValue(false) + } + } + } + addSource(_sitePlansFetched) { event -> + if (event.isError) { + AppLog.e(DOMAIN_REGISTRATION, "An error occurred while fetching plans : " + event.error.message) + } else if (selectedSiteRepository.getSelectedSite()?.id == event.site.id) { + postValue(isDomainCreditAvailable(event.plans)) + } + } + } + + init { + dispatcher.register(this) + } + + fun clear() { + dispatcher.unregister(this) + } + + private fun shouldFetchPlans(site: SiteModel) = !siteUtils.onFreePlan(site) && !siteUtils.hasCustomDomain(site) + + private fun fetchPlans(site: SiteModel) = dispatcher.dispatch(SiteActionBuilder.newFetchPlansAction(site)) + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onPlansFetched(event: OnPlansFetched) = _sitePlansFetched.postValue(event) +} From 194c2799acc762bf7fa1a72bdcc8775446f44c43 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 20:40:51 -0300 Subject: [PATCH 095/144] Introduce DomainRegistrationHandler tests --- .../mysite/DomainRegistrationHandlerTest.kt | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 WordPress/src/test/java/org/wordpress/android/ui/mysite/DomainRegistrationHandlerTest.kt diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/DomainRegistrationHandlerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/DomainRegistrationHandlerTest.kt new file mode 100644 index 000000000000..12ee6281ef03 --- /dev/null +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/DomainRegistrationHandlerTest.kt @@ -0,0 +1,165 @@ +package org.wordpress.android.ui.mysite + +import androidx.lifecycle.MutableLiveData +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.never +import com.nhaarman.mockitokotlin2.times +import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.whenever +import org.assertj.core.api.Assertions.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.wordpress.android.BaseUnitTest +import org.wordpress.android.fluxc.Dispatcher +import org.wordpress.android.fluxc.model.PlanModel +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.store.SiteStore.OnPlansFetched +import org.wordpress.android.fluxc.store.SiteStore.PlansError +import org.wordpress.android.fluxc.store.SiteStore.PlansErrorType +import org.wordpress.android.fluxc.store.SiteStore.PlansErrorType.GENERIC_ERROR +import org.wordpress.android.ui.plans.PlansConstants.PREMIUM_PLAN_ID +import org.wordpress.android.util.SiteUtilsWrapper + +class DomainRegistrationHandlerTest : BaseUnitTest() { + @Mock lateinit var dispatcher: Dispatcher + @Mock lateinit var selectedSiteRepository: SelectedSiteRepository + @Mock lateinit var siteUtils: SiteUtilsWrapper + @Mock lateinit var site: SiteModel + private lateinit var isDomainCreditAvailableEvents: MutableList + private lateinit var handler: DomainRegistrationHandler + private val onSiteChange = MutableLiveData() + + @Before + fun setUp() { + whenever(selectedSiteRepository.selectedSiteChange).thenReturn(onSiteChange) + whenever(selectedSiteRepository.getSelectedSite()).thenAnswer { onSiteChange.value } + + isDomainCreditAvailableEvents = mutableListOf() + handler = DomainRegistrationHandler(dispatcher, selectedSiteRepository, siteUtils) + handler.isDomainCreditAvailable.observeForever { isDomainCreditAvailableEvents.add(it) } + } + + @Test + fun `when site is null, don't emit value and don't fetch`() { + onSiteChange.postValue(null) + + assertThat(isDomainCreditAvailableEvents).hasSize(0) + + verify(dispatcher, never()).dispatch(any()) + } + + @Test + fun `when site is free, emit false and don't fetch`() { + setupSite(site = site, isFree = true, hasCustomDomain = false) + + onSiteChange.postValue(site) + + assertThat(isDomainCreditAvailableEvents).hasSize(1) + assertThat(isDomainCreditAvailableEvents.last()).isFalse + + verify(dispatcher, never()).dispatch(any()) + } + + @Test + fun `when site has custom domain, emit false and don't fetch`() { + setupSite(site = site, isFree = true, hasCustomDomain = false) + + onSiteChange.postValue(site) + + assertThat(isDomainCreditAvailableEvents).hasSize(1) + assertThat(isDomainCreditAvailableEvents.last()).isFalse + + verify(dispatcher, never()).dispatch(any()) + } + + @Test + fun `when site is not free and doesn't have custom domain, don't emit value and start fetch`() { + setupSite(site = site, isFree = false, hasCustomDomain = false) + + onSiteChange.postValue(site) + + assertThat(isDomainCreditAvailableEvents).hasSize(0) + + verify(dispatcher, times(1)).dispatch(any()) + } + + @Test + fun `when fetched site has a plan with credits, emit true`() { + setupSite(site = site, currentPlan = buildPlan(hasDomainCredit = true)) + + onSiteChange.postValue(site) + + assertThat(isDomainCreditAvailableEvents).hasSize(1) + assertThat(isDomainCreditAvailableEvents.last()).isTrue + } + + @Test + fun `when fetched site doesn't have a plan with credits, emit false`() { + setupSite(site = site, currentPlan = buildPlan(hasDomainCredit = false)) + + onSiteChange.postValue(site) + + assertThat(isDomainCreditAvailableEvents).hasSize(1) + assertThat(isDomainCreditAvailableEvents.last()).isFalse + } + + @Test + fun `when fetched site is different from currently selected site, don't emit value`() { + val selectedSite = SiteModel().apply { id = 1 } + + setupSite(site = selectedSite, currentPlan = buildPlan(hasDomainCredit = false)) + + onSiteChange.postValue(selectedSite) + + val fetchedSite = SiteModel().apply { id = 2 } + + buildOnPlansFetchedEvent(site = fetchedSite, currentPlan = buildPlan(hasDomainCredit = true))?.let { event -> + handler.onPlansFetched(event) + } + + assertThat(isDomainCreditAvailableEvents).hasSize(1) + assertThat(isDomainCreditAvailableEvents.last()).isFalse + } + + @Test + fun `when fetch fails, don't emit value`() { + setupSite(site = site, error = GENERIC_ERROR) + + onSiteChange.postValue(site) + + assertThat(isDomainCreditAvailableEvents).hasSize(0) + } + + private fun setupSite( + site: SiteModel, + isFree: Boolean = false, + hasCustomDomain: Boolean = false, + currentPlan: PlanModel? = null, + error: PlansErrorType? = null + ) { + whenever(siteUtils.onFreePlan(any())).thenReturn(isFree) + whenever(siteUtils.hasCustomDomain(any())).thenReturn(hasCustomDomain) + buildOnPlansFetchedEvent(site, currentPlan, error)?.let { event -> + whenever(dispatcher.dispatch(any())).then { handler.onPlansFetched(event) } + } + } + + private fun buildOnPlansFetchedEvent( + site: SiteModel, + currentPlan: PlanModel? = null, + error: PlansErrorType? = null + ) = if (currentPlan != null || error != null) { + OnPlansFetched(site, currentPlan?.let { listOf(it) }, error?.let { PlansError(it) }) + } else { + null + } + + private fun buildPlan(hasDomainCredit: Boolean) = PlanModel( + productId = PREMIUM_PLAN_ID.toInt(), + productSlug = null, + productName = null, + isCurrentPlan = true, + hasDomainCredit = hasDomainCredit + ) +} From 13c2f5569a0070b2dc2877d42c5c02da65f612b9 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 20:54:49 -0300 Subject: [PATCH 096/144] Use DomainRegistrationHandler in view model --- .../android/ui/mysite/MySiteViewModel.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index 90c6d92db063..d81e486a1e4e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import org.wordpress.android.R +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_PROMPT_SHOWN import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_TAPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_CROPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_GALLERY_PICKED @@ -108,7 +109,8 @@ class MySiteViewModel private val fluxCUtilsWrapper: FluxCUtilsWrapper, private val contextProvider: ContextProvider, private val siteIconUploadHandler: SiteIconUploadHandler, - private val siteStoriesHandler: SiteStoriesHandler + private val siteStoriesHandler: SiteStoriesHandler, + private val domainRegistrationHandler: DomainRegistrationHandler ) : ScopedViewModel(mainDispatcher) { private val _currentAccountAvatarUrl = MutableLiveData() private val _onSnackbarMessage = MutableLiveData>() @@ -126,8 +128,9 @@ class MySiteViewModel val uiModel: LiveData = merge( _currentAccountAvatarUrl, selectedSiteRepository.selectedSiteChange, - selectedSiteRepository.showSiteIconProgressBar.distinct() - ) { currentAvatarUrl, site, showSiteIconProgressBar -> + selectedSiteRepository.showSiteIconProgressBar.distinct(), + domainRegistrationHandler.isDomainCreditAvailable.distinct() + ) { currentAvatarUrl, site, showSiteIconProgressBar, isDomainCreditAvailable -> val items = if (site != null) { val siteItems = mutableListOf() siteItems.add( @@ -149,7 +152,10 @@ class MySiteViewModel site.isSelfHostedAdmin || site.hasCapabilityEditPages ) ) - siteItems.add(DomainRegistrationBlock(ListItemInteraction.create { domainRegistrationClick(site) })) + if (isDomainCreditAvailable == true) { + analyticsTrackerWrapper.track(DOMAIN_CREDIT_PROMPT_SHOWN) + siteItems.add(DomainRegistrationBlock(ListItemInteraction.create(site, this::domainRegistrationClick))) + } siteItems.addAll(siteItemsBuilder.buildSiteItems(site, this::onItemClick)) siteItems } else { @@ -389,6 +395,7 @@ class MySiteViewModel override fun onCleared() { siteIconUploadHandler.clear() siteStoriesHandler.clear() + domainRegistrationHandler.clear() super.onCleared() } From de5902e2c1cf54f30e0ac2d8c7644894d8758e19 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 20:55:04 -0300 Subject: [PATCH 097/144] Update view model tests --- .../org/wordpress/android/ui/mysite/MySiteViewModelTest.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt index 9f5e73f3933c..f56df00b6e63 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt @@ -84,6 +84,7 @@ class MySiteViewModelTest : BaseUnitTest() { @Mock lateinit var contextProvider: ContextProvider @Mock lateinit var siteIconUploadHandler: SiteIconUploadHandler @Mock lateinit var siteStoriesHandler: SiteStoriesHandler + @Mock lateinit var domainRegistrationHandler: DomainRegistrationHandler private lateinit var viewModel: MySiteViewModel private lateinit var uiModels: MutableList private lateinit var snackbars: MutableList @@ -120,7 +121,8 @@ class MySiteViewModelTest : BaseUnitTest() { fluxCUtilsWrapper, contextProvider, siteIconUploadHandler, - siteStoriesHandler + siteStoriesHandler, + domainRegistrationHandler ) uiModels = mutableListOf() snackbars = mutableListOf() From 8c82ab9e75d1e4cefc50e37b7c33ce2996786b67 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 21:25:18 -0300 Subject: [PATCH 098/144] Handle successful domain registration result --- .../android/ui/mysite/ImprovedMySiteFragment.kt | 4 ++++ .../org/wordpress/android/ui/mysite/MySiteViewModel.kt | 7 +++++++ .../wordpress/android/util/DomainRegistrationUtils.kt | 9 +++++++++ 3 files changed, 20 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt index a257748c9412..694c60dfa3e5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/ImprovedMySiteFragment.kt @@ -26,6 +26,7 @@ import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.TextInputDialogFragment import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistrationPurpose.CTA_DOMAIN_CREDIT_REDEMPTION +import org.wordpress.android.ui.domains.DomainRegistrationResultFragment.Companion.RESULT_REGISTERED_DOMAIN_EMAIL import org.wordpress.android.ui.main.utils.MeGravatarLoader import org.wordpress.android.ui.mysite.SiteIconUploadHandler.ItemUploadedModel import org.wordpress.android.ui.mysite.SiteNavigationAction.AddNewStory @@ -359,6 +360,9 @@ class ImprovedMySiteFragment : Fragment(), } viewModel.handleCropResult(UCrop.getOutput(data), resultCode == Activity.RESULT_OK) } + RequestCodes.DOMAIN_REGISTRATION -> if (resultCode == Activity.RESULT_OK) { + viewModel.handleSuccessfulDomainRegistrationResult(data.getStringExtra(RESULT_REGISTERED_DOMAIN_EMAIL)) + } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index d81e486a1e4e..518f8bc15d7b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import org.wordpress.android.R import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_PROMPT_SHOWN +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_SUCCESS import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_TAPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_CROPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.MY_SITE_ICON_GALLERY_PICKED @@ -86,6 +87,7 @@ import org.wordpress.android.util.UriWrapper import org.wordpress.android.util.WPMediaUtilsWrapper import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import org.wordpress.android.util.distinct +import org.wordpress.android.util.getEmailValidationMessage import org.wordpress.android.util.merge import org.wordpress.android.viewmodel.ContextProvider import org.wordpress.android.viewmodel.Event @@ -348,6 +350,11 @@ class MySiteViewModel selectedSiteRepository.getSelectedSite()?.let { site -> _onNavigation.value = Event(OpenStats(site)) } } + fun handleSuccessfulDomainRegistrationResult(email: String?) { + analyticsTrackerWrapper.track(DOMAIN_CREDIT_REDEMPTION_SUCCESS) + _onSnackbarMessage.postValue(Event(SnackbarMessageHolder(getEmailValidationMessage(email)))) + } + private fun startSiteIconUpload(filePath: String) { if (TextUtils.isEmpty(filePath)) { _onSnackbarMessage.postValue(Event(SnackbarMessageHolder(UiStringRes(R.string.error_locating_image)))) diff --git a/WordPress/src/main/java/org/wordpress/android/util/DomainRegistrationUtils.kt b/WordPress/src/main/java/org/wordpress/android/util/DomainRegistrationUtils.kt index 587fa4c0615f..36e6943d1fb1 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/DomainRegistrationUtils.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/DomainRegistrationUtils.kt @@ -4,6 +4,9 @@ import android.content.Context import android.text.TextUtils import android.view.Gravity import org.wordpress.android.R +import org.wordpress.android.ui.utils.UiString.UiStringRes +import org.wordpress.android.ui.utils.UiString.UiStringResWithParams +import org.wordpress.android.ui.utils.UiString.UiStringText import org.wordpress.android.util.ToastUtils.Duration fun requestEmailValidation(context: Context, email: String?) { @@ -22,3 +25,9 @@ fun requestEmailValidation(context: Context, email: String?) { context.resources.getDimensionPixelOffset(R.dimen.smart_toast_offset_y) ) } + +fun getEmailValidationMessage(email: String?) = if (email.isNullOrEmpty()) { + UiStringRes(R.string.my_site_verify_your_email_without_email) +} else { + UiStringResWithParams(R.string.my_site_verify_your_email, listOf(UiStringText(email))) +} From dd655932bbd79a9e079b7a362af6992183fb9b12 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 21:35:59 -0300 Subject: [PATCH 099/144] Move logic to reset comments status filter out of MySiteFragment --- .../main/java/org/wordpress/android/ui/main/MySiteFragment.kt | 3 --- .../java/org/wordpress/android/ui/main/WPMainActivity.java | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt index 4d12130b4d63..220ce55870d1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/MySiteFragment.kt @@ -97,7 +97,6 @@ import org.wordpress.android.ui.PagePostCreationSourcesDetail.STORY_FROM_MY_SITE import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.TextInputDialogFragment import org.wordpress.android.ui.accounts.LoginActivity -import org.wordpress.android.ui.comments.CommentsListFragment.CommentStatusCriteria.ALL import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistrationPurpose.CTA_DOMAIN_CREDIT_REDEMPTION import org.wordpress.android.ui.domains.DomainRegistrationResultFragment import org.wordpress.android.ui.main.WPMainActivity.OnScrollToTopListener @@ -784,8 +783,6 @@ class MySiteFragment : Fragment(), ActivityLauncher.viewBlogStats(activity, selectedSite) } RequestCodes.SITE_PICKER -> if (resultCode == Activity.RESULT_OK) { - // reset comments status filter - AppPrefs.setCommentsStatusFilter(ALL) // reset domain credit flag - it will be checked in onSiteChanged isDomainCreditAvailable = false } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java index 535da295bb77..af1ca2022637 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/main/WPMainActivity.java @@ -143,6 +143,7 @@ import static org.wordpress.android.login.LoginAnalyticsListener.CreatedAccountSource.EMAIL; import static org.wordpress.android.push.NotificationsProcessingService.ARG_NOTIFICATION_TYPE; import static org.wordpress.android.ui.JetpackConnectionSource.NOTIFICATIONS; +import static org.wordpress.android.ui.comments.CommentsListFragment.CommentStatusCriteria.ALL; /** * Main activity which hosts sites, reader, me and notifications pages @@ -1055,6 +1056,7 @@ public void onClick(View v) { QuickStartUtils.cancelQuickStartReminder(this); AppPrefs.setQuickStartNoticeRequired(false); AppPrefs.setLastSkippedQuickStartTask(null); + AppPrefs.setCommentsStatusFilter(ALL); // reset comments status filter mPrivateAtomicCookie.clearCookie(); } } From b5f355d0248525b97790381a83e662cef570d7fd Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 22:14:26 -0300 Subject: [PATCH 100/144] Add view model tests for domain registration --- .../android/ui/mysite/MySiteViewModelTest.kt | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt index f56df00b6e63..0ef48d4eeb2b 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt @@ -15,7 +15,11 @@ import org.junit.Test import org.mockito.Mock import org.wordpress.android.BaseUnitTest import org.wordpress.android.R +import org.wordpress.android.R.string import org.wordpress.android.TEST_DISPATCHER +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_PROMPT_SHOWN +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_SUCCESS +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_TAPPED import org.wordpress.android.fluxc.model.AccountModel import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.store.AccountStore @@ -33,6 +37,7 @@ import org.wordpress.android.ui.mysite.ListItemAction.SITE_SETTINGS import org.wordpress.android.ui.mysite.ListItemAction.STATS import org.wordpress.android.ui.mysite.ListItemAction.THEMES import org.wordpress.android.ui.mysite.ListItemAction.VIEW_SITE +import org.wordpress.android.ui.mysite.MySiteItem.DomainRegistrationBlock import org.wordpress.android.ui.mysite.MySiteItem.QuickActionsBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock import org.wordpress.android.ui.mysite.MySiteItem.SiteInfoBlock.IconState @@ -48,6 +53,7 @@ import org.wordpress.android.ui.mysite.SiteNavigationAction.ConnectJetpackForSta import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenActivityLog import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenAdmin import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenComments +import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenDomainRegistration import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMeScreen import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenMedia import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenPages @@ -64,6 +70,8 @@ import org.wordpress.android.ui.mysite.SiteNavigationAction.OpenThemes import org.wordpress.android.ui.mysite.SiteNavigationAction.StartWPComLoginForJetpackStats import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.utils.UiString.UiStringRes +import org.wordpress.android.ui.utils.UiString.UiStringResWithParams +import org.wordpress.android.ui.utils.UiString.UiStringText import org.wordpress.android.util.FluxCUtilsWrapper import org.wordpress.android.util.MediaUtilsWrapper import org.wordpress.android.util.NetworkUtilsWrapper @@ -95,18 +103,22 @@ class MySiteViewModelTest : BaseUnitTest() { private val siteUrl = "http://site.com" private val siteIcon = "http://site.com/icon.jpg" private val siteName = "Site" + private val emailAddress = "test@email.com" private lateinit var site: SiteModel private lateinit var siteInfoBlock: SiteInfoBlock private val onSiteChange = MutableLiveData() private val onShowSiteIconProgressBar = MutableLiveData() + private val isDomainCreditAvailable = MutableLiveData() @InternalCoroutinesApi @Before fun setUp() { onSiteChange.value = null onShowSiteIconProgressBar.value = null + isDomainCreditAvailable.value = null whenever(selectedSiteRepository.selectedSiteChange).thenReturn(onSiteChange) whenever(selectedSiteRepository.showSiteIconProgressBar).thenReturn(onShowSiteIconProgressBar) + whenever(domainRegistrationHandler.isDomainCreditAvailable).thenReturn(isDomainCreditAvailable) viewModel = MySiteViewModel( networkUtilsWrapper, TEST_DISPATCHER, @@ -664,12 +676,57 @@ class MySiteViewModelTest : BaseUnitTest() { assertThat(navigationActions).containsExactly(ConnectJetpackForStats(site)) } + @Test + fun `domain registration item click opens domain registration`() { + onSiteChange.postValue(site) + isDomainCreditAvailable.postValue(true) + + findDomainRegistrationBlock()?.onClick?.click() + + verify(analyticsTrackerWrapper).track(DOMAIN_CREDIT_REDEMPTION_TAPPED, site) + + assertThat(navigationActions).containsOnly(OpenDomainRegistration(site)) + } + + @Test + fun `correct event is tracked when domain registration item is shown`() { + onSiteChange.postValue(site) + isDomainCreditAvailable.postValue(true) + + verify(analyticsTrackerWrapper).track(DOMAIN_CREDIT_PROMPT_SHOWN) + } + + @Test + fun `snackbar is shown and correct event is tracked when handling successful domain registration result without email`() { + viewModel.handleSuccessfulDomainRegistrationResult(null) + + verify(analyticsTrackerWrapper).track(DOMAIN_CREDIT_REDEMPTION_SUCCESS) + + val message = UiStringRes(R.string.my_site_verify_your_email_without_email) + + assertThat(snackbars).containsOnly(SnackbarMessageHolder(message)) + } + + @Test + fun `snackbar is shown and correct event is tracked when handling successful domain registration result with email`() { + viewModel.handleSuccessfulDomainRegistrationResult(emailAddress) + + verify(analyticsTrackerWrapper).track(DOMAIN_CREDIT_REDEMPTION_SUCCESS) + + val message = UiStringResWithParams(string.my_site_verify_your_email, listOf(UiStringText(emailAddress))) + + assertThat(snackbars).containsOnly(SnackbarMessageHolder(message)) + } + private fun setupAccount(account: AccountModel?) = whenever(accountStore.account).thenReturn(account) private fun buildAccountWithAvatarUrl(avatarUrl: String?) = AccountModel().apply { this.avatarUrl = avatarUrl } private fun findQuickActionsBlock() = uiModels.last().items.find { it is QuickActionsBlock } as QuickActionsBlock? + private fun findDomainRegistrationBlock() = + uiModels.last().items.find { it is DomainRegistrationBlock } as DomainRegistrationBlock? + private fun invokeSiteInfoBlockAction(action: SiteInfoBlockAction) { val argument = when (action) { TITLE_CLICK -> 2 From 53717e0972bdafbeebfefd54b1ce7314b6921df0 Mon Sep 17 00:00:00 2001 From: Renan Ferrari Date: Tue, 8 Dec 2020 23:28:52 -0300 Subject: [PATCH 101/144] Fix lint errors --- .../org/wordpress/android/ui/mysite/MySiteViewModelTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt index 0ef48d4eeb2b..6afa9c83e90d 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/MySiteViewModelTest.kt @@ -697,7 +697,7 @@ class MySiteViewModelTest : BaseUnitTest() { } @Test - fun `snackbar is shown and correct event is tracked when handling successful domain registration result without email`() { + fun `snackbar is shown and event is tracked when handling successful domain registration result without email`() { viewModel.handleSuccessfulDomainRegistrationResult(null) verify(analyticsTrackerWrapper).track(DOMAIN_CREDIT_REDEMPTION_SUCCESS) @@ -708,7 +708,7 @@ class MySiteViewModelTest : BaseUnitTest() { } @Test - fun `snackbar is shown and correct event is tracked when handling successful domain registration result with email`() { + fun `snackbar is shown and event is tracked when handling successful domain registration result with email`() { viewModel.handleSuccessfulDomainRegistrationResult(emailAddress) verify(analyticsTrackerWrapper).track(DOMAIN_CREDIT_REDEMPTION_SUCCESS) From 88739288d2c3a30c72fb5f825cac1d02c17ea0bf Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 9 Dec 2020 09:18:21 +0100 Subject: [PATCH 102/144] Decrease line height on activity type filter screen --- WordPress/src/main/res/layout/activity_log_type_filter_item.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/res/layout/activity_log_type_filter_item.xml b/WordPress/src/main/res/layout/activity_log_type_filter_item.xml index 4151688fbbf8..fe22f8b1d07b 100644 --- a/WordPress/src/main/res/layout/activity_log_type_filter_item.xml +++ b/WordPress/src/main/res/layout/activity_log_type_filter_item.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/container" android:layout_width="match_parent" - android:layout_height="?attr/listPreferredItemHeight" + android:layout_height="?attr/listPreferredItemHeightSmall" android:background="?attr/selectableItemBackground" android:focusable="true"> From 6bb35de97e71c3d2be957b06262d2ba59f3d8590 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 9 Dec 2020 12:39:03 +0200 Subject: [PATCH 103/144] [Home Page Picker] Adds template to the existing site creation analytics if a template was used (#13489) * Adds the template key to the existing site creation preview analytics events * Added template to `site created` event --- .../sitecreation/misc/SiteCreationTracker.kt | 42 +++++++++++++++---- .../previews/SitePreviewViewModel.kt | 9 ++-- .../services/SiteCreationServiceManager.kt | 2 +- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationTracker.kt index 0b243b05ab32..c0561babc406 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/misc/SiteCreationTracker.kt @@ -1,6 +1,7 @@ package org.wordpress.android.ui.sitecreation.misc import org.wordpress.android.analytics.AnalyticsTracker +import org.wordpress.android.ui.sitecreation.theme.defaultTemplateSlug import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import java.util.Locale import javax.inject.Inject @@ -45,16 +46,37 @@ class SiteCreationTracker @Inject constructor(val tracker: AnalyticsTrackerWrapp ) } - fun trackPreviewLoading() { - tracker.track(AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_LOADING) + fun trackPreviewLoading(template: String?) { + if (template == null || template == defaultTemplateSlug) { + tracker.track(AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_LOADING) + } else { + tracker.track( + AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_LOADING, + mapOf("template" to template) + ) + } } - fun trackPreviewWebviewShown() { - tracker.track(AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_PREVIEW_VIEWED) + fun trackPreviewWebviewShown(template: String?) { + if (template == null || template == defaultTemplateSlug) { + tracker.track(AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_PREVIEW_VIEWED) + } else { + tracker.track( + AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_PREVIEW_VIEWED, + mapOf("template" to template) + ) + } } - fun trackPreviewWebviewFullyLoaded() { - tracker.track(AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_PREVIEW_LOADED) + fun trackPreviewWebviewFullyLoaded(template: String?) { + if (template == null || template == defaultTemplateSlug) { + tracker.track(AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_PREVIEW_LOADED) + } else { + tracker.track( + AnalyticsTracker.Stat.ENHANCED_SITE_CREATION_SUCCESS_PREVIEW_LOADED, + mapOf("template" to template) + ) + } } fun trackPreviewOkButtonTapped() { @@ -65,8 +87,12 @@ class SiteCreationTracker @Inject constructor(val tracker: AnalyticsTrackerWrapp * This stat is part of a funnel that provides critical information. Before * making ANY modification to this stat please refer to: p4qSXL-35X-p2 */ - fun trackSiteCreated() { - tracker.track(AnalyticsTracker.Stat.SITE_CREATED) + fun trackSiteCreated(template: String?) { + if (template == null || template == defaultTemplateSlug) { + tracker.track(AnalyticsTracker.Stat.SITE_CREATED) + } else { + tracker.track(AnalyticsTracker.Stat.SITE_CREATED, mapOf("template" to template)) + } } fun trackFlowExited() { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt index 8a74e13928e6..a6f758b91cd9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/previews/SitePreviewViewModel.kt @@ -256,7 +256,7 @@ class SitePreviewViewModel @Inject constructor( } private fun startPreLoadingWebView(skipDelay: Boolean = false) { - tracker.trackPreviewLoading() + tracker.trackPreviewLoading(siteCreationState.siteDesign) launch { if (!skipDelay) { /** @@ -271,7 +271,7 @@ class SitePreviewViewModel @Inject constructor( */ withContext(mainDispatcher) { if (uiState.value !is SitePreviewContentUiState) { - tracker.trackPreviewWebviewShown() + tracker.trackPreviewWebviewShown(siteCreationState.siteDesign) updateUiState(SitePreviewLoadingShimmerState(createSitePreviewData())) } } @@ -288,10 +288,7 @@ class SitePreviewViewModel @Inject constructor( fun onUrlLoaded() { if (!webviewFullyLoadedTracked) { webviewFullyLoadedTracked = true - tracker.trackPreviewWebviewFullyLoaded() - } - if (uiState.value is SitePreviewFullscreenProgressUiState) { - tracker.trackPreviewWebviewShown() + tracker.trackPreviewWebviewFullyLoaded(siteCreationState.siteDesign) } /** * Update the ui state if the loading or error screen is being shown. diff --git a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/services/SiteCreationServiceManager.kt b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/services/SiteCreationServiceManager.kt index 26558e6b453c..9b013d6f224b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/services/SiteCreationServiceManager.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/sitecreation/services/SiteCreationServiceManager.kt @@ -84,7 +84,7 @@ class SiteCreationServiceManager @Inject constructor( updateServiceState(SUCCESS, newSiteRemoteId) // This stat is part of a funnel that provides critical information. Before // making ANY modification to this stat please refer to: p4qSXL-35X-p2 - tracker.trackSiteCreated() + tracker.trackSiteCreated(siteData.siteDesign) } FAILURE -> { val currentState = serviceListener.getCurrentState() From 0f699a586528e7d6c59841f444f865ca0989131d Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 9 Dec 2020 12:06:11 +0100 Subject: [PATCH 104/144] Use PostImmutable model --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index efe1d3381d88..9e9bd622e3ee 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3377,7 +3377,7 @@ public void onPostChanged(OnPostChanged event) { AppLog.e(T.POSTS, "REMOTE_AUTO_SAVE_POST failed: " + event.error.type + " - " + event.error.message); } mEditPostRepository.loadPostByLocalPostId(mEditPostRepository.getId()); - mEditPostRepository.replace(postModel -> handleRemoteAutoSave(event.isError(), postModel)); + handleRemoteAutoSave(event.isError(), mEditPostRepository.getPost()); } } @@ -3403,7 +3403,7 @@ private boolean isRemoteAutoSaveError() { } @Nullable - private PostModel handleRemoteAutoSave(boolean isError, PostModel post) { + private PostImmutableModel handleRemoteAutoSave(boolean isError, PostImmutableModel post) { // We are in the process of remote previewing a post from the editor if (!isError && isUploadingPostForPreview()) { // We were uploading post for preview and we got no error: @@ -3444,7 +3444,10 @@ public void onPostUploaded(OnPostUploaded event) { }); } } else { - mEditPostRepository.set(() -> handleRemoteAutoSave(event.isError(), post)); + mEditPostRepository.set(() -> { + handleRemoteAutoSave(event.isError(), post); + return post; + }); } } } From b4e796c6e94c58d91c639ddbae2876898e449487 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 9 Dec 2020 12:07:53 +0100 Subject: [PATCH 105/144] Pass preview type as parameter --- .../android/ui/posts/EditPostActivity.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 9e9bd622e3ee..54df64fe0be5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -144,6 +144,7 @@ import org.wordpress.android.ui.posts.PostEditorAnalyticsSession.Editor; import org.wordpress.android.ui.posts.PostEditorAnalyticsSession.Outcome; import org.wordpress.android.ui.posts.RemotePreviewLogicHelper.PreviewLogicOperationResult; +import org.wordpress.android.ui.posts.RemotePreviewLogicHelper.RemotePreviewType; import org.wordpress.android.ui.posts.editor.EditorActionsProvider; import org.wordpress.android.ui.posts.editor.EditorPhotoPicker; import org.wordpress.android.ui.posts.editor.EditorPhotoPickerListener; @@ -3377,7 +3378,8 @@ public void onPostChanged(OnPostChanged event) { AppLog.e(T.POSTS, "REMOTE_AUTO_SAVE_POST failed: " + event.error.type + " - " + event.error.message); } mEditPostRepository.loadPostByLocalPostId(mEditPostRepository.getId()); - handleRemoteAutoSave(event.isError(), mEditPostRepository.getPost()); + handleRemotePreviewUploadResult(event.isError(), mEditPostRepository.getPost(), + RemotePreviewType.REMOTE_PREVIEW_WITH_REMOTE_AUTO_SAVE); } } @@ -3403,7 +3405,8 @@ private boolean isRemoteAutoSaveError() { } @Nullable - private PostImmutableModel handleRemoteAutoSave(boolean isError, PostImmutableModel post) { + private void handleRemotePreviewUploadResult(boolean isError, PostImmutableModel post, + RemotePreviewLogicHelper.RemotePreviewType param) { // We are in the process of remote previewing a post from the editor if (!isError && isUploadingPostForPreview()) { // We were uploading post for preview and we got no error: @@ -3413,9 +3416,7 @@ private PostImmutableModel handleRemoteAutoSave(boolean isError, PostImmutableMo EditPostActivity.this, mSite, post, - mPostLoadingState == PostLoadingState.UPLOADING_FOR_PREVIEW - ? RemotePreviewLogicHelper.RemotePreviewType.REMOTE_PREVIEW - : RemotePreviewLogicHelper.RemotePreviewType.REMOTE_PREVIEW_WITH_REMOTE_AUTO_SAVE + param ); updatePostLoadingAndDialogState(PostLoadingState.PREVIEWING, post); } else if (isError || isRemoteAutoSaveError()) { @@ -3424,7 +3425,6 @@ private PostImmutableModel handleRemoteAutoSave(boolean isError, PostImmutableMo mUploadUtilsWrapper.showSnackbarError(findViewById(R.id.editor_activity), getString(R.string.remote_preview_operation_error)); } - return post; } @SuppressWarnings("unused") @@ -3445,7 +3445,7 @@ public void onPostUploaded(OnPostUploaded event) { } } else { mEditPostRepository.set(() -> { - handleRemoteAutoSave(event.isError(), post); + handleRemotePreviewUploadResult(event.isError(), post, RemotePreviewType.REMOTE_PREVIEW); return post; }); } From f35383b6298c14fbc449c874534bd6805e1c6a78 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 9 Dec 2020 12:08:26 +0100 Subject: [PATCH 106/144] Move handleRemotePreviewUploadResult out of lambda --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index 54df64fe0be5..c392765e0e2e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3444,10 +3444,8 @@ public void onPostUploaded(OnPostUploaded event) { }); } } else { - mEditPostRepository.set(() -> { - handleRemotePreviewUploadResult(event.isError(), post, RemotePreviewType.REMOTE_PREVIEW); - return post; - }); + mEditPostRepository.set(() -> post); + handleRemotePreviewUploadResult(event.isError(), post, RemotePreviewType.REMOTE_PREVIEW); } } } From 8b5035bdb0a3c48f8d2300bf6dfa8c4e4f0640ce Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 9 Dec 2020 12:08:55 +0100 Subject: [PATCH 107/144] Remove parameter and use EditPostRepository --- .../wordpress/android/ui/posts/EditPostActivity.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index c392765e0e2e..b9c5a3eae167 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3378,8 +3378,7 @@ public void onPostChanged(OnPostChanged event) { AppLog.e(T.POSTS, "REMOTE_AUTO_SAVE_POST failed: " + event.error.type + " - " + event.error.message); } mEditPostRepository.loadPostByLocalPostId(mEditPostRepository.getId()); - handleRemotePreviewUploadResult(event.isError(), mEditPostRepository.getPost(), - RemotePreviewType.REMOTE_PREVIEW_WITH_REMOTE_AUTO_SAVE); + handleRemotePreviewUploadResult(event.isError(), RemotePreviewType.REMOTE_PREVIEW_WITH_REMOTE_AUTO_SAVE); } } @@ -3405,8 +3404,7 @@ private boolean isRemoteAutoSaveError() { } @Nullable - private void handleRemotePreviewUploadResult(boolean isError, PostImmutableModel post, - RemotePreviewLogicHelper.RemotePreviewType param) { + private void handleRemotePreviewUploadResult(boolean isError, RemotePreviewLogicHelper.RemotePreviewType param) { // We are in the process of remote previewing a post from the editor if (!isError && isUploadingPostForPreview()) { // We were uploading post for preview and we got no error: @@ -3415,10 +3413,10 @@ private void handleRemotePreviewUploadResult(boolean isError, PostImmutableModel ActivityLauncher.previewPostOrPageForResult( EditPostActivity.this, mSite, - post, + mEditPostRepository.getPost(), param ); - updatePostLoadingAndDialogState(PostLoadingState.PREVIEWING, post); + updatePostLoadingAndDialogState(PostLoadingState.PREVIEWING, mEditPostRepository.getPost()); } else if (isError || isRemoteAutoSaveError()) { // We got an error from the uploading or from the remote auto save of a post: show snackbar error updatePostLoadingAndDialogState(PostLoadingState.NONE); @@ -3445,7 +3443,7 @@ public void onPostUploaded(OnPostUploaded event) { } } else { mEditPostRepository.set(() -> post); - handleRemotePreviewUploadResult(event.isError(), post, RemotePreviewType.REMOTE_PREVIEW); + handleRemotePreviewUploadResult(event.isError(), RemotePreviewType.REMOTE_PREVIEW); } } } From b739d8a436e6b2efbeff6584c065409e939b1e28 Mon Sep 17 00:00:00 2001 From: malinajirka Date: Wed, 9 Dec 2020 12:10:16 +0100 Subject: [PATCH 108/144] Make sure the method is invoked only while previewing from editor --- .../org/wordpress/android/ui/posts/EditPostActivity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java index b9c5a3eae167..9cd7862bb197 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.java @@ -3378,7 +3378,10 @@ public void onPostChanged(OnPostChanged event) { AppLog.e(T.POSTS, "REMOTE_AUTO_SAVE_POST failed: " + event.error.type + " - " + event.error.message); } mEditPostRepository.loadPostByLocalPostId(mEditPostRepository.getId()); - handleRemotePreviewUploadResult(event.isError(), RemotePreviewType.REMOTE_PREVIEW_WITH_REMOTE_AUTO_SAVE); + if (isRemotePreviewingFromEditor()) { + handleRemotePreviewUploadResult(event.isError(), + RemotePreviewType.REMOTE_PREVIEW_WITH_REMOTE_AUTO_SAVE); + } } } From ed430675cf4589a094a7e8e00cb98041d5fbfabd Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Wed, 9 Dec 2020 08:15:42 -0500 Subject: [PATCH 109/144] Minor changes --- .../android/ui/activitylog/list/ActivityLogListActivity.kt | 1 + .../android/ui/activitylog/list/ActivityLogListItem.kt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt index e510c7773f17..c1d1745414a4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListActivity.kt @@ -52,6 +52,7 @@ class ActivityLogListActivity : LocaleAwareActivity(), } override fun onNegativeClicked(instanceTag: String) { + // Unused } private fun passRewindConfirmation(rewindId: String) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt index 145a3bd83f0b..3920c618603c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItem.kt @@ -125,6 +125,7 @@ sealed class ActivityLogListItem(val type: ViewType) { } enum class SecondaryAction(val itemId: Long) { - RESTORE(0), DOWNLOAD_BACKUP(1) + RESTORE(0), + DOWNLOAD_BACKUP(1); } } From 4b8cab1f1f973e61db7cb91068cb417c6dc0f380 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Wed, 9 Dec 2020 08:34:48 -0500 Subject: [PATCH 110/144] Change order of import --- .../activitylog/ActivityLogViewModel.kt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt index 7cfe35cb8d70..7d39b59e6d85 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/activitylog/ActivityLogViewModel.kt @@ -19,7 +19,6 @@ import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowBackupDownload import org.wordpress.android.ui.activitylog.ActivityLogNavigationEvents.ShowRestore import org.wordpress.android.ui.activitylog.list.ActivityLogListItem -import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Event import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Footer import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Header import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.Loading @@ -32,6 +31,7 @@ import org.wordpress.android.ui.utils.UiString.UiStringRes import org.wordpress.android.util.AppLog import org.wordpress.android.util.BackupFeatureConfig import org.wordpress.android.util.config.ActivityLogFiltersFeatureConfig +import org.wordpress.android.viewmodel.Event import org.wordpress.android.viewmodel.ResourceProvider import org.wordpress.android.viewmodel.ScopedViewModel import org.wordpress.android.viewmodel.SingleLiveEvent @@ -99,8 +99,8 @@ class ActivityLogViewModel @Inject constructor( get() = _showSnackbarMessage private val _navigationEvents = - MutableLiveData>() - val navigationEvents: LiveData> + MutableLiveData>() + val navigationEvents: LiveData> get() = _navigationEvents private val isLoadingInProgress: Boolean @@ -183,14 +183,14 @@ class ActivityLogViewModel @Inject constructor( } fun onItemClicked(item: ActivityLogListItem) { - if (item is Event) { + if (item is ActivityLogListItem.Event) { _showItemDetail.value = item } } // todo: annmarie - Remove once the feature exclusively uses the more menu fun onActionButtonClicked(item: ActivityLogListItem) { - if (item is Event) { + if (item is ActivityLogListItem.Event) { _showRewindDialog.value = item } } @@ -199,7 +199,7 @@ class ActivityLogViewModel @Inject constructor( secondaryAction: ActivityLogListItem.SecondaryAction, item: ActivityLogListItem ): Boolean { - if (item is Event) { + if (item is ActivityLogListItem.Event) { val navigationEvent = when (secondaryAction) { RESTORE -> { ShowRestore(item) @@ -266,8 +266,8 @@ class ActivityLogViewModel @Inject constructor( moveToTop = eventListStatus.value != LOADING_MORE } eventList.forEach { model -> - val currentItem = Event(model, disableActions, backupFeatureConfig.isEnabled()) - val lastItem = items.lastOrNull() as? Event + val currentItem = ActivityLogListItem.Event(model, disableActions, backupFeatureConfig.isEnabled()) + val lastItem = items.lastOrNull() as? ActivityLogListItem.Event if (lastItem == null || lastItem.formattedDate != currentItem.formattedDate) { items.add(Header(currentItem.formattedDate)) } @@ -296,7 +296,7 @@ class ActivityLogViewModel @Inject constructor( private fun getRewindProgressItem(activityLogModel: ActivityLogModel?): ActivityLogListItem.Progress { return activityLogModel?.let { - val rewoundEvent = Event( + val rewoundEvent = ActivityLogListItem.Event( model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) ActivityLogListItem.Progress(resourceProvider.getString(R.string.activity_log_currently_restoring_title), @@ -328,7 +328,7 @@ class ActivityLogViewModel @Inject constructor( private fun showRewindStartedMessage() { rewindStatusService.rewindingActivity?.let { - val event = Event(model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) + val event = ActivityLogListItem. Event(model = it, backupFeatureEnabled = backupFeatureConfig.isEnabled()) _showSnackbarMessage.value = resourceProvider.getString( R.string.activity_log_rewind_started_snackbar_message, event.formattedDate, @@ -340,7 +340,7 @@ class ActivityLogViewModel @Inject constructor( private fun showRewindFinishedMessage() { val item = rewindStatusService.rewindingActivity if (item != null) { - val event = Event(model = item, backupFeatureEnabled = backupFeatureConfig.isEnabled()) + val event = ActivityLogListItem.Event(model = item, backupFeatureEnabled = backupFeatureConfig.isEnabled()) _showSnackbarMessage.value = resourceProvider.getString(R.string.activity_log_rewind_finished_snackbar_message, event.formattedDate, From 2054d2be045b6cee5f28288fe7bdfef7e4722a97 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Wed, 9 Dec 2020 08:38:54 -0500 Subject: [PATCH 111/144] Remove git add WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt --- .../ui/activitylog/list/ActivityLogListItemMenuAdapter.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt index e7e250444523..b103e8e2b606 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/activitylog/list/ActivityLogListItemMenuAdapter.kt @@ -33,13 +33,14 @@ class ActivityLogListItemMenuAdapter( } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - var view = convertView val holder: ActivityListItemMenuHolder - if (view == null) { + val view: View + if (convertView == null) { view = inflater.inflate(R.layout.activity_log_list_item_menu_item, parent, false) - holder = ActivityListItemMenuHolder(view!!) + holder = ActivityListItemMenuHolder(view) view.tag = holder } else { + view = convertView holder = view.tag as ActivityListItemMenuHolder } From 7e6ba20c3fba50946a384468bc70693439bdfe24 Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco Date: Wed, 9 Dec 2020 16:01:27 +0100 Subject: [PATCH 112/144] Gutenberg - Fix Gallery block processor updating its linkTo values --- .../GalleryBlockProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/GalleryBlockProcessor.java b/WordPress/src/main/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/GalleryBlockProcessor.java index 392c19c4e85e..44425bec409c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/GalleryBlockProcessor.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/GalleryBlockProcessor.java @@ -48,10 +48,10 @@ public GalleryBlockProcessor(String localId, MediaFile mediaFile, String siteUrl Element parent = targetImg.parent(); if (parent != null && parent.is("a") && mLinkTo != null) { switch (mLinkTo) { - case "media": + case "file": parent.attr("href", mRemoteUrl); break; - case "attachment": + case "post": parent.attr("href", mAttachmentPageUrl); break; default: From a28a31da705f7647ba2e6c5d93916acf3373e11c Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco Date: Wed, 9 Dec 2020 16:09:54 +0100 Subject: [PATCH 113/144] Update Release notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index f15fa97650e8..ae114b9cd148 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -2,6 +2,7 @@ ----- * [*] My Site: Fixes crash on rotation while editing site title [https://github.com/wordpress-mobile/WordPress-Android/pull/13505] * [**] Posts List: Adds duplicate post functionality [https://github.com/wordpress-mobile/WordPress-Android/pull/13521] +* [*] Block Editor: Fix Gallery block uploads when the editor is closed [https://github.com/wordpress-mobile/WordPress-Android/pull/13570] 16.3 ----- From 05a988b69857cb0e12fcfa0d9cb1c84ed0f697d3 Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco Date: Wed, 9 Dec 2020 16:21:44 +0100 Subject: [PATCH 114/144] Update test content for GalleryBlockProcessor --- .../mediauploadcompletionprocessors/TestContent.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/TestContent.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/TestContent.kt index 22e84cafce59..a9c175d89c50 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/TestContent.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/TestContent.kt @@ -176,7 +176,7 @@ object TestContent { """ - const val oldGalleryBlockIdsNotFirst = """ + const val oldGalleryBlockIdsNotFirst = """