mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Page-icon-picker widget (#260)
This commit is contained in:
parent
5fb40987f2
commit
e84e8fd6fc
34 changed files with 921 additions and 5 deletions
|
@ -53,4 +53,4 @@ task clean(type: Delete) {
|
|||
|
||||
task runUnitTests(dependsOn: [':app:testDebugUnitTest']) {
|
||||
description 'Run all unit tests'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
1
library-page-icon-picker-widget/.gitignore
vendored
Normal file
1
library-page-icon-picker-widget/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
57
library-page-icon-picker-widget/build.gradle
Normal file
57
library-page-icon-picker-widget/build.gradle
Normal file
|
@ -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
|
||||
}
|
0
library-page-icon-picker-widget/consumer-rules.pro
Normal file
0
library-page-icon-picker-widget/consumer-rules.pro
Normal file
21
library-page-icon-picker-widget/proguard-rules.pro
vendored
Normal file
21
library-page-icon-picker-widget/proguard-rules.pro
vendored
Normal file
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
<manifest package="com.agileburo.anytype" />
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<PageIconPickerView>,
|
||||
private val new: List<PageIconPickerView>
|
||||
) : 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]
|
||||
}
|
||||
}
|
|
@ -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<PageIconPickerView>,
|
||||
private val onUploadPhotoClicked: () -> Unit,
|
||||
private val onSetRandomEmojiClicked: () -> Unit,
|
||||
private val onFilterQueryChanged: (String) -> Unit
|
||||
) : RecyclerView.Adapter<PageIconPickerViewHolder>() {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M11.999,21C16.9696,21 20.999,16.9706 20.999,12C20.999,7.0294 16.9696,3 11.999,3C7.0285,3 2.999,7.0294 2.999,12C2.999,16.9706 7.0285,21 11.999,21ZM11.999,23C18.0742,23 22.999,18.0751 22.999,12C22.999,5.9249 18.0742,1 11.999,1C5.9239,1 0.999,5.9249 0.999,12C0.999,18.0751 5.9239,23 11.999,23Z" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M16.999,9.5C16.999,10.3284 16.3275,11 15.499,11C14.6706,11 13.999,10.3284 13.999,9.5C13.999,8.6716 14.6706,8 15.499,8C16.3275,8 16.999,8.6716 16.999,9.5Z" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M9.999,9.5C9.999,10.3284 9.3274,11 8.499,11C7.6706,11 6.999,10.3284 6.999,9.5C6.999,8.6716 7.6706,8 8.499,8C9.3274,8 9.999,8.6716 9.999,9.5Z" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M5.2889,14C6.1495,16.8915 8.828,19 11.9991,19C15.1701,19 17.8486,16.8915 18.7092,14H5.2889Z" />
|
||||
</vector>
|
|
@ -0,0 +1,26 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M4.998,3L18.9981,3A2,2 0,0 1,20.9981 5L20.9981,19A2,2 0,0 1,18.9981 21L4.998,21A2,2 0,0 1,2.998 19L2.998,5A2,2 0,0 1,4.998 3z"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#2C2B27" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M7.9981,8m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M15.998,8m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M7.9981,16m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M15.998,16m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M11.998,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
|
||||
</vector>
|
|
@ -0,0 +1,17 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M10.998,11m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#ACA996" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M18.998,19L15.998,16"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="#ACA996"
|
||||
android:strokeLineCap="round" />
|
||||
</vector>
|
|
@ -0,0 +1,16 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M10.999,3C10.999,2.4477 11.4467,2 11.999,2C12.5513,2 12.999,2.4477 12.999,3V17C12.999,17.5523 12.5513,18 11.999,18C11.4467,18 10.999,17.5523 10.999,17V3Z" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:pathData="M4.999,22C4.4467,22 3.999,21.5523 3.999,21C3.999,20.4477 4.4467,20 4.999,20H18.999C19.5513,20 19.999,20.4477 19.999,21C19.999,21.5523 19.5513,22 18.999,22H4.999Z" />
|
||||
<path
|
||||
android:fillColor="#2C2B27"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M11.999,1.5858L19.7061,9.2929C20.0967,9.6834 20.0967,10.3166 19.7061,10.7071C19.3156,11.0977 18.6824,11.0977 18.2919,10.7071L11.999,4.4142L5.7061,10.7071C5.3156,11.0977 4.6824,11.0977 4.2919,10.7071C3.9014,10.3166 3.9014,9.6834 4.2919,9.2929L11.999,1.5858Z" />
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#DFDDD0" />
|
||||
<corners android:radius="6dp" />
|
||||
</shape>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#F3F2EC" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="@color/divider_color" />
|
||||
|
||||
<TextView
|
||||
style="@style/PageIconPickerActionTitleStyle"
|
||||
android:text="@string/page_icon_picker_choose_emoji" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_upload_photo"
|
||||
android:src="@drawable/ic_page_icon_picker_choose_emoji" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/graphik_medium"
|
||||
android:textColor="@color/emoji_category_text_color"
|
||||
android:textSize="13sp" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="@drawable/page_icon_picker_filter_background"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@drawable/ic_page_icon_picker_search"
|
||||
android:contentDescription="@string/content_description_loop_icon" />
|
||||
|
||||
<EditText
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:id="@+id/filterInputField"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="9dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:layout_marginEnd="9dp"
|
||||
android:layout_marginBottom="7dp"
|
||||
android:background="@null"
|
||||
android:fontFamily="@font/graphik_regular"
|
||||
android:hint="@string/page_icon_picker_emoji_filter"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:textSize="15sp" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/emoji"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/emoji_color"
|
||||
android:textSize="22sp"
|
||||
tools:text="🎢" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="@color/divider_color" />
|
||||
|
||||
<TextView
|
||||
style="@style/PageIconPickerActionTitleStyle"
|
||||
android:text="@string/page_icon_picker_pick_emoji_randomly" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_upload_photo"
|
||||
android:src="@drawable/ic_page_icon_picker_random_emoji" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="@color/divider_color" />
|
||||
|
||||
<TextView
|
||||
style="@style/PageIconPickerActionTitleStyle"
|
||||
android:text="@string/page_icon_picker_upload_photo" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:contentDescription="@string/content_description_upload_photo"
|
||||
android:src="@drawable/ic_page_icon_picker_upload_photo" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#EEAFAF">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/rectangle_debug_background"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/bottom_sheet_behavior">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/dragger"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/page_icon_picker_dragger_background" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="30dp"
|
||||
android:fontFamily="@font/graphik_semibold"
|
||||
android:text="@string/page_icon"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="30dp"
|
||||
android:text="@string/page_icon_picker_remove_text"
|
||||
android:textColor="#ACA996"
|
||||
android:textSize="17sp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyler"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="100dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="divider_color">#DFDDD0</color>
|
||||
<color name="emoji_category_text_color">#ACA996</color>
|
||||
</resources>
|
|
@ -0,0 +1,11 @@
|
|||
<resources>
|
||||
<string name="app_name">Page Icon Widget</string>
|
||||
<string name="page_icon_picker_upload_photo">Upload photo</string>
|
||||
<string name="content_description_upload_photo">Upload photo image</string>
|
||||
<string name="page_icon_picker_pick_emoji_randomly">Pick emoji randomly</string>
|
||||
<string name="page_icon_picker_choose_emoji">Choose emoji</string>
|
||||
<string name="page_icon_picker_emoji_filter">Filter</string>
|
||||
<string name="content_description_loop_icon">Loop icon</string>
|
||||
<string name="page_icon">Page icon</string>
|
||||
<string name="page_icon_picker_remove_text">Remove</string>
|
||||
</resources>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="PageIconPickerActionTitleStyle">
|
||||
<item name="android:layout_gravity">center_vertical</item>
|
||||
<item name="android:textColor">@color/black</item>
|
||||
<item name="android:textSize">15sp</item>
|
||||
<item name="android:fontFamily">@font/graphik_medium</item>
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.agileburo.anytype.sample">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name=".MainActivity" />
|
||||
<activity android:name=".PageIconPickerSampleActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#DFDDD0" />
|
||||
<corners android:radius="6dp" />
|
||||
</shape>
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#EEAFAF">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/sheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/rectangle_debug_background"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/bottom_sheet_behavior">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/dragger"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/page_icon_picker_dragger_background" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="30dp"
|
||||
android:fontFamily="@font/graphik_semibold"
|
||||
android:text="Page icon"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="30dp"
|
||||
android:text="Remove"
|
||||
android:textColor="#ACA996"
|
||||
android:textSize="17sp" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyler"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="100dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -8,4 +8,5 @@ include ':app',
|
|||
':data',
|
||||
':presentation',
|
||||
':core-ui',
|
||||
':library-kanban-widget'
|
||||
':library-kanban-widget',
|
||||
':library-page-icon-picker-widget'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue