mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Lambdas.
This commit is contained in:
@@ -124,12 +124,7 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
|
||||
// with a message queue, so submit it to the AndroidExecutor
|
||||
try {
|
||||
adapter = androidExecutor.runOnBackgroundThread(
|
||||
new Callable<BluetoothAdapter>() {
|
||||
@Override
|
||||
public BluetoothAdapter call() throws Exception {
|
||||
return BluetoothAdapter.getDefaultAdapter();
|
||||
}
|
||||
}).get();
|
||||
BluetoothAdapter::getDefaultAdapter).get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
LOG.warning("Interrupted while getting BluetoothAdapter");
|
||||
@@ -162,40 +157,36 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isRunning()) return;
|
||||
String address = AndroidUtils.getBluetoothAddress(appContext,
|
||||
adapter);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Local address " + scrubMacAddress(address));
|
||||
if (!StringUtils.isNullOrEmpty(address)) {
|
||||
// Advertise the Bluetooth address to contacts
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ADDRESS, address);
|
||||
callback.mergeLocalProperties(p);
|
||||
}
|
||||
// Bind a server socket to accept connections from contacts
|
||||
BluetoothServerSocket ss;
|
||||
try {
|
||||
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
|
||||
"RFCOMM", getUuid());
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
return;
|
||||
}
|
||||
if (!isRunning()) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
LOG.info("Socket bound");
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections();
|
||||
ioExecutor.execute(() -> {
|
||||
if (!isRunning()) return;
|
||||
String address = AndroidUtils.getBluetoothAddress(appContext,
|
||||
adapter);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Local address " + scrubMacAddress(address));
|
||||
if (!StringUtils.isNullOrEmpty(address)) {
|
||||
// Advertise the Bluetooth address to contacts
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ADDRESS, address);
|
||||
callback.mergeLocalProperties(p);
|
||||
}
|
||||
// Bind a server socket to accept connections from contacts
|
||||
BluetoothServerSocket ss;
|
||||
try {
|
||||
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
|
||||
"RFCOMM", getUuid());
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
return;
|
||||
}
|
||||
if (!isRunning()) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
LOG.info("Socket bound");
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -300,15 +291,12 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
|
||||
if (StringUtils.isNullOrEmpty(address)) continue;
|
||||
final String uuid = e.getValue().get(PROP_UUID);
|
||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
BluetoothSocket s = connect(address, uuid);
|
||||
if (s != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, wrapSocket(s));
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
BluetoothSocket s = connect(address, uuid);
|
||||
if (s != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, wrapSocket(s));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -438,21 +426,11 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
|
||||
}
|
||||
|
||||
private void enableAdapterAsync() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
enableAdapter();
|
||||
}
|
||||
});
|
||||
ioExecutor.execute(this::enableAdapter);
|
||||
}
|
||||
|
||||
private void disableAdapterAsync() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
disableAdapter();
|
||||
}
|
||||
});
|
||||
ioExecutor.execute(this::disableAdapter);
|
||||
}
|
||||
|
||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||
@@ -490,16 +468,13 @@ class DroidtoothPlugin implements DuplexPlugin, EventListener {
|
||||
|
||||
@Override
|
||||
public Callable<KeyAgreementConnection> listen() {
|
||||
return new Callable<KeyAgreementConnection>() {
|
||||
@Override
|
||||
public KeyAgreementConnection call() throws IOException {
|
||||
BluetoothSocket s = ss.accept();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(ID.getString() + ": Incoming connection");
|
||||
return new KeyAgreementConnection(
|
||||
new DroidtoothTransportConnection(
|
||||
DroidtoothPlugin.this, s), ID);
|
||||
}
|
||||
return () -> {
|
||||
BluetoothSocket s = ss.accept();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(ID.getString() + ": Incoming connection");
|
||||
return new KeyAgreementConnection(
|
||||
new DroidtoothTransportConnection(
|
||||
DroidtoothPlugin.this, s), ID);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -370,57 +370,45 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
|
||||
private void sendDevReports() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO: Trigger this with a TransportEnabledEvent
|
||||
File reportDir = AndroidUtils.getReportDir(appContext);
|
||||
reporter.sendReports(reportDir);
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
// TODO: Trigger this with a TransportEnabledEvent
|
||||
File reportDir = AndroidUtils.getReportDir(appContext);
|
||||
reporter.sendReports(reportDir);
|
||||
});
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// If there's already a port number stored in config, reuse it
|
||||
String portString = callback.getSettings().get(PREF_TOR_PORT);
|
||||
int port;
|
||||
if (StringUtils.isNullOrEmpty(portString)) port = 0;
|
||||
else port = Integer.parseInt(portString);
|
||||
// Bind a server socket to receive connections from Tor
|
||||
ServerSocket ss = null;
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress("127.0.0.1", port));
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
if (!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
// Store the port number
|
||||
final String localPort = String.valueOf(ss.getLocalPort());
|
||||
Settings s = new Settings();
|
||||
s.put(PREF_TOR_PORT, localPort);
|
||||
callback.mergeSettings(s);
|
||||
// Create a hidden service if necessary
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
publishHiddenService(localPort);
|
||||
}
|
||||
});
|
||||
backoff.reset();
|
||||
// Accept incoming hidden service connections from Tor
|
||||
acceptContactConnections(ss);
|
||||
ioExecutor.execute(() -> {
|
||||
// If there's already a port number stored in config, reuse it
|
||||
String portString = callback.getSettings().get(PREF_TOR_PORT);
|
||||
int port;
|
||||
if (StringUtils.isNullOrEmpty(portString)) port = 0;
|
||||
else port = Integer.parseInt(portString);
|
||||
// Bind a server socket to receive connections from Tor
|
||||
ServerSocket ss = null;
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress("127.0.0.1", port));
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
if (!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
// Store the port number
|
||||
final String localPort = String.valueOf(ss.getLocalPort());
|
||||
Settings s = new Settings();
|
||||
s.put(PREF_TOR_PORT, localPort);
|
||||
callback.mergeSettings(s);
|
||||
// Create a hidden service if necessary
|
||||
ioExecutor.execute(() -> publishHiddenService(localPort));
|
||||
backoff.reset();
|
||||
// Accept incoming hidden service connections from Tor
|
||||
acceptContactConnections(ss);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -550,15 +538,12 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
private void connectAndCallBack(final ContactId c,
|
||||
final TransportProperties p) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isRunning()) return;
|
||||
DuplexTransportConnection d = createConnection(p);
|
||||
if (d != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, d);
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
if (!isRunning()) return;
|
||||
DuplexTransportConnection d = createConnection(p);
|
||||
if (d != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -691,48 +676,43 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
|
||||
private void updateConnectionStatus() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
ioExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
|
||||
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||
ConnectivityManager cm = (ConnectivityManager) o;
|
||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||
boolean online = net != null && net.isConnected();
|
||||
boolean wifi = online && net.getType() == TYPE_WIFI;
|
||||
String country = locationUtils.getCurrentCountry();
|
||||
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
||||
country);
|
||||
Settings s = callback.getSettings();
|
||||
int network = s.getInt(PREF_TOR_NETWORK,
|
||||
PREF_TOR_NETWORK_ALWAYS);
|
||||
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||
ConnectivityManager cm = (ConnectivityManager) o;
|
||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||
boolean online = net != null && net.isConnected();
|
||||
boolean wifi = online && net.getType() == TYPE_WIFI;
|
||||
String country = locationUtils.getCurrentCountry();
|
||||
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
||||
country);
|
||||
Settings s = callback.getSettings();
|
||||
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
|
||||
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||
if ("".equals(country)) LOG.info("Country code unknown");
|
||||
else LOG.info("Country code: " + country);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!online) {
|
||||
LOG.info("Disabling network, device is offline");
|
||||
enableNetwork(false);
|
||||
} else if (blocked) {
|
||||
LOG.info("Disabling network, country is blocked");
|
||||
enableNetwork(false);
|
||||
} else if (network == PREF_TOR_NETWORK_NEVER
|
||||
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
|
||||
LOG.info("Disabling network due to data setting");
|
||||
enableNetwork(false);
|
||||
} else {
|
||||
LOG.info("Enabling network");
|
||||
enableNetwork(true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||
if ("".equals(country)) LOG.info("Country code unknown");
|
||||
else LOG.info("Country code: " + country);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!online) {
|
||||
LOG.info("Disabling network, device is offline");
|
||||
enableNetwork(false);
|
||||
} else if (blocked) {
|
||||
LOG.info("Disabling network, country is blocked");
|
||||
enableNetwork(false);
|
||||
} else if (network == PREF_TOR_NETWORK_NEVER
|
||||
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
|
||||
LOG.info("Disabling network due to data setting");
|
||||
enableNetwork(false);
|
||||
} else {
|
||||
LOG.info("Enabling network");
|
||||
enableNetwork(true);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,14 +27,11 @@ class AndroidExecutorImpl implements AndroidExecutor {
|
||||
@Inject
|
||||
AndroidExecutorImpl(Application app) {
|
||||
uiHandler = new Handler(app.getApplicationContext().getMainLooper());
|
||||
loop = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
backgroundHandler = new Handler();
|
||||
startLatch.countDown();
|
||||
Looper.loop();
|
||||
}
|
||||
loop = () -> {
|
||||
Looper.prepare();
|
||||
backgroundHandler = new Handler();
|
||||
startLatch.countDown();
|
||||
Looper.loop();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,9 @@ public abstract class BrambleTestCase {
|
||||
|
||||
public BrambleTestCase() {
|
||||
// Ensure exceptions thrown on worker threads cause tests to fail
|
||||
UncaughtExceptionHandler fail = new UncaughtExceptionHandler() {
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
UncaughtExceptionHandler fail = (thread, throwable) -> {
|
||||
throwable.printStackTrace();
|
||||
fail();
|
||||
};
|
||||
Thread.setDefaultUncaughtExceptionHandler(fail);
|
||||
}
|
||||
|
||||
@@ -50,18 +50,15 @@ public class PoliteExecutor implements Executor {
|
||||
@Override
|
||||
public void execute(final Runnable r) {
|
||||
final long submitted = System.currentTimeMillis();
|
||||
Runnable wrapped = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (log.isLoggable(LOG_LEVEL)) {
|
||||
long queued = System.currentTimeMillis() - submitted;
|
||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} finally {
|
||||
scheduleNext();
|
||||
}
|
||||
Runnable wrapped = () -> {
|
||||
if (log.isLoggable(LOG_LEVEL)) {
|
||||
long queued = System.currentTimeMillis() - submitted;
|
||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
||||
}
|
||||
try {
|
||||
r.run();
|
||||
} finally {
|
||||
scheduleNext();
|
||||
}
|
||||
};
|
||||
synchronized (lock) {
|
||||
|
||||
@@ -31,16 +31,13 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
|
||||
public void execute(final Runnable r) {
|
||||
if (log.isLoggable(LOG_LEVEL)) {
|
||||
final long submitted = System.currentTimeMillis();
|
||||
super.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long started = System.currentTimeMillis();
|
||||
long queued = started - submitted;
|
||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
||||
r.run();
|
||||
long executing = System.currentTimeMillis() - started;
|
||||
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
|
||||
}
|
||||
super.execute(() -> {
|
||||
long started = System.currentTimeMillis();
|
||||
long queued = started - submitted;
|
||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
||||
r.run();
|
||||
long executing = System.currentTimeMillis() - started;
|
||||
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
|
||||
});
|
||||
} else {
|
||||
super.execute(r);
|
||||
|
||||
@@ -103,15 +103,11 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
|
||||
@Override
|
||||
public boolean open() throws DbException {
|
||||
Runnable shutdownHook = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
close();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
Runnable shutdownHook = () -> {
|
||||
try {
|
||||
close();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
};
|
||||
boolean reopened = db.open();
|
||||
|
||||
@@ -266,12 +266,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
contactId = ctx.getContactId();
|
||||
connectionRegistry.registerConnection(contactId, transportId, true);
|
||||
// Start the outgoing session on another thread
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOutgoingSession();
|
||||
}
|
||||
});
|
||||
ioExecutor.execute(this::runOutgoingSession);
|
||||
try {
|
||||
// Create and run the incoming session
|
||||
incomingSession = createIncomingSession(ctx, reader);
|
||||
@@ -368,12 +363,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
||||
return;
|
||||
}
|
||||
// Start the incoming session on another thread
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runIncomingSession();
|
||||
}
|
||||
});
|
||||
ioExecutor.execute(this::runIncomingSession);
|
||||
try {
|
||||
// Create and run the outgoing session
|
||||
outgoingSession = createDuplexOutgoingSession(ctx, writer);
|
||||
|
||||
@@ -112,29 +112,23 @@ class Poller implements EventListener {
|
||||
}
|
||||
|
||||
private void connectToContact(final ContactId c, final SimplexPlugin p) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TransportId t = p.getId();
|
||||
if (!connectionRegistry.isConnected(c, t)) {
|
||||
TransportConnectionWriter w = p.createWriter(c);
|
||||
if (w != null)
|
||||
connectionManager.manageOutgoingConnection(c, t, w);
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
TransportId t = p.getId();
|
||||
if (!connectionRegistry.isConnected(c, t)) {
|
||||
TransportConnectionWriter w = p.createWriter(c);
|
||||
if (w != null)
|
||||
connectionManager.manageOutgoingConnection(c, t, w);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void connectToContact(final ContactId c, final DuplexPlugin p) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TransportId t = p.getId();
|
||||
if (!connectionRegistry.isConnected(c, t)) {
|
||||
DuplexTransportConnection d = p.createConnection(c);
|
||||
if (d != null)
|
||||
connectionManager.manageOutgoingConnection(c, t, d);
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
TransportId t = p.getId();
|
||||
if (!connectionRegistry.isConnected(c, t)) {
|
||||
DuplexTransportConnection d = p.createConnection(c);
|
||||
if (d != null)
|
||||
connectionManager.manageOutgoingConnection(c, t, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -161,12 +155,8 @@ class Poller implements EventListener {
|
||||
if (scheduled == null || due < scheduled.due) {
|
||||
final PollTask task = new PollTask(p, due, randomiseNext);
|
||||
tasks.put(t, task);
|
||||
scheduler.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ioExecutor.execute(task);
|
||||
}
|
||||
}, delay, MILLISECONDS);
|
||||
scheduler.schedule(
|
||||
() -> ioExecutor.execute(task), delay, MILLISECONDS);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
|
||||
@@ -260,16 +260,12 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
|
||||
@Override
|
||||
public Callable<KeyAgreementConnection> listen() {
|
||||
return new Callable<KeyAgreementConnection>() {
|
||||
@Override
|
||||
public KeyAgreementConnection call() throws IOException {
|
||||
Socket s = ss.accept();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(ID.getString() + ": Incoming connection");
|
||||
return new KeyAgreementConnection(
|
||||
new TcpTransportConnection(LanTcpPlugin.this, s),
|
||||
ID);
|
||||
}
|
||||
return () -> {
|
||||
Socket s = ss.accept();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(ID.getString() + ": Incoming connection");
|
||||
return new KeyAgreementConnection(
|
||||
new TcpTransportConnection(LanTcpPlugin.this, s), ID);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -50,12 +50,7 @@ class PortMapperImpl implements PortMapper {
|
||||
succeeded = gateway.addPortMapping(port, port,
|
||||
getHostAddress(internal), "TCP", "TCP");
|
||||
if (succeeded) {
|
||||
shutdownManager.addShutdownHook(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
deleteMapping(port);
|
||||
}
|
||||
});
|
||||
shutdownManager.addShutdownHook(() -> deleteMapping(port));
|
||||
}
|
||||
String externalString = gateway.getExternalIPAddress();
|
||||
if (LOG.isLoggable(INFO))
|
||||
|
||||
@@ -110,41 +110,37 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
protected void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
ServerSocket ss = null;
|
||||
for (InetSocketAddress addr : getLocalSocketAddresses()) {
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(addr);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Failed to bind " +
|
||||
scrubSocketAddress(addr));
|
||||
tryToClose(ss);
|
||||
}
|
||||
}
|
||||
if (ss == null || !ss.isBound()) {
|
||||
LOG.info("Could not bind server socket");
|
||||
return;
|
||||
}
|
||||
if (!running) {
|
||||
ioExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
ServerSocket ss = null;
|
||||
for (InetSocketAddress addr : getLocalSocketAddresses()) {
|
||||
try {
|
||||
ss = new ServerSocket();
|
||||
ss.bind(addr);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Failed to bind " + scrubSocketAddress(addr));
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
InetSocketAddress local =
|
||||
(InetSocketAddress) ss.getLocalSocketAddress();
|
||||
setLocalSocketAddress(local);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Listening on " + scrubSocketAddress(local));
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections();
|
||||
}
|
||||
if (ss == null || !ss.isBound()) {
|
||||
LOG.info("Could not bind server socket");
|
||||
return;
|
||||
}
|
||||
if (!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
InetSocketAddress local =
|
||||
(InetSocketAddress) ss.getLocalSocketAddress();
|
||||
setLocalSocketAddress(local);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Listening on " + scrubSocketAddress(local));
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -220,15 +216,12 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
|
||||
private void connectAndCallBack(final ContactId c,
|
||||
final TransportProperties p) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isRunning()) return;
|
||||
DuplexTransportConnection d = createConnection(p);
|
||||
if (d != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, d);
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
if (!isRunning()) return;
|
||||
DuplexTransportConnection d = createConnection(p);
|
||||
if (d != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,36 +54,32 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
|
||||
inputStream = new ReceiverInputStream(receiver);
|
||||
outputStream = new SenderOutputStream(sender);
|
||||
running = true;
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long now = clock.currentTimeMillis();
|
||||
long next = now + TICK_INTERVAL;
|
||||
try {
|
||||
while (running) {
|
||||
byte[] b = null;
|
||||
while (now < next && b == null) {
|
||||
b = writes.poll(next - now, MILLISECONDS);
|
||||
if (!running) return;
|
||||
now = clock.currentTimeMillis();
|
||||
}
|
||||
if (b == null) {
|
||||
sender.tick();
|
||||
while (next <= now) next += TICK_INTERVAL;
|
||||
} else {
|
||||
if (b.length == 0) return; // Poison pill
|
||||
writeHandler.handleWrite(b);
|
||||
}
|
||||
executor.execute(() -> {
|
||||
long now = clock.currentTimeMillis();
|
||||
long next = now + TICK_INTERVAL;
|
||||
try {
|
||||
while (running) {
|
||||
byte[] b = null;
|
||||
while (now < next && b == null) {
|
||||
b = writes.poll(next - now, MILLISECONDS);
|
||||
if (!running) return;
|
||||
now = clock.currentTimeMillis();
|
||||
}
|
||||
if (b == null) {
|
||||
sender.tick();
|
||||
while (next <= now) next += TICK_INTERVAL;
|
||||
} else {
|
||||
if (b.length == 0) return; // Poison pill
|
||||
writeHandler.handleWrite(b);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting to write");
|
||||
Thread.currentThread().interrupt();
|
||||
running = false;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
running = false;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting to write");
|
||||
Thread.currentThread().interrupt();
|
||||
running = false;
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
running = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,12 +54,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(DuplexOutgoingSession.class.getName());
|
||||
|
||||
private static final ThrowingRunnable<IOException> CLOSE =
|
||||
new ThrowingRunnable<IOException>() {
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
|
||||
@@ -43,12 +43,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(SimplexOutgoingSession.class.getName());
|
||||
|
||||
private static final ThrowingRunnable<IOException> CLOSE =
|
||||
new ThrowingRunnable<IOException>() {
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
|
||||
@@ -94,12 +94,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
private void validateOutstandingMessagesAsync(final ClientId c) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
validateOutstandingMessages(c);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> validateOutstandingMessages(c));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -121,12 +116,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
|
||||
private void validateNextMessageAsync(final Queue<MessageId> unvalidated) {
|
||||
if (unvalidated.isEmpty()) return;
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
validateNextMessage(unvalidated);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> validateNextMessage(unvalidated));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -159,12 +149,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
private void deliverOutstandingMessagesAsync(final ClientId c) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
deliverOutstandingMessages(c);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> deliverOutstandingMessages(c));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -187,12 +172,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
private void deliverNextPendingMessageAsync(
|
||||
final Queue<MessageId> pending) {
|
||||
if (pending.isEmpty()) return;
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
deliverNextPendingMessage(pending);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> deliverNextPendingMessage(pending));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -255,12 +235,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
private void validateMessageAsync(final Message m, final Group g) {
|
||||
validationExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
validateMessage(m, g);
|
||||
}
|
||||
});
|
||||
validationExecutor.execute(() -> validateMessage(m, g));
|
||||
}
|
||||
|
||||
@ValidationExecutor
|
||||
@@ -285,12 +260,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
|
||||
private void storeMessageContextAsync(final Message m, final ClientId c,
|
||||
final MessageContext result) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
storeMessageContext(m, c, result);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> storeMessageContext(m, c, result));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -385,12 +355,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
private void shareOutstandingMessagesAsync(final ClientId c) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shareOutstandingMessages(c);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> shareOutstandingMessages(c));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -418,12 +383,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
*/
|
||||
private void shareNextMessageAsync(final Queue<MessageId> toShare) {
|
||||
if (toShare.isEmpty()) return;
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shareNextMessage(toShare);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> shareNextMessage(toShare));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -452,12 +412,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
|
||||
private void invalidateNextMessageAsync(final Queue<MessageId> invalidate) {
|
||||
if (invalidate.isEmpty()) return;
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
invalidateNextMessage(invalidate);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> invalidateNextMessage(invalidate));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -513,12 +468,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
private void loadGroupAndValidateAsync(final Message m) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadGroupAndValidate(m);
|
||||
}
|
||||
});
|
||||
dbExecutor.execute(() -> loadGroupAndValidate(m));
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
|
||||
@@ -157,12 +157,8 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
|
||||
private void removeContact(final ContactId c) {
|
||||
activeContacts.remove(c);
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (TransportKeyManager m : managers.values())
|
||||
m.removeContact(c);
|
||||
}
|
||||
dbExecutor.execute(() -> {
|
||||
for (TransportKeyManager m : managers.values()) m.removeContact(c);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,32 +134,22 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
}
|
||||
|
||||
private void scheduleKeyRotation(long now) {
|
||||
Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rotateKeys();
|
||||
}
|
||||
};
|
||||
long delay = rotationPeriodLength - now % rotationPeriodLength;
|
||||
scheduler.schedule(task, delay, MILLISECONDS);
|
||||
scheduler.schedule((Runnable) this::rotateKeys, delay, MILLISECONDS);
|
||||
}
|
||||
|
||||
private void rotateKeys() {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
rotateKeys(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
rotateKeys(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,12 +28,9 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
||||
final CountDownLatch latch = new CountDownLatch(TASKS);
|
||||
for (int i = 0; i < TASKS; i++) {
|
||||
final int result = i;
|
||||
polite.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add(result);
|
||||
latch.countDown();
|
||||
}
|
||||
polite.execute(() -> {
|
||||
list.add(result);
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
// Wait for all the tasks to finish
|
||||
@@ -53,12 +50,9 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
||||
final CountDownLatch latch = new CountDownLatch(TASKS);
|
||||
for (int i = 0; i < TASKS; i++) {
|
||||
final int result = i;
|
||||
polite.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.add(result);
|
||||
latch.countDown();
|
||||
}
|
||||
polite.execute(() -> {
|
||||
list.add(result);
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
// Wait for all the tasks to finish
|
||||
@@ -78,18 +72,15 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
||||
for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1);
|
||||
for (int i = 0; i < TASKS; i++) {
|
||||
final int result = i;
|
||||
polite.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Each task waits for the next task, if any, to finish
|
||||
if (result < TASKS - 1) latches[result + 1].await();
|
||||
list.add(result);
|
||||
} catch (InterruptedException e) {
|
||||
fail();
|
||||
}
|
||||
latches[result].countDown();
|
||||
polite.execute(() -> {
|
||||
try {
|
||||
// Each task waits for the next task, if any, to finish
|
||||
if (result < TASKS - 1) latches[result + 1].await();
|
||||
list.add(result);
|
||||
} catch (InterruptedException e) {
|
||||
fail();
|
||||
}
|
||||
latches[result].countDown();
|
||||
});
|
||||
}
|
||||
// Wait for all the tasks to finish
|
||||
@@ -108,18 +99,15 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
||||
final CountDownLatch latch = new CountDownLatch(TASKS);
|
||||
for (int i = 0; i < TASKS; i++) {
|
||||
final int result = i;
|
||||
polite.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Each task runs faster than the previous task
|
||||
Thread.sleep(TASKS - result);
|
||||
list.add(result);
|
||||
} catch (InterruptedException e) {
|
||||
fail();
|
||||
}
|
||||
latch.countDown();
|
||||
polite.execute(() -> {
|
||||
try {
|
||||
// Each task runs faster than the previous task
|
||||
Thread.sleep(TASKS - result);
|
||||
list.add(result);
|
||||
} catch (InterruptedException e) {
|
||||
fail();
|
||||
}
|
||||
latch.countDown();
|
||||
});
|
||||
}
|
||||
// Wait for all the tasks to finish
|
||||
|
||||
@@ -17,11 +17,7 @@ public class ShutdownManagerImplTest extends BrambleTestCase {
|
||||
ShutdownManager s = createShutdownManager();
|
||||
Set<Integer> handles = new HashSet<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
int handle = s.addShutdownHook(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
});
|
||||
int handle = s.addShutdownHook(() -> {});
|
||||
// The handles should all be distinct
|
||||
assertTrue(handles.add(handle));
|
||||
}
|
||||
|
||||
@@ -113,17 +113,13 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
|
||||
final User32 user32 = (User32) Native.loadLibrary("user32",
|
||||
User32.class, options);
|
||||
// Create a callback to handle the WM_QUERYENDSESSION message
|
||||
WindowProc proc = new WindowProc() {
|
||||
@Override
|
||||
public LRESULT callback(HWND hwnd, int msg, WPARAM wp,
|
||||
LPARAM lp) {
|
||||
if (msg == WM_QUERYENDSESSION) {
|
||||
// It's safe to delay returning from this message
|
||||
runShutdownHooks();
|
||||
}
|
||||
// Pass the message to the default window procedure
|
||||
return user32.DefWindowProc(hwnd, msg, wp, lp);
|
||||
WindowProc proc = (hwnd, msg, wp, lp) -> {
|
||||
if (msg == WM_QUERYENDSESSION) {
|
||||
// It's safe to delay returning from this message
|
||||
runShutdownHooks();
|
||||
}
|
||||
// Pass the message to the default window procedure
|
||||
return user32.DefWindowProc(hwnd, msg, wp, lp);
|
||||
};
|
||||
// Create a native window
|
||||
HWND hwnd = user32.CreateWindowEx(0, "STATIC", "", WS_MINIMIZE,
|
||||
|
||||
@@ -108,33 +108,30 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
// Advertise the Bluetooth address to contacts
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ADDRESS, localDevice.getBluetoothAddress());
|
||||
callback.mergeLocalProperties(p);
|
||||
// Bind a server socket to accept connections from contacts
|
||||
String url = makeUrl("localhost", getUuid());
|
||||
StreamConnectionNotifier ss;
|
||||
try {
|
||||
ss = (StreamConnectionNotifier) Connector.open(url);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
return;
|
||||
}
|
||||
if (!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections(ss);
|
||||
ioExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
// Advertise the Bluetooth address to contacts
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put(PROP_ADDRESS, localDevice.getBluetoothAddress());
|
||||
callback.mergeLocalProperties(p);
|
||||
// Bind a server socket to accept connections from contacts
|
||||
String url = makeUrl("localhost", getUuid());
|
||||
StreamConnectionNotifier ss;
|
||||
try {
|
||||
ss = (StreamConnectionNotifier) Connector.open(url);
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
return;
|
||||
}
|
||||
if (!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
backoff.reset();
|
||||
callback.transportEnabled();
|
||||
acceptContactConnections(ss);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -220,20 +217,18 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
if (StringUtils.isNullOrEmpty(address)) continue;
|
||||
final String uuid = e.getValue().get(PROP_UUID);
|
||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
StreamConnection s = connect(makeUrl(address, uuid));
|
||||
if (s != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, wrapSocket(s));
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
StreamConnection s = connect(makeUrl(address, uuid));
|
||||
if (s != null) {
|
||||
backoff.reset();
|
||||
callback.outgoingConnectionCreated(c, wrapSocket(s));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StreamConnection connect(String url) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + url);
|
||||
try {
|
||||
@@ -341,16 +336,13 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
|
||||
@Override
|
||||
public Callable<KeyAgreementConnection> listen() {
|
||||
return new Callable<KeyAgreementConnection>() {
|
||||
@Override
|
||||
public KeyAgreementConnection call() throws Exception {
|
||||
StreamConnection s = ss.acceptAndOpen();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(ID.getString() + ": Incoming connection");
|
||||
return new KeyAgreementConnection(
|
||||
new BluetoothTransportConnection(
|
||||
BluetoothPlugin.this, s), ID);
|
||||
}
|
||||
return () -> {
|
||||
StreamConnection s = ss.acceptAndOpen();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(ID.getString() + ": Incoming connection");
|
||||
return new KeyAgreementConnection(
|
||||
new BluetoothTransportConnection(
|
||||
BluetoothPlugin.this, s), ID);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -390,15 +390,12 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
lock.unlock();
|
||||
}
|
||||
} else if (s.equals("RING")) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
answer();
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
try {
|
||||
answer();
|
||||
} catch (IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -138,16 +137,13 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
@Override
|
||||
public void stopService() throws ServiceException {
|
||||
// Clear all notifications
|
||||
Future<Void> f = androidExecutor.runOnUiThread(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() {
|
||||
clearContactNotification();
|
||||
clearGroupMessageNotification();
|
||||
clearForumPostNotification();
|
||||
clearBlogPostNotification();
|
||||
clearIntroductionSuccessNotification();
|
||||
return null;
|
||||
}
|
||||
Future<Void> f = androidExecutor.runOnUiThread(() -> {
|
||||
clearContactNotification();
|
||||
clearGroupMessageNotification();
|
||||
clearForumPostNotification();
|
||||
clearBlogPostNotification();
|
||||
clearIntroductionSuccessNotification();
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
f.get();
|
||||
@@ -236,44 +232,35 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
}
|
||||
|
||||
private void loadSettings() {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showContactNotification(final ContactId c) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (blockContacts) return;
|
||||
if (c.equals(blockedContact)) return;
|
||||
Integer count = contactCounts.get(c);
|
||||
if (count == null) contactCounts.put(c, 1);
|
||||
else contactCounts.put(c, count + 1);
|
||||
contactTotal++;
|
||||
updateContactNotification(true);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (blockContacts) return;
|
||||
if (c.equals(blockedContact)) return;
|
||||
Integer count = contactCounts.get(c);
|
||||
if (count == null) contactCounts.put(c, 1);
|
||||
else contactCounts.put(c, count + 1);
|
||||
contactTotal++;
|
||||
updateContactNotification(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearContactNotification(final ContactId c) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = contactCounts.remove(c);
|
||||
if (count == null) return; // Already cleared
|
||||
contactTotal -= count;
|
||||
updateContactNotification(false);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
Integer count = contactCounts.remove(c);
|
||||
if (count == null) return; // Already cleared
|
||||
contactTotal -= count;
|
||||
updateContactNotification(false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -358,40 +345,30 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Override
|
||||
public void clearAllContactNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearContactNotification();
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread(
|
||||
(Runnable) this::clearContactNotification);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void showGroupMessageNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (blockGroups) return;
|
||||
if (g.equals(blockedGroup)) return;
|
||||
Integer count = groupCounts.get(g);
|
||||
if (count == null) groupCounts.put(g, 1);
|
||||
else groupCounts.put(g, count + 1);
|
||||
groupTotal++;
|
||||
updateGroupMessageNotification(true);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (blockGroups) return;
|
||||
if (g.equals(blockedGroup)) return;
|
||||
Integer count = groupCounts.get(g);
|
||||
if (count == null) groupCounts.put(g, 1);
|
||||
else groupCounts.put(g, count + 1);
|
||||
groupTotal++;
|
||||
updateGroupMessageNotification(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearGroupMessageNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = groupCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
groupTotal -= count;
|
||||
updateGroupMessageNotification(false);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
Integer count = groupCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
groupTotal -= count;
|
||||
updateGroupMessageNotification(false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -445,40 +422,30 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Override
|
||||
public void clearAllGroupMessageNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearGroupMessageNotification();
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread(
|
||||
(Runnable) this::clearGroupMessageNotification);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void showForumPostNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (blockForums) return;
|
||||
if (g.equals(blockedGroup)) return;
|
||||
Integer count = forumCounts.get(g);
|
||||
if (count == null) forumCounts.put(g, 1);
|
||||
else forumCounts.put(g, count + 1);
|
||||
forumTotal++;
|
||||
updateForumPostNotification(true);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (blockForums) return;
|
||||
if (g.equals(blockedGroup)) return;
|
||||
Integer count = forumCounts.get(g);
|
||||
if (count == null) forumCounts.put(g, 1);
|
||||
else forumCounts.put(g, count + 1);
|
||||
forumTotal++;
|
||||
updateForumPostNotification(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearForumPostNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = forumCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
forumTotal -= count;
|
||||
updateForumPostNotification(false);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
Integer count = forumCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
forumTotal -= count;
|
||||
updateForumPostNotification(false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -532,40 +499,30 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Override
|
||||
public void clearAllForumPostNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearForumPostNotification();
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread(
|
||||
(Runnable) this::clearForumPostNotification);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void showBlogPostNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (blockBlogs) return;
|
||||
if (g.equals(blockedGroup)) return;
|
||||
Integer count = blogCounts.get(g);
|
||||
if (count == null) blogCounts.put(g, 1);
|
||||
else blogCounts.put(g, count + 1);
|
||||
blogTotal++;
|
||||
updateBlogPostNotification(true);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (blockBlogs) return;
|
||||
if (g.equals(blockedGroup)) return;
|
||||
Integer count = blogCounts.get(g);
|
||||
if (count == null) blogCounts.put(g, 1);
|
||||
else blogCounts.put(g, count + 1);
|
||||
blogTotal++;
|
||||
updateBlogPostNotification(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBlogPostNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = blogCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
blogTotal -= count;
|
||||
updateBlogPostNotification(false);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
Integer count = blogCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
blogTotal -= count;
|
||||
updateBlogPostNotification(false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -606,22 +563,15 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Override
|
||||
public void clearAllBlogPostNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearBlogPostNotification();
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread(
|
||||
(Runnable) this::clearBlogPostNotification);
|
||||
}
|
||||
|
||||
private void showIntroductionNotification() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (blockIntroductions) return;
|
||||
introductionTotal++;
|
||||
updateIntroductionNotification();
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (blockIntroductions) return;
|
||||
introductionTotal++;
|
||||
updateIntroductionNotification();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -656,71 +606,41 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Override
|
||||
public void clearAllIntroductionNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearIntroductionSuccessNotification();
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread(
|
||||
this::clearIntroductionSuccessNotification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
blockedGroup = g;
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread((Runnable) () -> blockedGroup = g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unblockNotification(final GroupId g) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (g.equals(blockedGroup)) blockedGroup = null;
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (g.equals(blockedGroup)) blockedGroup = null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockContactNotification(final ContactId c) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
blockedContact = c;
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread((Runnable) () -> blockedContact = c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unblockContactNotification(final ContactId c) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (c.equals(blockedContact)) blockedContact = null;
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
if (c.equals(blockedContact)) blockedContact = null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockAllBlogPostNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
blockBlogs = true;
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread((Runnable) () -> blockBlogs = true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unblockAllBlogPostNotifications() {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
blockBlogs = false;
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnUiThread((Runnable) () -> blockBlogs = false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,33 +112,30 @@ public class BriarService extends Service {
|
||||
}
|
||||
|
||||
private void showStartupFailureNotification(final StartResult result) {
|
||||
androidExecutor.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCompat.Builder b =
|
||||
new NotificationCompat.Builder(BriarService.this);
|
||||
b.setSmallIcon(android.R.drawable.stat_notify_error);
|
||||
b.setContentTitle(getText(
|
||||
R.string.startup_failed_notification_title));
|
||||
b.setContentText(getText(
|
||||
R.string.startup_failed_notification_text));
|
||||
Intent i = new Intent(BriarService.this,
|
||||
StartupFailureActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
i.putExtra("briar.START_RESULT", result);
|
||||
i.putExtra("briar.FAILURE_NOTIFICATION_ID",
|
||||
FAILURE_NOTIFICATION_ID);
|
||||
b.setContentIntent(PendingIntent.getActivity(BriarService.this,
|
||||
0, i, FLAG_UPDATE_CURRENT));
|
||||
Object o = getSystemService(NOTIFICATION_SERVICE);
|
||||
NotificationManager nm = (NotificationManager) o;
|
||||
nm.notify(FAILURE_NOTIFICATION_ID, b.build());
|
||||
// Bring the dashboard to the front to clear the back stack
|
||||
i = new Intent(BriarService.this, NavDrawerActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||
i.putExtra("briar.STARTUP_FAILED", true);
|
||||
startActivity(i);
|
||||
}
|
||||
androidExecutor.runOnUiThread(() -> {
|
||||
NotificationCompat.Builder b =
|
||||
new NotificationCompat.Builder(BriarService.this);
|
||||
b.setSmallIcon(android.R.drawable.stat_notify_error);
|
||||
b.setContentTitle(getText(
|
||||
R.string.startup_failed_notification_title));
|
||||
b.setContentText(getText(
|
||||
R.string.startup_failed_notification_text));
|
||||
Intent i = new Intent(BriarService.this,
|
||||
StartupFailureActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
i.putExtra("briar.START_RESULT", result);
|
||||
i.putExtra("briar.FAILURE_NOTIFICATION_ID",
|
||||
FAILURE_NOTIFICATION_ID);
|
||||
b.setContentIntent(PendingIntent.getActivity(BriarService.this,
|
||||
0, i, FLAG_UPDATE_CURRENT));
|
||||
Object o = getSystemService(NOTIFICATION_SERVICE);
|
||||
NotificationManager nm = (NotificationManager) o;
|
||||
nm.notify(FAILURE_NOTIFICATION_ID, b.build());
|
||||
// Bring the dashboard to the front to clear the back stack
|
||||
i = new Intent(BriarService.this, NavDrawerActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||
i.putExtra("briar.STARTUP_FAILED", true);
|
||||
startActivity(i);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -152,11 +152,8 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void runOnUiThreadUnlessDestroyed(final Runnable r) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!destroyed && !isFinishing()) r.run();
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
if (!destroyed && !isFinishing()) r.run();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.view.Window;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.controller.BriarController;
|
||||
import org.briarproject.briar.android.controller.DbController;
|
||||
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
import org.briarproject.briar.android.login.PasswordActivity;
|
||||
import org.briarproject.briar.android.panic.ExitActivity;
|
||||
|
||||
@@ -102,17 +101,8 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
if (briarController.hasEncryptionKey()) {
|
||||
// Don't use UiResultHandler because we want the result even if
|
||||
// this activity has been destroyed
|
||||
briarController.signOut(new ResultHandler<Void>() {
|
||||
@Override
|
||||
public void onResult(Void result) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
exit(removeFromRecentApps);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
briarController.signOut(result -> runOnUiThread(
|
||||
() -> exit(removeFromRecentApps)));
|
||||
} else {
|
||||
exit(removeFromRecentApps);
|
||||
}
|
||||
@@ -146,11 +136,6 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
|
||||
@Deprecated
|
||||
protected void finishOnUiThread() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(this::supportFinishAfterTransition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,38 +85,25 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
||||
}
|
||||
|
||||
void onBlogPostAdded(final BlogPostHeader h, final boolean local) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onBlogPostAdded(h, local);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onBlogPostAdded(h, local));
|
||||
}
|
||||
|
||||
void onBlogRemoved() {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onBlogRemoved();
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> listener.onBlogRemoved());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void loadBlogPosts(final GroupId groupId,
|
||||
final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<BlogPostItem> items = loadItems(groupId);
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Collection<BlogPostItem> items = loadItems(groupId);
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -151,21 +138,18 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
||||
handler.onResult(new BlogPostItem(header, body));
|
||||
return;
|
||||
}
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
BlogPostItem item = getItem(header);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading body took " + duration + " ms");
|
||||
handler.onResult(item);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
BlogPostItem item = getItem(header);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading body took " + duration + " ms");
|
||||
handler.onResult(item);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -180,22 +164,19 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
||||
loadBlogPost(header, handler);
|
||||
return;
|
||||
}
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
BlogPostHeader header = getPostHeader(g, m);
|
||||
BlogPostItem item = getItem(header);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading post took " + duration + " ms");
|
||||
handler.onResult(item);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
BlogPostHeader header1 = getPostHeader(g, m);
|
||||
BlogPostItem item = getItem(header1);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading post took " + duration + " ms");
|
||||
handler.onResult(item);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -204,19 +185,16 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
||||
public void repeatPost(final BlogPostItem item,
|
||||
final @Nullable String comment,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
Blog b = blogManager.getPersonalBlog(a);
|
||||
BlogPostHeader h = item.getHeader();
|
||||
blogManager.addLocalComment(a, b.getId(), comment, h);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
Blog b = blogManager.getPersonalBlog(a);
|
||||
BlogPostHeader h = item.getHeader();
|
||||
blogManager.addLocalComment(a, b.getId(), comment, h);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -99,13 +99,10 @@ abstract class BasePostFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
private void startPeriodicUpdate() {
|
||||
refresher = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Updating Content...");
|
||||
ui.updateDate(post.getTimestamp());
|
||||
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
|
||||
}
|
||||
refresher = () -> {
|
||||
LOG.info("Updating Content...");
|
||||
ui.updateDate(post.getTimestamp());
|
||||
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
|
||||
};
|
||||
LOG.info("Adding Handler Callback");
|
||||
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.blog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
@@ -41,16 +40,12 @@ public class BlogActivity extends BriarActivity
|
||||
|
||||
// Open Sharing Status on Toolbar click
|
||||
if (toolbar != null) {
|
||||
toolbar.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(BlogActivity.this,
|
||||
BlogSharingStatusActivity.class);
|
||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
});
|
||||
toolbar.setOnClickListener(v -> {
|
||||
Intent i1 = new Intent(BlogActivity.this,
|
||||
BlogSharingStatusActivity.class);
|
||||
i1.putExtra(GROUP_ID, groupId.getBytes());
|
||||
startActivity(i1);
|
||||
});
|
||||
}
|
||||
|
||||
if (state == null) {
|
||||
|
||||
@@ -126,21 +126,12 @@ class BlogControllerImpl extends BaseControllerImpl
|
||||
}
|
||||
|
||||
private void onBlogInvitationAccepted(final ContactId c) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onBlogInvitationAccepted(c);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onBlogInvitationAccepted(c));
|
||||
}
|
||||
|
||||
private void onBlogLeft(final ContactId c) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onBlogLeft(c);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> listener.onBlogLeft(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,25 +152,22 @@ class BlogControllerImpl extends BaseControllerImpl
|
||||
public void loadBlog(
|
||||
final ResultExceptionHandler<BlogItem, DbException> handler) {
|
||||
if (groupId == null) throw new IllegalStateException();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
Blog b = blogManager.getBlog(groupId);
|
||||
boolean ours = a.getId().equals(b.getAuthor().getId());
|
||||
boolean removable = blogManager.canBeRemoved(b);
|
||||
BlogItem blog = new BlogItem(b, ours, removable);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading blog took " + duration + " ms");
|
||||
handler.onResult(blog);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
Blog b = blogManager.getBlog(groupId);
|
||||
boolean ours = a.getId().equals(b.getAuthor().getId());
|
||||
boolean removable = blogManager.canBeRemoved(b);
|
||||
BlogItem blog = new BlogItem(b, ours, removable);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading blog took " + duration + " ms");
|
||||
handler.onResult(blog);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -188,22 +176,19 @@ class BlogControllerImpl extends BaseControllerImpl
|
||||
public void deleteBlog(
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
if (groupId == null) throw new IllegalStateException();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Blog b = blogManager.getBlog(groupId);
|
||||
blogManager.removeBlog(b);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Removing blog took " + duration + " ms");
|
||||
handler.onResult(null);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Blog b = blogManager.getBlog(groupId);
|
||||
blogManager.removeBlog(b);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Removing blog took " + duration + " ms");
|
||||
handler.onResult(null);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -212,21 +197,18 @@ class BlogControllerImpl extends BaseControllerImpl
|
||||
public void loadSharingContacts(
|
||||
final ResultExceptionHandler<Collection<ContactId>, DbException> handler) {
|
||||
if (groupId == null) throw new IllegalStateException();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<Contact> contacts =
|
||||
blogSharingManager.getSharedWith(groupId);
|
||||
Collection<ContactId> contactIds =
|
||||
new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) contactIds.add(c.getId());
|
||||
handler.onResult(contactIds);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Collection<Contact> contacts =
|
||||
blogSharingManager.getSharedWith(groupId);
|
||||
Collection<ContactId> contactIds =
|
||||
new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) contactIds.add(c.getId());
|
||||
handler.onResult(contactIds);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -331,12 +331,7 @@ public class BlogFragment extends BaseFragment
|
||||
Snackbar.make(list, stringId, Snackbar.LENGTH_LONG);
|
||||
snackbar.getView().setBackgroundResource(R.color.briar_primary);
|
||||
if (scroll) {
|
||||
View.OnClickListener onClick = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
list.smoothScrollToPosition(0);
|
||||
}
|
||||
};
|
||||
View.OnClickListener onClick = v -> list.smoothScrollToPosition(0);
|
||||
snackbar.setActionTextColor(ContextCompat
|
||||
.getColor(getContext(),
|
||||
R.color.briar_button_positive));
|
||||
@@ -347,12 +342,7 @@ public class BlogFragment extends BaseFragment
|
||||
|
||||
private void showDeleteDialog() {
|
||||
DialogInterface.OnClickListener okListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
deleteBlog();
|
||||
}
|
||||
};
|
||||
(dialog, which) -> deleteBlog();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(getString(R.string.blogs_remove_blog));
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Spanned;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@@ -95,12 +94,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
setTransitionName(item.getId());
|
||||
if (!fullText) {
|
||||
layout.setClickable(true);
|
||||
layout.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onBlogPostClick(item);
|
||||
}
|
||||
});
|
||||
layout.setOnClickListener(v -> listener.onBlogPostClick(item));
|
||||
}
|
||||
|
||||
// author and date
|
||||
@@ -113,12 +107,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
||||
// TODO make author clickable more often #624
|
||||
if (!fullText && item.getHeader().getType() == POST) {
|
||||
author.setAuthorClickable(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onAuthorClick(item);
|
||||
}
|
||||
});
|
||||
author.setAuthorClickable(v -> listener.onAuthorClick(item));
|
||||
} else {
|
||||
author.setAuthorNotClickable();
|
||||
}
|
||||
@@ -137,23 +126,20 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
}
|
||||
|
||||
// reblog button
|
||||
reblogButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(ctx, ReblogActivity.class);
|
||||
i.putExtra(GROUP_ID, item.getGroupId().getBytes());
|
||||
i.putExtra(POST_ID, item.getId().getBytes());
|
||||
reblogButton.setOnClickListener(v -> {
|
||||
Intent i = new Intent(ctx, ReblogActivity.class);
|
||||
i.putExtra(GROUP_ID, item.getGroupId().getBytes());
|
||||
i.putExtra(POST_ID, item.getId().getBytes());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
ActivityOptionsCompat options =
|
||||
makeSceneTransitionAnimation((Activity) ctx, layout,
|
||||
getTransitionName(item.getId()));
|
||||
ActivityCompat.startActivity((Activity) ctx, i,
|
||||
options.toBundle());
|
||||
} else {
|
||||
// work-around for android bug #224270
|
||||
ctx.startActivity(i);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
ActivityOptionsCompat options =
|
||||
makeSceneTransitionAnimation((Activity) ctx, layout,
|
||||
getTransitionName(item.getId()));
|
||||
ActivityCompat.startActivity((Activity) ctx, i,
|
||||
options.toBundle());
|
||||
} else {
|
||||
// work-around for android bug #224270
|
||||
ctx.startActivity(i);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -172,12 +158,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
reblogger.setAuthorStatus(item.getAuthorStatus());
|
||||
reblogger.setDate(item.getTimestamp());
|
||||
if (!fullText) {
|
||||
reblogger.setAuthorClickable(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onAuthorClick(item);
|
||||
}
|
||||
});
|
||||
reblogger.setAuthorClickable(v -> listener.onAuthorClick(item));
|
||||
}
|
||||
reblogger.setVisibility(VISIBLE);
|
||||
reblogger.setPersona(AuthorView.REBLOGGER);
|
||||
|
||||
@@ -91,40 +91,31 @@ class FeedControllerImpl extends BaseControllerImpl
|
||||
}
|
||||
|
||||
private void onBlogAdded() {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onBlogAdded();
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> listener.onBlogAdded());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBlogPosts(
|
||||
final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<BlogPostItem> posts = new ArrayList<>();
|
||||
for (Blog b : blogManager.getBlogs()) {
|
||||
try {
|
||||
posts.addAll(loadItems(b.getId()));
|
||||
} catch (NoSuchGroupException | NoSuchMessageException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<BlogPostItem> posts = new ArrayList<>();
|
||||
for (Blog b : blogManager.getBlogs()) {
|
||||
try {
|
||||
posts.addAll(loadItems(b.getId()));
|
||||
} catch (NoSuchGroupException | NoSuchMessageException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading all posts took " + duration + " ms");
|
||||
handler.onResult(posts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading all posts took " + duration + " ms");
|
||||
handler.onResult(posts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -132,22 +123,18 @@ class FeedControllerImpl extends BaseControllerImpl
|
||||
@Override
|
||||
public void loadPersonalBlog(
|
||||
final ResultExceptionHandler<Blog, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Author a = identityManager.getLocalAuthor();
|
||||
Blog b = blogManager.getPersonalBlog(a);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading blog took " + duration + " ms");
|
||||
handler.onResult(b);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Author a = identityManager.getLocalAuthor();
|
||||
Blog b = blogManager.getPersonalBlog(a);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading blog took " + duration + " ms");
|
||||
handler.onResult(b);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -246,12 +246,7 @@ public class FeedFragment extends BaseFragment implements
|
||||
Snackbar s = Snackbar.make(list, stringRes, LENGTH_LONG);
|
||||
s.getView().setBackgroundResource(R.color.briar_primary);
|
||||
if (scroll) {
|
||||
OnClickListener onClick = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
list.smoothScrollToPosition(0);
|
||||
}
|
||||
};
|
||||
OnClickListener onClick = v -> list.smoothScrollToPosition(0);
|
||||
s.setActionTextColor(ContextCompat
|
||||
.getColor(getContext(),
|
||||
R.color.briar_button_positive));
|
||||
|
||||
@@ -114,12 +114,7 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
|
||||
|
||||
ui.input.setListener(this);
|
||||
ui.input.setSendButtonEnabled(true);
|
||||
ui.scrollView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ui.scrollView.fullScroll(FOCUS_DOWN);
|
||||
}
|
||||
});
|
||||
ui.scrollView.post(() -> ui.scrollView.fullScroll(FOCUS_DOWN));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
@@ -42,12 +41,7 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
||||
ui.title.setText(item.getTitle());
|
||||
|
||||
// Delete Button
|
||||
ui.delete.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onDeleteClick(item);
|
||||
}
|
||||
});
|
||||
ui.delete.setOnClickListener(v -> listener.onDeleteClick(item));
|
||||
|
||||
// Author
|
||||
if (item.getAuthor() != null) {
|
||||
@@ -72,12 +66,7 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
|
||||
}
|
||||
|
||||
// Open feed's blog when clicked
|
||||
ui.layout.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onFeedClick(item);
|
||||
}
|
||||
});
|
||||
ui.layout.setOnClickListener(v -> listener.onFeedClick(item));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.android.blog;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
@@ -8,7 +7,6 @@ import android.text.TextWatcher;
|
||||
import android.util.Patterns;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
@@ -75,12 +73,7 @@ public class RssFeedImportActivity extends BriarActivity {
|
||||
});
|
||||
|
||||
importButton = (Button) findViewById(R.id.importButton);
|
||||
importButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
publish();
|
||||
}
|
||||
});
|
||||
importButton.setOnClickListener(v -> publish());
|
||||
|
||||
progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||
}
|
||||
@@ -126,54 +119,37 @@ public class RssFeedImportActivity extends BriarActivity {
|
||||
}
|
||||
|
||||
private void importFeed(final String url) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
feedManager.addFeed(url);
|
||||
feedImported();
|
||||
} catch (DbException | IOException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
importFailed();
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
try {
|
||||
feedManager.addFeed(url);
|
||||
feedImported();
|
||||
} catch (DbException | IOException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
importFailed();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void feedImported() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(this::supportFinishAfterTransition);
|
||||
}
|
||||
|
||||
private void importFailed() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// hide progress bar, show publish button
|
||||
progressBar.setVisibility(GONE);
|
||||
importButton.setVisibility(VISIBLE);
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
// hide progress bar, show publish button
|
||||
progressBar.setVisibility(GONE);
|
||||
importButton.setVisibility(VISIBLE);
|
||||
|
||||
// show error dialog
|
||||
AlertDialog.Builder builder =
|
||||
new AlertDialog.Builder(RssFeedImportActivity.this,
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setMessage(R.string.blogs_rss_feeds_import_error);
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setPositiveButton(R.string.try_again_button,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
publish();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
// show error dialog
|
||||
AlertDialog.Builder builder =
|
||||
new AlertDialog.Builder(RssFeedImportActivity.this,
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setMessage(R.string.blogs_rss_feeds_import_error);
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setPositiveButton(R.string.try_again_button,
|
||||
(dialog, which) -> publish());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -105,12 +105,7 @@ public class RssFeedManageActivity extends BriarActivity
|
||||
@Override
|
||||
public void onDeleteClick(final Feed feed) {
|
||||
DialogInterface.OnClickListener okListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
deleteFeed(feed);
|
||||
}
|
||||
};
|
||||
(dialog, which) -> deleteFeed(feed);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this,
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(getString(R.string.blogs_rss_remove_feed));
|
||||
@@ -124,81 +119,59 @@ public class RssFeedManageActivity extends BriarActivity
|
||||
|
||||
private void loadFeeds() {
|
||||
final int revision = adapter.getRevision();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
displayFeeds(revision, feedManager.getFeeds());
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
onLoadError();
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
displayFeeds(revision, feedManager.getFeeds());
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
onLoadError();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayFeeds(final int revision, final List<Feed> feeds) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (feeds.isEmpty()) list.showData();
|
||||
else adapter.addAll(feeds);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadFeeds();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (feeds.isEmpty()) list.showData();
|
||||
else adapter.addAll(feeds);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadFeeds();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void deleteFeed(final Feed feed) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
feedManager.removeFeed(feed);
|
||||
onFeedDeleted(feed);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
onDeleteError();
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
feedManager.removeFeed(feed);
|
||||
onFeedDeleted(feed);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
onDeleteError();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onLoadError() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.setEmptyText(R.string.blogs_rss_feeds_manage_error);
|
||||
list.showData();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
list.setEmptyText(R.string.blogs_rss_feeds_manage_error);
|
||||
list.showData();
|
||||
});
|
||||
}
|
||||
|
||||
private void onFeedDeleted(final Feed feed) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
adapter.remove(feed);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
adapter.remove(feed);
|
||||
});
|
||||
}
|
||||
|
||||
private void onDeleteError() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Snackbar.make(list,
|
||||
R.string.blogs_rss_feeds_manage_delete_error,
|
||||
LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(() -> Snackbar.make(list,
|
||||
R.string.blogs_rss_feeds_manage_delete_error,
|
||||
LENGTH_LONG).show());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,44 +141,35 @@ public class WriteBlogPostActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void storePost(final String body) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long now = System.currentTimeMillis();
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
BlogPost p = blogPostFactory
|
||||
.createBlogPost(groupId, now, null, author, body);
|
||||
blogManager.addLocalPost(p);
|
||||
postPublished();
|
||||
} catch (DbException | GeneralSecurityException | FormatException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
postFailedToPublish();
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
long now = System.currentTimeMillis();
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
BlogPost p = blogPostFactory
|
||||
.createBlogPost(groupId, now, null, author, body);
|
||||
blogManager.addLocalPost(p);
|
||||
postPublished();
|
||||
} catch (DbException | GeneralSecurityException
|
||||
| FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
postFailedToPublish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void postPublished() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setResult(RESULT_OK);
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
setResult(RESULT_OK);
|
||||
supportFinishAfterTransition();
|
||||
});
|
||||
}
|
||||
|
||||
private void postFailedToPublish() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// hide progress bar, show publish button
|
||||
progressBar.setVisibility(GONE);
|
||||
input.setVisibility(VISIBLE);
|
||||
// TODO show error
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
// hide progress bar, show publish button
|
||||
progressBar.setVisibility(GONE);
|
||||
input.setVisibility(VISIBLE);
|
||||
// TODO show error
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,11 +54,8 @@ public class ContactItemViewHolder<I extends ContactItem>
|
||||
}
|
||||
}
|
||||
|
||||
layout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) listener.onItemClick(avatar, item);
|
||||
}
|
||||
layout.setOnClickListener(v -> {
|
||||
if (listener != null) listener.onItemClick(avatar, item);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -114,36 +114,32 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
View contentView = inflater.inflate(R.layout.list, container, false);
|
||||
|
||||
OnContactClickListener<ContactListItem> onContactClickListener =
|
||||
new OnContactClickListener<ContactListItem>() {
|
||||
@Override
|
||||
public void onItemClick(View view, ContactListItem item) {
|
||||
Intent i = new Intent(getActivity(),
|
||||
ConversationActivity.class);
|
||||
ContactId contactId = item.getContact().getId();
|
||||
i.putExtra(CONTACT_ID, contactId.getInt());
|
||||
(view, item) -> {
|
||||
Intent i = new Intent(getActivity(),
|
||||
ConversationActivity.class);
|
||||
ContactId contactId = item.getContact().getId();
|
||||
i.putExtra(CONTACT_ID, contactId.getInt());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
ContactListItemViewHolder holder =
|
||||
(ContactListItemViewHolder) list
|
||||
.getRecyclerView()
|
||||
.findViewHolderForAdapterPosition(
|
||||
adapter.findItemPosition(
|
||||
item));
|
||||
Pair<View, String> avatar =
|
||||
Pair.create((View) holder.avatar,
|
||||
getTransitionName(holder.avatar));
|
||||
Pair<View, String> bulb =
|
||||
Pair.create((View) holder.bulb,
|
||||
getTransitionName(holder.bulb));
|
||||
ActivityOptionsCompat options =
|
||||
makeSceneTransitionAnimation(getActivity(),
|
||||
avatar, bulb);
|
||||
ActivityCompat.startActivity(getActivity(), i,
|
||||
options.toBundle());
|
||||
} else {
|
||||
// work-around for android bug #224270
|
||||
startActivity(i);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
ContactListItemViewHolder holder =
|
||||
(ContactListItemViewHolder) list
|
||||
.getRecyclerView()
|
||||
.findViewHolderForAdapterPosition(
|
||||
adapter.findItemPosition(item));
|
||||
Pair<View, String> avatar =
|
||||
Pair.create(holder.avatar,
|
||||
getTransitionName(holder.avatar));
|
||||
Pair<View, String> bulb =
|
||||
Pair.create(holder.bulb,
|
||||
getTransitionName(holder.bulb));
|
||||
ActivityOptionsCompat options =
|
||||
makeSceneTransitionAnimation(getActivity(),
|
||||
avatar, bulb);
|
||||
ActivityCompat.startActivity(getActivity(), i,
|
||||
options.toBundle());
|
||||
} else {
|
||||
// work-around for android bug #224270
|
||||
startActivity(i);
|
||||
}
|
||||
};
|
||||
adapter = new ContactListAdapter(getContext(), onContactClickListener);
|
||||
@@ -196,50 +192,42 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
|
||||
private void loadContacts() {
|
||||
final int revision = adapter.getRevision();
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
List<ContactListItem> contacts = new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
try {
|
||||
ContactId id = c.getId();
|
||||
GroupCount count =
|
||||
conversationManager.getGroupCount(id);
|
||||
boolean connected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
contacts.add(new ContactListItem(c, connected,
|
||||
count));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
List<ContactListItem> contacts = new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
try {
|
||||
ContactId id = c.getId();
|
||||
GroupCount count =
|
||||
conversationManager.getGroupCount(id);
|
||||
boolean connected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
contacts.add(new ContactListItem(c, connected, count));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Full load took " + duration + " ms");
|
||||
displayContacts(revision, contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Full load took " + duration + " ms");
|
||||
displayContacts(revision, contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayContacts(final int revision,
|
||||
final List<ContactListItem> contacts) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadContacts();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadContacts();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -295,44 +283,35 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
}
|
||||
|
||||
private void updateItem(final ContactId c, final BaseMessageHeader h) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
ContactListItem item = adapter.getItemAt(position);
|
||||
if (item != null) {
|
||||
ConversationItem i = ConversationItem.from(getContext(), h);
|
||||
item.addMessage(i);
|
||||
adapter.updateItemAt(position, item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
ContactListItem item = adapter.getItemAt(position);
|
||||
if (item != null) {
|
||||
ConversationItem i = ConversationItem.from(getContext(), h);
|
||||
item.addMessage(i);
|
||||
adapter.updateItemAt(position, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeItem(final ContactId c) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
ContactListItem item = adapter.getItemAt(position);
|
||||
if (item != null) adapter.remove(item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
ContactListItem item = adapter.getItemAt(position);
|
||||
if (item != null) adapter.remove(item);
|
||||
});
|
||||
}
|
||||
|
||||
private void setConnected(final ContactId c, final boolean connected) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
ContactListItem item = adapter.getItemAt(position);
|
||||
if (item != null) {
|
||||
item.setConnected(connected);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
ContactListItem item = adapter.getItemAt(position);
|
||||
if (item != null) {
|
||||
item.setConnected(connected);
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -289,102 +289,83 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void loadContactDetailsAndMessages() {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
if (contactName == null || contactAuthorId == null) {
|
||||
Contact contact = contactManager.getContact(contactId);
|
||||
contactName = contact.getAuthor().getName();
|
||||
contactAuthorId = contact.getAuthor().getId();
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading contact took " + duration + " ms");
|
||||
loadMessages();
|
||||
displayContactDetails();
|
||||
} catch (NoSuchContactException e) {
|
||||
finishOnUiThread();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
if (contactName == null || contactAuthorId == null) {
|
||||
Contact contact = contactManager.getContact(contactId);
|
||||
contactName = contact.getAuthor().getName();
|
||||
contactAuthorId = contact.getAuthor().getId();
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading contact took " + duration + " ms");
|
||||
loadMessages();
|
||||
displayContactDetails();
|
||||
} catch (NoSuchContactException e) {
|
||||
finishOnUiThread();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayContactDetails() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//noinspection ConstantConditions
|
||||
toolbarAvatar.setImageDrawable(
|
||||
new IdenticonDrawable(contactAuthorId.getBytes()));
|
||||
toolbarTitle.setText(contactName);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
//noinspection ConstantConditions
|
||||
toolbarAvatar.setImageDrawable(
|
||||
new IdenticonDrawable(contactAuthorId.getBytes()));
|
||||
toolbarTitle.setText(contactName);
|
||||
});
|
||||
}
|
||||
|
||||
private void displayContactOnlineStatus() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (connectionRegistry.isConnected(contactId)) {
|
||||
toolbarStatus.setImageDrawable(ContextCompat
|
||||
.getDrawable(ConversationActivity.this,
|
||||
R.drawable.contact_online));
|
||||
toolbarStatus
|
||||
.setContentDescription(getString(R.string.online));
|
||||
} else {
|
||||
toolbarStatus.setImageDrawable(ContextCompat
|
||||
.getDrawable(ConversationActivity.this,
|
||||
R.drawable.contact_offline));
|
||||
toolbarStatus
|
||||
.setContentDescription(getString(R.string.offline));
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (connectionRegistry.isConnected(contactId)) {
|
||||
toolbarStatus.setImageDrawable(ContextCompat
|
||||
.getDrawable(ConversationActivity.this,
|
||||
R.drawable.contact_online));
|
||||
toolbarStatus
|
||||
.setContentDescription(getString(R.string.online));
|
||||
} else {
|
||||
toolbarStatus.setImageDrawable(ContextCompat
|
||||
.getDrawable(ConversationActivity.this,
|
||||
R.drawable.contact_offline));
|
||||
toolbarStatus
|
||||
.setContentDescription(getString(R.string.offline));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMessages() {
|
||||
final int revision = adapter.getRevision();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<PrivateMessageHeader> headers =
|
||||
messagingManager.getMessageHeaders(contactId);
|
||||
Collection<IntroductionMessage> introductions =
|
||||
introductionManager
|
||||
.getIntroductionMessages(contactId);
|
||||
Collection<InvitationMessage> forumInvitations =
|
||||
forumSharingManager
|
||||
.getInvitationMessages(contactId);
|
||||
Collection<InvitationMessage> blogInvitations =
|
||||
blogSharingManager
|
||||
.getInvitationMessages(contactId);
|
||||
Collection<InvitationMessage> groupInvitations =
|
||||
groupInvitationManager
|
||||
.getInvitationMessages(contactId);
|
||||
List<InvitationMessage> invitations = new ArrayList<>(
|
||||
forumInvitations.size() + blogInvitations.size() +
|
||||
groupInvitations.size());
|
||||
invitations.addAll(forumInvitations);
|
||||
invitations.addAll(blogInvitations);
|
||||
invitations.addAll(groupInvitations);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading messages took " + duration + " ms");
|
||||
displayMessages(revision, headers, introductions,
|
||||
invitations);
|
||||
} catch (NoSuchContactException e) {
|
||||
finishOnUiThread();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<PrivateMessageHeader> headers =
|
||||
messagingManager.getMessageHeaders(contactId);
|
||||
Collection<IntroductionMessage> introductions =
|
||||
introductionManager.getIntroductionMessages(contactId);
|
||||
Collection<InvitationMessage> forumInvitations =
|
||||
forumSharingManager.getInvitationMessages(contactId);
|
||||
Collection<InvitationMessage> blogInvitations =
|
||||
blogSharingManager.getInvitationMessages(contactId);
|
||||
Collection<InvitationMessage> groupInvitations =
|
||||
groupInvitationManager.getInvitationMessages(contactId);
|
||||
List<InvitationMessage> invitations = new ArrayList<>(
|
||||
forumInvitations.size() + blogInvitations.size() +
|
||||
groupInvitations.size());
|
||||
invitations.addAll(forumInvitations);
|
||||
invitations.addAll(blogInvitations);
|
||||
invitations.addAll(groupInvitations);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading messages took " + duration + " ms");
|
||||
displayMessages(revision, headers, introductions, invitations);
|
||||
} catch (NoSuchContactException e) {
|
||||
finishOnUiThread();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -393,22 +374,19 @@ public class ConversationActivity extends BriarActivity
|
||||
final Collection<PrivateMessageHeader> headers,
|
||||
final Collection<IntroductionMessage> introductions,
|
||||
final Collection<InvitationMessage> invitations) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
textInputView.setSendButtonEnabled(true);
|
||||
List<ConversationItem> items = createItems(headers,
|
||||
introductions, invitations);
|
||||
if (items.isEmpty()) list.showData();
|
||||
else adapter.addAll(items);
|
||||
// Scroll to the bottom
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadMessages();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
textInputView.setSendButtonEnabled(true);
|
||||
List<ConversationItem> items = createItems(headers,
|
||||
introductions, invitations);
|
||||
if (items.isEmpty()) list.showData();
|
||||
else adapter.addAll(items);
|
||||
// Scroll to the bottom
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadMessages();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -459,39 +437,32 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void loadMessageBody(final MessageId m) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
String body = messagingManager.getMessageBody(m);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading body took " + duration + " ms");
|
||||
displayMessageBody(m, body);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
String body = messagingManager.getMessageBody(m);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading body took " + duration + " ms");
|
||||
displayMessageBody(m, body);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayMessageBody(final MessageId m, final String body) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
bodyCache.put(m, body);
|
||||
SparseArray<ConversationItem> messages =
|
||||
adapter.getPrivateMessages();
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
ConversationItem item = messages.valueAt(i);
|
||||
if (item.getId().equals(m)) {
|
||||
item.setBody(body);
|
||||
adapter.notifyItemChanged(messages.keyAt(i));
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
return;
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
bodyCache.put(m, body);
|
||||
SparseArray<ConversationItem> messages =
|
||||
adapter.getPrivateMessages();
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
ConversationItem item = messages.valueAt(i);
|
||||
if (item.getId().equals(m)) {
|
||||
item.setBody(body);
|
||||
adapter.notifyItemChanged(messages.keyAt(i));
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -573,14 +544,11 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void addConversationItem(final ConversationItem item) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
adapter.add(item);
|
||||
// Scroll to the bottom
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
adapter.add(item);
|
||||
// Scroll to the bottom
|
||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -588,24 +556,16 @@ public class ConversationActivity extends BriarActivity
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(final String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName,
|
||||
m);
|
||||
addConversationItem(item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void onFailure(final Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleDbException((DbException) exception);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -614,24 +574,16 @@ public class ConversationActivity extends BriarActivity
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(final String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName,
|
||||
m);
|
||||
addConversationItem(item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void onFailure(final Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleDbException((DbException) exception);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -640,24 +592,16 @@ public class ConversationActivity extends BriarActivity
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(final String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName,
|
||||
m);
|
||||
addConversationItem(item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void onFailure(final Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleDbException((DbException) exception);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -666,44 +610,33 @@ public class ConversationActivity extends BriarActivity
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(final String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName,
|
||||
m);
|
||||
addConversationItem(item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void onFailure(final Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleDbException((DbException) exception);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void markMessages(final Collection<MessageId> messageIds,
|
||||
final boolean sent, final boolean seen) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
Set<MessageId> messages = new HashSet<>(messageIds);
|
||||
SparseArray<ConversationOutItem> list =
|
||||
adapter.getOutgoingMessages();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ConversationOutItem item = list.valueAt(i);
|
||||
if (messages.contains(item.getId())) {
|
||||
item.setSent(sent);
|
||||
item.setSeen(seen);
|
||||
adapter.notifyItemChanged(list.keyAt(i));
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
Set<MessageId> messages = new HashSet<>(messageIds);
|
||||
SparseArray<ConversationOutItem> list =
|
||||
adapter.getOutgoingMessages();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ConversationOutItem item = list.valueAt(i);
|
||||
if (messages.contains(item.getId())) {
|
||||
item.setSent(sent);
|
||||
item.setSeen(seen);
|
||||
adapter.notifyItemChanged(list.keyAt(i));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -727,71 +660,54 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void loadGroupId(final String body, final long timestamp) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
messagingGroupId =
|
||||
messagingManager.getConversationId(contactId);
|
||||
createMessage(body, timestamp);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
messagingGroupId =
|
||||
messagingManager.getConversationId(contactId);
|
||||
createMessage(body, timestamp);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void createMessage(final String body, final long timestamp) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
//noinspection ConstantConditions init in loadGroupId()
|
||||
storeMessage(privateMessageFactory.createPrivateMessage(
|
||||
messagingGroupId, timestamp, body), body);
|
||||
} catch (FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
try {
|
||||
//noinspection ConstantConditions init in loadGroupId()
|
||||
storeMessage(privateMessageFactory.createPrivateMessage(
|
||||
messagingGroupId, timestamp, body), body);
|
||||
} catch (FormatException e) {throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void storeMessage(final PrivateMessage m, final String body) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
messagingManager.addLocalMessage(m);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
Message message = m.getMessage();
|
||||
PrivateMessageHeader h = new PrivateMessageHeader(
|
||||
message.getId(), message.getGroupId(),
|
||||
message.getTimestamp(), true, false, false, false);
|
||||
ConversationItem item = ConversationItem.from(h);
|
||||
item.setBody(body);
|
||||
bodyCache.put(message.getId(), body);
|
||||
addConversationItem(item);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
messagingManager.addLocalMessage(m);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
Message message = m.getMessage();
|
||||
PrivateMessageHeader h = new PrivateMessageHeader(
|
||||
message.getId(), message.getGroupId(),
|
||||
message.getTimestamp(), true, false, false, false);
|
||||
ConversationItem item = ConversationItem.from(h);
|
||||
item.setBody(body);
|
||||
bodyCache.put(message.getId(), body);
|
||||
addConversationItem(item);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void askToRemoveContact() {
|
||||
DialogInterface.OnClickListener okListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
removeContact();
|
||||
}
|
||||
};
|
||||
(dialog, which) -> removeContact();
|
||||
AlertDialog.Builder builder =
|
||||
new AlertDialog.Builder(ConversationActivity.this,
|
||||
R.style.BriarDialogTheme);
|
||||
@@ -803,118 +719,95 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void removeContact() {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
contactManager.removeContact(contactId);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} finally {
|
||||
finishAfterContactRemoved();
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
contactManager.removeContact(contactId);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
} finally {
|
||||
finishAfterContactRemoved();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void finishAfterContactRemoved() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String deleted = getString(R.string.contact_deleted_toast);
|
||||
Toast.makeText(ConversationActivity.this, deleted, LENGTH_SHORT)
|
||||
.show();
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
String deleted = getString(R.string.contact_deleted_toast);
|
||||
Toast.makeText(ConversationActivity.this, deleted, LENGTH_SHORT)
|
||||
.show();
|
||||
supportFinishAfterTransition();
|
||||
});
|
||||
}
|
||||
|
||||
private void enableIntroductionActionIfAvailable(final MenuItem item) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (contactManager.getActiveContacts().size() > 1) {
|
||||
enableIntroductionAction(item);
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
if (settings.getBoolean(SHOW_ONBOARDING_INTRODUCTION,
|
||||
true)) {
|
||||
showIntroductionOnboarding();
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
if (contactManager.getActiveContacts().size() > 1) {
|
||||
enableIntroductionAction(item);
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
if (settings.getBoolean(SHOW_ONBOARDING_INTRODUCTION,
|
||||
true)) {
|
||||
showIntroductionOnboarding();
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void enableIntroductionAction(final MenuItem item) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
item.setEnabled(true);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(() -> item.setEnabled(true));
|
||||
}
|
||||
|
||||
private void showIntroductionOnboarding() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// find view of overflow icon
|
||||
View target = null;
|
||||
for (int i = 0; i < toolbar.getChildCount(); i++) {
|
||||
if (toolbar.getChildAt(i) instanceof ActionMenuView) {
|
||||
ActionMenuView menu =
|
||||
(ActionMenuView) toolbar.getChildAt(i);
|
||||
target = menu.getChildAt(menu.getChildCount() - 1);
|
||||
break;
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
// find view of overflow icon
|
||||
View target = null;
|
||||
for (int i = 0; i < toolbar.getChildCount(); i++) {
|
||||
if (toolbar.getChildAt(i) instanceof ActionMenuView) {
|
||||
ActionMenuView menu =
|
||||
(ActionMenuView) toolbar.getChildAt(i);
|
||||
target = menu.getChildAt(menu.getChildCount() - 1);
|
||||
break;
|
||||
}
|
||||
if (target == null) {
|
||||
LOG.warning("No Overflow Icon found!");
|
||||
return;
|
||||
}
|
||||
|
||||
OnHidePromptListener listener = new OnHidePromptListener() {
|
||||
@Override
|
||||
public void onHidePrompt(MotionEvent motionEvent,
|
||||
boolean focalClicked) {
|
||||
introductionOnboardingSeen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHidePromptComplete() {
|
||||
}
|
||||
};
|
||||
new MaterialTapTargetPrompt.Builder(ConversationActivity.this)
|
||||
.setTarget(target)
|
||||
.setPrimaryText(R.string.introduction_onboarding_title)
|
||||
.setSecondaryText(R.string.introduction_onboarding_text)
|
||||
.setBackgroundColourFromRes(R.color.briar_primary)
|
||||
.setIcon(R.drawable.ic_more_vert_accent)
|
||||
.setOnHidePromptListener(listener)
|
||||
.show();
|
||||
}
|
||||
if (target == null) {
|
||||
LOG.warning("No Overflow Icon found!");
|
||||
return;
|
||||
}
|
||||
|
||||
OnHidePromptListener listener = new OnHidePromptListener() {
|
||||
@Override
|
||||
public void onHidePrompt(MotionEvent motionEvent,
|
||||
boolean focalClicked) {
|
||||
introductionOnboardingSeen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHidePromptComplete() {
|
||||
}
|
||||
};
|
||||
new MaterialTapTargetPrompt.Builder(ConversationActivity.this)
|
||||
.setTarget(target)
|
||||
.setPrimaryText(R.string.introduction_onboarding_title)
|
||||
.setSecondaryText(R.string.introduction_onboarding_text)
|
||||
.setBackgroundColourFromRes(R.color.briar_primary)
|
||||
.setIcon(R.drawable.ic_more_vert_accent)
|
||||
.setOnHidePromptListener(listener)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void introductionOnboardingSeen() {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings settings = new Settings();
|
||||
settings.putBoolean(SHOW_ONBOARDING_INTRODUCTION, false);
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Settings settings = new Settings();
|
||||
settings.putBoolean(SHOW_ONBOARDING_INTRODUCTION, false);
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -925,19 +818,15 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void markMessageRead(final GroupId g, final MessageId m) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
messagingManager.setReadFlag(g, m, true);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Marking read took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
messagingManager.setReadFlag(g, m, true);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Marking read took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -951,36 +840,33 @@ public class ConversationActivity extends BriarActivity
|
||||
if (position != INVALID_POSITION) {
|
||||
adapter.notifyItemChanged(position, item);
|
||||
}
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||
try {
|
||||
switch (item.getRequestType()) {
|
||||
case INTRODUCTION:
|
||||
respondToIntroductionRequest(item.getSessionId(),
|
||||
accept, timestamp);
|
||||
break;
|
||||
case FORUM:
|
||||
respondToForumRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
case BLOG:
|
||||
respondToBlogRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
case GROUP:
|
||||
respondToGroupRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown Request Type");
|
||||
}
|
||||
loadMessages();
|
||||
} catch (DbException | FormatException e) {
|
||||
introductionResponseError();
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
runOnDbThread(() -> {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||
try {
|
||||
switch (item.getRequestType()) {
|
||||
case INTRODUCTION:
|
||||
respondToIntroductionRequest(item.getSessionId(),
|
||||
accept, timestamp);
|
||||
break;
|
||||
case FORUM:
|
||||
respondToForumRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
case BLOG:
|
||||
respondToBlogRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
case GROUP:
|
||||
respondToGroupRequest(item.getSessionId(), accept);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown Request Type");
|
||||
}
|
||||
loadMessages();
|
||||
} catch (DbException | FormatException e) {
|
||||
introductionResponseError();
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1041,14 +927,10 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void introductionResponseError() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThreadUnlessDestroyed(() ->
|
||||
Toast.makeText(ConversationActivity.this,
|
||||
R.string.introduction_response_error,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
private ListenableFutureTask<String> getContactNameTask() {
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -35,12 +34,8 @@ class ConversationRequestViewHolder extends ConversationNoticeInViewHolder {
|
||||
if (item.wasAnswered() && item.canBeOpened()) {
|
||||
acceptButton.setVisibility(VISIBLE);
|
||||
acceptButton.setText(R.string.open);
|
||||
acceptButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.openRequestedShareable(item);
|
||||
}
|
||||
});
|
||||
acceptButton.setOnClickListener(
|
||||
v -> listener.openRequestedShareable(item));
|
||||
declineButton.setVisibility(GONE);
|
||||
} else if (item.wasAnswered()) {
|
||||
acceptButton.setVisibility(GONE);
|
||||
@@ -48,22 +43,16 @@ class ConversationRequestViewHolder extends ConversationNoticeInViewHolder {
|
||||
} else {
|
||||
acceptButton.setVisibility(VISIBLE);
|
||||
acceptButton.setText(R.string.accept);
|
||||
acceptButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
acceptButton.setEnabled(false);
|
||||
declineButton.setEnabled(false);
|
||||
listener.respondToRequest(item, true);
|
||||
}
|
||||
acceptButton.setOnClickListener(v -> {
|
||||
acceptButton.setEnabled(false);
|
||||
declineButton.setEnabled(false);
|
||||
listener.respondToRequest(item, true);
|
||||
});
|
||||
declineButton.setVisibility(VISIBLE);
|
||||
declineButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
acceptButton.setEnabled(false);
|
||||
declineButton.setEnabled(false);
|
||||
listener.respondToRequest(item, false);
|
||||
}
|
||||
declineButton.setOnClickListener(v -> {
|
||||
acceptButton.setEnabled(false);
|
||||
declineButton.setEnabled(false);
|
||||
listener.respondToRequest(item, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,26 +41,21 @@ public abstract class ContactSelectorControllerImpl
|
||||
public void loadContacts(final GroupId g,
|
||||
final Collection<ContactId> selection,
|
||||
final ResultExceptionHandler<Collection<SelectableContactItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<SelectableContactItem> contacts =
|
||||
new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
// was this contact already selected?
|
||||
boolean selected = selection.contains(c.getId());
|
||||
// can this contact be selected?
|
||||
boolean disabled = isDisabled(g, c);
|
||||
contacts.add(new SelectableContactItem(c, selected,
|
||||
disabled));
|
||||
}
|
||||
handler.onResult(contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Collection<SelectableContactItem> contacts = new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
// was this contact already selected?
|
||||
boolean selected = selection.contains(c.getId());
|
||||
// can this contact be selected?
|
||||
boolean disabled = isDisabled(g, c);
|
||||
contacts.add(new SelectableContactItem(c, selected,
|
||||
disabled));
|
||||
}
|
||||
handler.onResult(contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,16 +29,13 @@ public class DbControllerImpl implements DbController {
|
||||
|
||||
@Override
|
||||
public void runOnDbThread(final Runnable task) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
lifecycleManager.waitForDatabase();
|
||||
task.run();
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting for database");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
lifecycleManager.waitForDatabase();
|
||||
task.run();
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warning("Interrupted while waiting for database");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,13 +60,10 @@ public class SharingControllerImpl implements SharingController, EventListener {
|
||||
|
||||
private void setConnected(final ContactId c) {
|
||||
if (listener == null) return;
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (contacts.contains(c)) {
|
||||
int online = getOnlineCount();
|
||||
listener.onSharingInfoUpdated(contacts.size(), online);
|
||||
}
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (contacts.contains(c)) {
|
||||
int online = getOnlineCount();
|
||||
listener.onSharingInfoUpdated(contacts.size(), online);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,12 +20,7 @@ public abstract class UiExceptionHandler<E extends Exception>
|
||||
|
||||
@Override
|
||||
public void onException(final E exception) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onExceptionUi(exception);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> onExceptionUi(exception));
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -18,12 +18,7 @@ public abstract class UiResultExceptionHandler<R, E extends Exception>
|
||||
|
||||
@Override
|
||||
public void onResult(final R result) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onResultUi(result);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> onResultUi(result));
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -14,12 +14,7 @@ public abstract class UiResultHandler<R> implements ResultHandler<R> {
|
||||
|
||||
@Override
|
||||
public void onResult(final R result) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onResultUi(result);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> onResultUi(result));
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -5,14 +5,9 @@ import android.os.Bundle;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -79,22 +74,13 @@ public class CreateForumActivity extends BriarActivity {
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
});
|
||||
nameEntry.setOnEditorActionListener(new OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId,
|
||||
KeyEvent e) {
|
||||
createForum();
|
||||
return true;
|
||||
}
|
||||
nameEntry.setOnEditorActionListener((v, actionId, e) -> {
|
||||
createForum();
|
||||
return true;
|
||||
});
|
||||
|
||||
createForumButton = (Button) findViewById(R.id.createForumButton);
|
||||
createForumButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createForum();
|
||||
}
|
||||
});
|
||||
createForumButton.setOnClickListener(v -> createForum());
|
||||
|
||||
progress = (ProgressBar) findViewById(R.id.createForumProgressBar);
|
||||
}
|
||||
@@ -135,38 +121,31 @@ public class CreateForumActivity extends BriarActivity {
|
||||
}
|
||||
|
||||
private void storeForum(final String name) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Forum f = forumManager.addForum(name);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing forum took " + duration + " ms");
|
||||
displayForum(f);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
finishOnUiThread();
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Forum f = forumManager.addForum(name);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing forum took " + duration + " ms");
|
||||
displayForum(f);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
finishOnUiThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayForum(final Forum f) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Intent i = new Intent(CreateForumActivity.this,
|
||||
ForumActivity.class);
|
||||
i.putExtra(GROUP_ID, f.getId().getBytes());
|
||||
i.putExtra(GROUP_NAME, f.getName());
|
||||
startActivity(i);
|
||||
Toast.makeText(CreateForumActivity.this,
|
||||
R.string.forum_created_toast, LENGTH_LONG).show();
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
Intent i = new Intent(CreateForumActivity.this,
|
||||
ForumActivity.class);
|
||||
i.putExtra(GROUP_ID, f.getId().getBytes());
|
||||
i.putExtra(GROUP_NAME, f.getName());
|
||||
startActivity(i);
|
||||
Toast.makeText(CreateForumActivity.this,
|
||||
R.string.forum_created_toast, LENGTH_LONG).show();
|
||||
supportFinishAfterTransition();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.android.forum;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -11,7 +10,6 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
@@ -69,16 +67,12 @@ public class ForumActivity extends
|
||||
|
||||
// Open member list on Toolbar click
|
||||
if (toolbar != null) {
|
||||
toolbar.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(ForumActivity.this,
|
||||
ForumSharingStatusActivity.class);
|
||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
});
|
||||
toolbar.setOnClickListener(v -> {
|
||||
Intent i1 = new Intent(ForumActivity.this,
|
||||
ForumSharingStatusActivity.class);
|
||||
i1.putExtra(GROUP_ID, groupId.getBytes());
|
||||
startActivity(i1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,12 +141,7 @@ public class ForumActivity extends
|
||||
}
|
||||
|
||||
private void showUnsubscribeDialog() {
|
||||
OnClickListener okListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
deleteForum();
|
||||
}
|
||||
};
|
||||
OnClickListener okListener = (dialog, which) -> deleteForum();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this,
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(getString(R.string.dialog_title_leave_forum));
|
||||
|
||||
@@ -121,21 +121,17 @@ class ForumControllerImpl extends
|
||||
@Override
|
||||
public void loadSharingContacts(
|
||||
final ResultExceptionHandler<Collection<ContactId>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<Contact> contacts =
|
||||
forumSharingManager.getSharedWith(getGroupId());
|
||||
Collection<ContactId> contactIds =
|
||||
new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) contactIds.add(c.getId());
|
||||
handler.onResult(contactIds);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Collection<Contact> contacts =
|
||||
forumSharingManager.getSharedWith(getGroupId());
|
||||
Collection<ContactId> contactIds =
|
||||
new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) contactIds.add(c.getId());
|
||||
handler.onResult(contactIds);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -144,22 +140,18 @@ class ForumControllerImpl extends
|
||||
public void createAndStoreMessage(final String body,
|
||||
@Nullable final ForumItem parentItem,
|
||||
final ResultExceptionHandler<ForumItem, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
GroupCount count = forumManager.getGroupCount(getGroupId());
|
||||
long timestamp = max(count.getLatestMsgTime() + 1,
|
||||
clock.currentTimeMillis());
|
||||
MessageId parentId = parentItem != null ?
|
||||
parentItem.getId() : null;
|
||||
createMessage(body, timestamp, parentId, author, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
GroupCount count = forumManager.getGroupCount(getGroupId());
|
||||
long timestamp = max(count.getLatestMsgTime() + 1,
|
||||
clock.currentTimeMillis());
|
||||
MessageId parentId = parentItem != null ?
|
||||
parentItem.getId() : null;
|
||||
createMessage(body, timestamp, parentId, author, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -167,15 +159,11 @@ class ForumControllerImpl extends
|
||||
private void createMessage(final String body, final long timestamp,
|
||||
final @Nullable MessageId parentId, final LocalAuthor author,
|
||||
final ResultExceptionHandler<ForumItem, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Creating forum post...");
|
||||
ForumPost msg = forumManager
|
||||
.createLocalPost(getGroupId(), body, timestamp,
|
||||
parentId, author);
|
||||
storePost(msg, body, handler);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
LOG.info("Creating forum post...");
|
||||
ForumPost msg = forumManager.createLocalPost(getGroupId(), body,
|
||||
timestamp, parentId, author);
|
||||
storePost(msg, body, handler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,30 +185,17 @@ class ForumControllerImpl extends
|
||||
|
||||
private void onForumPostReceived(ForumPostHeader h, String body) {
|
||||
final ForumItem item = buildItem(h, body);
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onItemReceived(item);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onItemReceived(item));
|
||||
}
|
||||
|
||||
private void onForumInvitationAccepted(final ContactId c) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onInvitationAccepted(c);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onInvitationAccepted(c));
|
||||
}
|
||||
|
||||
private void onForumLeft(final ContactId c) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onForumLeft(c);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> listener.onForumLeft(c));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,15 +77,12 @@ class ForumListAdapter
|
||||
}
|
||||
|
||||
// Open Forum on Click
|
||||
ui.layout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(ctx, ForumActivity.class);
|
||||
Forum f = item.getForum();
|
||||
i.putExtra(GROUP_ID, f.getId().getBytes());
|
||||
i.putExtra(GROUP_NAME, f.getName());
|
||||
ctx.startActivity(i);
|
||||
}
|
||||
ui.layout.setOnClickListener(v -> {
|
||||
Intent i = new Intent(ctx, ForumActivity.class);
|
||||
Forum f = item.getForum();
|
||||
i.putExtra(GROUP_ID, f.getId().getBytes());
|
||||
i.putExtra(GROUP_NAME, f.getName());
|
||||
ctx.startActivity(i);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -155,82 +155,67 @@ public class ForumListFragment extends BaseEventFragment implements
|
||||
|
||||
private void loadForums() {
|
||||
final int revision = adapter.getRevision();
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<ForumListItem> forums = new ArrayList<>();
|
||||
for (Forum f : forumManager.getForums()) {
|
||||
try {
|
||||
GroupCount count =
|
||||
forumManager.getGroupCount(f.getId());
|
||||
forums.add(new ForumListItem(f, count));
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Continue
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<ForumListItem> forums = new ArrayList<>();
|
||||
for (Forum f : forumManager.getForums()) {
|
||||
try {
|
||||
GroupCount count =
|
||||
forumManager.getGroupCount(f.getId());
|
||||
forums.add(new ForumListItem(f, count));
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Continue
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Full load took " + duration + " ms");
|
||||
displayForums(revision, forums);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Full load took " + duration + " ms");
|
||||
displayForums(revision, forums);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayForums(final int revision,
|
||||
final Collection<ForumListItem> forums) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (forums.isEmpty()) list.showData();
|
||||
else adapter.addAll(forums);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadForums();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (forums.isEmpty()) list.showData();
|
||||
else adapter.addAll(forums);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadForums();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadAvailableForums() {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
int available =
|
||||
forumSharingManager.getInvitations().size();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading available took " + duration + " ms");
|
||||
displayAvailableForums(available);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
int available = forumSharingManager.getInvitations().size();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading available took " + duration + " ms");
|
||||
displayAvailableForums(available);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayAvailableForums(final int availableCount) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (availableCount == 0) {
|
||||
snackbar.dismiss();
|
||||
} else {
|
||||
snackbar.setText(getResources().getQuantityString(
|
||||
R.plurals.forums_shared, availableCount,
|
||||
availableCount));
|
||||
if (!snackbar.isShownOrQueued()) snackbar.show();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (availableCount == 0) {
|
||||
snackbar.dismiss();
|
||||
} else {
|
||||
snackbar.setText(getResources().getQuantityString(
|
||||
R.plurals.forums_shared, availableCount,
|
||||
availableCount));
|
||||
if (!snackbar.isShownOrQueued()) snackbar.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -263,29 +248,23 @@ public class ForumListFragment extends BaseEventFragment implements
|
||||
}
|
||||
|
||||
private void updateItem(final GroupId g, final ForumPostHeader m) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(g);
|
||||
ForumListItem item = adapter.getItemAt(position);
|
||||
if (item != null) {
|
||||
item.addHeader(m);
|
||||
adapter.updateItemAt(position, item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(g);
|
||||
ForumListItem item = adapter.getItemAt(position);
|
||||
if (item != null) {
|
||||
item.addHeader(m);
|
||||
adapter.updateItemAt(position, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeForum(final GroupId g) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(g);
|
||||
ForumListItem item = adapter.getItemAt(position);
|
||||
if (item != null) adapter.remove(item);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(g);
|
||||
ForumListItem item = adapter.getItemAt(position);
|
||||
if (item != null) adapter.remove(item);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -82,14 +82,11 @@ public abstract class BaseFragment extends Fragment
|
||||
public void runOnUiThreadUnlessDestroyed(final Runnable r) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Note that we don't have to check if the activity has
|
||||
// been destroyed as the Fragment has not been detached yet
|
||||
if (!isDetached() && !activity.isFinishing()) {
|
||||
r.run();
|
||||
}
|
||||
activity.runOnUiThread(() -> {
|
||||
// Note that we don't have to check if the activity has
|
||||
// been destroyed as the Fragment has not been detached yet
|
||||
if (!isDetached() && !activity.isFinishing()) {
|
||||
r.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.briar.android.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
@@ -35,12 +34,7 @@ public class ScreenFilterDialogFragment extends DialogFragment {
|
||||
builder.setMessage(getString(R.string.screen_filter_body,
|
||||
TextUtils.join("\n", apps)));
|
||||
builder.setNeutralButton(R.string.continue_button,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
(dialog, which) -> dialog.dismiss());
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,13 +71,10 @@ public class ContactChooserFragment extends BaseFragment {
|
||||
View contentView = inflater.inflate(R.layout.list, container, false);
|
||||
|
||||
OnContactClickListener<ContactListItem> onContactClickListener =
|
||||
new OnContactClickListener<ContactListItem>() {
|
||||
@Override
|
||||
public void onItemClick(View view, ContactListItem item) {
|
||||
if (c1 == null) throw new IllegalStateException();
|
||||
Contact c2 = item.getContact();
|
||||
showMessageScreen(c1, c2);
|
||||
}
|
||||
(view, item) -> {
|
||||
if (c1 == null) throw new IllegalStateException();
|
||||
Contact c2 = item.getContact();
|
||||
showMessageScreen(c1, c2);
|
||||
};
|
||||
adapter = new ContactListAdapter(getActivity(), onContactClickListener);
|
||||
|
||||
@@ -115,40 +112,32 @@ public class ContactChooserFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
private void loadContacts() {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
List<ContactListItem> contacts = new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
if (c.getId().equals(contactId)) {
|
||||
c1 = c;
|
||||
} else {
|
||||
ContactId id = c.getId();
|
||||
GroupCount count =
|
||||
conversationManager.getGroupCount(id);
|
||||
boolean connected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
contacts.add(new ContactListItem(c, connected,
|
||||
count));
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
List<ContactListItem> contacts = new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
if (c.getId().equals(contactId)) {
|
||||
c1 = c;
|
||||
} else {
|
||||
ContactId id = c.getId();
|
||||
GroupCount count =
|
||||
conversationManager.getGroupCount(id);
|
||||
boolean connected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
contacts.add(new ContactListItem(c, connected, count));
|
||||
}
|
||||
displayContacts(contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
displayContacts(contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayContacts(final List<ContactListItem> contacts) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -120,48 +120,41 @@ public class IntroductionMessageFragment extends BaseFragment
|
||||
|
||||
private void prepareToSetUpViews(final int contactId1,
|
||||
final int contactId2) {
|
||||
introductionActivity.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Contact c1 = contactManager.getContact(
|
||||
new ContactId(contactId1));
|
||||
Contact c2 = contactManager.getContact(
|
||||
new ContactId(contactId2));
|
||||
setUpViews(c1, c2);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
introductionActivity.runOnDbThread(() -> {
|
||||
try {
|
||||
Contact c1 = contactManager.getContact(
|
||||
new ContactId(contactId1));
|
||||
Contact c2 = contactManager.getContact(
|
||||
new ContactId(contactId2));
|
||||
setUpViews(c1, c2);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setUpViews(final Contact c1, final Contact c2) {
|
||||
introductionActivity.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
contact1 = c1;
|
||||
contact2 = c2;
|
||||
introductionActivity.runOnUiThreadUnlessDestroyed(() -> {
|
||||
contact1 = c1;
|
||||
contact2 = c2;
|
||||
|
||||
// set avatars
|
||||
ui.avatar1.setImageDrawable(new IdenticonDrawable(
|
||||
c1.getAuthor().getId().getBytes()));
|
||||
ui.avatar2.setImageDrawable(new IdenticonDrawable(
|
||||
c2.getAuthor().getId().getBytes()));
|
||||
// set avatars
|
||||
ui.avatar1.setImageDrawable(new IdenticonDrawable(
|
||||
c1.getAuthor().getId().getBytes()));
|
||||
ui.avatar2.setImageDrawable(new IdenticonDrawable(
|
||||
c2.getAuthor().getId().getBytes()));
|
||||
|
||||
// set contact names
|
||||
ui.contactName1.setText(c1.getAuthor().getName());
|
||||
ui.contactName2.setText(c2.getAuthor().getName());
|
||||
// set contact names
|
||||
ui.contactName1.setText(c1.getAuthor().getName());
|
||||
ui.contactName2.setText(c2.getAuthor().getName());
|
||||
|
||||
// set button action
|
||||
ui.message.setListener(IntroductionMessageFragment.this);
|
||||
// set button action
|
||||
ui.message.setListener(IntroductionMessageFragment.this);
|
||||
|
||||
// hide progress bar and show views
|
||||
ui.progressBar.setVisibility(GONE);
|
||||
ui.message.setSendButtonEnabled(true);
|
||||
ui.message.showSoftKeyboard();
|
||||
}
|
||||
// hide progress bar and show views
|
||||
ui.progressBar.setVisibility(GONE);
|
||||
ui.message.setSendButtonEnabled(true);
|
||||
ui.message.showSoftKeyboard();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -194,31 +187,22 @@ public class IntroductionMessageFragment extends BaseFragment
|
||||
|
||||
private void makeIntroduction(final Contact c1, final Contact c2,
|
||||
final String msg) {
|
||||
introductionActivity.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// actually make the introduction
|
||||
try {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
introductionManager.makeIntroduction(c1, c2, msg,
|
||||
timestamp);
|
||||
} catch (DbException | FormatException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
introductionError();
|
||||
}
|
||||
introductionActivity.runOnDbThread(() -> {
|
||||
// actually make the introduction
|
||||
try {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
introductionManager.makeIntroduction(c1, c2, msg, timestamp);
|
||||
} catch (DbException | FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
introductionError();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void introductionError() {
|
||||
introductionActivity.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(introductionActivity,
|
||||
R.string.introduction_error, LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
introductionActivity.runOnUiThreadUnlessDestroyed(
|
||||
() -> Toast.makeText(introductionActivity,
|
||||
R.string.introduction_error, LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
|
||||
@@ -353,15 +353,11 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(final SurfaceHolder holder) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
surfaceCreatedUi(holder);
|
||||
} catch (CameraException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
post(() -> {
|
||||
try {
|
||||
surfaceCreatedUi(holder);
|
||||
} catch (CameraException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -381,15 +377,11 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
@Override
|
||||
public void surfaceChanged(final SurfaceHolder holder, int format,
|
||||
final int w, final int h) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
surfaceChangedUi(holder, w, h);
|
||||
} catch (CameraException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
post(() -> {
|
||||
try {
|
||||
surfaceChangedUi(holder, w, h);
|
||||
} catch (CameraException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -420,12 +412,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(final SurfaceHolder holder) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
surfaceDestroyedUi(holder);
|
||||
}
|
||||
});
|
||||
post(() -> surfaceDestroyedUi(holder));
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -442,12 +429,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, final Camera camera) {
|
||||
LOG.info("Auto focus succeeded: " + success);
|
||||
postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
retryAutoFocus();
|
||||
}
|
||||
}, AUTO_FOCUS_RETRY_DELAY);
|
||||
postDelayed(this::retryAutoFocus, AUTO_FOCUS_RETRY_DELAY);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
@@ -66,24 +65,14 @@ public class IntroFragment extends BaseFragment {
|
||||
false);
|
||||
scrollView = (ScrollView) v.findViewById(R.id.scrollView);
|
||||
View button = v.findViewById(R.id.continueButton);
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
screenSeenListener.showNextScreen();
|
||||
}
|
||||
});
|
||||
button.setOnClickListener(view -> screenSeenListener.showNextScreen());
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
scrollView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
scrollView.fullScroll(FOCUS_DOWN);
|
||||
}
|
||||
});
|
||||
scrollView.post(() -> scrollView.fullScroll(FOCUS_DOWN));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.android.keyagreement;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.UiThread;
|
||||
@@ -144,12 +143,8 @@ public class KeyAgreementActivity extends BriarActivity implements
|
||||
// Should we show an explanation?
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
CAMERA)) {
|
||||
OnClickListener continueListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
requestPermission();
|
||||
}
|
||||
};
|
||||
OnClickListener continueListener =
|
||||
(dialog, which) -> requestPermission();
|
||||
Builder builder = new Builder(this, style.BriarDialogTheme);
|
||||
builder.setTitle(string.permission_camera_title);
|
||||
builder.setMessage(string.permission_camera_request_body);
|
||||
@@ -183,12 +178,8 @@ public class KeyAgreementActivity extends BriarActivity implements
|
||||
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
CAMERA)) {
|
||||
// The user has permanently denied the request
|
||||
OnClickListener cancelListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
};
|
||||
OnClickListener cancelListener =
|
||||
(dialog, which) -> supportFinishAfterTransition();
|
||||
Builder builder = new Builder(this, style.BriarDialogTheme);
|
||||
builder.setTitle(string.permission_camera_title);
|
||||
builder.setMessage(string.permission_camera_denied_body);
|
||||
@@ -214,77 +205,57 @@ public class KeyAgreementActivity extends BriarActivity implements
|
||||
}
|
||||
|
||||
private void keyAgreementFinished(final KeyAgreementResult result) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startContactExchange(result);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(() -> startContactExchange(result));
|
||||
}
|
||||
|
||||
private void startContactExchange(final KeyAgreementResult result) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LocalAuthor localAuthor;
|
||||
// Load the local pseudonym
|
||||
try {
|
||||
localAuthor = identityManager.getLocalAuthor();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
contactExchangeFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Exchange contact details
|
||||
contactExchangeTask.startExchange(KeyAgreementActivity.this,
|
||||
localAuthor, result.getMasterKey(),
|
||||
result.getConnection(), result.getTransportId(),
|
||||
result.wasAlice());
|
||||
runOnDbThread(() -> {
|
||||
LocalAuthor localAuthor;
|
||||
// Load the local pseudonym
|
||||
try {
|
||||
localAuthor = identityManager.getLocalAuthor();
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
contactExchangeFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Exchange contact details
|
||||
contactExchangeTask.startExchange(KeyAgreementActivity.this,
|
||||
localAuthor, result.getMasterKey(),
|
||||
result.getConnection(), result.getTransportId(),
|
||||
result.wasAlice());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contactExchangeSucceeded(final Author remoteAuthor) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(R.string.contact_added_toast);
|
||||
String text = String.format(format, contactName);
|
||||
Toast.makeText(KeyAgreementActivity.this, text, LENGTH_LONG)
|
||||
.show();
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(string.contact_added_toast);
|
||||
String text = String.format(format, contactName);
|
||||
Toast.makeText(KeyAgreementActivity.this, text, LENGTH_LONG).show();
|
||||
supportFinishAfterTransition();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void duplicateContact(final Author remoteAuthor) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(R.string.contact_already_exists);
|
||||
String text = String.format(format, contactName);
|
||||
Toast.makeText(KeyAgreementActivity.this, text, LENGTH_LONG)
|
||||
.show();
|
||||
finish();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(string.contact_already_exists);
|
||||
String text = String.format(format, contactName);
|
||||
Toast.makeText(KeyAgreementActivity.this, text, LENGTH_LONG).show();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contactExchangeFailed() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(KeyAgreementActivity.this,
|
||||
R.string.contact_exchange_failed, LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
Toast.makeText(KeyAgreementActivity.this,
|
||||
string.contact_exchange_failed, LENGTH_LONG).show();
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,23 +192,17 @@ public class ShowQrCodeFragment extends BaseEventFragment
|
||||
final KeyAgreementTask oldTask = task;
|
||||
final KeyAgreementTask newTask = keyAgreementTaskFactory.createTask();
|
||||
task = newTask;
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (oldTask != null) oldTask.stopListening();
|
||||
newTask.listen();
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
if (oldTask != null) oldTask.stopListening();
|
||||
newTask.listen();
|
||||
});
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void stopListening() {
|
||||
final KeyAgreementTask oldTask = task;
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (oldTask != null) oldTask.stopListening();
|
||||
}
|
||||
ioExecutor.execute(() -> {
|
||||
if (oldTask != null) oldTask.stopListening();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -255,13 +249,9 @@ public class ShowQrCodeFragment extends BaseEventFragment
|
||||
KeyAgreementAbortedEvent event = (KeyAgreementAbortedEvent) e;
|
||||
keyAgreementAborted(event.didRemoteAbort());
|
||||
} else if (e instanceof KeyAgreementFinishedEvent) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mainProgressContainer.setVisibility(VISIBLE);
|
||||
mainProgressTitle.setText(
|
||||
R.string.exchanging_contact_details);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
mainProgressContainer.setVisibility(VISIBLE);
|
||||
mainProgressTitle.setText(R.string.exchanging_contact_details);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -297,75 +287,54 @@ public class ShowQrCodeFragment extends BaseEventFragment
|
||||
}
|
||||
|
||||
private void setQrCode(final Payload localPayload) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
generateBitmapQR(localPayload);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(() -> generateBitmapQR(localPayload));
|
||||
}
|
||||
|
||||
private void keyAgreementFailed() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reset();
|
||||
// TODO show failure somewhere persistent?
|
||||
Toast.makeText(getActivity(), R.string.connection_failed,
|
||||
LENGTH_LONG).show();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
reset();
|
||||
// TODO show failure somewhere persistent?
|
||||
Toast.makeText(getActivity(), R.string.connection_failed,
|
||||
LENGTH_LONG).show();
|
||||
});
|
||||
}
|
||||
|
||||
private void keyAgreementWaiting() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
status.setText(R.string.waiting_for_contact_to_scan);
|
||||
}
|
||||
});
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> status.setText(R.string.waiting_for_contact_to_scan));
|
||||
}
|
||||
|
||||
private void keyAgreementStarted() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mainProgressContainer.setVisibility(VISIBLE);
|
||||
mainProgressTitle.setText(R.string.authenticating_with_device);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
mainProgressContainer.setVisibility(VISIBLE);
|
||||
mainProgressTitle.setText(R.string.authenticating_with_device);
|
||||
});
|
||||
}
|
||||
|
||||
private void keyAgreementAborted(final boolean remoteAborted) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reset();
|
||||
mainProgressContainer.setVisibility(INVISIBLE);
|
||||
mainProgressTitle.setText("");
|
||||
// TODO show abort somewhere persistent?
|
||||
Toast.makeText(getActivity(),
|
||||
remoteAborted ? R.string.connection_aborted_remote :
|
||||
R.string.connection_aborted_local, LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
reset();
|
||||
mainProgressContainer.setVisibility(INVISIBLE);
|
||||
mainProgressTitle.setText("");
|
||||
// TODO show abort somewhere persistent?
|
||||
Toast.makeText(getActivity(),
|
||||
remoteAborted ? R.string.connection_aborted_remote :
|
||||
R.string.connection_aborted_local, LENGTH_LONG)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResult(final Result result) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Got result from decoder");
|
||||
// Ignore results until the KeyAgreementTask is ready
|
||||
if (!gotLocalPayload) {
|
||||
return;
|
||||
}
|
||||
if (!gotRemotePayload) {
|
||||
gotRemotePayload = true;
|
||||
qrCodeScanned(result.getText());
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
LOG.info("Got result from decoder");
|
||||
// Ignore results until the KeyAgreementTask is ready
|
||||
if (!gotLocalPayload) {
|
||||
return;
|
||||
}
|
||||
if (!gotRemotePayload) {
|
||||
gotRemotePayload = true;
|
||||
qrCodeScanned(result.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -8,13 +7,10 @@ import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
@@ -61,13 +57,9 @@ public class PasswordActivity extends BaseActivity {
|
||||
progress = (ProgressBar) findViewById(R.id.progress_wheel);
|
||||
input = (TextInputLayout) findViewById(R.id.password_layout);
|
||||
password = (EditText) findViewById(R.id.edit_password);
|
||||
password.setOnEditorActionListener(new OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId,
|
||||
KeyEvent event) {
|
||||
validatePassword();
|
||||
return true;
|
||||
}
|
||||
password.setOnEditorActionListener((v, actionId, event) -> {
|
||||
validatePassword();
|
||||
return true;
|
||||
});
|
||||
password.addTextChangedListener(new TextWatcher() {
|
||||
|
||||
@@ -131,12 +123,7 @@ public class PasswordActivity extends BaseActivity {
|
||||
builder.setMessage(R.string.dialog_message_lost_password);
|
||||
builder.setPositiveButton(R.string.cancel, null);
|
||||
builder.setNegativeButton(R.string.delete,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
deleteAccount();
|
||||
}
|
||||
});
|
||||
(dialog, which) -> deleteAccount());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@@ -50,16 +50,13 @@ public class PasswordControllerImpl extends ConfigControllerImpl
|
||||
public void validatePassword(final String password,
|
||||
final ResultHandler<Boolean> resultHandler) {
|
||||
final byte[] encrypted = getEncryptedKey();
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] key = crypto.decryptWithPassword(encrypted, password);
|
||||
if (key == null) {
|
||||
resultHandler.onResult(false);
|
||||
} else {
|
||||
databaseConfig.setEncryptionKey(new SecretKey(key));
|
||||
resultHandler.onResult(true);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
byte[] key = crypto.decryptWithPassword(encrypted, password);
|
||||
if (key == null) {
|
||||
resultHandler.onResult(false);
|
||||
} else {
|
||||
databaseConfig.setEncryptionKey(new SecretKey(key));
|
||||
resultHandler.onResult(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -68,18 +65,15 @@ public class PasswordControllerImpl extends ConfigControllerImpl
|
||||
public void changePassword(final String password, final String newPassword,
|
||||
final ResultHandler<Boolean> resultHandler) {
|
||||
final byte[] encrypted = getEncryptedKey();
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
byte[] key = crypto.decryptWithPassword(encrypted, password);
|
||||
if (key == null) {
|
||||
resultHandler.onResult(false);
|
||||
} else {
|
||||
String hex =
|
||||
encryptDatabaseKey(new SecretKey(key), newPassword);
|
||||
storeEncryptedDatabaseKey(hex);
|
||||
resultHandler.onResult(true);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
byte[] key = crypto.decryptWithPassword(encrypted, password);
|
||||
if (key == null) {
|
||||
resultHandler.onResult(false);
|
||||
} else {
|
||||
String hex =
|
||||
encryptDatabaseKey(new SecretKey(key), newPassword);
|
||||
storeEncryptedDatabaseKey(hex);
|
||||
resultHandler.onResult(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -86,16 +86,13 @@ public class SetupControllerImpl extends PasswordControllerImpl
|
||||
public void createAccount(final ResultHandler<Void> resultHandler) {
|
||||
if (authorName == null || password == null)
|
||||
throw new IllegalStateException();
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
databaseConfig.setLocalAuthorName(authorName);
|
||||
SecretKey key = crypto.generateSecretKey();
|
||||
databaseConfig.setEncryptionKey(key);
|
||||
String hex = encryptDatabaseKey(key, password);
|
||||
storeEncryptedDatabaseKey(hex);
|
||||
resultHandler.onResult(null);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
databaseConfig.setLocalAuthorName(authorName);
|
||||
SecretKey key = crypto.generateSecretKey();
|
||||
databaseConfig.setEncryptionKey(key);
|
||||
String hex = encryptDatabaseKey(key, password);
|
||||
storeEncryptedDatabaseKey(hex);
|
||||
resultHandler.onResult(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -307,12 +307,9 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
daysUntilExpiry, daysUntilExpiry));
|
||||
}
|
||||
|
||||
expiryWarningClose.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
controller.expiryWarningDismissed();
|
||||
expiryWarning.setVisibility(GONE);
|
||||
}
|
||||
expiryWarningClose.setOnClickListener(v -> {
|
||||
controller.expiryWarningDismissed();
|
||||
expiryWarning.setVisibility(GONE);
|
||||
});
|
||||
|
||||
expiryWarning.setVisibility(VISIBLE);
|
||||
@@ -411,16 +408,13 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
}
|
||||
|
||||
private void setTransport(final TransportId id, final boolean enabled) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (transports == null || transportsAdapter == null) return;
|
||||
for (Transport t : transports) {
|
||||
if (t.id.equals(id)) {
|
||||
t.enabled = enabled;
|
||||
transportsAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (transports == null || transportsAdapter == null) return;
|
||||
for (Transport t : transports) {
|
||||
if (t.id.equals(id)) {
|
||||
t.enabled = enabled;
|
||||
transportsAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -98,71 +98,59 @@ public class NavDrawerControllerImpl extends DbControllerImpl
|
||||
|
||||
private void transportStateUpdate(final TransportId id,
|
||||
final boolean enabled) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.stateUpdate(id, enabled);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.stateUpdate(id, enabled));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showExpiryWarning(final ResultHandler<ExpiryWarning> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
int warningInt = settings.getInt(EXPIRY_DATE_WARNING, 0);
|
||||
boolean showUpdate =
|
||||
settings.getBoolean(EXPIRY_SHOW_UPDATE, true);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
int warningInt = settings.getInt(EXPIRY_DATE_WARNING, 0);
|
||||
boolean showUpdate =
|
||||
settings.getBoolean(EXPIRY_SHOW_UPDATE, true);
|
||||
|
||||
if (warningInt == 0) {
|
||||
// we have not warned before
|
||||
if (warningInt == 0) {
|
||||
// we have not warned before
|
||||
handler.onResult(SHOW);
|
||||
} else {
|
||||
long warningLong = warningInt * 1000L;
|
||||
long now = System.currentTimeMillis();
|
||||
long daysSinceLastWarning =
|
||||
(now - warningLong) / 1000 / 60 / 60 / 24;
|
||||
long daysBeforeExpiry =
|
||||
(EXPIRY_DATE - now) / 1000 / 60 / 60 / 24;
|
||||
|
||||
if (showUpdate) {
|
||||
handler.onResult(UPDATE);
|
||||
} else if (daysSinceLastWarning >= 30) {
|
||||
handler.onResult(SHOW);
|
||||
} else if (daysBeforeExpiry <= 3 &&
|
||||
daysSinceLastWarning > 0) {
|
||||
handler.onResult(SHOW);
|
||||
} else {
|
||||
long warningLong = warningInt * 1000L;
|
||||
long now = System.currentTimeMillis();
|
||||
long daysSinceLastWarning =
|
||||
(now - warningLong) / 1000 / 60 / 60 / 24;
|
||||
long daysBeforeExpiry =
|
||||
(EXPIRY_DATE - now) / 1000 / 60 / 60 / 24;
|
||||
|
||||
if (showUpdate) {
|
||||
handler.onResult(UPDATE);
|
||||
} else if (daysSinceLastWarning >= 30) {
|
||||
handler.onResult(SHOW);
|
||||
} else if (daysBeforeExpiry <= 3 &&
|
||||
daysSinceLastWarning > 0) {
|
||||
handler.onResult(SHOW);
|
||||
} else {
|
||||
handler.onResult(NO);
|
||||
}
|
||||
handler.onResult(NO);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expiryWarningDismissed() {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings settings = new Settings();
|
||||
int date = (int) (System.currentTimeMillis() / 1000L);
|
||||
settings.putInt(EXPIRY_DATE_WARNING, date);
|
||||
settings.putBoolean(EXPIRY_SHOW_UPDATE, false);
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Settings settings = new Settings();
|
||||
int date = (int) (System.currentTimeMillis() / 1000L);
|
||||
settings.putInt(EXPIRY_DATE_WARNING, date);
|
||||
settings.putBoolean(EXPIRY_SHOW_UPDATE, false);
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.preference.CheckBoxPreference;
|
||||
import android.support.v7.preference.ListPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@@ -92,51 +91,39 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
entryValues.toArray(new CharSequence[entryValues.size()]));
|
||||
panicAppPref.setDefaultValue(Panic.PACKAGE_NAME_NONE);
|
||||
|
||||
panicAppPref.setOnPreferenceChangeListener(
|
||||
new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference,
|
||||
Object newValue) {
|
||||
String packageName = (String) newValue;
|
||||
PanicResponder.setTriggerPackageName(getActivity(),
|
||||
packageName);
|
||||
showPanicApp(packageName);
|
||||
panicAppPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
String packageName = (String) newValue;
|
||||
PanicResponder.setTriggerPackageName(getActivity(), packageName);
|
||||
showPanicApp(packageName);
|
||||
|
||||
if (packageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
||||
lockPref.setEnabled(false);
|
||||
purgePref.setChecked(false);
|
||||
purgePref.setEnabled(false);
|
||||
uninstallPref.setChecked(false);
|
||||
uninstallPref.setEnabled(false);
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
} else {
|
||||
lockPref.setEnabled(true);
|
||||
purgePref.setEnabled(true);
|
||||
uninstallPref.setEnabled(true);
|
||||
}
|
||||
if (packageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
||||
lockPref.setEnabled(false);
|
||||
purgePref.setChecked(false);
|
||||
purgePref.setEnabled(false);
|
||||
uninstallPref.setChecked(false);
|
||||
uninstallPref.setEnabled(false);
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
} else {
|
||||
lockPref.setEnabled(true);
|
||||
purgePref.setEnabled(true);
|
||||
uninstallPref.setEnabled(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
if (entries.size() <= 1) {
|
||||
panicAppPref.setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(
|
||||
Preference preference) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(
|
||||
"market://details?id=info.guardianproject.ripple"));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (intent.resolveActivity(
|
||||
getActivity().getPackageManager()) !=
|
||||
null) {
|
||||
startActivity(intent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
panicAppPref.setOnPreferenceClickListener(preference -> {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(
|
||||
"market://details?id=info.guardianproject.ripple"));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (intent.resolveActivity(getActivity().getPackageManager())
|
||||
!= null) {
|
||||
startActivity(intent);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,26 +206,15 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
|
||||
private void showOptInDialog() {
|
||||
DialogInterface.OnClickListener okListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
PanicResponder.setTriggerPackageName(getActivity());
|
||||
showPanicApp(PanicResponder
|
||||
.getTriggerPackageName(getActivity()));
|
||||
getActivity().setResult(Activity.RESULT_OK);
|
||||
}
|
||||
};
|
||||
DialogInterface.OnClickListener cancelListener =
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
getActivity().finish();
|
||||
}
|
||||
};
|
||||
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
||||
PanicResponder.setTriggerPackageName(getActivity());
|
||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||
getActivity().setResult(Activity.RESULT_OK);
|
||||
};
|
||||
DialogInterface.OnClickListener cancelListener = (dialog, which) -> {
|
||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||
getActivity().finish();
|
||||
};
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext(),
|
||||
R.style.BriarDialogTheme);
|
||||
|
||||
@@ -93,18 +93,15 @@ public class PanicResponderActivity extends BriarActivity {
|
||||
}
|
||||
|
||||
private void deleteAllData() {
|
||||
androidExecutor.runOnBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
configController.deleteAccount(PanicResponderActivity.this);
|
||||
// TODO somehow delete/shred the database more thoroughly
|
||||
PanicResponder.deleteAllAppData(PanicResponderActivity.this);
|
||||
androidExecutor.runOnBackgroundThread(() -> {
|
||||
configController.deleteAccount(PanicResponderActivity.this);
|
||||
// TODO somehow delete/shred the database more thoroughly
|
||||
PanicResponder.deleteAllAppData(PanicResponderActivity.this);
|
||||
|
||||
// nothing left to do after everything is deleted,
|
||||
// so still sign out
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
// nothing left to do after everything is deleted,
|
||||
// so still sign out
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -76,16 +75,12 @@ public class GroupActivity extends
|
||||
|
||||
// Open member list on Toolbar click
|
||||
if (toolbar != null) {
|
||||
toolbar.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(GroupActivity.this,
|
||||
GroupMemberListActivity.class);
|
||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
});
|
||||
toolbar.setOnClickListener(v -> {
|
||||
Intent i1 = new Intent(GroupActivity.this,
|
||||
GroupMemberListActivity.class);
|
||||
i1.putExtra(GROUP_ID, groupId.getBytes());
|
||||
startActivity(i1);
|
||||
});
|
||||
}
|
||||
|
||||
setGroupEnabled(false);
|
||||
|
||||
@@ -85,24 +85,16 @@ class GroupControllerImpl extends
|
||||
LOG.info("Group message received, adding...");
|
||||
final GroupMessageItem item =
|
||||
buildItem(g.getHeader(), g.getBody());
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onItemReceived(item);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onItemReceived(item));
|
||||
}
|
||||
} else if (e instanceof ContactRelationshipRevealedEvent) {
|
||||
final ContactRelationshipRevealedEvent c =
|
||||
(ContactRelationshipRevealedEvent) e;
|
||||
if (getGroupId().equals(c.getGroupId())) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.runOnUiThreadUnlessDestroyed(() ->
|
||||
listener.onContactRelationshipRevealed(c.getMemberId(),
|
||||
c.getContactId(), c.getVisibility());
|
||||
}
|
||||
});
|
||||
c.getContactId(), c.getVisibility()));
|
||||
}
|
||||
} else if (e instanceof GroupInvitationResponseReceivedEvent) {
|
||||
GroupInvitationResponseReceivedEvent g =
|
||||
@@ -110,22 +102,14 @@ class GroupControllerImpl extends
|
||||
final GroupInvitationResponse r =
|
||||
(GroupInvitationResponse) g.getResponse();
|
||||
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onInvitationAccepted(r.getContactId());
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onInvitationAccepted(r.getContactId()));
|
||||
}
|
||||
} else if (e instanceof GroupDissolvedEvent) {
|
||||
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
|
||||
if (getGroupId().equals(g.getGroupId())) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupDissolved();
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onGroupDissolved());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,23 +142,19 @@ class GroupControllerImpl extends
|
||||
@Override
|
||||
public void loadSharingContacts(
|
||||
final ResultExceptionHandler<Collection<ContactId>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<GroupMember> members =
|
||||
privateGroupManager.getMembers(getGroupId());
|
||||
Collection<ContactId> contactIds = new ArrayList<>();
|
||||
for (GroupMember m : members) {
|
||||
if (m.getContactId() != null)
|
||||
contactIds.add(m.getContactId());
|
||||
}
|
||||
handler.onResult(contactIds);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Collection<GroupMember> members =
|
||||
privateGroupManager.getMembers(getGroupId());
|
||||
Collection<ContactId> contactIds = new ArrayList<>();
|
||||
for (GroupMember m : members) {
|
||||
if (m.getContactId() != null)
|
||||
contactIds.add(m.getContactId());
|
||||
}
|
||||
handler.onResult(contactIds);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -183,26 +163,22 @@ class GroupControllerImpl extends
|
||||
public void createAndStoreMessage(final String body,
|
||||
@Nullable final GroupMessageItem parentItem,
|
||||
final ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
MessageId parentId = null;
|
||||
MessageId previousMsgId =
|
||||
privateGroupManager.getPreviousMsgId(getGroupId());
|
||||
GroupCount count =
|
||||
privateGroupManager.getGroupCount(getGroupId());
|
||||
long timestamp = count.getLatestMsgTime();
|
||||
if (parentItem != null) parentId = parentItem.getId();
|
||||
timestamp = max(clock.currentTimeMillis(), timestamp + 1);
|
||||
createMessage(body, timestamp, parentId, author,
|
||||
previousMsgId, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
MessageId parentId = null;
|
||||
MessageId previousMsgId =
|
||||
privateGroupManager.getPreviousMsgId(getGroupId());
|
||||
GroupCount count =
|
||||
privateGroupManager.getGroupCount(getGroupId());
|
||||
long timestamp = count.getLatestMsgTime();
|
||||
if (parentItem != null) parentId = parentItem.getId();
|
||||
timestamp = max(clock.currentTimeMillis(), timestamp + 1);
|
||||
createMessage(body, timestamp, parentId, author, previousMsgId,
|
||||
handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -211,15 +187,12 @@ class GroupControllerImpl extends
|
||||
final @Nullable MessageId parentId, final LocalAuthor author,
|
||||
final MessageId previousMsgId,
|
||||
final ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Creating group message...");
|
||||
GroupMessage msg = groupMessageFactory
|
||||
.createGroupMessage(getGroupId(), timestamp,
|
||||
parentId, author, body, previousMsgId);
|
||||
storePost(msg, body, handler);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
LOG.info("Creating group message...");
|
||||
GroupMessage msg = groupMessageFactory
|
||||
.createGroupMessage(getGroupId(), timestamp,
|
||||
parentId, author, body, previousMsgId);
|
||||
storePost(msg, body, handler);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -246,17 +219,13 @@ class GroupControllerImpl extends
|
||||
@Override
|
||||
public void loadLocalAuthor(
|
||||
final ResultExceptionHandler<LocalAuthor, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
handler.onResult(author);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
handler.onResult(author);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -264,18 +233,14 @@ class GroupControllerImpl extends
|
||||
@Override
|
||||
public void isDissolved(final
|
||||
ResultExceptionHandler<Boolean, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean isDissolved =
|
||||
privateGroupManager.isDissolved(getGroupId());
|
||||
handler.onResult(isDissolved);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
boolean isDissolved =
|
||||
privateGroupManager.isDissolved(getGroupId());
|
||||
handler.onResult(isDissolved);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,17 +76,13 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
@Override
|
||||
public void createGroup(final String name,
|
||||
final ResultExceptionHandler<GroupId, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
createGroupAndMessages(author, name, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor author = identityManager.getLocalAuthor();
|
||||
createGroupAndMessages(author, name, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -94,36 +90,29 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
private void createGroupAndMessages(final LocalAuthor author,
|
||||
final String name,
|
||||
final ResultExceptionHandler<GroupId, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Creating group...");
|
||||
PrivateGroup group =
|
||||
groupFactory.createPrivateGroup(name, author);
|
||||
LOG.info("Creating new join announcement...");
|
||||
GroupMessage joinMsg = groupMessageFactory
|
||||
.createJoinMessage(group.getId(),
|
||||
clock.currentTimeMillis(), author);
|
||||
storeGroup(group, joinMsg, handler);
|
||||
}
|
||||
cryptoExecutor.execute(() -> {
|
||||
LOG.info("Creating group...");
|
||||
PrivateGroup group =
|
||||
groupFactory.createPrivateGroup(name, author);
|
||||
LOG.info("Creating new join announcement...");
|
||||
GroupMessage joinMsg =
|
||||
groupMessageFactory.createJoinMessage(group.getId(),
|
||||
clock.currentTimeMillis(), author);
|
||||
storeGroup(group, joinMsg, handler);
|
||||
});
|
||||
}
|
||||
|
||||
private void storeGroup(final PrivateGroup group,
|
||||
final GroupMessage joinMsg,
|
||||
final ResultExceptionHandler<GroupId, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Adding group to database...");
|
||||
try {
|
||||
groupManager.addPrivateGroup(group, joinMsg, true);
|
||||
handler.onResult(group.getId());
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
LOG.info("Adding group to database...");
|
||||
try {
|
||||
groupManager.addPrivateGroup(group, joinMsg, true);
|
||||
handler.onResult(group.getId());
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -137,25 +126,21 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
public void sendInvitation(final GroupId g,
|
||||
final Collection<ContactId> contactIds, final String message,
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||
List<Contact> contacts = new ArrayList<>();
|
||||
for (ContactId c : contactIds) {
|
||||
try {
|
||||
contacts.add(contactManager.getContact(c));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||
List<Contact> contacts = new ArrayList<>();
|
||||
for (ContactId c : contactIds) {
|
||||
try {
|
||||
contacts.add(contactManager.getContact(c));
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
signInvitations(g, localAuthor, contacts, message, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
signInvitations(g, localAuthor, contacts, message, handler);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -163,46 +148,39 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
||||
private void signInvitations(final GroupId g, final LocalAuthor localAuthor,
|
||||
final Collection<Contact> contacts, final String message,
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
List<InvitationContext> contexts = new ArrayList<>();
|
||||
for (Contact c : contacts) {
|
||||
byte[] signature = groupInvitationFactory.signInvitation(c,
|
||||
g, timestamp, localAuthor.getPrivateKey());
|
||||
contexts.add(new InvitationContext(c.getId(), timestamp,
|
||||
signature));
|
||||
}
|
||||
sendInvitations(g, contexts, message, handler);
|
||||
cryptoExecutor.execute(() -> {
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
List<InvitationContext> contexts = new ArrayList<>();
|
||||
for (Contact c : contacts) {
|
||||
byte[] signature = groupInvitationFactory.signInvitation(c, g,
|
||||
timestamp, localAuthor.getPrivateKey());
|
||||
contexts.add(new InvitationContext(c.getId(), timestamp,
|
||||
signature));
|
||||
}
|
||||
sendInvitations(g, contexts, message, handler);
|
||||
});
|
||||
}
|
||||
|
||||
private void sendInvitations(final GroupId g,
|
||||
final Collection<InvitationContext> contexts, final String message,
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String msg = message.isEmpty() ? null : message;
|
||||
for (InvitationContext context : contexts) {
|
||||
try {
|
||||
groupInvitationManager.sendInvitation(g,
|
||||
context.contactId, msg, context.timestamp,
|
||||
context.signature);
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
String msg = message.isEmpty() ? null : message;
|
||||
for (InvitationContext context : contexts) {
|
||||
try {
|
||||
groupInvitationManager.sendInvitation(g,
|
||||
context.contactId, msg, context.timestamp,
|
||||
context.signature);
|
||||
} catch (NoSuchContactException e) {
|
||||
// Continue
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
handler.onResult(null);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
handler.onResult(null);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,16 +5,12 @@ import android.os.Bundle;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.R;
|
||||
@@ -65,24 +61,15 @@ public class CreateGroupFragment extends BaseFragment {
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
});
|
||||
nameEntry.setOnEditorActionListener(new OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId,
|
||||
KeyEvent e) {
|
||||
createGroup();
|
||||
return true;
|
||||
}
|
||||
nameEntry.setOnEditorActionListener((v1, actionId, e) -> {
|
||||
createGroup();
|
||||
return true;
|
||||
});
|
||||
|
||||
nameLayout = (TextInputLayout) v.findViewById(R.id.nameLayout);
|
||||
|
||||
createGroupButton = (Button) v.findViewById(R.id.button);
|
||||
createGroupButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createGroup();
|
||||
}
|
||||
});
|
||||
createGroupButton.setOnClickListener(v1 -> createGroup());
|
||||
|
||||
progress = (ProgressBar) v.findViewById(R.id.progressBar);
|
||||
|
||||
|
||||
@@ -67,18 +67,14 @@ class GroupInvitationControllerImpl
|
||||
public void respondToInvitation(final GroupInvitationItem item,
|
||||
final boolean accept,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PrivateGroup g = item.getShareable();
|
||||
ContactId c = item.getCreator().getId();
|
||||
groupInvitationManager.respondToInvitation(c, g, accept);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
PrivateGroup g = item.getShareable();
|
||||
ContactId c = item.getCreator().getId();
|
||||
groupInvitationManager.respondToInvitation(c, g, accept);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -120,80 +120,54 @@ class GroupListControllerImpl extends DbControllerImpl
|
||||
}
|
||||
|
||||
private void onGroupMessageAdded(final GroupMessageHeader h) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupMessageAdded(h);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onGroupMessageAdded(h));
|
||||
}
|
||||
|
||||
private void onGroupInvitationReceived() {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupInvitationReceived();
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onGroupInvitationReceived());
|
||||
}
|
||||
|
||||
private void onGroupAdded(final GroupId g) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupAdded(g);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> listener.onGroupAdded(g));
|
||||
}
|
||||
|
||||
private void onGroupRemoved(final GroupId g) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupRemoved(g);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> listener.onGroupRemoved(g));
|
||||
}
|
||||
|
||||
private void onGroupDissolved(final GroupId g) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupDissolved(g);
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onGroupDissolved(g));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadGroups(
|
||||
final ResultExceptionHandler<Collection<GroupItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<PrivateGroup> groups =
|
||||
groupManager.getPrivateGroups();
|
||||
List<GroupItem> items = new ArrayList<>(groups.size());
|
||||
for (PrivateGroup g : groups) {
|
||||
try {
|
||||
GroupId id = g.getId();
|
||||
GroupCount count = groupManager.getGroupCount(id);
|
||||
boolean dissolved = groupManager.isDissolved(id);
|
||||
items.add(new GroupItem(g, count, dissolved));
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Continue
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<PrivateGroup> groups =
|
||||
groupManager.getPrivateGroups();
|
||||
List<GroupItem> items = new ArrayList<>(groups.size());
|
||||
for (PrivateGroup g : groups) {
|
||||
try {
|
||||
GroupId id = g.getId();
|
||||
GroupCount count = groupManager.getGroupCount(id);
|
||||
boolean dissolved = groupManager.isDissolved(id);
|
||||
items.add(new GroupItem(g, count, dissolved));
|
||||
} catch (NoSuchGroupException e) {
|
||||
// Continue
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading groups took " + duration + " ms");
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading groups took " + duration + " ms");
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -201,20 +175,16 @@ class GroupListControllerImpl extends DbControllerImpl
|
||||
@Override
|
||||
public void removeGroup(final GroupId g,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
groupManager.removePrivateGroup(g);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Removing group took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
groupManager.removePrivateGroup(g);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Removing group took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -222,17 +192,13 @@ class GroupListControllerImpl extends DbControllerImpl
|
||||
@Override
|
||||
public void loadAvailableGroups(
|
||||
final ResultExceptionHandler<Integer, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
handler.onResult(
|
||||
groupInvitationManager.getInvitations().size());
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
handler.onResult(
|
||||
groupInvitationManager.getInvitations().size());
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
@@ -107,25 +106,17 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
|
||||
status
|
||||
.setText(ctx.getString(R.string.groups_group_is_dissolved));
|
||||
status.setVisibility(VISIBLE);
|
||||
remove.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onGroupRemoveClick(group);
|
||||
}
|
||||
});
|
||||
remove.setOnClickListener(v -> listener.onGroupRemoveClick(group));
|
||||
remove.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
// Open Group on Click
|
||||
layout.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent i = new Intent(ctx, GroupActivity.class);
|
||||
GroupId id = group.getId();
|
||||
i.putExtra(GROUP_ID, id.getBytes());
|
||||
i.putExtra(GROUP_NAME, group.getName());
|
||||
ctx.startActivity(i);
|
||||
}
|
||||
layout.setOnClickListener(v -> {
|
||||
Intent i = new Intent(ctx, GroupActivity.class);
|
||||
GroupId id = group.getId();
|
||||
i.putExtra(GROUP_ID, id.getBytes());
|
||||
i.putExtra(GROUP_NAME, group.getName());
|
||||
ctx.startActivity(i);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -42,26 +42,22 @@ class GroupMemberListControllerImpl extends DbControllerImpl
|
||||
@Override
|
||||
public void loadMembers(final GroupId groupId, final
|
||||
ResultExceptionHandler<Collection<MemberListItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<MemberListItem> items = new ArrayList<>();
|
||||
Collection<GroupMember> members =
|
||||
privateGroupManager.getMembers(groupId);
|
||||
for (GroupMember m : members) {
|
||||
ContactId c = m.getContactId();
|
||||
boolean online = false;
|
||||
if (c != null)
|
||||
online = connectionRegistry.isConnected(c);
|
||||
items.add(new MemberListItem(m, online));
|
||||
}
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Collection<MemberListItem> items = new ArrayList<>();
|
||||
Collection<GroupMember> members =
|
||||
privateGroupManager.getMembers(groupId);
|
||||
for (GroupMember m : members) {
|
||||
ContactId c = m.getContactId();
|
||||
boolean online = false;
|
||||
if (c != null)
|
||||
online = connectionRegistry.isConnected(c);
|
||||
items.add(new MemberListItem(m, online));
|
||||
}
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.android.privategroup.reveal;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.LayoutRes;
|
||||
@@ -110,19 +109,8 @@ public class RevealContactsActivity extends ContactSelectorActivity
|
||||
new AlertDialog.Builder(this, R.style.OnboardingDialogTheme)
|
||||
.setMessage(getString(R.string.groups_reveal_dialog_message))
|
||||
.setNeutralButton(R.string.got_it,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
})
|
||||
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
onboardingShown();
|
||||
}
|
||||
})
|
||||
(dialog, which) -> dialog.cancel())
|
||||
.setOnCancelListener(dialog -> onboardingShown())
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -62,18 +62,12 @@ class RevealContactsControllerImpl extends DbControllerImpl
|
||||
public void loadContacts(final GroupId g,
|
||||
final Collection<ContactId> selection,
|
||||
final ResultExceptionHandler<Collection<RevealableContactItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<RevealableContactItem> items =
|
||||
getItems(g, selection);
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
handler.onResult(getItems(g, selection));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -105,38 +99,31 @@ class RevealContactsControllerImpl extends DbControllerImpl
|
||||
@Override
|
||||
public void isOnboardingNeeded(
|
||||
final ResultExceptionHandler<Boolean, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
handler.onResult(
|
||||
settings.getBoolean(SHOW_ONBOARDING_REVEAL_CONTACTS,
|
||||
true));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Settings settings =
|
||||
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
handler.onResult(
|
||||
settings.getBoolean(SHOW_ONBOARDING_REVEAL_CONTACTS,
|
||||
true));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onboardingShown(ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings settings = new Settings();
|
||||
settings.putBoolean(SHOW_ONBOARDING_REVEAL_CONTACTS, false);
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Settings settings = new Settings();
|
||||
settings.putBoolean(SHOW_ONBOARDING_REVEAL_CONTACTS, false);
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -144,22 +131,19 @@ class RevealContactsControllerImpl extends DbControllerImpl
|
||||
@Override
|
||||
public void reveal(final GroupId g, final Collection<ContactId> contacts,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
groupInvitationManager.revealRelationship(c, g);
|
||||
} catch (ProtocolStateException e) {
|
||||
// action is outdated, move to next contact
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.log(INFO, e.toString(), e);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
break;
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
groupInvitationManager.revealRelationship(c, g);
|
||||
} catch (ProtocolStateException e) {
|
||||
// action is outdated, move to next contact
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.log(INFO, e.toString(), e);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -256,12 +256,9 @@ public class BriarReportPrimer implements ReportPrimer {
|
||||
Looper.prepare();
|
||||
Handler handler = new Handler();
|
||||
handler.post(runnable);
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Looper looper = Looper.myLooper();
|
||||
if (looper != null) looper.quit();
|
||||
}
|
||||
handler.post(() -> {
|
||||
Looper looper = Looper.myLooper();
|
||||
if (looper != null) looper.quit();
|
||||
});
|
||||
Looper.loop();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.briar.android.reporting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
@@ -37,6 +36,7 @@ import java.util.logging.Logger;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.inputmethod.InputMethodManager.SHOW_FORCED;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.acra.ACRAConstants.EXTRA_REPORT_FILE;
|
||||
import static org.acra.ReportField.ANDROID_VERSION;
|
||||
@@ -115,37 +115,22 @@ public class DevReportActivity extends BaseCrashReportDialog
|
||||
includeDebugReport.setChecked(true);
|
||||
}
|
||||
|
||||
findViewById(R.id.acceptButton).setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
reviewing = true;
|
||||
requestReport.setVisibility(GONE);
|
||||
((InputMethodManager) getSystemService(
|
||||
Context.INPUT_METHOD_SERVICE))
|
||||
.showSoftInput(userCommentView,
|
||||
InputMethodManager.SHOW_FORCED);
|
||||
}
|
||||
});
|
||||
findViewById(R.id.declineButton).setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
closeReport();
|
||||
}
|
||||
});
|
||||
chevron.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean show =
|
||||
chevron.getText().equals(getString(R.string.show));
|
||||
if (show) {
|
||||
chevron.setText(R.string.hide);
|
||||
refresh();
|
||||
} else {
|
||||
chevron.setText(R.string.show);
|
||||
report.setVisibility(GONE);
|
||||
}
|
||||
findViewById(R.id.acceptButton).setOnClickListener(v -> {
|
||||
reviewing = true;
|
||||
requestReport.setVisibility(GONE);
|
||||
((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
|
||||
.showSoftInput(userCommentView, SHOW_FORCED);
|
||||
});
|
||||
findViewById(R.id.declineButton).setOnClickListener(v -> closeReport());
|
||||
chevron.setOnClickListener(v -> {
|
||||
boolean show =
|
||||
chevron.getText().equals(getString(R.string.show));
|
||||
if (show) {
|
||||
chevron.setText(R.string.hide);
|
||||
refresh();
|
||||
} else {
|
||||
chevron.setText(R.string.show);
|
||||
report.setVisibility(GONE);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -141,54 +141,39 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
notifyLockscreen.setVisible(true);
|
||||
notifyLockscreen.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
notifySound.setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
String title =
|
||||
getString(R.string.choose_ringtone_title);
|
||||
Intent i = new Intent(ACTION_RINGTONE_PICKER);
|
||||
i.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
|
||||
i.putExtra(EXTRA_RINGTONE_TITLE, title);
|
||||
i.putExtra(EXTRA_RINGTONE_DEFAULT_URI,
|
||||
DEFAULT_NOTIFICATION_URI);
|
||||
i.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
|
||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
||||
Uri uri;
|
||||
String ringtoneUri =
|
||||
settings.get(PREF_NOTIFY_RINGTONE_URI);
|
||||
if (StringUtils.isNullOrEmpty(ringtoneUri))
|
||||
uri = DEFAULT_NOTIFICATION_URI;
|
||||
else uri = Uri.parse(ringtoneUri);
|
||||
i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri);
|
||||
}
|
||||
startActivityForResult(i, REQUEST_RINGTONE);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
notifySound.setOnPreferenceClickListener(preference -> {
|
||||
String title = getString(R.string.choose_ringtone_title);
|
||||
Intent i = new Intent(ACTION_RINGTONE_PICKER);
|
||||
i.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
|
||||
i.putExtra(EXTRA_RINGTONE_TITLE, title);
|
||||
i.putExtra(EXTRA_RINGTONE_DEFAULT_URI, DEFAULT_NOTIFICATION_URI);
|
||||
i.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
|
||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
||||
Uri uri;
|
||||
String ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
||||
if (StringUtils.isNullOrEmpty(ringtoneUri))
|
||||
uri = DEFAULT_NOTIFICATION_URI;
|
||||
else uri = Uri.parse(ringtoneUri);
|
||||
i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri);
|
||||
}
|
||||
startActivityForResult(i, REQUEST_RINGTONE);
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("pref_key_send_feedback").setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
triggerFeedback();
|
||||
return true;
|
||||
}
|
||||
preference -> {
|
||||
triggerFeedback();
|
||||
return true;
|
||||
});
|
||||
|
||||
Preference testData = findPreference("pref_key_test_data");
|
||||
if (IS_DEBUG_BUILD) {
|
||||
testData.setOnPreferenceClickListener(
|
||||
new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(
|
||||
Preference preference) {
|
||||
LOG.info("Creating test data");
|
||||
testDataCreator.createTestData();
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
testData.setOnPreferenceClickListener(preference -> {
|
||||
LOG.info("Creating test data");
|
||||
testDataCreator.createTestData();
|
||||
getActivity().finish();
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
testData.setVisible(false);
|
||||
}
|
||||
@@ -209,83 +194,69 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
|
||||
private void loadSettings() {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
Settings btSettings =
|
||||
settingsManager.getSettings(BT_NAMESPACE);
|
||||
Settings torSettings =
|
||||
settingsManager.getSettings(TOR_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading settings took " + duration + " ms");
|
||||
boolean btSetting =
|
||||
btSettings.getBoolean(PREF_BT_ENABLE, false);
|
||||
int torSetting = torSettings.getInt(PREF_TOR_NETWORK,
|
||||
PREF_TOR_NETWORK_ALWAYS);
|
||||
displaySettings(btSetting, torSetting);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
Settings btSettings = settingsManager.getSettings(BT_NAMESPACE);
|
||||
Settings torSettings =
|
||||
settingsManager.getSettings(TOR_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading settings took " + duration + " ms");
|
||||
boolean btSetting =
|
||||
btSettings.getBoolean(PREF_BT_ENABLE, false);
|
||||
int torSetting = torSettings.getInt(PREF_TOR_NETWORK,
|
||||
PREF_TOR_NETWORK_ALWAYS);
|
||||
displaySettings(btSetting, torSetting);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displaySettings(final boolean btSetting,
|
||||
final int torSetting) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
enableBluetooth.setValue(Boolean.toString(btSetting));
|
||||
torNetwork.setValue(Integer.toString(torSetting));
|
||||
listener.runOnUiThreadUnlessDestroyed(() -> {
|
||||
enableBluetooth.setValue(Boolean.toString(btSetting));
|
||||
torNetwork.setValue(Integer.toString(torSetting));
|
||||
|
||||
notifyPrivateMessages.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_PRIVATE, true));
|
||||
notifyPrivateMessages.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_PRIVATE, true));
|
||||
|
||||
notifyGroupMessages.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_GROUP, true));
|
||||
notifyGroupMessages.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_GROUP, true));
|
||||
|
||||
notifyForumPosts.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_FORUM, true));
|
||||
notifyForumPosts.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_FORUM, true));
|
||||
|
||||
notifyBlogPosts.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_BLOG, true));
|
||||
notifyBlogPosts.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_BLOG, true));
|
||||
|
||||
notifyVibration.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_VIBRATION, true));
|
||||
notifyVibration.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_VIBRATION, true));
|
||||
|
||||
notifyLockscreen.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_LOCK_SCREEN, false));
|
||||
notifyLockscreen.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_LOCK_SCREEN, false));
|
||||
|
||||
String text;
|
||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
||||
String ringtoneName =
|
||||
settings.get(PREF_NOTIFY_RINGTONE_NAME);
|
||||
if (StringUtils.isNullOrEmpty(ringtoneName)) {
|
||||
text = getString(R.string.notify_sound_setting_default);
|
||||
} else {
|
||||
text = ringtoneName;
|
||||
}
|
||||
String text;
|
||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
||||
String ringtoneName = settings.get(PREF_NOTIFY_RINGTONE_NAME);
|
||||
if (StringUtils.isNullOrEmpty(ringtoneName)) {
|
||||
text = getString(R.string.notify_sound_setting_default);
|
||||
} else {
|
||||
text = getString(R.string.notify_sound_setting_disabled);
|
||||
text = ringtoneName;
|
||||
}
|
||||
notifySound.setSummary(text);
|
||||
} else {
|
||||
text = getString(R.string.notify_sound_setting_disabled);
|
||||
}
|
||||
notifySound.setSummary(text);
|
||||
});
|
||||
}
|
||||
|
||||
private void triggerFeedback() {
|
||||
androidExecutor.runOnBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ACRA.getErrorReporter().handleException(new UserFeedback(),
|
||||
false);
|
||||
}
|
||||
});
|
||||
androidExecutor.runOnBackgroundThread(() -> ACRA.getErrorReporter()
|
||||
.handleException(new UserFeedback(), false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -331,59 +302,47 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
|
||||
private void storeTorSettings(final int torSetting) {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings s = new Settings();
|
||||
s.putInt(PREF_TOR_NETWORK, torSetting);
|
||||
long now = System.currentTimeMillis();
|
||||
settingsManager.mergeSettings(s, TOR_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Merging settings took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
Settings s = new Settings();
|
||||
s.putInt(PREF_TOR_NETWORK, torSetting);
|
||||
long now = System.currentTimeMillis();
|
||||
settingsManager.mergeSettings(s, TOR_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Merging settings took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void storeBluetoothSettings(final boolean btSetting) {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Settings s = new Settings();
|
||||
s.putBoolean(PREF_BT_ENABLE, btSetting);
|
||||
long now = System.currentTimeMillis();
|
||||
settingsManager.mergeSettings(s, BT_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Merging settings took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
Settings s = new Settings();
|
||||
s.putBoolean(PREF_BT_ENABLE, btSetting);
|
||||
long now = System.currentTimeMillis();
|
||||
settingsManager.mergeSettings(s, BT_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Merging settings took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void storeSettings(final Settings settings) {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Merging settings took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
listener.runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Merging settings took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,20 +61,16 @@ class BlogInvitationControllerImpl
|
||||
public void respondToInvitation(final SharingInvitationItem item,
|
||||
final boolean accept,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Blog f = (Blog) item.getShareable();
|
||||
for (Contact c : item.getNewSharers()) {
|
||||
// TODO: What happens if a contact has been removed?
|
||||
blogSharingManager.respondToInvitation(f, c, accept);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Blog f = (Blog) item.getShareable();
|
||||
for (Contact c : item.getNewSharers()) {
|
||||
// TODO: What happens if a contact has been removed?
|
||||
blogSharingManager.respondToInvitation(f, c, accept);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,20 +62,16 @@ class ForumInvitationControllerImpl
|
||||
public void respondToInvitation(final SharingInvitationItem item,
|
||||
final boolean accept,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Forum f = (Forum) item.getShareable();
|
||||
for (Contact c : item.getNewSharers()) {
|
||||
// TODO: What happens if a contact has been removed?
|
||||
forumSharingManager.respondToInvitation(f, c, accept);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
Forum f = (Forum) item.getShareable();
|
||||
for (Contact c : item.getNewSharers()) {
|
||||
// TODO: What happens if a contact has been removed?
|
||||
forumSharingManager.respondToInvitation(f, c, accept);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -123,20 +123,17 @@ public abstract class InvitationActivity<I extends InvitationItem>
|
||||
|
||||
protected void displayInvitations(final int revision,
|
||||
final Collection<I> invitations, final boolean clear) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (invitations.isEmpty()) {
|
||||
LOG.info("No more invitations available, finishing");
|
||||
supportFinishAfterTransition();
|
||||
} else if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (clear) adapter.setItems(invitations);
|
||||
else adapter.addAll(invitations);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadInvitations(clear);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (invitations.isEmpty()) {
|
||||
LOG.info("No more invitations available, finishing");
|
||||
supportFinishAfterTransition();
|
||||
} else if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
if (clear) adapter.setItems(invitations);
|
||||
else adapter.addAll(invitations);
|
||||
} else {
|
||||
LOG.info("Concurrent update, reloading");
|
||||
loadInvitations(clear);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -93,23 +93,18 @@ public abstract class InvitationControllerImpl<I extends InvitationItem>
|
||||
@Override
|
||||
public void loadInvitations(final boolean clear,
|
||||
final ResultExceptionHandler<Collection<I>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<I> invitations = new ArrayList<>();
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
invitations.addAll(getInvitations());
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info(
|
||||
"Loading invitations took " + duration + " ms");
|
||||
handler.onResult(invitations);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
Collection<I> invitations = new ArrayList<>();
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
invitations.addAll(getInvitations());
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading invitations took " + duration + " ms");
|
||||
handler.onResult(invitations);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,18 +53,8 @@ public class InvitationViewHolder<I extends InvitationItem>
|
||||
subscribed.setVisibility(GONE);
|
||||
}
|
||||
|
||||
accept.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onItemClick(item, true);
|
||||
}
|
||||
});
|
||||
decline.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onItemClick(item, false);
|
||||
}
|
||||
});
|
||||
accept.setOnClickListener(v -> listener.onItemClick(item, true));
|
||||
decline.setOnClickListener(v -> listener.onItemClick(item, false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -58,27 +58,23 @@ class ShareBlogControllerImpl extends ContactSelectorControllerImpl
|
||||
public void share(final GroupId g, final Collection<ContactId> contacts,
|
||||
final String message,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String msg = isNullOrEmpty(message) ? null : message;
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
long time = Math.max(clock.currentTimeMillis(),
|
||||
conversationManager.getGroupCount(c)
|
||||
.getLatestMsgTime() + 1);
|
||||
blogSharingManager.sendInvitation(g, c, msg, time);
|
||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
String msg = isNullOrEmpty(message) ? null : message;
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
long time = Math.max(clock.currentTimeMillis(),
|
||||
conversationManager.getGroupCount(c)
|
||||
.getLatestMsgTime() + 1);
|
||||
blogSharingManager.sendInvitation(g, c, msg, time);
|
||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,27 +58,23 @@ class ShareForumControllerImpl extends ContactSelectorControllerImpl
|
||||
public void share(final GroupId g, final Collection<ContactId> contacts,
|
||||
final String message,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String msg = isNullOrEmpty(message) ? null : message;
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
long time = Math.max(clock.currentTimeMillis(),
|
||||
conversationManager.getGroupCount(c)
|
||||
.getLatestMsgTime() + 1);
|
||||
forumSharingManager.sendInvitation(g, c, msg, time);
|
||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
String msg = isNullOrEmpty(message) ? null : message;
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
long time = Math.max(clock.currentTimeMillis(),
|
||||
conversationManager.getGroupCount(c)
|
||||
.getLatestMsgTime() + 1);
|
||||
forumSharingManager.sendInvitation(g, c, msg, time);
|
||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -100,33 +100,25 @@ abstract class SharingStatusActivity extends BriarActivity {
|
||||
}
|
||||
|
||||
private void loadSharedWith() {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
List<ContactItem> contactItems = new ArrayList<>();
|
||||
for (Contact c : getSharedWith()) {
|
||||
boolean online =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
ContactItem item = new ContactItem(c, online);
|
||||
contactItems.add(item);
|
||||
}
|
||||
displaySharedWith(contactItems);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
List<ContactItem> contactItems = new ArrayList<>();
|
||||
for (Contact c : getSharedWith()) {
|
||||
boolean online = connectionRegistry.isConnected(c.getId());
|
||||
ContactItem item = new ContactItem(c, online);
|
||||
contactItems.add(item);
|
||||
}
|
||||
displaySharedWith(contactItems);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displaySharedWith(final List<ContactItem> contacts) {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
}
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -43,12 +43,9 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
setContentView(R.layout.splash);
|
||||
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startNextActivity();
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
new Handler().postDelayed(() -> {
|
||||
startNextActivity();
|
||||
supportFinishAfterTransition();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@@ -72,12 +69,8 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void setPreferencesDefaults() {
|
||||
androidExecutor.runOnBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
androidExecutor.runOnBackgroundThread(() ->
|
||||
PreferenceManager.setDefaultValues(SplashScreenActivity.this,
|
||||
R.xml.panic_preferences, false);
|
||||
}
|
||||
});
|
||||
R.xml.panic_preferences, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,13 +85,8 @@ public abstract class BaseThreadItemViewHolder<I extends ThreadItem>
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
layout.setBackgroundColor(
|
||||
(Integer) valueAnimator.getAnimatedValue());
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener(valueAnimator -> layout.setBackgroundColor(
|
||||
(Integer) valueAnimator.getAnimatedValue()));
|
||||
anim.setDuration(ANIMATION_DURATION);
|
||||
anim.start();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -117,22 +116,16 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
||||
});
|
||||
upButton = (UnreadMessageButton) findViewById(R.id.upButton);
|
||||
downButton = (UnreadMessageButton) findViewById(R.id.downButton);
|
||||
upButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = adapter.getVisibleUnreadPosTop();
|
||||
if (position != NO_POSITION) {
|
||||
list.getRecyclerView().scrollToPosition(position);
|
||||
}
|
||||
upButton.setOnClickListener(v -> {
|
||||
int position = adapter.getVisibleUnreadPosTop();
|
||||
if (position != NO_POSITION) {
|
||||
list.getRecyclerView().scrollToPosition(position);
|
||||
}
|
||||
});
|
||||
downButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = adapter.getVisibleUnreadPosBottom();
|
||||
if (position != NO_POSITION) {
|
||||
list.getRecyclerView().scrollToPosition(position);
|
||||
}
|
||||
downButton.setOnClickListener(v -> {
|
||||
int position = adapter.getVisibleUnreadPosBottom();
|
||||
if (position != NO_POSITION) {
|
||||
list.getRecyclerView().scrollToPosition(position);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -101,16 +101,12 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
public void onActivityDestroy() {
|
||||
final MessageId messageId = listener.getFirstVisibleMessageId();
|
||||
if (messageId != null) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
messageTracker
|
||||
.storeMessageId(groupId, messageId);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
messageTracker.storeMessageId(groupId, messageId);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -123,12 +119,8 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
GroupRemovedEvent s = (GroupRemovedEvent) e;
|
||||
if (s.getGroup().getId().equals(getGroupId())) {
|
||||
LOG.info("Group removed");
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGroupRemoved();
|
||||
}
|
||||
});
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onGroupRemoved());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,21 +129,18 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
public void loadNamedGroup(
|
||||
final ResultExceptionHandler<G, DbException> handler) {
|
||||
checkGroupId();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
G groupItem = loadNamedGroup();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading group took " + duration + " ms");
|
||||
handler.onResult(groupItem);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
G groupItem = loadNamedGroup();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading group took " + duration + " ms");
|
||||
handler.onResult(groupItem);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -163,36 +152,32 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
public void loadItems(
|
||||
final ResultExceptionHandler<ThreadItemList<I>, DbException> handler) {
|
||||
checkGroupId();
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Load headers
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<H> headers = loadHeaders();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading headers took " + duration + " ms");
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
// Load headers
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<H> headers = loadHeaders();
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading headers took " + duration + " ms");
|
||||
|
||||
// Load bodies into cache
|
||||
now = System.currentTimeMillis();
|
||||
for (H header : headers) {
|
||||
if (!bodyCache.containsKey(header.getId())) {
|
||||
bodyCache.put(header.getId(),
|
||||
loadMessageBody(header));
|
||||
}
|
||||
// Load bodies into cache
|
||||
now = System.currentTimeMillis();
|
||||
for (H header : headers) {
|
||||
if (!bodyCache.containsKey(header.getId())) {
|
||||
bodyCache.put(header.getId(),
|
||||
loadMessageBody(header));
|
||||
}
|
||||
duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading bodies took " + duration + " ms");
|
||||
|
||||
// Build and hand over items
|
||||
handler.onResult(buildItems(headers));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Loading bodies took " + duration + " ms");
|
||||
|
||||
// Build and hand over items
|
||||
handler.onResult(buildItems(headers));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -210,21 +195,17 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
|
||||
@Override
|
||||
public void markItemsRead(final Collection<I> items) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
for (I i : items) {
|
||||
markRead(i.getId());
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Marking read took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
for (I i : items) {
|
||||
markRead(i.getId());
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Marking read took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -234,22 +215,18 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
|
||||
protected void storePost(final M msg, final String body,
|
||||
final ResultExceptionHandler<I, DbException> resultHandler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
H header = addLocalMessage(msg);
|
||||
bodyCache.put(msg.getMessage().getId(), body);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
resultHandler.onResult(buildItem(header, body));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
resultHandler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
H header = addLocalMessage(msg);
|
||||
bodyCache.put(msg.getMessage().getId(), body);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
resultHandler.onResult(buildItem(header, body));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
resultHandler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -259,21 +236,17 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
||||
|
||||
@Override
|
||||
public void deleteNamedGroup(final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
G groupItem = loadNamedGroup();
|
||||
deleteNamedGroup(groupItem);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Removing group took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
G groupItem = loadNamedGroup();
|
||||
deleteNamedGroup(groupItem);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Removing group took " + duration + " ms");
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -50,12 +50,7 @@ public class ThreadPostViewHolder<I extends ThreadItem>
|
||||
lvlText.setVisibility(GONE);
|
||||
}
|
||||
|
||||
replyButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onReplyClick(item);
|
||||
}
|
||||
});
|
||||
replyButton.setOnClickListener(v -> listener.onReplyClick(item));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.util;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
@@ -143,16 +142,13 @@ public class UiUtils {
|
||||
|
||||
public static OnClickListener getGoToSettingsListener(
|
||||
final Context context) {
|
||||
return new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent i = new Intent();
|
||||
i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
|
||||
i.addCategory(CATEGORY_DEFAULT);
|
||||
i.setData(Uri.parse("package:" + APPLICATION_ID));
|
||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
}
|
||||
return (dialog, which) -> {
|
||||
Intent i = new Intent();
|
||||
i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
|
||||
i.addCategory(CATEGORY_DEFAULT);
|
||||
i.setData(Uri.parse("package:" + APPLICATION_ID));
|
||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,13 +156,7 @@ public class UiUtils {
|
||||
new AlertDialog.Builder(ctx, R.style.OnboardingDialogTheme)
|
||||
.setMessage(text)
|
||||
.setNeutralButton(R.string.got_it,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
})
|
||||
(dialog, which) -> dialog.cancel())
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -94,24 +94,13 @@ public class BriarRecyclerView extends FrameLayout {
|
||||
}
|
||||
|
||||
private void addLayoutChangeListener() {
|
||||
recyclerView.addOnLayoutChangeListener(
|
||||
new OnLayoutChangeListener() {
|
||||
@Override
|
||||
public void onLayoutChange(View v, int left, int top,
|
||||
int right, int bottom, int oldLeft, int oldTop,
|
||||
int oldRight, int oldBottom) {
|
||||
if (bottom < oldBottom) {
|
||||
recyclerView.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
scrollToPosition(
|
||||
recyclerView.getAdapter()
|
||||
.getItemCount() - 1);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
recyclerView.addOnLayoutChangeListener((v, left, top, right, bottom,
|
||||
oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
if (bottom < oldBottom) {
|
||||
recyclerView.postDelayed(() -> scrollToPosition(
|
||||
recyclerView.getAdapter().getItemCount() - 1), 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setLayoutManager(RecyclerView.LayoutManager layout) {
|
||||
@@ -191,14 +180,11 @@ public class BriarRecyclerView extends FrameLayout {
|
||||
if (recyclerView == null || recyclerView.getAdapter() == null) {
|
||||
throw new IllegalStateException("Need to call setAdapter() first!");
|
||||
}
|
||||
refresher = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Updating Content...");
|
||||
Adapter adapter = recyclerView.getAdapter();
|
||||
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
|
||||
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
|
||||
}
|
||||
refresher = () -> {
|
||||
LOG.info("Updating Content...");
|
||||
Adapter adapter = recyclerView.getAdapter();
|
||||
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
|
||||
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
|
||||
};
|
||||
LOG.info("Adding Handler Callback");
|
||||
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
|
||||
|
||||
@@ -75,34 +75,18 @@ public class TextInputView extends KeyboardAwareLinearLayout
|
||||
}
|
||||
|
||||
ui.emojiToggle.attach(ui.emojiDrawer);
|
||||
ui.emojiToggle.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onEmojiToggleClicked();
|
||||
ui.emojiToggle.setOnClickListener(v -> onEmojiToggleClicked());
|
||||
ui.editText.setOnClickListener(v -> showSoftKeyboard());
|
||||
ui.editText.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KEYCODE_BACK && isEmojiDrawerOpen()) {
|
||||
hideEmojiDrawer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
ui.editText.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showSoftKeyboard();
|
||||
}
|
||||
});
|
||||
ui.editText.setOnKeyListener(new OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KEYCODE_BACK && isEmojiDrawerOpen()) {
|
||||
hideEmojiDrawer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
ui.sendButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.onSendClick(ui.editText.getText().toString());
|
||||
}
|
||||
ui.sendButton.setOnClickListener(v -> {
|
||||
if (listener != null) {
|
||||
listener.onSendClick(ui.editText.getText().toString());
|
||||
}
|
||||
});
|
||||
ui.emojiDrawer.setEmojiEventListener(this);
|
||||
@@ -167,22 +151,13 @@ public class TextInputView extends KeyboardAwareLinearLayout
|
||||
if (isKeyboardOpen()) return;
|
||||
|
||||
if (ui.emojiDrawer.isShowing()) {
|
||||
postOnKeyboardOpen(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hideEmojiDrawer();
|
||||
}
|
||||
});
|
||||
postOnKeyboardOpen(this::hideEmojiDrawer);
|
||||
}
|
||||
ui.editText.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ui.editText.requestFocus();
|
||||
InputMethodManager imm =
|
||||
(InputMethodManager) getContext()
|
||||
.getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(ui.editText, SHOW_IMPLICIT);
|
||||
}
|
||||
ui.editText.post(() -> {
|
||||
ui.editText.requestFocus();
|
||||
InputMethodManager imm = (InputMethodManager)
|
||||
getContext().getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(ui.editText, SHOW_IMPLICIT);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -194,11 +169,7 @@ public class TextInputView extends KeyboardAwareLinearLayout
|
||||
|
||||
public void showEmojiDrawer() {
|
||||
if (isKeyboardOpen()) {
|
||||
postOnKeyboardClose(new Runnable() {
|
||||
@Override public void run() {
|
||||
ui.emojiDrawer.show(getKeyboardHeight());
|
||||
}
|
||||
});
|
||||
postOnKeyboardClose(() -> ui.emojiDrawer.show(getKeyboardHeight()));
|
||||
hideSoftKeyboard();
|
||||
} else {
|
||||
ui.emojiDrawer.show(getKeyboardHeight());
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
@@ -62,21 +61,13 @@ public class LinkDialogFragment extends DialogFragment {
|
||||
getString(R.string.link_warning_open_link)) : i;
|
||||
|
||||
Button openButton = (Button) v.findViewById(R.id.openButton);
|
||||
openButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(intent);
|
||||
getDialog().dismiss();
|
||||
}
|
||||
openButton.setOnClickListener(v1 -> {
|
||||
startActivity(intent);
|
||||
getDialog().dismiss();
|
||||
});
|
||||
|
||||
Button cancelButton = (Button) v.findViewById(R.id.cancelButton);
|
||||
cancelButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
getDialog().cancel();
|
||||
}
|
||||
});
|
||||
cancelButton.setOnClickListener(v1 -> getDialog().cancel());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user