Added proper message list, and almost nice notifications

This commit is contained in:
2015-08-28 13:49:53 +02:00
parent 5e2d19df58
commit e5b00c7453
24 changed files with 390 additions and 94 deletions

View File

@ -2,8 +2,10 @@ package ch.dissem.apps.abit;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
@ -16,13 +18,15 @@ import android.view.MenuItem;
* This activity is mostly just a 'shell' activity containing nothing
* more than a {@link MessageDetailFragment}.
*/
public class MessageDetailActivity extends ActionBarActivity {
public class MessageDetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_detail);
setContentView(R.layout.toolbar_layout);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Show the Up button in the action bar.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -39,12 +43,12 @@ public class MessageDetailActivity extends ActionBarActivity {
// Create the detail fragment and add it to the activity
// using a fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(MessageDetailFragment.ARG_ITEM,
getIntent().getStringExtra(MessageDetailFragment.ARG_ITEM));
arguments.putSerializable(MessageDetailFragment.ARG_ITEM,
getIntent().getSerializableExtra(MessageDetailFragment.ARG_ITEM));
MessageDetailFragment fragment = new MessageDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.message_detail_container, fragment)
.add(R.id.content, fragment)
.commit();
}
}

View File

@ -5,8 +5,14 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.Label;
import java.util.Iterator;
/**
@ -53,9 +59,29 @@ public class MessageDetailFragment extends Fragment {
// Show the dummy content as text in a TextView.
if (item != null) {
((TextView) rootView.findViewById(R.id.message_detail)).setText(item.getText());
((TextView) rootView.findViewById(R.id.subject)).setText(item.getSubject());
BitmessageAddress sender = item.getFrom();
((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());
} else if (item.getType() == Plaintext.Type.BROADCAST) {
((TextView) rootView.findViewById(R.id.recipient)).setText(R.string.broadcast);
}
((TextView) rootView.findViewById(R.id.text)).setText(item.getText());
}
boolean removed = false;
Iterator<Label> labels = item.getLabels().iterator();
while (labels.hasNext()) {
if (labels.next().getType() == Label.Type.UNREAD) {
labels.remove();
removed = true;
}
}
if (removed) {
Singleton.getBitmessageContext(inflater.getContext()).messages().save(item);
}
return rootView;
}
}

View File

@ -8,7 +8,6 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
@ -28,6 +27,8 @@ import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
import com.mikepenz.materialdrawer.model.interfaces.Nameable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
@ -51,6 +52,9 @@ import java.util.ArrayList;
*/
public class MessageListActivity extends AppCompatActivity
implements MessageListFragment.Callbacks {
public static final String EXTRA_SHOW_MESSAGE = "show_message";
private static final Logger LOG = LoggerFactory.getLogger(MessageListActivity.class);
private static final int ADD_IDENTITY = 1;
/**
@ -97,6 +101,7 @@ public class MessageListActivity extends AppCompatActivity
private void createDrawer(Toolbar toolbar) {
final ArrayList<IProfile> profiles = new ArrayList<>();
for (BitmessageAddress identity : bmc.addresses().getIdentities()) {
LOG.info("Adding identity " + identity.getAddress());
profiles.add(new ProfileDrawerItem()
.withName(identity.toString())
.withEmail(identity.getAddress())
@ -203,18 +208,7 @@ public class MessageListActivity extends AppCompatActivity
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.sync_disabled:
bmc.startup(new BitmessageContext.Listener() {
@Override
public void receive(final Plaintext plaintext) {
// TODO
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MessageListActivity.this, plaintext.getSubject(), Toast.LENGTH_LONG).show();
}
});
}
});
bmc.startup(Singleton.getMessageListener(this));
updateMenu();
return true;
case R.id.sync_enabled:
@ -256,4 +250,5 @@ public class MessageListActivity extends AppCompatActivity
public Label getSelectedLabel() {
return selectedLabel;
}
}

View File

@ -2,6 +2,7 @@ package ch.dissem.apps.abit;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.ListFragment;
@ -9,7 +10,9 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.Plaintext;
@ -84,11 +87,34 @@ public class MessageListFragment extends ListFragment {
}
public void updateList(Label label) {
setListAdapter(new ArrayAdapter<>(
setListAdapter(new ArrayAdapter<Plaintext>(
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
bmc.messages().findMessages(label)));
bmc.messages().findMessages(label)) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.message_row, null, false);
}
Plaintext item = getItem(position);
((ImageView) convertView.findViewById(R.id.avatar)).setImageDrawable(new Identicon(item.getFrom()));
TextView sender = (TextView) convertView.findViewById(R.id.sender);
sender.setText(item.getFrom().toString());
TextView subject = (TextView) convertView.findViewById(R.id.subject);
subject.setText(item.getSubject());
((TextView) convertView.findViewById(R.id.text)).setText(item.getText());
if (item.isUnread()) {
sender.setTypeface(Typeface.DEFAULT_BOLD);
subject.setTypeface(Typeface.DEFAULT_BOLD);
} else {
sender.setTypeface(Typeface.DEFAULT);
subject.setTypeface(Typeface.DEFAULT);
}
return convertView;
}
});
}
@Override

View File

@ -0,0 +1,69 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.apps.abit;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.NotificationCompat;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.Plaintext;
/**
* Created by chris on 22.08.15.
*/
public class MessageListener implements BitmessageContext.Listener {
private final Context ctx;
private final NotificationManager manager;
public MessageListener(Context ctx) {
this.ctx = ctx.getApplicationContext();
this.manager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void receive(final Plaintext plaintext) {
// TODO
// ctx.runOnUiThread(new Runnable() {
// @Override
// public void run() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
builder.setSmallIcon(R.drawable.ic_notification_new_message)
.setContentTitle(plaintext.getFrom().toString())
.setContentText(plaintext.getSubject());
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle(plaintext.getFrom().toString());
inboxStyle.setSummaryText(plaintext.getSubject());
String text = plaintext.getText();
if (text.length() > 100)
inboxStyle.addLine(text.substring(0, 100) + "");
else
inboxStyle.addLine(text);
builder.setStyle(inboxStyle);
Intent intent = new Intent(ctx, MessageListActivity.class);
intent.putExtra(MessageListActivity.EXTRA_SHOW_MESSAGE, plaintext);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0);
builder.setContentIntent(pendingIntent);
manager.notify(0, builder.build());
// }
// });
}
}

View File

@ -184,7 +184,13 @@ public class AndroidAddressRepository implements AddressRepository {
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(COLUMN_ALIAS, address.getAlias());
values.put(COLUMN_PUBLIC_KEY, Encode.bytes(address.getPubkey()));
if (address.getPubkey() != null) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
address.getPubkey().writeUnencrypted(out);
values.put(COLUMN_PUBLIC_KEY, out.toByteArray());
} else {
values.put(COLUMN_PUBLIC_KEY, (byte[]) null);
}
values.put(COLUMN_PRIVATE_KEY, Encode.bytes(address.getPrivateKey()));
values.put(COLUMN_SUBSCRIBED, address.isSubscribed());

View File

@ -18,6 +18,7 @@ package ch.dissem.apps.abit.repositories;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import ch.dissem.bitmessage.entity.ObjectMessage;
import ch.dissem.bitmessage.entity.payload.ObjectType;
@ -168,10 +169,9 @@ public class AndroidInventory implements Inventory {
values.put(COLUMN_TYPE, object.getType());
values.put(COLUMN_VERSION, object.getVersion());
long insert = db.insert(TABLE_NAME, null, values);
if (insert < 0) {
LOG.trace("Error while inserting object. Most probably it was requested twice.");
}
db.insertOrThrow(TABLE_NAME, null, values);
} catch (SQLiteConstraintException e) {
LOG.trace(e.getMessage(), e);
} catch (IOException e) {
LOG.error(e.getMessage(), e);
}

View File

@ -138,7 +138,7 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
text = ctx.getString(R.string.trash);
break;
case BROADCAST:
text = ctx.getString(R.string.broadcast);
text = ctx.getString(R.string.broadcasts);
break;
default:
text = c.getString(c.getColumnIndex(LBL_COLUMN_LABEL));
@ -192,7 +192,8 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
Cursor c = db.query(
TABLE_NAME, projection,
where,
null, null, null, null
null, null, null,
COLUMN_RECEIVED + " DESC"
);
c.moveToFirst();
while (!c.isAfterLast()) {
@ -224,8 +225,8 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
@Override
public void save(Plaintext message) {
SQLiteDatabase db = sql.getWritableDatabase();
try {
SQLiteDatabase db = sql.getWritableDatabase();
db.beginTransaction();
// save from address if necessary
@ -256,9 +257,11 @@ public class AndroidMessageRepository implements MessageRepository, InternalCont
values.put(JT_COLUMN_MESSAGE, (Long) message.getId());
db.insertOrThrow(JOIN_TABLE_NAME, null, values);
}
db.endTransaction();
db.setTransactionSuccessful();
} catch (IOException e) {
LOG.error(e.getMessage(), e);
} finally {
db.endTransaction();
}
}

View File

@ -33,7 +33,6 @@ public class SqlHelper extends SQLiteOpenHelper {
public SqlHelper(Context ctx) {
super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
setWriteAheadLoggingEnabled(true);
this.ctx = ctx;
}

View File

@ -1,6 +1,7 @@
package ch.dissem.apps.abit.service;
import android.content.Context;
import ch.dissem.apps.abit.MessageListener;
import ch.dissem.apps.abit.repositories.AndroidAddressRepository;
import ch.dissem.apps.abit.repositories.AndroidInventory;
import ch.dissem.apps.abit.repositories.AndroidMessageRepository;
@ -11,10 +12,11 @@ import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
import ch.dissem.bitmessage.security.sc.SpongySecurity;
/**
* Created by chris on 16.07.15.
* Provides singleton objects across the application.
*/
public class Singleton {
private static BitmessageContext bitmessageContext;
private static MessageListener messageListener;
public static BitmessageContext getBitmessageContext(Context ctx) {
if (bitmessageContext == null) {
@ -35,4 +37,15 @@ public class Singleton {
}
return bitmessageContext;
}
public static MessageListener getMessageListener(Context ctx) {
if (messageListener == null) {
synchronized (Singleton.class) {
if (messageListener == null) {
messageListener = new MessageListener(ctx);
}
}
}
return messageListener;
}
}