Show related messages (parents, replies)
This commit is contained in:
parent
8770575c95
commit
f77bbe1a43
@ -18,8 +18,10 @@ package ch.dissem.apps.abit;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.IdRes;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v7.widget.GridLayoutManager;
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -47,12 +49,14 @@ import ch.dissem.apps.abit.util.Drawables;
|
|||||||
import ch.dissem.apps.abit.util.Labels;
|
import ch.dissem.apps.abit.util.Labels;
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
|
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||||
|
|
||||||
import static android.text.util.Linkify.WEB_URLS;
|
import static android.text.util.Linkify.WEB_URLS;
|
||||||
import static ch.dissem.apps.abit.util.Constants.BITMESSAGE_ADDRESS_PATTERN;
|
import static ch.dissem.apps.abit.util.Constants.BITMESSAGE_ADDRESS_PATTERN;
|
||||||
import static ch.dissem.apps.abit.util.Constants.BITMESSAGE_URL_SCHEMA;
|
import static ch.dissem.apps.abit.util.Constants.BITMESSAGE_URL_SCHEMA;
|
||||||
|
import static ch.dissem.apps.abit.util.Strings.normalizeWhitespaces;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,16 +147,30 @@ public class MessageDetailFragment extends Fragment {
|
|||||||
removed = true;
|
removed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MessageRepository messageRepo = Singleton.getMessageRepository(inflater.getContext());
|
||||||
if (removed) {
|
if (removed) {
|
||||||
if (getActivity() instanceof ActionBarListener) {
|
if (getActivity() instanceof ActionBarListener) {
|
||||||
((ActionBarListener) getActivity()).updateUnread();
|
((ActionBarListener) getActivity()).updateUnread();
|
||||||
}
|
}
|
||||||
Singleton.getMessageRepository(inflater.getContext()).save(item);
|
messageRepo.save(item);
|
||||||
}
|
}
|
||||||
|
List<Plaintext> parents = new ArrayList<>(item.getParents().size());
|
||||||
|
for (InventoryVector parentIV : item.getParents()) {
|
||||||
|
parents.add(messageRepo.getMessage(parentIV));
|
||||||
|
}
|
||||||
|
showRelatedMessages(rootView, R.id.parents, parents);
|
||||||
|
showRelatedMessages(rootView, R.id.responses, messageRepo.findResponses(item));
|
||||||
}
|
}
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showRelatedMessages(View rootView, @IdRes int id, List<Plaintext> messages) {
|
||||||
|
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.parents);
|
||||||
|
RelatedMessageAdapter adapter = new RelatedMessageAdapter(getActivity(), messages);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.message, menu);
|
inflater.inflate(R.menu.message, menu);
|
||||||
@ -211,6 +229,61 @@ public class MessageDetailFragment extends Fragment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class RelatedMessageAdapter extends RecyclerView.Adapter<RelatedMessageAdapter.ViewHolder> {
|
||||||
|
private final List<Plaintext> messages;
|
||||||
|
private final Context ctx;
|
||||||
|
|
||||||
|
private RelatedMessageAdapter(Context ctx, List<Plaintext> messages) {
|
||||||
|
this.messages = messages;
|
||||||
|
this.ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RelatedMessageAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
Context context = parent.getContext();
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
|
||||||
|
// Inflate the custom layout
|
||||||
|
View contactView = inflater.inflate(R.layout.item_message_minimized, parent, false);
|
||||||
|
|
||||||
|
// Return a new holder instance
|
||||||
|
return new RelatedMessageAdapter.ViewHolder(contactView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Involves populating data into the item through holder
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(RelatedMessageAdapter.ViewHolder viewHolder, int position) {
|
||||||
|
// Get the data model based on position
|
||||||
|
Plaintext message = messages.get(position);
|
||||||
|
|
||||||
|
viewHolder.avatar.setImageDrawable(new Identicon(message.getFrom()));
|
||||||
|
viewHolder.status.setImageResource(Assets.getStatusDrawable(message.getStatus()));
|
||||||
|
viewHolder.sender.setText(message.getFrom().toString());
|
||||||
|
viewHolder.extract.setText(normalizeWhitespaces(message.getText()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the total count of items in the list
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return messages.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final ImageView avatar;
|
||||||
|
private final ImageView status;
|
||||||
|
private final TextView sender;
|
||||||
|
private final TextView extract;
|
||||||
|
|
||||||
|
ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
avatar = (ImageView) itemView.findViewById(R.id.avatar);
|
||||||
|
status = (ImageView) itemView.findViewById(R.id.status);
|
||||||
|
sender = (TextView) itemView.findViewById(R.id.sender);
|
||||||
|
extract = (TextView) itemView.findViewById(R.id.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class LabelAdapter extends
|
private static class LabelAdapter extends
|
||||||
RecyclerView.Adapter<LabelAdapter.ViewHolder> {
|
RecyclerView.Adapter<LabelAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import ch.dissem.bitmessage.networking.nio.NioNetworkHandler;
|
|||||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
|
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
|
||||||
|
import ch.dissem.bitmessage.utils.ConversationService;
|
||||||
import ch.dissem.bitmessage.utils.TTL;
|
import ch.dissem.bitmessage.utils.TTL;
|
||||||
|
|
||||||
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
||||||
@ -51,6 +52,7 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
|||||||
*/
|
*/
|
||||||
public class Singleton {
|
public class Singleton {
|
||||||
private static BitmessageContext bitmessageContext;
|
private static BitmessageContext bitmessageContext;
|
||||||
|
private static ConversationService conversationService;
|
||||||
private static MessageListener messageListener;
|
private static MessageListener messageListener;
|
||||||
private static BitmessageAddress identity;
|
private static BitmessageAddress identity;
|
||||||
private static AndroidProofOfWorkRepository powRepo;
|
private static AndroidProofOfWorkRepository powRepo;
|
||||||
@ -160,4 +162,16 @@ public class Singleton {
|
|||||||
throw new IllegalArgumentException("Identity expected, but no private key available");
|
throw new IllegalArgumentException("Identity expected, but no private key available");
|
||||||
Singleton.identity = identity;
|
Singleton.identity = identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ConversationService getConversationService(Context ctx) {
|
||||||
|
if (conversationService == null) {
|
||||||
|
final BitmessageContext bmc = getBitmessageContext(ctx);
|
||||||
|
synchronized (Singleton.class) {
|
||||||
|
if (conversationService == null) {
|
||||||
|
conversationService = new ConversationService(bmc.messages());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return conversationService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
10
app/src/main/res/drawable/border_bottom.xml
Normal file
10
app/src/main/res/drawable/border_bottom.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<item android:top="1dp" android:bottom="1dp">
|
||||||
|
<shape
|
||||||
|
android:shape="rectangle">
|
||||||
|
<stroke android:width="1dp" android:color="#FFDDDDDD" />
|
||||||
|
<solid android:color="#00000000" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
@ -78,12 +78,20 @@
|
|||||||
android:paddingRight="8dp"
|
android:paddingRight="8dp"
|
||||||
tools:text="Recipient" />
|
tools:text="Recipient" />
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/parents"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/avatar"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_below="@+id/avatar"
|
android:layout_below="@+id/parents"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
@ -98,5 +106,13 @@
|
|||||||
android:layout_below="@+id/text"
|
android:layout_below="@+id/text"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginRight="16dp" />
|
android:layout_marginRight="16dp" />
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/responses"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/text"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
64
app/src/main/res/layout/item_message_minimized.xml
Normal file
64
app/src/main/res/layout/item_message_minimized.xml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout 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:background="@drawable/border_bottom">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:src="@color/colorPrimaryDark"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sender"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignTop="@+id/avatar"
|
||||||
|
android:layout_marginTop="-5dp"
|
||||||
|
android:layout_toEndOf="@+id/avatar"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:lines="1"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:paddingTop="0dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="Sender" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_below="@+id/sender"
|
||||||
|
android:layout_toEndOf="@+id/avatar"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:lines="1"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
tools:text="Text" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/status"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignBottom="@id/avatar"
|
||||||
|
android:layout_alignEnd="@+id/avatar"
|
||||||
|
android:layout_marginBottom="-8dp"
|
||||||
|
android:layout_marginEnd="-8dp"
|
||||||
|
android:tint="@color/colorAccent"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:src="@drawable/ic_notification_proof_of_work" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
<!--
|
|
||||||
~ Copyright 2015 Christian Basler
|
~ Copyright 2015 Christian Basler
|
||||||
~
|
~
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -15,8 +14,7 @@
|
|||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -31,11 +29,10 @@
|
|||||||
android:foreground="?attr/selectableItemBackground"
|
android:foreground="?attr/selectableItemBackground"
|
||||||
tools:ignore="UselessParent">
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout
|
||||||
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:background="?attr/selectableItemBackground">
|
||||||
android:background="?attr/selectableItemBackground">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/avatar"
|
android:id="@+id/avatar"
|
||||||
@ -45,7 +42,7 @@
|
|||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
android:src="@color/colorPrimaryDark"
|
android:src="@color/colorPrimaryDark"
|
||||||
tools:ignore="ContentDescription"/>
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/sender"
|
android:id="@+id/sender"
|
||||||
@ -63,8 +60,7 @@
|
|||||||
android:paddingTop="0dp"
|
android:paddingTop="0dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:text="Sender"
|
tools:text="Sender" />
|
||||||
/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/subject"
|
android:id="@+id/subject"
|
||||||
@ -78,7 +74,7 @@
|
|||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
android:paddingRight="8dp"
|
android:paddingRight="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
tools:text="Subject"/>
|
tools:text="Subject" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
@ -94,7 +90,7 @@
|
|||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
android:paddingRight="8dp"
|
android:paddingRight="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
tools:text="Text"/>
|
tools:text="Text" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/status"
|
android:id="@+id/status"
|
||||||
@ -106,7 +102,7 @@
|
|||||||
android:layout_marginEnd="-8dp"
|
android:layout_marginEnd="-8dp"
|
||||||
android:tint="@color/colorAccent"
|
android:tint="@color/colorAccent"
|
||||||
tools:ignore="ContentDescription"
|
tools:ignore="ContentDescription"
|
||||||
tools:src="@drawable/ic_notification_proof_of_work"/>
|
tools:src="@drawable/ic_notification_proof_of_work" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user