🔃 Switch showcase library

Which, unfortunately, pulls along a lot of other
changes (mostly for the better)
This commit is contained in:
Christian Basler 2018-05-23 19:04:27 +02:00
parent 60c4a4d8a0
commit 0b432b6a67
12 changed files with 107 additions and 176 deletions

View File

@ -54,11 +54,11 @@ android {
//ext.jabitVersion = '2.0.4' //ext.jabitVersion = '2.0.4'
ext.jabitVersion = 'feature-refactoring-SNAPSHOT' ext.jabitVersion = 'feature-refactoring-SNAPSHOT'
ext.supportVersion = '27.1.0' ext.supportVersion = '27.1.1'
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.anko:anko:$anko_version" implementation "org.jetbrains.anko:anko:$anko_version"
@ -96,12 +96,12 @@ dependencies {
implementation 'com.google.zxing:core:3.3.2' implementation 'com.google.zxing:core:3.3.2'
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.0' implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.0'
implementation 'com.github.amlcurran.showcaseview:library:5.4.3' implementation 'com.github.deano2390:MaterialShowcaseView:1.2.0@aar'
implementation('com.github.h6ah4i:android-advancedrecyclerview:0.11.0@aar') { implementation('com.github.h6ah4i:android-advancedrecyclerview:0.11.0@aar') {
transitive = true transitive = true
} }
implementation 'com.github.angads25:filepicker:1.1.1' implementation 'com.github.angads25:filepicker:1.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.15.0' testImplementation 'org.mockito:mockito-core:2.15.0'

View File

@ -16,22 +16,14 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.content.Context
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.* import android.view.*
import android.widget.ImageView
import android.widget.TextView
import ch.dissem.apps.abit.adapter.ConversationAdapter import ch.dissem.apps.abit.adapter.ConversationAdapter
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.util.Drawables import ch.dissem.apps.abit.util.Drawables
import ch.dissem.apps.abit.util.Strings.prepareMessageExtract
import ch.dissem.apps.abit.util.getDrawable
import ch.dissem.bitmessage.entity.Conversation import ch.dissem.bitmessage.entity.Conversation
import ch.dissem.bitmessage.entity.Plaintext
import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.google_material_typeface_library.GoogleMaterial
import kotlinx.android.synthetic.main.fragment_conversation_detail.* import kotlinx.android.synthetic.main.fragment_conversation_detail.*
@ -78,7 +70,8 @@ class ConversationDetailFragment : Fragment() {
item?.let { item -> item?.let { item ->
subject.text = item.subject subject.text = item.subject
avatar.setImageDrawable(MultiIdenticon(item.participants)) avatar.setImageDrawable(MultiIdenticon(item.participants))
messages.adapter = ConversationAdapter(ctx, this@ConversationDetailFragment, item) messages.adapter =
ConversationAdapter(ctx, this@ConversationDetailFragment, item, Singleton.currentLabel.value)
messages.layoutManager = LinearLayoutManager(activity) messages.layoutManager = LinearLayoutManager(activity)
} }
} }
@ -122,61 +115,6 @@ class ConversationDetailFragment : Fragment() {
return false return false
} }
private class RelatedMessageAdapter internal constructor(
private val ctx: Context,
private val messages: List<Plaintext>
) : RecyclerView.Adapter<RelatedMessageAdapter.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): RelatedMessageAdapter.ViewHolder {
val context = parent.context
val inflater = LayoutInflater.from(context)
// Inflate the custom layout
val contactView = inflater.inflate(R.layout.item_message_minimized, parent, false)
// Return a new holder instance
return ViewHolder(contactView)
}
// Involves populating data into the item through holder
override fun onBindViewHolder(viewHolder: RelatedMessageAdapter.ViewHolder, position: Int) {
// Get the data model based on position
val message = messages[position]
viewHolder.avatar.setImageDrawable(Identicon(message.from))
viewHolder.status.setImageResource(message.status.getDrawable())
viewHolder.sender.text = message.from.toString()
viewHolder.extract.text = prepareMessageExtract(message.text)
viewHolder.item = message
}
// Returns the total count of items in the list
override fun getItemCount() = messages.size
internal inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal val avatar = itemView.findViewById<ImageView>(R.id.avatar)
internal val status = itemView.findViewById<ImageView>(R.id.status)
internal val sender = itemView.findViewById<TextView>(R.id.sender)
internal val extract = itemView.findViewById<TextView>(R.id.text)
internal var item: Plaintext? = null
init {
itemView.setOnClickListener {
if (ctx is MainActivity) {
item?.let { ctx.onItemSelected(it) }
} else {
val detailIntent = Intent(ctx, MessageDetailActivity::class.java)
detailIntent.putExtra(MessageDetailFragment.ARG_ITEM, item)
ctx.startActivity(detailIntent)
}
}
}
}
}
companion object { companion object {
/** /**
* The fragment argument representing the item ID that this fragment * The fragment argument representing the item ID that this fragment

View File

@ -17,15 +17,14 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.content.Intent import android.content.Intent
import android.graphics.Point import android.graphics.Canvas
import android.graphics.Paint
import android.os.Bundle import android.os.Bundle
import android.support.annotation.DrawableRes import android.support.annotation.DrawableRes
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import ch.dissem.apps.abit.drawer.ProfileImageListener import ch.dissem.apps.abit.drawer.ProfileImageListener
import ch.dissem.apps.abit.drawer.ProfileSelectionListener import ch.dissem.apps.abit.drawer.ProfileSelectionListener
import ch.dissem.apps.abit.listener.ListSelectionListener import ch.dissem.apps.abit.listener.ListSelectionListener
@ -42,7 +41,6 @@ import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.Conversation import ch.dissem.bitmessage.entity.Conversation
import ch.dissem.bitmessage.entity.Plaintext import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.entity.valueobject.Label
import com.github.amlcurran.showcaseview.ShowcaseView
import com.mikepenz.community_material_typeface_library.CommunityMaterial import com.mikepenz.community_material_typeface_library.CommunityMaterial
import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.google_material_typeface_library.GoogleMaterial
import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.IconicsDrawable
@ -59,6 +57,9 @@ import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView
import uk.co.deanwild.materialshowcaseview.shape.Shape
import uk.co.deanwild.materialshowcaseview.target.Target
import java.io.Serializable import java.io.Serializable
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import java.util.*
@ -150,33 +151,33 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
SyncAdapter.stopSync(this) SyncAdapter.stopSync(this)
} }
if (drawer.isDrawerOpen) { if (drawer.isDrawerOpen) {
val lps = RelativeLayout.LayoutParams( MaterialShowcaseView.Builder(this)
ViewGroup .setMaskColour(R.color.colorPrimary)
.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT .setTitleText(R.string.full_node)
).apply { .setContentText(R.string.full_node_description)
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM) .setDismissOnTouch(true)
addRule(RelativeLayout.ALIGN_PARENT_LEFT) .setDismissText(R.string.got_it)
val margin = ((resources.displayMetrics.density * 12) as Number).toInt() .setShape(object : Shape {
setMargins(margin, margin, margin, margin) var w = 0
var h = 0
override fun updateTarget(target: Target) {
w = target.bounds.width()
h = target.bounds.height()
} }
ShowcaseView.Builder(this) override fun getHeight() = h
.withMaterialShowcase()
.setStyle(R.style.CustomShowcaseTheme) override fun draw(canvas: Canvas, paint: Paint, x: Int, y: Int, padding: Int) {
.setContentTitle(R.string.full_node) val r = h.toFloat() / 2
.setContentText(R.string.full_node_description) canvas.drawCircle(x + w / 2 - r * 1.8f, y.toFloat(), r, paint)
.setTarget {
val view = drawer.stickyFooter
val location = IntArray(2)
view.getLocationInWindow(location)
val x = location[0] + 7 * view.width / 8
val y = location[1] + view.height / 2
Point(x, y)
} }
.replaceEndButton(R.layout.showcase_button)
.hideOnTouchOutside() override fun getWidth() = w
.build() })
.setButtonPosition(lps) .setTarget(drawer.stickyFooter)
.setDelay(1000)
.show()
} }
} }

View File

@ -24,11 +24,14 @@ import ch.dissem.bitmessage.ports.MessageRepository
class ConversationAdapter internal constructor( class ConversationAdapter internal constructor(
ctx: Context, ctx: Context,
private val parent: Fragment, private val parent: Fragment,
private val conversation: Conversation conversation: Conversation,
private val label: Label?
) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() { ) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() {
private val messageRepo = Singleton.getMessageRepository(ctx) private val messageRepo = Singleton.getMessageRepository(ctx)
private var filteredMessages = conversation.messages.filter { label == null || it.labels.any { it == label } }
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int
@ -46,7 +49,7 @@ class ConversationAdapter internal constructor(
// Involves populating data into the item through holder // Involves populating data into the item through holder
override fun onBindViewHolder(viewHolder: ConversationAdapter.ViewHolder, position: Int) { override fun onBindViewHolder(viewHolder: ConversationAdapter.ViewHolder, position: Int) {
// Get the data model based on position // Get the data model based on position
val message = conversation.messages[position] val message = filteredMessages[position]
viewHolder.apply { viewHolder.apply {
item = message item = message
@ -83,9 +86,9 @@ class ConversationAdapter internal constructor(
} }
} }
override fun getItemCount() = conversation.messages.size override fun getItemCount() = filteredMessages.size
class ViewHolder( inner class ViewHolder(
itemView: View, itemView: View,
parent: Fragment, parent: Fragment,
messageRepo: MessageRepository messageRepo: MessageRepository
@ -114,9 +117,12 @@ class ConversationAdapter internal constructor(
Singleton.labeler.delete(item) Singleton.labeler.delete(item)
messageRepo.save(item) messageRepo.save(item)
} }
filteredMessages.indexOf(item).let { i ->
filteredMessages -= item
notifyItemRemoved(i)
}
MainActivity.apply { MainActivity.apply {
updateUnread() updateUnread()
onBackPressed()
} }
true true
} }

View File

@ -181,7 +181,7 @@ class SwipeableConversationAdapter(ctx: Context) :
}.map { it.alias ?: labelUnknown }.distinct().joinToString() }.map { it.alias ?: labelUnknown }.distinct().joinToString()
subject.text = prepareMessageExtract(item.subject) subject.text = prepareMessageExtract(item.subject)
extract.text = prepareMessageExtract(item.extract) extract.text = prepareMessageExtract(item.extract)
item.messages.size.let { size -> item.messages.count { it.labels.contains(label) }.let { size ->
if (size <= 1) { if (size <= 1) {
count.text = "" count.text = ""
} else { } else {

View File

@ -1,16 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:orientation="vertical" android:orientation="vertical">
android:paddingBottom="64dp">
<TextView <TextView
android:id="@+id/subject" android:id="@+id/subject"
@ -50,10 +46,8 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/divider" android:layout_below="@+id/divider"
android:animateLayoutChanges="true" android:scrollbarStyle="outsideOverlay"
android:layout_marginLeft="16dp" android:scrollbars="vertical"
android:layout_marginRight="16dp" tools:listitem="@layout/item_message_detail" />
android:layout_marginBottom="16dp"/>
</RelativeLayout> </RelativeLayout>
</ScrollView>

View File

@ -3,6 +3,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:orientation="vertical"> android:orientation="vertical">

View File

@ -15,6 +15,7 @@
--> -->
<resources> <resources>
<dimen name="action_bar_offset">66dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. --> <!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen>

View File

@ -150,4 +150,5 @@ As an alternative you could configure a trusted node in the settings, but as of
<string name="preference_group_experimental">Experimental</string> <string name="preference_group_experimental">Experimental</string>
<string name="preference_group_experimental_summary">Only change if you know what you\'re doing</string> <string name="preference_group_experimental_summary">Only change if you know what you\'re doing</string>
<string name="unknown">Unknown</string> <string name="unknown">Unknown</string>
<string name="ok">OK</string>
</resources> </resources>

View File

@ -8,18 +8,6 @@
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item> <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style> </style>
<style name="CustomShowcaseTheme" parent="ShowcaseView">
<item name="sv_backgroundColor">#eeffc107</item>
<item name="sv_showcaseColor">#ffc107</item>
<item name="sv_buttonText">Hide</item>
<item name="sv_tintButtonColor">false</item>
<item name="sv_titleTextAppearance">@style/CustomTitle</item>
</style>
<style name="CustomTitle" parent="TextAppearance.ShowcaseView.Title">
<item name="android:textColor">@color/colorAccent</item>
</style>
<style name="FixedDialog" parent="Theme.AppCompat.Light.Dialog.MinWidth"> <style name="FixedDialog" parent="Theme.AppCompat.Light.Dialog.MinWidth">
<item name="windowNoTitle">false</item> <item name="windowNoTitle">false</item>
</style> </style>

View File

@ -1,12 +1,12 @@
buildscript { buildscript {
ext.kotlin_version = '1.2.40' ext.kotlin_version = '1.2.41'
ext.anko_version = '0.10.4' ext.anko_version = '0.10.4'
repositories { repositories {
jcenter() jcenter()
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.1' classpath 'com.android.tools.build:gradle:3.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip