diff --git a/app/build.gradle b/app/build.gradle index 330ee5d..ce56baa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -54,11 +54,11 @@ android { //ext.jabitVersion = '2.0.4' ext.jabitVersion = 'feature-refactoring-SNAPSHOT' -ext.supportVersion = '27.1.0' +ext.supportVersion = '27.1.1' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) 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.anko:anko:$anko_version" @@ -96,12 +96,12 @@ dependencies { implementation 'com.google.zxing:core:3.3.2' 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') { transitive = true } 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 'org.mockito:mockito-core:2.15.0' diff --git a/app/src/main/java/ch/dissem/apps/abit/ConversationDetailFragment.kt b/app/src/main/java/ch/dissem/apps/abit/ConversationDetailFragment.kt index 3030c57..87f9cba 100644 --- a/app/src/main/java/ch/dissem/apps/abit/ConversationDetailFragment.kt +++ b/app/src/main/java/ch/dissem/apps/abit/ConversationDetailFragment.kt @@ -16,22 +16,14 @@ package ch.dissem.apps.abit -import android.content.Context -import android.content.Intent import android.os.Bundle import android.support.v4.app.Fragment import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView import android.view.* -import android.widget.ImageView -import android.widget.TextView import ch.dissem.apps.abit.adapter.ConversationAdapter import ch.dissem.apps.abit.service.Singleton 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.Plaintext import com.mikepenz.google_material_typeface_library.GoogleMaterial import kotlinx.android.synthetic.main.fragment_conversation_detail.* @@ -78,7 +70,8 @@ class ConversationDetailFragment : Fragment() { item?.let { item -> subject.text = item.subject 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) } } @@ -122,61 +115,6 @@ class ConversationDetailFragment : Fragment() { return false } - private class RelatedMessageAdapter internal constructor( - private val ctx: Context, - private val messages: List - ) : 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 { /** * The fragment argument representing the item ID that this fragment diff --git a/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt b/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt index 33d1bf5..2ed025f 100644 --- a/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt +++ b/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt @@ -17,15 +17,14 @@ package ch.dissem.apps.abit import android.content.Intent -import android.graphics.Point +import android.graphics.Canvas +import android.graphics.Paint import android.os.Bundle import android.support.annotation.DrawableRes import android.support.v4.app.Fragment import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar 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.ProfileSelectionListener 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.Plaintext import ch.dissem.bitmessage.entity.valueobject.Label -import com.github.amlcurran.showcaseview.ShowcaseView import com.mikepenz.community_material_typeface_library.CommunityMaterial import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.IconicsDrawable @@ -59,6 +57,9 @@ import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu import kotlinx.android.synthetic.main.activity_main.* import org.jetbrains.anko.doAsync 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.lang.ref.WeakReference import java.util.* @@ -150,33 +151,33 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> { SyncAdapter.stopSync(this) } if (drawer.isDrawerOpen) { - val lps = RelativeLayout.LayoutParams( - ViewGroup - .LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - addRule(RelativeLayout.ALIGN_PARENT_BOTTOM) - addRule(RelativeLayout.ALIGN_PARENT_LEFT) - val margin = ((resources.displayMetrics.density * 12) as Number).toInt() - setMargins(margin, margin, margin, margin) - } - - ShowcaseView.Builder(this) - .withMaterialShowcase() - .setStyle(R.style.CustomShowcaseTheme) - .setContentTitle(R.string.full_node) + MaterialShowcaseView.Builder(this) + .setMaskColour(R.color.colorPrimary) + .setTitleText(R.string.full_node) .setContentText(R.string.full_node_description) - .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() - .build() - .setButtonPosition(lps) + .setDismissOnTouch(true) + .setDismissText(R.string.got_it) + .setShape(object : Shape { + var w = 0 + var h = 0 + + override fun updateTarget(target: Target) { + w = target.bounds.width() + h = target.bounds.height() + } + + override fun getHeight() = h + + override fun draw(canvas: Canvas, paint: Paint, x: Int, y: Int, padding: Int) { + val r = h.toFloat() / 2 + canvas.drawCircle(x + w / 2 - r * 1.8f, y.toFloat(), r, paint) + } + + override fun getWidth() = w + }) + .setTarget(drawer.stickyFooter) + .setDelay(1000) + .show() } } diff --git a/app/src/main/java/ch/dissem/apps/abit/adapter/ConversationAdapter.kt b/app/src/main/java/ch/dissem/apps/abit/adapter/ConversationAdapter.kt index c07ec0d..2523365 100644 --- a/app/src/main/java/ch/dissem/apps/abit/adapter/ConversationAdapter.kt +++ b/app/src/main/java/ch/dissem/apps/abit/adapter/ConversationAdapter.kt @@ -24,11 +24,14 @@ import ch.dissem.bitmessage.ports.MessageRepository class ConversationAdapter internal constructor( ctx: Context, private val parent: Fragment, - private val conversation: Conversation + conversation: Conversation, + private val label: Label? ) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() { private val messageRepo = Singleton.getMessageRepository(ctx) + private var filteredMessages = conversation.messages.filter { label == null || it.labels.any { it == label } } + override fun onCreateViewHolder( parent: ViewGroup, viewType: Int @@ -46,7 +49,7 @@ class ConversationAdapter internal constructor( // Involves populating data into the item through holder override fun onBindViewHolder(viewHolder: ConversationAdapter.ViewHolder, position: Int) { // Get the data model based on position - val message = conversation.messages[position] + val message = filteredMessages[position] viewHolder.apply { 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, parent: Fragment, messageRepo: MessageRepository @@ -114,9 +117,12 @@ class ConversationAdapter internal constructor( Singleton.labeler.delete(item) messageRepo.save(item) } + filteredMessages.indexOf(item).let { i -> + filteredMessages -= item + notifyItemRemoved(i) + } MainActivity.apply { updateUnread() - onBackPressed() } true } diff --git a/app/src/main/java/ch/dissem/apps/abit/adapter/SwipeableConversationAdapter.kt b/app/src/main/java/ch/dissem/apps/abit/adapter/SwipeableConversationAdapter.kt index ec2332d..3520fb7 100644 --- a/app/src/main/java/ch/dissem/apps/abit/adapter/SwipeableConversationAdapter.kt +++ b/app/src/main/java/ch/dissem/apps/abit/adapter/SwipeableConversationAdapter.kt @@ -181,7 +181,7 @@ class SwipeableConversationAdapter(ctx: Context) : }.map { it.alias ?: labelUnknown }.distinct().joinToString() subject.text = prepareMessageExtract(item.subject) extract.text = prepareMessageExtract(item.extract) - item.messages.size.let { size -> + item.messages.count { it.labels.contains(label) }.let { size -> if (size <= 1) { count.text = "" } else { diff --git a/app/src/main/res/layout/fragment_conversation_detail.xml b/app/src/main/res/layout/fragment_conversation_detail.xml index 64a8b25..0fb1a5d 100644 --- a/app/src/main/res/layout/fragment_conversation_detail.xml +++ b/app/src/main/res/layout/fragment_conversation_detail.xml @@ -1,59 +1,53 @@ <?xml version="1.0" encoding="utf-8"?> -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent"> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" - <RelativeLayout - android:layout_width="match_parent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:fitsSystemWindows="true" + android:focusableInTouchMode="true" + android:orientation="vertical"> + + <TextView + android:id="@+id/subject" + android:layout_width="0dp" android:layout_height="wrap_content" - android:fitsSystemWindows="true" - android:focusableInTouchMode="true" - android:orientation="vertical" - android:paddingBottom="64dp"> + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" + android:layout_toStartOf="@+id/avatar" + android:elegantTextHeight="false" + android:enabled="false" + android:gravity="center_vertical" + android:padding="16dp" + android:textAppearance="?android:attr/textAppearanceLarge" + tools:ignore="UnusedAttribute" + tools:text="Subject" /> - <TextView - android:id="@+id/subject" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_alignParentStart="true" - android:layout_alignParentTop="true" - android:layout_toStartOf="@+id/avatar" - android:elegantTextHeight="false" - android:enabled="false" - android:gravity="center_vertical" - android:padding="16dp" - android:textAppearance="?android:attr/textAppearanceLarge" - tools:ignore="UnusedAttribute" - tools:text="Subject" /> - - <ImageView - android:id="@+id/avatar" - android:layout_width="40dp" - android:layout_height="40dp" - android:layout_alignParentEnd="true" - android:layout_alignParentTop="true" - android:layout_margin="10dp" - android:src="@color/colorAccent" - tools:ignore="ContentDescription" /> + <ImageView + android:id="@+id/avatar" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_alignParentEnd="true" + android:layout_alignParentTop="true" + android:layout_margin="10dp" + android:src="@color/colorAccent" + tools:ignore="ContentDescription" /> - <View - android:id="@+id/divider" - android:layout_width="fill_parent" - android:layout_height="2dip" - android:layout_below="@id/subject" - android:background="@color/divider" /> + <View + android:id="@+id/divider" + android:layout_width="fill_parent" + android:layout_height="2dip" + android:layout_below="@id/subject" + android:background="@color/divider" /> - <android.support.v7.widget.RecyclerView - android:id="@+id/messages" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_below="@+id/divider" - android:animateLayoutChanges="true" - android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" - android:layout_marginBottom="16dp"/> + <android.support.v7.widget.RecyclerView + android:id="@+id/messages" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/divider" + android:scrollbarStyle="outsideOverlay" + android:scrollbars="vertical" + tools:listitem="@layout/item_message_detail" /> - </RelativeLayout> -</ScrollView> +</RelativeLayout> diff --git a/app/src/main/res/layout/item_message_detail.xml b/app/src/main/res/layout/item_message_detail.xml index 203903b..0c6f5e4 100644 --- a/app/src/main/res/layout/item_message_detail.xml +++ b/app/src/main/res/layout/item_message_detail.xml @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:fitsSystemWindows="true" - android:focusableInTouchMode="true" - android:orientation="vertical"> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:fitsSystemWindows="true" + android:focusableInTouchMode="true" + android:orientation="vertical"> <RelativeLayout android:id="@+id/header" diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 5d61d98..b397dc8 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -15,6 +15,7 @@ --> <resources> + <dimen name="action_bar_offset">66dp</dimen> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d7fe9af..c4cdb65 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -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_summary">Only change if you know what you\'re doing</string> <string name="unknown">Unknown</string> + <string name="ok">OK</string> </resources> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 49a7b0c..2f56be4 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -8,18 +8,6 @@ <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item> </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"> <item name="windowNoTitle">false</item> </style> diff --git a/build.gradle b/build.gradle index 6fca7cf..8aa1c51 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.2.40' + ext.kotlin_version = '1.2.41' ext.anko_version = '0.10.4' repositories { jcenter() google() } 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 'com.github.ben-manes:gradle-versions-plugin:0.17.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cefb6bf..5c92cf6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME 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