Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
AloqaIM-Android
Commits
c173a519
Commit
c173a519
authored
Jul 13, 2018
by
Filipe de Lima Brito
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat.Android into new/search-messages
parents
78795815
c32b8dc6
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
632 additions
and
126 deletions
+632
-126
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+30
-9
ChatRoomsFragment.kt
...ava/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
+10
-10
Text.kt
...src/main/java/chat/rocket/android/util/extensions/Text.kt
+0
-23
fragment_chat_room.xml
app/src/main/res/layout/fragment_chat_room.xml
+5
-4
fragment_chat_rooms.xml
app/src/main/res/layout/fragment_chat_rooms.xml
+3
-2
strings.xml
app/src/main/res/values-es/strings.xml
+1
-0
strings.xml
app/src/main/res/values-fr/strings.xml
+1
-0
strings.xml
app/src/main/res/values-hi-rIN/strings.xml
+1
-0
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+1
-0
strings.xml
app/src/main/res/values-uk-rRU/strings.xml
+1
-0
strings.xml
app/src/main/res/values/strings.xml
+1
-0
build.gradle
emoji/build.gradle
+2
-0
ComposerEditText.kt
...c/main/java/chat/rocket/android/emoji/ComposerEditText.kt
+1
-1
Emoji.kt
emoji/src/main/java/chat/rocket/android/emoji/Emoji.kt
+3
-1
EmojiKeyboardPopup.kt
...main/java/chat/rocket/android/emoji/EmojiKeyboardPopup.kt
+110
-11
EmojiParser.kt
emoji/src/main/java/chat/rocket/android/emoji/EmojiParser.kt
+4
-2
EmojiPickerPopup.kt
...c/main/java/chat/rocket/android/emoji/EmojiPickerPopup.kt
+24
-4
EmojiRepository.kt
...rc/main/java/chat/rocket/android/emoji/EmojiRepository.kt
+51
-13
EmojiTypefaceSpan.kt
.../main/java/chat/rocket/android/emoji/EmojiTypefaceSpan.kt
+0
-17
Fitzpatrick.kt
emoji/src/main/java/chat/rocket/android/emoji/Fitzpatrick.kt
+30
-0
EmojiCategory.kt
.../java/chat/rocket/android/emoji/internal/EmojiCategory.kt
+5
-2
EmojiPagerAdapter.kt
...a/chat/rocket/android/emoji/internal/EmojiPagerAdapter.kt
+158
-0
Preferences.kt
...in/java/chat/rocket/android/emoji/internal/Preferences.kt
+4
-0
color_change_circle.xml
emoji/src/main/res/drawable/color_change_circle.xml
+8
-0
emoji_picker.xml
emoji/src/main/res/layout-land/emoji_picker.xml
+26
-0
color_select_popup.xml
emoji/src/main/res/layout/color_select_popup.xml
+107
-0
emoji_keyboard.xml
emoji/src/main/res/layout/emoji_keyboard.xml
+21
-10
emoji_row_item.xml
emoji/src/main/res/layout/emoji_row_item.xml
+8
-17
colors.xml
emoji/src/main/res/values/colors.xml
+8
-0
strings.xml
emoji/src/main/res/values/strings.xml
+1
-0
styles.xml
emoji/src/main/res/values/styles.xml
+7
-0
No files found.
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
c173a519
...
...
@@ -24,6 +24,7 @@ import androidx.annotation.DrawableRes
import
androidx.core.text.bold
import
androidx.core.view.isVisible
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.FragmentManager
import
androidx.recyclerview.widget.DefaultItemAnimator
import
androidx.recyclerview.widget.LinearLayoutManager
import
androidx.recyclerview.widget.RecyclerView
...
...
@@ -35,6 +36,7 @@ import chat.rocket.android.chatroom.adapter.PeopleSuggestionsAdapter
import
chat.rocket.android.chatroom.adapter.RoomSuggestionsAdapter
import
chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import
chat.rocket.android.chatroom.presentation.ChatRoomView
import
chat.rocket.android.chatroom.ui.bottomsheet.MessageActionsBottomSheet
import
chat.rocket.android.chatroom.uimodel.BaseUiModel
import
chat.rocket.android.chatroom.uimodel.MessageUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
...
...
@@ -244,6 +246,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
super
.
onDestroyView
()
}
override
fun
onPause
()
{
super
.
onPause
()
setReactionButtonIcon
(
R
.
drawable
.
ic_reaction_24dp
)
emojiKeyboardPopup
.
dismiss
()
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
resultData
:
Intent
?)
{
if
(
resultData
!=
null
&&
resultCode
==
Activity
.
RESULT_OK
)
{
when
(
requestCode
)
{
...
...
@@ -654,22 +662,22 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override
fun
showConnectionState
(
state
:
State
)
{
ui
{
connection_status_text
.
fadeIn
()
text_connection_status
.
fadeIn
()
handler
.
removeCallbacks
(
dismissStatus
)
when
(
state
)
{
is
State
.
Connected
->
{
connection_status_text
.
text
=
getString
(
R
.
string
.
status_connected
)
text_connection_status
.
text
=
getString
(
R
.
string
.
status_connected
)
handler
.
postDelayed
(
dismissStatus
,
2000
)
}
is
State
.
Disconnected
->
connection_status_text
.
text
=
is
State
.
Disconnected
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_disconnected
)
is
State
.
Connecting
->
connection_status_text
.
text
=
is
State
.
Connecting
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_connecting
)
is
State
.
Authenticating
->
connection_status_text
.
text
=
is
State
.
Authenticating
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_authenticating
)
is
State
.
Disconnecting
->
connection_status_text
.
text
=
is
State
.
Disconnecting
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_disconnecting
)
is
State
.
Waiting
->
connection_status_text
.
text
=
is
State
.
Waiting
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_waiting
,
state
.
seconds
)
}
}
...
...
@@ -685,7 +693,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
private
val
dismissStatus
=
{
connection_status_text
.
fadeOut
()
text_connection_status
.
fadeOut
()
}
private
fun
setupRecyclerView
()
{
...
...
@@ -725,7 +733,20 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_send
.
isVisible
=
false
button_show_attachment_options
.
alpha
=
1f
button_show_attachment_options
.
isVisible
=
true
activity
?.
supportFragmentManager
?.
addOnBackStackChangedListener
{
println
(
"attach"
)
}
activity
?.
supportFragmentManager
?.
registerFragmentLifecycleCallbacks
(
object
:
FragmentManager
.
FragmentLifecycleCallbacks
()
{
override
fun
onFragmentAttached
(
fm
:
FragmentManager
,
f
:
Fragment
,
context
:
Context
)
{
if
(
f
is
MessageActionsBottomSheet
)
{
setReactionButtonIcon
(
R
.
drawable
.
ic_reaction_24dp
)
emojiKeyboardPopup
.
dismiss
()
}
}
},
true
)
subscribeComposeTextMessage
()
emojiKeyboardPopup
=
EmojiKeyboardPopup
(
activity
!!
,
activity
!!
.
findViewById
(
R
.
id
.
fragment_container
))
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
View file @
c173a519
...
...
@@ -290,25 +290,25 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
private
fun
showConnectionState
(
state
:
State
)
{
Timber
.
d
(
"Got new state: $state"
)
ui
{
connection_status_text
.
fadeIn
()
text_connection_status
.
fadeIn
()
handler
.
removeCallbacks
(
dismissStatus
)
when
(
state
)
{
is
State
.
Connected
->
{
connection_status_text
.
text
=
getString
(
R
.
string
.
status_connected
)
text_connection_status
.
text
=
getString
(
R
.
string
.
status_connected
)
handler
.
postDelayed
(
dismissStatus
,
2000
)
}
is
State
.
Disconnected
->
connection_status_text
.
text
=
getString
(
R
.
string
.
status_disconnected
)
is
State
.
Connecting
->
connection_status_text
.
text
=
getString
(
R
.
string
.
status_connecting
)
is
State
.
Authenticating
->
connection_status_text
.
text
=
getString
(
R
.
string
.
status_authenticating
)
is
State
.
Disconnecting
->
connection_status_text
.
text
=
getString
(
R
.
string
.
status_disconnecting
)
is
State
.
Waiting
->
connection_status_text
.
text
=
getString
(
R
.
string
.
status_waiting
,
state
.
seconds
)
is
State
.
Disconnected
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_disconnected
)
is
State
.
Connecting
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_connecting
)
is
State
.
Authenticating
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_authenticating
)
is
State
.
Disconnecting
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_disconnecting
)
is
State
.
Waiting
->
text_connection_status
.
text
=
getString
(
R
.
string
.
status_waiting
,
state
.
seconds
)
}
}
}
private
val
dismissStatus
=
{
if
(
connection_status_text
!=
null
)
{
connection_status_text
.
fadeOut
()
if
(
text_connection_status
!=
null
)
{
text_connection_status
.
fadeOut
()
}
}
...
...
@@ -324,4 +324,4 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
}
return
true
}
}
\ No newline at end of file
}
app/src/main/java/chat/rocket/android/util/extensions/Text.kt
View file @
c173a519
...
...
@@ -5,10 +5,8 @@ import android.text.Spanned
import
android.text.TextUtils
import
android.util.Base64
import
android.util.Patterns
import
android.widget.EditText
import
android.widget.TextView
import
chat.rocket.android.emoji.EmojiParser
import
chat.rocket.android.emoji.EmojiTypefaceSpan
import
org.json.JSONObject
import
ru.noties.markwon.Markwon
import
java.net.URLDecoder
...
...
@@ -21,21 +19,6 @@ fun String.ifEmpty(value: String): String {
return
this
}
fun
CharSequence
.
ifEmpty
(
value
:
String
):
CharSequence
{
if
(
isEmpty
())
{
return
value
}
return
this
}
fun
EditText
.
erase
()
{
this
.
text
.
clear
()
val
spans
=
this
.
text
.
getSpans
(
0
,
text
.
length
,
EmojiTypefaceSpan
::
class
.
java
)
spans
.
forEach
{
text
.
removeSpan
(
it
)
}
}
fun
String
.
isEmail
():
Boolean
=
Patterns
.
EMAIL_ADDRESS
.
matcher
(
this
).
matches
()
fun
String
.
encodeToBase64
():
String
{
...
...
@@ -94,9 +77,3 @@ var TextView.content: CharSequence?
Markwon
.
scheduleDrawables
(
this
)
Markwon
.
scheduleTableRows
(
this
)
}
var
TextView
.
spanned
:
CharSequence
?
get
()
=
text
set
(
value
)
{
text
=
spanned
}
\ No newline at end of file
app/src/main/res/layout/fragment_chat_room.xml
View file @
c173a519
...
...
@@ -12,9 +12,9 @@
android:layout_width=
"0dp"
android:layout_height=
"0dp"
app:layout_constraintBottom_toTopOf=
"@id/text_typing_status"
app:layout_constraintTop_toBottomOf=
"@+id/text_connection_status"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
>
app:layout_constraintStart_toStartOf=
"parent"
>
<include
android:id=
"@+id/layout_message_list"
...
...
@@ -117,7 +117,7 @@
app:layout_constraintBottom_toTopOf=
"@id/layout_message_composer"
/>
<TextView
android:id=
"@+id/
connection_status_text
"
android:id=
"@+id/
text_connection_status
"
android:layout_width=
"match_parent"
android:layout_height=
"32dp"
android:alpha=
"0"
...
...
@@ -127,6 +127,7 @@
android:textAppearance=
"@style/TextAppearance.AppCompat.Body2"
android:textColor=
"@color/colorWhite"
android:visibility=
"gone"
app:layout_constraintTop_toTopOf=
"parent"
tools:alpha=
"1"
tools:text=
"connected"
tools:visibility=
"visible"
/>
...
...
@@ -144,4 +145,4 @@
app:layout_constraintTop_toTopOf=
"parent"
tools:visibility=
"visible"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
</androidx.constraintlayout.widget.ConstraintLayout>
app/src/main/res/layout/fragment_chat_rooms.xml
View file @
c173a519
...
...
@@ -8,6 +8,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/recycler_view"
android:layout_below=
"@+id/text_connection_status"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
...
...
@@ -31,7 +32,7 @@
tools:visibility=
"visible"
/>
<TextView
android:id=
"@+id/
connection_status_text
"
android:id=
"@+id/
text_connection_status
"
android:layout_width=
"match_parent"
android:layout_height=
"32dp"
android:alpha=
"0"
...
...
@@ -55,4 +56,4 @@
android:textSize=
"20sp"
android:visibility=
"gone"
tools:visibility=
"visible"
/>
</RelativeLayout>
\ No newline at end of file
</RelativeLayout>
app/src/main/res/values-es/strings.xml
View file @
c173a519
...
...
@@ -267,6 +267,7 @@
<!-- Emoji message-->
<string
name=
"msg_no_recent_emoji"
>
Sin emojis recientes
</string>
<string
name=
"alert_title_default_skin_tone"
>
Tono de piel predeterminado
</string>
<!-- Sorting and grouping-->
<string
name=
"menu_chatroom_sort"
>
Ordenar
</string>
...
...
app/src/main/res/values-fr/strings.xml
View file @
c173a519
...
...
@@ -269,6 +269,7 @@
<!-- Emoji message-->
<string
name=
"msg_no_recent_emoji"
>
Aucun emoji récent
</string>
<string
name=
"alert_title_default_skin_tone"
>
Tonalité de peau par défaut
</string>
<!-- Sorting and grouping-->
<string
name=
"menu_chatroom_sort"
>
Trier
</string>
...
...
app/src/main/res/values-hi-rIN/strings.xml
View file @
c173a519
...
...
@@ -246,6 +246,7 @@
<!-- Emoji message-->
<string
name=
"msg_no_recent_emoji"
>
कोई नया इमोजी नहीं
</string>
<string
name=
"alert_title_default_skin_tone"
>
डिफ़ॉल्ट त्वचा टोन
</string>
<!-- Sorting and grouping-->
<string
name=
"menu_chatroom_sort"
>
क्रम
</string>
...
...
app/src/main/res/values-pt-rBR/strings.xml
View file @
c173a519
...
...
@@ -246,6 +246,7 @@
<!-- Emoji message-->
<string
name=
"msg_no_recent_emoji"
>
Nenhum emoji recente
</string>
<string
name=
"alert_title_default_skin_tone"
>
Tom de pele padrão
</string>
<!-- Sorting and grouping-->
<string
name=
"menu_chatroom_sort"
>
Ordenar
</string>
...
...
app/src/main/res/values-uk-rRU/strings.xml
View file @
c173a519
...
...
@@ -243,6 +243,7 @@
<!-- Emoji message-->
<string
name=
"msg_no_recent_emoji"
>
Нет недавно используемых emoji
</string>
<string
name=
"alert_title_default_skin_tone"
>
По умолчанию тон кожи
</string>
<!-- Sorting and grouping-->
<string
name=
"menu_chatroom_sort"
>
Сортировать
</string>
...
...
app/src/main/res/values/strings.xml
View file @
c173a519
...
...
@@ -246,6 +246,7 @@
<!-- Emoji message-->
<string
name=
"msg_no_recent_emoji"
>
No recent emojis
</string>
<string
name=
"alert_title_default_skin_tone"
>
Default skin tone
</string>
<!-- Sorting and grouping-->
<string
name=
"menu_chatroom_sort"
>
Sort
</string>
...
...
emoji/build.gradle
View file @
c173a519
...
...
@@ -29,6 +29,8 @@ dependencies {
implementation
libraries
.
androidKtx
implementation
libraries
.
appCompat
implementation
libraries
.
kotlin
implementation
libraries
.
coroutines
implementation
libraries
.
coroutinesAndroid
implementation
libraries
.
constraintlayout
implementation
libraries
.
recyclerview
implementation
libraries
.
material
...
...
emoji/src/main/java/chat/rocket/android/emoji/ComposerEditText.kt
View file @
c173a519
...
...
@@ -22,7 +22,7 @@ class ComposerEditText : AppCompatEditText {
override
fun
dispatchKeyEventPreIme
(
event
:
KeyEvent
):
Boolean
{
if
(
event
.
keyCode
==
KeyEvent
.
KEYCODE_BACK
)
{
val
state
=
getKeyDispatcherState
()
val
state
=
keyDispatcherState
if
(
state
!=
null
)
{
if
(
event
.
action
==
KeyEvent
.
ACTION_DOWN
)
{
state
.
startTracking
(
event
,
this
)
...
...
emoji/src/main/java/chat/rocket/android/emoji/Emoji.kt
View file @
c173a519
...
...
@@ -6,5 +6,7 @@ data class Emoji(
val
unicode
:
String
,
val
keywords
:
List
<
String
>,
val
category
:
String
,
val
count
:
Int
=
0
val
count
:
Int
=
0
,
val
siblings
:
MutableCollection
<
Emoji
>
=
mutableListOf
(),
val
fitzpatrick
:
Fitzpatrick
=
Fitzpatrick
.
Default
)
\ No newline at end of file
emoji/src/main/java/chat/rocket/android/emoji/EmojiKeyboardPopup.kt
View file @
c173a519
package
chat.rocket.android.emoji
import
android.annotation.SuppressLint
import
android.content.Context
import
android.text.Editable
import
android.text.TextWatcher
...
...
@@ -9,23 +10,32 @@ import android.view.View
import
android.view.ViewGroup
import
android.widget.EditText
import
android.widget.ImageView
import
android.widget.TextView
import
androidx.annotation.ColorInt
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.content.ContextCompat
import
androidx.core.content.edit
import
androidx.core.graphics.drawable.DrawableCompat
import
androidx.viewpager.widget.ViewPager
import
chat.rocket.android.emoji.internal.EmojiCategory
import
chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
com.google.android.material.tabs.TabLayout
class
EmojiKeyboardPopup
(
context
:
Context
,
view
:
View
)
:
OverKeyboardPopupWindow
(
context
,
view
)
{
class
EmojiKeyboardPopup
(
context
:
Context
,
view
:
View
)
:
OverKeyboardPopupWindow
(
context
,
view
)
{
private
lateinit
var
viewPager
:
ViewPager
private
lateinit
var
tabLayout
:
TabLayout
private
lateinit
var
searchView
:
View
private
lateinit
var
backspaceView
:
View
private
lateinit
var
parentContainer
:
ViewGroup
private
lateinit
var
changeColorView
:
View
private
lateinit
var
adapter
:
EmojiPagerAdapter
var
listener
:
EmojiKeyboardListener
?
=
null
@SuppressLint
(
"InflateParams"
)
override
fun
onCreateView
(
inflater
:
LayoutInflater
):
View
{
val
view
=
inflater
.
inflate
(
R
.
layout
.
emoji_keyboard
,
null
)
parentContainer
=
view
.
findViewById
(
R
.
id
.
emoji_keyboard_container
)
...
...
@@ -33,6 +43,7 @@ class EmojiKeyboardPopup(
searchView
=
view
.
findViewById
(
R
.
id
.
emoji_search
)
backspaceView
=
view
.
findViewById
(
R
.
id
.
emoji_backspace
)
tabLayout
=
view
.
findViewById
(
R
.
id
.
tabs
)
changeColorView
=
view
.
findViewById
(
R
.
id
.
color_change_view
)
tabLayout
.
setupWithViewPager
(
viewPager
)
return
view
}
...
...
@@ -44,11 +55,97 @@ class EmojiKeyboardPopup(
private
fun
setupBottomBar
()
{
searchView
.
setOnClickListener
{
//TODO: search not yet implemented
}
backspaceView
.
setOnClickListener
{
listener
?.
onNonEmojiKeyPressed
(
KeyEvent
.
KEYCODE_BACK
)
}
changeColorView
.
setOnClickListener
{
showSkinToneChooser
()
}
val
sharedPreferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
sharedPreferences
.
getString
(
PREF_EMOJI_SKIN_TONE
,
""
)
?.
let
{
changeSkinTone
(
Fitzpatrick
.
valueOf
(
it
))
}
}
private
fun
showSkinToneChooser
()
{
val
view
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
color_select_popup
,
null
)
val
dialog
=
AlertDialog
.
Builder
(
context
,
R
.
style
.
Dialog
)
.
setView
(
view
)
.
setTitle
(
context
.
getString
(
R
.
string
.
alert_title_default_skin_tone
))
.
setCancelable
(
true
)
.
create
()
view
.
findViewById
<
TextView
>(
R
.
id
.
default_tone_text
).
also
{
it
.
text
=
EmojiParser
.
parse
(
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
Default
)
}
view
.
findViewById
<
TextView
>(
R
.
id
.
light_tone_text
).
also
{
it
.
text
=
EmojiParser
.
parse
(
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
LightTone
)
}
view
.
findViewById
<
TextView
>(
R
.
id
.
medium_light_text
).
also
{
it
.
text
=
EmojiParser
.
parse
(
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
MediumLightTone
)
}
view
.
findViewById
<
TextView
>(
R
.
id
.
medium_tone_text
).
also
{
it
.
text
=
EmojiParser
.
parse
(
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
MediumTone
)
}
view
.
findViewById
<
TextView
>(
R
.
id
.
medium_dark_tone_text
).
also
{
it
.
text
=
EmojiParser
.
parse
(
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
MediumDarkTone
)
}
view
.
findViewById
<
TextView
>(
R
.
id
.
dark_tone_text
).
also
{
it
.
text
=
EmojiParser
.
parse
(
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
DarkTone
)
}
dialog
.
show
()
}
private
fun
changeSkinTone
(
tone
:
Fitzpatrick
)
{
val
drawable
=
ContextCompat
.
getDrawable
(
context
,
R
.
drawable
.
color_change_circle
)
!!
val
wrappedDrawable
=
DrawableCompat
.
wrap
(
drawable
)
DrawableCompat
.
setTint
(
wrappedDrawable
,
getFitzpatrickColor
(
tone
))
(
changeColorView
as
ImageView
).
setImageDrawable
(
wrappedDrawable
)
adapter
.
setFitzpatrick
(
tone
)
}
@ColorInt
private
fun
getFitzpatrickColor
(
tone
:
Fitzpatrick
):
Int
{
val
sharedPreferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
sharedPreferences
.
edit
{
putString
(
PREF_EMOJI_SKIN_TONE
,
tone
.
type
)
}
return
when
(
tone
)
{
Fitzpatrick
.
Default
->
ContextCompat
.
getColor
(
context
,
R
.
color
.
tone_default
)
Fitzpatrick
.
LightTone
->
ContextCompat
.
getColor
(
context
,
R
.
color
.
tone_light
)
Fitzpatrick
.
MediumLightTone
->
ContextCompat
.
getColor
(
context
,
R
.
color
.
tone_medium_light
)
Fitzpatrick
.
MediumTone
->
ContextCompat
.
getColor
(
context
,
R
.
color
.
tone_medium
)
Fitzpatrick
.
MediumDarkTone
->
ContextCompat
.
getColor
(
context
,
R
.
color
.
tone_medium_dark
)
Fitzpatrick
.
DarkTone
->
ContextCompat
.
getColor
(
context
,
R
.
color
.
tone_dark
)
}
}
private
fun
setupViewPager
()
{
...
...
@@ -64,12 +161,14 @@ class EmojiKeyboardPopup(
}
}
viewPager
.
adapter
=
Category
PagerAdapter
(
object
:
EmojiKeyboardListener
{
adapter
=
Emoji
PagerAdapter
(
object
:
EmojiKeyboardListener
{
override
fun
onEmojiAdded
(
emoji
:
Emoji
)
{
EmojiRepository
.
addToRecents
(
emoji
)
callback
.
onEmojiAdded
(
emoji
)
}
})
viewPager
.
offscreenPageLimit
=
EmojiCategory
.
values
().
size
viewPager
.
adapter
=
adapter
for
(
category
in
EmojiCategory
.
values
())
{
val
tab
=
tabLayout
.
getTabAt
(
category
.
ordinal
)
...
...
@@ -79,14 +178,18 @@ class EmojiKeyboardPopup(
textView
.
setImageResource
(
category
.
resourceIcon
())
}
val
currentTab
=
if
(
EmojiRepository
.
getRecents
().
isEmpty
())
EmojiCategory
.
PEOPLE
.
ordinal
else
val
currentTab
=
if
(
EmojiRepository
.
getRecents
().
isEmpty
())
{
EmojiCategory
.
PEOPLE
.
ordinal
}
else
{
EmojiCategory
.
RECENTS
.
ordinal
}
viewPager
.
currentItem
=
currentTab
}
}
class
EmojiTextWatcher
(
private
val
editor
:
EditText
)
:
TextWatcher
{
@Volatile
private
var
emojiToRemove
=
mutableListOf
<
EmojiTypefaceSpan
>()
@Volatile
private
var
emojiToRemove
=
mutableListOf
<
EmojiTypefaceSpan
>()
override
fun
afterTextChanged
(
s
:
Editable
)
{
val
message
=
editor
.
editableText
...
...
@@ -128,8 +231,4 @@ class EmojiKeyboardPopup(
override
fun
onTextChanged
(
s
:
CharSequence
,
start
:
Int
,
before
:
Int
,
count
:
Int
)
{
}
}
companion
object
{
const
val
PREF_EMOJI_RECENTS
=
"PREF_EMOJI_RECENTS"
}
}
\ No newline at end of file
emoji/src/main/java/chat/rocket/android/emoji/EmojiParser.kt
View file @
c173a519
package
chat.rocket.android.emoji
import
android.text.Spannable
import
android.text.SpannableString
import
android.text.Spanned
...
...
@@ -11,11 +12,12 @@ class EmojiParser {
* Spannable.
*
* @param text The text to parse
* @param factory Optional. A [Spannable.Factory] instance to reuse when creating [Spannable].
* @return A rendered Spannable containing any supported emoji.
*/
fun
parse
(
text
:
CharSequence
):
CharSequence
{
fun
parse
(
text
:
CharSequence
,
factory
:
Spannable
.
Factory
?
=
null
):
CharSequence
{
val
unicodedText
=
EmojiRepository
.
shortnameToUnicode
(
text
,
true
)
val
spannable
=
SpannableString
.
valueOf
(
unicodedText
)
val
spannable
=
factory
?.
newSpannable
(
unicodedText
)
?:
SpannableString
.
valueOf
(
unicodedText
)
val
typeface
=
EmojiRepository
.
cachedTypeface
// Look for groups of emojis, set a EmojiTypefaceSpan with the emojione font.
val
length
=
spannable
.
length
...
...
emoji/src/main/java/chat/rocket/android/emoji/EmojiPickerPopup.kt
View file @
c173a519
...
...
@@ -3,18 +3,23 @@ package chat.rocket.android.emoji
import
android.app.Dialog
import
android.content.Context
import
android.os.Bundle
import
com.google.android.material.tabs.TabLayout
import
androidx.viewpager.widget.ViewPager
import
android.view.LayoutInflater
import
android.view.Window
import
android.view.WindowManager
import
android.widget.ImageView
import
androidx.annotation.ColorInt
import
androidx.core.content.ContextCompat
import
androidx.core.content.edit
import
chat.rocket.android.emoji.internal.EmojiCategory
import
chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
kotlinx.android.synthetic.main.emoji_picker.*
class
EmojiPickerPopup
(
context
:
Context
)
:
Dialog
(
context
)
{
var
listener
:
EmojiKeyboardListener
?
=
null
private
lateinit
var
adapter
:
EmojiPagerAdapter
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
...
...
@@ -35,7 +40,7 @@ class EmojiPickerPopup(context: Context) : Dialog(context) {
}
private
fun
setupViewPager
()
{
pager_categories
.
adapter
=
Category
PagerAdapter
(
object
:
EmojiKeyboardListener
{
adapter
=
Emoji
PagerAdapter
(
object
:
EmojiKeyboardListener
{
override
fun
onEmojiAdded
(
emoji
:
Emoji
)
{
EmojiRepository
.
addToRecents
(
emoji
)
dismiss
()
...
...
@@ -43,6 +48,14 @@ class EmojiPickerPopup(context: Context) : Dialog(context) {
}
})
val
sharedPreferences
=
context
.
getSharedPreferences
(
"emoji"
,
Context
.
MODE_PRIVATE
)
sharedPreferences
.
getString
(
PREF_EMOJI_SKIN_TONE
,
""
)
?.
let
{
changeSkinTone
(
Fitzpatrick
.
valueOf
(
it
))
}
pager_categories
.
adapter
=
adapter
pager_categories
.
offscreenPageLimit
=
EmojiCategory
.
values
().
size
for
(
category
in
EmojiCategory
.
values
())
{
val
tab
=
tabs
.
getTabAt
(
category
.
ordinal
)
val
tabView
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
emoji_picker_tab
,
null
)
...
...
@@ -51,8 +64,15 @@ class EmojiPickerPopup(context: Context) : Dialog(context) {
textView
.
setImageResource
(
category
.
resourceIcon
())
}
val
currentTab
=
if
(
EmojiRepository
.
getRecents
().
isEmpty
())
EmojiCategory
.
PEOPLE
.
ordinal
else
val
currentTab
=
if
(
EmojiRepository
.
getRecents
().
isEmpty
())
{
EmojiCategory
.
PEOPLE
.
ordinal
}
else
{
EmojiCategory
.
RECENTS
.
ordinal
}
pager_categories
.
currentItem
=
currentTab
}
private
fun
changeSkinTone
(
tone
:
Fitzpatrick
)
{
adapter
.
setFitzpatrick
(
tone
)
}
}
\ No newline at end of file
emoji/src/main/java/chat/rocket/android/emoji/EmojiRepository.kt
View file @
c173a519
...
...
@@ -3,6 +3,12 @@ package chat.rocket.android.emoji
import
android.content.Context
import
android.content.SharedPreferences
import
android.graphics.Typeface
import
android.os.SystemClock
import
chat.rocket.android.emoji.internal.EmojiCategory
import
chat.rocket.android.emoji.internal.PREF_EMOJI_RECENTS
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.experimental.yield
import
org.json.JSONArray
import
org.json.JSONObject
import
java.io.BufferedReader
...
...
@@ -10,8 +16,11 @@ import java.io.InputStream
import
java.io.InputStreamReader
import
java.util.*
import
java.util.regex.Pattern
import
kotlin.coroutines.experimental.buildSequence
object
EmojiRepository
{
private
val
FITZPATRICK_REGEX
=
"(.*)_(tone[0-9]):"
.
toRegex
(
RegexOption
.
IGNORE_CASE
)
private
val
shortNameToUnicode
=
HashMap
<
String
,
String
>()
private
val
SHORTNAME_PATTERN
=
Pattern
.
compile
(
":([-+\\w]+):"
)
private
val
ALL_EMOJIS
=
mutableListOf
<
Emoji
>()
...
...
@@ -24,9 +33,9 @@ object EmojiRepository {
cachedTypeface
=
Typeface
.
createFromAsset
(
context
.
assets
,
"fonts/emojione-android.ttf"
)
val
stream
=
context
.
assets
.
open
(
path
)
val
emojis
=
loadEmojis
(
stream
)
emojis
.
forEach
{
emojis
.
forEach
{
emoji
->
val
unicodeIntList
=
mutableListOf
<
Int
>()
it
.
unicode
.
split
(
"-"
).
forEach
{
emoji
.
unicode
.
split
(
"-"
).
forEach
{
val
value
=
it
.
toInt
(
16
)
if
(
value
>=
0
x10000
)
{
val
surrogatePair
=
calculateSurrogatePairs
(
value
)
...
...
@@ -38,20 +47,40 @@ object EmojiRepository {
}
val
unicodeIntArray
=
unicodeIntList
.
toIntArray
()
val
unicode
=
String
(
unicodeIntArray
,
0
,
unicodeIntArray
.
size
)
ALL_EMOJIS
.
add
(
it
.
copy
(
unicode
=
unicode
))
val
emojiWithUnicode
=
emoji
.
copy
(
unicode
=
unicode
)
if
(
hasFitzpatrick
(
emoji
.
shortname
))
{
val
matchResult
=
FITZPATRICK_REGEX
.
find
(
emoji
.
shortname
)
val
prefix
=
matchResult
!!
.
groupValues
[
1
]
+
":"
val
fitzpatrick
=
Fitzpatrick
.
valueOf
(
matchResult
.
groupValues
[
2
])
val
defaultEmoji
=
ALL_EMOJIS
.
firstOrNull
{
it
.
shortname
==
prefix
}
val
emojiWithFitzpatrick
=
emojiWithUnicode
.
copy
(
fitzpatrick
=
fitzpatrick
)
if
(
defaultEmoji
!=
null
)
{
defaultEmoji
.
siblings
.
add
(
emojiWithFitzpatrick
)
}
else
{
// This emoji doesn't have a default tone, ie. :man_in_business_suit_levitating_tone1:
// In this case, the default emoji becomes the first toned one.
ALL_EMOJIS
.
add
(
emojiWithFitzpatrick
)
}
}
else
{
ALL_EMOJIS
.
add
(
emojiWithUnicode
)
}
shortNameToUnicode
.
apply
{
put
(
it
.
shortname
,
unicode
)
it
.
shortnameAlternates
.
forEach
{
alternate
->
put
(
alternate
,
unicode
)
}
put
(
emoji
.
shortname
,
unicode
)
emoji
.
shortnameAlternates
.
forEach
{
alternate
->
put
(
alternate
,
unicode
)
}
}
}
}
private
fun
hasFitzpatrick
(
shortname
:
String
):
Boolean
{
return
FITZPATRICK_REGEX
matches
shortname
}
/**
* Get all loaded emojis as list of Emoji objects.
*
* @return All emojis for all categories.
*/
fun
getAll
()
=
ALL_EMOJIS
internal
fun
getAll
()
=
ALL_EMOJIS
/**
* Get all emojis for a given category.
...
...
@@ -60,10 +89,19 @@ object EmojiRepository {
*
* @return All emoji from specified category
*/
fun
getEmojisByCategory
(
category
:
EmojiCategory
):
List
<
Emoji
>
{
internal
fun
getEmojisByCategory
(
category
:
EmojiCategory
):
List
<
Emoji
>
{
return
ALL_EMOJIS
.
filter
{
it
.
category
.
toLowerCase
()
==
category
.
name
.
toLowerCase
()
}
}
internal
fun
getEmojiSequenceByCategory
(
category
:
EmojiCategory
):
Sequence
<
Emoji
>
{
val
list
=
ALL_EMOJIS
.
filter
{
it
.
category
.
toLowerCase
()
==
category
.
name
.
toLowerCase
()
}
return
buildSequence
{
list
.
forEach
{
yield
(
it
)
}
}
}
/**
* Get the emoji given by a specified shortname. Returns null if can't find any.
*
...
...
@@ -71,21 +109,21 @@ object EmojiRepository {
*
* @return Emoji given by shortname or null
*/
fun
getEmojiByShortname
(
shortname
:
String
)
=
ALL_EMOJIS
.
firstOrNull
{
it
.
shortname
==
shortname
}
internal
fun
getEmojiByShortname
(
shortname
:
String
)
=
ALL_EMOJIS
.
firstOrNull
{
it
.
shortname
==
shortname
}
/**
* Add an emoji to the Recents category.
*/
fun
addToRecents
(
emoji
:
Emoji
)
{
internal
fun
addToRecents
(
emoji
:
Emoji
)
{
val
emojiShortname
=
emoji
.
shortname
val
recentsJson
=
JSONObject
(
preferences
.
getString
(
EmojiKeyboardPopup
.
PREF_EMOJI_RECENTS
,
"{}"
))
val
recentsJson
=
JSONObject
(
preferences
.
getString
(
PREF_EMOJI_RECENTS
,
"{}"
))
if
(
recentsJson
.
has
(
emojiShortname
))
{
val
useCount
=
recentsJson
.
getInt
(
emojiShortname
)
recentsJson
.
put
(
emojiShortname
,
useCount
+
1
)
}
else
{
recentsJson
.
put
(
emojiShortname
,
1
)
}
preferences
.
edit
().
putString
(
EmojiKeyboardPopup
.
PREF_EMOJI_RECENTS
,
recentsJson
.
toString
()).
apply
()
preferences
.
edit
().
putString
(
PREF_EMOJI_RECENTS
,
recentsJson
.
toString
()).
apply
()
}
/**
...
...
@@ -93,9 +131,9 @@ object EmojiRepository {
*
* @return All recent emojis ordered by usage.
*/
fun
getRecents
():
List
<
Emoji
>
{
internal
fun
getRecents
():
List
<
Emoji
>
{
val
list
=
mutableListOf
<
Emoji
>()
val
recentsJson
=
JSONObject
(
preferences
.
getString
(
EmojiKeyboardPopup
.
PREF_EMOJI_RECENTS
,
"{}"
))
val
recentsJson
=
JSONObject
(
preferences
.
getString
(
PREF_EMOJI_RECENTS
,
"{}"
))
for
(
shortname
in
recentsJson
.
keys
())
{
val
emoji
=
getEmojiByShortname
(
shortname
)
emoji
?.
let
{
...
...
emoji/src/main/java/chat/rocket/android/emoji/EmojiTypefaceSpan.kt
View file @
c173a519
...
...
@@ -16,23 +16,6 @@ class EmojiTypefaceSpan(family: String, private val newType: Typeface) : Typefac
}
private
fun
applyCustomTypeFace
(
paint
:
Paint
,
tf
:
Typeface
)
{
val
oldStyle
:
Int
val
old
=
paint
.
typeface
if
(
old
==
null
)
{
oldStyle
=
0
}
else
{
oldStyle
=
old
.
style
}
val
fake
=
oldStyle
and
tf
.
style
.
inv
()
if
(
fake
and
Typeface
.
BOLD
!=
0
)
{
paint
.
isFakeBoldText
=
true
}
if
(
fake
and
Typeface
.
ITALIC
!=
0
)
{
paint
.
textSkewX
=
-
0.25f
}
paint
.
typeface
=
tf
}
}
\ No newline at end of file
emoji/src/main/java/chat/rocket/android/emoji/Fitzpatrick.kt
0 → 100644
View file @
c173a519
package
chat.rocket.android.emoji
/**
* Taken the Fitzpatrick scale as reference and adapted to be used with emojione.
*
* @see <a href="https://en.wikipedia.org/wiki/Fitzpatrick_scale">https://en.wikipedia.org/wiki/Fitzpatrick_scale</a>
*/
sealed
class
Fitzpatrick
(
val
type
:
String
)
{
object
Default
:
Fitzpatrick
(
""
)
object
LightTone
:
Fitzpatrick
(
"tone1"
)
object
MediumLightTone
:
Fitzpatrick
(
"tone2"
)
object
MediumTone
:
Fitzpatrick
(
"tone3"
)
object
MediumDarkTone
:
Fitzpatrick
(
"tone4"
)
object
DarkTone
:
Fitzpatrick
(
"tone5"
)
companion
object
{
fun
valueOf
(
type
:
String
):
Fitzpatrick
{
return
when
(
type
)
{
""
->
Default
"tone1"
->
LightTone
"tone2"
->
MediumLightTone
"tone3"
->
MediumTone
"tone4"
->
MediumDarkTone
"tone5"
->
DarkTone
else
->
throw
IllegalArgumentException
(
"Fitzpatrick type '$type' is invalid"
)
}
}
}
}
\ No newline at end of file
emoji/src/main/java/chat/rocket/android/emoji/EmojiCategory.kt
→
emoji/src/main/java/chat/rocket/android/emoji/
internal/
EmojiCategory.kt
View file @
c173a519
package
chat.rocket.android.emoji
package
chat.rocket.android.emoji
.internal
import
android.text.SpannableString
import
android.text.Spanned
import
androidx.annotation.DrawableRes
import
chat.rocket.android.emoji.EmojiRepository
import
chat.rocket.android.emoji.EmojiTypefaceSpan
import
chat.rocket.android.emoji.R
enum
class
EmojiCategory
{
internal
enum
class
EmojiCategory
{
RECENTS
{
override
fun
resourceIcon
()
=
R
.
drawable
.
ic_emoji_recents
...
...
emoji/src/main/java/chat/rocket/android/emoji/
Category
PagerAdapter.kt
→
emoji/src/main/java/chat/rocket/android/emoji/
internal/Emoji
PagerAdapter.kt
View file @
c173a519
package
chat.rocket.android.emoji
package
chat.rocket.android.emoji
.internal
import
android.text.Spannable
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.TextView
import
androidx.core.view.isVisible
import
androidx.recyclerview.widget.DefaultItemAnimator
import
androidx.recyclerview.widget.GridLayoutManager
import
androidx.recyclerview.widget.RecyclerView
import
androidx.viewpager.widget.PagerAdapter
import
chat.rocket.android.emoji.Emoji
import
chat.rocket.android.emoji.EmojiKeyboardListener
import
chat.rocket.android.emoji.EmojiParser
import
chat.rocket.android.emoji.EmojiRepository
import
chat.rocket.android.emoji.Fitzpatrick
import
chat.rocket.android.emoji.R
import
kotlinx.android.synthetic.main.emoji_category_layout.view.*
import
java.util.*
import
kotlinx.android.synthetic.main.emoji_row_item.view.*
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.experimental.withContext
internal
class
CategoryPagerAdapter
(
private
val
listener
:
EmojiKeyboardListener
)
:
PagerAdapter
()
{
internal
class
EmojiPagerAdapter
(
private
val
listener
:
EmojiKeyboardListener
)
:
PagerAdapter
()
{
private
val
adapters
=
hashMapOf
<
EmojiCategory
,
EmojiAdapter
>()
private
var
fitzpatrick
:
Fitzpatrick
=
Fitzpatrick
.
Default
override
fun
isViewFromObject
(
view
:
View
,
obj
:
Any
):
Boolean
{
return
view
==
obj
...
...
@@ -23,21 +36,28 @@ internal class CategoryPagerAdapter(private val listener: EmojiKeyboardListener)
.
inflate
(
R
.
layout
.
emoji_category_layout
,
container
,
false
)
with
(
view
)
{
val
layoutManager
=
GridLayoutManager
(
context
,
8
)
val
adapter
=
EmojiAdapter
(
layoutManager
.
spanCount
,
listener
)
val
category
=
EmojiCategory
.
values
()[
position
]
val
emojis
=
if
(
category
!=
EmojiCategory
.
RECENTS
)
{
EmojiRepository
.
getEmojisByCategory
(
category
)
}
else
{
EmojiRepository
.
getRecents
()
}
val
recentEmojiSize
=
EmojiRepository
.
getRecents
().
size
text_no_recent_emoji
.
isVisible
=
category
==
EmojiCategory
.
RECENTS
&&
recentEmojiSize
==
0
adapter
.
addEmojis
(
emojis
)
emoji_recycler_view
.
layoutManager
=
layoutManager
emoji_recycler_view
.
itemAnimator
=
DefaultItemAnimator
()
emoji_recycler_view
.
adapter
=
adapter
emoji_recycler_view
.
isNestedScrollingEnabled
=
false
emoji_recycler_view
.
setRecycledViewPool
(
RecyclerView
.
RecycledViewPool
())
container
.
addView
(
view
)
launch
(
UI
)
{
val
emojis
=
if
(
category
!=
EmojiCategory
.
RECENTS
)
{
EmojiRepository
.
getEmojiSequenceByCategory
(
category
)
}
else
{
sequenceOf
(*
EmojiRepository
.
getRecents
().
toTypedArray
())
}
val
recentEmojiSize
=
EmojiRepository
.
getRecents
().
size
text_no_recent_emoji
.
isVisible
=
category
==
EmojiCategory
.
RECENTS
&&
recentEmojiSize
==
0
if
(
adapters
[
category
]
==
null
)
{
val
adapter
=
EmojiAdapter
(
listener
=
listener
)
emoji_recycler_view
.
adapter
=
adapter
adapters
[
category
]
=
adapter
adapter
.
addEmojisFromSequence
(
emojis
)
}
adapters
[
category
]
!!
.
setFitzpatrick
(
fitzpatrick
)
}
}
return
view
}
...
...
@@ -50,25 +70,58 @@ internal class CategoryPagerAdapter(private val listener: EmojiKeyboardListener)
override
fun
getPageTitle
(
position
:
Int
)
=
EmojiCategory
.
values
()[
position
].
textIcon
()
override
fun
getItemPosition
(
`object`
:
Any
):
Int
{
return
POSITION_NONE
}
fun
setFitzpatrick
(
fitzpatrick
:
Fitzpatrick
)
{
this
.
fitzpatrick
=
fitzpatrick
for
(
entry
in
adapters
.
entries
)
{
if
(
entry
.
key
!=
EmojiCategory
.
RECENTS
)
{
entry
.
value
.
setFitzpatrick
(
fitzpatrick
)
}
}
}
class
EmojiAdapter
(
private
va
l
spanCount
:
In
t
,
private
va
r
fitzpatrick
:
Fitzpatrick
=
Fitzpatrick
.
Defaul
t
,
private
val
listener
:
EmojiKeyboardListener
)
:
RecyclerView
.
Adapter
<
EmojiRowViewHolder
>()
{
private
va
r
emojis
=
Collections
.
emptyList
<
Emoji
>()
private
va
l
emojis
=
mutableListOf
<
Emoji
>()
fun
addEmojis
(
emojis
:
List
<
Emoji
>)
{
this
.
emojis
=
emojis
notifyItemRangeInserted
(
0
,
emojis
.
size
)
this
.
emojis
.
clear
()
this
.
emojis
.
addAll
(
emojis
)
notifyDataSetChanged
()
}
suspend
fun
addEmojisFromSequence
(
emojiSequence
:
Sequence
<
Emoji
>)
{
withContext
(
CommonPool
)
{
emojiSequence
.
forEachIndexed
{
index
,
emoji
->
withContext
(
UI
)
{
emojis
.
add
(
emoji
)
notifyItemInserted
(
index
)
}
}
}
}
fun
setFitzpatrick
(
fitzpatrick
:
Fitzpatrick
)
{
this
.
fitzpatrick
=
fitzpatrick
notifyDataSetChanged
()
}
override
fun
onBindViewHolder
(
holder
:
EmojiRowViewHolder
,
position
:
Int
)
{
holder
.
bind
(
emojis
[
position
])
val
emoji
=
emojis
[
position
]
holder
.
bind
(
emoji
.
siblings
.
find
{
it
.
fitzpatrick
==
fitzpatrick
}
?:
emoji
)
}
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
EmojiRowViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
emoji_row_item
,
parent
,
false
)
return
EmojiRowViewHolder
(
view
,
itemCount
,
spanCount
,
listener
)
return
EmojiRowViewHolder
(
view
,
listener
)
}
override
fun
getItemCount
():
Int
=
emojis
.
size
...
...
@@ -76,25 +129,30 @@ internal class CategoryPagerAdapter(private val listener: EmojiKeyboardListener)
class
EmojiRowViewHolder
(
itemView
:
View
,
private
val
itemCount
:
Int
,
private
val
spanCount
:
Int
,
private
val
listener
:
EmojiKeyboardListener
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
private
val
emojiView
:
TextView
=
itemView
.
findViewById
(
R
.
id
.
emoji
)
fun
bind
(
emoji
:
Emoji
)
{
val
context
=
itemView
.
context
emojiView
.
text
=
EmojiParser
.
parse
(
emoji
.
unicode
)
val
remainder
=
itemCount
%
spanCount
val
lastLineItemCount
=
if
(
remainder
==
0
)
spanCount
else
remainder
val
paddingBottom
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
picker_padding_bottom
)
if
(
adapterPosition
>=
itemCount
-
lastLineItemCount
)
{
itemView
.
setPadding
(
0
,
0
,
0
,
paddingBottom
)
}
itemView
.
setOnClickListener
{
listener
.
onEmojiAdded
(
emoji
)
with
(
itemView
)
{
val
parsedUnicode
=
unicodeCache
[
emoji
.
unicode
]
emoji_view
.
setSpannableFactory
(
spannableFactory
)
emoji_view
.
text
=
if
(
parsedUnicode
==
null
)
{
EmojiParser
.
parse
(
emoji
.
unicode
,
spannableFactory
).
let
{
unicodeCache
[
emoji
.
unicode
]
=
it
it
}
}
else
{
parsedUnicode
}
itemView
.
setOnClickListener
{
listener
.
onEmojiAdded
(
emoji
)
}
}
}
companion
object
{
private
val
spannableFactory
=
Spannable
.
Factory
()
private
val
unicodeCache
=
mutableMapOf
<
CharSequence
,
CharSequence
>()
}
}
}
\ No newline at end of file
emoji/src/main/java/chat/rocket/android/emoji/internal/Preferences.kt
0 → 100644
View file @
c173a519
package
chat.rocket.android.emoji.internal
internal
const
val
PREF_EMOJI_RECENTS
=
"PREF_EMOJI_RECENTS"
internal
const
val
PREF_EMOJI_SKIN_TONE
=
"PREF_EMOJI_SKIN_TONE"
\ No newline at end of file
emoji/src/main/res/drawable/color_change_circle.xml
0 → 100644
View file @
c173a519
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"oval"
>
<solid
android:color=
"@color/tone_default"
/>
<size
android:width=
"24dp"
android:height=
"24dp"
/>
</shape>
\ No newline at end of file
emoji/src/main/res/layout-land/emoji_picker.xml
0 → 100644
View file @
c173a519
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/picker_container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/colorWhite"
android:orientation=
"vertical"
>
<com.google.android.material.tabs.TabLayout
android:id=
"@+id/tabs"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
app:tabBackground=
"@color/whitesmoke"
app:tabGravity=
"fill"
app:tabMode=
"scrollable"
/>
<androidx.viewpager.widget.ViewPager
android:id=
"@+id/pager_categories"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_marginEnd=
"8dp"
android:layout_marginStart=
"8dp"
android:background=
"@color/colorWhite"
/>
</LinearLayout>
\ No newline at end of file
emoji/src/main/res/layout/color_select_popup.xml
0 → 100644
View file @
c173a519
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
>
<TextView
android:id=
"@+id/default_tone_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"16dp"
android:text=
"👌"
android:textSize=
"32sp"
android:tint=
"@color/tone_default"
app:layout_constraintEnd_toStartOf=
"@+id/light_tone_text"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintHorizontal_chainStyle=
"packed"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/color_change_circle"
/>
<TextView
android:id=
"@+id/light_tone_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"16dp"
android:layout_marginEnd=
"24dp"
android:text=
"👌🏻"
android:textSize=
"32sp"
android:tint=
"@color/tone_light"
app:layout_constraintEnd_toStartOf=
"@+id/medium_light_text"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintStart_toEndOf=
"@+id/default_tone_text"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/color_change_circle"
tools:text=
"👌"
/>
<TextView
android:id=
"@+id/medium_light_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"16dp"
android:text=
"👌🏼"
android:textSize=
"32sp"
android:tint=
"@color/tone_medium_light"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintStart_toEndOf=
"@+id/light_tone_text"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/color_change_circle"
tools:text=
"👌"
/>
<TextView
android:id=
"@+id/medium_tone_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
android:layout_marginBottom=
"16dp"
android:text=
"👌🏽"
android:textSize=
"32sp"
android:tint=
"@color/tone_medium"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/medium_dark_tone_text"
app:layout_constraintHorizontal_chainStyle=
"packed"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/default_tone_text"
app:srcCompat=
"@drawable/color_change_circle"
tools:text=
"👌"
/>
<TextView
android:id=
"@+id/medium_dark_tone_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"8dp"
android:layout_marginEnd=
"24dp"
android:layout_marginBottom=
"16dp"
android:text=
"👌🏾"
android:textSize=
"32sp"
android:tint=
"@color/tone_medium_dark"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/dark_tone_text"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintStart_toEndOf=
"@+id/medium_tone_text"
app:layout_constraintTop_toBottomOf=
"@+id/light_tone_text"
app:srcCompat=
"@drawable/color_change_circle"
tools:text=
"👌"
/>
<TextView
android:id=
"@+id/dark_tone_text"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
android:layout_marginBottom=
"16dp"
android:text=
"👌🏿"
android:textSize=
"32sp"
android:tint=
"@color/tone_dark"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/medium_dark_tone_text"
app:layout_constraintTop_toBottomOf=
"@+id/medium_light_text"
app:srcCompat=
"@drawable/color_change_circle"
tools:text=
"👌"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
emoji/src/main/res/layout/emoji_keyboard.xml
View file @
c173a519
...
...
@@ -3,7 +3,7 @@
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/emoji_keyboard_container"
android:layout_width=
"match_parent"
android:layout_height=
"
0dp
"
android:layout_height=
"
wrap_content
"
android:background=
"@color/colorWhite"
>
<View
...
...
@@ -26,7 +26,7 @@
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<
Relative
Layout
<
androidx.constraintlayout.widget.Constraint
Layout
android:id=
"@+id/emoji_actions_container"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
...
...
@@ -36,29 +36,40 @@
app:layout_constraintStart_toStartOf=
"parent"
>
<ImageView
android:id=
"@+id/
emoji_search
"
android:id=
"@+id/
color_change_view
"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentStart=
"true"
android:layout_centerVertical=
"true"
android:padding=
"8dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/color_change_circle"
/>
<ImageView
android:id=
"@+id/emoji_search"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:background=
"@color/whitesmoke"
android:clickable=
"true"
android:focusable=
"true"
android:padding=
"8dp"
android:src=
"@drawable/ic_search_gray_24px"
android:visibility=
"invisible"
/>
android:visibility=
"invisible"
app:layout_constraintEnd_toStartOf=
"@+id/emoji_backspace"
app:layout_constraintStart_toEndOf=
"@+id/color_change_view"
/>
<ImageView
android:id=
"@+id/emoji_backspace"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentEnd=
"true"
android:layout_centerVertical=
"true"
android:background=
"@color/whitesmoke"
android:clickable=
"true"
android:focusable=
"true"
android:padding=
"8dp"
android:src=
"@drawable/ic_backspace_gray_24dp"
/>
</RelativeLayout>
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/ic_backspace_gray_24dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
emoji/src/main/res/layout/emoji_row_item.xml
View file @
c173a519
<?xml version="1.0" encoding="utf-8"?>
<
FrameLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<
TextView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:id=
"@+id/emoji_view"
style=
"@style/TextAppearance.AppCompat.Title"
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:foreground=
"?selectableItemBackground"
android:gravity=
"center"
>
<TextView
android:id=
"@+id/emoji"
style=
"@style/TextAppearance.AppCompat.Title"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:gravity=
"center"
android:textColor=
"#000000"
android:textSize=
"26sp"
tools:text=
"😀"
/>
</FrameLayout>
\ No newline at end of file
android:textColor=
"#000000"
android:textSize=
"26sp"
tools:text=
"😀"
/>
emoji/src/main/res/values/colors.xml
View file @
c173a519
...
...
@@ -7,4 +7,12 @@
<color
name=
"colorEmojiIcon"
>
#FF767676
</color>
<color
name=
"colorDividerMessageComposer"
>
#D8D8D8
</color>
<!-- Skin tone colors -->
<color
name=
"tone_default"
>
#fdcb45
</color>
<color
name=
"tone_light"
>
#fcd6b4
</color>
<color
name=
"tone_medium_light"
>
#ecc0a1
</color>
<color
name=
"tone_medium"
>
#ba8b6f
</color>
<color
name=
"tone_medium_dark"
>
#926b4f
</color>
<color
name=
"tone_dark"
>
#614833
</color>
</resources>
emoji/src/main/res/values/strings.xml
View file @
c173a519
<resources>
<string
name=
"msg_no_recent_emoji"
>
No recent emoji
</string>
<string
name=
"alert_title_default_skin_tone"
>
Default skin tone
</string>
</resources>
emoji/src/main/res/values/styles.xml
0 → 100644
View file @
c173a519
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style
name=
"Dialog"
parent=
"Theme.AppCompat.Light.Dialog.Alert"
>
<item
name=
"android:windowMinWidthMajor"
>
80%
</item>
<item
name=
"android:windowMinWidthMinor"
>
80%
</item>
</style>
</resources>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment