mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Compare commits
76 Commits
screenshot
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39478a7914 | ||
|
|
112e71a9cb | ||
|
|
5650bef310 | ||
|
|
2a87171c49 | ||
|
|
15cb5409e7 | ||
|
|
fd07dc006d | ||
|
|
cc87c4e37d | ||
|
|
4a10e876f6 | ||
|
|
fad0057c4a | ||
|
|
5aabfcea9a | ||
|
|
f7d928c774 | ||
|
|
bd983d9796 | ||
|
|
de8d1b7d96 | ||
|
|
9155f62d0b | ||
|
|
86684e228a | ||
|
|
9615eff649 | ||
|
|
9381d46f51 | ||
|
|
e4a3a1ad40 | ||
|
|
905dc2a662 | ||
|
|
c2b7f85b8e | ||
|
|
ae81eb3737 | ||
|
|
60d949c342 | ||
|
|
1c90e64894 | ||
|
|
f0e2d5281f | ||
|
|
c7522dae1f | ||
|
|
097d14b9a1 | ||
|
|
0491c3cace | ||
|
|
cbae13feca | ||
|
|
b7c8859c82 | ||
|
|
2e120f752c | ||
|
|
031eac54c5 | ||
|
|
2c2596afdd | ||
|
|
d1be14effe | ||
|
|
b56e7ab07d | ||
|
|
089e9589ed | ||
|
|
660ba16a14 | ||
|
|
b101c4b636 | ||
|
|
fdfddd2667 | ||
|
|
296546544f | ||
|
|
ad579a6ba3 | ||
|
|
90e82357ba | ||
|
|
b3b40753d8 | ||
|
|
e60df3cece | ||
|
|
da3cb95151 | ||
|
|
c27885072f | ||
|
|
6557d564c9 | ||
|
|
53edcaf3e9 | ||
|
|
5122c961b4 | ||
|
|
f83b9244d4 | ||
|
|
81292967e0 | ||
|
|
b72f6b4fc3 | ||
|
|
488be49c93 | ||
|
|
90db45817a | ||
|
|
81863b9db6 | ||
|
|
da069adb57 | ||
|
|
46425b09fa | ||
|
|
41e1a436c9 | ||
|
|
989394d18b | ||
|
|
b6b3f9c292 | ||
|
|
a52547f73b | ||
|
|
24f823a3ce | ||
|
|
7d479063a9 | ||
|
|
2309e73216 | ||
|
|
4b325f797b | ||
|
|
9be83c3cc7 | ||
|
|
86f650503b | ||
|
|
d430b4fd2d | ||
|
|
fcf7cf72ea | ||
|
|
b78dfea95f | ||
|
|
183fe08565 | ||
|
|
7e32697696 | ||
|
|
29758b174a | ||
|
|
61e18f104e | ||
|
|
ffeca8817f | ||
|
|
59fae2fa3c | ||
|
|
2d9345c018 |
@@ -9,8 +9,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 10101
|
||||
versionName "1.1.1"
|
||||
versionCode 10102
|
||||
versionName "1.1.2"
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.briarproject.bramble.api;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface Nameable {
|
||||
|
||||
String getName();
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package org.briarproject.bramble.api;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An exception that indicates an unrecoverable version mismatch.
|
||||
*/
|
||||
public class UnsupportedVersionException extends IOException {
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.api.identity;
|
||||
|
||||
import org.briarproject.bramble.api.Nameable;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
|
||||
@@ -13,7 +14,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
|
||||
*/
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class Author {
|
||||
public class Author implements Nameable {
|
||||
|
||||
public enum Status {
|
||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
||||
|
||||
@@ -3,7 +3,13 @@ package org.briarproject.bramble.api.keyagreement;
|
||||
public interface KeyAgreementConstants {
|
||||
|
||||
/**
|
||||
* The current version of the BQP protocol. Version number 89 is reserved.
|
||||
* The version of the BQP protocol used in beta releases. This version
|
||||
* number is reserved.
|
||||
*/
|
||||
byte BETA_PROTOCOL_VERSION = 89;
|
||||
|
||||
/**
|
||||
* The current version of the BQP protocol.
|
||||
*/
|
||||
byte PROTOCOL_VERSION = 4;
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.briarproject.bramble.api.keyagreement;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Thrown when a QR code that has been scanned uses a protocol version that is
|
||||
* not supported.
|
||||
*/
|
||||
public class UnsupportedVersionException extends IOException {
|
||||
|
||||
private final boolean tooOld;
|
||||
|
||||
public UnsupportedVersionException(boolean tooOld) {
|
||||
this.tooOld = tooOld;
|
||||
}
|
||||
|
||||
public boolean isTooOld() {
|
||||
return tooOld;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.data.BdfReader;
|
||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
||||
import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
|
||||
import org.briarproject.bramble.api.keyagreement.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.BETA_PROTOCOL_VERSION;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
||||
@@ -43,8 +44,11 @@ class PayloadParserImpl implements PayloadParser {
|
||||
// First byte: the protocol version
|
||||
int protocolVersion = in.read();
|
||||
if (protocolVersion == -1) throw new FormatException();
|
||||
if (protocolVersion != PROTOCOL_VERSION)
|
||||
throw new UnsupportedVersionException();
|
||||
if (protocolVersion != PROTOCOL_VERSION) {
|
||||
boolean tooOld = protocolVersion < PROTOCOL_VERSION ||
|
||||
protocolVersion == BETA_PROTOCOL_VERSION;
|
||||
throw new UnsupportedVersionException(tooOld);
|
||||
}
|
||||
// The rest of the payload is a BDF list with one or more elements
|
||||
BdfReader r = bdfReaderFactory.createReader(in);
|
||||
BdfList payload = r.readList();
|
||||
|
||||
@@ -2,7 +2,7 @@ Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
|
||||
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
|
||||
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
|
||||
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
|
||||
Bridge 195.91.239.8:9001 BA83F62551545655BBEBBFF353A45438D73FD45A
|
||||
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
|
||||
Bridge 97.107.131.168:65341 DCDA8A5F1E2C50A6756A58462E5CF4B6B2DFDE26
|
||||
Bridge 85.229.131.78:444 50E433CCC5FEC11CC34CB4D92033561E065EA106
|
||||
Bridge 85.229.131.78:444 50E433CCC5FEC11CC34CB4D92033561E065EA106
|
||||
Bridge 178.62.62.193:8443 391B1F9B6A28A1C5FAE1872283985F975E5DB029
|
||||
Bridge 45.76.29.92:8443 ECF1DD51A46FDEF2C50CED992EEEAE8DED18DA0C
|
||||
@@ -0,0 +1,156 @@
|
||||
package org.briarproject.bramble.keyagreement;
|
||||
|
||||
import org.briarproject.bramble.api.Bytes;
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.data.BdfReader;
|
||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||
import org.briarproject.bramble.api.keyagreement.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.BETA_PROTOCOL_VERSION;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class PayloadParserImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final BdfReaderFactory bdfReaderFactory =
|
||||
context.mock(BdfReaderFactory.class);
|
||||
private final BdfReader bdfReader = context.mock(BdfReader.class);
|
||||
|
||||
private final PayloadParserImpl payloadParser =
|
||||
new PayloadParserImpl(bdfReaderFactory);
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testThrowsFormatExceptionIfPayloadIsEmpty() throws Exception {
|
||||
payloadParser.parse(new byte[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowsUnsupportedVersionExceptionForOldVersion()
|
||||
throws Exception {
|
||||
try {
|
||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION - 1});
|
||||
fail();
|
||||
} catch (UnsupportedVersionException e) {
|
||||
assertTrue(e.isTooOld());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowsUnsupportedVersionExceptionForBetaVersion()
|
||||
throws Exception {
|
||||
try {
|
||||
payloadParser.parse(new byte[] {BETA_PROTOCOL_VERSION});
|
||||
fail();
|
||||
} catch (UnsupportedVersionException e) {
|
||||
assertTrue(e.isTooOld());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowsUnsupportedVersionExceptionForNewVersion()
|
||||
throws Exception {
|
||||
try {
|
||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION + 1});
|
||||
fail();
|
||||
} catch (UnsupportedVersionException e) {
|
||||
assertFalse(e.isTooOld());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testThrowsFormatExceptionForEmptyList() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(bdfReaderFactory).createReader(
|
||||
with(any(ByteArrayInputStream.class)));
|
||||
will(returnValue(bdfReader));
|
||||
oneOf(bdfReader).readList();
|
||||
will(returnValue(new BdfList()));
|
||||
}});
|
||||
|
||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testThrowsFormatExceptionForDataAfterList()
|
||||
throws Exception {
|
||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(bdfReaderFactory).createReader(
|
||||
with(any(ByteArrayInputStream.class)));
|
||||
will(returnValue(bdfReader));
|
||||
oneOf(bdfReader).readList();
|
||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
||||
oneOf(bdfReader).eof();
|
||||
will(returnValue(false));
|
||||
}});
|
||||
|
||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testThrowsFormatExceptionForShortCommitment()
|
||||
throws Exception {
|
||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH - 1);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(bdfReaderFactory).createReader(
|
||||
with(any(ByteArrayInputStream.class)));
|
||||
will(returnValue(bdfReader));
|
||||
oneOf(bdfReader).readList();
|
||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
||||
oneOf(bdfReader).eof();
|
||||
will(returnValue(true));
|
||||
}});
|
||||
|
||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testThrowsFormatExceptionForLongCommitment()
|
||||
throws Exception {
|
||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH + 1);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(bdfReaderFactory).createReader(
|
||||
with(any(ByteArrayInputStream.class)));
|
||||
will(returnValue(bdfReader));
|
||||
oneOf(bdfReader).readList();
|
||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
||||
oneOf(bdfReader).eof();
|
||||
will(returnValue(true));
|
||||
}});
|
||||
|
||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsPayloadWithNoDescriptors() throws Exception {
|
||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(bdfReaderFactory).createReader(
|
||||
with(any(ByteArrayInputStream.class)));
|
||||
will(returnValue(bdfReader));
|
||||
oneOf(bdfReader).readList();
|
||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
||||
oneOf(bdfReader).eof();
|
||||
will(returnValue(true));
|
||||
}});
|
||||
|
||||
Payload p = payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
||||
assertArrayEquals(commitment, p.getCommitment());
|
||||
assertTrue(p.getTransportDescriptors().isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,13 @@ import org.briarproject.bramble.api.system.ResourceProvider;
|
||||
import org.briarproject.bramble.test.BrambleJavaIntegrationTestComponent;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.briarproject.bramble.test.DaggerBrambleJavaIntegrationTestComponent;
|
||||
import org.junit.AfterClass;
|
||||
import org.briarproject.bramble.util.OsUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@@ -29,13 +33,20 @@ import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class BridgeTest extends BrambleTestCase {
|
||||
|
||||
private final static long TIMEOUT = SECONDS.toMillis(23);
|
||||
@Parameters
|
||||
public static Iterable<String> data() {
|
||||
BrambleJavaIntegrationTestComponent component =
|
||||
DaggerBrambleJavaIntegrationTestComponent.builder().build();
|
||||
return component.getCircumventionProvider().getBridges();
|
||||
}
|
||||
|
||||
private final static long TIMEOUT = SECONDS.toMillis(30);
|
||||
|
||||
private final static Logger LOG =
|
||||
Logger.getLogger(BridgeTest.class.getName());
|
||||
@@ -53,17 +64,23 @@ public class BridgeTest extends BrambleTestCase {
|
||||
@Inject
|
||||
Clock clock;
|
||||
|
||||
private List<String> bridges;
|
||||
private LinuxTorPluginFactory factory;
|
||||
private final static File torDir = getTestDirectory();
|
||||
private final File torDir = getTestDirectory();
|
||||
private final String bridge;
|
||||
|
||||
private volatile String currentBridge = null;
|
||||
private LinuxTorPluginFactory factory;
|
||||
|
||||
public BridgeTest(String bridge) {
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// Skip this test unless it's explicitly enabled in the environment
|
||||
assumeTrue(isOptionalTestEnabled(BridgeTest.class));
|
||||
|
||||
// TODO: Remove this assumption when the plugin supports other platforms
|
||||
assumeTrue(OsUtils.isLinux());
|
||||
|
||||
BrambleJavaIntegrationTestComponent component =
|
||||
DaggerBrambleJavaIntegrationTestComponent.builder().build();
|
||||
component.inject(this);
|
||||
@@ -72,7 +89,6 @@ public class BridgeTest extends BrambleTestCase {
|
||||
LocationUtils locationUtils = () -> "US";
|
||||
SocketFactory torSocketFactory = SocketFactory.getDefault();
|
||||
|
||||
bridges = circumventionProvider.getBridges();
|
||||
CircumventionProvider bridgeProvider = new CircumventionProvider() {
|
||||
@Override
|
||||
public boolean isTorProbablyBlocked(String countryCode) {
|
||||
@@ -86,7 +102,7 @@ public class BridgeTest extends BrambleTestCase {
|
||||
|
||||
@Override
|
||||
public List<String> getBridges() {
|
||||
return singletonList(currentBridge);
|
||||
return singletonList(bridge);
|
||||
}
|
||||
};
|
||||
factory = new LinuxTorPluginFactory(ioExecutor, networkManager,
|
||||
@@ -94,25 +110,18 @@ public class BridgeTest extends BrambleTestCase {
|
||||
resourceProvider, bridgeProvider, clock, torDir);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
@After
|
||||
public void tearDown() {
|
||||
deleteTestDirectory(torDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBridges() throws Exception {
|
||||
assertTrue(bridges.size() > 0);
|
||||
|
||||
for (String bridge : bridges) testBridge(bridge);
|
||||
}
|
||||
|
||||
private void testBridge(String bridge) throws Exception {
|
||||
DuplexPlugin duplexPlugin =
|
||||
factory.createPlugin(new TorPluginCallBack());
|
||||
assertNotNull(duplexPlugin);
|
||||
LinuxTorPlugin plugin = (LinuxTorPlugin) duplexPlugin;
|
||||
|
||||
currentBridge = bridge;
|
||||
LOG.warning("Testing " + bridge);
|
||||
try {
|
||||
plugin.start();
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.BrambleJavaModule;
|
||||
import org.briarproject.bramble.event.EventModule;
|
||||
import org.briarproject.bramble.plugin.PluginModule;
|
||||
import org.briarproject.bramble.plugin.tor.BridgeTest;
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
@@ -22,4 +23,5 @@ public interface BrambleJavaIntegrationTestComponent {
|
||||
|
||||
void inject(BridgeTest init);
|
||||
|
||||
CircumventionProvider getCircumventionProvider();
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 26
|
||||
versionCode 10101
|
||||
versionName "1.1.1"
|
||||
versionCode 10102
|
||||
versionName "1.1.2"
|
||||
applicationId "org.briarproject.briar.android"
|
||||
buildConfigField "String", "GitHash",
|
||||
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
|
||||
@@ -104,7 +104,7 @@ dependencies {
|
||||
}
|
||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||
implementation "com.android.support:support-annotations:$supportVersion"
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
|
||||
implementation('ch.acra:acra:4.9.1') {
|
||||
exclude module: 'support-v4'
|
||||
@@ -140,9 +140,6 @@ dependencies {
|
||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.0.2"
|
||||
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
|
||||
androidTestScreenshotImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
androidTestScreenshotImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||
androidTestScreenshotImplementation "tools.fastlane:screengrab:1.2.0"
|
||||
androidTestScreenshotImplementation "com.android.support.test.uiautomator:uiautomator-v18:2.1.3"
|
||||
}
|
||||
@@ -156,8 +153,9 @@ task verifyTranslations {
|
||||
lc.children().each { value -> translations.add(value.text()) }
|
||||
|
||||
def folders = ["default", "en-US"]
|
||||
def exceptions = ["values-night", "values-v21", "values-ldrtl"]
|
||||
project.file("src/main/res").eachDir { dir ->
|
||||
if (dir.name.startsWith("values-") && !dir.name.endsWith("night") && !dir.name.endsWith("v21")) {
|
||||
if (dir.name.startsWith("values-") && !exceptions.contains(dir.name)) {
|
||||
folders.add(dir.name.substring(7).replace("-r", "-"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,5 +28,3 @@
|
||||
|
||||
# Emoji
|
||||
-keep class com.vanniktech.emoji.**
|
||||
|
||||
-keepclasseswithmembers public class android.support.v7.widget.RecyclerView { *; }
|
||||
|
||||
@@ -13,4 +13,3 @@
|
||||
-dontwarn junit.**
|
||||
|
||||
-dontwarn org.briarproject.briar.android.**
|
||||
-dontwarn org.briarproject.bramble.**
|
||||
|
||||
@@ -8,7 +8,7 @@ public class BriarTestComponentApplication extends BriarApplicationImpl {
|
||||
@Override
|
||||
protected AndroidComponent createApplicationComponent() {
|
||||
AndroidComponent component = DaggerBriarUiTestComponent.builder()
|
||||
.testAppModule(new TestAppModule(this)).build();
|
||||
.appModule(new AppModule(this)).build();
|
||||
// We need to load the eager singletons directly after making the
|
||||
// dependency graphs
|
||||
BrambleCoreModule.initEagerSingletons(component);
|
||||
|
||||
@@ -21,8 +21,6 @@ public abstract class UiTest {
|
||||
getTargetContext().getString(R.string.screenshot_alice);
|
||||
protected static final String PASSWORD = "123456";
|
||||
|
||||
protected final BriarUiTestComponent alice;
|
||||
|
||||
@Inject
|
||||
protected AccountManager accountManager;
|
||||
@Inject
|
||||
@@ -32,8 +30,7 @@ public abstract class UiTest {
|
||||
BriarTestComponentApplication app =
|
||||
(BriarTestComponentApplication) getTargetContext()
|
||||
.getApplicationContext();
|
||||
alice = (BriarUiTestComponent) app.getApplicationComponent();
|
||||
inject(alice);
|
||||
inject((BriarUiTestComponent) app.getApplicationComponent());
|
||||
}
|
||||
|
||||
protected abstract void inject(BriarUiTestComponent component);
|
||||
|
||||
@@ -13,13 +13,13 @@ import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = {
|
||||
TestAppModule.class,
|
||||
AppModule.class,
|
||||
BriarCoreModule.class,
|
||||
BrambleAndroidModule.class,
|
||||
BriarAccountModule.class,
|
||||
BrambleCoreModule.class
|
||||
})
|
||||
public interface BriarUiTestComponent extends AndroidComponent, FakeDataTestComponent {
|
||||
public interface BriarUiTestComponent extends AndroidComponent {
|
||||
|
||||
void inject(SetupDataTest test);
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
||||
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||
import org.briarproject.bramble.client.ClientModule;
|
||||
import org.briarproject.bramble.contact.ContactModule;
|
||||
import org.briarproject.bramble.crypto.CryptoModule;
|
||||
import org.briarproject.bramble.data.DataModule;
|
||||
import org.briarproject.bramble.db.DatabaseModule;
|
||||
import org.briarproject.bramble.event.EventModule;
|
||||
import org.briarproject.bramble.identity.IdentityModule;
|
||||
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||
import org.briarproject.bramble.record.RecordModule;
|
||||
import org.briarproject.bramble.sync.SyncModule;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
import org.briarproject.bramble.test.TestCryptoExecutorModule;
|
||||
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||
import org.briarproject.bramble.test.TestSecureRandomModule;
|
||||
import org.briarproject.bramble.transport.TransportModule;
|
||||
import org.briarproject.bramble.versioning.VersioningModule;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.client.BriarClientModule;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = {
|
||||
TestCryptoExecutorModule.class,
|
||||
TestDatabaseModule.class,
|
||||
TestPluginConfigModule.class,
|
||||
TestSecureRandomModule.class,
|
||||
BriarClientModule.class,
|
||||
ClientModule.class,
|
||||
ContactModule.class,
|
||||
CryptoModule.class,
|
||||
DataModule.class,
|
||||
DatabaseModule.class,
|
||||
EventModule.class,
|
||||
IdentityModule.class,
|
||||
LifecycleModule.class,
|
||||
MessagingModule.class,
|
||||
RecordModule.class,
|
||||
SyncModule.class,
|
||||
SystemModule.class,
|
||||
TransportModule.class,
|
||||
VersioningModule.class
|
||||
})
|
||||
interface FakeDataTestComponent {
|
||||
|
||||
void inject(ContactModule.EagerSingletons init);
|
||||
|
||||
void inject(IdentityModule.EagerSingletons init);
|
||||
|
||||
void inject(LifecycleModule.EagerSingletons init);
|
||||
|
||||
void inject(MessagingModule.EagerSingletons init);
|
||||
|
||||
void inject(SyncModule.EagerSingletons init);
|
||||
|
||||
void inject(SystemModule.EagerSingletons init);
|
||||
|
||||
void inject(TransportModule.EagerSingletons init);
|
||||
|
||||
void inject(VersioningModule.EagerSingletons init);
|
||||
|
||||
LifecycleManager getLifecycleManager();
|
||||
|
||||
IdentityManager getIdentityManager();
|
||||
|
||||
ContactManager getContactManager();
|
||||
|
||||
MessagingManager getMessagingManager();
|
||||
|
||||
KeyManager getKeyManager();
|
||||
|
||||
PrivateMessageFactory getPrivateMessageFactory();
|
||||
|
||||
EventBus getEventBus();
|
||||
|
||||
StreamWriterFactory getStreamWriterFactory();
|
||||
|
||||
StreamReaderFactory getStreamReaderFactory();
|
||||
|
||||
SyncSessionFactory getSyncSessionFactory();
|
||||
}
|
||||
@@ -5,59 +5,23 @@ import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.test.uiautomator.UiDevice;
|
||||
import android.support.test.uiautomator.UiObject;
|
||||
import android.support.test.uiautomator.UiSelector;
|
||||
import android.util.Log;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.SyncSession;
|
||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
import org.briarproject.bramble.api.transport.StreamContext;
|
||||
import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
||||
import org.briarproject.bramble.api.transport.StreamWriter;
|
||||
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||
import org.briarproject.bramble.contact.ContactModule;
|
||||
import org.briarproject.bramble.identity.IdentityModule;
|
||||
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||
import org.briarproject.bramble.sync.SyncModule;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||
import org.briarproject.bramble.test.TestUtils;
|
||||
import org.briarproject.bramble.transport.TransportModule;
|
||||
import org.briarproject.bramble.versioning.VersioningModule;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.action.ViewActions.typeText;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
|
||||
import static android.support.test.espresso.intent.Intents.intended;
|
||||
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
@@ -66,17 +30,9 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static android.support.test.runner.lifecycle.Stage.PAUSED;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.briar.android.TestPluginConfigModule.MAX_LATENCY;
|
||||
import static org.briarproject.briar.android.TestPluginConfigModule.TRANSPORT_ID;
|
||||
import static org.briarproject.briar.android.ViewActions.waitForActivity;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -92,49 +48,11 @@ public class SetupDataTest extends ScreenshotTest {
|
||||
}
|
||||
};
|
||||
|
||||
private FakeDataTestComponent bob;
|
||||
private final File testDir =
|
||||
getTargetContext().getDir("test", MODE_PRIVATE);
|
||||
private final File bobDir = new File(testDir, "bob");
|
||||
private final SecretKey master = getSecretKey();
|
||||
|
||||
@Override
|
||||
protected void inject(BriarUiTestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Log.e("TEST", testDir.getAbsolutePath());
|
||||
Log.e("TEST", "exists: " + testDir.exists());
|
||||
assertTrue(testDir.mkdirs());
|
||||
bob = DaggerFakeDataTestComponent.builder()
|
||||
.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
|
||||
injectEagerSingletons(bob);
|
||||
Log.e("TEST", "built bob");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
// Stop the lifecycle manager
|
||||
LifecycleManager lifecycleManager = bob.getLifecycleManager();
|
||||
lifecycleManager.stopServices();
|
||||
lifecycleManager.waitForShutdown();
|
||||
|
||||
TestUtils.deleteTestDirectory(testDir);
|
||||
}
|
||||
|
||||
private static void injectEagerSingletons(FakeDataTestComponent component) {
|
||||
component.inject(new ContactModule.EagerSingletons());
|
||||
component.inject(new IdentityModule.EagerSingletons());
|
||||
component.inject(new LifecycleModule.EagerSingletons());
|
||||
component.inject(new MessagingModule.EagerSingletons());
|
||||
component.inject(new SyncModule.EagerSingletons());
|
||||
component.inject(new SystemModule.EagerSingletons());
|
||||
component.inject(new TransportModule.EagerSingletons());
|
||||
component.inject(new VersioningModule.EagerSingletons());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAccount() throws Exception {
|
||||
// Enter username
|
||||
@@ -185,132 +103,26 @@ public class SetupDataTest extends ScreenshotTest {
|
||||
|
||||
assertTrue(accountManager.hasDatabaseKey());
|
||||
|
||||
// WIP below
|
||||
|
||||
// wait for OpenDatabaseActivity to go away
|
||||
onView(isRoot())
|
||||
.perform(waitUntilMatches(
|
||||
allOf(withId(R.id.progressBar), not(isDisplayed()))));
|
||||
lifecycleManager.waitForStartup();
|
||||
intended(hasComponent(NavDrawerActivity.class.getName()));
|
||||
createTestData();
|
||||
|
||||
// close expiry warning
|
||||
onView(withId(R.id.expiryWarning))
|
||||
.perform(waitUntilMatches(isDisplayed()));
|
||||
onView(withId(R.id.expiryWarningClose))
|
||||
.check(matches(isDisplayed()));
|
||||
onView(withId(R.id.expiryWarningClose))
|
||||
.perform(click());
|
||||
|
||||
LocalAuthor aliceAuthor = alice.identityManager().getLocalAuthor();
|
||||
|
||||
LocalAuthor bobAuthor = bob.getIdentityManager().createLocalAuthor(
|
||||
getTargetContext().getString(R.string.screenshot_bob));
|
||||
bob.getIdentityManager().registerLocalAuthor(bobAuthor);
|
||||
// Start the lifecycle manager
|
||||
bob.getLifecycleManager().startServices(getSecretKey());
|
||||
bob.getLifecycleManager().waitForStartup();
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
// Bob adds Alice as a contact
|
||||
ContactId aliceContactId = bob.getContactManager()
|
||||
.addContact(aliceAuthor, bobAuthor.getId(), master,
|
||||
timestamp, true, true, true);
|
||||
// Alice adds Bob as a contact
|
||||
ContactId bobContactId = alice.contactManager()
|
||||
.addContact(bobAuthor, aliceAuthor.getId(), master,
|
||||
timestamp, false, true, true);
|
||||
|
||||
// TODO figure out how many messages
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
|
||||
sendMessage(bob, aliceContactId);
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
|
||||
onView(isRoot())
|
||||
.perform(waitUntilMatches(withText(bobAuthor.getName())));
|
||||
onView(withId(R.id.recyclerView))
|
||||
.perform(actionOnItemAtPosition(0, click()));
|
||||
onView(isRoot())
|
||||
.perform(waitUntilMatches(withText(R.string.screenshot_message_2)));
|
||||
|
||||
assertEquals(1,
|
||||
alice.conversationManager().getGroupCount(bobContactId).getMsgCount());
|
||||
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
|
||||
private void sendMessage(FakeDataTestComponent device, ContactId contactId)
|
||||
throws Exception {
|
||||
// Send Bob a message
|
||||
MessagingManager messagingManager = device.getMessagingManager();
|
||||
GroupId groupId = messagingManager.getConversationId(contactId);
|
||||
PrivateMessageFactory privateMessageFactory =
|
||||
device.getPrivateMessageFactory();
|
||||
PrivateMessage message = privateMessageFactory.createPrivateMessage(
|
||||
groupId, getMinutesAgo(3),
|
||||
getTargetContext().getString(R.string.screenshot_message_2));
|
||||
messagingManager.addLocalMessage(message);
|
||||
private void createTestData() {
|
||||
try {
|
||||
createTestDataExceptions();
|
||||
} catch (DbException | FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void read(FakeDataTestComponent device,
|
||||
ContactId contactId, byte[] stream) throws Exception {
|
||||
// Read and recognise the tag
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(stream);
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
int read = in.read(tag);
|
||||
assertEquals(tag.length, read);
|
||||
KeyManager keyManager = device.getKeyManager();
|
||||
StreamContext ctx = keyManager.getStreamContext(TRANSPORT_ID, tag);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream reader
|
||||
StreamReaderFactory streamReaderFactory =
|
||||
device.getStreamReaderFactory();
|
||||
InputStream streamReader = streamReaderFactory.createStreamReader(
|
||||
in, ctx);
|
||||
// Create an incoming sync session
|
||||
SyncSessionFactory syncSessionFactory = device.getSyncSessionFactory();
|
||||
SyncSession session = syncSessionFactory.createIncomingSession(
|
||||
contactId, streamReader);
|
||||
// Read whatever needs to be read
|
||||
session.run();
|
||||
streamReader.close();
|
||||
}
|
||||
|
||||
private byte[] write(FakeDataTestComponent device,
|
||||
ContactId contactId) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
// Get a stream context
|
||||
KeyManager keyManager = device.getKeyManager();
|
||||
StreamContext ctx = keyManager.getStreamContext(contactId,
|
||||
TRANSPORT_ID);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream writer
|
||||
StreamWriterFactory streamWriterFactory =
|
||||
device.getStreamWriterFactory();
|
||||
StreamWriter streamWriter =
|
||||
streamWriterFactory.createStreamWriter(out, ctx);
|
||||
// Create an outgoing sync session
|
||||
SyncSessionFactory syncSessionFactory = device.getSyncSessionFactory();
|
||||
SyncSession session = syncSessionFactory.createSimplexOutgoingSession(
|
||||
contactId, MAX_LATENCY, streamWriter);
|
||||
// Write whatever needs to be written
|
||||
session.run();
|
||||
streamWriter.sendEndOfStream();
|
||||
// Return the contents of the stream
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void createTestDataExceptions()
|
||||
throws DbException, FormatException {
|
||||
String bobName =
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.StrictMode;
|
||||
|
||||
import com.vanniktech.emoji.RecentEmoji;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.reporting.DevConfig;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||
|
||||
@Module(includes = TestPluginConfigModule.class)
|
||||
public class TestAppModule {
|
||||
|
||||
static class EagerSingletons {
|
||||
@Inject
|
||||
AndroidNotificationManager androidNotificationManager;
|
||||
@Inject
|
||||
NetworkUsageLogger networkUsageLogger;
|
||||
@Inject
|
||||
DozeWatchdog dozeWatchdog;
|
||||
@Inject
|
||||
RecentEmoji recentEmoji;
|
||||
}
|
||||
|
||||
private final Application application;
|
||||
|
||||
public TestAppModule(Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Application providesApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DatabaseConfig provideDatabaseConfig(Application app) {
|
||||
//FIXME: StrictMode
|
||||
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskReads();
|
||||
StrictMode.allowThreadDiskWrites();
|
||||
File dbDir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
|
||||
File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE);
|
||||
StrictMode.setThreadPolicy(tp);
|
||||
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
||||
@NotNullByDefault
|
||||
DevConfig devConfig = new DevConfig() {
|
||||
|
||||
@Override
|
||||
public PublicKey getDevPublicKey() {
|
||||
try {
|
||||
return crypto.getMessageKeyParser().parsePublicKey(
|
||||
StringUtils.fromHexString(DEV_PUBLIC_KEY_HEX));
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDevOnionAddress() {
|
||||
return DEV_ONION_ADDRESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getReportDir() {
|
||||
return AndroidUtils.getReportDir(app.getApplicationContext());
|
||||
}
|
||||
};
|
||||
return devConfig;
|
||||
}
|
||||
|
||||
@Provides
|
||||
SharedPreferences provideSharedPreferences(Application app) {
|
||||
// FIXME unify this with getDefaultSharedPreferences()
|
||||
return app.getSharedPreferences("db", MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
AndroidNotificationManager provideAndroidNotificationManager(
|
||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||
AndroidNotificationManagerImpl notificationManager) {
|
||||
lifecycleManager.registerService(notificationManager);
|
||||
eventBus.addListener(notificationManager);
|
||||
return notificationManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ScreenFilterMonitor provideScreenFilterMonitor(
|
||||
LifecycleManager lifecycleManager,
|
||||
ScreenFilterMonitorImpl screenFilterMonitor) {
|
||||
lifecycleManager.registerService(screenFilterMonitor);
|
||||
return screenFilterMonitor;
|
||||
}
|
||||
|
||||
@Provides
|
||||
NetworkUsageLogger provideNetworkUsageLogger(
|
||||
LifecycleManager lifecycleManager) {
|
||||
NetworkUsageLogger networkUsageLogger = new NetworkUsageLogger();
|
||||
lifecycleManager.registerService(networkUsageLogger);
|
||||
return networkUsageLogger;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DozeWatchdog provideDozeWatchdog(LifecycleManager lifecycleManager) {
|
||||
DozeWatchdogImpl dozeWatchdog = new DozeWatchdogImpl(application);
|
||||
lifecycleManager.registerService(dozeWatchdog);
|
||||
return dozeWatchdog;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
LockManager provideLockManager(LifecycleManager lifecycleManager,
|
||||
EventBus eventBus, LockManagerImpl lockManager) {
|
||||
lifecycleManager.registerService(lockManager);
|
||||
eventBus.addListener(lockManager);
|
||||
return lockManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager,
|
||||
RecentEmojiImpl recentEmoji) {
|
||||
lifecycleManager.registerClient(recentEmoji);
|
||||
return recentEmoji;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||
|
||||
@Module
|
||||
public class TestPluginConfigModule {
|
||||
|
||||
public static final TransportId TRANSPORT_ID = getTransportId();
|
||||
public static final int MAX_LATENCY = 2 * 60 * 1000; // 2 minutes
|
||||
|
||||
@NotNullByDefault
|
||||
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
|
||||
|
||||
@Override
|
||||
public TransportId getId() {
|
||||
return TRANSPORT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLatency() {
|
||||
return MAX_LATENCY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@Provides
|
||||
PluginConfig providePluginConfig() {
|
||||
@NotNullByDefault
|
||||
PluginConfig pluginConfig = new PluginConfig() {
|
||||
|
||||
@Override
|
||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||
return singletonList(simplex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,9 +13,10 @@
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||
<uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" />
|
||||
|
||||
@@ -25,6 +26,7 @@
|
||||
android:icon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/app_name"
|
||||
android:logo="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/BriarTheme">
|
||||
|
||||
<receiver
|
||||
|
||||
@@ -41,13 +41,9 @@ import org.briarproject.briar.android.util.BriarNotificationBuilder;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
|
||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
|
||||
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
|
||||
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -235,19 +231,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
} else if (e instanceof BlogPostAddedEvent) {
|
||||
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
||||
showBlogPostNotification(b.getGroupId());
|
||||
} else if (e instanceof IntroductionRequestReceivedEvent) {
|
||||
ContactId c = ((IntroductionRequestReceivedEvent) e).getContactId();
|
||||
showContactNotification(c);
|
||||
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||
ContactId c =
|
||||
((IntroductionResponseReceivedEvent) e).getContactId();
|
||||
showContactNotification(c);
|
||||
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||
ContactId c = ((InvitationRequestReceivedEvent) e).getContactId();
|
||||
showContactNotification(c);
|
||||
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||
ContactId c = ((InvitationResponseReceivedEvent) e).getContactId();
|
||||
showContactNotification(c);
|
||||
} else if (e instanceof IntroductionSucceededEvent) {
|
||||
showIntroductionNotification();
|
||||
}
|
||||
@@ -327,9 +310,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
R.plurals.private_message_notification_text, contactTotal,
|
||||
contactTotal));
|
||||
b.setNumber(contactTotal);
|
||||
boolean showOnLockScreen =
|
||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
|
||||
b.setNotificationCategory(CATEGORY_MESSAGE);
|
||||
if (mayAlertAgain) setAlertProperties(b);
|
||||
setDeleteIntent(b, CONTACT_URI);
|
||||
Set<ContactId> contacts = contactCounts.keySet();
|
||||
@@ -431,9 +412,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
R.plurals.group_message_notification_text, groupTotal,
|
||||
groupTotal));
|
||||
b.setNumber(groupTotal);
|
||||
boolean showOnLockScreen =
|
||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||
b.setNotificationCategory(CATEGORY_SOCIAL);
|
||||
if (mayAlertAgain) setAlertProperties(b);
|
||||
setDeleteIntent(b, GROUP_URI);
|
||||
Set<GroupId> groups = groupCounts.keySet();
|
||||
@@ -504,9 +483,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
R.plurals.forum_post_notification_text, forumTotal,
|
||||
forumTotal));
|
||||
b.setNumber(forumTotal);
|
||||
boolean showOnLockScreen =
|
||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||
b.setNotificationCategory(CATEGORY_SOCIAL);
|
||||
if (mayAlertAgain) setAlertProperties(b);
|
||||
setDeleteIntent(b, FORUM_URI);
|
||||
Set<GroupId> forums = forumCounts.keySet();
|
||||
@@ -575,9 +552,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
R.plurals.blog_post_notification_text, blogTotal,
|
||||
blogTotal));
|
||||
b.setNumber(blogTotal);
|
||||
boolean showOnLockScreen =
|
||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||
b.setNotificationCategory(CATEGORY_SOCIAL);
|
||||
if (mayAlertAgain) setAlertProperties(b);
|
||||
setDeleteIntent(b, BLOG_URI);
|
||||
// Touching the notification shows the combined blog feed
|
||||
@@ -618,9 +593,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
b.setContentText(appContext.getResources().getQuantityString(
|
||||
R.plurals.introduction_notification_text, introductionTotal,
|
||||
introductionTotal));
|
||||
boolean showOnLockScreen =
|
||||
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
|
||||
b.setNotificationCategory(CATEGORY_MESSAGE);
|
||||
setAlertProperties(b);
|
||||
setDeleteIntent(b, INTRODUCTION_URI);
|
||||
// Touching the notification shows the contact list
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.StrictMode;
|
||||
|
||||
@@ -10,9 +11,24 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.bramble.api.reporting.DevConfig;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.system.LocationUtils;
|
||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||
import org.briarproject.bramble.api.system.Scheduler;
|
||||
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||
@@ -23,18 +39,25 @@ import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||
|
||||
@Module(includes = PluginConfigModule.class)
|
||||
@Module
|
||||
public class AppModule {
|
||||
|
||||
static class EagerSingletons {
|
||||
@@ -72,6 +95,47 @@ public class AppModule {
|
||||
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||
}
|
||||
|
||||
@Provides
|
||||
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||
@Scheduler ScheduledExecutorService scheduler,
|
||||
AndroidExecutor androidExecutor, SecureRandom random,
|
||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
||||
Application app, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, EventBus eventBus,
|
||||
ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
Context appContext = app.getApplicationContext();
|
||||
DuplexPluginFactory bluetooth =
|
||||
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
||||
appContext, random, eventBus, backoffFactory);
|
||||
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
||||
scheduler, appContext, networkManager, locationUtils, eventBus,
|
||||
torSocketFactory, backoffFactory, resourceProvider,
|
||||
circumventionProvider, clock);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
eventBus, backoffFactory, appContext);
|
||||
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
||||
@NotNullByDefault
|
||||
PluginConfig pluginConfig = new PluginConfig() {
|
||||
|
||||
@Override
|
||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||
return duplex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.system.LocationUtils;
|
||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||
import org.briarproject.bramble.api.system.Scheduler;
|
||||
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
@Module
|
||||
public class PluginConfigModule {
|
||||
|
||||
@Provides
|
||||
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||
@Scheduler ScheduledExecutorService scheduler,
|
||||
AndroidExecutor androidExecutor, SecureRandom random,
|
||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
||||
Application app, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, EventBus eventBus,
|
||||
ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
Context appContext = app.getApplicationContext();
|
||||
DuplexPluginFactory bluetooth =
|
||||
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
||||
appContext, random, eventBus, backoffFactory);
|
||||
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
||||
scheduler, appContext, networkManager, locationUtils, eventBus,
|
||||
torSocketFactory, backoffFactory, resourceProvider,
|
||||
circumventionProvider, clock);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
eventBus, backoffFactory, appContext);
|
||||
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
||||
@NotNullByDefault
|
||||
PluginConfig pluginConfig = new PluginConfig() {
|
||||
|
||||
@Override
|
||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||
return duplex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,6 +101,8 @@ public class LockManagerImpl implements LockManager, Service, EventListener {
|
||||
|
||||
@Override
|
||||
public void stopService() {
|
||||
timeoutMinutes = timeoutNever;
|
||||
if (alarmSet) alarmManager.cancel(lockIntent);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -21,11 +21,11 @@ import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.blog.Blog;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
||||
import org.briarproject.briar.api.blog.BlogManager;
|
||||
import org.briarproject.briar.api.blog.BlogSharingManager;
|
||||
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
|
||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -107,7 +107,7 @@ class BlogControllerImpl extends BaseControllerImpl
|
||||
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
|
||||
BlogInvitationResponseReceivedEvent b =
|
||||
(BlogInvitationResponseReceivedEvent) e;
|
||||
InvitationResponse r = b.getResponse();
|
||||
BlogInvitationResponse r = b.getMessageHeader();
|
||||
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
||||
LOG.info("Blog invitation accepted");
|
||||
onBlogInvitationAccepted(b.getContactId());
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
@@ -36,19 +35,10 @@ import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
|
||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.client.BaseMessageHeader;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
|
||||
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -57,6 +47,7 @@ import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
|
||||
import static android.support.v4.view.ViewCompat.getTransitionName;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
@@ -122,7 +113,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
ContactId contactId = item.getContact().getId();
|
||||
i.putExtra(CONTACT_ID, contactId.getInt());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (SDK_INT >= 23) {
|
||||
ContactListItemViewHolder holder =
|
||||
(ContactListItemViewHolder) list
|
||||
.getRecyclerView()
|
||||
@@ -256,41 +247,16 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
||||
PrivateMessageHeader h = p.getMessageHeader();
|
||||
updateItem(p.getContactId(), h);
|
||||
} else if (e instanceof IntroductionRequestReceivedEvent) {
|
||||
LOG.info("Introduction request received, updating item");
|
||||
IntroductionRequestReceivedEvent m =
|
||||
(IntroductionRequestReceivedEvent) e;
|
||||
IntroductionRequest ir = m.getIntroductionRequest();
|
||||
updateItem(m.getContactId(), ir);
|
||||
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||
LOG.info("Introduction response received, updating item");
|
||||
IntroductionResponseReceivedEvent m =
|
||||
(IntroductionResponseReceivedEvent) e;
|
||||
IntroductionResponse ir = m.getIntroductionResponse();
|
||||
updateItem(m.getContactId(), ir);
|
||||
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||
LOG.info("Invitation Request received, update item");
|
||||
InvitationRequestReceivedEvent m =
|
||||
(InvitationRequestReceivedEvent) e;
|
||||
InvitationRequest ir = m.getRequest();
|
||||
updateItem(m.getContactId(), ir);
|
||||
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||
LOG.info("Invitation response received, updating item");
|
||||
InvitationResponseReceivedEvent m =
|
||||
(InvitationResponseReceivedEvent) e;
|
||||
InvitationResponse ir = m.getResponse();
|
||||
updateItem(m.getContactId(), ir);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateItem(ContactId c, BaseMessageHeader h) {
|
||||
private void updateItem(ContactId c, PrivateMessageHeader h) {
|
||||
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);
|
||||
item.addMessage(h);
|
||||
adapter.updateItemAt(position, item);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.contact;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@@ -22,11 +23,10 @@ public class ContactListItem extends ContactItem {
|
||||
this.timestamp = count.getLatestMsgTime();
|
||||
}
|
||||
|
||||
void addMessage(ConversationItem message) {
|
||||
void addMessage(PrivateMessageHeader h) {
|
||||
empty = false;
|
||||
if (message.getTime() > timestamp) timestamp = message.getTime();
|
||||
if (!message.isRead())
|
||||
unread++;
|
||||
if (h.getTimestamp() > timestamp) timestamp = h.getTimestamp();
|
||||
if (!h.isRead()) unread++;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.arch.lifecycle.MutableLiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
@@ -50,6 +53,7 @@ import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.blog.BlogActivity;
|
||||
import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
|
||||
import org.briarproject.briar.android.contact.ConversationVisitor.BodyCache;
|
||||
import org.briarproject.briar.android.forum.ForumActivity;
|
||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||
@@ -62,24 +66,15 @@ import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.forum.ForumSharingManager;
|
||||
import org.briarproject.briar.api.introduction.IntroductionManager;
|
||||
import org.briarproject.briar.api.introduction.IntroductionMessage;
|
||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.messaging.PrivateRequest;
|
||||
import org.briarproject.briar.api.messaging.PrivateResponse;
|
||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
|
||||
import org.briarproject.briar.api.sharing.InvitationMessage;
|
||||
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
|
||||
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||
import org.thoughtcrime.securesms.components.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.components.util.ListenableFutureTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -87,13 +82,10 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
@@ -120,7 +112,8 @@ import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.S
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class ConversationActivity extends BriarActivity
|
||||
implements EventListener, ConversationListener, TextInputListener {
|
||||
implements EventListener, ConversationListener, TextInputListener,
|
||||
BodyCache {
|
||||
|
||||
public static final String CONTACT_ID = "briar.CONTACT_ID";
|
||||
|
||||
@@ -138,7 +131,9 @@ public class ConversationActivity extends BriarActivity
|
||||
Executor cryptoExecutor;
|
||||
|
||||
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
||||
private final MutableLiveData<String> contactName = new MutableLiveData<>();
|
||||
|
||||
private ConversationVisitor visitor;
|
||||
private ConversationAdapter adapter;
|
||||
private Toolbar toolbar;
|
||||
private CircleImageView toolbarAvatar;
|
||||
@@ -147,24 +142,14 @@ public class ConversationActivity extends BriarActivity
|
||||
private BriarRecyclerView list;
|
||||
private TextInputView textInputView;
|
||||
|
||||
private final ListenableFutureTask<String> contactNameTask =
|
||||
new ListenableFutureTask<>(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
Contact c = contactManager.getContact(contactId);
|
||||
contactName = c.getAuthor().getName();
|
||||
return c.getAuthor().getName();
|
||||
}
|
||||
});
|
||||
private final AtomicBoolean contactNameTaskStarted =
|
||||
new AtomicBoolean(false);
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
volatile ContactManager contactManager;
|
||||
@Inject
|
||||
volatile MessagingManager messagingManager;
|
||||
@Inject
|
||||
volatile ConversationManager conversationManager;
|
||||
@Inject
|
||||
volatile EventBus eventBus;
|
||||
@Inject
|
||||
volatile SettingsManager settingsManager;
|
||||
@@ -181,8 +166,6 @@ public class ConversationActivity extends BriarActivity
|
||||
|
||||
private volatile ContactId contactId;
|
||||
@Nullable
|
||||
private volatile String contactName;
|
||||
@Nullable
|
||||
private volatile AuthorId contactAuthorId;
|
||||
@Nullable
|
||||
private volatile GroupId messagingGroupId;
|
||||
@@ -211,6 +194,7 @@ public class ConversationActivity extends BriarActivity
|
||||
setTransitionName(toolbarAvatar, getAvatarTransitionName(contactId));
|
||||
setTransitionName(toolbarStatus, getBulbTransitionName(contactId));
|
||||
|
||||
visitor = new ConversationVisitor(this, this, contactName);
|
||||
adapter = new ConversationAdapter(this, this);
|
||||
list = findViewById(R.id.conversationView);
|
||||
list.setLayoutManager(new LinearLayoutManager(this));
|
||||
@@ -294,9 +278,9 @@ public class ConversationActivity extends BriarActivity
|
||||
runOnDbThread(() -> {
|
||||
try {
|
||||
long start = now();
|
||||
if (contactName == null || contactAuthorId == null) {
|
||||
if (contactAuthorId == null) {
|
||||
Contact contact = contactManager.getContact(contactId);
|
||||
contactName = contact.getAuthor().getName();
|
||||
contactName.postValue(contact.getAuthor().getName());
|
||||
contactAuthorId = contact.getAuthor().getId();
|
||||
}
|
||||
logDuration(LOG, "Loading contact", start);
|
||||
@@ -310,12 +294,13 @@ public class ConversationActivity extends BriarActivity
|
||||
});
|
||||
}
|
||||
|
||||
// contactAuthorId and contactName are expected to be set
|
||||
private void displayContactDetails() {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
//noinspection ConstantConditions
|
||||
toolbarAvatar.setImageDrawable(
|
||||
new IdenticonDrawable(contactAuthorId.getBytes()));
|
||||
toolbarTitle.setText(contactName);
|
||||
toolbarTitle.setText(contactName.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -343,23 +328,9 @@ public class ConversationActivity extends BriarActivity
|
||||
try {
|
||||
long start = now();
|
||||
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);
|
||||
conversationManager.getMessageHeaders(contactId);
|
||||
logDuration(LOG, "Loading messages", start);
|
||||
displayMessages(revision, headers, introductions, invitations);
|
||||
displayMessages(revision, headers);
|
||||
} catch (NoSuchContactException e) {
|
||||
finishOnUiThread();
|
||||
} catch (DbException e) {
|
||||
@@ -369,15 +340,12 @@ public class ConversationActivity extends BriarActivity
|
||||
}
|
||||
|
||||
private void displayMessages(int revision,
|
||||
Collection<PrivateMessageHeader> headers,
|
||||
Collection<IntroductionMessage> introductions,
|
||||
Collection<InvitationMessage> invitations) {
|
||||
Collection<PrivateMessageHeader> headers) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (revision == adapter.getRevision()) {
|
||||
adapter.incrementRevision();
|
||||
textInputView.setSendButtonEnabled(true);
|
||||
List<ConversationItem> items = createItems(headers,
|
||||
introductions, invitations);
|
||||
List<ConversationItem> items = createItems(headers);
|
||||
adapter.addAll(items);
|
||||
list.showData();
|
||||
// Scroll to the bottom
|
||||
@@ -396,41 +364,9 @@ public class ConversationActivity extends BriarActivity
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private List<ConversationItem> createItems(
|
||||
Collection<PrivateMessageHeader> headers,
|
||||
Collection<IntroductionMessage> introductions,
|
||||
Collection<InvitationMessage> invitations) {
|
||||
int size =
|
||||
headers.size() + introductions.size() + invitations.size();
|
||||
List<ConversationItem> items = new ArrayList<>(size);
|
||||
for (PrivateMessageHeader h : headers) {
|
||||
ConversationItem item = ConversationItem.from(h);
|
||||
String body = bodyCache.get(h.getId());
|
||||
if (body == null) loadMessageBody(h.getId());
|
||||
else item.setBody(body);
|
||||
items.add(item);
|
||||
}
|
||||
for (IntroductionMessage m : introductions) {
|
||||
ConversationItem item;
|
||||
if (m instanceof IntroductionRequest) {
|
||||
IntroductionRequest i = (IntroductionRequest) m;
|
||||
item = ConversationItem.from(this, contactName, i);
|
||||
} else {
|
||||
IntroductionResponse i = (IntroductionResponse) m;
|
||||
item = ConversationItem.from(this, contactName, i);
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
for (InvitationMessage i : invitations) {
|
||||
ConversationItem item;
|
||||
if (i instanceof InvitationRequest) {
|
||||
InvitationRequest r = (InvitationRequest) i;
|
||||
item = ConversationItem.from(this, contactName, r);
|
||||
} else {
|
||||
InvitationResponse r = (InvitationResponse) i;
|
||||
item = ConversationItem.from(this, contactName, r);
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
Collection<PrivateMessageHeader> headers) {
|
||||
List<ConversationItem> items = new ArrayList<>(headers.size());
|
||||
for (PrivateMessageHeader h : headers) items.add(h.accept(visitor));
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -476,9 +412,7 @@ public class ConversationActivity extends BriarActivity
|
||||
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
||||
if (p.getContactId().equals(contactId)) {
|
||||
LOG.info("Message received, adding");
|
||||
PrivateMessageHeader h = p.getMessageHeader();
|
||||
addConversationItem(ConversationItem.from(h));
|
||||
loadMessageBody(h.getId());
|
||||
onNewPrivateMessage(p.getMessageHeader());
|
||||
}
|
||||
} else if (e instanceof MessagesSentEvent) {
|
||||
MessagesSentEvent m = (MessagesSentEvent) e;
|
||||
@@ -504,38 +438,6 @@ public class ConversationActivity extends BriarActivity
|
||||
LOG.info("Contact disconnected");
|
||||
displayContactOnlineStatus();
|
||||
}
|
||||
} else if (e instanceof IntroductionRequestReceivedEvent) {
|
||||
IntroductionRequestReceivedEvent event =
|
||||
(IntroductionRequestReceivedEvent) e;
|
||||
if (event.getContactId().equals(contactId)) {
|
||||
LOG.info("Introduction request received, adding...");
|
||||
IntroductionRequest ir = event.getIntroductionRequest();
|
||||
handleIntroductionRequest(ir);
|
||||
}
|
||||
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||
IntroductionResponseReceivedEvent event =
|
||||
(IntroductionResponseReceivedEvent) e;
|
||||
if (event.getContactId().equals(contactId)) {
|
||||
LOG.info("Introduction response received, adding...");
|
||||
IntroductionResponse ir = event.getIntroductionResponse();
|
||||
handleIntroductionResponse(ir);
|
||||
}
|
||||
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||
InvitationRequestReceivedEvent event =
|
||||
(InvitationRequestReceivedEvent) e;
|
||||
if (event.getContactId().equals(contactId)) {
|
||||
LOG.info("Invitation received, adding...");
|
||||
InvitationRequest ir = event.getRequest();
|
||||
handleInvitationRequest(ir);
|
||||
}
|
||||
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||
InvitationResponseReceivedEvent event =
|
||||
(InvitationResponseReceivedEvent) e;
|
||||
if (event.getContactId().equals(contactId)) {
|
||||
LOG.info("Invitation response received, adding...");
|
||||
InvitationResponse ir = event.getResponse();
|
||||
handleInvitationResponse(ir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,84 +450,33 @@ public class ConversationActivity extends BriarActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIntroductionRequest(IntroductionRequest m) {
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
private void onNewPrivateMessage(PrivateMessageHeader h) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
if (h instanceof PrivateRequest || h instanceof PrivateResponse) {
|
||||
String cName = contactName.getValue();
|
||||
if (cName == null) {
|
||||
// Wait for the contact name to be loaded
|
||||
contactName.observe(this, new Observer<String>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable String cName) {
|
||||
if (cName != null) {
|
||||
addConversationItem(h.accept(visitor));
|
||||
contactName.removeObserver(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addConversationItem(h.accept(visitor));
|
||||
}
|
||||
} else {
|
||||
addConversationItem(h.accept(visitor));
|
||||
loadMessageBody(h.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIntroductionResponse(IntroductionResponse m) {
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleInvitationRequest(InvitationRequest m) {
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleInvitationResponse(InvitationResponse m) {
|
||||
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||
@Override
|
||||
public void onSuccess(String contactName) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
ConversationItem item = ConversationItem
|
||||
.from(ConversationActivity.this, contactName, m);
|
||||
addConversationItem(item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable exception) {
|
||||
runOnUiThreadUnlessDestroyed(
|
||||
() -> handleDbException((DbException) exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void markMessages(Collection<MessageId> messageIds,
|
||||
boolean sent, boolean seen) {
|
||||
private void markMessages(Collection<MessageId> messageIds, boolean sent,
|
||||
boolean seen) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
Set<MessageId> messages = new HashSet<>(messageIds);
|
||||
@@ -678,7 +529,8 @@ public class ConversationActivity extends BriarActivity
|
||||
//noinspection ConstantConditions init in loadGroupId()
|
||||
storeMessage(privateMessageFactory.createPrivateMessage(
|
||||
messagingGroupId, timestamp, body), body);
|
||||
} catch (FormatException e) {throw new RuntimeException(e);
|
||||
} catch (FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -693,10 +545,8 @@ public class ConversationActivity extends BriarActivity
|
||||
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);
|
||||
addConversationItem(h.accept(visitor));
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
@@ -823,7 +673,7 @@ public class ConversationActivity extends BriarActivity
|
||||
@UiThread
|
||||
@Override
|
||||
public void respondToRequest(ConversationRequestItem item, boolean accept) {
|
||||
item.setAnswered(true);
|
||||
item.setAnswered();
|
||||
int position = adapter.findItemPosition(item);
|
||||
if (position != INVALID_POSITION) {
|
||||
adapter.notifyItemChanged(position, item);
|
||||
@@ -909,10 +759,11 @@ public class ConversationActivity extends BriarActivity
|
||||
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
||||
}
|
||||
|
||||
private ListenableFutureTask<String> getContactNameTask() {
|
||||
if (!contactNameTaskStarted.getAndSet(true))
|
||||
runOnDbThread(contactNameTask);
|
||||
return contactNameTask;
|
||||
@Nullable
|
||||
@Override
|
||||
public String getBody(MessageId m) {
|
||||
String body = bodyCache.get(m);
|
||||
if (body == null) loadMessageBody(m);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,20 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.contact.ConversationRequestItem.RequestType;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationRequest;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
||||
import org.briarproject.briar.api.client.BaseMessageHeader;
|
||||
import org.briarproject.briar.api.forum.ForumInvitationRequest;
|
||||
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
|
||||
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.BLOG;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.FORUM;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.GROUP;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
abstract class ConversationItem {
|
||||
|
||||
protected @Nullable String body;
|
||||
@Nullable
|
||||
protected String body;
|
||||
private final MessageId id;
|
||||
private final GroupId groupId;
|
||||
private final long time;
|
||||
@@ -78,216 +58,4 @@ abstract class ConversationItem {
|
||||
|
||||
@LayoutRes
|
||||
abstract public int getLayout();
|
||||
|
||||
static ConversationItem from(PrivateMessageHeader h) {
|
||||
if (h.isLocal()) {
|
||||
return new ConversationMessageOutItem(h);
|
||||
} else {
|
||||
return new ConversationMessageInItem(h);
|
||||
}
|
||||
}
|
||||
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
IntroductionRequest ir) {
|
||||
if (ir.isLocal()) {
|
||||
String text = ctx.getString(R.string.introduction_request_sent,
|
||||
contactName, ir.getName());
|
||||
return new ConversationNoticeOutItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, ir.getMessage(), ir.getTimestamp(),
|
||||
ir.isSent(), ir.isSeen());
|
||||
} else {
|
||||
String text;
|
||||
if (ir.wasAnswered()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_request_answered_received,
|
||||
contactName, ir.getName());
|
||||
} else if (ir.contactExists()){
|
||||
text = ctx.getString(
|
||||
R.string.introduction_request_exists_received,
|
||||
contactName, ir.getName());
|
||||
} else {
|
||||
text = ctx.getString(R.string.introduction_request_received,
|
||||
contactName, ir.getName());
|
||||
}
|
||||
return new ConversationRequestItem(ir.getMessageId(),
|
||||
ir.getGroupId(), INTRODUCTION, ir.getSessionId(), text,
|
||||
ir.getMessage(), ir.getTimestamp(), ir.isRead(), null,
|
||||
ir.wasAnswered(), false);
|
||||
}
|
||||
}
|
||||
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
IntroductionResponse ir) {
|
||||
if (ir.isLocal()) {
|
||||
String text;
|
||||
if (ir.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_accepted_sent,
|
||||
ir.getName());
|
||||
text += "\n\n" + ctx.getString(
|
||||
R.string.introduction_response_accepted_sent_info,
|
||||
ir.getName());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_sent,
|
||||
ir.getName());
|
||||
}
|
||||
return new ConversationNoticeOutItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, null, ir.getTimestamp(), ir.isSent(),
|
||||
ir.isSeen());
|
||||
} else {
|
||||
String text;
|
||||
if (ir.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_accepted_received,
|
||||
contactName, ir.getName());
|
||||
} else {
|
||||
if (ir.isIntroducer()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_received,
|
||||
contactName, ir.getName());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_received_by_introducee,
|
||||
contactName, ir.getName());
|
||||
}
|
||||
}
|
||||
return new ConversationNoticeInItem(ir.getMessageId(),
|
||||
ir.getGroupId(), text, null, ir.getTimestamp(),
|
||||
ir.isRead());
|
||||
}
|
||||
}
|
||||
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
InvitationRequest ir) {
|
||||
if (ir.isLocal()) {
|
||||
String text;
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
text = ctx.getString(R.string.forum_invitation_sent,
|
||||
((ForumInvitationRequest) ir).getForumName(),
|
||||
contactName);
|
||||
} else if (ir instanceof BlogInvitationRequest) {
|
||||
text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
||||
((BlogInvitationRequest) ir).getBlogAuthorName(),
|
||||
contactName);
|
||||
} else if (ir instanceof GroupInvitationRequest) {
|
||||
text = ctx.getString(
|
||||
R.string.groups_invitations_invitation_sent,
|
||||
contactName, ir.getShareable().getName());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown InvitationRequest");
|
||||
}
|
||||
return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(),
|
||||
text, ir.getMessage(), ir.getTimestamp(), ir.isSent(),
|
||||
ir.isSeen());
|
||||
} else {
|
||||
String text;
|
||||
RequestType type;
|
||||
if (ir instanceof ForumInvitationRequest) {
|
||||
text = ctx.getString(R.string.forum_invitation_received,
|
||||
contactName,
|
||||
((ForumInvitationRequest) ir).getForumName());
|
||||
type = FORUM;
|
||||
} else if (ir instanceof BlogInvitationRequest) {
|
||||
text = ctx.getString(R.string.blogs_sharing_invitation_received,
|
||||
contactName,
|
||||
((BlogInvitationRequest) ir).getBlogAuthorName());
|
||||
type = BLOG;
|
||||
} else if (ir instanceof GroupInvitationRequest) {
|
||||
text = ctx.getString(
|
||||
R.string.groups_invitations_invitation_received,
|
||||
contactName, ir.getShareable().getName());
|
||||
type = GROUP;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown InvitationRequest");
|
||||
}
|
||||
return new ConversationRequestItem(ir.getId(),
|
||||
ir.getGroupId(), type, ir.getSessionId(), text,
|
||||
ir.getMessage(), ir.getTimestamp(), ir.isRead(),
|
||||
ir.getShareable().getId(), !ir.isAvailable(),
|
||||
ir.canBeOpened());
|
||||
}
|
||||
}
|
||||
|
||||
static ConversationItem from(Context ctx, String contactName,
|
||||
InvitationResponse ir) {
|
||||
@StringRes int res;
|
||||
if (ir.isLocal()) {
|
||||
if (ir.wasAccepted()) {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_accepted_sent;
|
||||
} else if (ir instanceof BlogInvitationResponse) {
|
||||
res = R.string.blogs_sharing_response_accepted_sent;
|
||||
} else if (ir instanceof GroupInvitationResponse) {
|
||||
res = R.string.groups_invitations_response_accepted_sent;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown InvitationResponse");
|
||||
}
|
||||
} else {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_declined_sent;
|
||||
} else if (ir instanceof BlogInvitationResponse) {
|
||||
res = R.string.blogs_sharing_response_declined_sent;
|
||||
} else if (ir instanceof GroupInvitationResponse) {
|
||||
res = R.string.groups_invitations_response_declined_sent;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown InvitationResponse");
|
||||
}
|
||||
}
|
||||
String text = ctx.getString(res, contactName);
|
||||
return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(),
|
||||
text, null, ir.getTimestamp(), ir.isSent(), ir.isSeen());
|
||||
} else {
|
||||
if (ir.wasAccepted()) {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_accepted_received;
|
||||
} else if (ir instanceof BlogInvitationResponse) {
|
||||
res = R.string.blogs_sharing_response_accepted_received;
|
||||
} else if (ir instanceof GroupInvitationResponse) {
|
||||
res = R.string.groups_invitations_response_accepted_received;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown InvitationResponse");
|
||||
}
|
||||
} else {
|
||||
if (ir instanceof ForumInvitationResponse) {
|
||||
res = R.string.forum_invitation_response_declined_received;
|
||||
} else if (ir instanceof BlogInvitationResponse) {
|
||||
res = R.string.blogs_sharing_response_declined_received;
|
||||
} else if (ir instanceof GroupInvitationResponse) {
|
||||
res = R.string.groups_invitations_response_declined_received;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown InvitationResponse");
|
||||
}
|
||||
}
|
||||
String text = ctx.getString(res, contactName);
|
||||
return new ConversationNoticeInItem(ir.getId(), ir.getGroupId(),
|
||||
text, null, ir.getTimestamp(), ir.isRead());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should not be used to display the resulting ConversationItem
|
||||
* in the UI, but only to update list information based on the
|
||||
* BaseMessageHeader.
|
||||
**/
|
||||
static ConversationItem from(Context ctx, BaseMessageHeader h) {
|
||||
if (h instanceof PrivateMessageHeader) {
|
||||
return from((PrivateMessageHeader) h);
|
||||
} else if(h instanceof IntroductionRequest) {
|
||||
return from(ctx, "", (IntroductionRequest) h);
|
||||
} else if(h instanceof IntroductionResponse) {
|
||||
return from(ctx, "", (IntroductionResponse) h);
|
||||
} else if(h instanceof InvitationRequest) {
|
||||
return from(ctx, "", (InvitationRequest) h);
|
||||
} else if(h instanceof InvitationResponse) {
|
||||
return from(ctx, "", (InvitationResponse) h);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown message header");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.api.messaging.PrivateResponse;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
@@ -17,13 +18,17 @@ class ConversationNoticeInItem extends ConversationItem {
|
||||
@Nullable
|
||||
private final String msgText;
|
||||
|
||||
ConversationNoticeInItem(MessageId id, GroupId groupId,
|
||||
String text, @Nullable String msgText, long time,
|
||||
boolean read) {
|
||||
ConversationNoticeInItem(MessageId id, GroupId groupId, String text,
|
||||
@Nullable String msgText, long time, boolean read) {
|
||||
super(id, groupId, text, time, read);
|
||||
this.msgText = msgText;
|
||||
}
|
||||
|
||||
ConversationNoticeInItem(String text, PrivateResponse r) {
|
||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isRead());
|
||||
this.msgText = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getMsgText() {
|
||||
return msgText;
|
||||
@@ -39,5 +44,4 @@ class ConversationNoticeInItem extends ConversationItem {
|
||||
public int getLayout() {
|
||||
return R.layout.list_item_conversation_notice_in;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package org.briarproject.briar.android.contact;
|
||||
import android.support.annotation.LayoutRes;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.api.messaging.PrivateRequest;
|
||||
import org.briarproject.briar.api.messaging.PrivateResponse;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
@@ -17,11 +17,16 @@ class ConversationNoticeOutItem extends ConversationOutItem {
|
||||
@Nullable
|
||||
private final String msgText;
|
||||
|
||||
ConversationNoticeOutItem(MessageId id, GroupId groupId,
|
||||
String text, @Nullable String msgText, long time,
|
||||
boolean sent, boolean seen) {
|
||||
super(id, groupId, text, time, sent, seen);
|
||||
this.msgText = msgText;
|
||||
ConversationNoticeOutItem(String text, PrivateRequest r) {
|
||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isSent(),
|
||||
r.isSeen());
|
||||
this.msgText = r.getMessage();
|
||||
}
|
||||
|
||||
ConversationNoticeOutItem(String text, PrivateResponse r) {
|
||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isSent(),
|
||||
r.isSeen());
|
||||
this.msgText = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -34,5 +39,4 @@ class ConversationNoticeOutItem extends ConversationOutItem {
|
||||
public int getLayout() {
|
||||
return R.layout.list_item_conversation_notice_out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ import android.support.annotation.LayoutRes;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.messaging.PrivateRequest;
|
||||
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||
import org.briarproject.briar.api.sharing.Shareable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
@@ -15,7 +17,7 @@ import javax.annotation.concurrent.NotThreadSafe;
|
||||
@NotNullByDefault
|
||||
class ConversationRequestItem extends ConversationNoticeInItem {
|
||||
|
||||
enum RequestType { INTRODUCTION, FORUM, BLOG, GROUP }
|
||||
enum RequestType {INTRODUCTION, FORUM, BLOG, GROUP}
|
||||
|
||||
@Nullable
|
||||
private final GroupId requestedGroupId;
|
||||
@@ -24,17 +26,19 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
||||
private final boolean canBeOpened;
|
||||
private boolean answered;
|
||||
|
||||
ConversationRequestItem(MessageId id, GroupId groupId,
|
||||
RequestType requestType, SessionId sessionId, String text,
|
||||
@Nullable String msgText, long time, boolean read,
|
||||
@Nullable GroupId requestedGroupId, boolean answered,
|
||||
boolean canBeOpened) {
|
||||
super(id, groupId, text, msgText, time, read);
|
||||
this.requestType = requestType;
|
||||
this.sessionId = sessionId;
|
||||
this.requestedGroupId = requestedGroupId;
|
||||
this.answered = answered;
|
||||
this.canBeOpened = canBeOpened;
|
||||
ConversationRequestItem(String text, RequestType type, PrivateRequest r) {
|
||||
super(r.getId(), r.getGroupId(), text, r.getMessage(),
|
||||
r.getTimestamp(), r.isRead());
|
||||
this.requestType = type;
|
||||
this.sessionId = r.getSessionId();
|
||||
this.answered = r.wasAnswered();
|
||||
if (r instanceof InvitationRequest) {
|
||||
this.requestedGroupId = ((Shareable) r.getNameable()).getId();
|
||||
this.canBeOpened = ((InvitationRequest) r).canBeOpened();
|
||||
} else {
|
||||
this.requestedGroupId = null;
|
||||
this.canBeOpened = false;
|
||||
}
|
||||
}
|
||||
|
||||
RequestType getRequestType() {
|
||||
@@ -54,8 +58,8 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
||||
return answered;
|
||||
}
|
||||
|
||||
void setAnswered(boolean answered) {
|
||||
this.answered = answered;
|
||||
void setAnswered() {
|
||||
this.answered = true;
|
||||
}
|
||||
|
||||
public boolean canBeOpened() {
|
||||
@@ -67,5 +71,4 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
||||
public int getLayout() {
|
||||
return R.layout.list_item_conversation_request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationRequest;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
||||
import org.briarproject.briar.api.forum.ForumInvitationRequest;
|
||||
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageVisitor;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.BLOG;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.FORUM;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.GROUP;
|
||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
||||
|
||||
private final Context ctx;
|
||||
private final BodyCache bodyCache;
|
||||
private final LiveData<String> contactName;
|
||||
|
||||
ConversationVisitor(Context ctx, BodyCache bodyCache,
|
||||
LiveData<String> contactName) {
|
||||
this.ctx = ctx;
|
||||
this.bodyCache = bodyCache;
|
||||
this.contactName = contactName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitPrivateMessageHeader(PrivateMessageHeader h) {
|
||||
ConversationItem item;
|
||||
if (h.isLocal()) item = new ConversationMessageOutItem(h);
|
||||
else item = new ConversationMessageInItem(h);
|
||||
String body = bodyCache.getBody(h.getId());
|
||||
if (body != null) item.setBody(body);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitBlogInvitationRequest(
|
||||
BlogInvitationRequest r) {
|
||||
if (r.isLocal()) {
|
||||
String text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
||||
r.getName(), contactName.getValue());
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text = ctx.getString(
|
||||
R.string.blogs_sharing_invitation_received,
|
||||
contactName.getValue(), r.getName());
|
||||
return new ConversationRequestItem(text, BLOG, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitBlogInvitationResponse(
|
||||
BlogInvitationResponse r) {
|
||||
if (r.isLocal()) {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_accepted_sent,
|
||||
contactName.getValue());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_declined_sent,
|
||||
contactName.getValue());
|
||||
}
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_accepted_received,
|
||||
contactName.getValue());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.blogs_sharing_response_declined_received,
|
||||
contactName.getValue());
|
||||
}
|
||||
return new ConversationNoticeInItem(text, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitForumInvitationRequest(
|
||||
ForumInvitationRequest r) {
|
||||
if (r.isLocal()) {
|
||||
String text = ctx.getString(R.string.forum_invitation_sent,
|
||||
r.getName(), contactName.getValue());
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text = ctx.getString(
|
||||
R.string.forum_invitation_received,
|
||||
contactName.getValue(), r.getName());
|
||||
return new ConversationRequestItem(text, FORUM, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitForumInvitationResponse(
|
||||
ForumInvitationResponse r) {
|
||||
if (r.isLocal()) {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_accepted_sent,
|
||||
contactName.getValue());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_declined_sent,
|
||||
contactName.getValue());
|
||||
}
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_accepted_received,
|
||||
contactName.getValue());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.forum_invitation_response_declined_received,
|
||||
contactName.getValue());
|
||||
}
|
||||
return new ConversationNoticeInItem(text, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitGroupInvitationRequest(
|
||||
GroupInvitationRequest r) {
|
||||
if (r.isLocal()) {
|
||||
String text = ctx.getString(
|
||||
R.string.groups_invitations_invitation_sent,
|
||||
contactName.getValue(), r.getName());
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text = ctx.getString(
|
||||
R.string.groups_invitations_invitation_received,
|
||||
contactName.getValue(), r.getName());
|
||||
return new ConversationRequestItem(text, GROUP, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitGroupInvitationResponse(
|
||||
GroupInvitationResponse r) {
|
||||
if (r.isLocal()) {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.groups_invitations_response_accepted_sent,
|
||||
contactName.getValue());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.groups_invitations_response_declined_sent,
|
||||
contactName.getValue());
|
||||
}
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.groups_invitations_response_accepted_received,
|
||||
contactName.getValue());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.groups_invitations_response_declined_received,
|
||||
contactName.getValue());
|
||||
}
|
||||
return new ConversationNoticeInItem(text, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitIntroductionRequest(IntroductionRequest r) {
|
||||
if (r.isLocal()) {
|
||||
String text = ctx.getString(R.string.introduction_request_sent,
|
||||
contactName.getValue(), r.getName());
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text = ctx.getString(R.string.introduction_request_received,
|
||||
contactName.getValue(), r.getName());
|
||||
return new ConversationRequestItem(text, INTRODUCTION, r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitIntroductionResponse(IntroductionResponse r) {
|
||||
if (r.isLocal()) {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
String introducee = r.getIntroducedAuthor().getName();
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_accepted_sent,
|
||||
introducee)
|
||||
+ "\n\n" + ctx.getString(
|
||||
R.string.introduction_response_accepted_sent_info,
|
||||
introducee);
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_sent,
|
||||
r.getIntroducedAuthor().getName());
|
||||
}
|
||||
return new ConversationNoticeOutItem(text, r);
|
||||
} else {
|
||||
String text;
|
||||
if (r.wasAccepted()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_accepted_received,
|
||||
contactName.getValue(),
|
||||
r.getIntroducedAuthor().getName());
|
||||
} else if (r.isIntroducer()) {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_received,
|
||||
contactName.getValue(),
|
||||
r.getIntroducedAuthor().getName());
|
||||
} else {
|
||||
text = ctx.getString(
|
||||
R.string.introduction_response_declined_received_by_introducee,
|
||||
contactName.getValue(),
|
||||
r.getIntroducedAuthor().getName());
|
||||
}
|
||||
return new ConversationNoticeInItem(text, r);
|
||||
}
|
||||
}
|
||||
|
||||
interface BodyCache {
|
||||
@Nullable
|
||||
String getBody(MessageId m);
|
||||
}
|
||||
}
|
||||
@@ -84,11 +84,10 @@ class ForumControllerImpl extends
|
||||
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
|
||||
ForumInvitationResponseReceivedEvent f =
|
||||
(ForumInvitationResponseReceivedEvent) e;
|
||||
ForumInvitationResponse r =
|
||||
(ForumInvitationResponse) f.getResponse();
|
||||
ForumInvitationResponse r = f.getMessageHeader();
|
||||
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) {
|
||||
LOG.info("Forum invitation was accepted");
|
||||
onForumInvitationAccepted(r.getContactId());
|
||||
onForumInvitationAccepted(f.getContactId());
|
||||
}
|
||||
} else if (e instanceof ContactLeftShareableEvent) {
|
||||
ContactLeftShareableEvent c = (ContactLeftShareableEvent) e;
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.introduction;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -82,8 +83,8 @@ public class IntroductionMessageFragment extends BaseFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
// change toolbar text
|
||||
ActionBar actionBar = introductionActivity.getSupportActionBar();
|
||||
@@ -182,7 +183,7 @@ public class IntroductionMessageFragment extends BaseFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendClick(String text) {
|
||||
public void onSendClick(@NonNull String text) {
|
||||
// disable button to prevent accidental double invitations
|
||||
ui.message.setSendButtonEnabled(false);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
|
||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
|
||||
@@ -23,6 +22,7 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
||||
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
||||
import org.briarproject.bramble.api.keyagreement.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementAbortedEvent;
|
||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFailedEvent;
|
||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
|
||||
@@ -244,8 +244,14 @@ public class KeyAgreementFragment extends BaseEventFragment
|
||||
task.connectAndRunProtocol(remotePayload);
|
||||
} catch (UnsupportedVersionException e) {
|
||||
reset();
|
||||
String msg = getString(R.string.qr_code_unsupported,
|
||||
getString(R.string.app_name));
|
||||
String msg;
|
||||
if (e.isTooOld()) {
|
||||
msg = getString(R.string.qr_code_too_old,
|
||||
getString(R.string.app_name));
|
||||
} else {
|
||||
msg = getString(R.string.qr_code_too_new,
|
||||
getString(R.string.app_name));
|
||||
}
|
||||
showNextFragment(ContactExchangeErrorFragment.newInstance(msg));
|
||||
} catch (CameraException e) {
|
||||
logCameraExceptionAndFinish(e);
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.graphics.drawable.ClipDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
@@ -15,6 +16,7 @@ import static android.graphics.Paint.Style.FILL;
|
||||
import static android.graphics.Paint.Style.STROKE;
|
||||
import static android.graphics.drawable.ClipDrawable.HORIZONTAL;
|
||||
import static android.view.Gravity.LEFT;
|
||||
import static android.view.Gravity.START;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
|
||||
@@ -35,11 +37,11 @@ public class StrengthMeter extends ProgressBar {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public StrengthMeter(Context context, AttributeSet attrs) {
|
||||
public StrengthMeter(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs, android.R.attr.progressBarStyleHorizontal);
|
||||
bar = new ShapeDrawable();
|
||||
bar.getPaint().setColor(RED);
|
||||
ClipDrawable clip = new ClipDrawable(bar, LEFT, HORIZONTAL);
|
||||
ClipDrawable clip = new ClipDrawable(bar, LEFT & START, HORIZONTAL);
|
||||
ShapeDrawable background = new ShapeDrawable();
|
||||
Paint p = background.getPaint();
|
||||
p.setStyle(FILL);
|
||||
@@ -50,6 +52,7 @@ public class StrengthMeter extends ProgressBar {
|
||||
Drawable[] layers = new Drawable[] { clip, background };
|
||||
setProgressDrawable(new LayerDrawable(layers));
|
||||
setIndeterminate(false);
|
||||
if (isInEditMode()) setStrength(STRONG);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package org.briarproject.briar.android.panic;
|
||||
|
||||
import info.guardianproject.trustedintents.ApkSignaturePin;
|
||||
|
||||
// needs to be public, because TrustedIntents will instantiate
|
||||
public final class FDroidSignaturePin extends ApkSignaturePin {
|
||||
|
||||
public FDroidSignaturePin() {
|
||||
this.fingerprints = new String[] {
|
||||
"927f7e38b6acbecd84e02dace33efa9a7a2f0979750f28f585688ee38b3a4e28"};
|
||||
this.certificates = new byte[][] {
|
||||
{48, -126, 3, 95, 48, -126, 2, 71, -96, 3, 2, 1, 2, 2, 4, 28,
|
||||
-30, 107, -102, 48, 13, 6, 9, 42, -122, 72, -122, -9,
|
||||
13, 1, 1, 11, 5, 0, 48, 96, 49, 11, 48, 9, 6, 3, 85, 4,
|
||||
6, 19, 2, 85, 75, 49, 12, 48, 10, 6, 3, 85, 4, 8, 19, 3,
|
||||
79, 82, 71, 49, 12, 48, 10, 6, 3, 85, 4, 7, 19, 3, 79,
|
||||
82, 71, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 102,
|
||||
100, 114, 111, 105, 100, 46, 111, 114, 103, 49, 15, 48,
|
||||
13, 6, 3, 85, 4, 11, 19, 6, 70, 68, 114, 111, 105, 100,
|
||||
49, 15, 48, 13, 6, 3, 85, 4, 3, 19, 6, 70, 68, 114, 111,
|
||||
105, 100, 48, 30, 23, 13, 49, 55, 49, 50, 48, 55, 49,
|
||||
55, 51, 48, 52, 50, 90, 23, 13, 52, 53, 48, 52, 50, 52,
|
||||
49, 55, 51, 48, 52, 50, 90, 48, 96, 49, 11, 48, 9, 6, 3,
|
||||
85, 4, 6, 19, 2, 85, 75, 49, 12, 48, 10, 6, 3, 85, 4, 8,
|
||||
19, 3, 79, 82, 71, 49, 12, 48, 10, 6, 3, 85, 4, 7, 19,
|
||||
3, 79, 82, 71, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10,
|
||||
102, 100, 114, 111, 105, 100, 46, 111, 114, 103, 49, 15,
|
||||
48, 13, 6, 3, 85, 4, 11, 19, 6, 70, 68, 114, 111, 105,
|
||||
100, 49, 15, 48, 13, 6, 3, 85, 4, 3, 19, 6, 70, 68, 114,
|
||||
111, 105, 100, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122,
|
||||
72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48,
|
||||
-126, 1, 10, 2, -126, 1, 1, 0, -107, -115, -106, 1, -26,
|
||||
72, -105, -99, 62, 3, -55, 34, 99, -112, -68, -20, -115,
|
||||
31, 34, 118, -50, 12, -32, -59, 74, -58, -37, -87, 21,
|
||||
105, 36, -82, 13, -51, 66, 4, 55, -111, 13, -46, -7,
|
||||
-69, -15, 36, 118, -7, 101, -86, 123, -83, -103, 110,
|
||||
116, -54, 112, 46, 12, 96, -76, -48, -70, -33, -81, 52,
|
||||
59, 73, 107, -126, -72, -25, 32, 93, 29, -20, 5, -41,
|
||||
-27, 123, -9, 104, -31, -59, -1, -83, -93, 99, 85, -116,
|
||||
-62, -55, 18, -63, 6, -51, -110, 33, 9, 7, -49, 102,
|
||||
-20, -122, -124, -68, 93, -102, 31, 48, 86, 96, -99,
|
||||
105, -52, 95, 12, 57, 99, 12, -24, 70, 40, -99, -20,
|
||||
-21, -85, -70, -105, 95, 117, -31, 126, -126, -39, 46,
|
||||
-62, 59, -23, -74, 108, -12, -56, -40, -96, 79, -37,
|
||||
-82, 1, 99, -104, 48, -60, 92, 14, 109, 127, -22, 31,
|
||||
115, -27, 108, 9, 92, 118, -45, 103, 117, 57, -50, -82,
|
||||
114, -113, 68, -82, 87, 96, 111, 72, 65, -63, 12, 31,
|
||||
-34, -31, -55, -101, 101, 101, 59, 73, -119, -122, 82,
|
||||
28, 47, -108, -85, 59, 46, 89, -93, -1, 9, -11, -51, 63,
|
||||
-44, 109, -76, -103, -26, -49, -80, 6, 52, -27, 73,
|
||||
-104, 40, 2, -101, -124, 60, -52, -105, -70, -24, -62,
|
||||
88, 38, 53, -99, -92, 31, 119, 26, 79, 60, -124, 25,
|
||||
-115, -89, -115, -109, 0, 6, 122, -78, 116, 82, 3, 39,
|
||||
-67, 45, -43, 17, -39, 2, 3, 1, 0, 1, -93, 33, 48, 31,
|
||||
48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 63, 109, -42,
|
||||
-109, 25, 22, 7, -37, -22, -41, -38, 58, -56, 2, -68,
|
||||
-38, -22, 65, -28, -60, 48, 13, 6, 9, 42, -122, 72,
|
||||
-122, -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, 94, 17,
|
||||
31, 36, 85, -11, 85, 44, 19, -80, -20, -92, -118, 93,
|
||||
40, 45, 96, 31, -3, -37, -110, -96, 102, 81, 61, -74,
|
||||
-125, -117, -112, 58, -47, 17, 78, -18, 111, -116, 26,
|
||||
-91, 73, 100, 84, -99, 21, 87, 73, -106, 108, -51, -125,
|
||||
-21, 119, -88, -78, 2, 82, -109, -64, -9, -86, -112,
|
||||
-115, 66, -86, 46, 71, 107, -65, 96, -102, 47, 35, -45,
|
||||
-126, 33, 34, 121, -25, -85, -121, -56, -42, 22, -1,
|
||||
-95, -86, 81, 100, -70, 113, 104, -73, 22, -19, 79, -19,
|
||||
52, 62, 42, 76, -112, 94, -34, 42, -57, -75, -90, -58,
|
||||
118, 127, -106, -39, 108, -56, -79, 103, -33, 22, 3, 47,
|
||||
103, -76, -81, 53, -22, -44, -26, -102, 63, -99, 39, 38,
|
||||
-108, 75, 33, 10, 25, -110, -125, -115, 114, -69, 73,
|
||||
-112, 36, 74, 77, -82, -44, 29, -123, -8, -117, 71,
|
||||
-105, 15, -109, 51, 22, 4, 80, 1, 43, 118, 121, -113,
|
||||
-70, 83, -56, 82, -110, 4, -63, 16, -57, 126, -70, 81,
|
||||
73, 61, 2, -61, 24, -14, -10, 4, -21, 90, 24, 66, 41,
|
||||
-57, -60, -113, -18, -54, -1, 103, -75, 32, -64, 67,
|
||||
103, 109, -79, -12, -113, -27, 114, 89, 116, 115, -13,
|
||||
-123, -70, 61, -41, -46, -118, 29, -105, -97, -75, 39,
|
||||
-51, 60, 88, 125, 55, -46, -95, 52, 57, 52, -115, 80,
|
||||
44, 109, 119, -116, -62, -77, -74, -88, 41, 57, -65,
|
||||
-71, -115, -67, 23, 66, -21, 56, 51, -91, 109}};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -31,13 +31,12 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
public static final String KEY_LOCK = "pref_key_lock";
|
||||
public static final String KEY_PANIC_APP = "pref_key_panic_app";
|
||||
public static final String KEY_PURGE = "pref_key_purge";
|
||||
public static final String KEY_UNINSTALL = "pref_key_uninstall";
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(PanicPreferencesFragment.class.getName());
|
||||
|
||||
private PackageManager pm;
|
||||
private SwitchPreference lockPref, purgePref, uninstallPref;
|
||||
private SwitchPreference lockPref, purgePref;
|
||||
private ListPreference panicAppPref;
|
||||
|
||||
@Override
|
||||
@@ -49,7 +48,6 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
lockPref = (SwitchPreference) findPreference(KEY_LOCK);
|
||||
panicAppPref = (ListPreference) findPreference(KEY_PANIC_APP);
|
||||
purgePref = (SwitchPreference) findPreference(KEY_PURGE);
|
||||
uninstallPref = (SwitchPreference) findPreference(KEY_UNINSTALL);
|
||||
|
||||
// check for connect/disconnect intents from panic trigger apps
|
||||
if (PanicResponder.checkForDisconnectIntent(getActivity())) {
|
||||
@@ -97,16 +95,11 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
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);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -145,27 +138,15 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||
String key) {
|
||||
if (key.equals(KEY_PURGE)) {
|
||||
// enable locking if purging gets enabled
|
||||
if (sharedPreferences.getBoolean(KEY_PURGE, false)) {
|
||||
lockPref.setChecked(true);
|
||||
}
|
||||
// disable uninstall if purging gets disabled
|
||||
else {
|
||||
uninstallPref.setChecked(false);
|
||||
}
|
||||
}
|
||||
// enable purging and locking if uninstall gets enabled
|
||||
if (key.equals(KEY_UNINSTALL) &&
|
||||
sharedPreferences.getBoolean(KEY_UNINSTALL, false)) {
|
||||
// enable locking if purging gets enabled
|
||||
if (key.equals(KEY_PURGE) &&
|
||||
sharedPreferences.getBoolean(KEY_PURGE, false)) {
|
||||
lockPref.setChecked(true);
|
||||
purgePref.setChecked(true);
|
||||
}
|
||||
// disable purging and uninstalling if locking gets disabled
|
||||
// disable purging if locking gets disabled
|
||||
if (key.equals(KEY_LOCK) &&
|
||||
!sharedPreferences.getBoolean(KEY_LOCK, true)) {
|
||||
purgePref.setChecked(false);
|
||||
uninstallPref.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,10 +160,8 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
panicAppPref.setIcon(
|
||||
android.R.drawable.ic_menu_close_clear_cancel);
|
||||
|
||||
// disable panic actions
|
||||
lockPref.setEnabled(false);
|
||||
// disable destructive panic actions
|
||||
purgePref.setEnabled(false);
|
||||
uninstallPref.setEnabled(false);
|
||||
} else {
|
||||
// display connected panic app
|
||||
try {
|
||||
@@ -192,10 +171,8 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||
panicAppPref.setIcon(
|
||||
pm.getApplicationIcon(triggerPackageName));
|
||||
|
||||
// enable panic actions
|
||||
lockPref.setEnabled(true);
|
||||
// enable destructive panic actions
|
||||
purgePref.setEnabled(true);
|
||||
uninstallPref.setEnabled(true);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// revert back to no app, just to be safe
|
||||
PanicResponder.setTriggerPackageName(getActivity(),
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.briarproject.briar.android.panic;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
@@ -11,7 +10,6 @@ import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.iilab.IilabEngineeringRSA2048Pin;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -22,10 +20,8 @@ import info.guardianproject.panic.Panic;
|
||||
import info.guardianproject.panic.PanicResponder;
|
||||
import info.guardianproject.trustedintents.TrustedIntents;
|
||||
|
||||
import static android.content.Intent.ACTION_DELETE;
|
||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
|
||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
|
||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_UNINSTALL;
|
||||
|
||||
public class PanicResponderActivity extends BriarActivity {
|
||||
|
||||
@@ -44,8 +40,8 @@ public class PanicResponderActivity extends BriarActivity {
|
||||
TrustedIntents trustedIntents = TrustedIntents.get(this);
|
||||
// Guardian Project Ripple
|
||||
trustedIntents.addTrustedSigner(GuardianProjectRSA4096.class);
|
||||
// Amnesty International's Panic Button, made by iilab.org
|
||||
trustedIntents.addTrustedSigner(IilabEngineeringRSA2048Pin.class);
|
||||
// F-Droid
|
||||
trustedIntents.addTrustedSigner(FDroidSignaturePin.class);
|
||||
|
||||
Intent intent = trustedIntents.getIntentFromTrustedSender(this);
|
||||
if (intent != null) {
|
||||
@@ -60,23 +56,16 @@ public class PanicResponderActivity extends BriarActivity {
|
||||
LOG.info("Panic Trigger came from connected app");
|
||||
|
||||
// Performing panic responses
|
||||
if (sharedPref.getBoolean(KEY_UNINSTALL, false)) {
|
||||
if (sharedPref.getBoolean(KEY_PURGE, false)) {
|
||||
LOG.info("Purging all data...");
|
||||
deleteAllData();
|
||||
|
||||
LOG.info("Uninstalling...");
|
||||
Intent uninstall = new Intent(ACTION_DELETE);
|
||||
uninstall.setData(
|
||||
Uri.parse("package:" + getPackageName()));
|
||||
startActivity(uninstall);
|
||||
} else if (sharedPref.getBoolean(KEY_PURGE, false)) {
|
||||
LOG.info("Purging all data...");
|
||||
deleteAllData();
|
||||
} else if (sharedPref.getBoolean(KEY_LOCK, true)) {
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
}
|
||||
// non-destructive actions are allowed by non-connected trusted apps
|
||||
if (sharedPref.getBoolean(KEY_LOCK, true)) {
|
||||
LOG.info("Signing out...");
|
||||
signOut(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +99,10 @@ class GroupControllerImpl extends
|
||||
} else if (e instanceof GroupInvitationResponseReceivedEvent) {
|
||||
GroupInvitationResponseReceivedEvent g =
|
||||
(GroupInvitationResponseReceivedEvent) e;
|
||||
GroupInvitationResponse r =
|
||||
(GroupInvitationResponse) g.getResponse();
|
||||
GroupInvitationResponse r = g.getMessageHeader();
|
||||
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
|
||||
listener.runOnUiThreadUnlessDestroyed(
|
||||
() -> listener.onInvitationAccepted(r.getContactId()));
|
||||
() -> listener.onInvitationAccepted(g.getContactId()));
|
||||
}
|
||||
} else if (e instanceof GroupDissolvedEvent) {
|
||||
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
|
||||
|
||||
@@ -292,8 +292,7 @@ public class DevReportActivity extends BaseCrashReportDialog
|
||||
cb.setChecked(required || !excluded);
|
||||
cb.setEnabled(!required);
|
||||
cb.setOnCheckedChangeListener(DevReportActivity.this);
|
||||
TextView title = v.findViewById(R.id.title);
|
||||
title.setText(field.toString());
|
||||
cb.setText(field.toString());
|
||||
TextView content = v.findViewById(R.id.content);
|
||||
content.setText(value);
|
||||
report.addView(v);
|
||||
|
||||
@@ -89,7 +89,6 @@ import static org.briarproject.briar.api.android.AndroidNotificationManager.GROU
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_FORUM;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_GROUP;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_LOCK_SCREEN;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_PRIVATE;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_NAME;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_URI;
|
||||
@@ -127,7 +126,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
private SwitchPreference notifyForumPosts;
|
||||
private SwitchPreference notifyBlogPosts;
|
||||
private SwitchPreference notifyVibration;
|
||||
private SwitchPreference notifyLockscreen;
|
||||
|
||||
private Preference notifySound;
|
||||
|
||||
@@ -179,8 +177,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
"pref_key_notify_blog_posts");
|
||||
notifyVibration = (SwitchPreference) findPreference(
|
||||
"pref_key_notify_vibration");
|
||||
notifyLockscreen = (SwitchPreference) findPreference(
|
||||
"pref_key_notify_lock_screen");
|
||||
notifySound = findPreference("pref_key_notify_sound");
|
||||
|
||||
language.setOnPreferenceChangeListener(this);
|
||||
@@ -207,10 +203,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
torMobile.setOnPreferenceChangeListener(this);
|
||||
screenLock.setOnPreferenceChangeListener(this);
|
||||
screenLockTimeout.setOnPreferenceChangeListener(this);
|
||||
if (SDK_INT >= 21) {
|
||||
notifyLockscreen.setVisible(true);
|
||||
notifyLockscreen.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
findPreference("pref_key_send_feedback").setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
@@ -380,8 +372,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
notifyForumPosts.setOnPreferenceChangeListener(this);
|
||||
notifyBlogPosts.setOnPreferenceChangeListener(this);
|
||||
notifyVibration.setOnPreferenceChangeListener(this);
|
||||
notifyLockscreen.setChecked(settings.getBoolean(
|
||||
PREF_NOTIFY_LOCK_SCREEN, false));
|
||||
notifySound.setOnPreferenceClickListener(
|
||||
pref -> onNotificationSoundClicked());
|
||||
String text;
|
||||
@@ -409,7 +399,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
setupNotificationPreference(notifyBlogPosts, BLOG_CHANNEL_ID,
|
||||
R.string.notify_blog_posts_setting_summary_26);
|
||||
notifyVibration.setVisible(false);
|
||||
notifyLockscreen.setVisible(false);
|
||||
notifySound.setVisible(false);
|
||||
}
|
||||
setSettingsEnabled(true);
|
||||
@@ -432,7 +421,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
notifyForumPosts.setEnabled(enabled);
|
||||
notifyBlogPosts.setEnabled(enabled);
|
||||
notifyVibration.setEnabled(enabled);
|
||||
notifyLockscreen.setEnabled(enabled);
|
||||
notifySound.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -553,10 +541,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
Settings s = new Settings();
|
||||
s.putBoolean(PREF_NOTIFY_VIBRATION, (Boolean) newValue);
|
||||
storeSettings(s);
|
||||
} else if (preference == notifyLockscreen) {
|
||||
Settings s = new Settings();
|
||||
s.putBoolean(PREF_NOTIFY_LOCK_SCREEN, (Boolean) newValue);
|
||||
storeSettings(s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android.sharing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -26,7 +27,7 @@ public abstract class InvitationAdapter<I extends InvitationItem, VH extends Inv
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(VH ui, int position) {
|
||||
public void onBindViewHolder(@NonNull VH ui, int position) {
|
||||
I item = getItemAt(position);
|
||||
if (item == null) return;
|
||||
ui.onBind(item, listener);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.briar.android.threaded;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@@ -36,8 +37,9 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
||||
this.layoutManager = layoutManager;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public BaseThreadItemViewHolder<I> onCreateViewHolder(
|
||||
public BaseThreadItemViewHolder<I> onCreateViewHolder(@NonNull
|
||||
ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.list_item_thread, parent, false);
|
||||
@@ -45,7 +47,8 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(BaseThreadItemViewHolder<I> ui, int position) {
|
||||
public void onBindViewHolder(@NonNull BaseThreadItemViewHolder<I> ui,
|
||||
int position) {
|
||||
I item = items.get(position);
|
||||
ui.bind(item, listener);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package org.briarproject.briar.android.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE;
|
||||
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
|
||||
|
||||
|
||||
public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
||||
@@ -22,6 +21,7 @@ public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
||||
|
||||
setLights(ContextCompat.getColor(context, R.color.briar_green_light),
|
||||
750, 500);
|
||||
if (SDK_INT >= 21) setVisibility(VISIBILITY_PRIVATE);
|
||||
}
|
||||
|
||||
public BriarNotificationBuilder setColorRes(@ColorRes int res) {
|
||||
@@ -29,13 +29,8 @@ public class BriarNotificationBuilder extends NotificationCompat.Builder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BriarNotificationBuilder setLockscreenVisibility(String category,
|
||||
boolean show) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setCategory(category);
|
||||
if (show) setVisibility(VISIBILITY_PRIVATE);
|
||||
else setVisibility(VISIBILITY_SECRET);
|
||||
}
|
||||
public BriarNotificationBuilder setNotificationCategory(String category) {
|
||||
if (SDK_INT >= 21) setCategory(category);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@ import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
|
||||
import static android.view.KeyEvent.ACTION_DOWN;
|
||||
import static android.view.KeyEvent.ACTION_UP;
|
||||
import static android.view.KeyEvent.KEYCODE_ENTER;
|
||||
import static android.view.inputmethod.EditorInfo.IME_NULL;
|
||||
import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
|
||||
@@ -157,7 +156,7 @@ public class UiUtils {
|
||||
|
||||
/**
|
||||
* Executes the runnable when clicking the link in the textView's text.
|
||||
*
|
||||
* <p>
|
||||
* Attention: This assumes that there's only <b>one</b> link in the text.
|
||||
*/
|
||||
public static void onSingleLinkClick(TextView textView, Runnable runnable) {
|
||||
|
||||
@@ -5,11 +5,10 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.annotation.DimenRes;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.constraint.ConstraintLayout;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
@@ -30,7 +29,7 @@ import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||
import static org.briarproject.briar.android.util.UiUtils.resolveAttribute;
|
||||
|
||||
@UiThread
|
||||
public class AuthorView extends RelativeLayout {
|
||||
public class AuthorView extends ConstraintLayout {
|
||||
|
||||
public static final int NORMAL = 0;
|
||||
public static final int REBLOGGER = 1;
|
||||
@@ -133,32 +132,24 @@ public class AuthorView extends RelativeLayout {
|
||||
date.setVisibility(VISIBLE);
|
||||
setAvatarSize(R.dimen.blogs_avatar_normal_size);
|
||||
setTextSize(authorName, R.dimen.text_size_small);
|
||||
setCenterVertical(authorName, false);
|
||||
setCenterVertical(trustIndicator, false);
|
||||
break;
|
||||
case REBLOGGER:
|
||||
avatarIcon.setVisibility(VISIBLE);
|
||||
date.setVisibility(VISIBLE);
|
||||
setAvatarSize(R.dimen.blogs_avatar_normal_size);
|
||||
setTextSize(authorName, R.dimen.text_size_small);
|
||||
setCenterVertical(authorName, false);
|
||||
setCenterVertical(trustIndicator, false);
|
||||
break;
|
||||
case COMMENTER:
|
||||
avatarIcon.setVisibility(INVISIBLE);
|
||||
date.setVisibility(VISIBLE);
|
||||
setAvatarSize(R.dimen.blogs_avatar_comment_size);
|
||||
setTextSize(authorName, R.dimen.text_size_tiny);
|
||||
setCenterVertical(authorName, false);
|
||||
setCenterVertical(trustIndicator, false);
|
||||
break;
|
||||
case LIST:
|
||||
avatarIcon.setVisibility(INVISIBLE);
|
||||
date.setVisibility(GONE);
|
||||
setAvatarSize(R.dimen.listitem_picture_size_small);
|
||||
setTextSize(authorName, R.dimen.text_size_medium);
|
||||
setCenterVertical(authorName, true);
|
||||
setCenterVertical(trustIndicator, true);
|
||||
break;
|
||||
case RSS_FEED:
|
||||
avatarIcon.setVisibility(INVISIBLE);
|
||||
@@ -166,8 +157,6 @@ public class AuthorView extends RelativeLayout {
|
||||
avatar.setImageResource(R.drawable.ic_rss_feed);
|
||||
setAvatarSize(R.dimen.blogs_avatar_normal_size);
|
||||
setTextSize(authorName, R.dimen.text_size_small);
|
||||
setCenterVertical(authorName, false);
|
||||
setCenterVertical(trustIndicator, false);
|
||||
break;
|
||||
case RSS_FEED_REBLOGGED:
|
||||
avatarIcon.setVisibility(INVISIBLE);
|
||||
@@ -175,8 +164,6 @@ public class AuthorView extends RelativeLayout {
|
||||
avatar.setImageResource(R.drawable.ic_rss_feed);
|
||||
setAvatarSize(R.dimen.blogs_avatar_comment_size);
|
||||
setTextSize(authorName, R.dimen.text_size_tiny);
|
||||
setCenterVertical(authorName, false);
|
||||
setCenterVertical(trustIndicator, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -194,10 +181,4 @@ public class AuthorView extends RelativeLayout {
|
||||
v.setTextSize(COMPLEX_UNIT_PX, textSize);
|
||||
}
|
||||
|
||||
private void setCenterVertical(View v, boolean center) {
|
||||
LayoutParams params = (LayoutParams) v.getLayoutParams();
|
||||
params.addRule(CENTER_VERTICAL, center ? RelativeLayout.TRUE : 0);
|
||||
v.setLayoutParams(params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ public class QrCodeView extends FrameLayout {
|
||||
private boolean fullscreen = false;
|
||||
private FullscreenListener listener;
|
||||
|
||||
public QrCodeView(@NonNull Context context,
|
||||
@Nullable AttributeSet attrs) {
|
||||
public QrCodeView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
LayoutInflater inflater = (LayoutInflater) context
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.view;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.widget.AppCompatTextView;
|
||||
import android.util.AttributeSet;
|
||||
@@ -11,13 +10,11 @@ import android.view.LayoutInflater;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
import im.delight.android.identicons.IdenticonDrawable;
|
||||
|
||||
@UiThread
|
||||
public class TextAvatarView extends FrameLayout {
|
||||
@@ -35,7 +32,6 @@ public class TextAvatarView extends FrameLayout {
|
||||
character = findViewById(R.id.textAvatarView);
|
||||
background = findViewById(R.id.avatarBackground);
|
||||
badge = findViewById(R.id.unreadCountView);
|
||||
badge.setVisibility(INVISIBLE);
|
||||
}
|
||||
|
||||
public TextAvatarView(Context context) {
|
||||
@@ -72,10 +68,4 @@ public class TextAvatarView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAuthorAvatar(Author author) {
|
||||
Drawable drawable = new IdenticonDrawable(author.getId().getBytes());
|
||||
background.setImageDrawable(drawable);
|
||||
character.setVisibility(GONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,9 +61,11 @@ public class TextInputView extends KeyboardAwareLinearLayout {
|
||||
public TextInputView(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
BriarApplication app =
|
||||
(BriarApplication) context.getApplicationContext();
|
||||
app.getApplicationComponent().inject(this);
|
||||
if (!isInEditMode()) {
|
||||
BriarApplication app =
|
||||
(BriarApplication) context.getApplicationContext();
|
||||
app.getApplicationComponent().inject(this);
|
||||
}
|
||||
setOrientation(VERTICAL);
|
||||
setLayoutTransition(new LayoutTransition());
|
||||
inflateLayout(context);
|
||||
|
||||
@@ -49,7 +49,7 @@ public class UnreadMessageButton extends FrameLayout {
|
||||
setDirection(direction);
|
||||
attributes.recycle();
|
||||
|
||||
setUnreadCount(0);
|
||||
if (!isInEditMode()) setUnreadCount(0);
|
||||
}
|
||||
|
||||
private void setDirection(int direction) {
|
||||
@@ -64,11 +64,11 @@ public class UnreadMessageButton extends FrameLayout {
|
||||
|
||||
public void setUnreadCount(int count) {
|
||||
if (count == 0) {
|
||||
setVisibility(INVISIBLE);
|
||||
fab.hide();
|
||||
unread.setVisibility(INVISIBLE);
|
||||
} else {
|
||||
// FIXME: Use animations when upgrading to support library 24.2.0
|
||||
// https://code.google.com/p/android/issues/detail?id=216469
|
||||
setVisibility(VISIBLE);
|
||||
fab.show();
|
||||
unread.setVisibility(VISIBLE);
|
||||
unread.setText(String.valueOf(count));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -42,8 +43,8 @@ public class LinkDialogFragment extends DialogFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_link_dialog, container,
|
||||
false);
|
||||
|
||||
@@ -21,7 +21,6 @@ public interface AndroidNotificationManager {
|
||||
String PREF_NOTIFY_RINGTONE_NAME = "notifyRingtoneName";
|
||||
String PREF_NOTIFY_RINGTONE_URI = "notifyRingtoneUri";
|
||||
String PREF_NOTIFY_VIBRATION = "notifyVibration";
|
||||
String PREF_NOTIFY_LOCK_SCREEN = "notifyLockScreen";
|
||||
|
||||
// Notification IDs
|
||||
int ONGOING_NOTIFICATION_ID = 1;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.components.util;
|
||||
|
||||
public interface FutureTaskListener<V> {
|
||||
void onSuccess(V result);
|
||||
|
||||
void onFailure(Throwable error);
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.components.util;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ListenableFutureTask<V> extends FutureTask<V> {
|
||||
|
||||
private final List<FutureTaskListener<V>> listeners = new LinkedList<>();
|
||||
|
||||
@Nullable
|
||||
private final Object identifier;
|
||||
|
||||
public ListenableFutureTask(Callable<V> callable) {
|
||||
this(callable, null);
|
||||
}
|
||||
|
||||
private ListenableFutureTask(Callable<V> callable,
|
||||
@Nullable Object identifier) {
|
||||
super(callable);
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public ListenableFutureTask(V result) {
|
||||
this(result, null);
|
||||
}
|
||||
|
||||
private ListenableFutureTask(V result, @Nullable Object identifier) {
|
||||
super(() -> result);
|
||||
this.identifier = identifier;
|
||||
this.run();
|
||||
}
|
||||
|
||||
public synchronized void addListener(FutureTaskListener<V> listener) {
|
||||
if (this.isDone()) {
|
||||
callback(listener);
|
||||
} else {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void removeListener(FutureTaskListener<V> listener) {
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void done() {
|
||||
callback();
|
||||
}
|
||||
|
||||
private void callback() {
|
||||
for (FutureTaskListener<V> listener : listeners) {
|
||||
callback(listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void callback(FutureTaskListener<V> listener) {
|
||||
if (listener != null) {
|
||||
try {
|
||||
listener.onSuccess(get());
|
||||
} catch (InterruptedException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (ExecutionException e) {
|
||||
listener.onFailure(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other != null && other instanceof ListenableFutureTask &&
|
||||
this.identifier != null) {
|
||||
return identifier.equals(other);
|
||||
} else {
|
||||
return super.equals(other);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (identifier != null) return identifier.hashCode();
|
||||
else return super.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="@color/window_background"/>
|
||||
<solid android:color="@color/thread_item_background"/>
|
||||
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:width="@dimen/forum_nested_line_width"
|
||||
android:color="@color/thread_indicator"/>
|
||||
</shape>
|
||||
@@ -1,8 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zm4.24,-1.41L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<vector android:height="16dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="16dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zm4.24,-1.41L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zm4.24,-1.41L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
|
||||
</vector>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<vector android:height="16dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="16dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||
</vector>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:bottomRightRadius="@dimen/message_bubble_radius_big"
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_small"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_big"/>
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_top_inner"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_top_outer"/>
|
||||
<padding
|
||||
android:bottom="@dimen/message_bubble_padding_bottom"
|
||||
android:left="@dimen/message_bubble_padding_sides"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_small"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_big"/>
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_top_inner"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_top_outer"/>
|
||||
<padding
|
||||
android:bottom="@dimen/message_bubble_padding_top"
|
||||
android:left="@dimen/message_bubble_padding_sides"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:bottomRightRadius="@dimen/message_bubble_radius_big"
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_small"/>
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_top_outer"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_top_inner"/>
|
||||
<padding
|
||||
android:bottom="@dimen/message_bubble_padding_bottom"
|
||||
android:left="@dimen/message_bubble_padding_sides"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_small"/>
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_top_outer"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_top_inner"/>
|
||||
<padding
|
||||
android:bottom="@dimen/message_bubble_padding_top"
|
||||
android:left="@dimen/message_bubble_padding_sides"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:bottomRightRadius="@dimen/message_bubble_radius_big"
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_small"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_big"/>
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_top_inner"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_top_outer"/>
|
||||
<padding
|
||||
android:bottom="@dimen/message_bubble_padding_bottom"
|
||||
android:left="@dimen/message_bubble_padding_sides"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:bottomRightRadius="@dimen/message_bubble_radius_big"
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_big"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_small"/>
|
||||
android:topLeftRadius="@dimen/message_bubble_radius_top_outer"
|
||||
android:topRightRadius="@dimen/message_bubble_radius_top_inner"/>
|
||||
<padding
|
||||
android:bottom="@dimen/message_bubble_padding_bottom"
|
||||
android:left="@dimen/message_bubble_padding_sides"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="400dp"
|
||||
android:height="100dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportHeight="49.5"
|
||||
android:viewportWidth="194.8">
|
||||
<path
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
app:layout_constraintBottom_toBottomOf="@id/explanationText"
|
||||
app:layout_constraintEnd_toStartOf="@id/explanationText"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/explanationImage"
|
||||
@@ -34,8 +35,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:adjustViewBounds="true"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingEnd="@dimen/margin_large"
|
||||
android:paddingStart="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_large"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/qr_code_explanation"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".android.login.ChangePasswordActivity">
|
||||
|
||||
<RelativeLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
@@ -22,9 +22,11 @@
|
||||
android:id="@+id/current_password_entry_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:errorEnabled="true"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<EditText
|
||||
@@ -40,10 +42,11 @@
|
||||
android:id="@+id/new_password_entry_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/current_password_entry_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:errorEnabled="true"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/current_password_entry_wrapper"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<EditText
|
||||
@@ -59,10 +62,11 @@
|
||||
android:id="@+id/new_password_confirm_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/new_password_entry_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:errorEnabled="true"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/new_password_entry_wrapper"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<EditText
|
||||
@@ -79,30 +83,33 @@
|
||||
android:id="@+id/strength_meter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/new_password_confirm_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:visibility="invisible"/>
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/new_password_confirm_wrapper"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/change_password"
|
||||
style="@style/BriarButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/strength_meter"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:enabled="false"
|
||||
android:text="@string/change_password"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/strength_meter"
|
||||
tools:enabled="true"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_wheel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/change_password"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:visibility="invisible"/>
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/change_password"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
@@ -20,20 +20,23 @@
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<include layout="@layout/contact_avatar_status"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/contactName"
|
||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
|
||||
android:textColor="@color/action_bar_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:gravity="center"
|
||||
tools:text="Contact Name"/>
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textColor="@color/action_bar_text"
|
||||
tools:text="Contact Name of someone who chose a long name"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -1,186 +1,224 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/report_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible"
|
||||
tools:context=".android.reporting.DevReportActivity">
|
||||
tools:context=".android.reporting.DevReportActivity"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<include layout="@layout/toolbar"/>
|
||||
<include
|
||||
android:id="@+id/appBar"
|
||||
layout="@layout/toolbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/user_comment_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_large"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginRight="@dimen/margin_large"
|
||||
android:layout_marginStart="@dimen/margin_large">
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appBar">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/user_comment_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/user_comment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine|textCapSentences"
|
||||
tools:hint="@string/describe_crash"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/user_email_layout"
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/user_comment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/user_comment_layout"
|
||||
android:layout_marginTop="@dimen/margin_small">
|
||||
android:inputType="textMultiLine|textCapSentences"
|
||||
android:maxLines="5"
|
||||
tools:hint="@string/describe_crash"/>
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/user_email"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/optional_contact_email"
|
||||
android:inputType="textEmailAddress"
|
||||
android:maxLines="1"/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/user_email_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_large"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginRight="@dimen/margin_large"
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/user_comment_layout">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/include_debug_report"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@+id/user_email_layout"
|
||||
android:layout_marginTop="@dimen/margin_small"
|
||||
android:layout_toLeftOf="@+id/chevron"
|
||||
android:checked="false"
|
||||
android:text="@string/include_debug_report_crash"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/chevron"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignTop="@+id/include_debug_report"
|
||||
android:text="@string/show"/>
|
||||
|
||||
<ScrollView
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/user_email"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/include_debug_report"
|
||||
android:layout_marginTop="@dimen/margin_small">
|
||||
android:hint="@string/optional_contact_email"
|
||||
android:inputType="textEmailAddress"
|
||||
android:maxLines="1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/report_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/listitem_height_one_line_avatar"
|
||||
android:paddingEnd="@dimen/margin_large"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingStart="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_small"
|
||||
android:visibility="gone"/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
</ScrollView>
|
||||
<CheckBox
|
||||
android:id="@+id/include_debug_report"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
android:checked="false"
|
||||
android:text="@string/include_debug_report_crash"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/chevron"
|
||||
app:layout_constraintEnd_toStartOf="@+id/chevron"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/chevron"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_wheel"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
<Button
|
||||
android:id="@+id/chevron"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/show"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/user_email_layout"/>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/report_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/include_debug_report">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/report_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_below="@+id/include_debug_report"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"/>
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/listitem_height_one_line_avatar"
|
||||
android:paddingEnd="@dimen/margin_large"
|
||||
android:paddingStart="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_small"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<RelativeLayout
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_wheel"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/include_debug_report"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/request_report"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/margin_large"
|
||||
android:visibility="invisible">
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/crashed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:gravity="center"
|
||||
android:text="@string/briar_crashed"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_large"/>
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintBottom_toTopOf="@+id/fault"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:layout_editor_absoluteY="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fault"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/crashed"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:gravity="center"
|
||||
android:text="@string/not_your_fault"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_large"/>
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintBottom_toTopOf="@+id/pleaseSend"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/crashed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pleaseSend"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/fault"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:gravity="center"
|
||||
android:text="@string/please_send_report"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_large"/>
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintBottom_toTopOf="@+id/encrypted"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/fault"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/encrypted"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/pleaseSend"
|
||||
android:layout_marginBottom="@dimen/margin_large"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:gravity="center"
|
||||
android:text="@string/report_is_encrypted"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_large"/>
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintBottom_toTopOf="@+id/acceptButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pleaseSend"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/declineButton"
|
||||
style="@style/BriarButtonFlat.Negative"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@+id/encrypted"
|
||||
android:text="@string/close"/>
|
||||
android:text="@string/close"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/acceptButton"
|
||||
app:layout_constraintEnd_toStartOf="@+id/acceptButton"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/acceptButton"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/acceptButton"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/encrypted"
|
||||
android:text="@string/send_report"/>
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:text="@string/send_report"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toEndOf="@+id/declineButton"
|
||||
app:layout_constraintTop_toBottomOf="@+id/encrypted"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -2,57 +2,75 @@
|
||||
<android.support.v4.widget.DrawerLayout
|
||||
android:id="@+id/drawer_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".android.navdrawer.NavDrawerActivity">
|
||||
|
||||
<!-- The first child(root) is the content view -->
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/constraintLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/toolbar"/>
|
||||
<include
|
||||
android:id="@+id/appBar"
|
||||
layout="@layout/toolbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<RelativeLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/expiryWarning"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/briar_warning_background"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/margin_medium"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appBar"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/expiryWarningText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toLeftOf="@+id/expiryWarningClose"
|
||||
android:text="@plurals/expiry_warning"
|
||||
android:textColor="@color/briar_text_primary_inverse"
|
||||
android:textSize="@dimen/text_size_small"/>
|
||||
android:textSize="@dimen/text_size_small"
|
||||
app:layout_constraintEnd_toStartOf="@+id/expiryWarningClose"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/expiryWarningClose"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_height="0dp"
|
||||
android:contentDescription="@string/close"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_close"
|
||||
android:tint="@color/briar_text_tertiary_inverse"/>
|
||||
android:tint="@color/briar_text_tertiary_inverse"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/expiryWarning"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<!-- The second child is the menu -->
|
||||
<include
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:text="@string/startup_open_database"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
@@ -5,24 +5,20 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<RelativeLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/margin_activity_vertical"
|
||||
android:paddingEnd="@dimen/margin_activity_horizontal"
|
||||
android:paddingLeft="@dimen/margin_activity_horizontal"
|
||||
android:paddingRight="@dimen/margin_activity_horizontal"
|
||||
android:paddingStart="@dimen/margin_activity_horizontal"
|
||||
android:paddingTop="@dimen/margin_activity_vertical">
|
||||
android:padding="@dimen/margin_activity_vertical">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/password_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:errorEnabled="true"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<EditText
|
||||
@@ -40,31 +36,36 @@
|
||||
style="@style/BriarButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/password_layout"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:onClick="onSignInClick"
|
||||
android:text="@string/sign_in_button"/>
|
||||
android:text="@string/sign_in_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/password_layout"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_wheel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/btn_sign_in"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:visibility="invisible"/>
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/btn_sign_in"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/btn_sign_in"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/btn_sign_in"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:onClick="onForgottenPasswordClick"
|
||||
android:text="@string/forgotten_password"
|
||||
android:textColor="?android:attr/textColorLink"/>
|
||||
android:textColor="?android:attr/textColorLink"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_sign_in"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_small"
|
||||
android:padding="@dimen/margin_medium"
|
||||
tools:context=".android.blog.RssFeedImportActivity">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
@@ -35,7 +35,8 @@
|
||||
android:id="@+id/importButton"
|
||||
style="@style/BriarButton"
|
||||
android:enabled="false"
|
||||
android:text="@string/blogs_rss_feeds_import_button"/>
|
||||
android:text="@string/blogs_rss_feeds_import_button"
|
||||
tools:enabled="true"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
@@ -43,6 +44,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
@@ -1,178 +1,179 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:padding="@dimen/margin_medium"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<ScrollView
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:padding="8dp"
|
||||
tools:ignore="HardcodedText">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<TextView
|
||||
android:id="@+id/textViewContacts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of contacts"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewContacts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of contacts"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarContacts"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="49"
|
||||
android:progress="20"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textViewContactsSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewContacts"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarContacts"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="49"
|
||||
android:progress="20"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textViewContactsSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewContacts"/>
|
||||
<TextView
|
||||
android:id="@+id/textViewContactsSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarContacts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewContacts"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewContactsSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarContacts"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
<TextView
|
||||
android:id="@+id/textViewMessages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of messages per contact"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarContacts"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarMessages"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="20"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textViewMessagesSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewMessages"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewMessages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of messages per contact"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarContacts"/>
|
||||
<TextView
|
||||
android:id="@+id/textViewMessagesSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarMessages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewMessages"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarMessages"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="15"
|
||||
app:layout_constraintEnd_toStartOf="@+id/textViewMessagesSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewMessages"/>
|
||||
<TextView
|
||||
android:id="@+id/textViewBlogPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of blog posts"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarMessages"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewMessagesSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarMessages"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarBlogPosts"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="20"
|
||||
app:layout_constraintEnd_toStartOf="@+id/TextViewBlogPostsSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewBlogPosts"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewBlogPosts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of blog posts"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarMessages"/>
|
||||
<TextView
|
||||
android:id="@+id/TextViewBlogPostsSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarBlogPosts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewBlogPosts"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarBlogPosts"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="30"
|
||||
app:layout_constraintEnd_toStartOf="@+id/TextViewBlogPostsSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewBlogPosts"/>
|
||||
<TextView
|
||||
android:id="@+id/textViewForums"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of forums"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarBlogPosts"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/TextViewBlogPostsSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarBlogPosts"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarForums"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="5"
|
||||
app:layout_constraintEnd_toStartOf="@+id/TextViewForumsSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewForums"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewForums"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of forums"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarBlogPosts"/>
|
||||
<TextView
|
||||
android:id="@+id/TextViewForumsSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="5"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarForums"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewForums"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarForums"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="10"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="3"
|
||||
app:layout_constraintEnd_toStartOf="@+id/TextViewForumsSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewForums"/>
|
||||
<TextView
|
||||
android:id="@+id/textViewForumMessages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of forum messages"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarForums"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/TextViewForumsSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarForums"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarForumMessages"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="20"
|
||||
app:layout_constraintEnd_toStartOf="@+id/TextViewForumMessagesSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewForumMessages"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewForumMessages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:text="Number of forum messages"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarForums"/>
|
||||
<TextView
|
||||
android:id="@+id/TextViewForumMessagesSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarForumMessages"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewForumMessages"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekBarForumMessages"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="50"
|
||||
android:paddingTop="5dp"
|
||||
android:progress="30"
|
||||
app:layout_constraintEnd_toStartOf="@+id/TextViewForumMessagesSb"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewForumMessages"/>
|
||||
<Button
|
||||
android:id="@+id/buttonCreateTestData"
|
||||
style="@style/BriarButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:text="Create test data"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarForumMessages"
|
||||
app:layout_constraintVertical_bias="1.0"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/TextViewForumMessagesSb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="20"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/seekBarForumMessages"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonCreateTestData"
|
||||
style="@style/BriarButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:text="Create test data"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seekBarForumMessages"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</ScrollView>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</ScrollView>
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
android:id="@+id/upButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|right"
|
||||
android:layout_gravity="top|right|end"
|
||||
app:direction="up"/>
|
||||
|
||||
<org.briarproject.briar.android.view.UnreadMessageButton
|
||||
android:id="@+id/downButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_gravity="bottom|right|end"
|
||||
app:direction="down"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="bottom"
|
||||
app:buttonText="@string/blogs_publish_blog_post"
|
||||
app:hint="@string/blogs_write_blog_post_body_hint"
|
||||
app:fillHeight="true"/>
|
||||
app:fillHeight="true"
|
||||
app:hint="@string/blogs_write_blog_post_body_hint"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
android:id="@+id/merge"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:layout_height="wrap_content"
|
||||
tools:layout_width="match_parent"
|
||||
tools:parentTag="android.support.constraint.ConstraintLayout"
|
||||
tools:showIn="@layout/list_item_blog_post">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
@@ -9,54 +14,64 @@
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="@dimen/blogs_avatar_normal_size"
|
||||
android:layout_height="@dimen/blogs_avatar_normal_size"
|
||||
android:layout_alignTop="@+id/authorName"
|
||||
android:layout_marginRight="@dimen/margin_medium"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/authorName"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatarIcon"
|
||||
android:layout_width="@dimen/blogs_avatar_icon_size"
|
||||
android:layout_height="@dimen/blogs_avatar_icon_size"
|
||||
android:layout_alignBottom="@+id/avatar"
|
||||
android:layout_alignRight="@+id/avatar"
|
||||
android:background="@drawable/bubble_white"
|
||||
android:contentDescription="@string/blogs_reblog_button"
|
||||
android:padding="2dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_repeat"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="ContentDescription"/>
|
||||
app:layout_constraintBottom_toBottomOf="@+id/avatar"
|
||||
app:layout_constraintEnd_toEndOf="@+id/avatar"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/authorName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:layout_marginEnd="@dimen/margin_medium"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_marginRight="@dimen/margin_medium"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Author Name"/>
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/trustIndicator"
|
||||
app:layout_constraintStart_toEndOf="@+id/avatar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Author View that can have a long name"/>
|
||||
|
||||
<org.briarproject.briar.android.view.TrustIndicatorView
|
||||
android:id="@+id/trustIndicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/authorName"
|
||||
android:layout_alignTop="@+id/authorName"
|
||||
android:layout_marginLeft="@dimen/margin_small"
|
||||
android:layout_toRightOf="@id/authorName"
|
||||
android:scaleType="center"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/authorName"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/authorName"
|
||||
app:layout_constraintTop_toTopOf="@+id/authorName"
|
||||
app:layout_goneMarginEnd="0dp"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:src="@drawable/trust_indicator_verified"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dateView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/authorName"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:layout_toRightOf="@+id/avatar"
|
||||
android:gravity="bottom"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_tiny"
|
||||
tools:text="yesterday"/>
|
||||
app:layout_constraintStart_toStartOf="@+id/authorName"
|
||||
app:layout_constraintTop_toBottomOf="@+id/authorName"
|
||||
tools:text="yesterday"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</merge>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/relativeLayout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@@ -62,8 +61,6 @@
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintBottom_toTopOf="@+id/emptyAction"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/emptyImage"
|
||||
tools:text="@string/no_contacts"/>
|
||||
@@ -79,8 +76,6 @@
|
||||
android:textSize="@dimen/text_size_small"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/emptyText"
|
||||
tools:text="@string/no_contacts_action"/>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/margin_activity_horizontal"
|
||||
android:layout_marginStart="@dimen/margin_activity_horizontal"
|
||||
android:layout_marginTop="@dimen/margin_activity_vertical"
|
||||
android:checked="false"
|
||||
android:text="@string/don_t_ask_again"/>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
android:id="@+id/contactStatus"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_gravity="bottom|end|right"
|
||||
android:scaleType="fitCenter"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/contact_online"/>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_large">
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_large">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="wrap_content"
|
||||
@@ -13,7 +15,8 @@
|
||||
<TextView
|
||||
android:id="@+id/screen_filter_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/screen_filter_body"/>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
@@ -21,8 +24,8 @@
|
||||
android:id="@+id/screen_filter_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:layout_weight="0"
|
||||
android:text="@string/screen_filter_allow"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:descendantFocusability="beforeDescendants"
|
||||
android:focusable="true"
|
||||
@@ -17,7 +17,7 @@
|
||||
android:id="@+id/postLayout"
|
||||
style="@style/BriarCard"
|
||||
layout="@layout/list_item_blog_post"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<ProgressBar
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:src="@drawable/alerts_and_states_error"
|
||||
@@ -25,6 +27,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/sorry"
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingTop="@dimen/margin_large"
|
||||
tools:text="Connection failed"/>
|
||||
tools:text="@string/waiting_for_contact_to_scan"/>
|
||||
</LinearLayout>
|
||||
|
||||
<org.briarproject.briar.android.view.QrCodeView
|
||||
@@ -47,6 +47,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/white"/>
|
||||
android:background="@android:color/white"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -47,27 +48,28 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:layout_height="@dimen/button_size">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.5"
|
||||
android:text="@string/cancel"/>
|
||||
android:text="@string/cancel"
|
||||
app:layout_constraintEnd_toStartOf="@+id/openButton"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/openButton"
|
||||
style="@style/BriarButtonFlat.Negative"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.5"
|
||||
android:text="@string/link_warning_open_link"/>
|
||||
android:text="@string/link_warning_open_link"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/cancelButton"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -10,19 +10,13 @@
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_activity_vertical"
|
||||
android:paddingEnd="@dimen/margin_activity_horizontal"
|
||||
android:paddingLeft="@dimen/margin_activity_horizontal"
|
||||
android:paddingRight="@dimen/margin_activity_horizontal"
|
||||
android:paddingStart="@dimen/margin_activity_horizontal"
|
||||
android:paddingTop="@dimen/margin_activity_vertical">
|
||||
android:padding="@dimen/margin_activity_vertical">
|
||||
|
||||
<org.briarproject.briar.android.login.DozeView
|
||||
android:id="@+id/dozeView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
@@ -30,8 +24,8 @@
|
||||
android:id="@+id/huaweiView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dozeView"/>
|
||||
|
||||
<Button
|
||||
@@ -42,8 +36,8 @@
|
||||
android:enabled="false"
|
||||
android:text="@string/create_account_button"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/huaweiView"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:enabled="true"/>
|
||||
@@ -55,8 +49,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/next"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/next"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
@@ -7,113 +7,125 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarContact1"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_activity_horizontal"
|
||||
android:layout_margin="@dimen/margin_large"
|
||||
app:layout_constraintEnd_toStartOf="@+id/introductionIcon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/nameContact1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_large"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginRight="@dimen/margin_large"
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
app:layout_constraintEnd_toStartOf="@+id/introductionIcon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/avatarContact1"
|
||||
tools:text="Contact 1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top|center_horizontal"
|
||||
android:orientation="vertical">
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/introductionIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_large"
|
||||
android:src="@drawable/ic_contact_introduction"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/barrier"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/avatarContact2"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarContact1"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="@dimen/listitem_picture_size"
|
||||
android:layout_height="@dimen/listitem_picture_size"
|
||||
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginStart="@dimen/listitem_horizontal_margin"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarContact2"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_large"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/introductionIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/nameContact1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_small"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Contact 1"/>
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/nameContact2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_large"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginRight="@dimen/margin_large"
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/introductionIcon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/avatarContact2"
|
||||
tools:text="Contact 2 can have quite a long name"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/introductionIcon"
|
||||
android:layout_width="@dimen/listitem_picture_size"
|
||||
android:layout_height="@dimen/listitem_picture_size"
|
||||
android:src="@drawable/ic_contact_introduction"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top|center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarContact2"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="@dimen/listitem_picture_size"
|
||||
android:layout_height="@dimen/listitem_picture_size"
|
||||
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginStart="@dimen/listitem_horizontal_margin"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/nameContact2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_small"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Contact 2"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
<android.support.constraint.Barrier
|
||||
android:id="@+id/barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="nameContact1,nameContact2"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="@dimen/margin_large"
|
||||
app:layout_constraintBottom_toTopOf="@+id/introductionNotPossibleView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/barrier"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/introductionNotPossibleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_activity_horizontal"
|
||||
android:layout_margin="@dimen/margin_large"
|
||||
android:text="@string/introduction_not_possible"
|
||||
android:textSize="@dimen/text_size_large"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/progressBar"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.briarproject.briar.android.view.LargeTextInputView
|
||||
android:id="@+id/introductionMessageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:visibility="gone"
|
||||
app:buttonText="@string/introduction_button"
|
||||
app:hint="@string/introduction_message_hint"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/introductionNotPossibleView"
|
||||
app:maxLines="5"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</ScrollView>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@@ -9,27 +9,32 @@
|
||||
|
||||
<View
|
||||
android:id="@+id/inputDivider"
|
||||
style="@style/Divider.Horizontal"/>
|
||||
style="@style/Divider.Horizontal"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<org.briarproject.briar.android.view.AuthorView
|
||||
android:id="@+id/authorView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:padding="@dimen/listitem_vertical_margin"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:persona="commenter"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/bodyView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/authorView"
|
||||
android:paddingBottom="@dimen/listitem_vertical_margin"
|
||||
android:paddingLeft="@dimen/listitem_vertical_margin"
|
||||
android:paddingRight="@dimen/listitem_vertical_margin"
|
||||
android:paddingEnd="@dimen/listitem_vertical_margin"
|
||||
android:paddingStart="@dimen/listitem_vertical_margin"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/authorView"
|
||||
tools:text="This is a comment that appears below a blog post. Usually, it is expected to be rather short. Not much longer than this one."/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
@@ -9,63 +9,70 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
<org.briarproject.briar.android.view.AuthorView
|
||||
android:id="@+id/rebloggerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/listitem_vertical_margin">
|
||||
android:layout_marginBottom="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginRight="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginStart="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginTop="@dimen/listitem_vertical_margin"
|
||||
app:layout_constraintEnd_toStartOf="@+id/commentView"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:persona="reblogger"/>
|
||||
|
||||
<org.briarproject.briar.android.view.AuthorView
|
||||
android:id="@+id/rebloggerView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginBottom="@dimen/listitem_horizontal_margin"
|
||||
android:layout_toLeftOf="@+id/commentView"
|
||||
app:persona="reblogger"/>
|
||||
<org.briarproject.briar.android.view.AuthorView
|
||||
android:id="@+id/authorView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginLeft="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginRight="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginStart="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginTop="@dimen/listitem_vertical_margin"
|
||||
app:layout_constraintEnd_toStartOf="@+id/commentView"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rebloggerView"/>
|
||||
|
||||
<org.briarproject.briar.android.view.AuthorView
|
||||
android:id="@+id/authorView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@+id/rebloggerView"
|
||||
android:layout_marginBottom="@dimen/listitem_vertical_margin"
|
||||
android:layout_toLeftOf="@+id/commentView"/>
|
||||
<android.support.v7.widget.AppCompatImageButton
|
||||
android:id="@+id/commentView"
|
||||
android:layout_width="@dimen/button_size"
|
||||
android:layout_height="@dimen/button_size"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/blogs_reblog_comment_hint"
|
||||
android:src="@drawable/ic_repeat"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?attr/colorControlNormal"/>
|
||||
|
||||
<android.support.v7.widget.AppCompatImageButton
|
||||
android:id="@+id/commentView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/blogs_reblog_comment_hint"
|
||||
android:padding="@dimen/margin_small"
|
||||
android:src="@drawable/ic_repeat"
|
||||
app:tint="?attr/colorControlNormal"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/bodyView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/authorView"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
tools:text="This is a body text that shows the content of a blog post.\n\nThis one is not short, but it is also not too long."/>
|
||||
|
||||
</RelativeLayout>
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/bodyView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/listitem_vertical_margin"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/authorView"
|
||||
tools:text="This is a body text that shows the content of a blog post.\n\nThis one is not short, but it is also not too long."/>
|
||||
|
||||
<!-- TODO replace with RecyclerView -->
|
||||
<LinearLayout
|
||||
android:id="@+id/commentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_marginTop="@dimen/listitem_vertical_margin"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@+id/bodyView">
|
||||
|
||||
<include
|
||||
layout="@layout/list_item_blog_comment"
|
||||
@@ -74,6 +81,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
@@ -1,95 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/linearLayout4"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="vertical">
|
||||
android:focusable="true">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
<FrameLayout
|
||||
android:id="@+id/avatarFrameView"
|
||||
android:layout_width="@dimen/listitem_picture_frame_size"
|
||||
android:layout_height="@dimen/listitem_picture_frame_size"
|
||||
android:layout_margin="@dimen/listitem_horizontal_margin"
|
||||
app:layout_constraintBottom_toTopOf="@+id/divider"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarView"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="@dimen/listitem_picture_size"
|
||||
android:layout_height="@dimen/listitem_picture_size"
|
||||
android:layout_gravity="bottom|left|start"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/unreadCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/unread_bubble_size"
|
||||
android:background="@drawable/bubble"
|
||||
android:gravity="center"
|
||||
android:minWidth="@dimen/unread_bubble_size"
|
||||
android:textColor="@color/briar_text_primary_inverse"
|
||||
android:textSize="@dimen/unread_bubble_text_size"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="@+id/avatarFrameView"
|
||||
app:layout_constraintTop_toTopOf="@+id/avatarFrameView"
|
||||
tools:text="123"/>
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/nameView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/listitem_horizontal_margin"
|
||||
android:paddingTop="@dimen/listitem_horizontal_margin">
|
||||
android:layout_marginEnd="@dimen/margin_medium"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_marginRight="@dimen/margin_medium"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:layout_marginTop="@dimen/listitem_vertical_margin"
|
||||
android:paddingEnd="@dimen/margin_medium"
|
||||
android:paddingStart="@dimen/margin_medium"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/dateView"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bulbView"
|
||||
app:layout_constraintStart_toEndOf="@+id/avatarFrameView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="This is a name of a contact"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/avatarFrameView"
|
||||
android:layout_width="@dimen/listitem_picture_frame_size"
|
||||
android:layout_height="@dimen/listitem_picture_frame_size"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginStart="@dimen/listitem_horizontal_margin">
|
||||
<TextView
|
||||
android:id="@+id/dateView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/listitem_vertical_margin"
|
||||
android:layout_marginEnd="@dimen/margin_medium"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_marginRight="@dimen/margin_medium"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:paddingEnd="@dimen/margin_medium"
|
||||
android:paddingStart="@dimen/margin_medium"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
app:layout_constraintBottom_toTopOf="@+id/divider"
|
||||
app:layout_constraintEnd_toStartOf="@+id/bulbView"
|
||||
app:layout_constraintStart_toEndOf="@+id/avatarFrameView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/nameView"
|
||||
tools:text="Dec 24"/>
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarView"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="@dimen/listitem_picture_size"
|
||||
android:layout_height="@dimen/listitem_picture_size"
|
||||
android:layout_gravity="bottom|left"
|
||||
tools:src="@mipmap/ic_launcher_round"/>
|
||||
<ImageView
|
||||
android:id="@+id/bulbView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/listitem_horizontal_margin"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/contact_connected"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/unreadCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/unread_bubble_size"
|
||||
android:layout_gravity="right|top"
|
||||
android:background="@drawable/bubble"
|
||||
android:gravity="center"
|
||||
android:minWidth="@dimen/unread_bubble_size"
|
||||
android:textColor="@color/briar_text_primary_inverse"
|
||||
android:textSize="@dimen/unread_bubble_text_size"
|
||||
android:textStyle="bold"
|
||||
tools:text="123"/>
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
style="@style/Divider.ContactList"
|
||||
android:layout_width="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/nameView"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginStart="@dimen/listitem_horizontal_margin"
|
||||
android:layout_toEndOf="@+id/avatarFrameView"
|
||||
android:layout_toLeftOf="@+id/bulbView"
|
||||
android:layout_toRightOf="@+id/avatarFrameView"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/nameView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
tools:text="This is a name of a contact"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dateView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Dec 24"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bulbView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||
tools:src="@drawable/contact_connected"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View style="@style/Divider.ContactList"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
@@ -23,7 +23,9 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/margin_medium"
|
||||
android:layout_marginLeft="@dimen/margin_medium"
|
||||
android:layout_marginRight="@dimen/margin_medium"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="2"
|
||||
@@ -36,7 +38,9 @@
|
||||
android:layout_width="@dimen/listitem_horizontal_margin"
|
||||
android:layout_height="@dimen/listitem_horizontal_margin"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/contact_connected"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/message_bubble_margin"
|
||||
android:layout_marginEnd="@dimen/message_bubble_margin_non_tail"
|
||||
android:layout_marginLeft="@dimen/message_bubble_margin_tail"
|
||||
android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
|
||||
android:layout_marginStart="@dimen/message_bubble_margin_tail"
|
||||
android:layout_marginTop="@dimen/message_bubble_margin"
|
||||
android:background="@drawable/msg_in"
|
||||
android:elevation="@dimen/message_bubble_elevation"
|
||||
android:orientation="vertical">
|
||||
android:elevation="@dimen/message_bubble_elevation">
|
||||
|
||||
<com.vanniktech.emoji.EmojiTextView
|
||||
android:id="@+id/text"
|
||||
@@ -19,6 +21,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/time"
|
||||
app:layout_constraintEnd_toEndOf="@+id/time"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Short message"/>
|
||||
|
||||
<TextView
|
||||
@@ -26,8 +31,9 @@
|
||||
style="@style/TextMessage.Timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|end"
|
||||
android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text"
|
||||
tools:text="Dec 24, 13:37"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user