From 6c127b06cb6625e2abeadcdc712b7f4d4d06fe62 Mon Sep 17 00:00:00 2001 From: Sergey Golovin Date: Thu, 19 Oct 2023 00:21:32 +0300 Subject: [PATCH] Release 0.0.1-alpha --- .gitignore | 43 +++ .gitlab/CODEOWNERS | 3 + .gitlab/merge_request_templates /Default.md | 58 ++++ CODE_STYLE.md | 8 + CONTRIBUTING.md | 87 ++++++ LICENSE | 4 + README.md | 106 ++++++- build-logic/convention/build.gradle.kts | 54 ++++ ...droidApplicationComposeConventionPlugin.kt | 17 ++ .../AndroidApplicationConventionPlugin.kt | 44 +++ .../main/kotlin/AndroidInstrumentedTests.kt | 33 +++ .../src/main/kotlin/DependencyLockPlugin.kt | 23 ++ .../kotlin/VKIDLibraryConventionPlugin.kt | 41 +++ .../kotlin/VKIDPublishConventionPlugin.kt | 135 +++++++++ .../main/kotlin/com/vk/id/AndroidCompose.kt | 77 +++++ .../src/main/kotlin/com/vk/id/Detekt.kt | 39 +++ .../main/kotlin/com/vk/id/KotlinAndroid.kt | 71 +++++ .../main/kotlin/com/vk/id/PrintTestApks.kt | 98 +++++++ .../kotlin/com/vk/id/ProjectExtensions.kt | 33 +++ .../src/main/kotlin/com/vk/id/Versions.kt | 7 + build-logic/gradle.properties | 4 + build-logic/settings.gradle.kts | 14 + build.gradle.kts | 9 + config/detekt-compose.yml | 20 ++ config/detekt.yml | 26 ++ gradle.properties | 33 +++ gradle/libs.versions.toml | 53 ++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 ++++++++++++ gradlew.bat | 89 ++++++ logo.svg | 11 + sample/.gitignore | 2 + sample/build.gradle.kts | 52 ++++ sample/gradle.lockfile | 160 +++++++++++ sample/proguard-rules.pro | 21 ++ sample/src/main/AndroidManifest.xml | 47 ++++ .../java/com/vk/id/sample/MainActivity.kt | 111 ++++++++ .../main/java/com/vk/id/sample/VKButton.kt | 215 ++++++++++++++ sample/src/main/res/drawable/vkid_icon.xml | 37 +++ sample/src/main/res/drawable/vkid_spinner.xml | 9 + .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5553 bytes .../src/main/res/mipmap-hdpi/mp_launcher.png | Bin 0 -> 5185 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3149 bytes .../src/main/res/mipmap-mdpi/mp_launcher.png | Bin 0 -> 2963 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 8140 bytes .../src/main/res/mipmap-xhdpi/mp_launcher.png | Bin 0 -> 7581 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 14782 bytes .../main/res/mipmap-xxhdpi/mp_launcher.png | Bin 0 -> 13600 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 21625 bytes .../main/res/mipmap-xxxhdpi/mp_launcher.png | Bin 0 -> 20327 bytes sample/src/main/res/values-ru/strings.xml | 5 + sample/src/main/res/values/colors.xml | 8 + sample/src/main/res/values/strings.xml | 5 + sample/src/main/res/values/themes.xml | 4 + .../main/res/xml/network_security_config.xml | 9 + scripts/git-hooks/pre-push | 26 ++ scripts/install-git-hooks.sh | 9 + settings-gradle.lockfile | 4 + settings.gradle.kts | 21 ++ vkid/.gitignore | 1 + vkid/api/vkid.api | 126 +++++++++ vkid/build.gradle.kts | 36 +++ vkid/consumer-rules.pro | 0 vkid/gradle.lockfile | 159 +++++++++++ vkid/gradle.properties | 3 + vkid/proguard-rules.pro | 21 ++ vkid/src/main/AndroidManifest.xml | 64 +++++ vkid/src/main/java/com/vk/id/AccessToken.kt | 11 + vkid/src/main/java/com/vk/id/VKID.kt | 263 ++++++++++++++++++ vkid/src/main/java/com/vk/id/VKIDAuthFail.kt | 16 ++ .../java/com/vk/id/auth/VKIDAuthParams.kt | 70 +++++ .../java/com/vk/id/internal/api/VKIDApi.kt | 76 +++++ .../com/vk/id/internal/api/VKIDApiService.kt | 83 ++++++ .../java/com/vk/id/internal/api/VKIDCall.kt | 13 + .../com/vk/id/internal/auth/AuthActivity.kt | 221 +++++++++++++++ .../vk/id/internal/auth/AuthEventBridge.kt | 13 + .../com/vk/id/internal/auth/AuthOptions.kt | 83 ++++++ .../id/internal/auth/AuthProvidersChooser.kt | 5 + .../auth/AuthProvidersChooserDefault.kt | 19 ++ .../com/vk/id/internal/auth/AuthResult.kt | 50 ++++ .../vk/id/internal/auth/ServiceCredentials.kt | 7 + .../vk/id/internal/auth/VKIDAuthProvider.kt | 7 + .../vk/id/internal/auth/VKIDTokenPayload.kt | 24 ++ .../id/internal/auth/app/AppAuthProvider.kt | 18 ++ .../internal/auth/app/SilentAuthInfoUtils.kt | 75 +++++ .../auth/app/SilentAuthServicesProvider.kt | 58 ++++ .../auth/app/TrustedProvidersCache.kt | 81 ++++++ .../internal/auth/app/VkAuthProviderInfo.kt | 35 +++ .../auth/app/VkAuthSilentAuthProvider.kt | 52 ++++ .../id/internal/auth/device/DeviceIdPrefs.kt | 71 +++++ .../internal/auth/device/DeviceIdProvider.kt | 110 ++++++++ .../internal/auth/pkce/PkceGeneratorSHA256.kt | 71 +++++ .../id/internal/auth/web/BrowserDescriptor.kt | 141 ++++++++++ .../vk/id/internal/auth/web/BrowserMatcher.kt | 5 + .../id/internal/auth/web/BrowserSelector.kt | 190 +++++++++++++ .../com/vk/id/internal/auth/web/Browsers.kt | 160 +++++++++++ .../vk/id/internal/auth/web/ContextUtils.kt | 21 ++ .../id/internal/auth/web/DelimitedVersion.kt | 117 ++++++++ .../vk/id/internal/auth/web/VersionRange.kt | 113 ++++++++ .../auth/web/VersionedBrowserMatcher.kt | 131 +++++++++ .../id/internal/auth/web/WebAuthProvider.kt | 58 ++++ .../auth/web/WhiteListedBrowserHelper.kt | 33 +++ .../concurrent/CoroutinesDispatchers.kt | 7 + .../concurrent/CoroutinesDispatchersProd.kt | 9 + .../java/com/vk/id/internal/di/VKIDDeps.kt | 23 ++ .../com/vk/id/internal/di/VKIDDepsProd.kt | 129 +++++++++ .../id/internal/log/AndroidLogcatLogEngine.kt | 21 ++ .../com/vk/id/internal/log/FakeLogEngine.kt | 15 + .../java/com/vk/id/internal/log/LogEngine.kt | 12 + .../java/com/vk/id/internal/log/Logger.kt | 10 + .../com/vk/id/internal/log/LoggerWithTag.kt | 18 ++ .../java/com/vk/id/internal/log/VKIDLog.kt | 35 +++ .../com/vk/id/internal/store/PrefsStore.kt | 23 ++ .../main/java/com/vk/id/internal/util/MD5.kt | 59 ++++ .../id/internal/util/ThreadLocalDelegate.kt | 58 ++++ .../res/values/make_all_resources_private.xml | 6 + vkid/src/main/res/values/styles.xml | 36 +++ .../log/AndroidLogcatLogEngineTest.kt | 33 +++ .../vk/id/internal/log/FakeLogEngineTest.kt | 37 +++ .../com/vk/id/internal/log/VKIDLogTest.kt | 58 ++++ 121 files changed, 5674 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .gitlab/CODEOWNERS create mode 100644 .gitlab/merge_request_templates /Default.md create mode 100644 CODE_STYLE.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 build-logic/convention/build.gradle.kts create mode 100644 build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/AndroidInstrumentedTests.kt create mode 100644 build-logic/convention/src/main/kotlin/DependencyLockPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/VKIDLibraryConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/VKIDPublishConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/vk/id/AndroidCompose.kt create mode 100644 build-logic/convention/src/main/kotlin/com/vk/id/Detekt.kt create mode 100644 build-logic/convention/src/main/kotlin/com/vk/id/KotlinAndroid.kt create mode 100644 build-logic/convention/src/main/kotlin/com/vk/id/PrintTestApks.kt create mode 100644 build-logic/convention/src/main/kotlin/com/vk/id/ProjectExtensions.kt create mode 100644 build-logic/convention/src/main/kotlin/com/vk/id/Versions.kt create mode 100644 build-logic/gradle.properties create mode 100644 build-logic/settings.gradle.kts create mode 100644 build.gradle.kts create mode 100644 config/detekt-compose.yml create mode 100644 config/detekt.yml create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 logo.svg create mode 100644 sample/.gitignore create mode 100644 sample/build.gradle.kts create mode 100644 sample/gradle.lockfile create mode 100644 sample/proguard-rules.pro create mode 100644 sample/src/main/AndroidManifest.xml create mode 100644 sample/src/main/java/com/vk/id/sample/MainActivity.kt create mode 100644 sample/src/main/java/com/vk/id/sample/VKButton.kt create mode 100644 sample/src/main/res/drawable/vkid_icon.xml create mode 100644 sample/src/main/res/drawable/vkid_spinner.xml create mode 100644 sample/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 sample/src/main/res/mipmap-hdpi/mp_launcher.png create mode 100644 sample/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 sample/src/main/res/mipmap-mdpi/mp_launcher.png create mode 100644 sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 sample/src/main/res/mipmap-xhdpi/mp_launcher.png create mode 100644 sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 sample/src/main/res/mipmap-xxhdpi/mp_launcher.png create mode 100644 sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 sample/src/main/res/mipmap-xxxhdpi/mp_launcher.png create mode 100644 sample/src/main/res/values-ru/strings.xml create mode 100644 sample/src/main/res/values/colors.xml create mode 100644 sample/src/main/res/values/strings.xml create mode 100644 sample/src/main/res/values/themes.xml create mode 100644 sample/src/main/res/xml/network_security_config.xml create mode 100755 scripts/git-hooks/pre-push create mode 100644 scripts/install-git-hooks.sh create mode 100644 settings-gradle.lockfile create mode 100644 settings.gradle.kts create mode 100644 vkid/.gitignore create mode 100644 vkid/api/vkid.api create mode 100644 vkid/build.gradle.kts create mode 100644 vkid/consumer-rules.pro create mode 100644 vkid/gradle.lockfile create mode 100644 vkid/gradle.properties create mode 100644 vkid/proguard-rules.pro create mode 100644 vkid/src/main/AndroidManifest.xml create mode 100644 vkid/src/main/java/com/vk/id/AccessToken.kt create mode 100644 vkid/src/main/java/com/vk/id/VKID.kt create mode 100644 vkid/src/main/java/com/vk/id/VKIDAuthFail.kt create mode 100644 vkid/src/main/java/com/vk/id/auth/VKIDAuthParams.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/api/VKIDApi.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/api/VKIDApiService.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/api/VKIDCall.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/AuthActivity.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/AuthEventBridge.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/AuthOptions.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/AuthProvidersChooser.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/AuthProvidersChooserDefault.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/AuthResult.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/ServiceCredentials.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/VKIDAuthProvider.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/VKIDTokenPayload.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/app/AppAuthProvider.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/app/SilentAuthInfoUtils.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/app/SilentAuthServicesProvider.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/app/TrustedProvidersCache.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/app/VkAuthProviderInfo.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/app/VkAuthSilentAuthProvider.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/device/DeviceIdPrefs.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/device/DeviceIdProvider.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/pkce/PkceGeneratorSHA256.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/BrowserDescriptor.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/BrowserMatcher.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/BrowserSelector.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/Browsers.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/ContextUtils.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/DelimitedVersion.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/VersionRange.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/VersionedBrowserMatcher.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/WebAuthProvider.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/auth/web/WhiteListedBrowserHelper.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/concurrent/CoroutinesDispatchers.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/concurrent/CoroutinesDispatchersProd.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/di/VKIDDeps.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/di/VKIDDepsProd.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/log/AndroidLogcatLogEngine.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/log/FakeLogEngine.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/log/LogEngine.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/log/Logger.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/log/LoggerWithTag.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/log/VKIDLog.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/store/PrefsStore.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/util/MD5.kt create mode 100644 vkid/src/main/java/com/vk/id/internal/util/ThreadLocalDelegate.kt create mode 100644 vkid/src/main/res/values/make_all_resources_private.xml create mode 100644 vkid/src/main/res/values/styles.xml create mode 100644 vkid/src/test/java/com/vk/id/internal/log/AndroidLogcatLogEngineTest.kt create mode 100644 vkid/src/test/java/com/vk/id/internal/log/FakeLogEngineTest.kt create mode 100644 vkid/src/test/java/com/vk/id/internal/log/VKIDLogTest.kt diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..156caf32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +.gradle +/local.properties +/.idea/workspace.xml +.DS_Store + +# built application files +*.apk +*.ap_ + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ + +# Local configuration file (sdk path, etc) +local.properties + +# Eclipse project files +.classpath +.project + +# Proguard folder generated by Eclipse +proguard/ + +# Intellij project files +*.iml +*.ipr +*.iws +.idea/ + +# Gradle +build/ + +# Maven +target/ +build-maven + +!gradle \ No newline at end of file diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS new file mode 100644 index 00000000..71894a32 --- /dev/null +++ b/.gitlab/CODEOWNERS @@ -0,0 +1,3 @@ +# ===== CODE OWNERS ===== +*gradle.lockfile @co-is @co-is-required +*settings.gradle.kts @co-is @co-is-required diff --git a/.gitlab/merge_request_templates /Default.md b/.gitlab/merge_request_templates /Default.md new file mode 100644 index 00000000..d8e2b813 --- /dev/null +++ b/.gitlab/merge_request_templates /Default.md @@ -0,0 +1,58 @@ +## Чеклист для влития + +* [ ] Ветка сделана от свежей версии девелопа +* [ ] Код проверен на тестовом окружении +* [ ] Код покрыт тестами, по возможности +* [ ] В демку внесены изменения, по возможности +* [ ] Изменения описаны в документации +* [ ] Задача находится в статусе Verified или у нее стоит тег dev_test + +## Какиe изменения сделаны? + + +## Зачем сделаны изменения? + + +## Как реализованы изменения? + + +## Как проводилось тестирование? + + +## На что обратить внимание? + diff --git a/CODE_STYLE.md b/CODE_STYLE.md new file mode 100644 index 00000000..e655a1fc --- /dev/null +++ b/CODE_STYLE.md @@ -0,0 +1,8 @@ +# Code Style + +В проекте используется detekt и [ktlint](https://detekt.dev/docs/rules/formatting/)-плагин для него. +Ktlint это чуть более строгие стандартные [котлиновские гайдлайны](https://kotlinlang.org/docs/coding-conventions.html). + +И детект и форматтер запускаются одной командой `./gradlew detekt` — форматтер постарается сразу исправить то, что сможет, но ошибки покажет в любом случае, даже если все исправил. + +Чтобы detekt запускался перед каждым пушем, выполните скрипт `sudo bash scripts/install-git-hooks.sh` — может понадобиться sudo так как гит-хуки это исполняемые файлы. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..0e0a919f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,87 @@ +# Contributing + +## ⏳ Подготовка к разработке +Для начала работы нужно склонировать репозиторий и перейти в созданную директорию + +```bash +git clone git@gitlab.mvk.com:vk-ecosystem/shared/vk-id.git +cd android-sdk +``` +Так же можно сделать форк и склонировать его + +## 🐶 Базовые команды +> Все команды запускаются из корня проекта +1. `./gradlew build` - полная сборка проекта +2. `./gradlew test` - прогон unit тестов +3. `./gradlew lint` - запуск android линта +4. `./gradlew detekt` - запуск detekt для проверки качества кода + +## 🪵 Создание ветки + +Ветки создаются от `develop`. + +Для названия веток используется специальный шаблон: + +``` +{username}/{task_type}/{issue_number}/{description} + +Где: +- {username} - Ник пользователя в свободном формате, латиницей +- {task_type} - "fix", если это испарвление бага и "feature", если это полноценная доработка +- {issue_number} - VKIDSDK-XXX для разработчиков VK и ISSUE-XXX для внешних контрибьютеров +- {description} - Краткое описание проделанной работы +``` + +Пример: +```bash +git checkout develop +git pull +git checkout -b u.name/feature/some-feature/ISSUE-0000 +``` + +Для веток будет сделана проверка формата в хуке `commit-msg`, которая провалидирует соответствие названия ветки шаблону + +## 📝 Создание коммита + +Сообщение в коммите должно соответствовать шаблону: + +``` +{issue_number}: {commit_description} + +Где: +- {issue_number} - VKIDSDK-XXX для разработчиков VK и ISSUE-XXX для внешних контрибьютеров +- {commit_description} - Краткое описание коммита на английском языке +``` + +Для коммитов будет добавлен линтер на хук `commit-msg`, который проверяет, соответствует ли сообщение в коммите шаблону + +Пример: +```bash +git checkout develop +git add -A +git commit -m "ISSUE-0000: some commit description" +``` + +## 😸 Подготовка Merge Request + +Заголовок мра должен быть сделан по следующему шаблону: +``` +{issue_number}: {commit_description} + +Где: +- {issue_number} - VKIDSDK-XXX для разработчиков VK и ISSUE-XXX для внешних контрибьютеров +- {commit_description} - Краткое описание коммита на английском языке +``` + +Пример: +``` +ISSUE-000: Some issue description +``` + +Для того, чтобы подготовить Merge Request, необходимо пройти [Чеклист](.gitlab/Default.md) + +## 🚅 Релизы версий +### TODO, добавить после публикации релизов + +## 🖊️ Документация +### TODO, добавить после поддержки генерации документации \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..792e0c8e --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +Copyright © 2023 V Kontakte LLC +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 198e539e..91b56e16 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,106 @@ -# VK ID +
+

