Minor UI improvements

- added outbox label
- notification is now always removed when on main activity
- send status is now shown in message list and detail view
This commit is contained in:
2016-10-27 17:37:34 +02:00
parent 7332886786
commit e249c86b79
18 changed files with 246 additions and 51 deletions

View File

@ -22,6 +22,7 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
@ -101,10 +102,11 @@ public class AddressDetailFragment extends Fragment {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.address, menu);
Drawables.addIcon(getActivity(), menu, R.id.write_message, GoogleMaterial.Icon.gmd_mail);
Drawables.addIcon(getActivity(), menu, R.id.share, GoogleMaterial.Icon.gmd_share);
Drawables.addIcon(getActivity(), menu, R.id.delete, GoogleMaterial.Icon.gmd_delete);
Drawables.addIcon(getActivity(), menu, R.id.export,
FragmentActivity activity = getActivity();
Drawables.addIcon(activity, menu, R.id.write_message, GoogleMaterial.Icon.gmd_mail);
Drawables.addIcon(activity, menu, R.id.share, GoogleMaterial.Icon.gmd_share);
Drawables.addIcon(activity, menu, R.id.delete, GoogleMaterial.Icon.gmd_delete);
Drawables.addIcon(activity, menu, R.id.export,
CommunityMaterial.Icon.cmd_export)
.setVisible(item != null && item.getPrivateKey() != null);
@ -185,6 +187,17 @@ public class AddressDetailFragment extends Fragment {
// Show the dummy content as text in a TextView.
if (item != null) {
FragmentActivity activity = getActivity();
if (item.isChan()) {
activity.setTitle(R.string.title_chan_detail);
} else if (item.getPrivateKey() != null) {
activity.setTitle(R.string.title_identity_detail);
} else if (item.isSubscribed()) {
activity.setTitle(R.string.title_subscription_detail);
} else {
activity.setTitle(R.string.title_contact_detail);
}
((ImageView) rootView.findViewById(R.id.avatar)).setImageDrawable(new Identicon(item));
TextView name = (TextView) rootView.findViewById(R.id.name);
name.setText(item.toString());
@ -207,8 +220,8 @@ public class AddressDetailFragment extends Fragment {
TextView address = (TextView) rootView.findViewById(R.id.address);
address.setText(item.getAddress());
address.setSelected(true);
((TextView) rootView.findViewById(R.id.stream_number)).setText(getActivity()
.getString(R.string.stream_number, item.getStream()));
((TextView) rootView.findViewById(R.id.stream_number)).setText(
getString(R.string.stream_number, item.getStream()));
if (item.getPrivateKey() == null) {
Switch active = (Switch) rootView.findViewById(R.id.active);
active.setChecked(item.isSubscribed());

View File

@ -93,13 +93,14 @@ public class AddressListFragment extends AbstractItemListFragment<BitmessageAddr
convertView = inflater.inflate(R.layout.subscription_row, parent, false);
}
BitmessageAddress item = getItem(position);
assert item != null;
((ImageView) convertView.findViewById(R.id.avatar)).setImageDrawable(new
Identicon(item));
TextView name = (TextView) convertView.findViewById(R.id.name);
name.setText(item.toString());
TextView streamNumber = (TextView) convertView.findViewById(R.id.stream_number);
streamNumber.setText(getContext().getString(R.string.stream_number, item
.getStream()));
streamNumber.setText(getContext().getString(R.string.stream_number,
item.getStream()));
convertView.findViewById(R.id.subscribed).setVisibility(item.isSubscribed() ?
View.VISIBLE : View.INVISIBLE);
return convertView;

View File

@ -37,7 +37,7 @@ public class Identicon extends Drawable {
private final boolean chan;
private final TextPaint textPaint;
public Identicon(BitmessageAddress input) {
public Identicon(@NonNull BitmessageAddress input) {
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);

View File

@ -151,8 +151,6 @@ public class MainActivity extends AppCompatActivity
createDrawer(toolbar, labels);
Singleton.getMessageListener(this).resetNotification();
// handle intents
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_SHOW_MESSAGE)) {
@ -283,7 +281,8 @@ public class MainActivity extends AppCompatActivity
.withName(label.toString())
.withTag(label);
if (label.getType() == null) {
item.withIcon(CommunityMaterial.Icon.cmd_label);
item.withIcon(CommunityMaterial.Icon.cmd_label)
.withIconColor(label.getColor());
} else {
switch (label.getType()) {
case INBOX:
@ -292,6 +291,9 @@ public class MainActivity extends AppCompatActivity
case DRAFT:
item.withIcon(CommunityMaterial.Icon.cmd_file);
break;
case OUTBOX:
item.withIcon(CommunityMaterial.Icon.cmd_outbox);
break;
case SENT:
item.withIcon(CommunityMaterial.Icon.cmd_send);
break;
@ -386,6 +388,7 @@ public class MainActivity extends AppCompatActivity
protected void onResume() {
updateUnread();
updateNodeSwitch();
Singleton.getMessageListener(this).resetNotification();
super.onResume();
}
@ -397,13 +400,10 @@ public class MainActivity extends AppCompatActivity
.withEmail(identity.getAddress())
.withTag(identity);
if (accountHeader.getProfiles() != null) {
// we know that there are 2 setting
// elements.
// we know that there are 2 setting elements.
// Set the new profile above them ;)
accountHeader.addProfile(
newProfile, accountHeader
.getProfiles().size()
- 2);
newProfile, accountHeader.getProfiles().size() - 2);
} else {
accountHeader.addProfiles(newProfile);
}

View File

@ -34,6 +34,7 @@ import java.util.Iterator;
import ch.dissem.apps.abit.listener.ActionBarListener;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.apps.abit.util.Assets;
import ch.dissem.apps.abit.util.Drawables;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
@ -92,9 +93,12 @@ public class MessageDetailFragment extends Fragment {
// Show the dummy content as text in a TextView.
if (item != null) {
((TextView) rootView.findViewById(R.id.subject)).setText(item.getSubject());
ImageView status = (ImageView) rootView.findViewById(R.id.status);
status.setImageResource(Assets.getStatusDrawable(item.getStatus()));
status.setContentDescription(getString(Assets.getStatusString(item.getStatus())));
BitmessageAddress sender = item.getFrom();
((ImageView) rootView.findViewById(R.id.avatar)).setImageDrawable(new Identicon
(sender));
((ImageView) rootView.findViewById(R.id.avatar))
.setImageDrawable(new Identicon(sender));
((TextView) rootView.findViewById(R.id.sender)).setText(sender.toString());
if (item.getTo() != null) {
((TextView) rootView.findViewById(R.id.recipient)).setText(item.getTo().toString());

View File

@ -41,6 +41,7 @@ import java.util.List;
import ch.dissem.apps.abit.Identicon;
import ch.dissem.apps.abit.R;
import ch.dissem.apps.abit.util.Assets;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.Label;
@ -82,6 +83,7 @@ public class SwipeableMessageAdapter
static class ViewHolder extends AbstractSwipeableItemViewHolder {
public final FrameLayout container;
public final ImageView avatar;
public final ImageView status;
public final TextView sender;
public final TextView subject;
public final TextView extract;
@ -90,6 +92,7 @@ public class SwipeableMessageAdapter
super(v);
container = (FrameLayout) v.findViewById(R.id.container);
avatar = (ImageView) v.findViewById(R.id.avatar);
status = (ImageView) v.findViewById(R.id.status);
sender = (TextView) v.findViewById(R.id.sender);
subject = (TextView) v.findViewById(R.id.subject);
extract = (TextView) v.findViewById(R.id.text);
@ -164,6 +167,9 @@ public class SwipeableMessageAdapter
// set data
holder.avatar.setImageDrawable(new Identicon(item.getFrom()));
holder.status.setImageResource(Assets.getStatusDrawable(item.getStatus()));
holder.status.setContentDescription(
holder.status.getContext().getString(Assets.getStatusString(item.getStatus())));
holder.sender.setText(item.getFrom().toString());
holder.subject.setText(normalizeWhitespaces(item.getSubject()));
holder.extract.setText(normalizeWhitespaces(item.getText()));

View File

@ -20,6 +20,8 @@ import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import ch.dissem.apps.abit.MainActivity;
import ch.dissem.apps.abit.notification.NewMessageNotification;
@ -38,6 +40,7 @@ public class MessageListener implements BitmessageContext.Listener {
private final Deque<Plaintext> unacknowledged = new LinkedList<>();
private int numberOfUnacknowledgedMessages = 0;
private final NewMessageNotification notification;
private final ExecutorService pool = Executors.newSingleThreadExecutor();
public MessageListener(Context ctx) {
this.notification = new NewMessageNotification(ctx);
@ -45,33 +48,32 @@ public class MessageListener implements BitmessageContext.Listener {
@Override
public void receive(final Plaintext plaintext) {
synchronized (unacknowledged) {
pool.submit(() -> {
unacknowledged.addFirst(plaintext);
numberOfUnacknowledgedMessages++;
if (unacknowledged.size() > 5) {
unacknowledged.removeLast();
}
}
if (numberOfUnacknowledgedMessages == 1) {
notification.singleNotification(plaintext);
} else {
notification.multiNotification(unacknowledged, numberOfUnacknowledgedMessages);
}
notification.show();
if (numberOfUnacknowledgedMessages == 1) {
notification.singleNotification(plaintext);
} else {
notification.multiNotification(unacknowledged, numberOfUnacknowledgedMessages);
}
notification.show();
// If MainActivity is shown, update the sidebar badges
MainActivity main = MainActivity.getInstance();
if (main != null) {
main.updateUnread();
}
// If MainActivity is shown, update the sidebar badges
MainActivity main = MainActivity.getInstance();
if (main != null) {
main.updateUnread();
}
});
}
public void resetNotification() {
notification.hide();
synchronized (unacknowledged) {
pool.submit(() -> {
notification.hide();
unacknowledged.clear();
numberOfUnacknowledgedMessages = 0;
}
});
}
}

View File

@ -123,6 +123,9 @@ public class AndroidMessageRepository extends AbstractMessageRepository {
case DRAFT:
text = context.getString(R.string.draft);
break;
case OUTBOX:
text = context.getString(R.string.outbox);
break;
case SENT:
text = context.getString(R.string.sent);
break;
@ -197,7 +200,7 @@ public class AndroidMessageRepository extends AbstractMessageRepository {
TABLE_NAME, projection,
where,
null, null, null,
COLUMN_RECEIVED + " DESC"
COLUMN_RECEIVED + " DESC, " + COLUMN_SENT + " DESC"
)) {
while (c.moveToNext()) {
byte[] iv = c.getBlob(c.getColumnIndex(COLUMN_IV));

View File

@ -27,7 +27,7 @@ import ch.dissem.apps.abit.util.Assets;
*/
public class SqlHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
private static final int DATABASE_VERSION = 5;
private static final int DATABASE_VERSION = 6;
private static final String DATABASE_NAME = "jabit.db";
private final Context ctx;
@ -59,6 +59,8 @@ public class SqlHelper extends SQLiteOpenHelper {
executeMigration(db, "V3.2__Update_table_message");
case 4:
executeMigration(db, "V3.3__Create_table_node");
case 5:
executeMigration(db, "V3.4__Add_label_outbox");
default:
// Nothing to do. Let's assume we won't upgrade from a version that's newer than
// DATABASE_VERSION.

View File

@ -17,6 +17,8 @@
package ch.dissem.apps.abit.util;
import android.content.Context;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import java.io.IOException;
import java.io.InputStream;
@ -24,6 +26,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import ch.dissem.apps.abit.R;
import ch.dissem.bitmessage.entity.Plaintext;
/**
* Helper class to work with Assets.
*/
@ -44,4 +49,44 @@ public class Assets {
throw new RuntimeException(e);
}
}
@DrawableRes
public static int getStatusDrawable(Plaintext.Status status) {
switch (status) {
case RECEIVED:
return 0;
case DRAFT:
return R.drawable.draft;
case PUBKEY_REQUESTED:
return R.drawable.public_key;
case DOING_PROOF_OF_WORK:
return R.drawable.ic_notification_proof_of_work;
case SENT:
return R.drawable.sent;
case SENT_ACKNOWLEDGED:
return R.drawable.sent_acknowledged;
default:
return 0;
}
}
@StringRes
public static int getStatusString(Plaintext.Status status) {
switch (status) {
case RECEIVED:
return R.string.status_received;
case DRAFT:
return R.string.status_draft;
case PUBKEY_REQUESTED:
return R.string.status_public_key;
case DOING_PROOF_OF_WORK:
return R.string.proof_of_work_title;
case SENT:
return R.string.status_sent;
case SENT_ACKNOWLEDGED:
return R.string.status_sent_acknowledged;
default:
return 0;
}
}
}