Added ongoing notification showing network status
- renamed packages to be more consistent - somewhate refactored the way notifications are made
This commit is contained in:
		| @@ -21,7 +21,7 @@ import android.os.Bundle; | |||||||
| import android.support.v4.app.ListFragment; | import android.support.v4.app.ListFragment; | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.widget.ListView; | import android.widget.ListView; | ||||||
| import ch.dissem.apps.abit.listeners.ListSelectionListener; | import ch.dissem.apps.abit.listener.ListSelectionListener; | ||||||
| import ch.dissem.apps.abit.service.Singleton; | import ch.dissem.apps.abit.service.Singleton; | ||||||
| import ch.dissem.bitmessage.BitmessageContext; | import ch.dissem.bitmessage.BitmessageContext; | ||||||
| import ch.dissem.bitmessage.entity.valueobject.Label; | import ch.dissem.bitmessage.entity.valueobject.Label; | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import android.view.*; | |||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| import ch.dissem.apps.abit.service.Singleton; | import ch.dissem.apps.abit.service.Singleton; | ||||||
| import ch.dissem.apps.abit.utils.Drawables; | import ch.dissem.apps.abit.util.Drawables; | ||||||
| import ch.dissem.bitmessage.BitmessageContext; | import ch.dissem.bitmessage.BitmessageContext; | ||||||
| import ch.dissem.bitmessage.entity.BitmessageAddress; | import ch.dissem.bitmessage.entity.BitmessageAddress; | ||||||
| import ch.dissem.bitmessage.entity.Plaintext; | import ch.dissem.bitmessage.entity.Plaintext; | ||||||
|   | |||||||
| @@ -10,13 +10,13 @@ import android.view.MenuItem; | |||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.widget.AdapterView; | import android.widget.AdapterView; | ||||||
|  |  | ||||||
| import ch.dissem.apps.abit.listeners.ActionBarListener; | import ch.dissem.apps.abit.listener.ActionBarListener; | ||||||
| import ch.dissem.apps.abit.listeners.ListSelectionListener; | import ch.dissem.apps.abit.listener.ListSelectionListener; | ||||||
|  | import ch.dissem.apps.abit.notification.NetworkNotification; | ||||||
| import ch.dissem.apps.abit.service.Singleton; | import ch.dissem.apps.abit.service.Singleton; | ||||||
| import ch.dissem.bitmessage.BitmessageContext; | import ch.dissem.bitmessage.BitmessageContext; | ||||||
| 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.Streamable; |  | ||||||
| import ch.dissem.bitmessage.entity.valueobject.Label; | import ch.dissem.bitmessage.entity.valueobject.Label; | ||||||
|  |  | ||||||
| import com.mikepenz.community_material_typeface_library.CommunityMaterial; | import com.mikepenz.community_material_typeface_library.CommunityMaterial; | ||||||
| @@ -39,6 +39,8 @@ import org.slf4j.LoggerFactory; | |||||||
|  |  | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
|  | import java.util.Timer; | ||||||
|  | import java.util.TimerTask; | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -288,6 +290,7 @@ public class MessageListActivity extends AppCompatActivity | |||||||
|         switch (item.getItemId()) { |         switch (item.getItemId()) { | ||||||
|             case R.id.sync_disabled: |             case R.id.sync_disabled: | ||||||
|                 bmc.startup(); |                 bmc.startup(); | ||||||
|  |                 new NetworkNotification(this).show(); | ||||||
|                 updateMenu(); |                 updateMenu(); | ||||||
|                 return true; |                 return true; | ||||||
|             case R.id.sync_enabled: |             case R.id.sync_enabled: | ||||||
|   | |||||||
| @@ -1,21 +1,15 @@ | |||||||
| package ch.dissem.apps.abit; | package ch.dissem.apps.abit; | ||||||
|  |  | ||||||
| import android.app.Activity; |  | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.graphics.Typeface; | import android.graphics.Typeface; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.support.design.widget.FloatingActionButton; | import android.support.design.widget.FloatingActionButton; | ||||||
| import android.support.v4.app.ListFragment; |  | ||||||
| import android.view.*; | import android.view.*; | ||||||
| import android.widget.ArrayAdapter; | import android.widget.ArrayAdapter; | ||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.ListView; |  | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| import ch.dissem.apps.abit.listeners.ActionBarListener; | import ch.dissem.apps.abit.listener.ActionBarListener; | ||||||
| import ch.dissem.apps.abit.listeners.ListSelectionListener; | import ch.dissem.apps.abit.listener.ListSelectionListener; | ||||||
| import ch.dissem.apps.abit.service.Singleton; |  | ||||||
| import ch.dissem.bitmessage.BitmessageContext; |  | ||||||
| import ch.dissem.bitmessage.entity.BitmessageAddress; |  | ||||||
| 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 ch.dissem.bitmessage.ports.MessageRepository; | import ch.dissem.bitmessage.ports.MessageRepository; | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.listeners; | package ch.dissem.apps.abit.listener; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Created by chris on 06.09.15. |  * Created by chris on 06.09.15. | ||||||
| @@ -14,7 +14,7 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.listeners; | package ch.dissem.apps.abit.listener; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A callback interface that all activities containing this fragment must |  * A callback interface that all activities containing this fragment must | ||||||
| @@ -14,10 +14,9 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.listeners; | package ch.dissem.apps.abit.listener; | ||||||
| 
 | 
 | ||||||
| import android.annotation.TargetApi; | import android.annotation.TargetApi; | ||||||
| import android.app.Notification; |  | ||||||
| import android.app.NotificationManager; | import android.app.NotificationManager; | ||||||
| import android.app.PendingIntent; | import android.app.PendingIntent; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| @@ -34,9 +33,11 @@ import android.text.Spannable; | |||||||
| import android.text.SpannableString; | import android.text.SpannableString; | ||||||
| import android.text.Spanned; | import android.text.Spanned; | ||||||
| import android.text.style.StyleSpan; | import android.text.style.StyleSpan; | ||||||
|  | 
 | ||||||
| import ch.dissem.apps.abit.Identicon; | import ch.dissem.apps.abit.Identicon; | ||||||
| import ch.dissem.apps.abit.MessageListActivity; | import ch.dissem.apps.abit.MessageListActivity; | ||||||
| import ch.dissem.apps.abit.R; | import ch.dissem.apps.abit.R; | ||||||
|  | import ch.dissem.apps.abit.notification.NewMessageNotification; | ||||||
| import ch.dissem.bitmessage.BitmessageContext; | import ch.dissem.bitmessage.BitmessageContext; | ||||||
| import ch.dissem.bitmessage.entity.Plaintext; | import ch.dissem.bitmessage.entity.Plaintext; | ||||||
| 
 | 
 | ||||||
| @@ -50,18 +51,17 @@ import java.util.LinkedList; | |||||||
|  * </p> |  * </p> | ||||||
|  */ |  */ | ||||||
| public class MessageListener implements BitmessageContext.Listener { | public class MessageListener implements BitmessageContext.Listener { | ||||||
|     private static final StyleSpan SPAN_EMPHASIS = new StyleSpan(Typeface.BOLD); |  | ||||||
|     private final Context ctx; |     private final Context ctx; | ||||||
|     private final NotificationManager manager; |     private final NotificationManager manager; | ||||||
|     private final LinkedList<Plaintext> unacknowledged = new LinkedList<>(); |     private final LinkedList<Plaintext> unacknowledged = new LinkedList<>(); | ||||||
|     private final int pictureSize; |  | ||||||
|     private int numberOfUnacknowledgedMessages = 0; |     private int numberOfUnacknowledgedMessages = 0; | ||||||
|  |     private final NewMessageNotification notification; | ||||||
| 
 | 
 | ||||||
|     public MessageListener(Context ctx) { |     public MessageListener(Context ctx) { | ||||||
|         this.ctx = ctx.getApplicationContext(); |         this.ctx = ctx.getApplicationContext(); | ||||||
|         this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); |         this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); | ||||||
| 
 | 
 | ||||||
|         this.pictureSize = getMaxContactPhotoSize(ctx); |         this.notification = new NewMessageNotification(ctx); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) |     @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) | ||||||
| @@ -94,57 +94,15 @@ public class MessageListener implements BitmessageContext.Listener { | |||||||
| 
 | 
 | ||||||
|         NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx); |         NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx); | ||||||
|         if (numberOfUnacknowledgedMessages == 1) { |         if (numberOfUnacknowledgedMessages == 1) { | ||||||
|             Spannable bigText = new SpannableString(plaintext.getSubject() + "\n" + plaintext.getText()); |             notification.singleNotification(plaintext); | ||||||
|             bigText.setSpan(SPAN_EMPHASIS, 0, plaintext.getSubject().length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); |  | ||||||
|             builder.setSmallIcon(R.drawable.ic_notification_new_message) |  | ||||||
|                     .setLargeIcon(toBitmap(new Identicon(plaintext.getFrom()))) |  | ||||||
|                     .setContentTitle(plaintext.getFrom().toString()) |  | ||||||
|                     .setContentText(plaintext.getSubject()) |  | ||||||
|                     .setStyle(new NotificationCompat.BigTextStyle().bigText(bigText)) |  | ||||||
|                     .setContentInfo("Info"); |  | ||||||
| 
 |  | ||||||
|             Intent showMessageIntent = new Intent(ctx, MessageListActivity.class); |  | ||||||
|             showMessageIntent.putExtra(MessageListActivity.EXTRA_SHOW_MESSAGE, plaintext); |  | ||||||
|             PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent, PendingIntent.FLAG_UPDATE_CURRENT); |  | ||||||
|             builder.setContentIntent(pendingIntent); |  | ||||||
| 
 |  | ||||||
|             builder.addAction(R.drawable.ic_action_reply, ctx.getString(R.string.reply), pendingIntent); |  | ||||||
|             builder.addAction(R.drawable.ic_action_delete, ctx.getString(R.string.delete), pendingIntent); |  | ||||||
|         } else { |         } else { | ||||||
|             builder.setSmallIcon(R.drawable.ic_notification_new_message) |             notification.multiNotification(unacknowledged, numberOfUnacknowledgedMessages); | ||||||
|                     .setContentTitle(ctx.getString(R.string.n_new_messages, this.unacknowledged.size())) |  | ||||||
|                     .setContentText(ctx.getString(R.string.app_name)); |  | ||||||
| 
 |  | ||||||
|             NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); |  | ||||||
|             synchronized (unacknowledged) { |  | ||||||
|                 inboxStyle.setBigContentTitle(ctx.getString(R.string.n_new_messages, numberOfUnacknowledgedMessages)); |  | ||||||
|                 for (Plaintext msg : unacknowledged) { |  | ||||||
|                     Spannable sb = new SpannableString(msg.getFrom() + " " + msg.getSubject()); |  | ||||||
|                     sb.setSpan(SPAN_EMPHASIS, 0, String.valueOf(msg.getFrom()).length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); |  | ||||||
|                     inboxStyle.addLine(sb); |  | ||||||
|         } |         } | ||||||
|             } |         notification.show(); | ||||||
|             builder.setStyle(inboxStyle); |  | ||||||
| 
 |  | ||||||
