Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization part 1: implement kotlinx-serializable, use serialized AddedViews #414

Merged
merged 24 commits into from
Jul 19, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2500285
setup kotlinx serialization plugin
mzorz Jul 2, 2020
c25f9cd
added @Serializable annotations, changed AddedViewList constructor to…
mzorz Jul 2, 2020
b855ea6
implemented serializer/deserializer and added AddedViewInfo structure…
mzorz Jul 3, 2020
9687731
Merge branch 'feature/wp-stories/alpha1-cut' into issue/393-keep-state
mzorz Jul 4, 2020
ce53d6a
added update() method to update AddedViewInfo when it's saved
mzorz Jul 4, 2020
9af1b21
removed custom serializer, fixed bad import preventing View from bein…
mzorz Jul 5, 2020
5531659
using ArrayListSerializer for AddedViewList
mzorz Jul 6, 2020
9d4867c
made changes so added views can be either referenced (rememberd) or r…
mzorz Jul 6, 2020
8065985
added AddedViewTextInfo class to hold information inherent to TextVie…
mzorz Jul 6, 2020
f76a380
fixed lint warnings
mzorz Jul 6, 2020
97cf627
removed commented code line
mzorz Jul 6, 2020
5c8a3d8
clarified comment
mzorz Jul 6, 2020
a12891c
only trigger the texteditor if view is a new addition (not a re-add f…
mzorz Jul 6, 2020
e557194
using the actual calculated value in px for fontSize
mzorz Jul 6, 2020
f98e5bd
modified test log comment
mzorz Jul 6, 2020
402b9ba
renamed method
mzorz Jul 6, 2020
ef642bb
updated proguard rules to keep serializer classes
mzorz Jul 7, 2020
6ee2f54
removed test code
mzorz Jul 7, 2020
53c04cf
removed unused imports
mzorz Jul 7, 2020
3713a9b
renamed param
mzorz Jul 8, 2020
aed3634
renamed variable
mzorz Jul 17, 2020
8e84597
simplified fun expression with assignment
mzorz Jul 17, 2020
4492f53
renamed iterator temporal variable name for clarity
mzorz Jul 17, 2020
7a65da2
returning assignment in when statement itself
mzorz Jul 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

buildscript {
ext.kotlinVersion = '1.3.61'
ext.serializationVersion = '0.14.0'
repositories {
google()
jcenter()
Expand All @@ -10,6 +11,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
classpath 'com.automattic.android:fetchstyle:1.1'
classpath 'io.sentry:sentry-android-gradle-plugin:1.7.27'
// NOTE: Do not place your application dependencies here; they belong
Expand Down
2 changes: 2 additions & 0 deletions photoeditor/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlinx-serialization'

android {
compileSdkVersion rootProject.compileSdkVersion
Expand Down Expand Up @@ -36,6 +37,7 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion"

implementation "androidx.appcompat:appcompat:$appCompatVersion"
implementation "androidx.core:core-ktx:$coreVersion"
Expand Down
9 changes: 9 additions & 0 deletions photoeditor/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keepattributes *Annotation*, InnerClasses
-dontnote kotlinx.serialization.SerializationKt
-keep,includedescriptorclasses class com.automattic.photoeditor.**$$serializer { *; } # <-- change package name to your app's
-keepclassmembers class com.automattic.photoeditor.** { # <-- change package name to your app's
*** Companion;
}
-keepclasseswithmembers class com.automattic.photoeditor.** { # <-- change package name to your app's
kotlinx.serialization.KSerializer serializer(...);
}
109 changes: 85 additions & 24 deletions photoeditor/src/main/java/com/automattic/photoeditor/PhotoEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import com.automattic.photoeditor.views.ViewType
import com.automattic.photoeditor.views.ViewType.EMOJI
import com.automattic.photoeditor.views.ViewType.TEXT
import com.automattic.photoeditor.views.added.AddedView
import com.automattic.photoeditor.views.added.AddedViewInfo
import com.automattic.photoeditor.views.added.AddedViewList
import com.automattic.photoeditor.views.brush.BrushDrawingView
import com.automattic.photoeditor.views.brush.BrushViewChangeListener
Expand All @@ -52,8 +53,8 @@ import kotlinx.android.synthetic.main.view_photo_editor_emoji.view.*
import kotlinx.android.synthetic.main.view_photo_editor_text.view.*
import java.io.File
import java.io.FileInputStream
import java.util.ArrayList
import java.lang.ref.WeakReference
import java.util.ArrayList

/**
*
Expand Down Expand Up @@ -233,9 +234,16 @@ class PhotoEditor private constructor(builder: Builder) :
* @param colorCodeTextView text color to be displayed
*/
@SuppressLint("ClickableViewAccessibility")
fun addText(text: String, colorCodeTextView: Int, textTypeface: Typeface? = null, fontSizeSp: Float = 18f) {
fun addText(
jd-alexander marked this conversation as resolved.
Show resolved Hide resolved
text: String,
colorCodeTextView: Int,
textTypeface: Typeface? = null,
fontSizeSp: Float = 18f,
isViewReadd: Boolean = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be isViewReady? Not sure. Just checking :)

Suggested change
isViewReadd: Boolean = false
isViewReady: Boolean = false

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's intended - is this view being re-added.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay understood. I get it now. Do you think it could be renamed to isViewBeingReadded? LMK. because at first glance I thought it was a typo 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure thing! done in 3713a9b :)

): View? {
brushDrawingView.brushDrawingMode = false
getLayout(ViewType.TEXT)?.apply {
val view: View?
view = getLayout(ViewType.TEXT)?.apply {
val textInputTv = findViewById<TextView>(R.id.tvPhotoEditorText)

textInputTv.text = text
Expand All @@ -262,13 +270,14 @@ class PhotoEditor private constructor(builder: Builder) :
setOnTouchListener(multiTouchListenerInstance)
addViewToParent(this, ViewType.TEXT)

// now open TextEditor right away
if (mOnPhotoEditorListener != null) {
// now open TextEditor right away if this is new text being added
if (mOnPhotoEditorListener != null && !isViewReadd) {
val textInput = textInputTv.text.toString()
val currentTextColor = textInputTv.currentTextColor
mOnPhotoEditorListener?.onEditTextChangeListener(this, textInput, currentTextColor, true)
}
}
return view
}

/**
Expand Down Expand Up @@ -300,7 +309,9 @@ class PhotoEditor private constructor(builder: Builder) :
inputTextView.setTextColor(colorCode)
parentView.updateViewLayout(view, view.layoutParams)
val i = addedViews.indexOfView(view)
if (i > -1) addedViews[i] = AddedView(view, addedViews[i].viewType)
if (i > -1) {
addedViews[i] = AddedView.buildAddedViewFromView(view, addedViews[i].viewType)
}
}
}

Expand All @@ -310,8 +321,8 @@ class PhotoEditor private constructor(builder: Builder) :
*
* @param emojiName unicode in form of string to display emoji
*/
fun addEmoji(emojiName: String) {
addEmoji(null, emojiName)
fun addEmoji(emojiName: String): View? {
return addEmoji(null, emojiName)
}

/**
Expand All @@ -321,9 +332,10 @@ class PhotoEditor private constructor(builder: Builder) :
* @param emojiTypeface typeface for custom font to show emoji unicode in specific font
* @param emojiName unicode in form of string to display emoji
*/
fun addEmoji(emojiTypeface: Typeface?, emojiName: String) {
fun addEmoji(emojiTypeface: Typeface?, emojiName: String): View? {
brushDrawingView.brushDrawingMode = false
getLayout(ViewType.EMOJI)?.apply {
val view = getLayout(ViewType.EMOJI)
view?.apply {
val emojiTextView = findViewById<TextView>(R.id.tvPhotoEditorEmoji)

if (emojiTypeface != null) {
Expand Down Expand Up @@ -366,6 +378,7 @@ class PhotoEditor private constructor(builder: Builder) :
// setOnTouchListener(multiTouchListenerInstance)
addViewToParent(this, ViewType.EMOJI)
}
return view
}

/**
Expand All @@ -379,11 +392,55 @@ class PhotoEditor private constructor(builder: Builder) :
)
params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
parentView.addView(rootView, params)
addedViews.add(AddedView(rootView, viewType, sourceUri))
addedViews.add(AddedView.buildAddedViewFromView(rootView, viewType, sourceUri))
mOnPhotoEditorListener?.onAddViewListener(viewType, addedViews.size)
}

fun addViewToParentWithTouchListener(rootView: View, viewType: ViewType, sourceUri: Uri? = null) {
fun addViewToParentWithTouchListener(addedView: AddedView) {
addedView.view?.let {
addViewToParentWithTouchListener(it, addedView.viewType, addedView.uri)
} ?: buildViewFromAddedViewInfo(addedView.viewInfo, addedView.viewType)
}

private fun buildViewFromAddedViewInfo(addedViewInfo: AddedViewInfo, viewType: ViewType): View? {
var view: View? = null
when (viewType) {
EMOJI -> {
// create emoji view layout
view = addEmoji(addedViewInfo.addedViewTextInfo.text)
// apply specific TextView parameters for emoji (fontsize)
val emojiTextView = view?.findViewById<TextView>(R.id.tvPhotoEditorEmoji)
// the actual calculated text size as obtained from the view is expressed in px.
emojiTextView?.setTextSize(TypedValue.COMPLEX_UNIT_PX, addedViewInfo.addedViewTextInfo.fontSizePx)
}
TEXT -> {
// create TEXT view layout
view = addText(
text = addedViewInfo.addedViewTextInfo.text,
colorCodeTextView = addedViewInfo.addedViewTextInfo.textColor,
isViewReadd = true
)
// apply specific TextView parameters for text (fontsize, text color)
val normalTextView = view?.findViewById<TextView>(R.id.tvPhotoEditorText)
// the actual calculated text size as obtained from the view is expressed in px.
normalTextView?.setTextSize(TypedValue.COMPLEX_UNIT_PX, addedViewInfo.addedViewTextInfo.fontSizePx)
normalTextView?.setTextColor(addedViewInfo.addedViewTextInfo.textColor)
}
}

// now apply all common parameters to newly created view object
view?.let {
it.rotation = addedViewInfo.rotation
it.translationX = addedViewInfo.translationX
it.translationY = addedViewInfo.translationY
it.scaleX = addedViewInfo.scale
it.scaleY = addedViewInfo.scale
}

return view
}

private fun addViewToParentWithTouchListener(rootView: View, viewType: ViewType, sourceUri: Uri? = null) {
val multiTouchListenerInstance = getNewMultitouchListener(rootView) // newMultiTouchListener
when {
viewType == EMOJI -> {
Expand Down Expand Up @@ -544,7 +601,7 @@ class PhotoEditor private constructor(builder: Builder) :
redoViews.add(removeView)
}
mOnPhotoEditorListener?.onRemoveViewListener(addedViews.size)
val viewTag = removeView.view.tag
val viewTag = removeView.view?.tag
(viewTag as? ViewType)?.let {
mOnPhotoEditorListener?.onRemoveViewListener(it, addedViews.size)
}
Expand All @@ -567,7 +624,7 @@ class PhotoEditor private constructor(builder: Builder) :
parentView.addView(redoView.view)
addedViews.add(redoView)
}
val viewTag = redoView.view.tag
val viewTag = redoView.view?.tag
if (viewTag != null && viewTag is ViewType) {
mOnPhotoEditorListener?.onAddViewListener(viewTag, addedViews.size)
}
Expand All @@ -585,7 +642,9 @@ class PhotoEditor private constructor(builder: Builder) :
*/
fun clearAllViews() {
for (addedView in addedViews) {
parentView.removeView(addedView.view)
addedView.view?.let {
parentView.removeView(it)
}
}

if (addedViews.containsView(brushDrawingView)) {
Expand Down Expand Up @@ -735,9 +794,9 @@ class PhotoEditor private constructor(builder: Builder) :
val viewPositionInfo = ViewPositionInfo(
originalCanvasWidth,
originalCanvasHeight,
v.view.width,
v.view.height,
v.view.matrix
requireNotNull(v.view).width,
jd-alexander marked this conversation as resolved.
Show resolved Hide resolved
requireNotNull(v.view).height,
requireNotNull(v.view).matrix
)
when (v.viewType) {
ViewType.STICKER_ANIMATED -> {
Expand Down Expand Up @@ -887,9 +946,9 @@ class PhotoEditor private constructor(builder: Builder) :
val viewPositionInfo = ViewPositionInfo(
widthParent,
heightParent,
v.view.width,
v.view.height,
v.view.matrix
requireNotNull(v.view).width,
requireNotNull(v.view).height,
requireNotNull(v.view).matrix
)
when (v.viewType) {
ViewType.STICKER_ANIMATED -> {
Expand Down Expand Up @@ -975,15 +1034,17 @@ class PhotoEditor private constructor(builder: Builder) :
if (redoViews.size > 0) {
redoViews.removeAt(redoViews.size - 1)
}
addedViews.add(AddedView(brushDrawingView, ViewType.BRUSH_DRAWING))
addedViews.add(AddedView.buildAddedViewFromView(brushDrawingView, ViewType.BRUSH_DRAWING))
mOnPhotoEditorListener?.onAddViewListener(ViewType.BRUSH_DRAWING, addedViews.size)
}

override fun onViewRemoved(brushDrawingView: BrushDrawingView) {
if (addedViews.size > 0) {
val removeView = addedViews.removeAt(addedViews.size - 1)
if (removeView.view !is BrushDrawingView) {
parentView.removeView(removeView.view)
removeView.view?.let {
if (it !is BrushDrawingView) {
parentView.removeView(it)
}
}
redoViews.add(removeView)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.automattic.photoeditor.views

import kotlinx.serialization.Serializable

/**
*
*
Expand All @@ -10,6 +12,7 @@ package com.automattic.photoeditor.views
* @version 0.1.1
* @since 18/01/2017.
*/
@Serializable
enum class ViewType {
BRUSH_DRAWING,
TEXT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,91 @@ package com.automattic.photoeditor.views.added

import android.net.Uri
import android.view.View
import android.widget.TextView
import com.automattic.photoeditor.R
import com.automattic.photoeditor.views.ViewType
import com.automattic.photoeditor.views.ViewType.EMOJI
import com.automattic.photoeditor.views.ViewType.TEXT
import kotlinx.serialization.Transient
import kotlinx.serialization.Decoder
import kotlinx.serialization.Encoder
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer

class AddedView(val view: View, val viewType: ViewType, val uri: Uri? = null)
@Serializable
class AddedView(
@Transient val view: View? = null,
val viewType: ViewType,
var viewInfo: AddedViewInfo,
@Serializable(with = UriSerializer::class)
val uri: Uri? = null
) {
companion object {
fun buildAddedViewFromView(
view: View,
viewType: ViewType,
uri: Uri? = null
): AddedView {
return AddedView(
view,
viewType,
buildViewInfoFromView(
view,
getTextInfoFromActualView(view, viewType)
),
uri
)
}

fun getTextInfoFromActualView(view: View, viewType: ViewType): AddedViewTextInfo {
val txtView: TextView
when (viewType) {
EMOJI -> {
txtView = view.findViewById(R.id.tvPhotoEditorEmoji)
}
TEXT -> {
txtView = view.findViewById(R.id.tvPhotoEditorText)
}
else -> {
// default text
txtView = view.findViewById(R.id.tvPhotoEditorText)
}
}
jd-alexander marked this conversation as resolved.
Show resolved Hide resolved
jd-alexander marked this conversation as resolved.
Show resolved Hide resolved
return AddedViewTextInfo(txtView.text.toString(), txtView.textSize, txtView.currentTextColor)
}

fun buildViewInfoFromView(view: View, addedViewText: AddedViewTextInfo): AddedViewInfo {
return AddedViewInfo(
view.rotation,
view.translationX,
view.translationY,
view.scaleX,
addedViewText
)
}
}

fun update() {
view?.let {
viewInfo = AddedViewInfo(
it.rotation,
it.translationX,
it.translationY,
it.scaleX,
getTextInfoFromActualView(view, viewType)
)
}
}

@Serializer(forClass = Uri::class)
object UriSerializer : KSerializer<Uri> {
override fun deserialize(input: Decoder): Uri {
return Uri.parse(input.decodeString())
}

override fun serialize(output: Encoder, obj: Uri) {
output.encodeString(obj.toString())
}
}
}
Loading