From e84e8fd6fcba3ff8cd32864fd6a007df1aa1d102 Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Mon, 2 Mar 2020 21:56:10 +0300 Subject: [PATCH] Page-icon-picker widget (#260) --- build.gradle | 2 +- dependencies.gradle | 4 + library-page-icon-picker-widget/.gitignore | 1 + library-page-icon-picker-widget/build.gradle | 57 +++++++ .../consumer-rules.pro | 0 .../proguard-rules.pro | 21 +++ .../src/main/AndroidManifest.xml | 1 + .../model/PageIconPickerView.kt | 53 ++++++ .../model/PageIconPickerViewDiffUtil.kt | 20 +++ .../ui/PageIconPickerAdapter.kt | 95 +++++++++++ .../ui/PageIconPickerViewHolder.kt | 48 ++++++ .../ic_page_icon_picker_choose_emoji.xml | 20 +++ .../ic_page_icon_picker_random_emoji.xml | 26 +++ .../drawable/ic_page_icon_picker_search.xml | 17 ++ .../ic_page_icon_picker_upload_photo.xml | 16 ++ .../page_icon_picker_dragger_background.xml | 5 + .../page_icon_picker_filter_background.xml | 5 + .../item_page_icon_picker_choose_emoji.xml | 25 +++ ...page_icon_picker_emoji_category_header.xml | 14 ++ .../item_page_icon_picker_emoji_filter.xml | 34 ++++ .../item_page_icon_picker_emoji_item.xml | 16 ++ ...m_page_icon_picker_pick_emoji_randomly.xml | 25 +++ .../item_page_icon_picker_upload_photo.xml | 25 +++ .../layout_page_icon_picker_bottom_sheet.xml | 62 +++++++ .../src/main/res/values/colors.xml | 5 + .../src/main/res/values/strings.xml | 11 ++ .../src/main/res/values/styles.xml | 12 ++ .../PageIconPickerViewDiffUtilTest.kt | 159 ++++++++++++++++++ sample/build.gradle | 3 + sample/src/main/AndroidManifest.xml | 9 +- .../sample/PageIconPickerSampleActivity.kt | 65 +++++++ .../page_icon_picker_dragger_background.xml | 5 + .../sample_page_icon_picker_activity.xml | 62 +++++++ settings.gradle | 3 +- 34 files changed, 921 insertions(+), 5 deletions(-) create mode 100644 library-page-icon-picker-widget/.gitignore create mode 100644 library-page-icon-picker-widget/build.gradle create mode 100644 library-page-icon-picker-widget/consumer-rules.pro create mode 100644 library-page-icon-picker-widget/proguard-rules.pro create mode 100644 library-page-icon-picker-widget/src/main/AndroidManifest.xml create mode 100644 library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerView.kt create mode 100644 library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerViewDiffUtil.kt create mode 100644 library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerAdapter.kt create mode 100644 library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerViewHolder.kt create mode 100644 library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_choose_emoji.xml create mode 100644 library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_random_emoji.xml create mode 100644 library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_search.xml create mode 100644 library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_upload_photo.xml create mode 100644 library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_dragger_background.xml create mode 100644 library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_filter_background.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_choose_emoji.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_category_header.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_filter.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_item.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_pick_emoji_randomly.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_upload_photo.xml create mode 100644 library-page-icon-picker-widget/src/main/res/layout/layout_page_icon_picker_bottom_sheet.xml create mode 100644 library-page-icon-picker-widget/src/main/res/values/colors.xml create mode 100644 library-page-icon-picker-widget/src/main/res/values/strings.xml create mode 100644 library-page-icon-picker-widget/src/main/res/values/styles.xml create mode 100644 library-page-icon-picker-widget/src/test/java/com/agileburo/anytype/library_page_icon_picker_widget/PageIconPickerViewDiffUtilTest.kt create mode 100644 sample/src/main/java/com/agileburo/anytype/sample/PageIconPickerSampleActivity.kt create mode 100644 sample/src/main/res/drawable/page_icon_picker_dragger_background.xml create mode 100644 sample/src/main/res/layout/sample_page_icon_picker_activity.xml diff --git a/build.gradle b/build.gradle index dd1695d445..bae5176bf3 100644 --- a/build.gradle +++ b/build.gradle @@ -53,4 +53,4 @@ task clean(type: Delete) { task runUnitTests(dependsOn: [':app:testDebugUnitTest']) { description 'Run all unit tests' -} \ No newline at end of file +} diff --git a/dependencies.gradle b/dependencies.gradle index c9863fda28..d90c0c0e11 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -159,4 +159,8 @@ ext { annotations: "androidx.room:room-compiler:$room_version", roomTesting: "androidx.room:room-testing:$room_version" ] + + libraryPageIconPicker = [ + emojiJava: "com.vdurmont:emoji-java:5.1.1" + ] } \ No newline at end of file diff --git a/library-page-icon-picker-widget/.gitignore b/library-page-icon-picker-widget/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/library-page-icon-picker-widget/.gitignore @@ -0,0 +1 @@ +/build diff --git a/library-page-icon-picker-widget/build.gradle b/library-page-icon-picker-widget/build.gradle new file mode 100644 index 0000000000..a823ef1084 --- /dev/null +++ b/library-page-icon-picker-widget/build.gradle @@ -0,0 +1,57 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + def config = rootProject.extensions.getByName("ext") + + compileSdkVersion compile_sdk + + defaultConfig { + minSdkVersion config["min_sdk"] + targetSdkVersion config["target_sdk"] + versionCode config["version_code"] + versionName config["version_name"] + + testInstrumentationRunner config["test_runner"] + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + testOptions { + unitTests { + includeAndroidResources = true + } + } +} + +dependencies { + def applicationDependencies = rootProject.ext.mainApplication + def unitTestDependencies = rootProject.ext.unitTesting + def lib = rootProject.ext.libraryPageIconPicker + + implementation lib.emojiJava + + implementation project(':core-utils') + implementation project(':core-ui') + + implementation applicationDependencies.appcompat + implementation applicationDependencies.kotlin + implementation applicationDependencies.coroutines + implementation applicationDependencies.androidxCore + + implementation applicationDependencies.design + implementation applicationDependencies.recyclerView + implementation applicationDependencies.constraintLayout + implementation applicationDependencies.timber + + testImplementation unitTestDependencies.junit + testImplementation unitTestDependencies.kotlinTest + testImplementation unitTestDependencies.robolectric + testImplementation unitTestDependencies.androidXTestCore +} \ No newline at end of file diff --git a/library-page-icon-picker-widget/consumer-rules.pro b/library-page-icon-picker-widget/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/library-page-icon-picker-widget/proguard-rules.pro b/library-page-icon-picker-widget/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/library-page-icon-picker-widget/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. +# +# 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 diff --git a/library-page-icon-picker-widget/src/main/AndroidManifest.xml b/library-page-icon-picker-widget/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..27a87dae25 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerView.kt b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerView.kt new file mode 100644 index 0000000000..c19f967b59 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerView.kt @@ -0,0 +1,53 @@ +package com.agileburo.anytype.library_page_icon_picker_widget.model + +import com.agileburo.anytype.core_ui.common.ViewType +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_CHOOSE_EMOJI +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_CATEGORY_HEADER +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_FILTER +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_ITEM +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_PICK_RANDOM_EMOJI +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_UPLOAD_PHOTO + +sealed class PageIconPickerView : ViewType { + + /** + * @property alias short name or convenient name for an emoji. + */ + data class Emoji( + val alias: String = "", + val unicode: String + ) : PageIconPickerView() { + override fun getViewType() = HOLDER_EMOJI_ITEM + } + + /** + * @property category emoji category + */ + data class GroupHeader( + val category: String + ) : PageIconPickerView() { + override fun getViewType() = HOLDER_EMOJI_CATEGORY_HEADER + } + + /** + * Emoji filter. + */ + object EmojiFilter : PageIconPickerView() { + override fun getViewType() = HOLDER_EMOJI_FILTER + } + + /** + * User actions related to emoji picker feature. + */ + sealed class Action : PageIconPickerView() { + object UploadPhoto : Action() { + override fun getViewType() = HOLDER_UPLOAD_PHOTO + } + object PickRandomly : Action() { + override fun getViewType() = HOLDER_PICK_RANDOM_EMOJI + } + object ChooseEmoji : Action() { + override fun getViewType() = HOLDER_CHOOSE_EMOJI + } + } +} \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerViewDiffUtil.kt b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerViewDiffUtil.kt new file mode 100644 index 0000000000..084cd6b98c --- /dev/null +++ b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/model/PageIconPickerViewDiffUtil.kt @@ -0,0 +1,20 @@ +package com.agileburo.anytype.library_page_icon_picker_widget.model + +import androidx.recyclerview.widget.DiffUtil + +class PageIconPickerViewDiffUtil( + private val old: List, + private val new: List +) : DiffUtil.Callback() { + + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return old[oldItemPosition] == new[newItemPosition] + } + + override fun getOldListSize() = old.size + override fun getNewListSize() = new.size + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { + return old[oldItemPosition] == new[newItemPosition] + } +} \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerAdapter.kt b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerAdapter.kt new file mode 100644 index 0000000000..9316fec90a --- /dev/null +++ b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerAdapter.kt @@ -0,0 +1,95 @@ +package com.agileburo.anytype.library_page_icon_picker_widget.ui + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.widget.doOnTextChanged +import androidx.recyclerview.widget.RecyclerView +import com.agileburo.anytype.R +import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_CHOOSE_EMOJI +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_CATEGORY_HEADER +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_FILTER +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_ITEM +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_PICK_RANDOM_EMOJI +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_UPLOAD_PHOTO +import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_filter.view.* + +class PageIconPickerAdapter( + private var views: List, + private val onUploadPhotoClicked: () -> Unit, + private val onSetRandomEmojiClicked: () -> Unit, + private val onFilterQueryChanged: (String) -> Unit +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageIconPickerViewHolder { + val inflater = LayoutInflater.from(parent.context) + + return when (viewType) { + HOLDER_UPLOAD_PHOTO -> PageIconPickerViewHolder.UploadPhoto( + view = inflater.inflate( + R.layout.item_page_icon_picker_upload_photo, + parent, + false + ) + ).apply { + itemView.setOnClickListener { onUploadPhotoClicked() } + } + HOLDER_PICK_RANDOM_EMOJI -> PageIconPickerViewHolder.PickRandom( + view = inflater.inflate( + R.layout.item_page_icon_picker_pick_emoji_randomly, + parent, + false + ) + ).apply { + itemView.setOnClickListener { onSetRandomEmojiClicked() } + } + HOLDER_CHOOSE_EMOJI -> PageIconPickerViewHolder.ChooseEmoji( + view = inflater.inflate( + R.layout.item_page_icon_picker_choose_emoji, + parent, + false + ) + ) + HOLDER_EMOJI_CATEGORY_HEADER -> PageIconPickerViewHolder.CategoryHeader( + view = inflater.inflate( + R.layout.item_page_icon_picker_emoji_category_header, + parent, + false + ) + ) + HOLDER_EMOJI_ITEM -> PageIconPickerViewHolder.EmojiItem( + view = LayoutInflater.from(parent.context).inflate( + R.layout.item_page_icon_picker_emoji_item, + parent, + false + ) + ) + HOLDER_EMOJI_FILTER -> PageIconPickerViewHolder.EmojiFilter( + view = LayoutInflater.from(parent.context).inflate( + R.layout.item_page_icon_picker_emoji_filter, + parent, + false + ) + ).apply { + itemView.filterInputField.doOnTextChanged { text, _, _, _ -> + onFilterQueryChanged(text.toString()) + } + } + else -> throw IllegalStateException("Unexpected view type: $viewType") + } + } + + override fun getItemCount(): Int = views.size + override fun getItemViewType(position: Int) = views[position].getViewType() + + override fun onBindViewHolder(holder: PageIconPickerViewHolder, position: Int) { + when (holder) { + is PageIconPickerViewHolder.CategoryHeader -> { + holder.bind(views[position] as PageIconPickerView.GroupHeader) + } + is PageIconPickerViewHolder.EmojiItem -> { + holder.bind(views[position] as PageIconPickerView.Emoji) + } + } + } +} \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerViewHolder.kt b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerViewHolder.kt new file mode 100644 index 0000000000..bf39895f31 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/java/com/agileburo/anytype/library_page_icon_picker_widget/ui/PageIconPickerViewHolder.kt @@ -0,0 +1,48 @@ +package com.agileburo.anytype.library_page_icon_picker_widget.ui + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView +import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_category_header.view.* +import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_item.view.* + +sealed class PageIconPickerViewHolder(view: View) : RecyclerView.ViewHolder(view) { + + class UploadPhoto(view: View) : PageIconPickerViewHolder(view) + + class PickRandom(view: View) : PageIconPickerViewHolder(view) + + class ChooseEmoji(view: View) : PageIconPickerViewHolder(view) + + class CategoryHeader(view: View) : PageIconPickerViewHolder(view) { + + private val category = itemView.category + + fun bind(item: PageIconPickerView.GroupHeader) { + category.text = item.category + } + + } + + class EmojiItem(view: View) : PageIconPickerViewHolder(view) { + + private val emoji = itemView.emoji + + fun bind( + item: PageIconPickerView.Emoji + ) { + emoji.text = item.unicode + } + } + + class EmojiFilter(view: View) : PageIconPickerViewHolder(view) + + companion object { + const val HOLDER_UPLOAD_PHOTO = 0 + const val HOLDER_PICK_RANDOM_EMOJI = 1 + const val HOLDER_CHOOSE_EMOJI = 2 + const val HOLDER_EMOJI_CATEGORY_HEADER = 3 + const val HOLDER_EMOJI_ITEM = 4 + const val HOLDER_EMOJI_FILTER = 5 + } +} \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_choose_emoji.xml b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_choose_emoji.xml new file mode 100644 index 0000000000..20447adf9c --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_choose_emoji.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_random_emoji.xml b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_random_emoji.xml new file mode 100644 index 0000000000..90daa50c8e --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_random_emoji.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_search.xml b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_search.xml new file mode 100644 index 0000000000..17d5481ea7 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_search.xml @@ -0,0 +1,17 @@ + + + + diff --git a/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_upload_photo.xml b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_upload_photo.xml new file mode 100644 index 0000000000..86615ab89e --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/drawable/ic_page_icon_picker_upload_photo.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_dragger_background.xml b/library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_dragger_background.xml new file mode 100644 index 0000000000..6595b134b3 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_dragger_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_filter_background.xml b/library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_filter_background.xml new file mode 100644 index 0000000000..ebd8ef2fb7 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/drawable/page_icon_picker_filter_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_choose_emoji.xml b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_choose_emoji.xml new file mode 100644 index 0000000000..97048f13d3 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_choose_emoji.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_category_header.xml b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_category_header.xml new file mode 100644 index 0000000000..3261a21118 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_category_header.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_filter.xml b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_filter.xml new file mode 100644 index 0000000000..8ab0e6e3af --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_filter.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_item.xml b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_item.xml new file mode 100644 index 0000000000..b0d545305c --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_emoji_item.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_pick_emoji_randomly.xml b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_pick_emoji_randomly.xml new file mode 100644 index 0000000000..d4e11461a3 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_pick_emoji_randomly.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_upload_photo.xml b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_upload_photo.xml new file mode 100644 index 0000000000..b54f09e52d --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/item_page_icon_picker_upload_photo.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/layout/layout_page_icon_picker_bottom_sheet.xml b/library-page-icon-picker-widget/src/main/res/layout/layout_page_icon_picker_bottom_sheet.xml new file mode 100644 index 0000000000..d302cb48f1 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/layout/layout_page_icon_picker_bottom_sheet.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/values/colors.xml b/library-page-icon-picker-widget/src/main/res/values/colors.xml new file mode 100644 index 0000000000..08f3bd8cae --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #DFDDD0 + #ACA996 + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/main/res/values/strings.xml b/library-page-icon-picker-widget/src/main/res/values/strings.xml new file mode 100644 index 0000000000..224335c9a3 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/values/strings.xml @@ -0,0 +1,11 @@ + + Page Icon Widget + Upload photo + Upload photo image + Pick emoji randomly + Choose emoji + Filter + Loop icon + Page icon + Remove + diff --git a/library-page-icon-picker-widget/src/main/res/values/styles.xml b/library-page-icon-picker-widget/src/main/res/values/styles.xml new file mode 100644 index 0000000000..7e64f6cff0 --- /dev/null +++ b/library-page-icon-picker-widget/src/main/res/values/styles.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/library-page-icon-picker-widget/src/test/java/com/agileburo/anytype/library_page_icon_picker_widget/PageIconPickerViewDiffUtilTest.kt b/library-page-icon-picker-widget/src/test/java/com/agileburo/anytype/library_page_icon_picker_widget/PageIconPickerViewDiffUtilTest.kt new file mode 100644 index 0000000000..2421ed9e33 --- /dev/null +++ b/library-page-icon-picker-widget/src/test/java/com/agileburo/anytype/library_page_icon_picker_widget/PageIconPickerViewDiffUtilTest.kt @@ -0,0 +1,159 @@ +package com.agileburo.anytype.library_page_icon_picker_widget + +import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView +import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerViewDiffUtil +import org.junit.Test +import kotlin.test.assertEquals + +class PageIconPickerViewDiffUtilTest { + + @Test + fun `two emoji-filter items should be considered the same`() { + val old = listOf( + PageIconPickerView.EmojiFilter + ) + + val new = listOf( + PageIconPickerView.EmojiFilter + ) + + val util = PageIconPickerViewDiffUtil( + old = old, + new = new + ) + + val result = util.areItemsTheSame(0, 0) + + assertEquals( + expected = true, + actual = result + ) + } + + @Test + fun `two upload-photo-action items should be considered the same`() { + val old = listOf( + PageIconPickerView.Action.UploadPhoto + ) + + val new = listOf( + PageIconPickerView.Action.UploadPhoto + ) + + val util = PageIconPickerViewDiffUtil( + old = old, + new = new + ) + + val result = util.areItemsTheSame(0, 0) + + assertEquals( + expected = true, + actual = result + ) + } + + @Test + fun `two choose-emoji-action items should be considered the same`() { + val old = listOf( + PageIconPickerView.Action.ChooseEmoji + ) + + val new = listOf( + PageIconPickerView.Action.ChooseEmoji + ) + + val util = PageIconPickerViewDiffUtil( + old = old, + new = new + ) + + val result = util.areItemsTheSame(0, 0) + + assertEquals( + expected = true, + actual = result + ) + } + + @Test + fun `two pick-random-emoji-action items should be considered the same`() { + val old = listOf( + PageIconPickerView.Action.PickRandomly + ) + + val new = listOf( + PageIconPickerView.Action.PickRandomly + ) + + val util = PageIconPickerViewDiffUtil( + old = old, + new = new + ) + + val result = util.areItemsTheSame(0, 0) + + assertEquals( + expected = true, + actual = result + ) + } + + @Test + fun `two emoji items should be considered the same`() { + val old = listOf( + PageIconPickerView.Emoji( + alias = "grining", + unicode = "U+13131" + ) + ) + + val new = listOf( + PageIconPickerView.Emoji( + alias = "grining", + unicode = "U+13131" + ) + ) + + val util = PageIconPickerViewDiffUtil( + old = old, + new = new + ) + + val result = util.areItemsTheSame(0, 0) + + assertEquals( + expected = true, + actual = result + ) + } + + @Test + fun `two emoji items should be considered different`() { + val old = listOf( + PageIconPickerView.Emoji( + alias = "smile", + unicode = "U+13131" + ) + ) + + val new = listOf( + PageIconPickerView.Emoji( + alias = "grining", + unicode = "U+13131" + ) + ) + + val util = PageIconPickerViewDiffUtil( + old = old, + new = new + ) + + val result = util.areItemsTheSame(0, 0) + + assertEquals( + expected = false, + actual = result + ) + } +} \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index ef266cb74e..485d287d76 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -32,8 +32,11 @@ android { dependencies { + implementation 'com.vdurmont:emoji-java:5.1.1' + implementation project(':core-utils') implementation project(':core-ui') + implementation project(':library-page-icon-picker-widget') implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index a9ce5f8191..4acf8f344e 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -1,18 +1,21 @@ - + android:theme="@style/AppTheme" + tools:ignore="GoogleAppIndexingWarning"> + + - diff --git a/sample/src/main/java/com/agileburo/anytype/sample/PageIconPickerSampleActivity.kt b/sample/src/main/java/com/agileburo/anytype/sample/PageIconPickerSampleActivity.kt new file mode 100644 index 0000000000..5f44e2402c --- /dev/null +++ b/sample/src/main/java/com/agileburo/anytype/sample/PageIconPickerSampleActivity.kt @@ -0,0 +1,65 @@ +package com.agileburo.anytype.sample + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.GridLayoutManager +import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerAdapter +import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder +import com.vdurmont.emoji.EmojiManager +import kotlinx.android.synthetic.main.sample_page_icon_picker_activity.* + +class PageIconPickerSampleActivity : AppCompatActivity(R.layout.sample_page_icon_picker_activity) { + + private val emojis by lazy { + EmojiManager + .getAll() + .map { emoji -> + PageIconPickerView.Emoji( + unicode = emoji.unicode + ) + } + + } + + private val pageIconPickerAdapter = PageIconPickerAdapter( + views = listOf( + PageIconPickerView.Action.UploadPhoto, + PageIconPickerView.Action.PickRandomly, + PageIconPickerView.Action.ChooseEmoji, + PageIconPickerView.EmojiFilter + ) + emojis, + onUploadPhotoClicked = {}, + onSetRandomEmojiClicked = {}, + onFilterQueryChanged = {} + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + recyler.apply { + setItemViewCacheSize(100) + setHasFixedSize(true) + layoutManager = GridLayoutManager(context, PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT).apply { + spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int) = + when (val type = pageIconPickerAdapter.getItemViewType(position)) { + PageIconPickerViewHolder.HOLDER_UPLOAD_PHOTO -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT + PageIconPickerViewHolder.HOLDER_CHOOSE_EMOJI -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT + PageIconPickerViewHolder.HOLDER_PICK_RANDOM_EMOJI -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT + PageIconPickerViewHolder.HOLDER_EMOJI_CATEGORY_HEADER -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT + PageIconPickerViewHolder.HOLDER_EMOJI_FILTER -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT + PageIconPickerViewHolder.HOLDER_EMOJI_ITEM -> 1 + else -> throw IllegalStateException("Unexpected view type: $type") + } + } + } + adapter = pageIconPickerAdapter.apply { + setHasStableIds(true) + } + } + } + + companion object { + const val PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT = 8 + } +} \ No newline at end of file diff --git a/sample/src/main/res/drawable/page_icon_picker_dragger_background.xml b/sample/src/main/res/drawable/page_icon_picker_dragger_background.xml new file mode 100644 index 0000000000..6595b134b3 --- /dev/null +++ b/sample/src/main/res/drawable/page_icon_picker_dragger_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/sample_page_icon_picker_activity.xml b/sample/src/main/res/layout/sample_page_icon_picker_activity.xml new file mode 100644 index 0000000000..05898b8cef --- /dev/null +++ b/sample/src/main/res/layout/sample_page_icon_picker_activity.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 2308e75a99..2dd92434f6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,4 +8,5 @@ include ':app', ':data', ':presentation', ':core-ui', - ':library-kanban-widget' + ':library-kanban-widget', + ':library-page-icon-picker-widget'