|             Intent intent = new Intent(ctx, MessageListActivity.class); |  | ||||||
|             intent.setAction(MessageListActivity.ACTION_SHOW_INBOX); |  | ||||||
|             PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 1, intent, 0); |  | ||||||
|             builder.setContentIntent(pendingIntent); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         manager.notify(0, builder.build()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private Bitmap toBitmap(Identicon identicon) { |  | ||||||
|         Bitmap bitmap = Bitmap.createBitmap(pictureSize, pictureSize, Bitmap.Config.ARGB_8888); |  | ||||||
|         Canvas canvas = new Canvas(bitmap); |  | ||||||
|         identicon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); |  | ||||||
|         identicon.draw(canvas); |  | ||||||
|         return bitmap; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void resetNotification() { |     public void resetNotification() { | ||||||
|         manager.cancel(0); |         notification.hide(); | ||||||
|         synchronized (unacknowledged) { |         synchronized (unacknowledged) { | ||||||
|             unacknowledged.clear(); |             unacknowledged.clear(); | ||||||
|             numberOfUnacknowledgedMessages = 0; |             numberOfUnacknowledgedMessages = 0; | ||||||
| @@ -0,0 +1,33 @@ | |||||||
|  | package ch.dissem.apps.abit.notification; | ||||||
|  |  | ||||||
|  | import android.app.Notification; | ||||||
|  | import android.app.NotificationManager; | ||||||
|  | import android.content.Context; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Some base class to create and handle notifications. | ||||||
|  |  */ | ||||||
|  | public abstract class AbstractNotification { | ||||||
|  |     protected final Context ctx; | ||||||
|  |     protected final NotificationManager manager; | ||||||
|  |     public Notification notification; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public AbstractNotification(Context ctx) { | ||||||
|  |         this.ctx = ctx; | ||||||
|  |         this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @return an id unique to this notification class | ||||||
|  |      */ | ||||||
|  |     protected abstract int getNotificationId(); | ||||||
|  |  | ||||||
|  |     public void show() { | ||||||
|  |         manager.notify(getNotificationId(), notification); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void hide() { | ||||||
|  |         manager.cancel(getNotificationId()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,87 @@ | |||||||
|  | package ch.dissem.apps.abit.notification; | ||||||
|  |  | ||||||
|  | import android.annotation.SuppressLint; | ||||||
|  | import android.app.PendingIntent; | ||||||
|  | import android.content.Context; | ||||||
|  | import android.content.Intent; | ||||||
|  | import android.support.v7.app.NotificationCompat; | ||||||
|  |  | ||||||
|  | import java.util.Timer; | ||||||
|  | import java.util.TimerTask; | ||||||
|  |  | ||||||
|  | import ch.dissem.apps.abit.MessageListActivity; | ||||||
|  | import ch.dissem.apps.abit.R; | ||||||
|  | import ch.dissem.apps.abit.service.Singleton; | ||||||
|  | import ch.dissem.bitmessage.BitmessageContext; | ||||||
|  | import ch.dissem.bitmessage.utils.Property; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Shows the network status (as long as the client is connected as a full node) | ||||||
|  |  */ | ||||||
|  | public class NetworkNotification extends AbstractNotification { | ||||||
|  |     private final BitmessageContext bmc; | ||||||
|  |     private NotificationCompat.Builder builder; | ||||||
|  |  | ||||||
|  |     public NetworkNotification(Context ctx) { | ||||||
|  |         super(ctx); | ||||||
|  |         builder = new NotificationCompat.Builder(ctx); | ||||||
|  |         builder.setSmallIcon(R.drawable.ic_notification_new_message) | ||||||
|  |                 .setContentTitle(ctx.getString(R.string.bitmessage_active)); | ||||||
|  |         builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); | ||||||
|  |         bmc = Singleton.getBitmessageContext(ctx); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @SuppressLint("StringFormatMatches") | ||||||
|  |     private boolean update() { | ||||||
|  |         boolean running = bmc.isRunning(); | ||||||
|  |         builder.setOngoing(running); | ||||||
|  |         Property connections = bmc.status().getProperty("network").getProperty("connections"); | ||||||
|  |         if (!running) { | ||||||
|  |             builder.setContentText(ctx.getString(R.string.connection_info_disconnected)); | ||||||
|  |         } else if (connections.getProperties().length == 0) { | ||||||
|  |             builder.setContentText(ctx.getString(R.string.connection_info_pending)); | ||||||
|  |         } else { | ||||||
|  |             StringBuilder info = new StringBuilder(); | ||||||
|  |             for (Property stream : connections.getProperties()) { | ||||||
|  |                 int streamNumber = Integer.parseInt(stream.getName().substring("stream ".length())); | ||||||
|  |                 Integer nodeCount = (Integer) stream.getProperty("nodes").getValue(); | ||||||
|  |                 if (nodeCount == 1) { | ||||||
|  |                     info.append(ctx.getString(R.string.connection_info_1, | ||||||
|  |                             streamNumber)); | ||||||
|  |                 } else { | ||||||
|  |                     info.append(ctx.getString(R.string.connection_info_n, | ||||||
|  |                             streamNumber, nodeCount)); | ||||||
|  |                 } | ||||||
|  |                 info.append('\n'); | ||||||
|  |             } | ||||||
|  |             builder.setContentText(info); | ||||||
|  |         } | ||||||
|  |         Intent showMessageIntent = new Intent(ctx, MessageListActivity.class); | ||||||
|  |         PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 1, showMessageIntent, 0); | ||||||
|  |         builder.setContentIntent(pendingIntent); | ||||||
|  |         notification = builder.build(); | ||||||
|  |         return running; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void show() { | ||||||
|  |         update(); | ||||||
|  |         super.show(); | ||||||
|  |  | ||||||
|  |         final Timer timer = new Timer(); | ||||||
|  |         timer.schedule(new TimerTask() { | ||||||
|  |             @Override | ||||||
|  |             public void run() { | ||||||
|  |                 if (!update()) { | ||||||
|  |                     cancel(); | ||||||
|  |                 } | ||||||
|  |                 NetworkNotification.super.show(); | ||||||
|  |             } | ||||||
|  |         }, 10_000, 10_000); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     protected int getNotificationId() { | ||||||
|  |         return 2; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,81 @@ | |||||||
|  | package ch.dissem.apps.abit.notification; | ||||||
|  |  | ||||||
|  | import android.app.NotificationManager; | ||||||
|  | import android.app.PendingIntent; | ||||||
|  | import android.content.Context; | ||||||
|  | import android.content.Intent; | ||||||
|  | import android.graphics.Typeface; | ||||||
|  | import android.support.v7.app.NotificationCompat; | ||||||
|  | import android.text.Spannable; | ||||||
|  | import android.text.SpannableString; | ||||||
|  | import android.text.Spanned; | ||||||
|  | import android.text.style.StyleSpan; | ||||||
|  |  | ||||||
|  | import java.util.LinkedList; | ||||||
|  |  | ||||||
|  | import ch.dissem.apps.abit.Identicon; | ||||||
|  | import ch.dissem.apps.abit.MessageListActivity; | ||||||
|  | import ch.dissem.apps.abit.R; | ||||||
|  | import ch.dissem.bitmessage.entity.Plaintext; | ||||||
|  |  | ||||||
|  | import static ch.dissem.apps.abit.util.Drawables.toBitmap; | ||||||
|  |  | ||||||
|  | public class NewMessageNotification extends AbstractNotification { | ||||||
|  |     private static final StyleSpan SPAN_EMPHASIS = new StyleSpan(Typeface.BOLD); | ||||||
|  |  | ||||||
|  |     public NewMessageNotification(Context ctx) { | ||||||
|  |         super(ctx); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public NewMessageNotification singleNotification(Plaintext plaintext) { | ||||||
|  |         NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx); | ||||||
|  |         Spannable bigText = new SpannableString(plaintext.getSubject() + "\n" + plaintext.getText()); | ||||||
|  |         bigText.setSpan(SPAN_EMPHASIS, 0, plaintext.getSubject().length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); | ||||||
|  |         builder.setSmallIcon(R.drawable.ic_notification_new_message) | ||||||
|  |                 .setLargeIcon(toBitmap(new Identicon(plaintext.getFrom()), 192)) | ||||||
|  |                 .setContentTitle(plaintext.getFrom().toString()) | ||||||
|  |                 .setContentText(plaintext.getSubject()) | ||||||
|  |                 .setStyle(new NotificationCompat.BigTextStyle().bigText(bigText)) | ||||||
|  |                 .setContentInfo("Info"); | ||||||
|  |  | ||||||
|  |         Intent showMessageIntent = new Intent(ctx, MessageListActivity.class); | ||||||
|  |         showMessageIntent.putExtra(MessageListActivity.EXTRA_SHOW_MESSAGE, plaintext); | ||||||
|  |         PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, showMessageIntent, PendingIntent.FLAG_UPDATE_CURRENT); | ||||||
|  |         builder.setContentIntent(pendingIntent); | ||||||
|  |  | ||||||
|  |         builder.addAction(R.drawable.ic_action_reply, ctx.getString(R.string.reply), pendingIntent); | ||||||
|  |         builder.addAction(R.drawable.ic_action_delete, ctx.getString(R.string.delete), pendingIntent); | ||||||
|  |         notification = builder.build(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public NewMessageNotification multiNotification(LinkedList<Plaintext> unacknowledged, int numberOfUnacknowledgedMessages) { | ||||||
|  |         NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx); | ||||||
|  |         builder.setSmallIcon(R.drawable.ic_notification_new_message) | ||||||
|  |                 .setContentTitle(ctx.getString(R.string.n_new_messages, unacknowledged.size())) | ||||||
|  |                 .setContentText(ctx.getString(R.string.app_name)); | ||||||
|  |  | ||||||
|  |         NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); | ||||||
|  |         synchronized (unacknowledged) { | ||||||
|  |             inboxStyle.setBigContentTitle(ctx.getString(R.string.n_new_messages, numberOfUnacknowledgedMessages)); | ||||||
|  |             for (Plaintext msg : unacknowledged) { | ||||||
|  |                 Spannable sb = new SpannableString(msg.getFrom() + " " + msg.getSubject()); | ||||||
|  |                 sb.setSpan(SPAN_EMPHASIS, 0, String.valueOf(msg.getFrom()).length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); | ||||||
|  |                 inboxStyle.addLine(sb); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         builder.setStyle(inboxStyle); | ||||||
|  |  | ||||||
|  |         Intent intent = new Intent(ctx, MessageListActivity.class); | ||||||
|  |         intent.setAction(MessageListActivity.ACTION_SHOW_INBOX); | ||||||
|  |         PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 1, intent, 0); | ||||||
|  |         builder.setContentIntent(pendingIntent); | ||||||
|  |         notification = builder.build(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     protected int getNotificationId() { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -14,7 +14,7 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.repositories; | package ch.dissem.apps.abit.repository; | ||||||
| 
 | 
 | ||||||
| import android.content.ContentValues; | import android.content.ContentValues; | ||||||
| import android.database.Cursor; | import android.database.Cursor; | ||||||
| @@ -14,7 +14,7 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.repositories; | package ch.dissem.apps.abit.repository; | ||||||
| 
 | 
 | ||||||
| import android.content.ContentValues; | import android.content.ContentValues; | ||||||
| import android.database.Cursor; | import android.database.Cursor; | ||||||
| @@ -36,7 +36,7 @@ import java.io.IOException; | |||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import static ch.dissem.apps.abit.repositories.SqlHelper.join; | import static ch.dissem.apps.abit.repository.SqlHelper.join; | ||||||
| import static ch.dissem.bitmessage.utils.UnixTime.now; | import static ch.dissem.bitmessage.utils.UnixTime.now; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @@ -14,7 +14,7 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.repositories; | package ch.dissem.apps.abit.repository; | ||||||
| 
 | 
 | ||||||
| import android.content.ContentValues; | import android.content.ContentValues; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| @@ -40,7 +40,7 @@ import java.util.Collection; | |||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| import static ch.dissem.apps.abit.repositories.SqlHelper.join; | import static ch.dissem.apps.abit.repository.SqlHelper.join; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * {@link MessageRepository} implementation using the Android SQL API. |  * {@link MessageRepository} implementation using the Android SQL API. | ||||||
| @@ -14,12 +14,12 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.repositories; | package ch.dissem.apps.abit.repository; | ||||||
| 
 | 
 | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.database.sqlite.SQLiteDatabase; | import android.database.sqlite.SQLiteDatabase; | ||||||
| import android.database.sqlite.SQLiteOpenHelper; | import android.database.sqlite.SQLiteOpenHelper; | ||||||
| import ch.dissem.apps.abit.utils.Assets; | import ch.dissem.apps.abit.util.Assets; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Handles database migration and provides access. |  * Handles database migration and provides access. | ||||||
| @@ -1,13 +1,12 @@ | |||||||
| package ch.dissem.apps.abit.service; | package ch.dissem.apps.abit.service; | ||||||
|  |  | ||||||
| import android.app.NotificationManager; |  | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
|  |  | ||||||
| import ch.dissem.apps.abit.listeners.MessageListener; | import ch.dissem.apps.abit.listener.MessageListener; | ||||||
| import ch.dissem.apps.abit.repositories.AndroidAddressRepository; | import ch.dissem.apps.abit.repository.AndroidAddressRepository; | ||||||
| import ch.dissem.apps.abit.repositories.AndroidInventory; | import ch.dissem.apps.abit.repository.AndroidInventory; | ||||||
| import ch.dissem.apps.abit.repositories.AndroidMessageRepository; | import ch.dissem.apps.abit.repository.AndroidMessageRepository; | ||||||
| import ch.dissem.apps.abit.repositories.SqlHelper; | import ch.dissem.apps.abit.repository.SqlHelper; | ||||||
| import ch.dissem.bitmessage.BitmessageContext; | import ch.dissem.bitmessage.BitmessageContext; | ||||||
| import ch.dissem.bitmessage.networking.DefaultNetworkHandler; | import ch.dissem.bitmessage.networking.DefaultNetworkHandler; | ||||||
| import ch.dissem.bitmessage.ports.MemoryNodeRegistry; | import ch.dissem.bitmessage.ports.MemoryNodeRegistry; | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.utils; | package ch.dissem.apps.abit.util; | ||||||
| 
 | 
 | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| 
 | 
 | ||||||
| @@ -14,11 +14,16 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package ch.dissem.apps.abit.utils; | package ch.dissem.apps.abit.util; | ||||||
| 
 | 
 | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
|  | import android.graphics.Bitmap; | ||||||
|  | import android.graphics.Canvas; | ||||||
| import android.view.Menu; | import android.view.Menu; | ||||||
|  | 
 | ||||||
|  | import ch.dissem.apps.abit.Identicon; | ||||||
| import ch.dissem.apps.abit.R; | import ch.dissem.apps.abit.R; | ||||||
|  | 
 | ||||||
| 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; | ||||||
| 
 | 
 | ||||||
| @@ -29,4 +34,16 @@ public class Drawables { | |||||||
|     public static void addIcon(Context ctx, Menu menu, int menuItem, GoogleMaterial.Icon icon) { |     public static void addIcon(Context ctx, Menu menu, int menuItem, GoogleMaterial.Icon icon) { | ||||||
|         menu.findItem(menuItem).setIcon(new IconicsDrawable(ctx, icon).colorRes(R.color.primary_text_default_material_dark).actionBar()); |         menu.findItem(menuItem).setIcon(new IconicsDrawable(ctx, icon).colorRes(R.color.primary_text_default_material_dark).actionBar()); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public static Bitmap toBitmap(Identicon identicon, int size) { | ||||||
|  |         return toBitmap(identicon, size, size); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Bitmap toBitmap(Identicon identicon, int width, int height) { | ||||||
|  |         Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); | ||||||
|  |         Canvas canvas = new Canvas(bitmap); | ||||||
|  |         identicon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); | ||||||
|  |         identicon.draw(canvas); | ||||||
|  |         return bitmap; | ||||||
|  |     } | ||||||
| } | } | ||||||
| @@ -30,7 +30,11 @@ | |||||||
|     <string name="archive">Archiv</string> |     <string name="archive">Archiv</string> | ||||||
|     <string name="empty_trash">Papierkorb leeren</string> |     <string name="empty_trash">Papierkorb leeren</string> | ||||||
|     <string name="mark_unread">Als ungelesen markieren</string> |     <string name="mark_unread">Als ungelesen markieren</string> | ||||||
|     <string name="stream_number">Stream #%d</string> |     <string name="stream_number">Stream %d</string> | ||||||
|     <string name="enabled">Aktiv</string> |     <string name="enabled">Aktiv</string> | ||||||
|     <string name="title_subscription_detail">Abonnement</string> |     <string name="title_subscription_detail">Abonnement</string> | ||||||
|  |     <string name="connection_info_1">Stream %1$d: eine Verbindung</string> | ||||||
|  |     <string name="connection_info_n">Stream %1$d: %2$d Verbindungen</string> | ||||||
|  |     <string name="connection_info_disconnected">Getrennt</string> | ||||||
|  |     <string name="connection_info_pending">Verbindung wird aufgebaut…</string> | ||||||
| </resources> | </resources> | ||||||
| @@ -18,6 +18,8 @@ | |||||||
|     <string name="title_activity_open_bitmessage_link">Import Contact</string> |     <string name="title_activity_open_bitmessage_link">Import Contact</string> | ||||||
|  |  | ||||||
|     <string name="action_settings">Settings</string> |     <string name="action_settings">Settings</string> | ||||||
|  |     <string name="connection_info_1">Stream #%1$d: one connection</string> | ||||||
|  |     <string name="connection_info_n">Stream #%1$d: %2$d connections</string> | ||||||
|     <string name="import_address">Import Address</string> |     <string name="import_address">Import Address</string> | ||||||
|     <string name="import_contact">Add to contacts</string> |     <string name="import_contact">Add to contacts</string> | ||||||
|     <string name="label">Label</string> |     <string name="label">Label</string> | ||||||
| @@ -33,4 +35,6 @@ | |||||||
|     <string name="empty_trash">Empty Trash</string> |     <string name="empty_trash">Empty Trash</string> | ||||||
|     <string name="stream_number">Stream #%d</string> |     <string name="stream_number">Stream #%d</string> | ||||||
|     <string name="enabled">Enabled</string> |     <string name="enabled">Enabled</string> | ||||||
|  |     <string name="connection_info_disconnected">Disconnected</string> | ||||||
|  |     <string name="connection_info_pending">Connecting…</string> | ||||||
| </resources> | </resources> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user