+ VK ID SDK Logo +

+

+ VK ID SDK — библиотека для авторизации пользователей Android-приложений с помощью аккаунта VK ID. +

+
-VK ID - SDK для авторизации пользователей Android приложений с помощью аккаунта VK. +## Предварительно +Что такое VK ID и как интегрировать его в приложение читайте здесь https://id.vk.com/business/go/docs/vkid/latest/start-page. + +Чтобы подключить VK ID SDK, сначала получите ID приложения (app_id) и защищенный ключ (client_secret). Для этого создайте приложение в [кабинете подключения VK ID](https://id.vk.com/business/go/docs/vkid/latest/create-application). + + +## Установка + +Для начала работы добавьте репозиторий: +```kotlin +maven { + url("https://artifactory-external.vkpartner.ru/artifactory/vkid-sdk-andorid/") +} +``` + +Подключите библиотеку: +```kotlin +implementation("com.vk.id:vkid:${sdkVersion}") +``` + +И пропишите плейсхолдеры манифеста в секции `android` в `build.gradle.kts`: +```kotlin +android { + //... + addManifestPlaceholders(mapOf( + "VKIDClientID" to "1233445", // ID вашего приложения (app_id). + "VKIDClientSecret" to "000000000000", // Ваш защищенный ключ (client_secret). + "VKIDRedirectHost" to "vk.com", // Обычно используется vk.com. + "VKIDRedirectScheme" to "vk1233445", // Обычно используется vk{ID приложения}. + )) +} +``` + +## Интеграция +### Инициализация VK ID SDK +Инициализируйте работу VK ID SDK через объект `VKID`. +```kotlin +val vkid = VKID(context) +``` +### Авторизация +Результат авторизации передается в коллбэк `VKID.AuthCallback`, поэтому его нужно объявить: +```kotlin +private val vkAuthCallback = object : VKID.AuthCallback { + override fun onSuccess(accessToken: AccessToken) { + val token = accessToken.token + //... + } + + override fun onFail(fail: VKIDAuthFail) { + when (fail) { + is VKIDAuthFail.Canceled -> { /*...*/ } + else -> { + //... + } + } + } +} +``` +Авторизация запускается с помощью метода authorize(), у которого есть два варианта вызова: +```kotlin +viewModelScope.launch { + vkid.authorize(vkAuthCallback) +} +``` +или с передачей LifecycleOwner: +```kotlin +vkid.authorize(this@MainActivity, vkAuthCallback) // Первый параметр LifecycleOwner, например активити. +``` + +## Демонстрация + +SDK поставляется с [тестовым примером приложения](sample), где можно посмотреть работу авторизации. +Чтобы получить токен, создайте файл secrets.properties и пропишите в нем client_id и client_secret вашего приложения VK ID: + + +Файл `secrets.properties`: +``` +VKIDClientSecret=Ваш защищённый ключ +VKIDClientID=Ваш ID приложения +``` + +## Документация + +- [Что такое VK ID](https://id.vk.com/business/go/docs/vkid/latest/start-page) +- [Создание приложения](https://platform.vk.com/docs/vkid/latest/create-application) +- [Требования к дизайну](https://platform.vk.com/docs/vkid/latest/guidelines/design-rules) + +## Contributing +Проект VK ID SDK имеет открытый исходный код на GitHub, и вы можете присоединиться к его доработке — мы будем благодарны за внесение улучшений и исправление возможных ошибок. + +### Code of Conduct +Если вы собираетесь вносить изменения в проект VK ID SDK, следуйте [правилам разработки](CODE_OF_CONDUCT.md). Они помогут понять, какие действия возможны, а какие недопустимы. + +### Contributing Guide +В [руководстве](CONTRIBUTING.md) вы можете подробно ознакомиться с процессом разработки и узнать, как предлагать улучшения и исправления, а ещё — как добавлять и тестировать свои изменения в VK ID SDK. +Также рекомендуем ознакомиться с общими [правилами оформления кода](CODE_STYLE.md) в проекте. diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts new file mode 100644 index 00000000..f08cadef --- /dev/null +++ b/build-logic/convention/build.gradle.kts @@ -0,0 +1,54 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `kotlin-dsl` +} + +group = "com.vk.id.buildlogic" + +// Configure the build-logic plugins to target JDK 17 +// This matches the JDK used to build the project, and is not related to what is running on device. +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} +tasks.withType().configureEach { + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } +} + +dependencies { + compileOnly(libs.android.gradlePlugin) + compileOnly(libs.kotlin.gradlePlugin) + compileOnly(libs.ksp.gradlePlugin) + compileOnly(libs.detekt.gradlePlugin) +} + +gradlePlugin { + plugins { + register("androidApplication") { + id = "vkid.android.application" + implementationClass = "AndroidApplicationConventionPlugin" + } + register("androidApplicationCompose") { + id = "vkid.android.application.compose" + implementationClass = "AndroidApplicationComposeConventionPlugin" + } + register("androidLibrary") { + id = "vkid.android.library" + implementationClass = "VKIDLibraryConventionPlugin" + } + register("vkidPublish") { + id = "vkid.android.publish" + implementationClass = "VKIDPublishConventionPlugin" + } + register("vkidDependencyLock") { + id = "vkid.android.dependency.lock" + implementationClass = "DependencyLockPlugin" + description = """Helper to create lockfiles for all modules with one command. + |Usage: `./gradlew allDependencies --write-locks`""".trimMargin() + } + } +} + diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt new file mode 100644 index 00000000..df11912c --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt @@ -0,0 +1,17 @@ +import com.android.build.api.dsl.ApplicationExtension +import com.vk.id.configureAndroidCompose +import com.vk.id.configureDetekt +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +class AndroidApplicationComposeConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + pluginManager.apply("vkid.android.application") + val extension = extensions.getByType() + configureAndroidCompose(extension) + configureDetekt(isCompose = true) + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt new file mode 100644 index 00000000..bf1f55d4 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2022 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 + * + * 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. + */ + +import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.variant.ApplicationAndroidComponentsExtension +import com.vk.id.Versions +import com.vk.id.configureKotlinAndroid +import com.vk.id.configurePrintApksTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +class AndroidApplicationConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.application") + apply("org.jetbrains.kotlin.android") + } + + extensions.configure { + configureKotlinAndroid(this) + defaultConfig.targetSdk = Versions.targetSdk + } + extensions.configure { + configurePrintApksTask(this) + } + } + } + +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/AndroidInstrumentedTests.kt b/build-logic/convention/src/main/kotlin/AndroidInstrumentedTests.kt new file mode 100644 index 00000000..d9a55351 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/AndroidInstrumentedTests.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2023 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 + * + * 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. + */ + +import com.android.build.api.variant.LibraryAndroidComponentsExtension +import org.gradle.api.Project + +/** + * Disable unnecessary Android instrumented tests for the [project] if there is no `androidTest` folder. + * Otherwise, these projects would be compiled, packaged, installed and ran only to end-up with the following message: + * + * > Starting 0 tests on AVD + * + * Note: this could be improved by checking other potential sourceSets based on buildTypes and flavors. + */ +internal fun LibraryAndroidComponentsExtension.disableUnnecessaryAndroidTests( + project: Project, +) = beforeVariants { + it.enableAndroidTest = it.enableAndroidTest + && project.projectDir.resolve("src/androidTest").exists() +} diff --git a/build-logic/convention/src/main/kotlin/DependencyLockPlugin.kt b/build-logic/convention/src/main/kotlin/DependencyLockPlugin.kt new file mode 100644 index 00000000..388db175 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/DependencyLockPlugin.kt @@ -0,0 +1,23 @@ +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task + +/** + * Usage: `./gradlew allDependencies --write-locks` + */ +class DependencyLockPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + subprojects { + configurations.all { + resolutionStrategy.activateDependencyLocking() + } + } + + val allSubTasks = subprojects.map { ":${it.name}:dependencies" }.map(project.tasks::getByPath) + tasks.register("allDependencies") { + dependsOn(allSubTasks) + } + } + } +} diff --git a/build-logic/convention/src/main/kotlin/VKIDLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/VKIDLibraryConventionPlugin.kt new file mode 100644 index 00000000..8cab19bd --- /dev/null +++ b/build-logic/convention/src/main/kotlin/VKIDLibraryConventionPlugin.kt @@ -0,0 +1,41 @@ +import com.android.build.gradle.LibraryExtension +import com.vk.id.Versions +import com.vk.id.configureDetekt +import com.vk.id.configureKotlinAndroid +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.kotlin +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +class VKIDLibraryConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.library") + apply("org.jetbrains.kotlin.android") + } + + extensions.configure { + configureKotlinAndroid(this) + defaultConfig.targetSdk = Versions.targetSdk + + tasks.withType().configureEach { + kotlinOptions { + // Force implicit visibility modifiers to avoid mistakes like exposing internal api + freeCompilerArgs = freeCompilerArgs + "-Xexplicit-api=strict" + } + } + + resourcePrefix("vkid_") + } + configureDetekt(isCompose = false) + dependencies { + add("androidTestImplementation", kotlin("test")) + add("testImplementation", kotlin("test")) + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/VKIDPublishConventionPlugin.kt b/build-logic/convention/src/main/kotlin/VKIDPublishConventionPlugin.kt new file mode 100644 index 00000000..516c9adf --- /dev/null +++ b/build-logic/convention/src/main/kotlin/VKIDPublishConventionPlugin.kt @@ -0,0 +1,135 @@ +import com.android.build.gradle.LibraryExtension +import com.vk.id.stringProperty +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.provider.Property +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.get +import org.gradle.plugins.signing.SigningExtension +import java.net.URI +import java.util.Base64 + +class VKIDPublishConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + apply(plugin = MAVEN_PUBLISH_PLUGIN_ID) + apply(plugin = SIGNING_PLUGIN_ID) + + configurePublishSingleVariant() + } + } + + private fun Project.configurePublishSingleVariant() { + val projectName = name + + extensions.configure { + publishing { + singleVariant("release") { + withSourcesJar() + } + } + } + + pluginManager.withPlugin(MAVEN_PUBLISH_PLUGIN_ID) { + extensions.configure(PublishingExtension::class.java) { + repositories { + maven { + url = URI(stringProperty(RELEASE_REPOSITORY_URL)) + credentials { + username = stringProperty(REPOSITORY_USERNAME) + password = stringProperty(REPOSITORY_PASSWORD) + } + } + } + publications { + register(projectName, MavenPublication::class.java) { + groupId = stringProperty(GROUP) + artifactId = stringProperty(POM_ARTIFACT_ID) + version = stringProperty(VERSION_NAME) + + afterEvaluate { + from(components["release"]) + applyPom(this) + } + } + } + extensions.configure(SigningExtension::class.java) { + val keyId = stringProperty(SIGNING_KEY_ID) + val password = stringProperty(SIGNING_PASSWORD) + val secretKey = String(Base64.getDecoder().decode(stringProperty(SECRET_KEY_RING_BASE64))) + if (keyId.isNotEmpty()) { + println("Sign key id: $keyId") + } + useInMemoryPgpKeys(keyId, secretKey, password) + sign(publications[projectName]) + } + } + } + } + + private fun MavenPublication.applyPom(project: Project) { + fun Property.pset(propertyName: String) = set(project.stringProperty(propertyName)) + + pom { + name.pset(POM_NAME) + description.pset(POM_DESCRIPTION) + url.pset(POM_URL) + packaging = project.stringProperty(POM_PACKAGING) + scm { + url.pset(POM_SCM_URL) + connection.pset(POM_SCM_CONNECTION) + developerConnection.pset(POM_SCM_DEV_CONNECTION) + } + licenses { + license { + name.pset(POM_LICENCE_NAME) + url.pset(POM_LICENCE_URL) + distribution.pset(POM_LICENCE_DISTRIBUTION) + } + } + developers { + developer { + id.pset(POM_DEVELOPER_ID) + name.pset(POM_DEVELOPER_NAME) + email.pset(POM_DEVELOPER_EMAIL) + } + } + } + } + + private companion object { + const val GROUP = "GROUP" + const val POM_ARTIFACT_ID = "POM_ARTIFACT_ID" + const val VERSION_NAME = "VERSION_NAME" + + const val RELEASE_REPOSITORY_URL = "RELEASE_REPOSITORY_URL" + const val REPOSITORY_USERNAME = "REPOSITORY_USERNAME" + const val REPOSITORY_PASSWORD = "REPOSITORY_PASSWORD" + const val SIGNING_KEY_ID = "SIGNING_KEY_ID" + const val SECRET_KEY_RING_BASE64 = "SECRET_KEY_RING_BASE64" + const val SIGNING_PASSWORD = "SIGNING_PASSWORD" + + const val POM_URL = "POM_URL" + const val POM_NAME = "POM_NAME" + const val POM_DESCRIPTION = "POM_DESCRIPTION" + const val POM_PACKAGING = "POM_PACKAGING" + + const val MAVEN_PUBLISH_PLUGIN_ID = "maven-publish" + const val SIGNING_PLUGIN_ID = "signing" + + const val POM_SCM_URL = "POM_SCM_URL" + const val POM_SCM_CONNECTION = "POM_SCM_CONNECTION" + const val POM_SCM_DEV_CONNECTION = "POM_SCM_DEV_CONNECTION" + + const val POM_LICENCE_NAME = "POM_LICENCE_NAME" + const val POM_LICENCE_URL = "POM_LICENCE_URL" + const val POM_LICENCE_DISTRIBUTION = "POM_LICENCE_DISTRIBUTION" + + const val POM_DEVELOPER_ID = "POM_DEVELOPER_ID" + const val POM_DEVELOPER_NAME = "POM_DEVELOPER_NAME" + const val POM_DEVELOPER_EMAIL = "POM_DEVELOPER_EMAIL" + } +} diff --git a/build-logic/convention/src/main/kotlin/com/vk/id/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/com/vk/id/AndroidCompose.kt new file mode 100644 index 00000000..8eb9eb03 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/vk/id/AndroidCompose.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2022 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 + * + * 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. + */ + +package com.vk.id + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.io.File + +/** + * Configure Compose-specific options + */ +internal fun Project.configureAndroidCompose( + commonExtension: CommonExtension<*, *, *, *, *>, +) { + commonExtension.apply { + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString() + } + + dependencies { + val bom = libs.findLibrary("androidx-compose-bom").get() + add("implementation", platform(bom)) + add("androidTestImplementation", platform(bom)) + } + } + + tasks.withType().configureEach { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + buildComposeMetricsParameters() + } + } +} + +private fun Project.buildComposeMetricsParameters(): List { + val metricParameters = mutableListOf() + val enableMetricsProvider = project.providers.gradleProperty("enableComposeCompilerMetrics") + val enableMetrics = (enableMetricsProvider.orNull == "true") + if (enableMetrics) { + val metricsFolder = File(project.buildDir, "compose-metrics") + metricParameters.add("-P") + metricParameters.add( + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" + metricsFolder.absolutePath + ) + } + + val enableReportsProvider = project.providers.gradleProperty("enableComposeCompilerReports") + val enableReports = (enableReportsProvider.orNull == "true") + if (enableReports) { + val reportsFolder = File(project.buildDir, "compose-reports") + metricParameters.add("-P") + metricParameters.add( + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" + reportsFolder.absolutePath + ) + } + return metricParameters.toList() +} diff --git a/build-logic/convention/src/main/kotlin/com/vk/id/Detekt.kt b/build-logic/convention/src/main/kotlin/com/vk/id/Detekt.kt new file mode 100644 index 00000000..3c5f3d44 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/vk/id/Detekt.kt @@ -0,0 +1,39 @@ +package com.vk.id + +import io.gitlab.arturbosch.detekt.Detekt +import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.withType + +fun Project.configureDetekt(isCompose: Boolean = false) { + pluginManager.apply("io.gitlab.arturbosch.detekt") + + tasks.withType().configureEach { + jvmTarget = "1.8" + reports { + html.required.set(true) + html.outputLocation.set(file("${project.buildDir}/reports/detekt-results-${project.name}.html")) + txt.required.set(true) + txt.outputLocation.set(file("${project.buildDir}/reports/detekt-results-${project.name}.txt")) + xml.required.set(false) + sarif.required.set(false) + md.required.set(false) + } + buildUponDefaultConfig = true + allRules = false + val configs = listOfNotNull( + "$rootDir/config/detekt.yml", + if (isCompose) "$rootDir/config/detekt-compose.yml" else null + ) + config.setFrom(configs) + autoCorrect = true + + } + tasks.withType().configureEach { + jvmTarget = "1.8" + } + dependencies { + "detektPlugins"(libs.findLibrary("detekt-formatting").get()) + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/com/vk/id/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/com/vk/id/KotlinAndroid.kt new file mode 100644 index 00000000..5ed88be0 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/vk/id/KotlinAndroid.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2022 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 + * + * 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. + */ + +package com.vk.id + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +/** + * Configure base Kotlin with Android options + */ +internal fun Project.configureKotlinAndroid( + commonExtension: CommonExtension<*, *, *, *, *>, +) { + commonExtension.apply { + compileSdk = Versions.compileSdk + + defaultConfig { + minSdk = Versions.minSdk + } + + compileOptions { + // Up to Java 11 APIs are available through desugaring + // https://developer.android.com/studio/write/java11-minimal-support-table + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + isCoreLibraryDesugaringEnabled = true + } + } + + configureKotlin() + + dependencies { + add("coreLibraryDesugaring", libs.findLibrary("android.desugarJdkLibs").get()) + } +} + +/** + * Configure base Kotlin options + */ +private fun Project.configureKotlin() { + // Use withType to workaround https://youtrack.jetbrains.com/issue/KT-55947 + tasks.withType().configureEach { + kotlinOptions { + // Set JVM target to 11 + jvmTarget = JavaVersion.VERSION_11.toString() + // Treat all Kotlin warnings as errors (disabled by default) + // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties + val warningsAsErrors: String? by project + allWarningsAsErrors = warningsAsErrors.toBoolean() + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/vk/id/PrintTestApks.kt b/build-logic/convention/src/main/kotlin/com/vk/id/PrintTestApks.kt new file mode 100644 index 00000000..25603fb7 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/vk/id/PrintTestApks.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2022 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 + * + * 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. + */ + +package com.vk.id + +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.BuiltArtifactsLoader +import com.android.build.api.variant.HasAndroidTest +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.file.Directory +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.TaskAction +import java.io.File + +internal fun Project.configurePrintApksTask(extension: AndroidComponentsExtension<*, *, *>) { + extension.onVariants { variant -> + if (variant is HasAndroidTest) { + val loader = variant.artifacts.getBuiltArtifactsLoader() + val artifact = variant.androidTest?.artifacts?.get(SingleArtifact.APK) + val javaSources = variant.androidTest?.sources?.java?.all + val kotlinSources = variant.androidTest?.sources?.kotlin?.all + + val testSources = if (javaSources != null && kotlinSources != null) { + javaSources.zip(kotlinSources) { javaDirs, kotlinDirs -> + javaDirs + kotlinDirs + } + } else javaSources ?: kotlinSources + + if (artifact != null && testSources != null) { + tasks.register( + "${variant.name}PrintTestApk", + PrintApkLocationTask::class.java + ) { + apkFolder.set(artifact) + builtArtifactsLoader.set(loader) + variantName.set(variant.name) + sources.set(testSources) + } + } + } + } +} + +internal abstract class PrintApkLocationTask : DefaultTask() { + @get:InputDirectory + abstract val apkFolder: DirectoryProperty + + @get:InputFiles + abstract val sources: ListProperty + + @get:Internal + abstract val builtArtifactsLoader: Property + + @get:Input + abstract val variantName: Property + + @TaskAction + fun taskAction() { + val hasFiles = sources.orNull?.any { directory -> + directory.asFileTree.files.any { + it.isFile && it.parentFile.path.contains("build${File.separator}generated").not() + } + } ?: throw RuntimeException("Cannot check androidTest sources") + + // Don't print APK location if there are no androidTest source files + if (!hasFiles) { + return + } + + val builtArtifacts = builtArtifactsLoader.get().load(apkFolder.get()) + ?: throw RuntimeException("Cannot load APKs") + if (builtArtifacts.elements.size != 1) + throw RuntimeException("Expected one APK !") + val apk = File(builtArtifacts.elements.single().outputFile).toPath() + println(apk) + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/com/vk/id/ProjectExtensions.kt b/build-logic/convention/src/main/kotlin/com/vk/id/ProjectExtensions.kt new file mode 100644 index 00000000..f5769205 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/vk/id/ProjectExtensions.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2023 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 + * + * 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. + */ + +package com.vk.id + +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.kotlin.dsl.getByType + +val Project.libs + get(): VersionCatalog = extensions.getByType().named("libs") + +fun Project.stringProperty(key: String, default: String = ""): String { + var prop = (properties[key] as? String).takeIf { it is String && it.isNotEmpty() } + if (prop == null) { + prop = (rootProject.properties[key] as? String).takeIf { it is String && it.isNotEmpty() } + } + return prop ?: default +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/com/vk/id/Versions.kt b/build-logic/convention/src/main/kotlin/com/vk/id/Versions.kt new file mode 100644 index 00000000..b7a0de51 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/vk/id/Versions.kt @@ -0,0 +1,7 @@ +package com.vk.id + +object Versions { + const val minSdk = 21 + const val compileSdk = 33 + const val targetSdk = 33 +} diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties new file mode 100644 index 00000000..48b2ab83 --- /dev/null +++ b/build-logic/gradle.properties @@ -0,0 +1,4 @@ +# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534 +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configureondemand=true \ No newline at end of file diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 00000000..2907fbfb --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,14 @@ +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" +include(":convention") diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 00000000..d9059a0d --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.binary.compatibility.validator) apply false + alias(libs.plugins.kotlin.parcelize) apply false + alias(libs.plugins.detekt) apply false + id("vkid.android.dependency.lock") apply true +} diff --git a/config/detekt-compose.yml b/config/detekt-compose.yml new file mode 100644 index 00000000..6903012e --- /dev/null +++ b/config/detekt-compose.yml @@ -0,0 +1,20 @@ +complexity: + active: true + LongParameterList: + active: true + ignoreDefaultParameters: true + +naming: + FunctionNaming: + active: true + ignoreAnnotated: ['Composable'] + +style: + active: true + MagicNumber: + active: true + ignorePropertyDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + UnusedPrivateMember: + active: true + ignoreAnnotated: ["Preview"] diff --git a/config/detekt.yml b/config/detekt.yml new file mode 100644 index 00000000..18d8ffb4 --- /dev/null +++ b/config/detekt.yml @@ -0,0 +1,26 @@ +build: + maxIssues: 0 + excludeCorrectable: false + +config: + validation: true + warningsAsErrors: true + +complexity: + active: true + NestedBlockDepth: + # increased from 4 to 5 + active: true + threshold: 5 + +style: + active: true + MaxLineLength: + # disable to prefer ktlint rule + active: false + +formatting: + active: true + MaximumLineLength: + active: true + maxLineLength: 150 \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..64bfb333 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,33 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true + +POM_DESCRIPTION=Android library for VK ID authorization +POM_DEVELOPER_ID=vk +POM_DEVELOPER_NAME=VK ID +POM_DEVELOPER_EMAIL=devsupport@corp.vk.com +POM_LICENCE_NAME=MIT + +VERSION_NAME=0.0.1-alpha +VERSION_CODE=1 +GROUP=com.vk.id \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..d6785c02 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,53 @@ +[versions] +androidDesugarJdkLibs = "2.0.3" +androidGradlePlugin = "8.1.1" +androidxActivity = "1.7.0" +androidxAnnotation = "1.6.0" +androidxBrowser = "1.5.0" +androidxComposeBom = "2023.04.01" +androidxComposeCompiler = "1.4.6" +androidxCore = "1.9.0" +detekt = "1.22.0" +binary-compatibility-validator = "0.13.2" +kotlin = "1.8.20" +kotlinxCoroutines = "1.7.1" +ksp = "1.8.20-1.0.11" +mockk = "1.13.5" +okHttpVersion = "4.11.0" +okioVersion = "3.4.0" +preference = "1.2.0" + +[libraries] +android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" } +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" } +androidx-annotation = { group = "androidx.annotation", name = "annotation", version.ref = "androidxAnnotation" } +androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } +androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-compose-ui-util = { group = "androidx.compose.ui", name = "ui-util" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidxCore" } +androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" } +androidx-preference-ktx = { group = "androidx.preference", name = "preference-ktx", version.ref = "preference" } +kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" } +kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } +mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } +okhttp3-okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okHttpVersion" } +okhttp3-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okHttpVersion" } +okio = { group = "com.squareup.okio", name = "okio", version = { require = "3.4.0" } } + +# Dependencies of the included build-logic +android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } +kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } +ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } +detekt-formatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" } +detekt-gradlePlugin = { group = "io.gitlab.arturbosch.detekt", name = "detekt-gradle-plugin", version.ref = "detekt" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" } +kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 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

K7UpUK$>l@ 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 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..e63a2c64 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 02 16:01:06 MSK 2023 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..4f906e0c --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/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/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@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 execute + +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 execute + +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 + +: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 %* + +: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/logo.svg b/logo.svg new file mode 100644 index 00000000..b1e7c007 --- /dev/null +++ b/logo.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/sample/.gitignore b/sample/.gitignore new file mode 100644 index 00000000..50fd5bee --- /dev/null +++ b/sample/.gitignore @@ -0,0 +1,2 @@ +/build +/secrets.properties \ No newline at end of file diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts new file mode 100644 index 00000000..c29a8b7f --- /dev/null +++ b/sample/build.gradle.kts @@ -0,0 +1,52 @@ +import com.android.build.api.dsl.ApplicationDefaultConfig +import java.io.FileInputStream +import java.util.Properties + +plugins { + id("vkid.android.application.compose") +} + +android { + namespace = "com.vk.id.sample" + + defaultConfig { + applicationId = "com.vk.id.sample" + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + initVKID() + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } +} + +dependencies { + implementation(project(":vkid")) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.ui.util) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.kotlinx.coroutines.android) + debugImplementation(libs.androidx.compose.ui.tooling) +} + +fun ApplicationDefaultConfig.initVKID() { + val secrets = Properties() + secrets.load(FileInputStream(file("secrets.properties"))) + val clientId = secrets["VKIDClientID"] ?: throw IllegalStateException("Add VKIDClientID to file secrets.properties") + val clientSecret = secrets["VKIDClientSecret"] ?: throw IllegalStateException("Add VKIDClientSecret to file secrets.properties") + addManifestPlaceholders(mapOf( + "VKIDRedirectHost" to "vk.com", + "VKIDRedirectScheme" to "vk$clientId", + "VKIDClientID" to clientId, + "VKIDClientSecret" to clientSecret + )) +} diff --git a/sample/gradle.lockfile b/sample/gradle.lockfile new file mode 100644 index 00000000..3afa1096 --- /dev/null +++ b/sample/gradle.lockfile @@ -0,0 +1,160 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# This file is expected to be part of source control. +androidx.activity:activity-compose:1.7.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.activity:activity-ktx:1.7.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.activity:activity:1.7.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.annotation:annotation-experimental:1.1.0=debugAndroidTestCompileClasspath +androidx.annotation:annotation-experimental:1.3.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.annotation:annotation-jvm:1.6.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.annotation:annotation:1.5.0=debugAndroidTestCompileClasspath +androidx.annotation:annotation:1.6.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.appcompat:appcompat-resources:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.appcompat:appcompat:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.arch.core:core-common:2.2.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.arch.core:core-runtime:2.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.asynclayoutinflater:asynclayoutinflater:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.autofill:autofill:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.browser:browser:1.5.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.collection:collection-ktx:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.collection:collection:1.0.0=debugAndroidTestCompileClasspath +androidx.collection:collection:1.1.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.animation:animation-core:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.animation:animation:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.compiler:compiler:1.4.6=kotlin-extension +androidx.compose.foundation:foundation-layout:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.foundation:foundation:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.material3:material3:1.0.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.material:material-icons-core:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.material:material-ripple:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.material:material:1.4.2=debugRuntimeClasspath,debugUnitTestRuntimeClasspath +androidx.compose.runtime:runtime-saveable:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.runtime:runtime:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-geometry:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-graphics:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-text:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-tooling-data:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath +androidx.compose.ui:ui-tooling-preview:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-tooling:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath +androidx.compose.ui:ui-unit:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui-util:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose.ui:ui:1.4.2=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.compose:compose-bom:2023.04.01=androidTestImplementationDependenciesMetadata,debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.concurrent:concurrent-futures:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.coordinatorlayout:coordinatorlayout:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.core:core-ktx:1.2.0=debugAndroidTestCompileClasspath +androidx.core:core-ktx:1.9.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.core:core:1.8.0=debugAndroidTestCompileClasspath +androidx.core:core:1.9.0=debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.cursoradapter:cursoradapter:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.customview:customview-poolingcontainer:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.customview:customview:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.documentfile:documentfile:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.drawerlayout:drawerlayout:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.emoji2:emoji2:1.3.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.fragment:fragment-ktx:1.3.6=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.fragment:fragment:1.3.6=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.interpolator:interpolator:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.legacy:legacy-support-core-ui:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.legacy:legacy-support-core-utils:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-common:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-livedata-core-ktx:2.6.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-livedata-core:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-livedata:2.6.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-process:2.6.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-runtime-ktx:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-runtime:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.lifecycle:lifecycle-viewmodel:2.6.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.loader:loader:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.localbroadcastmanager:localbroadcastmanager:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.preference:preference-ktx:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.preference:preference:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.print:print:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.profileinstaller:profileinstaller:1.3.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.recyclerview:recyclerview:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.savedstate:savedstate-ktx:1.2.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.savedstate:savedstate:1.2.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.slidingpanelayout:slidingpanelayout:1.2.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.startup:startup-runtime:1.1.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.swiperefreshlayout:swiperefreshlayout:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.tracing:tracing:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.transition:transition:1.4.1=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.vectordrawable:vectordrawable-animated:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.vectordrawable:vectordrawable:1.1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.viewpager:viewpager:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +androidx.window:window:1.0.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.android.tools:desugar_jdk_libs:2.0.3=coreLibraryDesugaring +com.android.tools:desugar_jdk_libs_configuration:2.0.3=coreLibraryDesugaring +com.beust:jcommander:1.82=detekt +com.google.guava:listenablefuture:1.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.pinterest.ktlint:ktlint-core:0.47.1=detektPlugins +com.pinterest.ktlint:ktlint-ruleset-experimental:0.47.1=detektPlugins +com.pinterest.ktlint:ktlint-ruleset-standard:0.47.1=detektPlugins +com.squareup.okhttp3:logging-interceptor:4.11.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.squareup.okhttp3:okhttp:4.11.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.squareup.okio:okio-jvm:3.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +com.squareup.okio:okio:3.4.0=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +io.github.davidburstrom.contester:contester-breakpoint:0.2.0=detekt +io.github.detekt.sarif4k:sarif4k:0.0.1=detekt +io.github.microutils:kotlin-logging-jvm:2.1.23=detektPlugins +io.gitlab.arturbosch.detekt:detekt-api:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-cli:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-core:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-formatting:1.22.0=detektPlugins +io.gitlab.arturbosch.detekt:detekt-metrics:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-parser:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-psi-utils:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-report-html:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-report-md:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-report-sarif:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-report-txt:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-report-xml:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-complexity:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-coroutines:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-documentation:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-empty:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-errorprone:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-exceptions:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-naming:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-performance:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules-style:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-rules:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-tooling:1.22.0=detekt +io.gitlab.arturbosch.detekt:detekt-utils:1.22.0=detekt +net.java.dev.jna:jna:5.6.0=detekt,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.ec4j.core:ec4j-core:0.3.0=detektPlugins +org.jetbrains.intellij.deps:trove4j:1.0.20200330=detekt,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.8.20=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.21=detekt +org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.20=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.21=detekt +org.jetbrains.kotlin:kotlin-daemon-embeddable:1.8.20=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.8.20=kotlinKlibCommonizerClasspath +org.jetbrains.kotlin:kotlin-parcelize-runtime:1.8.20=debugRuntimeClasspath,debugUnitTestRuntimeClasspath,releaseRuntimeClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlin:kotlin-reflect:1.6.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.jetbrains.kotlin:kotlin-reflect:1.7.21=detekt +org.jetbrains.kotlin:kotlin-script-runtime:1.7.21=detekt +org.jetbrains.kotlin:kotlin-script-runtime:1.8.20=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.jetbrains.kotlin:kotlin-stdlib-common:1.7.21=detekt +org.jetbrains.kotlin:kotlin-stdlib-common:1.8.20=apiDependenciesMetadata,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20=apiDependenciesMetadata,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20=apiDependenciesMetadata,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlin:kotlin-stdlib:1.7.21=detekt +org.jetbrains.kotlin:kotlin-stdlib:1.8.20=apiDependenciesMetadata,debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.jetbrains.kotlinx:kotlinx-html-jvm:0.8.0=detekt +org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.1.0=detekt +org.jetbrains.kotlinx:kotlinx-serialization-core:1.1.0=detekt +org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.1.0=detekt +org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0=detekt +org.jetbrains:annotations:13.0=apiDependenciesMetadata,detekt,kotlinCompilerClasspath,kotlinKlibCommonizerClasspath +org.jetbrains:annotations:23.0.0=debugAndroidTestCompileClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +org.slf4j:slf4j-api:1.7.32=detektPlugins +org.yaml:snakeyaml:1.33=detekt +empty=androidApis,androidJdkImage,androidTestApiDependenciesMetadata,androidTestCompileOnlyDependenciesMetadata,androidTestDebugApiDependenciesMetadata,androidTestDebugCompileOnlyDependenciesMetadata,androidTestDebugImplementationDependenciesMetadata,androidTestDebugIntransitiveDependenciesMetadata,androidTestIntransitiveDependenciesMetadata,androidTestReleaseApiDependenciesMetadata,androidTestReleaseCompileOnlyDependenciesMetadata,androidTestReleaseImplementationDependenciesMetadata,androidTestReleaseIntransitiveDependenciesMetadata,androidTestUtil,compileOnlyDependenciesMetadata,debugAndroidTestAnnotationProcessorClasspath,debugAndroidTestApiDependenciesMetadata,debugAndroidTestCompileOnlyDependenciesMetadata,debugAndroidTestImplementationDependenciesMetadata,debugAndroidTestIntransitiveDependenciesMetadata,debugAnnotationProcessorClasspath,debugApiDependenciesMetadata,debugCompileOnlyDependenciesMetadata,debugIntransitiveDependenciesMetadata,debugReverseMetadataValues,debugUnitTestAnnotationProcessorClasspath,debugUnitTestApiDependenciesMetadata,debugUnitTestCompileOnlyDependenciesMetadata,debugUnitTestImplementationDependenciesMetadata,debugUnitTestIntransitiveDependenciesMetadata,debugWearBundling,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinCompilerPluginClasspathDebug,kotlinCompilerPluginClasspathDebugAndroidTest,kotlinCompilerPluginClasspathDebugUnitTest,kotlinCompilerPluginClasspathRelease,kotlinCompilerPluginClasspathReleaseUnitTest,kotlinNativeCompilerPluginClasspath,lintChecks,lintPublish,releaseAnnotationProcessorClasspath,releaseApiDependenciesMetadata,releaseCompileOnlyDependenciesMetadata,releaseImplementationDependenciesMetadata,releaseIntransitiveDependenciesMetadata,releaseReverseMetadataValues,releaseUnitTestAnnotationProcessorClasspath,releaseUnitTestApiDependenciesMetadata,releaseUnitTestCompileOnlyDependenciesMetadata,releaseUnitTestImplementationDependenciesMetadata,releaseUnitTestIntransitiveDependenciesMetadata,releaseWearBundling,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testDebugApiDependenciesMetadata,testDebugCompileOnlyDependenciesMetadata,testDebugImplementationDependenciesMetadata,testDebugIntransitiveDependenciesMetadata,testFixturesApiDependenciesMetadata,testFixturesCompileOnlyDependenciesMetadata,testFixturesDebugApiDependenciesMetadata,testFixturesDebugCompileOnlyDependenciesMetadata,testFixturesDebugImplementationDependenciesMetadata,testFixturesDebugIntransitiveDependenciesMetadata,testFixturesImplementationDependenciesMetadata,testFixturesIntransitiveDependenciesMetadata,testFixturesReleaseApiDependenciesMetadata,testFixturesReleaseCompileOnlyDependenciesMetadata,testFixturesReleaseImplementationDependenciesMetadata,testFixturesReleaseIntransitiveDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testReleaseApiDependenciesMetadata,testReleaseCompileOnlyDependenciesMetadata,testReleaseImplementationDependenciesMetadata,testReleaseIntransitiveDependenciesMetadata diff --git a/sample/proguard-rules.pro b/sample/proguard-rules.pro new file mode 100644 index 00000000..ff59496d --- /dev/null +++ b/sample/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle.kts. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml new file mode 100644 index 00000000..e4143975 --- /dev/null +++ b/sample/src/main/AndroidManifest.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/java/com/vk/id/sample/MainActivity.kt b/sample/src/main/java/com/vk/id/sample/MainActivity.kt new file mode 100644 index 00000000..35c2907a --- /dev/null +++ b/sample/src/main/java/com/vk/id/sample/MainActivity.kt @@ -0,0 +1,111 @@ +package com.vk.id.sample + +import android.os.Bundle +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vk.id.AccessToken +import com.vk.id.VKID +import com.vk.id.VKIDAuthFail +import kotlinx.coroutines.flow.MutableStateFlow + +class MainActivity : ComponentActivity() { + + // todo move to viewmodel + private val vkid = VKID(this) + + private val vkAuthCallback = object : VKID.AuthCallback { + override fun onSuccess(accessToken: AccessToken) { + setUiStateVkAuthComplete() + val token = accessToken.token.hideLastCharacters(TOKEN_VISIBLE_CHARACTERS) + showToast("There is token: $token") + } + + override fun onFail(fail: VKIDAuthFail) { + setUiStateVkAuthComplete() + when (fail) { + is VKIDAuthFail.Canceled -> { + showToast("Auth canceled") + } + + else -> { + showToast("Something wrong: ${fail.description}") + } + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + VKID.logsEnabled = true + setContent { + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + val vkInProgress by vkAuthInProgress.collectAsState() + VKIDButton( + inProgress = vkInProgress, + enabled = vkInProgress.not(), + onClick = ::startAuth, + modifier = Modifier.width(335.dp) + ) + Spacer(modifier = Modifier.height(24.dp)) + VKIDButtonSmall( + inProgress = vkInProgress, + enabled = vkInProgress.not(), + onClick = ::startAuth + ) + } + } + } + + private fun startAuth() { + setUiStateVkAuthInProgress() + vkid.authorize(this@MainActivity, vkAuthCallback) + } + + private fun String.hideLastCharacters(firstCharactersToKeepVisible: Int): String { + return if (this.length <= firstCharactersToKeepVisible) { + this + } else { + this.substring(0, firstCharactersToKeepVisible) + "..." + } + } + + private fun setUiStateVkAuthComplete() { + vkAuthInProgress.tryEmit(false) + } + + private fun setUiStateVkAuthInProgress() { + vkAuthInProgress.tryEmit(true) + } + + private fun showToast(text: String) { + toastOnScreen?.cancel() + toastOnScreen = Toast.makeText(this@MainActivity, text, Toast.LENGTH_LONG) + toastOnScreen?.show() + } + + private var toastOnScreen: Toast? = null + private val vkAuthInProgress: MutableStateFlow = MutableStateFlow(false) + + private companion object { + const val TOKEN_VISIBLE_CHARACTERS = 10 + } +} diff --git a/sample/src/main/java/com/vk/id/sample/VKButton.kt b/sample/src/main/java/com/vk/id/sample/VKButton.kt new file mode 100644 index 00000000..00d3eb9e --- /dev/null +++ b/sample/src/main/java/com/vk/id/sample/VKButton.kt @@ -0,0 +1,215 @@ +package com.vk.id.sample + +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicText +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun VKIDButton( + modifier: Modifier = Modifier, + radius: Dp = 8.dp, + showIcon: Boolean = true, + inProgress: Boolean = false, + enabled: Boolean = true, + onClick: () -> Unit, +) { + Row( + modifier = modifier + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple( + color = Color.White + ), + enabled = enabled, + role = Role.Button, + onClick = onClick + ) + .height(44.dp) + .clipToBounds() + .clip(RoundedCornerShape(radius)) + .background(colorResource(R.color.vkid_azure_A100)), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Box( + modifier = Modifier + .padding(8.dp) + .weight(1f), + contentAlignment = Alignment.CenterStart + ) { + if (showIcon) { + VKIcon() + } + } + @Suppress("MagicNumber") + Box( + modifier = Modifier.weight(4f), + contentAlignment = Alignment.Center + ) { + BasicText( + text = stringResource(R.string.vkid_log_in_with_vkid), + style = TextStyle( + color = colorResource(id = R.color.vkid_white), + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center + ) + ) + } + Box( + modifier = Modifier + .weight(1f) + .padding(8.dp), + contentAlignment = Alignment.CenterEnd + ) { + if (inProgress) { + CircleProgress() + } + } + } +} + +@Composable +fun VKIDButtonSmall( + onClick: () -> Unit, + inProgress: Boolean = false, + enabled: Boolean = true, +) { + Row( + horizontalArrangement = Arrangement.spacedBy(0.dp, Alignment.CenterHorizontally), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .width(44.dp) + .height(44.dp) + .background( + color = colorResource(R.color.vkid_azure_A100), + shape = RoundedCornerShape(size = 10.dp) + ) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple( + color = Color.White + ), + enabled = enabled, + role = Role.Button, + onClick = onClick + ) + ) { + Box(modifier = Modifier.padding(8.dp)) { + if (inProgress) { + CircleProgress() + } else { + Image( + painter = painterResource(id = R.drawable.vkid_icon), + contentDescription = null, + colorFilter = ColorFilter.tint(colorResource(id = R.color.vkid_white)), + modifier = Modifier + .size(28.dp) + .padding(1.dp) + ) + } + } + } +} + +@Composable +private fun VKIcon() { + Image( + painter = painterResource(id = R.drawable.vkid_icon), + contentDescription = null, + colorFilter = ColorFilter.tint(colorResource(id = R.color.vkid_white)), + modifier = Modifier + .size(28.dp) + .padding(1.dp) + ) +} + +@Composable +private fun CircleProgress() { + val infiniteTransition = rememberInfiniteTransition(label = "vkid_spinner") + val angle by infiniteTransition.animateFloat( + initialValue = 0f, + targetValue = 360f, + animationSpec = infiniteRepeatable( + animation = tween(durationMillis = 1000, easing = LinearEasing), + repeatMode = RepeatMode.Restart + ), + label = "vkid_spinner" + ) + Image( + modifier = Modifier + .graphicsLayer { + rotationZ = angle + }, + painter = painterResource(id = R.drawable.vkid_spinner), + contentDescription = null, + ) +} + +@Preview +@Composable +private fun PreviewVKIDButtonSmall() { + VKIDButtonSmall(onClick = {}) +} + +@Preview +@Composable +private fun PreviewVKIDButtonSmallProgress() { + VKIDButtonSmall(onClick = {}, inProgress = true) +} + +@Preview +@Composable +private fun PreviewVKIDButton() { + VKIDButton(onClick = {}) +} + +@Preview +@Composable +private fun PreviewVKIDButtonNoIcon() { + VKIDButton(onClick = {}, showIcon = false) +} + +@Preview +@Composable +private fun PreviewVKIDButtonProgress() { + VKIDButton(onClick = {}, inProgress = true) +} diff --git a/sample/src/main/res/drawable/vkid_icon.xml b/sample/src/main/res/drawable/vkid_icon.xml new file mode 100644 index 00000000..c326a7ca --- /dev/null +++ b/sample/src/main/res/drawable/vkid_icon.xml @@ -0,0 +1,37 @@ + + + + diff --git a/sample/src/main/res/drawable/vkid_spinner.xml b/sample/src/main/res/drawable/vkid_spinner.xml new file mode 100644 index 00000000..817d8778 --- /dev/null +++ b/sample/src/main/res/drawable/vkid_spinner.xml @@ -0,0 +1,9 @@ + + + diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..6808f8519adf7e44757a0470fc3a1a5eb42a6f49 GIT binary patch literal 5553 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 literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-hdpi/mp_launcher.png b/sample/src/main/res/mipmap-hdpi/mp_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..463dadcf7806c0f1b9aba53f456617f0a004111d GIT binary patch literal 5185 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 literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..7863c138877790e1dda7e895652f94ebcfd9ca4a GIT binary patch literal 3149 zcmV-T46^fyP)I>q%JI&&k5PMcq&lAD zUP)Fwp2bgH#J7AOhm?hVMV5X3TmO&*1X*|J(4pQgXFsuaro4I!&-I47uGdF6Zcn2C zw32eARB}ZWhD)PJ&MCGxKlAvx+q^kv&YTEbjSH-+SOMFVkMx+UGqCqThE<+cyDtL{7ErdD571u_9;0|xkSLDvLFKeW%W%6nCsco?;U+czNY_)ErrNc1|Wr2Tjdd316D8r zW3B7Z?5|owdS@KBz&i8mqTy-E*P0aRv(mqt z3%aV$us>YfSt&WC(LeOkXE*Y7*;*>CN0r>r*d(m!m}Xz4*Lf@n6B8%PL@2O{Z{Oec z`Lm>L9hi1K`>Blxv*?OIzT1GGpXE!HMpRLc)#Y2 zljV}pY%NXR_Er5xo@FqW5=f(e@MX_!>+9_Axf5X3&Oi}SKw_=(QE}8H5s!TefEkmV z6{)CfjI~P3_{t_oU5m3pwl&K9e&@5F-j=gant@EdTi>k>)1;1-Q34^2A6qRIqDVqn zBsl?gDL|RI5}-0kqfGOq8Do`_obG(Upuu_ zq-2t)oU`2!^s3H+WpRU#3!k2cqD=NP=E1cUF3#U!7(Ca3Ermeh@H?j?f=F5v5!m8S zHQ4qaec+feAbHLcb1-#D(SjzDT`j%Mb3)cXd-{JzG&VN20FaytXX~SGT+f%HR?!Pb zrjbA#Ay;VF(yx0Ce;roNi#VRQyvfIy*^MZbvaE}Y3(8nxt1`frf9cKO({L_rXt!T< zsm~cHN~d<61Fl<-%ZNke=DYXVL~5R>z@iA;gn3OUmH+&r8}0hWDz#(^#GPhO6dZ6;_;6v>(+%bKa~y@|mLYcXUZCpS*2Xh%HwxKyWuzeb7>3hN;I|Fe~hfe-$r(a zEh}4mJp92DKs#ylW1)z{iauq42_Rhq4xFA^A*p8#@M5;t!+TSku%w}YQrUCO0m!P~_CXc<>>IY40rZf4=uxgyN)i9LhT-fr#W+OTBrs}jJ4Ve|xq3(XWe@DNWgGfQo{)l}hXMHO_k*$-c2j&UxyKz^yM$$G0K>{CN)? zzVTovnQT3zwYya^T@UF3hQS!Ln-Wm=B9>9Hc@a-Y_wK7$Qiz!MyHlI+{Kxb0W#yjN zr{kFq=f)8%m34mC3p@R*H|@6wENSU?hPcdwmPG)hT|%;P;fzsic<(^FNdq1nU2Tan~g6NCkx?b@#*X~ zoObVM6ob`C9I@$e4C#@DOiM?nn@Ro`6`C6+K6mLG1~cq6P$(3Nt@R7)pp!3>#*&{z zg41UR!uUv9pO?iwZ!N&7cYlfnD_YToB-wmT>%%ay%`{2EyGU{(l?#1(u3#}lBqyp)8JM#GqN)&&GKeCfi=<{=!H_V?6b zWC)>s`5QrxZ8#RRsitr5(3p!>&h8*mqtOs+KnRJ z6Di(e7%REWS!*KBMix%C9A35p(kVma8ovx$I8eN)qc1jQuI{+rE^}y)I#gyMMb2Ee z-pDGpk>8Hyxu0HYFcMbSZIsK%ANAA~uQo58Stn`d$2(Ns8M5U?#U!}>Db1N8QaXvG zj!Cb2`jFh+iK8uIb%74G&xg2tT9?nMoASa{uTtcd{U(M*A~XyaPkQTIzj;|Je-V!@ zspc>5tN>??0VY&yq4BS!`O~T0isMb1C{^R|i|1h2pd~ z?isas>iegJg(k(_M=2z#Ng04lz$+z5xwI0M{8nY3-tHU#4NVpl3>u@2VMl9JD`wQ4 zGWYF!Mj32hbTX%TElhao(kEBW9&c6}B%5LV(Y7~we6Ve?DB7%6E5kadEGVl%Xrl7s?<6`~%7dp!2MFQT= zQRjB~t^d$XL^70-GNajSwyf{J_V`anw_3;Xas%LGY8|gbU9ScLkYU)UWmvDnuwKew zVcUusZ!D|3@BJVM3IJGrs&xjgzw7^Mz!}MqW{FgWO3on*Dg{M0B(MSbVM)aG_x+ze n97{d2thOjt2K;UO&z1iJR=#APb+UI~00000NkvXXu0mjfhfxpb literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-mdpi/mp_launcher.png b/sample/src/main/res/mipmap-mdpi/mp_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..653c573f73c516583319991e23d4a012b071a8b3 GIT binary patch literal 2963 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 JPDHLkV1n55y{!NM literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..7f3689aa09049aac7b95c98bc0349c803d05318b GIT binary patch literal 8140 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 m{#=TYE(*wc<30mCt^Wh`lLhO!;N30&00007~` literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-xhdpi/mp_launcher.png b/sample/src/main/res/mipmap-xhdpi/mp_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8dbdd03ddeb717dcef7d268b1775778aeb71a034 GIT binary patch literal 7581 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 literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..11d94f8d3fca1d72fe232fa688a85ffd0a349d41 GIT binary patch literal 14782 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 FV1m3%yc+-j literal 0 HcmV?d00001 diff --git a/sample/src/main/res/mipmap-xxxhdpi/mp_launcher.png b/sample/src/main/res/mipmap-xxxhdpi/mp_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7e1152848a61ea60f981f23f10ef834984020692 GIT binary patch literal 20327 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 + + VK ID Sample + Войти через VK ID + \ No newline at end of file diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml new file mode 100644 index 00000000..5e7f9f99 --- /dev/null +++ b/sample/src/main/res/values/colors.xml @@ -0,0 +1,8 @@ + + + #0077FF + #19191A + #8019191A + #FFFFFF + #B3FFFFFF + \ No newline at end of file diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml new file mode 100644 index 00000000..f3d4abc4 --- /dev/null +++ b/sample/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + + VK ID Sample + Log in with VK ID + \ No newline at end of file diff --git a/sample/src/main/res/values/themes.xml b/sample/src/main/res/values/themes.xml new file mode 100644 index 00000000..da981ef9 --- /dev/null +++ b/sample/src/main/res/values/themes.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/vkid/src/test/java/com/vk/id/internal/log/AndroidLogcatLogEngineTest.kt b/vkid/src/test/java/com/vk/id/internal/log/AndroidLogcatLogEngineTest.kt new file mode 100644 index 00000000..d02d85ca --- /dev/null +++ b/vkid/src/test/java/com/vk/id/internal/log/AndroidLogcatLogEngineTest.kt @@ -0,0 +1,33 @@ +package com.vk.id.internal.log + +import android.util.Log +import io.mockk.every +import io.mockk.mockkStatic +import io.mockk.verify +import org.junit.Before +import org.junit.Test + +public class AndroidLogcatLogEngineTest { + @Before + public fun setUp() { + mockkStatic(Log::class) + every { Log.i(any(), any()) } returns 0 + every { Log.d(any(), any()) } returns 0 + every { Log.e(any(), any(), any()) } returns 0 + } + + @Test + public fun `test AndroidLogcatLogEngine logs to Logcat`() { + val androidLogcatLogEngine = AndroidLogcatLogEngine() + + androidLogcatLogEngine.log(LogEngine.LogLevel.INFO, "TestTag", "TestMessage", null) + verify { Log.i("TestTag", "TestMessage") } + + androidLogcatLogEngine.log(LogEngine.LogLevel.DEBUG, "TestTag", "TestMessage", null) + verify { Log.d("TestTag", "TestMessage") } + + val throwable = Throwable("TestError") + androidLogcatLogEngine.log(LogEngine.LogLevel.ERROR, "TestTag", "TestMessage", throwable) + verify { Log.e("TestTag", "TestMessage", throwable) } + } +} diff --git a/vkid/src/test/java/com/vk/id/internal/log/FakeLogEngineTest.kt b/vkid/src/test/java/com/vk/id/internal/log/FakeLogEngineTest.kt new file mode 100644 index 00000000..4bec5896 --- /dev/null +++ b/vkid/src/test/java/com/vk/id/internal/log/FakeLogEngineTest.kt @@ -0,0 +1,37 @@ +package com.vk.id.internal.log + +import android.util.Log +import io.mockk.every +import io.mockk.mockkStatic +import io.mockk.verify +import org.junit.Before +import org.junit.Test + +public class FakeLogEngineTest { + @Before + public fun setUp() { + mockkStatic(Log::class) + every { Log.i(any(), any()) } returns 0 + every { Log.d(any(), any()) } returns 0 + every { Log.e(any(), any(), any()) } returns 0 + } + + @Test + public fun `test FakeLogEngine does not log`() { + val fakeLogEngine = FakeLogEngine() + fakeLogEngine.log( + LogEngine.LogLevel.DEBUG, + "TestTag", + "TestMessage", + Throwable("Throwable") + ) + + verify(exactly = 0) { + Log.d(any(), any()) + } + verify(exactly = 0) { + Log.d(any(), any(), any()) + } + // Since the FakeLogEngine doesn't do any action, this test passes if no exception is thrown. + } +} diff --git a/vkid/src/test/java/com/vk/id/internal/log/VKIDLogTest.kt b/vkid/src/test/java/com/vk/id/internal/log/VKIDLogTest.kt new file mode 100644 index 00000000..458f9731 --- /dev/null +++ b/vkid/src/test/java/com/vk/id/internal/log/VKIDLogTest.kt @@ -0,0 +1,58 @@ +package com.vk.id.internal.log + +import io.mockk.confirmVerified +import io.mockk.mockk +import io.mockk.verify +import org.junit.Before +import org.junit.Test + +public class VKIDLogTest { + private lateinit var mockEngine: LogEngine + + @Before + public fun setUp() { + mockEngine = mockk(relaxed = true) + VKIDLog.setLogEngine(mockEngine) + } + + @Test + public fun `test setting log engine`() { + val anotherMockEngine = mockk(relaxed = true) + VKIDLog.setLogEngine(anotherMockEngine) + + VKIDLog.log(LogEngine.LogLevel.DEBUG, "TestTag", "TestMessage", null) + + verify { anotherMockEngine.log(LogEngine.LogLevel.DEBUG, "TestTag", "TestMessage", null) } + confirmVerified(anotherMockEngine) + + verify(exactly = 0) { + mockEngine.log( + any(), + any(), + any(), + any() + ) + } // Ensure the old engine is not used + } + + @Test + public fun `test creating logger with tag and logging info`() { + val logger = VKIDLog.createLoggerForTag("TestTag") + + logger.info("TestInfoMessage") + logger.debug("TestDebugMessage") + val throwable = Throwable("TestError") + logger.error("TestErrorMessage", throwable) + + verify { mockEngine.log(LogEngine.LogLevel.INFO, "TestTag", "TestInfoMessage", null) } + verify { mockEngine.log(LogEngine.LogLevel.DEBUG, "TestTag", "TestDebugMessage", null) } + verify { + mockEngine.log( + LogEngine.LogLevel.ERROR, + "TestTag", + "TestErrorMessage", + throwable + ) + } + } +}