mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Compare commits
78 Commits
953-check-
...
beta-0.16.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
531e555b52 | ||
|
|
a9024aa34b | ||
|
|
d4e3b7842c | ||
|
|
167fddfbcc | ||
|
|
a48d642648 | ||
|
|
9a70f054c7 | ||
|
|
ca43d13bd6 | ||
|
|
5b71004179 | ||
|
|
63befccdbf | ||
|
|
4ecf7c02d0 | ||
|
|
f25badc18c | ||
|
|
6e931e9ba5 | ||
|
|
7e749124bf | ||
|
|
5822eb7808 | ||
|
|
7a7e086541 | ||
|
|
abab3167c2 | ||
|
|
8d08570568 | ||
|
|
2007078f13 | ||
|
|
dfb71a7978 | ||
|
|
480b0e3a03 | ||
|
|
8f8751f4ac | ||
|
|
de2ea112ee | ||
|
|
6f99a53fd9 | ||
|
|
a8a9b9032d | ||
|
|
6b15fb89de | ||
|
|
a711d6b8a1 | ||
|
|
5678f8aaa4 | ||
|
|
2fe37f6c26 | ||
|
|
a879747968 | ||
|
|
95e8fd7ee0 | ||
|
|
4416aaaa4c | ||
|
|
500d5f0efe | ||
|
|
fc8978fd90 | ||
|
|
73df126bd4 | ||
|
|
9146488c7d | ||
|
|
613a7fe376 | ||
|
|
ecb62f00d4 | ||
|
|
c4540a03cd | ||
|
|
3e31da99b5 | ||
|
|
098c1d0b1e | ||
|
|
178e908c86 | ||
|
|
ecf7cf14ae | ||
|
|
09e2a15a73 | ||
|
|
ab387860a6 | ||
|
|
f63fc94f2b | ||
|
|
41e5928cca | ||
|
|
8303175494 | ||
|
|
151eb6935b | ||
|
|
6a419c0c7b | ||
|
|
1795b32121 | ||
|
|
01971768ce | ||
|
|
ef7483ab01 | ||
|
|
527d11473d | ||
|
|
775dadc9a0 | ||
|
|
800b10a988 | ||
|
|
c977bf047d | ||
|
|
660a25f21d | ||
|
|
e7fd6d23af | ||
|
|
46982897f0 | ||
|
|
d24de68d64 | ||
|
|
7514c46a3f | ||
|
|
6632c0f8e3 | ||
|
|
79aafcda69 | ||
|
|
05af21e8dc | ||
|
|
0dc62cbbdc | ||
|
|
f3a084cfd2 | ||
|
|
8b32f82566 | ||
|
|
d598b6ed44 | ||
|
|
f5dc6f24b9 | ||
|
|
37454392da | ||
|
|
de7f9111d3 | ||
|
|
96d2889a6c | ||
|
|
f6412d1e9a | ||
|
|
b377cd6b1c | ||
|
|
f6cdbda5bb | ||
|
|
855c600a3e | ||
|
|
ea6e8303b0 | ||
|
|
d4934040d9 |
@@ -1,4 +1,4 @@
|
|||||||
image: registry.gitlab.com/fdroid/ci-images:client-latest
|
image: registry.gitlab.com/fdroid/ci-images-base:latest
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
|
|||||||
@@ -25,38 +25,38 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':bramble-core')
|
compile project(':bramble-core')
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: '*.jar')
|
||||||
provided 'javax.annotation:jsr250-api:1.0'
|
provided 'javax.annotation:jsr250-api:1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
def torBinaryDir = 'src/main/res/raw'
|
def torBinaryDir = 'src/main/res/raw'
|
||||||
|
|
||||||
task downloadTorGeoIp(type: Download) {
|
task downloadTorGeoIp(type: Download) {
|
||||||
src 'https://briarproject.org/build/geoip-2015-12-01.zip'
|
src 'https://briarproject.org/build/geoip-2017-05-02.zip'
|
||||||
dest "$torBinaryDir/geoip.zip"
|
dest "$torBinaryDir/geoip.zip"
|
||||||
onlyIfNewer true
|
onlyIfNewer true
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadTorBinaryArm(type: Download) {
|
task downloadTorBinaryArm(type: Download) {
|
||||||
src 'https://briarproject.org/build/tor-0.2.7.6-arm.zip'
|
src 'https://briarproject.org/build/tor-0.2.9.11-arm.zip'
|
||||||
dest "$torBinaryDir/tor_arm.zip"
|
dest "$torBinaryDir/tor_arm.zip"
|
||||||
onlyIfNewer true
|
onlyIfNewer true
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadTorBinaryArmPie(type: Download) {
|
task downloadTorBinaryArmPie(type: Download) {
|
||||||
src 'https://briarproject.org/build/tor-0.2.7.6-arm-pie.zip'
|
src 'https://briarproject.org/build/tor-0.2.9.11-arm-pie.zip'
|
||||||
dest "$torBinaryDir/tor_arm_pie.zip"
|
dest "$torBinaryDir/tor_arm_pie.zip"
|
||||||
onlyIfNewer true
|
onlyIfNewer true
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadTorBinaryX86(type: Download) {
|
task downloadTorBinaryX86(type: Download) {
|
||||||
src 'https://briarproject.org/build/tor-0.2.7.6-x86.zip'
|
src 'https://briarproject.org/build/tor-0.2.9.11-x86.zip'
|
||||||
dest "$torBinaryDir/tor_x86.zip"
|
dest "$torBinaryDir/tor_x86.zip"
|
||||||
onlyIfNewer true
|
onlyIfNewer true
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadTorBinaryX86Pie(type: Download) {
|
task downloadTorBinaryX86Pie(type: Download) {
|
||||||
src 'https://briarproject.org/build/tor-0.2.7.6-x86-pie.zip'
|
src 'https://briarproject.org/build/tor-0.2.9.11-x86-pie.zip'
|
||||||
dest "$torBinaryDir/tor_x86_pie.zip"
|
dest "$torBinaryDir/tor_x86_pie.zip"
|
||||||
onlyIfNewer true
|
onlyIfNewer true
|
||||||
}
|
}
|
||||||
@@ -64,31 +64,31 @@ task downloadTorBinaryX86Pie(type: Download) {
|
|||||||
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
|
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
|
||||||
src "$torBinaryDir/geoip.zip"
|
src "$torBinaryDir/geoip.zip"
|
||||||
algorithm 'SHA-256'
|
algorithm 'SHA-256'
|
||||||
checksum '9bcdaf0a7ba0933735328d8ec466c25c25dbb459efc2bce9e55c774eabea5162'
|
checksum '51f4d1272fb867e1f3b36b67a584e2a33c40b40f62305457d799fd399cd77c9b'
|
||||||
}
|
}
|
||||||
|
|
||||||
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
|
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
|
||||||
src "$torBinaryDir/tor_arm.zip"
|
src "$torBinaryDir/tor_arm.zip"
|
||||||
algorithm 'SHA-256'
|
algorithm 'SHA-256'
|
||||||
checksum '83272962eda701cd5d74d2418651c4ff0f0b1dff51f558a292d1a1c42bf12146'
|
checksum '1da6008663a8ad98b349e62acbbf42c379f65ec504fa467cb119c187cd5a4c6b'
|
||||||
}
|
}
|
||||||
|
|
||||||
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
|
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
|
||||||
src "$torBinaryDir/tor_arm_pie.zip"
|
src "$torBinaryDir/tor_arm_pie.zip"
|
||||||
algorithm 'SHA-256'
|
algorithm 'SHA-256'
|
||||||
checksum 'd0300d1e45de11ebb24ed62b9c492be9c2e88590b7822195ab38c7a76ffcf646'
|
checksum 'eb061f880829e05f104690ac744848133f2dacef04759d425a2cff0df32c271e'
|
||||||
}
|
}
|
||||||
|
|
||||||
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
|
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
|
||||||
src "$torBinaryDir/tor_x86.zip"
|
src "$torBinaryDir/tor_x86.zip"
|
||||||
algorithm 'SHA-256'
|
algorithm 'SHA-256'
|
||||||
checksum 'b8813d97b01ee1b9c9a4233c1b9bbe9f9f6b494ae6f9cbd84de8a3911911615e'
|
checksum 'f5308aff8303daca082f82227d02b51ddedba4ab1d1420739ada0427ae5dbb41'
|
||||||
}
|
}
|
||||||
|
|
||||||
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
|
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
|
||||||
src "$torBinaryDir/tor_x86_pie.zip"
|
src "$torBinaryDir/tor_x86_pie.zip"
|
||||||
algorithm 'SHA-256'
|
algorithm 'SHA-256'
|
||||||
checksum '9c66e765aa196dc089951a1b2140cc8290305c2fcbf365121f99e01a233baf4e'
|
checksum '889a6c81ac73d05d35ed610ca5a913cee44d333e4ae1749c2a107f2f7dd8197b'
|
||||||
}
|
}
|
||||||
|
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
|
|||||||
Binary file not shown.
@@ -7,12 +7,12 @@ apply plugin: 'witness'
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile "com.google.dagger:dagger:2.0.2"
|
compile "com.google.dagger:dagger:2.0.2"
|
||||||
compile 'com.google.dagger:dagger-compiler:2.0.2'
|
compile 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
compile 'com.google.code.findbugs:jsr305:3.0.1'
|
compile 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
testCompile "org.jmock:jmock:2.8.1"
|
testCompile "org.jmock:jmock:2.8.2"
|
||||||
testCompile "org.jmock:jmock-junit4:2.8.1"
|
testCompile "org.jmock:jmock-junit4:2.8.2"
|
||||||
testCompile "org.jmock:jmock-legacy:2.8.1"
|
testCompile "org.jmock:jmock-legacy:2.8.2"
|
||||||
testCompile "org.hamcrest:hamcrest-library:1.3"
|
testCompile "org.hamcrest:hamcrest-library:1.3"
|
||||||
testCompile "org.hamcrest:hamcrest-core:1.3"
|
testCompile "org.hamcrest:hamcrest-core:1.3"
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ dependencyVerification {
|
|||||||
verify = [
|
verify = [
|
||||||
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
'com.google.code.findbugs:jsr305:c885ce34249682bc0236b4a7d56efcc12048e6135a5baf7a9cde8ad8cda13fcd',
|
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||||
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
|
|||||||
@@ -137,7 +137,8 @@ public interface CryptoComponent {
|
|||||||
TransportKeys rotateTransportKeys(TransportKeys k, long rotationPeriod);
|
TransportKeys rotateTransportKeys(TransportKeys k, long rotationPeriod);
|
||||||
|
|
||||||
/** Encodes the pseudo-random tag that is used to recognise a stream. */
|
/** Encodes the pseudo-random tag that is used to recognise a stream. */
|
||||||
void encodeTag(byte[] tag, SecretKey tagKey, long streamNumber);
|
void encodeTag(byte[] tag, SecretKey tagKey, int protocolVersion,
|
||||||
|
long streamNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs the given byte[] with the given PrivateKey.
|
* Signs the given byte[] with the given PrivateKey.
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import org.briarproject.bramble.api.crypto.SecretKey;
|
|||||||
|
|
||||||
public interface TransportConstants {
|
public interface TransportConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current version of the transport protocol.
|
||||||
|
*/
|
||||||
|
int PROTOCOL_VERSION = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the pseudo-random tag in bytes.
|
* The length of the pseudo-random tag in bytes.
|
||||||
*/
|
*/
|
||||||
@@ -14,21 +19,22 @@ public interface TransportConstants {
|
|||||||
*/
|
*/
|
||||||
int STREAM_HEADER_NONCE_LENGTH = 24;
|
int STREAM_HEADER_NONCE_LENGTH = 24;
|
||||||
|
|
||||||
/**
|
|
||||||
* The length of the stream header initialisation vector (IV) in bytes.
|
|
||||||
*/
|
|
||||||
int STREAM_HEADER_IV_LENGTH = STREAM_HEADER_NONCE_LENGTH - 8;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the message authentication code (MAC) in bytes.
|
* The length of the message authentication code (MAC) in bytes.
|
||||||
*/
|
*/
|
||||||
int MAC_LENGTH = 16;
|
int MAC_LENGTH = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The length of the stream header plaintext in bytes. The stream header
|
||||||
|
* contains the protocol version, stream number and frame key.
|
||||||
|
*/
|
||||||
|
int STREAM_HEADER_PLAINTEXT_LENGTH = 2 + 8 + SecretKey.LENGTH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the stream header in bytes.
|
* The length of the stream header in bytes.
|
||||||
*/
|
*/
|
||||||
int STREAM_HEADER_LENGTH = STREAM_HEADER_IV_LENGTH + SecretKey.LENGTH
|
int STREAM_HEADER_LENGTH = STREAM_HEADER_NONCE_LENGTH
|
||||||
+ MAC_LENGTH;
|
+ STREAM_HEADER_PLAINTEXT_LENGTH + MAC_LENGTH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the frame nonce in bytes.
|
* The length of the frame nonce in bytes.
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id 'java'
|
||||||
id "net.ltgt.apt" version "0.9"
|
id 'net.ltgt.apt' version '0.9'
|
||||||
id "idea"
|
id 'idea'
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = 1.6
|
sourceCompatibility = 1.6
|
||||||
targetCompatibility = 1.6
|
targetCompatibility = 1.6
|
||||||
|
|
||||||
@@ -10,17 +11,18 @@ apply plugin: 'witness'
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':bramble-api')
|
compile project(':bramble-api')
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
compile 'com.madgag.spongycastle:core:1.56.0.0'
|
||||||
compile 'com.madgag.spongycastle:core:1.54.0.0'
|
compile 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
|
||||||
compile 'com.h2database:h2:1.4.190'
|
compile 'org.bitlet:weupnp:0.1.4'
|
||||||
|
|
||||||
testCompile project(path: ':bramble-api', configuration: 'testOutput')
|
testCompile project(path: ':bramble-api', configuration: 'testOutput')
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.madgag.spongycastle:core:1e7fa4b19ccccd1011364ab838d0b4702470c178bbbdd94c5c90b2d4d749ea1e',
|
'com.madgag.spongycastle:core:5e791b0eaa9e0c4594231b44f616a52adddb7dccedeb0ad9ad74887e19499a23',
|
||||||
'com.h2database:h2:23ba495a07bbbb3bd6c3084d10a96dad7a23741b8b6d64b213459a784195a98c'
|
'com.h2database:h2:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
|
||||||
|
'org.bitlet:weupnp:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -54,6 +54,7 @@ public class BrambleCoreModule {
|
|||||||
c.inject(new IdentityModule.EagerSingletons());
|
c.inject(new IdentityModule.EagerSingletons());
|
||||||
c.inject(new LifecycleModule.EagerSingletons());
|
c.inject(new LifecycleModule.EagerSingletons());
|
||||||
c.inject(new PluginModule.EagerSingletons());
|
c.inject(new PluginModule.EagerSingletons());
|
||||||
|
c.inject(new PropertiesModule.EagerSingletons());
|
||||||
c.inject(new SyncModule.EagerSingletons());
|
c.inject(new SyncModule.EagerSingletons());
|
||||||
c.inject(new SystemModule.EagerSingletons());
|
c.inject(new SystemModule.EagerSingletons());
|
||||||
c.inject(new TransportModule.EagerSingletons());
|
c.inject(new TransportModule.EagerSingletons());
|
||||||
|
|||||||
@@ -45,8 +45,10 @@ import static org.briarproject.bramble.api.invitation.InvitationConstants.CODE_B
|
|||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
|
import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
|
||||||
|
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
||||||
|
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
|
|
||||||
class CryptoComponentImpl implements CryptoComponent {
|
class CryptoComponentImpl implements CryptoComponent {
|
||||||
@@ -412,8 +414,11 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encodeTag(byte[] tag, SecretKey tagKey, long streamNumber) {
|
public void encodeTag(byte[] tag, SecretKey tagKey, int protocolVersion,
|
||||||
|
long streamNumber) {
|
||||||
if (tag.length < TAG_LENGTH) throw new IllegalArgumentException();
|
if (tag.length < TAG_LENGTH) throw new IllegalArgumentException();
|
||||||
|
if (protocolVersion < 0 || protocolVersion > MAX_16_BIT_UNSIGNED)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
if (streamNumber < 0 || streamNumber > MAX_32_BIT_UNSIGNED)
|
if (streamNumber < 0 || streamNumber > MAX_32_BIT_UNSIGNED)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
// Initialise the PRF
|
// Initialise the PRF
|
||||||
@@ -421,10 +426,14 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
// The output of the PRF must be long enough to use as a tag
|
// The output of the PRF must be long enough to use as a tag
|
||||||
int macLength = prf.getDigestSize();
|
int macLength = prf.getDigestSize();
|
||||||
if (macLength < TAG_LENGTH) throw new IllegalStateException();
|
if (macLength < TAG_LENGTH) throw new IllegalStateException();
|
||||||
// The input is the stream number as a 64-bit integer
|
// The input is the protocol version as a 16-bit integer, followed by
|
||||||
byte[] input = new byte[INT_64_BYTES];
|
// the stream number as a 64-bit integer
|
||||||
ByteUtils.writeUint64(streamNumber, input, 0);
|
byte[] protocolVersionBytes = new byte[INT_16_BYTES];
|
||||||
prf.update(input, 0, input.length);
|
ByteUtils.writeUint16(protocolVersion, protocolVersionBytes, 0);
|
||||||
|
prf.update(protocolVersionBytes, 0, protocolVersionBytes.length);
|
||||||
|
byte[] streamNumberBytes = new byte[INT_64_BYTES];
|
||||||
|
ByteUtils.writeUint64(streamNumber, streamNumberBytes, 0);
|
||||||
|
prf.update(streamNumberBytes, 0, streamNumberBytes.length);
|
||||||
byte[] mac = new byte[macLength];
|
byte[] mac = new byte[macLength];
|
||||||
prf.doFinal(mac, 0);
|
prf.doFinal(mac, 0);
|
||||||
// The output is the first TAG_LENGTH bytes of the MAC
|
// The output is the first TAG_LENGTH bytes of the MAC
|
||||||
|
|||||||
@@ -20,9 +20,11 @@ import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NO
|
|||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_PLAINTEXT_LENGTH;
|
||||||
|
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@@ -117,7 +119,7 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
|||||||
|
|
||||||
private void readStreamHeader() throws IOException {
|
private void readStreamHeader() throws IOException {
|
||||||
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
||||||
byte[] streamHeaderPlaintext = new byte[SecretKey.LENGTH];
|
byte[] streamHeaderPlaintext = new byte[STREAM_HEADER_PLAINTEXT_LENGTH];
|
||||||
// Read the stream header
|
// Read the stream header
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
while (offset < STREAM_HEADER_LENGTH) {
|
while (offset < STREAM_HEADER_LENGTH) {
|
||||||
@@ -126,21 +128,35 @@ class StreamDecrypterImpl implements StreamDecrypter {
|
|||||||
if (read == -1) throw new EOFException();
|
if (read == -1) throw new EOFException();
|
||||||
offset += read;
|
offset += read;
|
||||||
}
|
}
|
||||||
// The nonce consists of the stream number followed by the IV
|
// Extract the nonce
|
||||||
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
||||||
ByteUtils.writeUint64(streamNumber, streamHeaderNonce, 0);
|
System.arraycopy(streamHeaderCiphertext, 0, streamHeaderNonce, 0,
|
||||||
System.arraycopy(streamHeaderCiphertext, 0, streamHeaderNonce,
|
STREAM_HEADER_NONCE_LENGTH);
|
||||||
INT_64_BYTES, STREAM_HEADER_IV_LENGTH);
|
|
||||||
// Decrypt and authenticate the stream header
|
// Decrypt and authenticate the stream header
|
||||||
try {
|
try {
|
||||||
cipher.init(false, streamHeaderKey, streamHeaderNonce);
|
cipher.init(false, streamHeaderKey, streamHeaderNonce);
|
||||||
int decrypted = cipher.process(streamHeaderCiphertext,
|
int decrypted = cipher.process(streamHeaderCiphertext,
|
||||||
STREAM_HEADER_IV_LENGTH, SecretKey.LENGTH + MAC_LENGTH,
|
STREAM_HEADER_NONCE_LENGTH,
|
||||||
|
STREAM_HEADER_PLAINTEXT_LENGTH + MAC_LENGTH,
|
||||||
streamHeaderPlaintext, 0);
|
streamHeaderPlaintext, 0);
|
||||||
if (decrypted != SecretKey.LENGTH) throw new RuntimeException();
|
if (decrypted != STREAM_HEADER_PLAINTEXT_LENGTH)
|
||||||
|
throw new RuntimeException();
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
frameKey = new SecretKey(streamHeaderPlaintext);
|
// Check the protocol version
|
||||||
|
int receivedProtocolVersion =
|
||||||
|
ByteUtils.readUint16(streamHeaderPlaintext, 0);
|
||||||
|
if (receivedProtocolVersion != PROTOCOL_VERSION)
|
||||||
|
throw new FormatException();
|
||||||
|
// Check the stream number
|
||||||
|
long receivedStreamNumber = ByteUtils.readUint64(streamHeaderPlaintext,
|
||||||
|
INT_16_BYTES);
|
||||||
|
if (receivedStreamNumber != streamNumber) throw new FormatException();
|
||||||
|
// Extract the frame key
|
||||||
|
byte[] frameKeyBytes = new byte[SecretKey.LENGTH];
|
||||||
|
System.arraycopy(streamHeaderPlaintext, INT_16_BYTES + INT_64_BYTES,
|
||||||
|
frameKeyBytes, 0, SecretKey.LENGTH);
|
||||||
|
frameKey = new SecretKey(frameKeyBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,8 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@@ -36,22 +37,22 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory {
|
|||||||
AuthenticatedCipher cipher = cipherProvider.get();
|
AuthenticatedCipher cipher = cipherProvider.get();
|
||||||
long streamNumber = ctx.getStreamNumber();
|
long streamNumber = ctx.getStreamNumber();
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(tag, ctx.getTagKey(), streamNumber);
|
crypto.encodeTag(tag, ctx.getTagKey(), PROTOCOL_VERSION, streamNumber);
|
||||||
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
||||||
crypto.getSecureRandom().nextBytes(streamHeaderIv);
|
crypto.getSecureRandom().nextBytes(streamHeaderNonce);
|
||||||
SecretKey frameKey = crypto.generateSecretKey();
|
SecretKey frameKey = crypto.generateSecretKey();
|
||||||
return new StreamEncrypterImpl(out, cipher, streamNumber, tag,
|
return new StreamEncrypterImpl(out, cipher, streamNumber, tag,
|
||||||
streamHeaderIv, ctx.getHeaderKey(), frameKey);
|
streamHeaderNonce, ctx.getHeaderKey(), frameKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamEncrypter createInvitationStreamEncrypter(OutputStream out,
|
public StreamEncrypter createInvitationStreamEncrypter(OutputStream out,
|
||||||
SecretKey headerKey) {
|
SecretKey headerKey) {
|
||||||
AuthenticatedCipher cipher = cipherProvider.get();
|
AuthenticatedCipher cipher = cipherProvider.get();
|
||||||
byte[] streamHeaderIv = new byte[STREAM_HEADER_IV_LENGTH];
|
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
||||||
crypto.getSecureRandom().nextBytes(streamHeaderIv);
|
crypto.getSecureRandom().nextBytes(streamHeaderNonce);
|
||||||
SecretKey frameKey = crypto.generateSecretKey();
|
SecretKey frameKey = crypto.generateSecretKey();
|
||||||
return new StreamEncrypterImpl(out, cipher, 0, null, streamHeaderIv,
|
return new StreamEncrypterImpl(out, cipher, 0, null, streamHeaderNonce,
|
||||||
headerKey, frameKey);
|
headerKey, frameKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NO
|
|||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_PLAINTEXT_LENGTH;
|
||||||
|
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@@ -33,7 +35,7 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
|||||||
private final long streamNumber;
|
private final long streamNumber;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final byte[] tag;
|
private final byte[] tag;
|
||||||
private final byte[] streamHeaderIv;
|
private final byte[] streamHeaderNonce;
|
||||||
private final byte[] frameNonce, frameHeader;
|
private final byte[] frameNonce, frameHeader;
|
||||||
private final byte[] framePlaintext, frameCiphertext;
|
private final byte[] framePlaintext, frameCiphertext;
|
||||||
|
|
||||||
@@ -41,13 +43,13 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
|||||||
private boolean writeTag, writeStreamHeader;
|
private boolean writeTag, writeStreamHeader;
|
||||||
|
|
||||||
StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
|
StreamEncrypterImpl(OutputStream out, AuthenticatedCipher cipher,
|
||||||
long streamNumber, @Nullable byte[] tag, byte[] streamHeaderIv,
|
long streamNumber, @Nullable byte[] tag, byte[] streamHeaderNonce,
|
||||||
SecretKey streamHeaderKey, SecretKey frameKey) {
|
SecretKey streamHeaderKey, SecretKey frameKey) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.cipher = cipher;
|
this.cipher = cipher;
|
||||||
this.streamNumber = streamNumber;
|
this.streamNumber = streamNumber;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.streamHeaderIv = streamHeaderIv;
|
this.streamHeaderNonce = streamHeaderNonce;
|
||||||
this.streamHeaderKey = streamHeaderKey;
|
this.streamHeaderKey = streamHeaderKey;
|
||||||
this.frameKey = frameKey;
|
this.frameKey = frameKey;
|
||||||
frameNonce = new byte[FRAME_NONCE_LENGTH];
|
frameNonce = new byte[FRAME_NONCE_LENGTH];
|
||||||
@@ -114,22 +116,23 @@ class StreamEncrypterImpl implements StreamEncrypter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeStreamHeader() throws IOException {
|
private void writeStreamHeader() throws IOException {
|
||||||
// The nonce consists of the stream number followed by the IV
|
// The header contains the protocol version, stream number and frame key
|
||||||
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
|
byte[] streamHeaderPlaintext = new byte[STREAM_HEADER_PLAINTEXT_LENGTH];
|
||||||
ByteUtils.writeUint64(streamNumber, streamHeaderNonce, 0);
|
ByteUtils.writeUint16(PROTOCOL_VERSION, streamHeaderPlaintext, 0);
|
||||||
System.arraycopy(streamHeaderIv, 0, streamHeaderNonce, INT_64_BYTES,
|
ByteUtils.writeUint64(streamNumber, streamHeaderPlaintext,
|
||||||
STREAM_HEADER_IV_LENGTH);
|
INT_16_BYTES);
|
||||||
byte[] streamHeaderPlaintext = frameKey.getBytes();
|
System.arraycopy(frameKey.getBytes(), 0, streamHeaderPlaintext,
|
||||||
|
INT_16_BYTES + INT_64_BYTES, SecretKey.LENGTH);
|
||||||
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
|
||||||
System.arraycopy(streamHeaderIv, 0, streamHeaderCiphertext, 0,
|
System.arraycopy(streamHeaderNonce, 0, streamHeaderCiphertext, 0,
|
||||||
STREAM_HEADER_IV_LENGTH);
|
STREAM_HEADER_NONCE_LENGTH);
|
||||||
// Encrypt and authenticate the frame key
|
// Encrypt and authenticate the stream header key
|
||||||
try {
|
try {
|
||||||
cipher.init(true, streamHeaderKey, streamHeaderNonce);
|
cipher.init(true, streamHeaderKey, streamHeaderNonce);
|
||||||
int encrypted = cipher.process(streamHeaderPlaintext, 0,
|
int encrypted = cipher.process(streamHeaderPlaintext, 0,
|
||||||
SecretKey.LENGTH, streamHeaderCiphertext,
|
STREAM_HEADER_PLAINTEXT_LENGTH, streamHeaderCiphertext,
|
||||||
STREAM_HEADER_IV_LENGTH);
|
STREAM_HEADER_NONCE_LENGTH);
|
||||||
if (encrypted != SecretKey.LENGTH + MAC_LENGTH)
|
if (encrypted != STREAM_HEADER_PLAINTEXT_LENGTH + MAC_LENGTH)
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
} catch (GeneralSecurityException badCipher) {
|
} catch (GeneralSecurityException badCipher) {
|
||||||
throw new RuntimeException(badCipher);
|
throw new RuntimeException(badCipher);
|
||||||
|
|||||||
@@ -70,25 +70,7 @@ class XSalsa20Poly1305AuthenticatedCipher implements AuthenticatedCipher {
|
|||||||
byte[] subKey = new byte[SUBKEY_LENGTH];
|
byte[] subKey = new byte[SUBKEY_LENGTH];
|
||||||
xSalsa20Engine.processBytes(zero, 0, SUBKEY_LENGTH, subKey, 0);
|
xSalsa20Engine.processBytes(zero, 0, SUBKEY_LENGTH, subKey, 0);
|
||||||
|
|
||||||
// Reverse the order of the Poly130 subkey
|
// Clamp the subkey
|
||||||
//
|
|
||||||
// NaCl and libsodium use the first 32 bytes of XSalsa20 as the
|
|
||||||
// subkey for crypto_onetimeauth_poly1305, which interprets it
|
|
||||||
// as r[0] ... r[15], k[0] ... k[15]. See section 9 of the NaCl
|
|
||||||
// paper (http://cr.yp.to/highspeed/naclcrypto-20090310.pdf),
|
|
||||||
// where the XSalsa20 output is defined as (r, s, t, ...).
|
|
||||||
//
|
|
||||||
// BC's Poly1305 implementation interprets the subkey as
|
|
||||||
// k[0] ... k[15], r[0] ... r[15] (per poly1305_aes_clamp in
|
|
||||||
// the reference implementation).
|
|
||||||
//
|
|
||||||
// To be NaCl-compatible, we reverse the subkey.
|
|
||||||
System.arraycopy(subKey, 0, zero, 0, SUBKEY_LENGTH / 2);
|
|
||||||
System.arraycopy(subKey, SUBKEY_LENGTH / 2, subKey, 0,
|
|
||||||
SUBKEY_LENGTH / 2);
|
|
||||||
System.arraycopy(zero, 0, subKey, SUBKEY_LENGTH / 2,
|
|
||||||
SUBKEY_LENGTH / 2);
|
|
||||||
// Now we can clamp the correct part of the subkey
|
|
||||||
Poly1305KeyGenerator.clamp(subKey);
|
Poly1305KeyGenerator.clamp(subKey);
|
||||||
|
|
||||||
// Initialize Poly1305 with the subkey
|
// Initialize Poly1305 with the subkey
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
|
|
||||||
@@ -126,7 +127,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
for (long streamNumber : inKeys.getWindow().getUnseen()) {
|
for (long streamNumber : inKeys.getWindow().getUnseen()) {
|
||||||
TagContext tagCtx = new TagContext(c, inKeys, streamNumber);
|
TagContext tagCtx = new TagContext(c, inKeys, streamNumber);
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(tag, inKeys.getTagKey(), streamNumber);
|
crypto.encodeTag(tag, inKeys.getTagKey(), PROTOCOL_VERSION,
|
||||||
|
streamNumber);
|
||||||
inContexts.put(new Bytes(tag), tagCtx);
|
inContexts.put(new Bytes(tag), tagCtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +244,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
// Add tags for any stream numbers added to the window
|
// Add tags for any stream numbers added to the window
|
||||||
for (long streamNumber : change.getAdded()) {
|
for (long streamNumber : change.getAdded()) {
|
||||||
byte[] addTag = new byte[TAG_LENGTH];
|
byte[] addTag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(addTag, inKeys.getTagKey(), streamNumber);
|
crypto.encodeTag(addTag, inKeys.getTagKey(), PROTOCOL_VERSION,
|
||||||
|
streamNumber);
|
||||||
inContexts.put(new Bytes(addTag), new TagContext(
|
inContexts.put(new Bytes(addTag), new TagContext(
|
||||||
tagCtx.contactId, inKeys, streamNumber));
|
tagCtx.contactId, inKeys, streamNumber));
|
||||||
}
|
}
|
||||||
@@ -250,7 +253,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
for (long streamNumber : change.getRemoved()) {
|
for (long streamNumber : change.getRemoved()) {
|
||||||
if (streamNumber == tagCtx.streamNumber) continue;
|
if (streamNumber == tagCtx.streamNumber) continue;
|
||||||
byte[] removeTag = new byte[TAG_LENGTH];
|
byte[] removeTag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(removeTag, inKeys.getTagKey(), streamNumber);
|
crypto.encodeTag(removeTag, inKeys.getTagKey(),
|
||||||
|
PROTOCOL_VERSION, streamNumber);
|
||||||
inContexts.remove(new Bytes(removeTag));
|
inContexts.remove(new Bytes(removeTag));
|
||||||
}
|
}
|
||||||
// Write the window back to the DB
|
// Write the window back to the DB
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import static junit.framework.Assert.assertEquals;
|
|||||||
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
@@ -22,7 +23,8 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
private final AuthenticatedCipher cipher;
|
private final AuthenticatedCipher cipher;
|
||||||
private final SecretKey streamHeaderKey, frameKey;
|
private final SecretKey streamHeaderKey, frameKey;
|
||||||
private final byte[] streamHeaderIv, payload;
|
private final byte[] streamHeaderNonce, protocolVersionBytes;
|
||||||
|
private final byte[] streamNumberBytes, payload;
|
||||||
private final int payloadLength = 123, paddingLength = 234;
|
private final int payloadLength = 123, paddingLength = 234;
|
||||||
private final long streamNumber = 1234;
|
private final long streamNumber = 1234;
|
||||||
|
|
||||||
@@ -30,7 +32,12 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
cipher = new TestAuthenticatedCipher(); // Null cipher
|
cipher = new TestAuthenticatedCipher(); // Null cipher
|
||||||
streamHeaderKey = TestUtils.getSecretKey();
|
streamHeaderKey = TestUtils.getSecretKey();
|
||||||
frameKey = TestUtils.getSecretKey();
|
frameKey = TestUtils.getSecretKey();
|
||||||
streamHeaderIv = TestUtils.getRandomBytes(STREAM_HEADER_IV_LENGTH);
|
streamHeaderNonce =
|
||||||
|
TestUtils.getRandomBytes(STREAM_HEADER_NONCE_LENGTH);
|
||||||
|
protocolVersionBytes = new byte[2];
|
||||||
|
ByteUtils.writeUint16(PROTOCOL_VERSION, protocolVersionBytes, 0);
|
||||||
|
streamNumberBytes = new byte[8];
|
||||||
|
ByteUtils.writeUint64(streamNumber, streamNumberBytes, 0);
|
||||||
payload = TestUtils.getRandomBytes(payloadLength);
|
payload = TestUtils.getRandomBytes(payloadLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +54,9 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(protocolVersionBytes);
|
||||||
|
out.write(streamNumberBytes);
|
||||||
out.write(frameKey.getBytes());
|
out.write(frameKey.getBytes());
|
||||||
out.write(new byte[MAC_LENGTH]);
|
out.write(new byte[MAC_LENGTH]);
|
||||||
out.write(frameHeader);
|
out.write(frameHeader);
|
||||||
@@ -76,6 +85,85 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
assertEquals(-1, s.readFrame(buffer));
|
assertEquals(-1, s.readFrame(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IOException.class)
|
||||||
|
public void testWrongProtocolVersionThrowsException() throws Exception {
|
||||||
|
byte[] wrongProtocolVersionBytes = new byte[2];
|
||||||
|
ByteUtils.writeUint16(PROTOCOL_VERSION + 1, wrongProtocolVersionBytes,
|
||||||
|
0);
|
||||||
|
|
||||||
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
|
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
||||||
|
paddingLength);
|
||||||
|
|
||||||
|
byte[] frameHeader1 = new byte[FRAME_HEADER_LENGTH];
|
||||||
|
int payloadLength1 = 345, paddingLength1 = 456;
|
||||||
|
FrameEncoder.encodeHeader(frameHeader1, true, payloadLength1,
|
||||||
|
paddingLength1);
|
||||||
|
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(wrongProtocolVersionBytes);
|
||||||
|
out.write(streamNumberBytes);
|
||||||
|
out.write(frameKey.getBytes());
|
||||||
|
out.write(new byte[MAC_LENGTH]);
|
||||||
|
out.write(frameHeader);
|
||||||
|
out.write(payload);
|
||||||
|
out.write(new byte[paddingLength]);
|
||||||
|
out.write(new byte[MAC_LENGTH]);
|
||||||
|
out.write(frameHeader1);
|
||||||
|
out.write(payload1);
|
||||||
|
out.write(new byte[paddingLength1]);
|
||||||
|
out.write(new byte[MAC_LENGTH]);
|
||||||
|
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
|
// Try to read the first frame
|
||||||
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
|
s.readFrame(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IOException.class)
|
||||||
|
public void testWrongStreamNumberThrowsException() throws Exception {
|
||||||
|
byte[] wrongStreamNumberBytes = new byte[8];
|
||||||
|
ByteUtils.writeUint64(streamNumber + 1, wrongStreamNumberBytes, 0);
|
||||||
|
|
||||||
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
|
FrameEncoder.encodeHeader(frameHeader, false, payloadLength,
|
||||||
|
paddingLength);
|
||||||
|
|
||||||
|
byte[] frameHeader1 = new byte[FRAME_HEADER_LENGTH];
|
||||||
|
int payloadLength1 = 345, paddingLength1 = 456;
|
||||||
|
FrameEncoder.encodeHeader(frameHeader1, true, payloadLength1,
|
||||||
|
paddingLength1);
|
||||||
|
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(protocolVersionBytes);
|
||||||
|
out.write(wrongStreamNumberBytes);
|
||||||
|
out.write(frameKey.getBytes());
|
||||||
|
out.write(new byte[MAC_LENGTH]);
|
||||||
|
out.write(frameHeader);
|
||||||
|
out.write(payload);
|
||||||
|
out.write(new byte[paddingLength]);
|
||||||
|
out.write(new byte[MAC_LENGTH]);
|
||||||
|
out.write(frameHeader1);
|
||||||
|
out.write(payload1);
|
||||||
|
out.write(new byte[paddingLength1]);
|
||||||
|
out.write(new byte[MAC_LENGTH]);
|
||||||
|
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
|
StreamDecrypterImpl s = new StreamDecrypterImpl(in, cipher,
|
||||||
|
streamNumber, streamHeaderKey);
|
||||||
|
|
||||||
|
// Try to read the first frame
|
||||||
|
byte[] buffer = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
|
s.readFrame(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IOException.class)
|
@Test(expected = IOException.class)
|
||||||
public void testTruncatedFrameThrowsException() throws Exception {
|
public void testTruncatedFrameThrowsException() throws Exception {
|
||||||
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] frameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -83,7 +171,9 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
paddingLength);
|
paddingLength);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(protocolVersionBytes);
|
||||||
|
out.write(streamNumberBytes);
|
||||||
out.write(frameKey.getBytes());
|
out.write(frameKey.getBytes());
|
||||||
out.write(new byte[MAC_LENGTH]);
|
out.write(new byte[MAC_LENGTH]);
|
||||||
out.write(frameHeader);
|
out.write(frameHeader);
|
||||||
@@ -111,7 +201,9 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
byte[] payload = TestUtils.getRandomBytes(payloadLength);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(protocolVersionBytes);
|
||||||
|
out.write(streamNumberBytes);
|
||||||
out.write(frameKey.getBytes());
|
out.write(frameKey.getBytes());
|
||||||
out.write(new byte[MAC_LENGTH]);
|
out.write(new byte[MAC_LENGTH]);
|
||||||
out.write(frameHeader);
|
out.write(frameHeader);
|
||||||
@@ -138,7 +230,9 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
padding[paddingLength - 1] = 1;
|
padding[paddingLength - 1] = 1;
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(protocolVersionBytes);
|
||||||
|
out.write(streamNumberBytes);
|
||||||
out.write(frameKey.getBytes());
|
out.write(frameKey.getBytes());
|
||||||
out.write(new byte[MAC_LENGTH]);
|
out.write(new byte[MAC_LENGTH]);
|
||||||
out.write(frameHeader);
|
out.write(frameHeader);
|
||||||
@@ -162,7 +256,9 @@ public class StreamDecrypterImplTest extends BrambleTestCase {
|
|||||||
paddingLength);
|
paddingLength);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(streamHeaderIv);
|
out.write(streamHeaderNonce);
|
||||||
|
out.write(protocolVersionBytes);
|
||||||
|
out.write(streamNumberBytes);
|
||||||
out.write(frameKey.getBytes());
|
out.write(frameKey.getBytes());
|
||||||
out.write(new byte[MAC_LENGTH]);
|
out.write(new byte[MAC_LENGTH]);
|
||||||
out.write(frameHeader);
|
out.write(frameHeader);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.briarproject.bramble.crypto;
|
|||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.ByteUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -11,8 +12,9 @@ import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HE
|
|||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_NONCE_LENGTH;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -21,7 +23,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
private final AuthenticatedCipher cipher;
|
private final AuthenticatedCipher cipher;
|
||||||
private final SecretKey streamHeaderKey, frameKey;
|
private final SecretKey streamHeaderKey, frameKey;
|
||||||
private final byte[] tag, streamHeaderIv, payload;
|
private final byte[] tag, streamHeaderNonce, protocolVersionBytes;
|
||||||
|
private final byte[] streamNumberBytes, payload;
|
||||||
private final long streamNumber = 1234;
|
private final long streamNumber = 1234;
|
||||||
private final int payloadLength = 123, paddingLength = 234;
|
private final int payloadLength = 123, paddingLength = 234;
|
||||||
|
|
||||||
@@ -30,7 +33,12 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
streamHeaderKey = TestUtils.getSecretKey();
|
streamHeaderKey = TestUtils.getSecretKey();
|
||||||
frameKey = TestUtils.getSecretKey();
|
frameKey = TestUtils.getSecretKey();
|
||||||
tag = TestUtils.getRandomBytes(TAG_LENGTH);
|
tag = TestUtils.getRandomBytes(TAG_LENGTH);
|
||||||
streamHeaderIv = TestUtils.getRandomBytes(STREAM_HEADER_IV_LENGTH);
|
streamHeaderNonce =
|
||||||
|
TestUtils.getRandomBytes(STREAM_HEADER_NONCE_LENGTH);
|
||||||
|
protocolVersionBytes = new byte[2];
|
||||||
|
ByteUtils.writeUint16(PROTOCOL_VERSION, protocolVersionBytes, 0);
|
||||||
|
streamNumberBytes = new byte[8];
|
||||||
|
ByteUtils.writeUint64(streamNumber, streamNumberBytes, 0);
|
||||||
payload = TestUtils.getRandomBytes(payloadLength);
|
payload = TestUtils.getRandomBytes(payloadLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +46,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testRejectsNegativePayloadLength() throws Exception {
|
public void testRejectsNegativePayloadLength() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, -1, 0, false);
|
s.writeFrame(payload, -1, 0, false);
|
||||||
}
|
}
|
||||||
@@ -47,7 +56,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testRejectsNegativePaddingLength() throws Exception {
|
public void testRejectsNegativePaddingLength() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, 0, -1, false);
|
s.writeFrame(payload, 0, -1, false);
|
||||||
}
|
}
|
||||||
@@ -56,7 +66,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testRejectsMaxPayloadPlusPadding() throws Exception {
|
public void testRejectsMaxPayloadPlusPadding() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH + 1];
|
byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH + 1];
|
||||||
s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 1, false);
|
s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 1, false);
|
||||||
@@ -66,7 +77,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testAcceptsMaxPayloadIncludingPadding() throws Exception {
|
public void testAcceptsMaxPayloadIncludingPadding() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH - 1, 1, false);
|
s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH - 1, 1, false);
|
||||||
@@ -78,7 +90,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testAcceptsMaxPayloadWithoutPadding() throws Exception {
|
public void testAcceptsMaxPayloadWithoutPadding() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH];
|
byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH];
|
||||||
s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 0, false);
|
s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 0, false);
|
||||||
@@ -90,14 +103,17 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
|
public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, false);
|
s.writeFrame(payload, payloadLength, 0, false);
|
||||||
|
|
||||||
// Expect the tag, stream header, frame header, payload and MAC
|
// Expect the tag, stream header, frame header, payload and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -113,14 +129,17 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWriteUnpaddedFinalFrameWithTag() throws Exception {
|
public void testWriteUnpaddedFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, true);
|
s.writeFrame(payload, payloadLength, 0, true);
|
||||||
|
|
||||||
// Expect the tag, stream header, frame header, payload and MAC
|
// Expect the tag, stream header, frame header, payload and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -136,13 +155,16 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWriteUnpaddedNonFinalFrameWithoutTag() throws Exception {
|
public void testWriteUnpaddedNonFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, false);
|
s.writeFrame(payload, payloadLength, 0, false);
|
||||||
|
|
||||||
// Expect the stream header, frame header, payload and MAC
|
// Expect the stream header, frame header, payload and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -158,13 +180,16 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWriteUnpaddedFinalFrameWithoutTag() throws Exception {
|
public void testWriteUnpaddedFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, 0, true);
|
s.writeFrame(payload, payloadLength, 0, true);
|
||||||
|
|
||||||
// Expect the stream header, frame header, payload and MAC
|
// Expect the stream header, frame header, payload and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -180,14 +205,17 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWritePaddedNonFinalFrameWithTag() throws Exception {
|
public void testWritePaddedNonFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, false);
|
s.writeFrame(payload, payloadLength, paddingLength, false);
|
||||||
|
|
||||||
// Expect the tag, stream header, frame header, payload, padding and MAC
|
// Expect the tag, stream header, frame header, payload, padding and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -205,14 +233,17 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWritePaddedFinalFrameWithTag() throws Exception {
|
public void testWritePaddedFinalFrameWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, true);
|
s.writeFrame(payload, payloadLength, paddingLength, true);
|
||||||
|
|
||||||
// Expect the tag, stream header, frame header, payload, padding and MAC
|
// Expect the tag, stream header, frame header, payload, padding and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -230,13 +261,16 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWritePaddedNonFinalFrameWithoutTag() throws Exception {
|
public void testWritePaddedNonFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, false);
|
s.writeFrame(payload, payloadLength, paddingLength, false);
|
||||||
|
|
||||||
// Expect the stream header, frame header, payload, padding and MAC
|
// Expect the stream header, frame header, payload, padding and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -254,13 +288,16 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWritePaddedFinalFrameWithoutTag() throws Exception {
|
public void testWritePaddedFinalFrameWithoutTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
s.writeFrame(payload, payloadLength, paddingLength, true);
|
s.writeFrame(payload, payloadLength, paddingLength, true);
|
||||||
|
|
||||||
// Expect the stream header, frame header, payload, padding and MAC
|
// Expect the stream header, frame header, payload, padding and MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -278,7 +315,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testWriteTwoFramesWithTag() throws Exception {
|
public void testWriteTwoFramesWithTag() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
int payloadLength1 = 345, paddingLength1 = 456;
|
int payloadLength1 = 345, paddingLength1 = 456;
|
||||||
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
byte[] payload1 = TestUtils.getRandomBytes(payloadLength1);
|
||||||
|
|
||||||
@@ -289,7 +327,9 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
// MAC, second frame header, payload, padding, MAC
|
// MAC, second frame header, payload, padding, MAC
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
byte[] expectedFrameHeader = new byte[FRAME_HEADER_LENGTH];
|
||||||
@@ -315,7 +355,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
// Flush the stream once
|
// Flush the stream once
|
||||||
s.flush();
|
s.flush();
|
||||||
@@ -323,7 +364,9 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
// Expect the tag and stream header
|
// Expect the tag and stream header
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
|
|
||||||
@@ -335,7 +378,8 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, tag, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
// Flush the stream twice
|
// Flush the stream twice
|
||||||
s.flush();
|
s.flush();
|
||||||
@@ -344,7 +388,9 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
// Expect the tag and stream header
|
// Expect the tag and stream header
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(tag);
|
expected.write(tag);
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
|
|
||||||
@@ -355,14 +401,17 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
|
|||||||
public void testFlushDoesNotWriteTagIfNull() throws Exception {
|
public void testFlushDoesNotWriteTagIfNull() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
|
||||||
streamNumber, null, streamHeaderIv, streamHeaderKey, frameKey);
|
streamNumber, null, streamHeaderNonce, streamHeaderKey,
|
||||||
|
frameKey);
|
||||||
|
|
||||||
// Flush the stream once
|
// Flush the stream once
|
||||||
s.flush();
|
s.flush();
|
||||||
|
|
||||||
// Expect the stream header
|
// Expect the stream header
|
||||||
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
ByteArrayOutputStream expected = new ByteArrayOutputStream();
|
||||||
expected.write(streamHeaderIv);
|
expected.write(streamHeaderNonce);
|
||||||
|
expected.write(protocolVersionBytes);
|
||||||
|
expected.write(streamNumberBytes);
|
||||||
expected.write(frameKey.getBytes());
|
expected.write(frameKey.getBytes());
|
||||||
expected.write(new byte[MAC_LENGTH]);
|
expected.write(new byte[MAC_LENGTH]);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.briarproject.bramble.crypto;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Bytes;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
|
import org.briarproject.bramble.test.TestSecureRandomProvider;
|
||||||
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
|
public class TagEncodingTest extends BrambleTestCase {
|
||||||
|
|
||||||
|
private final CryptoComponent crypto;
|
||||||
|
private final SecretKey tagKey;
|
||||||
|
private final long streamNumber = 1234567890;
|
||||||
|
|
||||||
|
public TagEncodingTest() {
|
||||||
|
crypto = new CryptoComponentImpl(new TestSecureRandomProvider());
|
||||||
|
tagKey = TestUtils.getSecretKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeyAffectsTag() throws Exception {
|
||||||
|
Set<Bytes> set = new HashSet<Bytes>();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
|
SecretKey tagKey = TestUtils.getSecretKey();
|
||||||
|
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber);
|
||||||
|
assertTrue(set.add(new Bytes(tag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProtocolVersionAffectsTag() throws Exception {
|
||||||
|
Set<Bytes> set = new HashSet<Bytes>();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
|
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber);
|
||||||
|
assertTrue(set.add(new Bytes(tag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStreamNumberAffectsTag() throws Exception {
|
||||||
|
Set<Bytes> set = new HashSet<Bytes>();
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
|
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i);
|
||||||
|
assertTrue(set.add(new Bytes(tag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ import java.util.Collection;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
|
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -115,7 +116,7 @@ public class SyncIntegrationTest extends BrambleTestCase {
|
|||||||
private void read(byte[] connectionData) throws Exception {
|
private void read(byte[] connectionData) throws Exception {
|
||||||
// Calculate the expected tag
|
// Calculate the expected tag
|
||||||
byte[] expectedTag = new byte[TAG_LENGTH];
|
byte[] expectedTag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(expectedTag, tagKey, streamNumber);
|
crypto.encodeTag(expectedTag, tagKey, PROTOCOL_VERSION, streamNumber);
|
||||||
|
|
||||||
// Read the tag
|
// Read the tag
|
||||||
InputStream in = new ByteArrayInputStream(connectionData);
|
InputStream in = new ByteArrayInputStream(connectionData);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
|
import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
@@ -86,7 +87,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets per contact)
|
// Encode the tags (3 sets per contact)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(6).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(6).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Save the keys that were rotated
|
// Save the keys that were rotated
|
||||||
@@ -133,7 +134,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Save the keys
|
// Save the keys
|
||||||
@@ -199,7 +200,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Rotate the transport keys (the keys are unaffected)
|
// Rotate the transport keys (the keys are unaffected)
|
||||||
@@ -247,7 +248,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Rotate the transport keys (the keys are unaffected)
|
// Rotate the transport keys (the keys are unaffected)
|
||||||
@@ -306,7 +307,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Rotate the transport keys (the keys are unaffected)
|
// Rotate the transport keys (the keys are unaffected)
|
||||||
@@ -355,7 +356,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction(tags));
|
will(new EncodeTagAction(tags));
|
||||||
}
|
}
|
||||||
// Rotate the transport keys (the keys are unaffected)
|
// Rotate the transport keys (the keys are unaffected)
|
||||||
@@ -365,7 +366,8 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
oneOf(db).addTransportKeys(txn, contactId, transportKeys);
|
oneOf(db).addTransportKeys(txn, contactId, transportKeys);
|
||||||
// Encode a new tag after sliding the window
|
// Encode a new tag after sliding the window
|
||||||
oneOf(crypto).encodeTag(with(any(byte[].class)),
|
oneOf(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with((long) REORDERING_WINDOW_SIZE));
|
with(tagKey), with(PROTOCOL_VERSION),
|
||||||
|
with((long) REORDERING_WINDOW_SIZE));
|
||||||
will(new EncodeTagAction(tags));
|
will(new EncodeTagAction(tags));
|
||||||
// Save the reordering window (previous rotation period, base 1)
|
// Save the reordering window (previous rotation period, base 1)
|
||||||
oneOf(db).setReorderingWindow(txn, contactId, transportId, 999,
|
oneOf(db).setReorderingWindow(txn, contactId, transportId, 999,
|
||||||
@@ -428,7 +430,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Schedule key rotation at the start of the next rotation period
|
// Schedule key rotation at the start of the next rotation period
|
||||||
@@ -450,7 +452,7 @@ public class TransportKeyManagerImplTest extends BrambleTestCase {
|
|||||||
// Encode the tags (3 sets)
|
// Encode the tags (3 sets)
|
||||||
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
|
||||||
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
exactly(3).of(crypto).encodeTag(with(any(byte[].class)),
|
||||||
with(tagKey), with(i));
|
with(tagKey), with(PROTOCOL_VERSION), with(i));
|
||||||
will(new EncodeTagAction());
|
will(new EncodeTagAction());
|
||||||
}
|
}
|
||||||
// Save the keys that were rotated
|
// Save the keys that were rotated
|
||||||
|
|||||||
@@ -7,10 +7,19 @@ apply plugin: 'witness'
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(':bramble-core')
|
compile project(':bramble-core')
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
compile fileTree(dir: 'libs', include: '*.jar')
|
||||||
|
compile 'net.java.dev.jna:jna:4.4.0'
|
||||||
|
compile 'net.java.dev.jna:jna-platform:4.4.0'
|
||||||
|
|
||||||
testCompile project(path: ':bramble-core', configuration: 'testOutput')
|
testCompile project(path: ':bramble-core', configuration: 'testOutput')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencyVerification {
|
||||||
|
verify = [
|
||||||
|
'net.java.dev.jna:jna:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
|
||||||
|
'net.java.dev.jna:jna-platform:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
tasks.withType(Test) {
|
tasks.withType(Test) {
|
||||||
systemProperty 'java.library.path', 'libs'
|
systemProperty 'java.library.path', 'libs'
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -5,13 +5,10 @@ dependencies {
|
|||||||
def supportVersion = '23.2.1'
|
def supportVersion = '23.2.1'
|
||||||
compile project(':briar-core')
|
compile project(':briar-core')
|
||||||
compile project(':bramble-android')
|
compile project(':bramble-android')
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
|
||||||
|
|
||||||
compile "com.android.support:support-v4:$supportVersion"
|
compile "com.android.support:support-v4:$supportVersion"
|
||||||
compile("com.android.support:appcompat-v7:$supportVersion") {
|
compile("com.android.support:appcompat-v7:$supportVersion") {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
}
|
}
|
||||||
|
|
||||||
compile("com.android.support:preference-v14:$supportVersion") {
|
compile("com.android.support:preference-v14:$supportVersion") {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
}
|
}
|
||||||
@@ -20,7 +17,7 @@ dependencies {
|
|||||||
exclude module: 'recyclerview-v7'
|
exclude module: 'recyclerview-v7'
|
||||||
}
|
}
|
||||||
compile "com.android.support:cardview-v7:$supportVersion"
|
compile "com.android.support:cardview-v7:$supportVersion"
|
||||||
compile 'com.android.support:support-annotations:23.4.0'
|
compile "com.android.support:support-annotations:$supportVersion"
|
||||||
compile('ch.acra:acra:4.8.5') {
|
compile('ch.acra:acra:4.8.5') {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
exclude module: 'support-annotations'
|
exclude module: 'support-annotations'
|
||||||
@@ -28,15 +25,16 @@ dependencies {
|
|||||||
compile 'info.guardianproject.panic:panic:0.5'
|
compile 'info.guardianproject.panic:panic:0.5'
|
||||||
compile 'info.guardianproject.trustedintents:trustedintents:0.2'
|
compile 'info.guardianproject.trustedintents:trustedintents:0.2'
|
||||||
compile 'de.hdodenhof:circleimageview:2.1.0'
|
compile 'de.hdodenhof:circleimageview:2.1.0'
|
||||||
compile 'com.google.zxing:core:3.2.1'
|
compile 'com.google.zxing:core:3.3.0'
|
||||||
provided 'javax.annotation:jsr250-api:1.0'
|
|
||||||
compile 'com.jpardogo.materialtabstrip:library:1.1.0'
|
compile 'com.jpardogo.materialtabstrip:library:1.1.0'
|
||||||
compile 'com.github.bumptech.glide:glide:3.7.0'
|
compile 'com.github.bumptech.glide:glide:3.8.0'
|
||||||
compile 'uk.co.samuelwall:material-tap-target-prompt:1.3.0'
|
compile 'uk.co.samuelwall:material-tap-target-prompt:1.9.2'
|
||||||
|
|
||||||
|
provided 'javax.annotation:jsr250-api:1.0'
|
||||||
|
|
||||||
testCompile project(path: ':bramble-core', configuration: 'testOutput')
|
testCompile project(path: ':bramble-core', configuration: 'testOutput')
|
||||||
testCompile 'org.robolectric:robolectric:3.0'
|
testCompile 'org.robolectric:robolectric:3.0'
|
||||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
testCompile 'org.mockito:mockito-core:2.8.9'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
@@ -45,20 +43,18 @@ dependencyVerification {
|
|||||||
'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
|
'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
|
||||||
'info.guardianproject.trustedintents:trustedintents:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
|
'info.guardianproject.trustedintents:trustedintents:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
|
||||||
'de.hdodenhof:circleimageview:bcbc588e19e6dcf8c120b1957776bfe229efba5d2fbe5da7156372eeacf65503',
|
'de.hdodenhof:circleimageview:bcbc588e19e6dcf8c120b1957776bfe229efba5d2fbe5da7156372eeacf65503',
|
||||||
'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259',
|
'com.google.zxing:core:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
||||||
'com.android.support:support-v4:81ce890f26d35c75ad17d0f998a7e3230330c3b41e0b629566bc744bee89e448',
|
'com.jpardogo.materialtabstrip:library:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
|
||||||
|
'com.github.bumptech.glide:glide:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655',
|
||||||
|
'uk.co.samuelwall:material-tap-target-prompt:5d4951124366bc5c52e57beaa294db7611f0aa2a8d80e0163e1383e1966ba5b2',
|
||||||
'com.android.support:appcompat-v7:00f9d93acacd6731f309724054bf51492814b4b2869f16d7d5c0038dcb8c9a0d',
|
'com.android.support:appcompat-v7:00f9d93acacd6731f309724054bf51492814b4b2869f16d7d5c0038dcb8c9a0d',
|
||||||
'com.android.support:preference-v14:44881bb46094e86d0bc2426f205419674a5b4eb514b44b5a4659b5de29f71eb7',
|
'com.android.support:preference-v14:44881bb46094e86d0bc2426f205419674a5b4eb514b44b5a4659b5de29f71eb7',
|
||||||
'com.android.support:design:003e0c0bea0a6891f8b2bc43f20ae7af2a49a17363e5bb10df5ee0bae12fa686',
|
'com.android.support:design:003e0c0bea0a6891f8b2bc43f20ae7af2a49a17363e5bb10df5ee0bae12fa686',
|
||||||
'com.android.support:support-annotations:e91a88dd0c5e99069b7f09d4a46b5e06f1e9c4c72fc0a8e987e25d86af480f01',
|
'com.android.support:cardview-v7:4595f1c4a28cfa083b6c0920ad4d49e1c2ca4b8302a955e548f68eb63b74931b',
|
||||||
'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1',
|
'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1',
|
||||||
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1',
|
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1',
|
||||||
'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe',
|
'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe',
|
||||||
'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025',
|
'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025',
|
||||||
'com.android.support:cardview-v7:4595f1c4a28cfa083b6c0920ad4d49e1c2ca4b8302a955e548f68eb63b74931b',
|
|
||||||
'com.jpardogo.materialtabstrip:library:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
|
|
||||||
'com.github.bumptech.glide:glide:76ef123957b5fbaebb05fcbe6606dd58c3bc3fcdadb257f99811d0ac9ea9b88b',
|
|
||||||
'uk.co.samuelwall:material-tap-target-prompt:f67e1caead12a914525b32cbf6da52a96b93ff89573f93cb41102ef3130fb64a',
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,9 +78,10 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 22
|
targetSdkVersion 22
|
||||||
versionCode 14
|
versionCode 1603
|
||||||
versionName "0.14"
|
versionName "0.16.3"
|
||||||
resValue "string", "app_package", "org.briarproject.briar"
|
applicationId "org.briarproject.briar.beta"
|
||||||
|
resValue "string", "app_package", "org.briarproject.briar.beta"
|
||||||
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
|
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,5 +106,6 @@ android {
|
|||||||
lintOptions {
|
lintOptions {
|
||||||
warning 'MissingTranslation'
|
warning 'MissingTranslation'
|
||||||
warning 'ImpliedQuantity'
|
warning 'ImpliedQuantity'
|
||||||
|
warning 'ExtraTranslation'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".android.BriarApplicationImpl"
|
android:name="org.briarproject.briar.android.BriarApplicationImpl"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@mipmap/ic_launcher_round"
|
android:icon="@mipmap/ic_launcher_round"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
android:theme="@style/BriarTheme">
|
android:theme="@style/BriarTheme">
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".android.BriarService"
|
android:name="org.briarproject.briar.android.BriarService"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="org.briarproject.briar.android.BriarService"/>
|
<action android:name="org.briarproject.briar.android.BriarService"/>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
</service>
|
</service>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.reporting.DevReportActivity"
|
android:name="org.briarproject.briar.android.reporting.DevReportActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:finishOnTaskLaunch="true"
|
android:finishOnTaskLaunch="true"
|
||||||
@@ -47,24 +47,24 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.splash.ExpiredActivity"
|
android:name="org.briarproject.briar.android.splash.ExpiredActivity"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.login.PasswordActivity"
|
android:name="org.briarproject.briar.android.login.PasswordActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:windowSoftInputMode="stateVisible">
|
android:windowSoftInputMode="stateVisible">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.login.SetupActivity"
|
android:name="org.briarproject.briar.android.login.SetupActivity"
|
||||||
android:label="@string/setup_title"
|
android:label="@string/setup_title"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.splash.SplashScreenActivity"
|
android:name="org.briarproject.briar.android.splash.SplashScreenActivity"
|
||||||
android:theme="@style/BriarTheme.NoActionBar"
|
android:theme="@style/BriarTheme.NoActionBar"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -74,268 +74,268 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.navdrawer.NavDrawerActivity"
|
android:name="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:theme="@style/BriarTheme.NoActionBar"
|
android:theme="@style/BriarTheme.NoActionBar"
|
||||||
android:launchMode="singleTop">
|
android:launchMode="singleTop">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.contact.ConversationActivity"
|
android:name="org.briarproject.briar.android.contact.ConversationActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/BriarTheme.NoActionBar"
|
android:theme="@style/BriarTheme.NoActionBar"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:windowSoftInputMode="stateHidden|adjustResize">
|
android:windowSoftInputMode="stateHidden|adjustResize">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.privategroup.creation.CreateGroupActivity"
|
android:name="org.briarproject.briar.android.privategroup.creation.CreateGroupActivity"
|
||||||
android:label="@string/groups_create_group_title"
|
android:label="@string/groups_create_group_title"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.privategroup.conversation.GroupActivity"
|
android:name="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:theme="@style/BriarTheme.NoActionBar"
|
android:theme="@style/BriarTheme.NoActionBar"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.privategroup.invitation.GroupInvitationActivity"
|
android:name="org.briarproject.briar.android.privategroup.invitation.GroupInvitationActivity"
|
||||||
android:label="@string/groups_invitations_title"
|
android:label="@string/groups_invitations_title"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"/>
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.privategroup.memberlist.GroupMemberListActivity"
|
android:name="org.briarproject.briar.android.privategroup.memberlist.GroupMemberListActivity"
|
||||||
android:label="@string/groups_member_list"
|
android:label="@string/groups_member_list"
|
||||||
android:parentActivityName=".android.privategroup.conversation.GroupActivity"
|
android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.privategroup.conversation.GroupActivity"
|
android:value="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.privategroup.reveal.RevealContactsActivity"
|
android:name="org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity"
|
||||||
android:label="@string/groups_reveal_contacts"
|
android:label="@string/groups_reveal_contacts"
|
||||||
android:parentActivityName=".android.privategroup.conversation.GroupActivity"
|
android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
|
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.privategroup.conversation.GroupActivity"
|
android:value="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.privategroup.creation.GroupInviteActivity"
|
android:name="org.briarproject.briar.android.privategroup.creation.GroupInviteActivity"
|
||||||
android:label="@string/groups_invite_members"
|
android:label="@string/groups_invite_members"
|
||||||
android:parentActivityName=".android.privategroup.conversation.GroupActivity"
|
android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.privategroup.conversation.GroupActivity"/>
|
android:value="org.briarproject.briar.android.privategroup.conversation.GroupActivity"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.sharing.ForumInvitationActivity"
|
android:name="org.briarproject.briar.android.sharing.ForumInvitationActivity"
|
||||||
android:label="@string/forum_invitations_title"
|
android:label="@string/forum_invitations_title"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.sharing.BlogInvitationActivity"
|
android:name="org.briarproject.briar.android.sharing.BlogInvitationActivity"
|
||||||
android:label="@string/blogs_sharing_invitations_title"
|
android:label="@string/blogs_sharing_invitations_title"
|
||||||
android:parentActivityName=".android.contact.ConversationActivity">
|
android:parentActivityName="org.briarproject.briar.android.contact.ConversationActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.contact.ConversationActivity"
|
android:value="org.briarproject.briar.android.contact.ConversationActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.forum.CreateForumActivity"
|
android:name="org.briarproject.briar.android.forum.CreateForumActivity"
|
||||||
android:label="@string/create_forum_title"
|
android:label="@string/create_forum_title"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:windowSoftInputMode="stateVisible">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.forum.ForumActivity"
|
android:name="org.briarproject.briar.android.forum.ForumActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:theme="@style/BriarTheme.NoActionBar"
|
android:theme="@style/BriarTheme.NoActionBar"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.sharing.ShareForumActivity"
|
android:name="org.briarproject.briar.android.sharing.ShareForumActivity"
|
||||||
android:label="@string/activity_share_toolbar_header"
|
android:label="@string/activity_share_toolbar_header"
|
||||||
android:parentActivityName=".android.forum.ForumActivity"
|
android:parentActivityName="org.briarproject.briar.android.forum.ForumActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.forum.ForumActivity"
|
android:value="org.briarproject.briar.android.forum.ForumActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.sharing.ShareBlogActivity"
|
android:name="org.briarproject.briar.android.sharing.ShareBlogActivity"
|
||||||
android:label="@string/activity_share_toolbar_header"
|
android:label="@string/activity_share_toolbar_header"
|
||||||
android:parentActivityName=".android.blog.BlogActivity"
|
android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden">
|
android:windowSoftInputMode="adjustResize|stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.blog.BlogActivity"
|
android:value="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.sharing.ForumSharingStatusActivity"
|
android:name="org.briarproject.briar.android.sharing.ForumSharingStatusActivity"
|
||||||
android:label="@string/sharing_status"
|
android:label="@string/sharing_status"
|
||||||
android:parentActivityName=".android.forum.ForumActivity">
|
android:parentActivityName="org.briarproject.briar.android.forum.ForumActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.forum.ForumActivity"
|
android:value="org.briarproject.briar.android.forum.ForumActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.sharing.BlogSharingStatusActivity"
|
android:name="org.briarproject.briar.android.sharing.BlogSharingStatusActivity"
|
||||||
android:label="@string/sharing_status"
|
android:label="@string/sharing_status"
|
||||||
android:parentActivityName=".android.blog.BlogActivity">
|
android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.blog.BlogActivity"
|
android:value="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.blog.BlogActivity"
|
android:name="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:theme="@style/BriarTheme.NoActionBar">
|
android:theme="@style/BriarTheme.NoActionBar">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"/>
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.blog.WriteBlogPostActivity"
|
android:name="org.briarproject.briar.android.blog.WriteBlogPostActivity"
|
||||||
android:label="@string/blogs_write_blog_post"
|
android:label="@string/blogs_write_blog_post"
|
||||||
android:parentActivityName=".android.blog.BlogActivity"
|
android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
android:windowSoftInputMode="stateVisible|adjustResize">
|
android:windowSoftInputMode="stateVisible|adjustResize">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.blog.BlogActivity"
|
android:value="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.blog.ReblogActivity"
|
android:name="org.briarproject.briar.android.blog.ReblogActivity"
|
||||||
android:label="@string/blogs_reblog_button"
|
android:label="@string/blogs_reblog_button"
|
||||||
android:parentActivityName=".android.blog.BlogActivity"
|
android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
android:windowSoftInputMode="stateHidden">
|
android:windowSoftInputMode="stateHidden">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.blog.BlogActivity"
|
android:value="org.briarproject.briar.android.blog.BlogActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.blog.RssFeedImportActivity"
|
android:name="org.briarproject.briar.android.blog.RssFeedImportActivity"
|
||||||
android:label="@string/blogs_rss_feeds_import"
|
android:label="@string/blogs_rss_feeds_import"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:windowSoftInputMode="stateVisible|adjustResize">
|
android:windowSoftInputMode="stateVisible|adjustResize">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.blog.RssFeedManageActivity"
|
android:name="org.briarproject.briar.android.blog.RssFeedManageActivity"
|
||||||
android:label="@string/blogs_rss_feeds_manage"
|
android:label="@string/blogs_rss_feeds_manage"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.invitation.AddContactActivity"
|
android:name="org.briarproject.briar.android.invitation.AddContactActivity"
|
||||||
android:label="@string/add_contact_title"
|
android:label="@string/add_contact_title"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.keyagreement.KeyAgreementActivity"
|
android:name="org.briarproject.briar.android.keyagreement.KeyAgreementActivity"
|
||||||
android:label="@string/add_contact_title"
|
android:label="@string/add_contact_title"
|
||||||
android:theme="@style/BriarTheme.NoActionBar"
|
android:theme="@style/BriarTheme.NoActionBar"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"/>
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.introduction.IntroductionActivity"
|
android:name="org.briarproject.briar.android.introduction.IntroductionActivity"
|
||||||
android:label="@string/introduction_activity_title"
|
android:label="@string/introduction_activity_title"
|
||||||
android:parentActivityName=".android.contact.ConversationActivity"
|
android:parentActivityName="org.briarproject.briar.android.contact.ConversationActivity"
|
||||||
android:windowSoftInputMode="stateHidden|adjustResize">
|
android:windowSoftInputMode="stateHidden|adjustResize">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.contact.ConversationActivity"
|
android:value="org.briarproject.briar.android.contact.ConversationActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.StartupFailureActivity"
|
android:name="org.briarproject.briar.android.StartupFailureActivity"
|
||||||
android:label="@string/startup_failed_activity_title">
|
android:label="@string/startup_failed_activity_title">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.settings.SettingsActivity"
|
android:name="org.briarproject.briar.android.settings.SettingsActivity"
|
||||||
android:label="@string/settings_button"
|
android:label="@string/settings_button"
|
||||||
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
|
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
android:permission="android.permission.READ_NETWORK_USAGE_HISTORY">
|
android:permission="android.permission.READ_NETWORK_USAGE_HISTORY">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.navdrawer.NavDrawerActivity"
|
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||||
/>
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
|
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
|
||||||
@@ -344,27 +344,27 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.login.ChangePasswordActivity"
|
android:name="org.briarproject.briar.android.login.ChangePasswordActivity"
|
||||||
android:label="@string/change_password"
|
android:label="@string/change_password"
|
||||||
android:parentActivityName=".android.settings.SettingsActivity">
|
android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.settings.SettingsActivity"
|
android:value="org.briarproject.briar.android.settings.SettingsActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.panic.PanicPreferencesActivity"
|
android:name="org.briarproject.briar.android.panic.PanicPreferencesActivity"
|
||||||
android:label="@string/panic_setting"
|
android:label="@string/panic_setting"
|
||||||
android:parentActivityName=".android.settings.SettingsActivity">
|
android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".android.settings.SettingsActivity"
|
android:value="org.briarproject.briar.android.settings.SettingsActivity"
|
||||||
/>
|
/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.panic.PanicResponderActivity"
|
android:name="org.briarproject.briar.android.panic.PanicResponderActivity"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
<!-- this can never have launchMode singleTask or singleInstance! -->
|
<!-- this can never have launchMode singleTask or singleInstance! -->
|
||||||
@@ -375,7 +375,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.panic.ExitActivity"
|
android:name="org.briarproject.briar.android.panic.ExitActivity"
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import static android.content.Context.NOTIFICATION_SERVICE;
|
|||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
|
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
|
||||||
import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
|
import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
|
||||||
|
import static android.support.v4.app.NotificationCompat.VISIBILITY_PRIVATE;
|
||||||
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
|
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||||
@@ -327,7 +328,12 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
b.setCategory(CATEGORY_MESSAGE);
|
b.setCategory(CATEGORY_MESSAGE);
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
if (showOnLockScreen)
|
||||||
|
b.setVisibility(VISIBILITY_PRIVATE);
|
||||||
|
else
|
||||||
|
b.setVisibility(VISIBILITY_SECRET);
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
@@ -347,17 +353,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
return defaults;
|
return defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearAllContactNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
clearContactNotification();
|
|
||||||
clearIntroductionSuccessNotification();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void showGroupMessageNotification(final GroupId g) {
|
private void showGroupMessageNotification(final GroupId g) {
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
androidExecutor.runOnUiThread(new Runnable() {
|
||||||
@@ -432,7 +427,12 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
b.setCategory(CATEGORY_SOCIAL);
|
b.setCategory(CATEGORY_SOCIAL);
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
if (showOnLockScreen)
|
||||||
|
b.setVisibility(VISIBILITY_PRIVATE);
|
||||||
|
else
|
||||||
|
b.setVisibility(VISIBILITY_SECRET);
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
@@ -440,16 +440,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearAllGroupMessageNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
clearGroupMessageNotification();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void showForumPostNotification(final GroupId g) {
|
private void showForumPostNotification(final GroupId g) {
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
androidExecutor.runOnUiThread(new Runnable() {
|
||||||
@@ -524,7 +514,12 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
b.setCategory(CATEGORY_SOCIAL);
|
b.setCategory(CATEGORY_SOCIAL);
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
if (showOnLockScreen)
|
||||||
|
b.setVisibility(VISIBILITY_PRIVATE);
|
||||||
|
else
|
||||||
|
b.setVisibility(VISIBILITY_SECRET);
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
@@ -532,16 +527,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearAllForumPostNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
clearForumPostNotification();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void showBlogPostNotification(final GroupId g) {
|
private void showBlogPostNotification(final GroupId g) {
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
androidExecutor.runOnUiThread(new Runnable() {
|
||||||
@@ -602,7 +587,12 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
b.setCategory(CATEGORY_SOCIAL);
|
b.setCategory(CATEGORY_SOCIAL);
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
if (showOnLockScreen)
|
||||||
|
b.setVisibility(VISIBILITY_PRIVATE);
|
||||||
|
else
|
||||||
|
b.setVisibility(VISIBILITY_SECRET);
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
@@ -658,7 +648,12 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
b.setCategory(CATEGORY_MESSAGE);
|
b.setCategory(CATEGORY_MESSAGE);
|
||||||
b.setVisibility(VISIBILITY_SECRET);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
if (showOnLockScreen)
|
||||||
|
b.setVisibility(VISIBILITY_PRIVATE);
|
||||||
|
else
|
||||||
|
b.setVisibility(VISIBILITY_SECRET);
|
||||||
}
|
}
|
||||||
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
|
||||||
NotificationManager nm = (NotificationManager) o;
|
NotificationManager nm = (NotificationManager) o;
|
||||||
@@ -705,68 +700,6 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void blockAllContactNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
blockContacts = true;
|
|
||||||
blockIntroductions = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unblockAllContactNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
blockContacts = false;
|
|
||||||
blockIntroductions = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void blockAllGroupMessageNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
blockGroups = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unblockAllGroupMessageNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
blockGroups = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void blockAllForumPostNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
blockForums = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unblockAllForumPostNotifications() {
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
blockForums = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void blockAllBlogPostNotifications() {
|
public void blockAllBlogPostNotifications() {
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
androidExecutor.runOnUiThread(new Runnable() {
|
||||||
@@ -786,5 +719,4 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ public class AppModule {
|
|||||||
static class EagerSingletons {
|
static class EagerSingletons {
|
||||||
@Inject
|
@Inject
|
||||||
AndroidNotificationManager androidNotificationManager;
|
AndroidNotificationManager androidNotificationManager;
|
||||||
@Inject
|
|
||||||
ScreenFilterMonitor screenFilterMonitor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Application application;
|
private final Application application;
|
||||||
@@ -171,10 +169,8 @@ public class AppModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
|
||||||
ScreenFilterMonitor provideScreenFilterMonitor(
|
ScreenFilterMonitor provideScreenFilterMonitor(
|
||||||
LifecycleManager lifecycleManager, ScreenFilterMonitorImpl sfm) {
|
ScreenFilterMonitorImpl screenFilterMonitor) {
|
||||||
lifecycleManager.registerService(sfm);
|
return screenFilterMonitor;
|
||||||
return sfm;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,9 @@ package org.briarproject.briar.android;
|
|||||||
*/
|
*/
|
||||||
public interface BriarApplication {
|
public interface BriarApplication {
|
||||||
|
|
||||||
|
// This build expires on 21 October 2017
|
||||||
|
long EXPIRY_DATE = 1508544000 * 1000L;
|
||||||
|
|
||||||
AndroidComponent getApplicationComponent();
|
AndroidComponent getApplicationComponent();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,13 @@
|
|||||||
package org.briarproject.briar.android;
|
package org.briarproject.briar.android;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.Signature;
|
import android.content.pm.Signature;
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.v7.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.lifecycle.Service;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.lifecycle.ServiceException;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||||
|
|
||||||
@@ -26,38 +16,26 @@ import java.io.InputStream;
|
|||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
|
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
|
||||||
import static android.content.Intent.ACTION_PACKAGE_ADDED;
|
|
||||||
import static android.content.Intent.EXTRA_REPLACING;
|
|
||||||
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
||||||
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||||
import static android.content.pm.PackageManager.GET_SIGNATURES;
|
import static android.content.pm.PackageManager.GET_SIGNATURES;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@NotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
class ScreenFilterMonitorImpl implements ScreenFilterMonitor {
|
||||||
public class ScreenFilterMonitorImpl extends BroadcastReceiver
|
|
||||||
implements Service, ScreenFilterMonitor {
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ScreenFilterMonitorImpl.class.getName());
|
Logger.getLogger(ScreenFilterMonitorImpl.class.getName());
|
||||||
private static final String PREF_SCREEN_FILTER_APPS =
|
|
||||||
"shownScreenFilterApps";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore Play Services if it uses this package name and public key - it's
|
* Ignore Play Services if it uses this package name and public key - it's
|
||||||
@@ -78,124 +56,17 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
|
|||||||
"82BA35E003C1B4B10DD244A8EE24FFFD333872AB5221985EDAB0FC0D" +
|
"82BA35E003C1B4B10DD244A8EE24FFFD333872AB5221985EDAB0FC0D" +
|
||||||
"0B145B6AA192858E79020103";
|
"0B145B6AA192858E79020103";
|
||||||
|
|
||||||
private final Context appContext;
|
|
||||||
private final AndroidExecutor androidExecutor;
|
|
||||||
private final PackageManager pm;
|
private final PackageManager pm;
|
||||||
private final SharedPreferences prefs;
|
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
// The following must only be accessed on the UI thread
|
|
||||||
private final Set<String> apps = new HashSet<>();
|
|
||||||
private final Set<String> shownApps;
|
|
||||||
private boolean serviceStarted = false;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ScreenFilterMonitorImpl(AndroidExecutor executor, Application app) {
|
ScreenFilterMonitorImpl(Application app) {
|
||||||
this.androidExecutor = executor;
|
pm = app.getPackageManager();
|
||||||
this.appContext = app;
|
|
||||||
pm = appContext.getPackageManager();
|
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
|
|
||||||
shownApps = getShownScreenFilterApps();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startService() throws ServiceException {
|
|
||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
|
||||||
Future<Void> f = androidExecutor.runOnUiThread(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() {
|
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
|
||||||
intentFilter.addAction(ACTION_PACKAGE_ADDED);
|
|
||||||
intentFilter.addDataScheme("package");
|
|
||||||
appContext.registerReceiver(ScreenFilterMonitorImpl.this,
|
|
||||||
intentFilter);
|
|
||||||
apps.addAll(getInstalledScreenFilterApps());
|
|
||||||
serviceStarted = true;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
f.get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
throw new ServiceException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopService() throws ServiceException {
|
|
||||||
Future<Void> f = androidExecutor.runOnUiThread(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() {
|
|
||||||
serviceStarted = false;
|
|
||||||
appContext.unregisterReceiver(ScreenFilterMonitorImpl.this);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
f.get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
throw new ServiceException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> getShownScreenFilterApps() {
|
|
||||||
// Result must not be modified
|
|
||||||
Set<String> s = prefs.getStringSet(PREF_SCREEN_FILTER_APPS, null);
|
|
||||||
HashSet<String> result = new HashSet<>();
|
|
||||||
if (s != null) {
|
|
||||||
result.addAll(s);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (!intent.getBooleanExtra(EXTRA_REPLACING, false)) {
|
|
||||||
final String packageName =
|
|
||||||
intent.getData().getEncodedSchemeSpecificPart();
|
|
||||||
androidExecutor.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
String pkg = isOverlayApp(packageName);
|
|
||||||
if (pkg == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
apps.add(pkg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@UiThread
|
@UiThread
|
||||||
public Set<String> getApps() {
|
public Set<String> getApps() {
|
||||||
if (!serviceStarted) {
|
Set<String> screenFilterApps = new TreeSet<>();
|
||||||
apps.addAll(getInstalledScreenFilterApps());
|
|
||||||
}
|
|
||||||
TreeSet<String> buf = new TreeSet<>();
|
|
||||||
if (apps.isEmpty()) {
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
buf.addAll(apps);
|
|
||||||
buf.removeAll(shownApps);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@UiThread
|
|
||||||
public void storeAppsAsShown(Collection<String> s, boolean persistent) {
|
|
||||||
HashSet<String> buf = new HashSet<>(s);
|
|
||||||
shownApps.addAll(buf);
|
|
||||||
if (persistent && !s.isEmpty()) {
|
|
||||||
buf.addAll(getShownScreenFilterApps());
|
|
||||||
prefs.edit()
|
|
||||||
.putStringSet(PREF_SCREEN_FILTER_APPS, buf)
|
|
||||||
.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> getInstalledScreenFilterApps() {
|
|
||||||
HashSet<String> screenFilterApps = new HashSet<>();
|
|
||||||
List<PackageInfo> packageInfos =
|
List<PackageInfo> packageInfos =
|
||||||
pm.getInstalledPackages(GET_PERMISSIONS);
|
pm.getInstalledPackages(GET_PERMISSIONS);
|
||||||
for (PackageInfo packageInfo : packageInfos) {
|
for (PackageInfo packageInfo : packageInfos) {
|
||||||
@@ -209,21 +80,6 @@ public class ScreenFilterMonitorImpl extends BroadcastReceiver
|
|||||||
return screenFilterApps;
|
return screenFilterApps;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if a package uses the SYSTEM_ALERT_WINDOW permission and if so
|
|
||||||
// returns the app name.
|
|
||||||
@Nullable
|
|
||||||
private String isOverlayApp(String pkg) {
|
|
||||||
try {
|
|
||||||
PackageInfo pkgInfo = pm.getPackageInfo(pkg, GET_PERMISSIONS);
|
|
||||||
if (isOverlayApp(pkgInfo)) {
|
|
||||||
return pkgToString(pkgInfo);
|
|
||||||
}
|
|
||||||
} catch (NameNotFoundException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetches the application name for a given package.
|
// Fetches the application name for a given package.
|
||||||
@Nullable
|
@Nullable
|
||||||
private String pkgToString(PackageInfo pkgInfo) {
|
private String pkgToString(PackageInfo pkgInfo) {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import org.briarproject.briar.android.privategroup.conversation.GroupConversatio
|
|||||||
import org.briarproject.briar.android.privategroup.creation.CreateGroupActivity;
|
import org.briarproject.briar.android.privategroup.creation.CreateGroupActivity;
|
||||||
import org.briarproject.briar.android.privategroup.creation.CreateGroupFragment;
|
import org.briarproject.briar.android.privategroup.creation.CreateGroupFragment;
|
||||||
import org.briarproject.briar.android.privategroup.creation.CreateGroupMessageFragment;
|
import org.briarproject.briar.android.privategroup.creation.CreateGroupMessageFragment;
|
||||||
import org.briarproject.briar.android.privategroup.creation.GroupCreateModule;
|
import org.briarproject.briar.android.privategroup.creation.CreateGroupModule;
|
||||||
import org.briarproject.briar.android.privategroup.creation.GroupInviteActivity;
|
import org.briarproject.briar.android.privategroup.creation.GroupInviteActivity;
|
||||||
import org.briarproject.briar.android.privategroup.creation.GroupInviteFragment;
|
import org.briarproject.briar.android.privategroup.creation.GroupInviteFragment;
|
||||||
import org.briarproject.briar.android.privategroup.invitation.GroupInvitationActivity;
|
import org.briarproject.briar.android.privategroup.invitation.GroupInvitationActivity;
|
||||||
@@ -71,7 +71,7 @@ import dagger.Component;
|
|||||||
@Component(
|
@Component(
|
||||||
modules = {ActivityModule.class, ForumModule.class, SharingModule.class,
|
modules = {ActivityModule.class, ForumModule.class, SharingModule.class,
|
||||||
BlogModule.class, ContactModule.class, GroupListModule.class,
|
BlogModule.class, ContactModule.class, GroupListModule.class,
|
||||||
GroupCreateModule.class, GroupInvitationModule.class,
|
CreateGroupModule.class, GroupInvitationModule.class,
|
||||||
GroupConversationModule.class, GroupMemberModule.class,
|
GroupConversationModule.class, GroupMemberModule.class,
|
||||||
GroupRevealModule.class},
|
GroupRevealModule.class},
|
||||||
dependencies = AndroidComponent.class)
|
dependencies = AndroidComponent.class)
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ package org.briarproject.briar.android.activity;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.annotation.LayoutRes;
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewGroup.LayoutParams;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
@@ -13,7 +17,9 @@ import org.briarproject.briar.android.BriarApplication;
|
|||||||
import org.briarproject.briar.android.DestroyableContext;
|
import org.briarproject.briar.android.DestroyableContext;
|
||||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||||
import org.briarproject.briar.android.forum.ForumModule;
|
import org.briarproject.briar.android.forum.ForumModule;
|
||||||
import org.briarproject.briar.android.fragment.SFDialogFragment;
|
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
||||||
|
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
||||||
|
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
||||||
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -23,21 +29,23 @@ import java.util.Set;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||||
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
||||||
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
||||||
|
|
||||||
public abstract class BaseActivity extends AppCompatActivity
|
public abstract class BaseActivity extends AppCompatActivity
|
||||||
implements DestroyableContext {
|
implements DestroyableContext, OnTapFilteredListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected ScreenFilterMonitor screenFilterMonitor;
|
||||||
|
|
||||||
protected ActivityComponent activityComponent;
|
protected ActivityComponent activityComponent;
|
||||||
|
|
||||||
private final List<ActivityLifecycleController> lifecycleControllers =
|
private final List<ActivityLifecycleController> lifecycleControllers =
|
||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
private boolean destroyed = false;
|
private boolean destroyed = false;
|
||||||
|
private ScreenFilterDialogFragment dialogFrag;
|
||||||
@Inject
|
|
||||||
protected ScreenFilterMonitor screenFilterMonitor;
|
|
||||||
private SFDialogFragment dialogFrag;
|
|
||||||
|
|
||||||
public abstract void injectActivity(ActivityComponent component);
|
public abstract void injectActivity(ActivityComponent component);
|
||||||
|
|
||||||
@@ -65,7 +73,6 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||||||
for (ActivityLifecycleController alc : lifecycleControllers) {
|
for (ActivityLifecycleController alc : lifecycleControllers) {
|
||||||
alc.onActivityCreate(this);
|
alc.onActivityCreate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityComponent getActivityComponent() {
|
public ActivityComponent getActivityComponent() {
|
||||||
@@ -97,12 +104,6 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostResume() {
|
|
||||||
super.onPostResume();
|
|
||||||
showNewScreenFilterWarning();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
@@ -112,18 +113,14 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void showNewScreenFilterWarning() {
|
private void showScreenFilterWarning() {
|
||||||
final Set<String> apps = screenFilterMonitor.getApps();
|
if (dialogFrag != null && dialogFrag.isVisible()) return;
|
||||||
if (apps.isEmpty()) {
|
Set<String> apps = screenFilterMonitor.getApps();
|
||||||
return;
|
if (apps.isEmpty()) return;
|
||||||
}
|
dialogFrag =
|
||||||
dialogFrag = SFDialogFragment.newInstance(new ArrayList<>(apps));
|
ScreenFilterDialogFragment.newInstance(new ArrayList<>(apps));
|
||||||
dialogFrag.setCancelable(false);
|
dialogFrag.setCancelable(false);
|
||||||
dialogFrag.show(getSupportFragmentManager(), "SFDialog");
|
dialogFrag.show(getSupportFragmentManager(), dialogFrag.getTag());
|
||||||
}
|
|
||||||
|
|
||||||
public void rememberShownApps(ArrayList<String> s, boolean permanent) {
|
|
||||||
screenFilterMonitor.storeAppsAsShown(s, permanent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -161,4 +158,70 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||||||
supportFinishAfterTransition();
|
supportFinishAfterTransition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wraps the given view in a wrapper that notifies this activity when an
|
||||||
|
* obscured touch has been filtered, and returns the wrapper.
|
||||||
|
*/
|
||||||
|
private View makeTapSafeWrapper(View v) {
|
||||||
|
TapSafeFrameLayout wrapper = new TapSafeFrameLayout(this);
|
||||||
|
wrapper.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
|
||||||
|
wrapper.setOnTapFilteredListener(this);
|
||||||
|
wrapper.addView(v);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds the AppCompat toolbar, if any, and configures it to filter
|
||||||
|
* obscured touches. If a custom toolbar is used, it will be part of the
|
||||||
|
* content view and thus protected by the wrapper. But the default toolbar
|
||||||
|
* is outside the wrapper.
|
||||||
|
*/
|
||||||
|
private void protectToolbar() {
|
||||||
|
View decorView = getWindow().getDecorView();
|
||||||
|
if (decorView instanceof ViewGroup) {
|
||||||
|
Toolbar toolbar = findToolbar((ViewGroup) decorView);
|
||||||
|
if (toolbar != null) toolbar.setFilterTouchesWhenObscured(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Toolbar findToolbar(ViewGroup vg) {
|
||||||
|
for (int i = 0, len = vg.getChildCount(); i < len; i++) {
|
||||||
|
View child = vg.getChildAt(i);
|
||||||
|
if (child instanceof Toolbar) return (Toolbar) child;
|
||||||
|
if (child instanceof ViewGroup) {
|
||||||
|
Toolbar toolbar = findToolbar((ViewGroup) child);
|
||||||
|
if (toolbar != null) return toolbar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContentView(@LayoutRes int layoutRes) {
|
||||||
|
setContentView(getLayoutInflater().inflate(layoutRes, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContentView(View v) {
|
||||||
|
super.setContentView(makeTapSafeWrapper(v));
|
||||||
|
protectToolbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContentView(View v, LayoutParams layoutParams) {
|
||||||
|
super.setContentView(makeTapSafeWrapper(v), layoutParams);
|
||||||
|
protectToolbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addContentView(View v, LayoutParams layoutParams) {
|
||||||
|
super.addContentView(makeTapSafeWrapper(v), layoutParams);
|
||||||
|
protectToolbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTapFiltered() {
|
||||||
|
showScreenFilterWarning();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -20,8 +21,10 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.view.View.INVISIBLE;
|
import static android.view.View.INVISIBLE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.MIN_DATE_RESOLUTION;
|
import static org.briarproject.briar.android.util.UiUtils.MIN_DATE_RESOLUTION;
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -58,6 +61,20 @@ abstract class BasePostFragment extends BaseFragment {
|
|||||||
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
||||||
progressBar.setVisibility(VISIBLE);
|
progressBar.setVisibility(VISIBLE);
|
||||||
ui = new BlogPostViewHolder(view);
|
ui = new BlogPostViewHolder(view);
|
||||||
|
ui.setOnBlogPostClickListener(new OnBlogPostClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onBlogPostClick(BlogPostItem post) {
|
||||||
|
// We're already there
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthorClick(BlogPostItem post) {
|
||||||
|
Intent i = new Intent(getContext(), BlogActivity.class);
|
||||||
|
i.putExtra(GROUP_ID, post.getGroupId().getBytes());
|
||||||
|
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
getContext().startActivity(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class BlogControllerImpl extends BaseControllerImpl
|
|||||||
BlogInvitationResponseReceivedEvent b =
|
BlogInvitationResponseReceivedEvent b =
|
||||||
(BlogInvitationResponseReceivedEvent) e;
|
(BlogInvitationResponseReceivedEvent) e;
|
||||||
InvitationResponse r = b.getResponse();
|
InvitationResponse r = b.getResponse();
|
||||||
if (r.getGroupId().equals(groupId) && r.wasAccepted()) {
|
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
||||||
LOG.info("Blog invitation accepted");
|
LOG.info("Blog invitation accepted");
|
||||||
onBlogInvitationAccepted(b.getContactId());
|
onBlogInvitationAccepted(b.getContactId());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import org.briarproject.briar.R;
|
|||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.blog.BlogController.BlogSharingListener;
|
import org.briarproject.briar.android.blog.BlogController.BlogSharingListener;
|
||||||
import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
|
|
||||||
import org.briarproject.briar.android.controller.SharingController;
|
import org.briarproject.briar.android.controller.SharingController;
|
||||||
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
@@ -216,10 +215,19 @@ public class BlogFragment extends BaseFragment
|
|||||||
showNextFragment(f);
|
showNextFragment(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthorClick(BlogPostItem post) {
|
||||||
|
if (post.getGroupId().equals(groupId)) return; // We're already there
|
||||||
|
Intent i = new Intent(getContext(), BlogActivity.class);
|
||||||
|
i.putExtra(GROUP_ID, post.getGroupId().getBytes());
|
||||||
|
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
getContext().startActivity(i);
|
||||||
|
}
|
||||||
|
|
||||||
private void loadBlogPosts(final boolean reload) {
|
private void loadBlogPosts(final boolean reload) {
|
||||||
blogController.loadBlogPosts(
|
blogController.loadBlogPosts(
|
||||||
new UiResultExceptionHandler<Collection<BlogPostItem>, DbException>(
|
new UiResultExceptionHandler<Collection<BlogPostItem>,
|
||||||
this) {
|
DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(Collection<BlogPostItem> posts) {
|
public void onResultUi(Collection<BlogPostItem> posts) {
|
||||||
if (posts.isEmpty()) {
|
if (posts.isEmpty()) {
|
||||||
@@ -257,13 +265,13 @@ public class BlogFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setToolbarTitle(Author a) {
|
private void setToolbarTitle(Author a) {
|
||||||
String title = getString(R.string.blogs_personal_blog, a.getName());
|
getActivity().setTitle(a.getName());
|
||||||
getActivity().setTitle(title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSharedContacts() {
|
private void loadSharedContacts() {
|
||||||
blogController.loadSharingContacts(
|
blogController.loadSharingContacts(
|
||||||
new UiResultExceptionHandler<Collection<ContactId>, DbException>(this) {
|
new UiResultExceptionHandler<Collection<ContactId>,
|
||||||
|
DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(Collection<ContactId> contacts) {
|
public void onResultUi(Collection<ContactId> contacts) {
|
||||||
sharingController.addAll(contacts);
|
sharingController.addAll(contacts);
|
||||||
|
|||||||
@@ -48,8 +48,4 @@ class BlogPostAdapter
|
|||||||
return a.getId().equals(b.getId());
|
return a.getId().equals(b.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnBlogPostClickListener {
|
|
||||||
void onBlogPostClick(BlogPostItem post);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.widget.TextView;
|
|||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
|
|
||||||
import org.briarproject.briar.android.view.AuthorView;
|
import org.briarproject.briar.android.view.AuthorView;
|
||||||
import org.briarproject.briar.api.blog.BlogCommentHeader;
|
import org.briarproject.briar.api.blog.BlogCommentHeader;
|
||||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
import org.briarproject.briar.api.blog.BlogPostHeader;
|
||||||
@@ -49,6 +48,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
private final TextView body;
|
private final TextView body;
|
||||||
private final ViewGroup commentContainer;
|
private final ViewGroup commentContainer;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private OnBlogPostClickListener listener;
|
private OnBlogPostClickListener listener;
|
||||||
|
|
||||||
BlogPostViewHolder(View v) {
|
BlogPostViewHolder(View v) {
|
||||||
@@ -111,10 +111,15 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
author.setPersona(
|
author.setPersona(
|
||||||
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
||||||
// TODO make author clickable more often #624
|
// TODO make author clickable more often #624
|
||||||
if (item.getHeader().getType() == POST) {
|
if (listener != null && item.getHeader().getType() == POST) {
|
||||||
author.setBlogLink(post.getGroupId());
|
author.setAuthorClickable(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
listener.onAuthorClick(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
author.unsetBlogLink();
|
author.setAuthorNotClickable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// post body
|
// post body
|
||||||
@@ -165,7 +170,14 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
reblogger.setAuthor(item.getAuthor());
|
reblogger.setAuthor(item.getAuthor());
|
||||||
reblogger.setAuthorStatus(item.getAuthorStatus());
|
reblogger.setAuthorStatus(item.getAuthorStatus());
|
||||||
reblogger.setDate(item.getTimestamp());
|
reblogger.setDate(item.getTimestamp());
|
||||||
reblogger.setBlogLink(item.getGroupId());
|
if (listener != null) {
|
||||||
|
reblogger.setAuthorClickable(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
listener.onAuthorClick(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
reblogger.setVisibility(VISIBLE);
|
reblogger.setVisibility(VISIBLE);
|
||||||
reblogger.setPersona(AuthorView.REBLOGGER);
|
reblogger.setPersona(AuthorView.REBLOGGER);
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
|
|
||||||
import org.briarproject.briar.android.blog.FeedController.FeedListener;
|
import org.briarproject.briar.android.blog.FeedController.FeedListener;
|
||||||
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
@@ -34,6 +33,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.app.Activity.RESULT_OK;
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.support.design.widget.Snackbar.LENGTH_LONG;
|
import static android.support.design.widget.Snackbar.LENGTH_LONG;
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_WRITE_BLOG_POST;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_WRITE_BLOG_POST;
|
||||||
@@ -223,6 +223,14 @@ public class FeedFragment extends BaseFragment implements
|
|||||||
showNextFragment(f);
|
showNextFragment(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthorClick(BlogPostItem post) {
|
||||||
|
Intent i = new Intent(getContext(), BlogActivity.class);
|
||||||
|
i.putExtra(GROUP_ID, post.getGroupId().getBytes());
|
||||||
|
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
getContext().startActivity(i);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUniqueTag() {
|
public String getUniqueTag() {
|
||||||
return TAG;
|
return TAG;
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
|
interface OnBlogPostClickListener {
|
||||||
|
|
||||||
|
void onBlogPostClick(BlogPostItem post);
|
||||||
|
|
||||||
|
void onAuthorClick(BlogPostItem post);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import android.os.Bundle;
|
|||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Patterns;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -20,9 +21,12 @@ import org.briarproject.briar.android.activity.BriarActivity;
|
|||||||
import org.briarproject.briar.api.feed.FeedManager;
|
import org.briarproject.briar.api.feed.FeedManager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
@@ -98,10 +102,17 @@ public class RssFeedImportActivity extends BriarActivity {
|
|||||||
|
|
||||||
private void enableOrDisableImportButton() {
|
private void enableOrDisableImportButton() {
|
||||||
String url = urlInput.getText().toString();
|
String url = urlInput.getText().toString();
|
||||||
if (url.startsWith("http://") || url.startsWith("https://"))
|
importButton.setEnabled(validateAndNormaliseUrl(url) != null);
|
||||||
importButton.setEnabled(true);
|
}
|
||||||
else
|
|
||||||
importButton.setEnabled(false);
|
@Nullable
|
||||||
|
private String validateAndNormaliseUrl(String url) {
|
||||||
|
if (!Patterns.WEB_URL.matcher(url).matches()) return null;
|
||||||
|
try {
|
||||||
|
return new URL(url).toString();
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publish() {
|
private void publish() {
|
||||||
@@ -109,7 +120,9 @@ public class RssFeedImportActivity extends BriarActivity {
|
|||||||
importButton.setVisibility(GONE);
|
importButton.setVisibility(GONE);
|
||||||
progressBar.setVisibility(VISIBLE);
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
|
||||||
importFeed(urlInput.getText().toString());
|
String url = validateAndNormaliseUrl(urlInput.getText().toString());
|
||||||
|
if (url == null) throw new AssertionError();
|
||||||
|
importFeed(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void importFeed(final String url) {
|
private void importFeed(final String url) {
|
||||||
|
|||||||
@@ -178,8 +178,6 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
notificationManager.blockAllContactNotifications();
|
|
||||||
notificationManager.clearAllContactNotifications();
|
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
loadContacts();
|
loadContacts();
|
||||||
list.startPeriodicUpdate();
|
list.startPeriodicUpdate();
|
||||||
@@ -189,7 +187,6 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
|||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
eventBus.removeListener(this);
|
eventBus.removeListener(this);
|
||||||
notificationManager.unblockAllContactNotifications();
|
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
list.showProgressBar();
|
list.showProgressBar();
|
||||||
list.stopPeriodicUpdate();
|
list.stopPeriodicUpdate();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.forum;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@@ -38,16 +39,15 @@ import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LEN
|
|||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class CreateForumActivity extends BriarActivity
|
public class CreateForumActivity extends BriarActivity {
|
||||||
implements OnEditorActionListener, OnClickListener {
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(CreateForumActivity.class.getName());
|
Logger.getLogger(CreateForumActivity.class.getName());
|
||||||
|
|
||||||
|
private TextInputLayout nameEntryLayout;
|
||||||
private EditText nameEntry;
|
private EditText nameEntry;
|
||||||
private Button createForumButton;
|
private Button createForumButton;
|
||||||
private ProgressBar progress;
|
private ProgressBar progress;
|
||||||
private TextView feedback;
|
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
@Inject
|
@Inject
|
||||||
@@ -59,12 +59,10 @@ public class CreateForumActivity extends BriarActivity
|
|||||||
|
|
||||||
setContentView(R.layout.activity_create_forum);
|
setContentView(R.layout.activity_create_forum);
|
||||||
|
|
||||||
|
nameEntryLayout =
|
||||||
|
(TextInputLayout) findViewById(R.id.createForumNameLayout);
|
||||||
nameEntry = (EditText) findViewById(R.id.createForumNameEntry);
|
nameEntry = (EditText) findViewById(R.id.createForumNameEntry);
|
||||||
TextWatcher nameEntryWatcher = new TextWatcher() {
|
nameEntry.addTextChangedListener(new TextWatcher() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count,
|
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||||
@@ -72,21 +70,39 @@ public class CreateForumActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence text, int start,
|
public void onTextChanged(CharSequence s, int start,
|
||||||
int lengthBefore, int lengthAfter) {
|
int lengthBefore, int lengthAfter) {
|
||||||
enableOrDisableCreateButton();
|
enableOrDisableCreateButton();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
nameEntry.setOnEditorActionListener(this);
|
|
||||||
nameEntry.addTextChangedListener(nameEntryWatcher);
|
|
||||||
|
|
||||||
feedback = (TextView) findViewById(R.id.createForumFeedback);
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
nameEntry.setOnEditorActionListener(new OnEditorActionListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onEditorAction(TextView v, int actionId,
|
||||||
|
KeyEvent e) {
|
||||||
|
createForum();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
createForumButton = (Button) findViewById(R.id.createForumButton);
|
createForumButton = (Button) findViewById(R.id.createForumButton);
|
||||||
createForumButton.setOnClickListener(this);
|
createForumButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
createForum();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
progress = (ProgressBar) findViewById(R.id.createForumProgressBar);
|
progress = (ProgressBar) findViewById(R.id.createForumProgressBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
showSoftKeyboard(nameEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,36 +111,27 @@ public class CreateForumActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void enableOrDisableCreateButton() {
|
private void enableOrDisableCreateButton() {
|
||||||
if (progress == null) return; // Not created yet
|
if (createForumButton == null) return; // Not created yet
|
||||||
createForumButton.setEnabled(validateName());
|
createForumButton.setEnabled(validateName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) {
|
|
||||||
hideSoftKeyboard(textView);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean validateName() {
|
private boolean validateName() {
|
||||||
String name = nameEntry.getText().toString();
|
String name = nameEntry.getText().toString();
|
||||||
int length = StringUtils.toUtf8(name).length;
|
int length = StringUtils.toUtf8(name).length;
|
||||||
if (length > MAX_FORUM_NAME_LENGTH) {
|
if (length > MAX_FORUM_NAME_LENGTH) {
|
||||||
feedback.setText(R.string.name_too_long);
|
nameEntryLayout.setError(getString(R.string.name_too_long));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
feedback.setText("");
|
nameEntryLayout.setError(null);
|
||||||
return length > 0;
|
return length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void createForum() {
|
||||||
public void onClick(View view) {
|
if (!validateName()) return;
|
||||||
if (view == createForumButton) {
|
hideSoftKeyboard(nameEntry);
|
||||||
hideSoftKeyboard(view);
|
createForumButton.setVisibility(GONE);
|
||||||
if (!validateName()) return;
|
progress.setVisibility(VISIBLE);
|
||||||
createForumButton.setVisibility(GONE);
|
storeForum(nameEntry.getText().toString());
|
||||||
progress.setVisibility(VISIBLE);
|
|
||||||
storeForum(nameEntry.getText().toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeForum(final String name) {
|
private void storeForum(final String name) {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class ForumControllerImpl extends
|
|||||||
(ForumInvitationResponseReceivedEvent) e;
|
(ForumInvitationResponseReceivedEvent) e;
|
||||||
ForumInvitationResponse r =
|
ForumInvitationResponse r =
|
||||||
(ForumInvitationResponse) f.getResponse();
|
(ForumInvitationResponse) f.getResponse();
|
||||||
if (r.getGroupId().equals(getGroupId()) && r.wasAccepted()) {
|
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) {
|
||||||
LOG.info("Forum invitation was accepted");
|
LOG.info("Forum invitation was accepted");
|
||||||
onForumInvitationAccepted(r.getContactId());
|
onForumInvitationAccepted(r.getContactId());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,8 +119,6 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
notificationManager.blockAllForumPostNotifications();
|
|
||||||
notificationManager.clearAllForumPostNotifications();
|
|
||||||
loadForums();
|
loadForums();
|
||||||
loadAvailableForums();
|
loadAvailableForums();
|
||||||
list.startPeriodicUpdate();
|
list.startPeriodicUpdate();
|
||||||
@@ -129,7 +127,6 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
notificationManager.unblockAllForumPostNotifications();
|
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
list.showProgressBar();
|
list.showProgressBar();
|
||||||
list.stopPeriodicUpdate();
|
list.stopPeriodicUpdate();
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package org.briarproject.briar.android.fragment;
|
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.DialogFragment;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
|
||||||
import org.briarproject.briar.R;
|
|
||||||
import org.briarproject.briar.android.activity.BaseActivity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
|
||||||
@ParametersNotNullByDefault
|
|
||||||
public class SFDialogFragment extends DialogFragment {
|
|
||||||
|
|
||||||
public static SFDialogFragment newInstance(ArrayList<String> apps) {
|
|
||||||
SFDialogFragment frag = new SFDialogFragment();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putStringArrayList("apps", apps);
|
|
||||||
frag.setArguments(args);
|
|
||||||
return frag;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
|
||||||
AlertDialog.Builder builder =
|
|
||||||
new AlertDialog.Builder(
|
|
||||||
getActivity(),
|
|
||||||
R.style.BriarDialogThemeNoFilter);
|
|
||||||
builder.setTitle(R.string.screen_filter_title);
|
|
||||||
LayoutInflater li = getActivity().getLayoutInflater();
|
|
||||||
//Pass null here because it's an AlertDialog
|
|
||||||
View v =
|
|
||||||
li.inflate(R.layout.alert_dialog_checkbox, null,
|
|
||||||
false);
|
|
||||||
TextView t = (TextView) v.findViewById(R.id.alert_dialog_text);
|
|
||||||
final ArrayList<String> apps =
|
|
||||||
getArguments().getStringArrayList("apps");
|
|
||||||
t.setText(getString(R.string.screen_filter_body, TextUtils
|
|
||||||
.join("\n", apps)));
|
|
||||||
final CheckBox cb =
|
|
||||||
(CheckBox) v.findViewById(
|
|
||||||
R.id.checkBox_screen_filter_reminder);
|
|
||||||
builder.setNeutralButton(R.string.continue_button,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog,
|
|
||||||
int which) {
|
|
||||||
((BaseActivity) getActivity())
|
|
||||||
.rememberShownApps(apps, cb.isChecked());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setView(v);
|
|
||||||
return builder.create();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package org.briarproject.briar.android.fragment;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public class ScreenFilterDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
|
public static ScreenFilterDialogFragment newInstance(
|
||||||
|
ArrayList<String> apps) {
|
||||||
|
ScreenFilterDialogFragment frag = new ScreenFilterDialogFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putStringArrayList("apps", apps);
|
||||||
|
frag.setArguments(args);
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
|
||||||
|
R.style.BriarDialogThemeNoFilter);
|
||||||
|
builder.setTitle(R.string.screen_filter_title);
|
||||||
|
ArrayList<String> apps = getArguments().getStringArrayList("apps");
|
||||||
|
builder.setMessage(getString(R.string.screen_filter_body,
|
||||||
|
TextUtils.join("\n", apps)));
|
||||||
|
builder.setNeutralButton(R.string.continue_button,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,6 @@ import im.delight.android.identicons.IdenticonDrawable;
|
|||||||
|
|
||||||
import static android.app.Activity.RESULT_OK;
|
import static android.app.Activity.RESULT_OK;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_MESSAGE_LENGTH;
|
||||||
@@ -94,7 +93,6 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
View v = inflater.inflate(R.layout.introduction_message, container,
|
View v = inflater.inflate(R.layout.introduction_message, container,
|
||||||
false);
|
false);
|
||||||
ui = new ViewHolder(v);
|
ui = new ViewHolder(v);
|
||||||
ui.text.setVisibility(GONE);
|
|
||||||
ui.message.setSendButtonEnabled(false);
|
ui.message.setSendButtonEnabled(false);
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
@@ -156,17 +154,11 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
ui.contactName1.setText(c1.getAuthor().getName());
|
ui.contactName1.setText(c1.getAuthor().getName());
|
||||||
ui.contactName2.setText(c2.getAuthor().getName());
|
ui.contactName2.setText(c2.getAuthor().getName());
|
||||||
|
|
||||||
// set introduction text
|
|
||||||
ui.text.setText(String.format(
|
|
||||||
getString(R.string.introduction_message_text),
|
|
||||||
c1.getAuthor().getName(), c2.getAuthor().getName()));
|
|
||||||
|
|
||||||
// set button action
|
// set button action
|
||||||
ui.message.setListener(IntroductionMessageFragment.this);
|
ui.message.setListener(IntroductionMessageFragment.this);
|
||||||
|
|
||||||
// hide progress bar and show views
|
// hide progress bar and show views
|
||||||
ui.progressBar.setVisibility(GONE);
|
ui.progressBar.setVisibility(GONE);
|
||||||
ui.text.setVisibility(VISIBLE);
|
|
||||||
ui.message.setSendButtonEnabled(true);
|
ui.message.setSendButtonEnabled(true);
|
||||||
ui.message.showSoftKeyboard();
|
ui.message.showSoftKeyboard();
|
||||||
}
|
}
|
||||||
@@ -234,7 +226,6 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
private final ProgressBar progressBar;
|
private final ProgressBar progressBar;
|
||||||
private final CircleImageView avatar1, avatar2;
|
private final CircleImageView avatar1, avatar2;
|
||||||
private final TextView contactName1, contactName2;
|
private final TextView contactName1, contactName2;
|
||||||
private final TextView text;
|
|
||||||
private final TextInputView message;
|
private final TextInputView message;
|
||||||
|
|
||||||
private ViewHolder(View v) {
|
private ViewHolder(View v) {
|
||||||
@@ -243,7 +234,6 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
avatar2 = (CircleImageView) v.findViewById(R.id.avatarContact2);
|
avatar2 = (CircleImageView) v.findViewById(R.id.avatarContact2);
|
||||||
contactName1 = (TextView) v.findViewById(R.id.nameContact1);
|
contactName1 = (TextView) v.findViewById(R.id.nameContact1);
|
||||||
contactName2 = (TextView) v.findViewById(R.id.nameContact2);
|
contactName2 = (TextView) v.findViewById(R.id.nameContact2);
|
||||||
text = (TextView) v.findViewById(R.id.introductionText);
|
|
||||||
message = (TextInputView) v
|
message = (TextInputView) v
|
||||||
.findViewById(R.id.introductionMessageView);
|
.findViewById(R.id.introductionMessageView);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.briarproject.briar.android.activity.ActivityComponent;
|
|||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.blog.FeedFragment;
|
import org.briarproject.briar.android.blog.FeedFragment;
|
||||||
import org.briarproject.briar.android.contact.ContactListFragment;
|
import org.briarproject.briar.android.contact.ContactListFragment;
|
||||||
|
import org.briarproject.briar.android.controller.handler.UiResultHandler;
|
||||||
import org.briarproject.briar.android.forum.ForumListFragment;
|
import org.briarproject.briar.android.forum.ForumListFragment;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
||||||
@@ -45,6 +46,9 @@ import javax.inject.Inject;
|
|||||||
import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
|
import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
|
||||||
import static android.support.v4.view.GravityCompat.START;
|
import static android.support.v4.view.GravityCompat.START;
|
||||||
import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
|
import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry;
|
||||||
|
|
||||||
public class NavDrawerActivity extends BriarActivity implements
|
public class NavDrawerActivity extends BriarActivity implements
|
||||||
BaseFragmentListener, TransportStateListener,
|
BaseFragmentListener, TransportStateListener,
|
||||||
@@ -128,6 +132,12 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
updateTransports();
|
updateTransports();
|
||||||
|
controller.showExpiryWarning(new UiResultHandler<Boolean>(this) {
|
||||||
|
@Override
|
||||||
|
public void onResultUi(Boolean showWarning) {
|
||||||
|
if (showWarning) showExpiryWarning();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exitIfStartupFailed(Intent intent) {
|
private void exitIfStartupFailed(Intent intent) {
|
||||||
@@ -254,6 +264,34 @@ public class NavDrawerActivity extends BriarActivity implements
|
|||||||
// Do nothing for now
|
// Do nothing for now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
private void showExpiryWarning() {
|
||||||
|
int daysUntilExpiry = getDaysUntilExpiry();
|
||||||
|
if (daysUntilExpiry < 0) signOut();
|
||||||
|
|
||||||
|
// show expiry warning text
|
||||||
|
final ViewGroup
|
||||||
|
expiryWarning = (ViewGroup) findViewById(R.id.expiryWarning);
|
||||||
|
TextView expiryWarningText =
|
||||||
|
(TextView) expiryWarning.findViewById(R.id.expiryWarningText);
|
||||||
|
expiryWarningText.setText(getResources()
|
||||||
|
.getQuantityString(R.plurals.expiry_warning, daysUntilExpiry,
|
||||||
|
daysUntilExpiry));
|
||||||
|
|
||||||
|
// make close button functional
|
||||||
|
ImageView expiryWarningClose =
|
||||||
|
(ImageView) expiryWarning.findViewById(R.id.expiryWarningClose);
|
||||||
|
expiryWarningClose.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
controller.expiryWarningDismissed();
|
||||||
|
expiryWarning.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expiryWarning.setVisibility(VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeTransports(final LayoutInflater inflater) {
|
private void initializeTransports(final LayoutInflater inflater) {
|
||||||
transports = new ArrayList<>(3);
|
transports = new ArrayList<>(3);
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ package org.briarproject.briar.android.navdrawer;
|
|||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||||
|
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface NavDrawerController extends ActivityLifecycleController {
|
public interface NavDrawerController extends ActivityLifecycleController {
|
||||||
|
|
||||||
boolean isTransportRunning(TransportId transportId);
|
boolean isTransportRunning(TransportId transportId);
|
||||||
|
|
||||||
|
void showExpiryWarning(final ResultHandler<Boolean> handler);
|
||||||
|
|
||||||
|
void expiryWarningDismissed();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.navdrawer;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
@@ -14,7 +15,10 @@ import org.briarproject.bramble.api.plugin.PluginManager;
|
|||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
|
import org.briarproject.bramble.api.plugin.event.TransportDisabledEvent;
|
||||||
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
|
import org.briarproject.bramble.api.plugin.event.TransportEnabledEvent;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
import org.briarproject.briar.android.controller.DbControllerImpl;
|
import org.briarproject.briar.android.controller.DbControllerImpl;
|
||||||
|
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -22,6 +26,9 @@ import java.util.logging.Logger;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
|
||||||
|
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -30,18 +37,21 @@ public class NavDrawerControllerImpl extends DbControllerImpl
|
|||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(NavDrawerControllerImpl.class.getName());
|
Logger.getLogger(NavDrawerControllerImpl.class.getName());
|
||||||
|
private static final String EXPIRY_DATE_WARNING = "expiryDateWarning";
|
||||||
|
|
||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
|
private final SettingsManager settingsManager;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
|
|
||||||
private volatile TransportStateListener listener;
|
private volatile TransportStateListener listener;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
NavDrawerControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
NavDrawerControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||||
LifecycleManager lifecycleManager,
|
LifecycleManager lifecycleManager, PluginManager pluginManager,
|
||||||
PluginManager pluginManager, EventBus eventBus) {
|
SettingsManager settingsManager, EventBus eventBus) {
|
||||||
super(dbExecutor, lifecycleManager);
|
super(dbExecutor, lifecycleManager);
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
|
this.settingsManager = settingsManager;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +102,63 @@ public class NavDrawerControllerImpl extends DbControllerImpl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showExpiryWarning(final ResultHandler<Boolean> handler) {
|
||||||
|
runOnDbThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Settings settings =
|
||||||
|
settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||||
|
int warningInt = settings.getInt(EXPIRY_DATE_WARNING, 0);
|
||||||
|
|
||||||
|
if (warningInt == 0) {
|
||||||
|
// we have not warned before
|
||||||
|
handler.onResult(true);
|
||||||
|
} else {
|
||||||
|
long warningLong = warningInt * 1000L;
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long daysSinceLastWarning =
|
||||||
|
(now - warningLong) / 1000 / 60 / 60 / 24;
|
||||||
|
long daysBeforeExpiry =
|
||||||
|
(EXPIRY_DATE - now) / 1000 / 60 / 60 / 24;
|
||||||
|
|
||||||
|
if (daysSinceLastWarning >= 30) {
|
||||||
|
handler.onResult(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (daysBeforeExpiry <= 3 && daysSinceLastWarning > 0) {
|
||||||
|
handler.onResult(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handler.onResult(false);
|
||||||
|
}
|
||||||
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void expiryWarningDismissed() {
|
||||||
|
runOnDbThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Settings settings = new Settings();
|
||||||
|
int date = (int) (System.currentTimeMillis() / 1000L);
|
||||||
|
settings.putInt(EXPIRY_DATE_WARNING, date);
|
||||||
|
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
|
||||||
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTransportRunning(TransportId transportId) {
|
public boolean isTransportRunning(TransportId transportId) {
|
||||||
Plugin plugin = pluginManager.getPlugin(transportId);
|
Plugin plugin = pluginManager.getPlugin(transportId);
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class GroupControllerImpl extends
|
|||||||
(GroupInvitationResponseReceivedEvent) e;
|
(GroupInvitationResponseReceivedEvent) e;
|
||||||
final GroupInvitationResponse r =
|
final GroupInvitationResponse r =
|
||||||
(GroupInvitationResponse) g.getResponse();
|
(GroupInvitationResponse) g.getResponse();
|
||||||
if (getGroupId().equals(r.getGroupId()) && r.wasAccepted()) {
|
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
|
||||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
@@ -1,25 +1,15 @@
|
|||||||
package org.briarproject.briar.android.privategroup.conversation;
|
package org.briarproject.briar.android.privategroup.conversation;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
|
|
||||||
import org.briarproject.briar.android.threaded.BaseThreadItemViewHolder;
|
import org.briarproject.briar.android.threaded.BaseThreadItemViewHolder;
|
||||||
import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
|
import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
|
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
|
||||||
import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityIcon;
|
|
||||||
import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityString;
|
|
||||||
import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -27,16 +17,10 @@ class JoinMessageItemViewHolder
|
|||||||
extends BaseThreadItemViewHolder<GroupMessageItem> {
|
extends BaseThreadItemViewHolder<GroupMessageItem> {
|
||||||
|
|
||||||
private final boolean isCreator;
|
private final boolean isCreator;
|
||||||
private final ImageView icon;
|
|
||||||
private final TextView info;
|
|
||||||
private final Button options;
|
|
||||||
|
|
||||||
JoinMessageItemViewHolder(View v, boolean isCreator) {
|
JoinMessageItemViewHolder(View v, boolean isCreator) {
|
||||||
super(v);
|
super(v);
|
||||||
this.isCreator = isCreator;
|
this.isCreator = isCreator;
|
||||||
icon = (ImageView) v.findViewById(R.id.icon);
|
|
||||||
info = (TextView) v.findViewById(R.id.info);
|
|
||||||
options = (Button) v.findViewById(R.id.optionsButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -56,9 +40,6 @@ class JoinMessageItemViewHolder
|
|||||||
getContext().getString(R.string.groups_member_joined,
|
getContext().getString(R.string.groups_member_joined,
|
||||||
item.getAuthor().getName()));
|
item.getAuthor().getName()));
|
||||||
}
|
}
|
||||||
icon.setVisibility(View.GONE);
|
|
||||||
info.setVisibility(View.GONE);
|
|
||||||
options.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind(final JoinMessageItem item) {
|
private void bind(final JoinMessageItem item) {
|
||||||
@@ -75,32 +56,6 @@ class JoinMessageItemViewHolder
|
|||||||
item.getAuthor().getName()));
|
item.getAuthor().getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.getStatus() == OURSELVES || item.getStatus() == UNKNOWN) {
|
|
||||||
icon.setVisibility(View.GONE);
|
|
||||||
info.setVisibility(View.GONE);
|
|
||||||
options.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
icon.setVisibility(View.VISIBLE);
|
|
||||||
icon.setImageResource(getVisibilityIcon(item.getVisibility()));
|
|
||||||
info.setVisibility(View.VISIBLE);
|
|
||||||
info.setText(getVisibilityString(getContext(), item.getVisibility(),
|
|
||||||
item.getAuthor().getName()));
|
|
||||||
if (item.getVisibility() == INVISIBLE) {
|
|
||||||
options.setVisibility(View.VISIBLE);
|
|
||||||
options.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent i =
|
|
||||||
new Intent(ctx, RevealContactsActivity.class);
|
|
||||||
i.putExtra(GROUP_ID, item.getGroupId().getBytes());
|
|
||||||
ctx.startActivity(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
options.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
package org.briarproject.briar.android.privategroup.creation;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
|
||||||
import org.briarproject.briar.android.contactselection.ContactSelectorActivity;
|
|
||||||
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
|
||||||
import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
|
||||||
@ParametersNotNullByDefault
|
|
||||||
public abstract class BaseGroupInviteActivity
|
|
||||||
extends ContactSelectorActivity implements MessageFragmentListener {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
CreateGroupController controller;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void contactsSelected(Collection<ContactId> contacts) {
|
|
||||||
super.contactsSelected(contacts);
|
|
||||||
|
|
||||||
showNextFragment(new CreateGroupMessageFragment());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onButtonClick(String message) {
|
|
||||||
if (groupId == null)
|
|
||||||
throw new IllegalStateException("GroupId was not initialized");
|
|
||||||
controller.sendInvitation(groupId, contacts, message,
|
|
||||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
|
||||||
@Override
|
|
||||||
public void onResultUi(Void result) {
|
|
||||||
setResult(RESULT_OK);
|
|
||||||
supportFinishAfterTransition();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onExceptionUi(DbException exception) {
|
|
||||||
setResult(RESULT_CANCELED);
|
|
||||||
handleDbException(exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaximumMessageLength() {
|
|
||||||
return MAX_GROUP_INVITATION_MSG_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,16 +9,20 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||||
import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class CreateGroupActivity extends BaseGroupInviteActivity implements
|
public class CreateGroupActivity extends BriarActivity
|
||||||
CreateGroupListener, MessageFragmentListener {
|
implements CreateGroupListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CreateGroupController controller;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
@@ -29,32 +33,20 @@ public class CreateGroupActivity extends BaseGroupInviteActivity implements
|
|||||||
public void onCreate(@Nullable Bundle bundle) {
|
public void onCreate(@Nullable Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_fragment_container);
|
||||||
|
|
||||||
if (bundle == null) {
|
if (bundle == null) {
|
||||||
showInitialFragment(new CreateGroupFragment());
|
showInitialFragment(new CreateGroupFragment());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
|
|
||||||
// At this point, the group had been created already,
|
|
||||||
// so don't allow to create it again.
|
|
||||||
openNewGroup();
|
|
||||||
overridePendingTransition(R.anim.screen_old_in,
|
|
||||||
R.anim.screen_new_out);
|
|
||||||
} else {
|
|
||||||
super.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGroupNameChosen(String name) {
|
public void onGroupNameChosen(String name) {
|
||||||
controller.createGroup(name,
|
controller.createGroup(name,
|
||||||
new UiResultExceptionHandler<GroupId, DbException>(this) {
|
new UiResultExceptionHandler<GroupId, DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(GroupId g) {
|
public void onResultUi(GroupId g) {
|
||||||
groupId = g;
|
openNewGroup(g);
|
||||||
switchToContactSelectorFragment(g);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -64,16 +56,10 @@ public class CreateGroupActivity extends BaseGroupInviteActivity implements
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switchToContactSelectorFragment(GroupId g) {
|
private void openNewGroup(GroupId g) {
|
||||||
showNextFragment(GroupInviteFragment.newInstance(g));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openNewGroup() {
|
|
||||||
Intent i = new Intent(this, GroupActivity.class);
|
Intent i = new Intent(this, GroupActivity.class);
|
||||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
i.putExtra(GROUP_ID, g.getBytes());
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
// finish this activity, so we can't come back to it
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,27 @@ package org.briarproject.briar.android.privategroup.creation;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
|
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
|
||||||
|
|
||||||
public class CreateGroupFragment extends BaseFragment {
|
public class CreateGroupFragment extends BaseFragment {
|
||||||
@@ -22,8 +30,10 @@ public class CreateGroupFragment extends BaseFragment {
|
|||||||
public final static String TAG = CreateGroupFragment.class.getName();
|
public final static String TAG = CreateGroupFragment.class.getName();
|
||||||
|
|
||||||
private CreateGroupListener listener;
|
private CreateGroupListener listener;
|
||||||
private EditText name;
|
private EditText nameEntry;
|
||||||
private Button button;
|
private Button createGroupButton;
|
||||||
|
private TextInputLayout nameLayout;
|
||||||
|
private ProgressBar progress;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
@@ -35,42 +45,54 @@ public class CreateGroupFragment extends BaseFragment {
|
|||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
// inflate view
|
|
||||||
View v = inflater.inflate(R.layout.fragment_create_group, container,
|
View v = inflater.inflate(R.layout.fragment_create_group, container,
|
||||||
false);
|
false);
|
||||||
name = (EditText) v.findViewById(R.id.name);
|
nameEntry = (EditText) v.findViewById(R.id.name);
|
||||||
name.addTextChangedListener(new TextWatcher() {
|
nameEntry.addTextChangedListener(new TextWatcher() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count,
|
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||||
int after) {
|
int after) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence s, int start, int before,
|
public void onTextChanged(CharSequence s, int start,
|
||||||
int count) {
|
int lengthBefore, int lengthAfter) {
|
||||||
validateName();
|
enableOrDisableCreateButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
button = (Button) v.findViewById(R.id.button);
|
nameEntry.setOnEditorActionListener(new OnEditorActionListener() {
|
||||||
button.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public boolean onEditorAction(TextView v, int actionId,
|
||||||
listener.hideSoftKeyboard(name);
|
KeyEvent e) {
|
||||||
listener.onGroupNameChosen(name.getText().toString());
|
createGroup();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
nameLayout = (TextInputLayout) v.findViewById(R.id.nameLayout);
|
||||||
|
|
||||||
|
createGroupButton = (Button) v.findViewById(R.id.button);
|
||||||
|
createGroupButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
createGroup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
progress = (ProgressBar) v.findViewById(R.id.progressBar);
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
listener.showSoftKeyboard(name);
|
listener.showSoftKeyboard(nameEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,12 +105,27 @@ public class CreateGroupFragment extends BaseFragment {
|
|||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateName() {
|
private void enableOrDisableCreateButton() {
|
||||||
String name = this.name.getText().toString();
|
if (createGroupButton == null) return; // Not created yet
|
||||||
if (name.length() < 1 || StringUtils.utf8IsTooLong(name, MAX_GROUP_NAME_LENGTH))
|
createGroupButton.setEnabled(validateName());
|
||||||
button.setEnabled(false);
|
|
||||||
else if (!button.isEnabled())
|
|
||||||
button.setEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean validateName() {
|
||||||
|
String name = nameEntry.getText().toString();
|
||||||
|
int length = StringUtils.toUtf8(name).length;
|
||||||
|
if (length > MAX_GROUP_NAME_LENGTH) {
|
||||||
|
nameLayout.setError(getString(R.string.name_too_long));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nameLayout.setError(null);
|
||||||
|
return length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createGroup() {
|
||||||
|
if (!validateName()) return;
|
||||||
|
listener.hideSoftKeyboard(nameEntry);
|
||||||
|
createGroupButton.setVisibility(GONE);
|
||||||
|
progress.setVisibility(VISIBLE);
|
||||||
|
listener.onGroupNameChosen(nameEntry.getText().toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import dagger.Module;
|
|||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
public class GroupCreateModule {
|
public class CreateGroupModule {
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
@Provides
|
@Provides
|
||||||
@@ -3,25 +3,43 @@ package org.briarproject.briar.android.privategroup.creation;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
import org.briarproject.briar.android.contactselection.ContactSelectorActivity;
|
||||||
|
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
import org.briarproject.briar.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
||||||
|
|
||||||
public class GroupInviteActivity extends BaseGroupInviteActivity
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
public class GroupInviteActivity extends ContactSelectorActivity
|
||||||
implements MessageFragmentListener {
|
implements MessageFragmentListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CreateGroupController controller;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(@Nullable Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
byte[] g = i.getByteArrayExtra(GROUP_ID);
|
byte[] g = i.getByteArrayExtra(GROUP_ID);
|
||||||
if (g == null) throw new IllegalStateException("No GroupId in intent.");
|
if (g == null) throw new IllegalStateException("No GroupId in intent");
|
||||||
groupId = new GroupId(g);
|
groupId = new GroupId(g);
|
||||||
|
|
||||||
if (bundle == null) {
|
if (bundle == null) {
|
||||||
@@ -29,4 +47,36 @@ public class GroupInviteActivity extends BaseGroupInviteActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contactsSelected(Collection<ContactId> contacts) {
|
||||||
|
super.contactsSelected(contacts);
|
||||||
|
|
||||||
|
showNextFragment(new CreateGroupMessageFragment());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onButtonClick(String message) {
|
||||||
|
if (groupId == null)
|
||||||
|
throw new IllegalStateException("GroupId was not initialized");
|
||||||
|
controller.sendInvitation(groupId, contacts, message,
|
||||||
|
new UiResultExceptionHandler<Void, DbException>(this) {
|
||||||
|
@Override
|
||||||
|
public void onResultUi(Void result) {
|
||||||
|
setResult(RESULT_OK);
|
||||||
|
supportFinishAfterTransition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onExceptionUi(DbException exception) {
|
||||||
|
setResult(RESULT_CANCELED);
|
||||||
|
handleDbException(exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumMessageLength() {
|
||||||
|
return MAX_GROUP_INVITATION_MSG_LENGTH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,15 +79,12 @@ class GroupListControllerImpl extends DbControllerImpl
|
|||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"GroupListListener needs to be attached");
|
"GroupListListener needs to be attached");
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
notificationManager.blockAllGroupMessageNotifications();
|
|
||||||
notificationManager.clearAllGroupMessageNotifications();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
eventBus.removeListener(this);
|
eventBus.removeListener(this);
|
||||||
notificationManager.unblockAllGroupMessageNotifications();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ class MemberListAdapter extends
|
|||||||
@Override
|
@Override
|
||||||
public boolean areContentsTheSame(MemberListItem m1, MemberListItem m2) {
|
public boolean areContentsTheSame(MemberListItem m1, MemberListItem m2) {
|
||||||
if (m1.isOnline() != m2.isOnline()) return false;
|
if (m1.isOnline() != m2.isOnline()) return false;
|
||||||
if (m1.getVisibility() != m2.getVisibility()) return false;
|
|
||||||
if (m1.getContactId() != m2.getContactId()) return false;
|
if (m1.getContactId() != m2.getContactId()) return false;
|
||||||
if (m1.getStatus() != m2.getStatus()) return false;
|
if (m1.getStatus() != m2.getStatus()) return false;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.identity.Author;
|
|||||||
import org.briarproject.bramble.api.identity.Author.Status;
|
import org.briarproject.bramble.api.identity.Author.Status;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.briar.api.privategroup.GroupMember;
|
import org.briarproject.briar.api.privategroup.GroupMember;
|
||||||
import org.briarproject.briar.api.privategroup.Visibility;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
@@ -39,10 +38,6 @@ class MemberListItem {
|
|||||||
return groupMember.getContactId();
|
return groupMember.getContactId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Visibility getVisibility() {
|
|
||||||
return groupMember.getVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isOnline() {
|
boolean isOnline() {
|
||||||
return online;
|
return online;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ import org.briarproject.briar.R;
|
|||||||
import org.briarproject.briar.android.view.AuthorView;
|
import org.briarproject.briar.android.view.AuthorView;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
|
|
||||||
import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityIcon;
|
|
||||||
import static org.briarproject.briar.android.privategroup.VisibilityHelper.getVisibilityString;
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -22,16 +19,12 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
|
|||||||
private final AuthorView author;
|
private final AuthorView author;
|
||||||
private final ImageView bulb;
|
private final ImageView bulb;
|
||||||
private final TextView creator;
|
private final TextView creator;
|
||||||
private final ImageView icon;
|
|
||||||
private final TextView info;
|
|
||||||
|
|
||||||
MemberListItemHolder(View v) {
|
MemberListItemHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
author = (AuthorView) v.findViewById(R.id.authorView);
|
author = (AuthorView) v.findViewById(R.id.authorView);
|
||||||
bulb = (ImageView) v.findViewById(R.id.bulbView);
|
bulb = (ImageView) v.findViewById(R.id.bulbView);
|
||||||
creator = (TextView) v.findViewById(R.id.creatorView);
|
creator = (TextView) v.findViewById(R.id.creatorView);
|
||||||
icon = (ImageView) v.findViewById(R.id.icon);
|
|
||||||
info = (TextView) v.findViewById(R.id.info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bind(MemberListItem item) {
|
protected void bind(MemberListItem item) {
|
||||||
@@ -64,19 +57,6 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
|
|||||||
} else {
|
} else {
|
||||||
creator.setVisibility(View.GONE);
|
creator.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// visibility information
|
|
||||||
if (item.getStatus() == OURSELVES || item.getStatus() == UNKNOWN) {
|
|
||||||
icon.setVisibility(View.GONE);
|
|
||||||
info.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
icon.setVisibility(View.VISIBLE);
|
|
||||||
icon.setImageResource(getVisibilityIcon(item.getVisibility()));
|
|
||||||
info.setVisibility(View.VISIBLE);
|
|
||||||
info.setText(
|
|
||||||
getVisibilityString(info.getContext(), item.getVisibility(),
|
|
||||||
item.getMember().getName()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.content.Intent;
|
|||||||
import android.media.Ringtone;
|
import android.media.Ringtone;
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.preference.CheckBoxPreference;
|
import android.support.v7.preference.CheckBoxPreference;
|
||||||
import android.support.v7.preference.ListPreference;
|
import android.support.v7.preference.ListPreference;
|
||||||
@@ -54,6 +55,7 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGT
|
|||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
|
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_FORUM;
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_GROUP;
|
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_PRIVATE;
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_NAME;
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_NAME;
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_URI;
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_URI;
|
||||||
@@ -81,6 +83,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
private CheckBoxPreference notifyForumPosts;
|
private CheckBoxPreference notifyForumPosts;
|
||||||
private CheckBoxPreference notifyBlogPosts;
|
private CheckBoxPreference notifyBlogPosts;
|
||||||
private CheckBoxPreference notifyVibration;
|
private CheckBoxPreference notifyVibration;
|
||||||
|
private CheckBoxPreference notifyLockscreen;
|
||||||
|
|
||||||
private Preference notifySound;
|
private Preference notifySound;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
@@ -114,6 +118,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
"pref_key_notify_blog_posts");
|
"pref_key_notify_blog_posts");
|
||||||
notifyVibration = (CheckBoxPreference) findPreference(
|
notifyVibration = (CheckBoxPreference) findPreference(
|
||||||
"pref_key_notify_vibration");
|
"pref_key_notify_vibration");
|
||||||
|
notifyLockscreen = (CheckBoxPreference) findPreference(
|
||||||
|
"pref_key_notify_lock_screen");
|
||||||
notifySound = findPreference("pref_key_notify_sound");
|
notifySound = findPreference("pref_key_notify_sound");
|
||||||
|
|
||||||
enableBluetooth.setOnPreferenceChangeListener(this);
|
enableBluetooth.setOnPreferenceChangeListener(this);
|
||||||
@@ -123,7 +129,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
notifyForumPosts.setOnPreferenceChangeListener(this);
|
notifyForumPosts.setOnPreferenceChangeListener(this);
|
||||||
notifyBlogPosts.setOnPreferenceChangeListener(this);
|
notifyBlogPosts.setOnPreferenceChangeListener(this);
|
||||||
notifyVibration.setOnPreferenceChangeListener(this);
|
notifyVibration.setOnPreferenceChangeListener(this);
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
notifyLockscreen.setVisible(true);
|
||||||
|
notifyLockscreen.setOnPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
notifySound.setOnPreferenceClickListener(
|
notifySound.setOnPreferenceClickListener(
|
||||||
new Preference.OnPreferenceClickListener() {
|
new Preference.OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -234,6 +243,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
notifyVibration.setChecked(settings.getBoolean(
|
notifyVibration.setChecked(settings.getBoolean(
|
||||||
PREF_NOTIFY_VIBRATION, true));
|
PREF_NOTIFY_VIBRATION, true));
|
||||||
|
|
||||||
|
notifyLockscreen.setChecked(settings.getBoolean(
|
||||||
|
PREF_NOTIFY_LOCK_SCREEN, false));
|
||||||
|
|
||||||
String text;
|
String text;
|
||||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
||||||
String ringtoneName =
|
String ringtoneName =
|
||||||
@@ -290,6 +302,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
s.putBoolean(PREF_NOTIFY_VIBRATION, (Boolean) o);
|
s.putBoolean(PREF_NOTIFY_VIBRATION, (Boolean) o);
|
||||||
storeSettings(s);
|
storeSettings(s);
|
||||||
|
} else if (preference == notifyLockscreen) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putBoolean(PREF_NOTIFY_LOCK_SCREEN, (Boolean) o);
|
||||||
|
storeSettings(s);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
|
||||||
import static org.briarproject.briar.android.TestingConstants.DEFAULT_LOG_LEVEL;
|
import static org.briarproject.briar.android.TestingConstants.DEFAULT_LOG_LEVEL;
|
||||||
import static org.briarproject.briar.android.TestingConstants.TESTING;
|
import static org.briarproject.briar.android.TestingConstants.TESTING;
|
||||||
|
|
||||||
@@ -30,9 +31,6 @@ public class SplashScreenActivity extends BaseActivity {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(SplashScreenActivity.class.getName());
|
Logger.getLogger(SplashScreenActivity.class.getName());
|
||||||
|
|
||||||
// This build expires on 1 July 2017
|
|
||||||
private static final long EXPIRY_DATE = 1498863600 * 1000L;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected ConfigController configController;
|
protected ConfigController configController;
|
||||||
@Inject
|
@Inject
|
||||||
@@ -83,10 +81,6 @@ public class SplashScreenActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void showNewScreenFilterWarning() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableStrictMode() {
|
private void enableStrictMode() {
|
||||||
if (TESTING) {
|
if (TESTING) {
|
||||||
ThreadPolicy.Builder threadPolicy = new ThreadPolicy.Builder();
|
ThreadPolicy.Builder threadPolicy = new ThreadPolicy.Builder();
|
||||||
|
|||||||
@@ -142,7 +142,6 @@ public abstract class ThreadListActivity<G extends NamedGroup, A extends ThreadI
|
|||||||
if (replyIdBytes != null) replyId = new MessageId(replyIdBytes);
|
if (replyIdBytes != null) replyId = new MessageId(replyIdBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadItems();
|
|
||||||
sharingController.setSharingListener(this);
|
sharingController.setSharingListener(this);
|
||||||
loadSharingContacts();
|
loadSharingContacts();
|
||||||
}
|
}
|
||||||
@@ -239,6 +238,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, A extends ThreadI
|
|||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
sharingController.onStart();
|
sharingController.onStart();
|
||||||
|
loadItems();
|
||||||
list.startPeriodicUpdate();
|
list.startPeriodicUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,19 +99,21 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityDestroy() {
|
public void onActivityDestroy() {
|
||||||
dbExecutor.execute(new Runnable() {
|
final MessageId messageId = listener.getFirstVisibleMessageId();
|
||||||
@Override
|
if (messageId != null) {
|
||||||
public void run() {
|
dbExecutor.execute(new Runnable() {
|
||||||
try {
|
@Override
|
||||||
messageTracker
|
public void run() {
|
||||||
.storeMessageId(groupId,
|
try {
|
||||||
listener.getFirstVisibleMessageId());
|
messageTracker
|
||||||
} catch (DbException e) {
|
.storeMessageId(groupId, messageId);
|
||||||
if (LOG.isLoggable(WARNING))
|
} catch (DbException e) {
|
||||||
LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import static android.text.format.DateUtils.FORMAT_ABBREV_TIME;
|
|||||||
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
||||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||||
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
|
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
|
||||||
|
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
|
||||||
|
|
||||||
public class UiUtils {
|
public class UiUtils {
|
||||||
|
|
||||||
@@ -64,6 +65,12 @@ public class UiUtils {
|
|||||||
MIN_DATE_RESOLUTION, flags).toString();
|
MIN_DATE_RESOLUTION, flags).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getDaysUntilExpiry() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long daysBeforeExpiry = (EXPIRY_DATE - now) / 1000 / 60 / 60 / 24;
|
||||||
|
return (int) daysBeforeExpiry;
|
||||||
|
}
|
||||||
|
|
||||||
public static SpannableStringBuilder getTeaser(Context ctx, Spanned body) {
|
public static SpannableStringBuilder getTeaser(Context ctx, Spanned body) {
|
||||||
if (body.length() < TEASER_LENGTH)
|
if (body.length() < TEASER_LENGTH)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.briarproject.briar.android.view;
|
package org.briarproject.briar.android.view;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.support.annotation.DimenRes;
|
import android.support.annotation.DimenRes;
|
||||||
@@ -16,9 +15,7 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.Author.Status;
|
import org.briarproject.bramble.api.identity.Author.Status;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.blog.BlogActivity;
|
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -27,12 +24,10 @@ import de.hdodenhof.circleimageview.CircleImageView;
|
|||||||
import im.delight.android.identicons.IdenticonDrawable;
|
import im.delight.android.identicons.IdenticonDrawable;
|
||||||
|
|
||||||
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
|
||||||
import static android.graphics.Typeface.BOLD;
|
import static android.graphics.Typeface.BOLD;
|
||||||
import static android.util.TypedValue.COMPLEX_UNIT_PX;
|
import static android.util.TypedValue.COMPLEX_UNIT_PX;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.NONE;
|
import static org.briarproject.bramble.api.identity.Author.Status.NONE;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public class AuthorView extends RelativeLayout {
|
public class AuthorView extends RelativeLayout {
|
||||||
@@ -110,24 +105,16 @@ public class AuthorView extends RelativeLayout {
|
|||||||
requestLayout();
|
requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlogLink(final GroupId groupId) {
|
public void setAuthorClickable(OnClickListener listener) {
|
||||||
setClickable(true);
|
setClickable(true);
|
||||||
TypedValue outValue = new TypedValue();
|
TypedValue outValue = new TypedValue();
|
||||||
getContext().getTheme().resolveAttribute(
|
getContext().getTheme().resolveAttribute(
|
||||||
android.R.attr.selectableItemBackground, outValue, true);
|
android.R.attr.selectableItemBackground, outValue, true);
|
||||||
setBackgroundResource(outValue.resourceId);
|
setBackgroundResource(outValue.resourceId);
|
||||||
setOnClickListener(new OnClickListener() {
|
setOnClickListener(listener);
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent i = new Intent(getContext(), BlogActivity.class);
|
|
||||||
i.putExtra(GROUP_ID, groupId.getBytes());
|
|
||||||
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
|
||||||
getContext().startActivity(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unsetBlogLink() {
|
public void setAuthorNotClickable() {
|
||||||
setClickable(false);
|
setClickable(false);
|
||||||
setBackgroundResource(android.R.color.transparent);
|
setBackgroundResource(android.R.color.transparent);
|
||||||
setOnClickListener(null);
|
setOnClickListener(null);
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.briarproject.briar.android.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.AttrRes;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static android.view.MotionEvent.FLAG_WINDOW_IS_OBSCURED;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public class TapSafeFrameLayout extends FrameLayout {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private OnTapFilteredListener listener;
|
||||||
|
|
||||||
|
public TapSafeFrameLayout(Context context) {
|
||||||
|
super(context);
|
||||||
|
setFilterTouchesWhenObscured(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TapSafeFrameLayout(Context context, @Nullable AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setFilterTouchesWhenObscured(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TapSafeFrameLayout(Context context, @Nullable AttributeSet attrs,
|
||||||
|
@AttrRes int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
setFilterTouchesWhenObscured(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnTapFilteredListener(OnTapFilteredListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onFilterTouchEventForSecurity(MotionEvent e) {
|
||||||
|
boolean filter = (e.getFlags() & FLAG_WINDOW_IS_OBSCURED) != 0;
|
||||||
|
if (filter && listener != null) listener.onTapFiltered();
|
||||||
|
return !filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnTapFilteredListener {
|
||||||
|
void onTapFiltered();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,19 +18,14 @@ public interface AndroidNotificationManager {
|
|||||||
String PREF_NOTIFY_RINGTONE_NAME = "notifyRingtoneName";
|
String PREF_NOTIFY_RINGTONE_NAME = "notifyRingtoneName";
|
||||||
String PREF_NOTIFY_RINGTONE_URI = "notifyRingtoneUri";
|
String PREF_NOTIFY_RINGTONE_URI = "notifyRingtoneUri";
|
||||||
String PREF_NOTIFY_VIBRATION = "notifyVibration";
|
String PREF_NOTIFY_VIBRATION = "notifyVibration";
|
||||||
|
String PREF_NOTIFY_LOCK_SCREEN = "notifyLockScreen";
|
||||||
|
|
||||||
void clearContactNotification(ContactId c);
|
void clearContactNotification(ContactId c);
|
||||||
|
|
||||||
void clearAllContactNotifications();
|
|
||||||
|
|
||||||
void clearGroupMessageNotification(GroupId g);
|
void clearGroupMessageNotification(GroupId g);
|
||||||
|
|
||||||
void clearAllGroupMessageNotifications();
|
|
||||||
|
|
||||||
void clearForumPostNotification(GroupId g);
|
void clearForumPostNotification(GroupId g);
|
||||||
|
|
||||||
void clearAllForumPostNotifications();
|
|
||||||
|
|
||||||
void clearBlogPostNotification(GroupId g);
|
void clearBlogPostNotification(GroupId g);
|
||||||
|
|
||||||
void clearAllBlogPostNotifications();
|
void clearAllBlogPostNotifications();
|
||||||
@@ -43,18 +38,6 @@ public interface AndroidNotificationManager {
|
|||||||
|
|
||||||
void unblockNotification(GroupId g);
|
void unblockNotification(GroupId g);
|
||||||
|
|
||||||
void blockAllContactNotifications();
|
|
||||||
|
|
||||||
void unblockAllContactNotifications();
|
|
||||||
|
|
||||||
void blockAllGroupMessageNotifications();
|
|
||||||
|
|
||||||
void unblockAllGroupMessageNotifications();
|
|
||||||
|
|
||||||
void blockAllForumPostNotifications();
|
|
||||||
|
|
||||||
void unblockAllForumPostNotifications();
|
|
||||||
|
|
||||||
void blockAllBlogPostNotifications();
|
void blockAllBlogPostNotifications();
|
||||||
|
|
||||||
void unblockAllBlogPostNotifications();
|
void unblockAllBlogPostNotifications();
|
||||||
|
|||||||
@@ -2,14 +2,10 @@ package org.briarproject.briar.api.android;
|
|||||||
|
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface ScreenFilterMonitor {
|
public interface ScreenFilterMonitor {
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
Set<String> getApps();
|
Set<String> getApps();
|
||||||
|
|
||||||
@UiThread
|
|
||||||
void storeAppsAsShown(Collection<String> s, boolean persistent);
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
briar-android/src/main/res/drawable/ic_close.xml
Normal file
9
briar-android/src/main/res/drawable/ic_close.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="18dp"
|
||||||
|
android:height="18dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,44 +1,42 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center_horizontal"
|
android:orientation="vertical"
|
||||||
android:padding="20dp" >
|
android:padding="@dimen/margin_large">
|
||||||
|
|
||||||
<TextView
|
<android.support.design.widget.TextInputLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/createForumNameLayout"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="@dimen/text_size_medium"
|
|
||||||
android:text="@string/choose_forum_name" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/createForumNameEntry"
|
app:errorEnabled="true">
|
||||||
android:maxLines="1"
|
|
||||||
android:inputType="text|textCapSentences" />
|
|
||||||
|
|
||||||
<TextView
|
<EditText
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/createForumNameEntry"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/createForumFeedback"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:hint="@string/choose_forum_hint"
|
||||||
android:paddingLeft="50dp"
|
android:inputType="text|textCapSentences"
|
||||||
android:paddingRight="50dp" />
|
android:maxLines="1"/>
|
||||||
|
|
||||||
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
style="@style/BriarButton"
|
|
||||||
android:id="@+id/createForumButton"
|
android:id="@+id/createForumButton"
|
||||||
android:text="@string/create_forum_button" />
|
style="@style/BriarButton"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="@string/create_forum_button"/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/createForumProgressBar"
|
android:id="@+id/createForumProgressBar"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
android:visibility="gone" />
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -5,5 +5,5 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/expiry_warning"
|
android:text="@string/expiry_date_reached"
|
||||||
android:textSize="@dimen/text_size_large"/>
|
android:textSize="@dimen/text_size_large"/>
|
||||||
@@ -15,6 +15,38 @@
|
|||||||
|
|
||||||
<include layout="@layout/toolbar"/>
|
<include layout="@layout/toolbar"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/expiryWarning"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/briar_warning_background"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="@dimen/margin_medium"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/expiryWarningText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toLeftOf="@+id/expiryWarningClose"
|
||||||
|
android:text="@string/expiry_warning"
|
||||||
|
android:textColor="@color/briar_text_primary_inverse"
|
||||||
|
android:textSize="@dimen/text_size_small"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/expiryWarningClose"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:contentDescription="@string/close"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/ic_close"
|
||||||
|
android:tint="@color/briar_text_tertiary_inverse"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/fragmentContainer"
|
android:id="@+id/fragmentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:hint="@string/blogs_rss_feeds_import_hint"
|
android:hint="@string/blogs_rss_feeds_import_hint"
|
||||||
android:inputType="textMultiLine|textUri"/>
|
android:inputType="textUri"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/importButton"
|
android:id="@+id/importButton"
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<?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:filterTouchesWhenObscured="false"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:fadeScrollbars="false"
|
|
||||||
android:paddingLeft="20dp"
|
|
||||||
android:paddingRight="20dp"
|
|
||||||
android:paddingStart="20dp"
|
|
||||||
android:paddingTop="20dp"
|
|
||||||
android:theme="@style/BriarTheme">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/alert_dialog_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingLeft="3dp"
|
|
||||||
android:paddingRight="6dp"
|
|
||||||
android:text="TextView"
|
|
||||||
android:textAppearance="@style/BriarTextBody"
|
|
||||||
android:theme="@+theme/BriarDialogTheme"/>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/checkBox_screen_filter_reminder"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="15dp"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:layout_weight="0"
|
|
||||||
android:filterTouchesWhenObscured="false"
|
|
||||||
android:text="@string/checkbox_dont_show_again"
|
|
||||||
android:textAppearance="@style/BriarTextBody"/>
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,20 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="@dimen/margin_medium">
|
android:padding="@dimen/margin_large">
|
||||||
|
|
||||||
<EditText
|
<android.support.design.widget.TextInputLayout
|
||||||
android:id="@+id/name"
|
android:id="@+id/nameLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
app:errorEnabled="true">
|
||||||
android:gravity="bottom"
|
|
||||||
android:maxLines="1"
|
<EditText
|
||||||
android:inputType="text|textCapSentences"
|
android:id="@+id/name"
|
||||||
android:hint="@string/groups_create_group_hint"/>
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/groups_create_group_hint"
|
||||||
|
android:inputType="text|textCapSentences"
|
||||||
|
android:maxLines="1"/>
|
||||||
|
|
||||||
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button"
|
android:id="@+id/button"
|
||||||
@@ -22,4 +30,13 @@
|
|||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
android:text="@string/groups_create_group_button"/>
|
android:text="@string/groups_create_group_button"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<ScrollView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
@@ -7,119 +7,100 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ScrollView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/margin_activity_horizontal"
|
android:layout_margin="@dimen/margin_activity_horizontal"
|
||||||
android:orientation="vertical">
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RelativeLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_toLeftOf="@+id/introductionIcon"
|
|
||||||
android:gravity="top|center_horizontal"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<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"/>
|
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.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="@color/briar_text_primary"
|
|
||||||
android:textSize="@dimen/text_size_tiny"
|
|
||||||
tools:text="Contact 1"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/introductionIcon"
|
|
||||||
android:layout_width="@dimen/listitem_picture_size"
|
|
||||||
android:layout_height="@dimen/listitem_picture_size"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:src="@drawable/ic_contact_introduction"
|
|
||||||
tools:ignore="ContentDescription"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_toEndOf="@+id/introductionIcon"
|
|
||||||
android:layout_toRightOf="@+id/introductionIcon"
|
|
||||||
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"/>
|
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.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="@color/briar_text_primary"
|
|
||||||
android:textSize="@dimen/text_size_tiny"
|
|
||||||
tools:text="Contact 2"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/progressBar"
|
|
||||||
style="?android:attr/progressBarStyleLarge"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:gravity="top|center_horizontal"
|
||||||
tools:visibility="gone"/>
|
android:orientation="vertical">
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
android:id="@+id/introductionText"
|
android:id="@+id/avatarContact1"
|
||||||
android:layout_width="match_parent"
|
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"/>
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.components.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="@color/briar_text_primary"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:text="Contact 1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/introductionIcon"
|
||||||
|
android:layout_width="@dimen/listitem_picture_size"
|
||||||
|
android:layout_height="@dimen/listitem_picture_size"
|
||||||
|
android:src="@drawable/ic_contact_introduction"
|
||||||
|
tools:ignore="ContentDescription"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/margin_activity_horizontal"
|
android:gravity="top|center_horizontal"
|
||||||
android:textColor="@color/briar_text_secondary"
|
android:orientation="vertical">
|
||||||
android:textSize="@dimen/text_size_medium"
|
|
||||||
tools:text="@string/introduction_message_text"/>
|
<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"/>
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.components.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="@color/briar_text_primary"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:text="Contact 2"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
tools:visibility="gone"/>
|
||||||
|
|
||||||
<org.briarproject.briar.android.view.LargeTextInputView
|
<org.briarproject.briar.android.view.LargeTextInputView
|
||||||
android:id="@+id/introductionMessageView"
|
android:id="@+id/introductionMessageView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:buttonText="@string/introduction_button"
|
app:buttonText="@string/introduction_button"
|
||||||
app:hint="@string/introduction_message_hint"
|
app:hint="@string/introduction_message_hint"
|
||||||
app:maxLines="5"/>
|
app:maxLines="5"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
@@ -19,57 +19,15 @@
|
|||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
tools:text="@string/groups_member_joined"/>
|
tools:text="@string/groups_member_joined"/>
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignBottom="@+id/info"
|
|
||||||
android:layout_alignLeft="@+id/text"
|
|
||||||
android:layout_alignTop="@+id/info"
|
|
||||||
android:layout_below="@+id/text"
|
|
||||||
android:layout_marginRight="@dimen/margin_medium"
|
|
||||||
android:scaleType="center"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
tools:src="@drawable/ic_visibility"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignEnd="@+id/text"
|
|
||||||
android:layout_alignRight="@+id/text"
|
|
||||||
android:layout_below="@+id/text"
|
|
||||||
android:layout_marginBottom="@dimen/margin_medium"
|
|
||||||
android:layout_toRightOf="@+id/icon"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:minHeight="24dp"
|
|
||||||
android:textColor="@color/briar_text_secondary"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textSize="@dimen/text_size_tiny"
|
|
||||||
android:textStyle="italic"
|
|
||||||
tools:text="@string/groups_reveal_visible_revealed_by_contact"/>
|
|
||||||
|
|
||||||
<org.briarproject.briar.android.view.AuthorView
|
<org.briarproject.briar.android.view.AuthorView
|
||||||
android:id="@+id/author"
|
android:id="@+id/author"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignLeft="@+id/text"
|
android:layout_alignLeft="@+id/text"
|
||||||
android:layout_below="@+id/info"
|
android:layout_alignStart="@+id/text"
|
||||||
android:layout_toLeftOf="@+id/optionsButton"
|
android:layout_below="@+id/text"
|
||||||
app:persona="commenter"/>
|
app:persona="commenter"/>
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/optionsButton"
|
|
||||||
style="@style/BriarButtonFlat.Positive.Tiny"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignBottom="@+id/author"
|
|
||||||
android:layout_alignEnd="@+id/text"
|
|
||||||
android:layout_alignRight="@+id/text"
|
|
||||||
android:layout_below="@+id/info"
|
|
||||||
android:gravity="right|center_vertical"
|
|
||||||
android:text="@string/options"/>
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style="@style/Divider.ThreadItem"
|
style="@style/Divider.ThreadItem"
|
||||||
android:layout_below="@+id/author"
|
android:layout_below="@+id/author"
|
||||||
|
|||||||
@@ -13,11 +13,13 @@
|
|||||||
android:id="@+id/authorView"
|
android:id="@+id/authorView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginBottom="@dimen/margin_small"
|
android:layout_marginBottom="@dimen/margin_small"
|
||||||
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||||
|
android:layout_toStartOf="@+id/bulbView"
|
||||||
android:layout_toLeftOf="@+id/bulbView"
|
android:layout_toLeftOf="@+id/bulbView"
|
||||||
app:persona="list"/>
|
app:persona="list"/>
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@
|
|||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignTop="@+id/authorView"
|
android:layout_alignTop="@+id/authorView"
|
||||||
|
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||||
tools:src="@drawable/contact_connected"/>
|
tools:src="@drawable/contact_connected"/>
|
||||||
|
|
||||||
@@ -39,40 +42,16 @@
|
|||||||
android:layout_below="@+id/authorView"
|
android:layout_below="@+id/authorView"
|
||||||
android:layout_marginBottom="@dimen/margin_small"
|
android:layout_marginBottom="@dimen/margin_small"
|
||||||
android:layout_marginLeft="@dimen/listitem_group_member_indentation"
|
android:layout_marginLeft="@dimen/listitem_group_member_indentation"
|
||||||
|
android:layout_marginStart="@dimen/listitem_group_member_indentation"
|
||||||
android:text="@string/groups_member_created_you"
|
android:text="@string/groups_member_created_you"
|
||||||
android:textColor="@color/briar_text_secondary"
|
android:textColor="@color/briar_text_secondary"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/creatorView"
|
|
||||||
android:layout_marginLeft="@dimen/listitem_group_member_indentation"
|
|
||||||
android:layout_marginRight="@dimen/margin_small"
|
|
||||||
android:contentDescription="@string/forum_invitation_already_sharing"
|
|
||||||
android:src="@drawable/ic_visibility"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/creatorView"
|
|
||||||
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
|
||||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
|
||||||
android:layout_toRightOf="@+id/icon"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:minHeight="24dp"
|
|
||||||
android:textColor="@color/briar_text_secondary"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textSize="@dimen/text_size_tiny"
|
|
||||||
android:textStyle="italic"
|
|
||||||
tools:text="@string/groups_reveal_visible_revealed_by_us"/>
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider"
|
||||||
style="@style/Divider.ContactList"
|
style="@style/Divider.ContactList"
|
||||||
android:layout_below="@+id/info"
|
android:layout_below="@+id/creatorView"
|
||||||
|
android:layout_marginStart="@dimen/listitem_group_member_indentation"
|
||||||
android:layout_marginLeft="@dimen/listitem_group_member_indentation"
|
android:layout_marginLeft="@dimen/listitem_group_member_indentation"
|
||||||
android:layout_marginTop="@dimen/margin_medium"/>
|
android:layout_marginTop="@dimen/margin_medium"/>
|
||||||
|
|
||||||
|
|||||||
@@ -10,16 +10,16 @@
|
|||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_group_reveal"
|
android:id="@+id/action_group_invite"
|
||||||
android:icon="@drawable/ic_visibility_white"
|
android:icon="@drawable/social_share_white"
|
||||||
android:title="@string/groups_reveal_contacts"
|
android:title="@string/groups_invite_members"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_group_invite"
|
android:id="@+id/action_group_reveal"
|
||||||
android:icon="@drawable/ic_add_white"
|
android:icon="@drawable/ic_visibility_white"
|
||||||
android:title="@string/groups_invite_members"
|
android:title="@string/groups_reveal_contacts"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="never"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_group_leave"
|
android:id="@+id/action_group_leave"
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
<string name="text_too_long">Der eingegebene Text ist leider zu lang</string>
|
<string name="text_too_long">Der eingegebene Text ist leider zu lang</string>
|
||||||
<string name="show_onboarding">Hilfe anzeigen</string>
|
<string name="show_onboarding">Hilfe anzeigen</string>
|
||||||
<!--Contacts and Private Conversations-->
|
<!--Contacts and Private Conversations-->
|
||||||
<string name="no_contacts">Du scheinst hier neu zu sein und noch keine Kontakte zu haben.\n\nVerwende das \"+\"-Icon am oberen Bildschirmrand an und folge den Anweisungen um Freunde zu deiner Kontaktliste hinzuzufügen.\n\nDenke daran dass Du neue Kontakte nur dann hinzufügen kannst, wenn Du ihnen physisch begegnest. Das hindert andere daran, sich als Deine Person auszugeben oder Deine Nachrichten zu lesen.</string>
|
<string name="no_contacts">Du scheinst hier neu zu sein und noch keine Kontakte zu haben.\n\nTippe auf das \"+\"-Symbol am oberen Bildschirmrand an und folge den Anweisungen, um Freunde zu deiner Kontaktliste hinzuzufügen.\n\nDenke daran, dass du neue Kontakte nur dann hinzufügen kannst, wenn du ihnen persönlich begegnest. Das hindert andere daran, sich als deine Person auszugeben oder deine Nachrichten zu lesen.</string>
|
||||||
<string name="date_no_private_messages">Keine Nachrichten.</string>
|
<string name="date_no_private_messages">Keine Nachrichten.</string>
|
||||||
<string name="no_private_messages">Das ist die Gesprächsansicht.\n\nEs scheint hier einen Mangel an Gesprächsthemen zu geben.\n\nUm ein neues Gespräch zu beginnen, verwende einfach das Eingabefeld am unteren Bildschirmrand.</string>
|
<string name="no_private_messages">Das ist die Gesprächsansicht.\n\nEs scheint hier einen Mangel an Gesprächsthemen zu geben.\n\nUm ein neues Gespräch zu beginnen, verwende einfach das Eingabefeld am unteren Bildschirmrand.</string>
|
||||||
<string name="message_hint">Nachricht eingeben</string>
|
<string name="message_hint">Nachricht eingeben</string>
|
||||||
@@ -117,8 +117,6 @@
|
|||||||
<string name="introduction_onboarding_text">Du kannst Deine Kontakte untereinander bekannt machen. So können sie sich über Briar verbinden, ohne sich persönlich treffen zu müssen.</string>
|
<string name="introduction_onboarding_text">Du kannst Deine Kontakte untereinander bekannt machen. So können sie sich über Briar verbinden, ohne sich persönlich treffen zu müssen.</string>
|
||||||
<string name="introduction_activity_title">Kontakt auswählen</string>
|
<string name="introduction_activity_title">Kontakt auswählen</string>
|
||||||
<string name="introduction_message_title">Kontakte untereinander bekannt machen</string>
|
<string name="introduction_message_title">Kontakte untereinander bekannt machen</string>
|
||||||
<string name="introduction_message_text">Du kannst eine Nachricht erstellen die mit Deiner Kontaktempfehlung an %1$s und %2$s mitgesendet wird:</string>
|
|
||||||
<string name="introduction_message_hint">Gib eine Nachricht ein (optional)</string>
|
|
||||||
<string name="introduction_button">Kontaktempfehlung abgeben</string>
|
<string name="introduction_button">Kontaktempfehlung abgeben</string>
|
||||||
<string name="introduction_sent">Deine Kontaktempfehlung wurde verschickt</string>
|
<string name="introduction_sent">Deine Kontaktempfehlung wurde verschickt</string>
|
||||||
<string name="introduction_error">Es gab einen Fehler beim Versuch, die Kontaktempfehlung zu verschicken</string>
|
<string name="introduction_error">Es gab einen Fehler beim Versuch, die Kontaktempfehlung zu verschicken</string>
|
||||||
@@ -137,7 +135,7 @@
|
|||||||
<item quantity="other">%d neue Kontakte hinzugefügt.</item>
|
<item quantity="other">%d neue Kontakte hinzugefügt.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<!--Private Groups-->
|
<!--Private Groups-->
|
||||||
<string name="groups_list_empty">Du bist in keiner Gruppe Mitglied.\n\nVerwende das + Symbol am oberen Rand um eine Gruppe zu erstellen oder frage bitte Deine Kontakte um Aufnahme in einer deren Gruppen.</string>
|
<string name="groups_list_empty">Du bist in keiner Gruppe Mitglied.\n\nTippe auf das \"+\"-Symbol am oberen Bildschirmrand, um eine Gruppe zu erstellen, oder frage deine Kontakte um Aufnahme in einer ihrer Gruppen.</string>
|
||||||
<string name="groups_created_by">Erstellt durch %s</string>
|
<string name="groups_created_by">Erstellt durch %s</string>
|
||||||
<plurals name="messages">
|
<plurals name="messages">
|
||||||
<item quantity="one">%d Nachrichten</item>
|
<item quantity="one">%d Nachrichten</item>
|
||||||
@@ -149,7 +147,6 @@
|
|||||||
<string name="groups_create_group_title">Private Gruppe erstellen</string>
|
<string name="groups_create_group_title">Private Gruppe erstellen</string>
|
||||||
<string name="groups_create_group_button">Gruppe erstellen</string>
|
<string name="groups_create_group_button">Gruppe erstellen</string>
|
||||||
<string name="groups_create_group_invitation_button">Einladung schicken</string>
|
<string name="groups_create_group_invitation_button">Einladung schicken</string>
|
||||||
<string name="groups_create_group_hint">Gebe Deiner privaten Gruppe einen Namen</string>
|
|
||||||
<string name="groups_invitation_sent">Gruppeneinladung versendet</string>
|
<string name="groups_invitation_sent">Gruppeneinladung versendet</string>
|
||||||
<string name="groups_message_sent">Nachricht gesendet</string>
|
<string name="groups_message_sent">Nachricht gesendet</string>
|
||||||
<string name="groups_member_list">Mitglieder</string>
|
<string name="groups_member_list">Mitglieder</string>
|
||||||
@@ -190,9 +187,7 @@
|
|||||||
<string name="groups_reveal_visible_revealed_by_contact">Beziehung zum Kontakt ist für diese Gruppe sichtbar (offengelegt durch %s)</string>
|
<string name="groups_reveal_visible_revealed_by_contact">Beziehung zum Kontakt ist für diese Gruppe sichtbar (offengelegt durch %s)</string>
|
||||||
<string name="groups_reveal_invisible">Beziehung zum Kontakt ist für diese Gruppe nicht sichtbar</string>
|
<string name="groups_reveal_invisible">Beziehung zum Kontakt ist für diese Gruppe nicht sichtbar</string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="no_forums">Du hast noch keine Foren.\n\nWarum erstellst du nicht einfach selbst ein neues Forum, indem du auf das \"+\"-Icon am oberen Bildschirmrand tippst?\n\nDu kannst auch deine Kontakte auffordern, Foren mit dir zu teilen.</string>
|
<string name="no_forums">Du hast noch keine Foren.\n\nWarum erstellst du nicht einfach selbst ein neues Forum, indem du auf das \"+\"-Symbol am oberen Bildschirmrand tippst?\n\nDu kannst auch deine Kontakte auffordern, Foren mit dir zu teilen.</string>
|
||||||
<string name="create_forum_title">Neues Forum</string>
|
|
||||||
<string name="choose_forum_name">Wähle einen Namen für dein Forum:</string>
|
|
||||||
<string name="create_forum_button">Forum erstellen</string>
|
<string name="create_forum_button">Forum erstellen</string>
|
||||||
<string name="forum_created_toast">Forum wurde erstellt</string>
|
<string name="forum_created_toast">Forum wurde erstellt</string>
|
||||||
<string name="no_forum_posts">Dieses Forum ist leer.\n\nBenutze das Stift-Icon am oberen Bildschirmrand um den ersten Beitrag zu verfassen.\n\nFühlst du dich einsam hier? Dann teile das Forum mit weiteren Kontakten!</string>
|
<string name="no_forum_posts">Dieses Forum ist leer.\n\nBenutze das Stift-Icon am oberen Bildschirmrand um den ersten Beitrag zu verfassen.\n\nFühlst du dich einsam hier? Dann teile das Forum mit weiteren Kontakten!</string>
|
||||||
@@ -216,7 +211,6 @@
|
|||||||
<string name="activity_share_toolbar_header">Kontakte auswählen</string>
|
<string name="activity_share_toolbar_header">Kontakte auswählen</string>
|
||||||
<string name="no_contacts_selector">Du scheinst hier neu zu sein und noch keine Kontakte zu haben.\n\nBitte komm zurück, wenn du deinen ersten Kontakt hinzugefügt hast.</string>
|
<string name="no_contacts_selector">Du scheinst hier neu zu sein und noch keine Kontakte zu haben.\n\nBitte komm zurück, wenn du deinen ersten Kontakt hinzugefügt hast.</string>
|
||||||
<string name="forum_shared_snackbar">Forum mit gewählten Kontakten geteilt</string>
|
<string name="forum_shared_snackbar">Forum mit gewählten Kontakten geteilt</string>
|
||||||
<string name="forum_share_message">Du kannst eine optionale Einladungsnachricht verfassen, die an die ausgewählten Kontakte geschickt wird.</string>
|
|
||||||
<string name="forum_share_error">Es gab einen Fehler beim Versuch, dieses Forum zu teilen.</string>
|
<string name="forum_share_error">Es gab einen Fehler beim Versuch, dieses Forum zu teilen.</string>
|
||||||
<string name="forum_invitation_received">%1$s hat das Forum \"%2$s\" mit dir geteilt.</string>
|
<string name="forum_invitation_received">%1$s hat das Forum \"%2$s\" mit dir geteilt.</string>
|
||||||
<string name="forum_invitation_sent">Du hast das Forum \"%1$s\" mit %2$s geteilt.</string>
|
<string name="forum_invitation_sent">Du hast das Forum \"%1$s\" mit %2$s geteilt.</string>
|
||||||
@@ -253,7 +247,6 @@
|
|||||||
<string name="blogs_remove_blog_dialog_message">Bist Du sicher, dass Du diesen Blog und alle dazugehörigen Beiträge löschen möchtest?\nBeachte, dass dies nicht den Blog auf Geräten anderer Leute löscht.</string>
|
<string name="blogs_remove_blog_dialog_message">Bist Du sicher, dass Du diesen Blog und alle dazugehörigen Beiträge löschen möchtest?\nBeachte, dass dies nicht den Blog auf Geräten anderer Leute löscht.</string>
|
||||||
<string name="blogs_remove_blog_ok">Blog entfernen</string>
|
<string name="blogs_remove_blog_ok">Blog entfernen</string>
|
||||||
<string name="blogs_blog_removed">Blog wurde entfernt</string>
|
<string name="blogs_blog_removed">Blog wurde entfernt</string>
|
||||||
<string name="blogs_reblog_comment_hint">Füge optionalen Kommentar hinzu</string>
|
|
||||||
<string name="blogs_reblog_button">Rebloggen</string>
|
<string name="blogs_reblog_button">Rebloggen</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">Blog teilen</string>
|
<string name="blogs_sharing_share">Blog teilen</string>
|
||||||
@@ -318,10 +311,6 @@
|
|||||||
<string name="uninstall_setting_summary">Diese Aktion benötigt manuelle Bestätigung im Falle eines Panik-Ereignisses</string>
|
<string name="uninstall_setting_summary">Diese Aktion benötigt manuelle Bestätigung im Falle eines Panik-Ereignisses</string>
|
||||||
<!--Settings Notifications-->
|
<!--Settings Notifications-->
|
||||||
<string name="notification_settings_title">Benachrichtigungen</string>
|
<string name="notification_settings_title">Benachrichtigungen</string>
|
||||||
<string name="notify_private_messages_setting">Benachrichtigungen für private Nachrichten anzeigen</string>
|
|
||||||
<string name="notify_group_messages_setting">Benachrichtigungen für Gruppennachrichten anzeigen</string>
|
|
||||||
<string name="notify_forum_posts_setting">Benachrichtigungen für Forenbeiträge anzeigen</string>
|
|
||||||
<string name="notify_blog_posts_setting">Benachrichtigungen für Blog-Beiträge anzeigen</string>
|
|
||||||
<string name="notify_vibration_setting">Vibration</string>
|
<string name="notify_vibration_setting">Vibration</string>
|
||||||
<string name="notify_sound_setting">Tonsignal</string>
|
<string name="notify_sound_setting">Tonsignal</string>
|
||||||
<string name="notify_sound_setting_default">Standardklingelton</string>
|
<string name="notify_sound_setting_default">Standardklingelton</string>
|
||||||
@@ -354,8 +343,4 @@
|
|||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
<string name="progress_title_logout">Von Briar abmelden ...</string>
|
<string name="progress_title_logout">Von Briar abmelden ...</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
<string name="screen_filter_title">Bildschirmfilter erkannt</string>
|
|
||||||
<string name="screen_filter_body">Diese Apps können andere Apps überlagern:\n\n%1$s \n\nBriar reagiert im Fall einer Überlagerung nicht auf Benutzereingaben.
|
|
||||||
Falls dadurch Probleme in der Verwendung von Briar entstehen, versuche diese Apps zu deaktivieren.\n</string>
|
|
||||||
<string name="checkbox_dont_show_again">Nicht noch einmal für diese Apps warnen</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<!--Setup-->
|
<!--Setup-->
|
||||||
<string name="setup_title">Configuración de Briar</string>
|
<string name="setup_title">Configuración de Briar</string>
|
||||||
<string name="setup_explanation">Tu cuenta de Briar se almacena de manera cifrada en tu teléfono y no en ninguna nube. Si desinstalas Briar u olvidas tu contraseña, no podrás recuperar ni tu cuenta, ni tus datos.</string>
|
<string name="setup_explanation">Tu cuenta de Briar se almacena de manera cifrada en tu dispositivo y no en ninguna nube. Si desinstalas Briar u olvidas tu contraseña, no podrás recuperar ni tu cuenta ni tus datos.</string>
|
||||||
<string name="choose_nickname">Elige tu nombre de usuario</string>
|
<string name="choose_nickname">Elige tu nombre de usuario</string>
|
||||||
<string name="choose_password">Elige tu contraseña</string>
|
<string name="choose_password">Elige tu contraseña</string>
|
||||||
<string name="confirm_password">Confirma tu contraseña</string>
|
<string name="confirm_password">Confirma tu contraseña</string>
|
||||||
@@ -13,10 +13,10 @@
|
|||||||
<!--Login-->
|
<!--Login-->
|
||||||
<string name="enter_password">Introduce tu contraseña:</string>
|
<string name="enter_password">Introduce tu contraseña:</string>
|
||||||
<string name="try_again">Contraseña incorrecta, inténtalo de nuevo</string>
|
<string name="try_again">Contraseña incorrecta, inténtalo de nuevo</string>
|
||||||
<string name="sign_in_button">Registrarse</string>
|
<string name="sign_in_button">Identificarse</string>
|
||||||
<string name="forgotten_password">Olvidé mi contraseña</string>
|
<string name="forgotten_password">Olvidé mi contraseña</string>
|
||||||
<string name="dialog_title_lost_password">Contraseña olvidada</string>
|
<string name="dialog_title_lost_password">Contraseña olvidada</string>
|
||||||
<string name="dialog_message_lost_password">Tu cuenta de Briar se almacena de manera cifrada en tu teléfono y no en ninguna nube, así que no podemos reiniciar tu contraseña. ¿Deseas eliminar tu cuenta y empezar de nuevo?\n\nAdvertencia: Tus identidades, contactos y mensajes se perderán para siempre.</string>
|
<string name="dialog_message_lost_password">Tu cuenta de Briar se almacena de manera cifrada en tu dispositivo y no en ninguna nube, así que no podemos reiniciar tu contraseña. ¿Deseas eliminar tu cuenta y empezar de nuevo?\n\nAdvertencia: tus identidades, contactos y mensajes se perderán para siempre.</string>
|
||||||
<string name="startup_failed_notification_title">Briar no pudo iniciarse</string>
|
<string name="startup_failed_notification_title">Briar no pudo iniciarse</string>
|
||||||
<string name="startup_failed_notification_text">Quizá tengas que reinstalar Briar.</string>
|
<string name="startup_failed_notification_text">Quizá tengas que reinstalar Briar.</string>
|
||||||
<string name="startup_failed_activity_title">Fallo al iniciar Briar</string>
|
<string name="startup_failed_activity_title">Fallo al iniciar Briar</string>
|
||||||
@@ -44,8 +44,8 @@
|
|||||||
<item quantity="other">Tienes %d nuevos mensajes privados.</item>
|
<item quantity="other">Tienes %d nuevos mensajes privados.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="group_message_notification_text">
|
<plurals name="group_message_notification_text">
|
||||||
<item quantity="one"> h</item>
|
<item quantity="one">Tienes un nuevo mensaje de grupo.</item>
|
||||||
<item quantity="other">%d mensajes de grupo nuevos.</item>
|
<item quantity="other">Tienes %d nuevos mensajes de grupo.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="forum_post_notification_text">
|
<plurals name="forum_post_notification_text">
|
||||||
<item quantity="one">Hay una nueva publicación en el foro.</item>
|
<item quantity="one">Hay una nueva publicación en el foro.</item>
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
<string name="text_too_long">El texto es demasiado largo</string>
|
<string name="text_too_long">El texto es demasiado largo</string>
|
||||||
<string name="show_onboarding">Mostrar diálogo de ayuda</string>
|
<string name="show_onboarding">Mostrar diálogo de ayuda</string>
|
||||||
<!--Contacts and Private Conversations-->
|
<!--Contacts and Private Conversations-->
|
||||||
<string name="no_contacts">Parece que eres nuevo por aquí y no tienes aún contactos.\n\nPulsa el ícono + en la parte superior y sigue las instrucciones para añadir amigos a tu lista.\n\nPor favor, recuerda: sólo puedes añadir nuevos contactos cara a cara para evitar que nadie suplante tu identidad o lea tus mensajes en el futuro. </string>
|
<string name="no_contacts">Parece que eres nuevo por aquí y no tienes aún contactos.\n\nPulsa el signo + en la parte superior y sigue las instrucciones para añadir amigos a tu lista.\n\nPor favor, recuerda: sólo puedes añadir nuevos contactos cara a cara para evitar que nadie suplante tu identidad o lea tus mensajes en el futuro. </string>
|
||||||
<string name="date_no_private_messages">Sin mensajes.</string>
|
<string name="date_no_private_messages">Sin mensajes.</string>
|
||||||
<string name="no_private_messages">Ésta es la vista de conversación.\n\nParece que aún no hay ninguna.\n\nPulsa el campo de texto en la parte inferior para empezar la conversación.</string>
|
<string name="no_private_messages">Esta es la vista de conversación.\n\nParece que aún no hay ninguna.\n\nPulsa el campo de texto en la parte inferior para empezar la conversación.</string>
|
||||||
<string name="message_hint">Escribe un mensaje</string>
|
<string name="message_hint">Escribe un mensaje</string>
|
||||||
<string name="delete_contact">Eliminar contacto</string>
|
<string name="delete_contact">Eliminar contacto</string>
|
||||||
<string name="dialog_title_delete_contact">Confirmar eliminación de contacto</string>
|
<string name="dialog_title_delete_contact">Confirmar eliminación de contacto</string>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
<string name="contact_already_exists">El contacto %s ya existe</string>
|
<string name="contact_already_exists">El contacto %s ya existe</string>
|
||||||
<string name="contact_exchange_failed">El intercambio del contacto falló</string>
|
<string name="contact_exchange_failed">El intercambio del contacto falló</string>
|
||||||
<string name="qr_code_invalid">El código QR no es válido</string>
|
<string name="qr_code_invalid">El código QR no es válido</string>
|
||||||
<string name="connecting_to_device">Conectado al dispositivo\u2026</string>
|
<string name="connecting_to_device">Conectando al dispositivo\u2026</string>
|
||||||
<string name="authenticating_with_device">Autentificándose con el dispositivo\u2026</string>
|
<string name="authenticating_with_device">Autentificándose con el dispositivo\u2026</string>
|
||||||
<string name="connection_aborted_local">¡Hemos interumpido la conexión! Esto podría significar que alguien está intentando interceptar la conexión</string>
|
<string name="connection_aborted_local">¡Hemos interumpido la conexión! Esto podría significar que alguien está intentando interceptar la conexión</string>
|
||||||
<string name="connection_aborted_remote">¡La conexión ha sido interrumpida por tu contacto! Esto podría significar que alguien está intentando interceptar la conexión</string>
|
<string name="connection_aborted_remote">¡La conexión ha sido interrumpida por tu contacto! Esto podría significar que alguien está intentando interceptar la conexión</string>
|
||||||
@@ -117,8 +117,7 @@
|
|||||||
<string name="introduction_onboarding_text">Presenta a tus contactos entre sí para ahorrarles encontrarse en persona para poder conectar mediante Briar.</string>
|
<string name="introduction_onboarding_text">Presenta a tus contactos entre sí para ahorrarles encontrarse en persona para poder conectar mediante Briar.</string>
|
||||||
<string name="introduction_activity_title">Seleccionar contacto</string>
|
<string name="introduction_activity_title">Seleccionar contacto</string>
|
||||||
<string name="introduction_message_title">Presentar a dos contactos</string>
|
<string name="introduction_message_title">Presentar a dos contactos</string>
|
||||||
<string name="introduction_message_text">Puedes redactar un mensaje que se enviará a %1$s y a %2$s junto con tu presentación:</string>
|
<string name="introduction_message_hint">Añade un mensaje (opcional)</string>
|
||||||
<string name="introduction_message_hint">Escribe un mensaje (opcional)</string>
|
|
||||||
<string name="introduction_button">Realizar la presentación</string>
|
<string name="introduction_button">Realizar la presentación</string>
|
||||||
<string name="introduction_sent">Tu presentación se ha mandado.</string>
|
<string name="introduction_sent">Tu presentación se ha mandado.</string>
|
||||||
<string name="introduction_error">Ocurrió un error realizando la presentación.</string>
|
<string name="introduction_error">Ocurrió un error realizando la presentación.</string>
|
||||||
@@ -137,7 +136,7 @@
|
|||||||
<item quantity="other">%d nuevos contactos añadido</item>
|
<item quantity="other">%d nuevos contactos añadido</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<!--Private Groups-->
|
<!--Private Groups-->
|
||||||
<string name="groups_list_empty">Aún no participas en ningún grupo.\n\nCrea un grupo pulsando en el ícono + arriba o pide a tus contactos que te inviten a uno de sus grupos.</string>
|
<string name="groups_list_empty">Aún no participas en ningún grupo.\n\nCrea un grupo pulsando en el signo + arriba o pide a tus contactos que te inviten a uno de sus grupos.</string>
|
||||||
<string name="groups_created_by">Creado por %s</string>
|
<string name="groups_created_by">Creado por %s</string>
|
||||||
<plurals name="messages">
|
<plurals name="messages">
|
||||||
<item quantity="one">%d mensaje</item>
|
<item quantity="one">%d mensaje</item>
|
||||||
@@ -149,7 +148,7 @@
|
|||||||
<string name="groups_create_group_title">Crear grupo privado</string>
|
<string name="groups_create_group_title">Crear grupo privado</string>
|
||||||
<string name="groups_create_group_button">Crear grupo</string>
|
<string name="groups_create_group_button">Crear grupo</string>
|
||||||
<string name="groups_create_group_invitation_button">Enviar invitación</string>
|
<string name="groups_create_group_invitation_button">Enviar invitación</string>
|
||||||
<string name="groups_create_group_hint">Dar nombre al grupo privado</string>
|
<string name="groups_create_group_hint">Elige un nombre para tu grupo privado</string>
|
||||||
<string name="groups_invitation_sent">Se ha mandado la invitación de grupo</string>
|
<string name="groups_invitation_sent">Se ha mandado la invitación de grupo</string>
|
||||||
<string name="groups_message_sent">Mensaje enviado</string>
|
<string name="groups_message_sent">Mensaje enviado</string>
|
||||||
<string name="groups_member_list">Integrantes</string>
|
<string name="groups_member_list">Integrantes</string>
|
||||||
@@ -169,7 +168,7 @@
|
|||||||
<string name="groups_dissolved_dialog_message">El creador de este grupo lo ha disuelto.\n\nYa no puedes escribir mensajes al grupo y puede que no recibas todas las publicaciones que se hayan escrito.</string>
|
<string name="groups_dissolved_dialog_message">El creador de este grupo lo ha disuelto.\n\nYa no puedes escribir mensajes al grupo y puede que no recibas todas las publicaciones que se hayan escrito.</string>
|
||||||
<!--Private Group Invitations-->
|
<!--Private Group Invitations-->
|
||||||
<string name="groups_invitations_title">Invitaciones de grupo</string>
|
<string name="groups_invitations_title">Invitaciones de grupo</string>
|
||||||
<string name="groups_invitations_invitation_sent">Has invitado a %1$s a ingresar en el grupo \"%2$s\".</string>
|
<string name="groups_invitations_invitation_sent">Has invitado a %1$s a ingresar en el grupo «%2$s».</string>
|
||||||
<string name="groups_invitations_invitation_received">%1$s te ha invitado a unirte al grupo «%2$s».</string>
|
<string name="groups_invitations_invitation_received">%1$s te ha invitado a unirte al grupo «%2$s».</string>
|
||||||
<string name="groups_invitations_joined">Te uniste al grupo</string>
|
<string name="groups_invitations_joined">Te uniste al grupo</string>
|
||||||
<string name="groups_invitations_declined">Invitación de grupo declinada</string>
|
<string name="groups_invitations_declined">Invitación de grupo declinada</string>
|
||||||
@@ -190,12 +189,10 @@
|
|||||||
<string name="groups_reveal_visible_revealed_by_contact">Las relaciones entre los contactos son visibles al grupo (las reveló %s)</string>
|
<string name="groups_reveal_visible_revealed_by_contact">Las relaciones entre los contactos son visibles al grupo (las reveló %s)</string>
|
||||||
<string name="groups_reveal_invisible">Las relaciones entre los contactos no son visibles al grupo</string>
|
<string name="groups_reveal_invisible">Las relaciones entre los contactos no son visibles al grupo</string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="no_forums">No tienes ningún foro aún.\n\n¿Por qué no creas uno pulsando el ícono + de la parte superior?\n\nTambién puedes pedirle a tus contactos que compartan foros contigo.</string>
|
<string name="no_forums">No tienes ningún foro aún.\n\n¿Por qué no creas uno pulsando el signo + de la parte superior?\n\nTambién puedes pedirle a tus contactos que compartan foros contigo.</string>
|
||||||
<string name="create_forum_title">Nuevo foro</string>
|
|
||||||
<string name="choose_forum_name">Elige un nombre para tu foro:</string>
|
|
||||||
<string name="create_forum_button">Crear foro</string>
|
<string name="create_forum_button">Crear foro</string>
|
||||||
<string name="forum_created_toast">Foro creado</string>
|
<string name="forum_created_toast">Foro creado</string>
|
||||||
<string name="no_forum_posts">Este foro está vacío.\n\nUsa el ícono del lápiz de la parte superior para redactar una primera publicación.\n\n¿No te sientes un poco solo aquí? ¡Comparte este foro con más contactos!</string>
|
<string name="no_forum_posts">Este foro está vacío.\n\nUsa el signo del lápiz de la parte superior para redactar una primera publicación.\n\n¿No te sientes un poco solo aquí? ¡Comparte este foro con más contactos!</string>
|
||||||
<string name="no_posts">Sin publicaciones</string>
|
<string name="no_posts">Sin publicaciones</string>
|
||||||
<plurals name="posts">
|
<plurals name="posts">
|
||||||
<item quantity="one">%d publicación</item>
|
<item quantity="one">%d publicación</item>
|
||||||
@@ -216,7 +213,7 @@
|
|||||||
<string name="activity_share_toolbar_header">Elige contactos</string>
|
<string name="activity_share_toolbar_header">Elige contactos</string>
|
||||||
<string name="no_contacts_selector">Parece que eres nuevo aquí y no tienes contactos aún.\n\nPor favor, vuelve cuando hayas añadido tu primer contacto.</string>
|
<string name="no_contacts_selector">Parece que eres nuevo aquí y no tienes contactos aún.\n\nPor favor, vuelve cuando hayas añadido tu primer contacto.</string>
|
||||||
<string name="forum_shared_snackbar">Foro compartido con los contactos seleccionados</string>
|
<string name="forum_shared_snackbar">Foro compartido con los contactos seleccionados</string>
|
||||||
<string name="forum_share_message">Puedes redactar un mensaje de invitación opcional que se enviará a los contactos seleccionados.</string>
|
<string name="forum_share_message">Añade un mensaje (opcional)</string>
|
||||||
<string name="forum_share_error">Hubo un error compartiendo este foro.</string>
|
<string name="forum_share_error">Hubo un error compartiendo este foro.</string>
|
||||||
<string name="forum_invitation_received">%1$s ha compartido el foro \"%2$s\" contigo.</string>
|
<string name="forum_invitation_received">%1$s ha compartido el foro \"%2$s\" contigo.</string>
|
||||||
<string name="forum_invitation_sent">Has compartido el foro \"%1$s\" con %2$s.</string>
|
<string name="forum_invitation_sent">Has compartido el foro \"%1$s\" con %2$s.</string>
|
||||||
@@ -247,13 +244,13 @@
|
|||||||
<string name="blogs_blog_post_created">Creado artículo del blog</string>
|
<string name="blogs_blog_post_created">Creado artículo del blog</string>
|
||||||
<string name="blogs_blog_post_received">Recibido nuevo artículo del blog</string>
|
<string name="blogs_blog_post_received">Recibido nuevo artículo del blog</string>
|
||||||
<string name="blogs_blog_post_scroll_to">Desplazarse hasta</string>
|
<string name="blogs_blog_post_scroll_to">Desplazarse hasta</string>
|
||||||
<string name="blogs_feed_empty_state">Esta es la lista global de entradas del blog.\n\nParece que nadie ha publicado nada todavía.\n\nSé el primero: pulsa el icono del lápiz para escribir una nueva entrada de blog.</string>
|
<string name="blogs_feed_empty_state">Esta es la lista global de entradas de blogs.\n\nParece que nadie ha publicado nada todavía.\n\nSé el primero: pulsa el signo del lápiz para escribir una nueva entrada de blog.</string>
|
||||||
<string name="blogs_personal_blog">Blog personal de %s</string>
|
<string name="blogs_personal_blog">Blog personal de %s</string>
|
||||||
<string name="blogs_remove_blog">Eliminar blog</string>
|
<string name="blogs_remove_blog">Eliminar blog</string>
|
||||||
<string name="blogs_remove_blog_dialog_message">¿Seguro que quieres eliminar este blog y todos sus artículos?\nTen en cuenta que no se eliminará el blog de los dispositivos de otras personas.</string>
|
<string name="blogs_remove_blog_dialog_message">¿Seguro que quieres eliminar este blog y todos sus artículos?\nTen en cuenta que no se eliminará el blog de los dispositivos de otras personas.</string>
|
||||||
<string name="blogs_remove_blog_ok">Eliminar blog</string>
|
<string name="blogs_remove_blog_ok">Eliminar blog</string>
|
||||||
<string name="blogs_blog_removed">Blog eliminado</string>
|
<string name="blogs_blog_removed">Blog eliminado</string>
|
||||||
<string name="blogs_reblog_comment_hint">Añade un comentario opcional</string>
|
<string name="blogs_reblog_comment_hint">Añade un comentario (opcional)</string>
|
||||||
<string name="blogs_reblog_button">Rebloguear</string>
|
<string name="blogs_reblog_button">Rebloguear</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">Compartir blog</string>
|
<string name="blogs_sharing_share">Compartir blog</string>
|
||||||
@@ -318,13 +315,17 @@
|
|||||||
<string name="uninstall_setting_summary">Requerirá confirmación manual en el momento de pánico</string>
|
<string name="uninstall_setting_summary">Requerirá confirmación manual en el momento de pánico</string>
|
||||||
<!--Settings Notifications-->
|
<!--Settings Notifications-->
|
||||||
<string name="notification_settings_title">Notificaciones</string>
|
<string name="notification_settings_title">Notificaciones</string>
|
||||||
<string name="notify_private_messages_setting">Mostrar alertas para mensajes privados</string>
|
<string name="notify_private_messages_setting_title">Mensajes privados</string>
|
||||||
<string name="notify_group_messages_setting">Mostrar alertas para mensajes de grupo</string>
|
<string name="notify_private_messages_setting_summary">Notificar mensajes privados</string>
|
||||||
<string name="notify_forum_posts_setting">Mostrar alertas para publicaciones de foros</string>
|
<string name="notify_group_messages_setting_title">Mensajes de grupo</string>
|
||||||
<string name="notify_blog_posts_setting">Mostrar alertas para artículos de blogs</string>
|
<string name="notify_group_messages_setting_summary">Notificar mensajes de grupo</string>
|
||||||
|
<string name="notify_forum_posts_setting_title">Publicaciones en foros</string>
|
||||||
|
<string name="notify_forum_posts_setting_summary">Notificar publicaciones en foros</string>
|
||||||
|
<string name="notify_blog_posts_setting_title">Entradas de blog</string>
|
||||||
|
<string name="notify_blog_posts_setting_summary">Notificar entradas de blog</string>
|
||||||
<string name="notify_vibration_setting">Vibrar</string>
|
<string name="notify_vibration_setting">Vibrar</string>
|
||||||
<string name="notify_sound_setting">Sonar</string>
|
<string name="notify_sound_setting">Sonar</string>
|
||||||
<string name="notify_sound_setting_default">Alerta sonora predeterminada</string>
|
<string name="notify_sound_setting_default">Tono de notificación predeterminado</string>
|
||||||
<string name="notify_sound_setting_disabled">Ninguna</string>
|
<string name="notify_sound_setting_disabled">Ninguna</string>
|
||||||
<string name="choose_ringtone_title">Elegir alerta sonora</string>
|
<string name="choose_ringtone_title">Elegir alerta sonora</string>
|
||||||
<!--Settings Feedback-->
|
<!--Settings Feedback-->
|
||||||
@@ -354,8 +355,6 @@
|
|||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
<string name="progress_title_logout">Saliendo de Briar…</string>
|
<string name="progress_title_logout">Saliendo de Briar…</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
<string name="screen_filter_title">Filtro de pantalla detectado</string>
|
<string name="screen_filter_title">Superposición de pantalla detectada</string>
|
||||||
<string name="screen_filter_body">Las siguientes aplicaciones pueden mostrarse por encima de otras:\n\n%1$s \n\nBriar no reaccionará a los toques mientras otra aplicación se muestre encima.
|
<string name="screen_filter_body">Otra aplicación se está mostrando encima de Briar. Por seguridad, Briar no responderá a los toques mientras se muestre otra aplicación encima.\n\nIntenta apagar las siguientes aplicaciones cuando uses Briar:\n\n%1$s</string>
|
||||||
Si experiencia algún problema, pruebe a desactivar esas aplicaciones cuando use Briar.\n</string>
|
|
||||||
<string name="checkbox_dont_show_again">No mostrar más para estas aplicaciones</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -49,11 +49,11 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="forum_post_notification_text">
|
<plurals name="forum_post_notification_text">
|
||||||
<item quantity="one">Nouveau post de forum.</item>
|
<item quantity="one">Nouveau post de forum.</item>
|
||||||
<item quantity="other">%d nouveaux posts de forum.</item>
|
<item quantity="other">%d nouveaux messages de forum.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="blog_post_notification_text">
|
<plurals name="blog_post_notification_text">
|
||||||
<item quantity="one">Nouveau post de blog.</item>
|
<item quantity="one">Nouveau post de blog.</item>
|
||||||
<item quantity="other">%d Nouveaux posts de blog.</item>
|
<item quantity="other">%d Nouveaux messages de blog.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<!--Misc-->
|
<!--Misc-->
|
||||||
<string name="now">Maintenant</string>
|
<string name="now">Maintenant</string>
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
<string name="try_again_button">Essayer à nouveau</string>
|
<string name="try_again_button">Essayer à nouveau</string>
|
||||||
<string name="connected_to_contact">Connecté au contact</string>
|
<string name="connected_to_contact">Connecté au contact</string>
|
||||||
<string name="calculating_confirmation_code">Calcul du code de confirmation\u2026</string>
|
<string name="calculating_confirmation_code">Calcul du code de confirmation\u2026</string>
|
||||||
<string name="your_confirmation_code">Votre code d\'invitation est </string>
|
<string name="your_confirmation_code">Votre code de confirmation est </string>
|
||||||
<string name="enter_confirmation_code">Veuillez saisir le code de confirmation de votre contact :</string>
|
<string name="enter_confirmation_code">Veuillez saisir le code de confirmation de votre contact :</string>
|
||||||
<string name="waiting_for_contact">Attente du contact\u2026</string>
|
<string name="waiting_for_contact">Attente du contact\u2026</string>
|
||||||
<string name="waiting_for_contact_to_scan">En attente de scan et de la connexion du contact\u2026</string>
|
<string name="waiting_for_contact_to_scan">En attente de scan et de la connexion du contact\u2026</string>
|
||||||
@@ -117,8 +117,7 @@
|
|||||||
<string name="introduction_onboarding_text">Vous pouvez introduire vos contacts les uns les autres, ils n\'ont donc pas besoin de se rencontrer pour se connecter avec Briar.</string>
|
<string name="introduction_onboarding_text">Vous pouvez introduire vos contacts les uns les autres, ils n\'ont donc pas besoin de se rencontrer pour se connecter avec Briar.</string>
|
||||||
<string name="introduction_activity_title">Sélectionner contact </string>
|
<string name="introduction_activity_title">Sélectionner contact </string>
|
||||||
<string name="introduction_message_title">Introduire des contacts</string>
|
<string name="introduction_message_title">Introduire des contacts</string>
|
||||||
<string name="introduction_message_text">Vous pouvez composer un message qui sera envoyé à %1$s et %2$s avec votre introduction :</string>
|
<string name="introduction_message_hint">Ajouter un message (optionnel)</string>
|
||||||
<string name="introduction_message_hint">Taper le message (optionnel) </string>
|
|
||||||
<string name="introduction_button">Effectuer l\'introduction</string>
|
<string name="introduction_button">Effectuer l\'introduction</string>
|
||||||
<string name="introduction_sent">Votre admission a été envoyée.</string>
|
<string name="introduction_sent">Votre admission a été envoyée.</string>
|
||||||
<string name="introduction_error">Une erreur s\'est produite lors de l\'admission.</string>
|
<string name="introduction_error">Une erreur s\'est produite lors de l\'admission.</string>
|
||||||
@@ -149,7 +148,7 @@
|
|||||||
<string name="groups_create_group_title">Créer un groupe privé</string>
|
<string name="groups_create_group_title">Créer un groupe privé</string>
|
||||||
<string name="groups_create_group_button">Créer un groupe</string>
|
<string name="groups_create_group_button">Créer un groupe</string>
|
||||||
<string name="groups_create_group_invitation_button">Envoyer invitation</string>
|
<string name="groups_create_group_invitation_button">Envoyer invitation</string>
|
||||||
<string name="groups_create_group_hint">Ajouter un nom au groupe privé</string>
|
<string name="groups_create_group_hint">Choisissez un nom pour votre groupe privé</string>
|
||||||
<string name="groups_invitation_sent">Invitation envoyée au groupe</string>
|
<string name="groups_invitation_sent">Invitation envoyée au groupe</string>
|
||||||
<string name="groups_message_sent">Message envoyé</string>
|
<string name="groups_message_sent">Message envoyé</string>
|
||||||
<string name="groups_member_list">Liste de participants</string>
|
<string name="groups_member_list">Liste de participants</string>
|
||||||
@@ -191,17 +190,15 @@
|
|||||||
<string name="groups_reveal_invisible">Votre lien avec le contact est invisible par le groupe</string>
|
<string name="groups_reveal_invisible">Votre lien avec le contact est invisible par le groupe</string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="no_forums">Vous n\'avez pas de forums.\n\nPourquoi ne pas en créer un en touchant l\'icône + en haut ?\n\nVous pouvez aussi demander à vos contacts d\'en partager avec vous.</string>
|
<string name="no_forums">Vous n\'avez pas de forums.\n\nPourquoi ne pas en créer un en touchant l\'icône + en haut ?\n\nVous pouvez aussi demander à vos contacts d\'en partager avec vous.</string>
|
||||||
<string name="create_forum_title">Nouveau forum</string>
|
|
||||||
<string name="choose_forum_name">Choisissez un nom pour votre forum :</string>
|
|
||||||
<string name="create_forum_button">Créer un forum</string>
|
<string name="create_forum_button">Créer un forum</string>
|
||||||
<string name="forum_created_toast">Forum créé</string>
|
<string name="forum_created_toast">Forum créé</string>
|
||||||
<string name="no_forum_posts">Ce forum est vide.\n\nUtilisez l\'icône crayon, en haut pour écrire le premier post.\n\nVous sentez-vous seul, ici? Partager ce forum avec d\'autres contacts !</string>
|
<string name="no_forum_posts">Ce forum est vide.\n\nUtilisez l\'icône crayon, en haut pour écrire le premier message.\n\nVous sentez-vous seul, ici? Partager ce forum avec d\'autres contacts !</string>
|
||||||
<string name="no_posts">Aucun post</string>
|
<string name="no_posts">Aucun message</string>
|
||||||
<plurals name="posts">
|
<plurals name="posts">
|
||||||
<item quantity="one">%d message</item>
|
<item quantity="one">%d message</item>
|
||||||
<item quantity="other">%d messages</item>
|
<item quantity="other">%d messages</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="forum_new_entry_posted">Entrée de forum postée</string>
|
<string name="forum_new_entry_posted">Message de forum saisi</string>
|
||||||
<string name="forum_new_message_hint">Nouvelle entrée</string>
|
<string name="forum_new_message_hint">Nouvelle entrée</string>
|
||||||
<string name="forum_message_reply_hint">Nouvelle réponse</string>
|
<string name="forum_message_reply_hint">Nouvelle réponse</string>
|
||||||
<string name="btn_reply">Répondre</string>
|
<string name="btn_reply">Répondre</string>
|
||||||
@@ -216,7 +213,7 @@
|
|||||||
<string name="activity_share_toolbar_header">Choisissez des contacts</string>
|
<string name="activity_share_toolbar_header">Choisissez des contacts</string>
|
||||||
<string name="no_contacts_selector">Vous semblez être nouveau ici et n\'avez pas encore de contacts.\n\nRevenez lorsque vous aurez ajouté votre premier contact.</string>
|
<string name="no_contacts_selector">Vous semblez être nouveau ici et n\'avez pas encore de contacts.\n\nRevenez lorsque vous aurez ajouté votre premier contact.</string>
|
||||||
<string name="forum_shared_snackbar">Forum partagé avec les contacts choisis</string>
|
<string name="forum_shared_snackbar">Forum partagé avec les contacts choisis</string>
|
||||||
<string name="forum_share_message">Vous pouvez composer un message d\'invitation optionnel qui sera envoyé aux contacts choisis.</string>
|
<string name="forum_share_message">Ajouter un message (optionnel)</string>
|
||||||
<string name="forum_share_error">Une erreur s\'est produite lors du partage du forum.</string>
|
<string name="forum_share_error">Une erreur s\'est produite lors du partage du forum.</string>
|
||||||
<string name="forum_invitation_received">%1$s a partagé le forum \"%2$s\" avec vous.</string>
|
<string name="forum_invitation_received">%1$s a partagé le forum \"%2$s\" avec vous.</string>
|
||||||
<string name="forum_invitation_sent">Vous avez partagé le forum \"%1$s\" avec %2$s.</string>
|
<string name="forum_invitation_sent">Vous avez partagé le forum \"%1$s\" avec %2$s.</string>
|
||||||
@@ -239,21 +236,21 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="nobody">Personne</string>
|
<string name="nobody">Personne</string>
|
||||||
<!--Blogs-->
|
<!--Blogs-->
|
||||||
<string name="blogs_other_blog_empty_state">Ce blog est actuellement vide.\n\nSoit l\'auteur n\'a encore rien écrit, soit la personne qui l\'a partagé avec vous doit venir en ligne pour que les posts soient synchronisés.</string>
|
<string name="blogs_other_blog_empty_state">Ce blog est actuellement vide.\n\nSoit l\'auteur n\'a encore rien écrit, soit la personne qui l\'a partagé avec vous doit venir en ligne pour que les messages soient synchronisés.</string>
|
||||||
<string name="read_more">Lire la suite</string>
|
<string name="read_more">Lire la suite</string>
|
||||||
<string name="blogs_write_blog_post">Écrire un post de blog</string>
|
<string name="blogs_write_blog_post">Écrire un message de blog</string>
|
||||||
<string name="blogs_write_blog_post_body_hint">Saisir ici votre post de blog</string>
|
<string name="blogs_write_blog_post_body_hint">Saisir ici votre message de blog</string>
|
||||||
<string name="blogs_publish_blog_post">Publier</string>
|
<string name="blogs_publish_blog_post">Publier</string>
|
||||||
<string name="blogs_blog_post_created">Post de blog créé</string>
|
<string name="blogs_blog_post_created">Message de blog créé</string>
|
||||||
<string name="blogs_blog_post_received">Nouveau post de blog reçu</string>
|
<string name="blogs_blog_post_received">Nouveau message de blog reçu</string>
|
||||||
<string name="blogs_blog_post_scroll_to">Défiler jusqu\'à</string>
|
<string name="blogs_blog_post_scroll_to">Défiler jusqu\'à</string>
|
||||||
<string name="blogs_feed_empty_state">Ceci est le flux global des blogs.\n\nIl semble que personne n\'ait encore rien écrit.\n\nSoyez le premier et touchez l\'icône stylet pour écrire un post de blog.</string>
|
<string name="blogs_feed_empty_state">Ceci est le flux global des blogs.\n\nIl semble que personne n\'ait encore rien écrit.\n\nSoyez le premier et touchez l\'icône stylet pour écrire un message de blog.</string>
|
||||||
<string name="blogs_personal_blog">Blog personnel de %s</string>
|
<string name="blogs_personal_blog">Blog personnel de %s</string>
|
||||||
<string name="blogs_remove_blog">Supprimer le blog</string>
|
<string name="blogs_remove_blog">Supprimer le blog</string>
|
||||||
<string name="blogs_remove_blog_dialog_message">Êtes-vous sûr de vouloir supprimer ce blog et tous ses posts ?\nNotez que ceci ne supprimera pas le blog sur les appareils des autres personnes.</string>
|
<string name="blogs_remove_blog_dialog_message">Êtes-vous sûr de vouloir supprimer ce blog et tous ses messages ?\nNotez que ceci ne supprimera pas le blog sur les appareils des autres personnes.</string>
|
||||||
<string name="blogs_remove_blog_ok">Supprimer le blog</string>
|
<string name="blogs_remove_blog_ok">Supprimer le blog</string>
|
||||||
<string name="blogs_blog_removed">Blog supprimé</string>
|
<string name="blogs_blog_removed">Blog supprimé</string>
|
||||||
<string name="blogs_reblog_comment_hint">Ajouter un commentaire optionnel</string>
|
<string name="blogs_reblog_comment_hint">Ajouter un commentaire (optionnel)</string>
|
||||||
<string name="blogs_reblog_button">Reblog</string>
|
<string name="blogs_reblog_button">Reblog</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">Partager le blog</string>
|
<string name="blogs_sharing_share">Partager le blog</string>
|
||||||
@@ -280,7 +277,7 @@
|
|||||||
<string name="blogs_rss_feeds_manage_author">Auteur :</string>
|
<string name="blogs_rss_feeds_manage_author">Auteur :</string>
|
||||||
<string name="blogs_rss_feeds_manage_updated">Dernière mise à jour :</string>
|
<string name="blogs_rss_feeds_manage_updated">Dernière mise à jour :</string>
|
||||||
<string name="blogs_rss_remove_feed">Supprimer le flux</string>
|
<string name="blogs_rss_remove_feed">Supprimer le flux</string>
|
||||||
<string name="blogs_rss_remove_feed_dialog_message">Êtes-vous sûr de vouloir supprimer ce flux et tous ses messages ?\nLes postes que vous avez partagés ne seront pas supprimés des appareils des autres personnes.</string>
|
<string name="blogs_rss_remove_feed_dialog_message">Êtes-vous sûr de vouloir supprimer ce flux et tous ses messages ?\nLes messages que vous avez partagés ne seront pas supprimés des appareils des autres personnes.</string>
|
||||||
<string name="blogs_rss_remove_feed_ok">Supprimer le flux</string>
|
<string name="blogs_rss_remove_feed_ok">Supprimer le flux</string>
|
||||||
<string name="blogs_rss_feeds_manage_delete_error">Le flux n\'a pas pu être supprimé !</string>
|
<string name="blogs_rss_feeds_manage_delete_error">Le flux n\'a pas pu être supprimé !</string>
|
||||||
<string name="blogs_rss_feeds_manage_empty_state">Vous n\'avez importé aucun flux RSS.\n\nPourquoi ne pas cliquer le plus dans le coin en haut à droite pour ajouter votre premier ?</string>
|
<string name="blogs_rss_feeds_manage_empty_state">Vous n\'avez importé aucun flux RSS.\n\nPourquoi ne pas cliquer le plus dans le coin en haut à droite pour ajouter votre premier ?</string>
|
||||||
@@ -318,10 +315,14 @@
|
|||||||
<string name="uninstall_setting_summary">Ceci nécessite une confirmation manuelle en cas d\'événement de panique</string>
|
<string name="uninstall_setting_summary">Ceci nécessite une confirmation manuelle en cas d\'événement de panique</string>
|
||||||
<!--Settings Notifications-->
|
<!--Settings Notifications-->
|
||||||
<string name="notification_settings_title">Notifications</string>
|
<string name="notification_settings_title">Notifications</string>
|
||||||
<string name="notify_private_messages_setting">Afficher les alertes pour les messages privés</string>
|
<string name="notify_private_messages_setting_title">Messages privés</string>
|
||||||
<string name="notify_group_messages_setting">Afficher les alertes pour les messages de groupe</string>
|
<string name="notify_private_messages_setting_summary">Afficher les notifications pour les messages privés</string>
|
||||||
<string name="notify_forum_posts_setting">Afficher les alertes pour les posts de forum</string>
|
<string name="notify_group_messages_setting_title">Messages de groupe</string>
|
||||||
<string name="notify_blog_posts_setting">Afficher les alertes pour les posts de blog</string>
|
<string name="notify_group_messages_setting_summary">Afficher les notifications pour les messages de groupe</string>
|
||||||
|
<string name="notify_forum_posts_setting_title">Messages de forum</string>
|
||||||
|
<string name="notify_forum_posts_setting_summary">Afficher les notifications des messages de forum</string>
|
||||||
|
<string name="notify_blog_posts_setting_title">Messages de blog</string>
|
||||||
|
<string name="notify_blog_posts_setting_summary">Afficher les notifications pour les messages de blog</string>
|
||||||
<string name="notify_vibration_setting">Vibration</string>
|
<string name="notify_vibration_setting">Vibration</string>
|
||||||
<string name="notify_sound_setting">Sonnerie</string>
|
<string name="notify_sound_setting">Sonnerie</string>
|
||||||
<string name="notify_sound_setting_default">Sonnerie par défaut</string>
|
<string name="notify_sound_setting_default">Sonnerie par défaut</string>
|
||||||
@@ -354,8 +355,6 @@
|
|||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
<string name="progress_title_logout">Déconnexion de Briar ...</string>
|
<string name="progress_title_logout">Déconnexion de Briar ...</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
<string name="screen_filter_title">Filtre d\'écran détecté</string>
|
<string name="screen_filter_title">Superposition d\'écran détectée</string>
|
||||||
<string name="screen_filter_body">Les applications suivantes ont l\'autorisation de s\'afficher par dessus d\'autres :\n\n%1$s \n\nBriar ne répondra pas aux touches lorsqu\'une autre application s\'affiche par dessus.
|
<string name="screen_filter_body">Une autre app s\'affiche par dessus Briar. Pour protéger votre sécurité, Briar ne répond pas au toucher lorsqu\'une autre app s\'affiche par dessus.\n\nEssayer de fermer les applications suivantes lorsque vous utilisez Briar :\n\n%1$s</string>
|
||||||
En cas de problèmes, essayer d\'arrêter ces applications durant l\'utilisation de Briar.\n</string>
|
|
||||||
<string name="checkbox_dont_show_again">Ne plus m\'avertir à propos de ces applications</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -21,8 +21,11 @@
|
|||||||
<string name="startup_failed_notification_text">Potresti dover reinstallare Briar</string>
|
<string name="startup_failed_notification_text">Potresti dover reinstallare Briar</string>
|
||||||
<string name="startup_failed_activity_title">Fallimento Avvio Briar</string>
|
<string name="startup_failed_activity_title">Fallimento Avvio Briar</string>
|
||||||
<string name="startup_failed_db_error">Per alcune reagioni, il tuo database Briar si è corrotto in modo irreparabile. Il tuo account, i tuoi dati e tutte le connessioni ai tuoi contatti sono andati persi. Sfortunatamente, devi reinstallare Briar per creare un nuovo account.</string>
|
<string name="startup_failed_db_error">Per alcune reagioni, il tuo database Briar si è corrotto in modo irreparabile. Il tuo account, i tuoi dati e tutte le connessioni ai tuoi contatti sono andati persi. Sfortunatamente, devi reinstallare Briar per creare un nuovo account.</string>
|
||||||
|
<string name="startup_failed_service_error">Briar non è stato in grado di caricare un plugin richiesto. Reinstallare Briar di solito sistema questo problema. Però ricorda che perderai il tuo account e tutti i dati ad esso associati poichè Briar non usa server centralizzati per mantenere i tuoi dati.</string>
|
||||||
<string name="expiry_warning">Questo software è scaduto.\nSi prega di installare una nuova versione.</string>
|
<string name="expiry_warning">Questo software è scaduto.\nSi prega di installare una nuova versione.</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
|
<string name="nav_drawer_open_description">Apri la barra di navigazione</string>
|
||||||
|
<string name="nav_drawer_close_description">Chiudi la barra di navigazione</string>
|
||||||
<string name="contact_list_button">Contatti</string>
|
<string name="contact_list_button">Contatti</string>
|
||||||
<string name="groups_button">Gruppi privati</string>
|
<string name="groups_button">Gruppi privati</string>
|
||||||
<string name="forums_button">Forum</string>
|
<string name="forums_button">Forum</string>
|
||||||
@@ -40,6 +43,10 @@
|
|||||||
<item quantity="one">Nuovo messaggio privato.</item>
|
<item quantity="one">Nuovo messaggio privato.</item>
|
||||||
<item quantity="other">%d nuovi messaggi privati.</item>
|
<item quantity="other">%d nuovi messaggi privati.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="group_message_notification_text">
|
||||||
|
<item quantity="one">Nuovo messaggio di gruppo.</item>
|
||||||
|
<item quantity="other">%d nuovi messaggi di gruppo.</item>
|
||||||
|
</plurals>
|
||||||
<plurals name="forum_post_notification_text">
|
<plurals name="forum_post_notification_text">
|
||||||
<item quantity="one">Nuovo messaggio sul forum.</item>
|
<item quantity="one">Nuovo messaggio sul forum.</item>
|
||||||
<item quantity="other">%d nuovi messaggi sul forum.</item>
|
<item quantity="other">%d nuovi messaggi sul forum.</item>
|
||||||
@@ -54,6 +61,7 @@
|
|||||||
<string name="hide">Nascondi</string>
|
<string name="hide">Nascondi</string>
|
||||||
<string name="ok">OK</string>
|
<string name="ok">OK</string>
|
||||||
<string name="cancel">Annulla</string>
|
<string name="cancel">Annulla</string>
|
||||||
|
<string name="got_it">Ho capito</string>
|
||||||
<string name="delete">Cancella</string>
|
<string name="delete">Cancella</string>
|
||||||
<string name="accept">Accetta</string>
|
<string name="accept">Accetta</string>
|
||||||
<string name="decline">Declina</string>
|
<string name="decline">Declina</string>
|
||||||
@@ -68,14 +76,18 @@
|
|||||||
<string name="text_too_long">Il testo inserito è troppo lungo</string>
|
<string name="text_too_long">Il testo inserito è troppo lungo</string>
|
||||||
<string name="show_onboarding">Mostra l\'aiuto</string>
|
<string name="show_onboarding">Mostra l\'aiuto</string>
|
||||||
<!--Contacts and Private Conversations-->
|
<!--Contacts and Private Conversations-->
|
||||||
|
<string name="no_contacts">Sembra che tu sia nuovo qui e non hai ancora contatti.\n\nPremi l\' icona in alto e segui le istruzioni per aggiungere qualche amico alla tua lista.\n\nPer favore ricorda: Puoi solo aggiungere nuovi contatti faccia-a-faccia per evitare che altri ti impersonino o leggano i tuoi messaggi in futuro.</string>
|
||||||
<string name="date_no_private_messages">Nessun messaggio.</string>
|
<string name="date_no_private_messages">Nessun messaggio.</string>
|
||||||
|
<string name="no_private_messages">Questa è la vista conversazione\n\n\Sembra che ci sia una mancanza di conversazione.\n\nPremi il campo di immissione in basso per iniziare una conversazione.</string>
|
||||||
<string name="message_hint">Scrivi un messaggio</string>
|
<string name="message_hint">Scrivi un messaggio</string>
|
||||||
<string name="delete_contact">Elimina contatto</string>
|
<string name="delete_contact">Elimina contatto</string>
|
||||||
<string name="dialog_title_delete_contact">Conferma cancellazione contatto</string>
|
<string name="dialog_title_delete_contact">Conferma cancellazione contatto</string>
|
||||||
|
<string name="dialog_message_delete_contact">Sei sicuro di voler rimuovere questo contatto e tutti i messaggi scambiati con esso?</string>
|
||||||
<string name="contact_deleted_toast">Contatto cancellato</string>
|
<string name="contact_deleted_toast">Contatto cancellato</string>
|
||||||
<!--Adding Contacts-->
|
<!--Adding Contacts-->
|
||||||
<string name="add_contact_title">Aggiungi un Contatto</string>
|
<string name="add_contact_title">Aggiungi un Contatto</string>
|
||||||
<string name="your_nickname">Scegli l\'identità che vuoi usare:</string>
|
<string name="your_nickname">Scegli l\'identità che vuoi usare:</string>
|
||||||
|
<string name="face_to_face">Devi incontrarti con la persona che vuoi aggiungere come contatto.\n\nQuesto evita che qualcuno ti impersoni o legga i tuoi messaggi in futuro.</string>
|
||||||
<string name="continue_button">Continua</string>
|
<string name="continue_button">Continua</string>
|
||||||
<string name="your_invitation_code">Il tuo codice di invito è</string>
|
<string name="your_invitation_code">Il tuo codice di invito è</string>
|
||||||
<string name="enter_invitation_code">Si prega di inserire il vostro codice di invito di contatto:</string>
|
<string name="enter_invitation_code">Si prega di inserire il vostro codice di invito di contatto:</string>
|
||||||
@@ -88,22 +100,30 @@
|
|||||||
<string name="your_confirmation_code">Il tuo codice di conferma è</string>
|
<string name="your_confirmation_code">Il tuo codice di conferma è</string>
|
||||||
<string name="enter_confirmation_code">Si prega di inserire il vostro codice di conferma di contatto:</string>
|
<string name="enter_confirmation_code">Si prega di inserire il vostro codice di conferma di contatto:</string>
|
||||||
<string name="waiting_for_contact">In attesa del contatto\u2026</string>
|
<string name="waiting_for_contact">In attesa del contatto\u2026</string>
|
||||||
|
<string name="waiting_for_contact_to_scan">Aspettando il contatto per la scansione ed il collegamento\u2026</string>
|
||||||
<string name="exchanging_contact_details">Scambio dettagli contatto\u2026</string>
|
<string name="exchanging_contact_details">Scambio dettagli contatto\u2026</string>
|
||||||
<string name="codes_do_not_match">I codici non corrispondono</string>
|
<string name="codes_do_not_match">I codici non corrispondono</string>
|
||||||
|
<string name="interfering">Questo può voler dire che qualcuno sta cercando di interferire con la tua conessione</string>
|
||||||
<string name="contact_added_toast">Contatto aggiunto: %s</string>
|
<string name="contact_added_toast">Contatto aggiunto: %s</string>
|
||||||
<string name="contact_already_exists">Il contatto %s esiste già</string>
|
<string name="contact_already_exists">Il contatto %s esiste già</string>
|
||||||
<string name="contact_exchange_failed">Scambio di contatto fallito</string>
|
<string name="contact_exchange_failed">Scambio di contatto fallito</string>
|
||||||
<string name="qr_code_invalid">Il codice QR non è valido</string>
|
<string name="qr_code_invalid">Il codice QR non è valido</string>
|
||||||
<string name="connecting_to_device">Connessione al dispositivo\u2026</string>
|
<string name="connecting_to_device">Connessione al dispositivo\u2026</string>
|
||||||
<string name="authenticating_with_device">Autenticazione con il dispositivo\u2026</string>
|
<string name="authenticating_with_device">Autenticazione con il dispositivo\u2026</string>
|
||||||
|
<string name="connection_aborted_local">Connessione abortita da noi!Questo può voler dire che qualcuno sta cercando di interferire con la tua connessione</string>
|
||||||
|
<string name="connection_aborted_remote">Connessione abortita dal tuo contatto!Questo può voler dire che qualcuno sta cercando di interferire con la tua connessione</string>
|
||||||
<!--Introductions-->
|
<!--Introductions-->
|
||||||
|
<string name="introduction_onboarding_title">Introduzione tuoi contatti</string>
|
||||||
|
<string name="introduction_onboarding_text">Puoi presentare i tuoi contatti fra di loro, così non hanno bisogno di incontrarsi di persona per connettersi a Briar.</string>
|
||||||
<string name="introduction_activity_title">Seleziona Contatto</string>
|
<string name="introduction_activity_title">Seleziona Contatto</string>
|
||||||
<string name="introduction_message_title">Introduzione Contatti</string>
|
<string name="introduction_message_title">Introduzione Contatti</string>
|
||||||
<string name="introduction_message_hint">Scrivi messaggio (facoltativo)</string>
|
|
||||||
<string name="introduction_button">Crea l\'introduzione</string>
|
<string name="introduction_button">Crea l\'introduzione</string>
|
||||||
<string name="introduction_sent">La tua introduzione è stata inviata.</string>
|
<string name="introduction_sent">La tua introduzione è stata inviata.</string>
|
||||||
<string name="introduction_error">C\'è stato un errore nella creazione dell\'introduzione</string>
|
<string name="introduction_error">C\'è stato un errore nella creazione dell\'introduzione</string>
|
||||||
|
<string name="introduction_response_error">Errore durante la risposta all\' introduzione</string>
|
||||||
<string name="introduction_request_sent">Hai richiesto di introdurre %1$s a %2$s.</string>
|
<string name="introduction_request_sent">Hai richiesto di introdurre %1$s a %2$s.</string>
|
||||||
|
<string name="introduction_request_received">%1$s ha chiesto di introdurti in %2$s. Vuoi aggiungere %2$s alla tua lista contatti?</string>
|
||||||
|
<string name="introduction_request_exists_received">%1$s ha chiesto di introdurti in %2$s, ma %2$s è già nella tua lista contatti. Dato che %1$s può non saperlo, puoi comunque rispondere:</string>
|
||||||
<string name="introduction_request_answered_received">%1$s ha richiesto di introdurti a %2$s.</string>
|
<string name="introduction_request_answered_received">%1$s ha richiesto di introdurti a %2$s.</string>
|
||||||
<string name="introduction_response_accepted_sent">Hai accettato l\'introduzione a %1$s.</string>
|
<string name="introduction_response_accepted_sent">Hai accettato l\'introduzione a %1$s.</string>
|
||||||
<string name="introduction_response_declined_sent">Hai declinato l\'introduzione a %1$s.</string>
|
<string name="introduction_response_declined_sent">Hai declinato l\'introduzione a %1$s.</string>
|
||||||
@@ -115,55 +135,87 @@
|
|||||||
<item quantity="other">Aggiunti %d nuovi contatti.</item>
|
<item quantity="other">Aggiunti %d nuovi contatti.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<!--Private Groups-->
|
<!--Private Groups-->
|
||||||
|
<string name="groups_list_empty">Non stai partecipando a nessun gruppo.\n\nClicca l\' icona + in alto per creare un tuo gruppo o chiedi ai tuoi contatti di essere invitato in uno dei loro gruppi.</string>
|
||||||
<string name="groups_created_by">Creato da %s</string>
|
<string name="groups_created_by">Creato da %s</string>
|
||||||
|
<plurals name="messages">
|
||||||
|
<item quantity="one">%d messaggio</item>
|
||||||
|
<item quantity="other">%d messaggi</item>
|
||||||
|
</plurals>
|
||||||
<string name="groups_group_is_empty">Questo gruppo e\' vuoto</string>
|
<string name="groups_group_is_empty">Questo gruppo e\' vuoto</string>
|
||||||
<string name="groups_group_is_dissolved">Questo gruppo e\' stato sciolto</string>
|
<string name="groups_group_is_dissolved">Questo gruppo e\' stato sciolto</string>
|
||||||
<string name="groups_remove">Rimuovere</string>
|
<string name="groups_remove">Rimuovere</string>
|
||||||
<string name="groups_create_group_title">Crea gruppo privato</string>
|
<string name="groups_create_group_title">Crea gruppo privato</string>
|
||||||
<string name="groups_create_group_button">Crea gruppo</string>
|
<string name="groups_create_group_button">Crea gruppo</string>
|
||||||
<string name="groups_create_group_invitation_button">Invia invito</string>
|
<string name="groups_create_group_invitation_button">Invia invito</string>
|
||||||
<string name="groups_create_group_hint">Inserisci un nome per il tuo gruppo privato</string>
|
|
||||||
<string name="groups_invitation_sent">Invito a partecipare al gruppo spedito</string>
|
<string name="groups_invitation_sent">Invito a partecipare al gruppo spedito</string>
|
||||||
<string name="groups_message_sent">Messaggio inviato</string>
|
<string name="groups_message_sent">Messaggio inviato</string>
|
||||||
<string name="groups_member_list">Lista membri</string>
|
<string name="groups_member_list">Lista membri</string>
|
||||||
<string name="groups_invite_members">Invita Membri</string>
|
<string name="groups_invite_members">Invita Membri</string>
|
||||||
<string name="groups_member_created_you">Hai creato un nuovo gruppo</string>
|
<string name="groups_member_created_you">Hai creato un nuovo gruppo</string>
|
||||||
<string name="groups_member_created">%s e\' il creatore del gruppo.</string>
|
<string name="groups_member_created">%s e\' il creatore del gruppo.</string>
|
||||||
|
<string name="groups_member_joined_you">Ti sei unito al gruppo</string>
|
||||||
|
<string name="groups_member_joined">%s si è unito al gruppo</string>
|
||||||
<string name="groups_leave">Lascia gruppo</string>
|
<string name="groups_leave">Lascia gruppo</string>
|
||||||
<string name="groups_leave_dialog_title">Abbandonare il gruppo</string>
|
<string name="groups_leave_dialog_title">Abbandonare il gruppo</string>
|
||||||
<string name="groups_leave_dialog_message">Sei sicuro di voler abbandonare questo gruppo?</string>
|
<string name="groups_leave_dialog_message">Sei sicuro di voler abbandonare questo gruppo?</string>
|
||||||
<string name="groups_dissolve">Sciogli il gruppo</string>
|
<string name="groups_dissolve">Sciogli il gruppo</string>
|
||||||
<string name="groups_dissolve_dialog_title">Conferma lo scioglimento del gruppo</string>
|
<string name="groups_dissolve_dialog_title">Conferma lo scioglimento del gruppo</string>
|
||||||
|
<string name="groups_dissolve_dialog_message">Sei sicuro di voler sciogliere questo gruppo?\n\nTutti gli altri membri non saranno più in grado di continuare le loro conversazioni e potrebbero non ricevere gli ultimi messaggi.</string>
|
||||||
<string name="groups_dissolve_button">Sciogli</string>
|
<string name="groups_dissolve_button">Sciogli</string>
|
||||||
|
<string name="groups_dissolved_dialog_title">Il gruppo è stato dissolto</string>
|
||||||
|
<string name="groups_dissolved_dialog_message">Il creatore di questo gruppo l\'ha sciolto.\n\nNon puoi più scrivere messaggi in questo gruppo e potresti non ricevere tutti i messaggi che sono stati scritti.</string>
|
||||||
<!--Private Group Invitations-->
|
<!--Private Group Invitations-->
|
||||||
<string name="groups_invitations_title">Inviti spediti</string>
|
<string name="groups_invitations_title">Inviti spediti</string>
|
||||||
|
<string name="groups_invitations_invitation_sent">Hai invitato %1$s ad unirsi al gruppo \"%2$s\".</string>
|
||||||
|
<string name="groups_invitations_invitation_received">%1$s ti ha invitato ad unirti al gruppo \"%2$s\".</string>
|
||||||
<string name="groups_invitations_joined">Unito al gruppo</string>
|
<string name="groups_invitations_joined">Unito al gruppo</string>
|
||||||
<string name="groups_invitations_declined">Invito al gruppo rifiutato</string>
|
<string name="groups_invitations_declined">Invito al gruppo rifiutato</string>
|
||||||
|
<plurals name="groups_invitations_open">
|
||||||
|
<item quantity="one">%d invito al gruppo aperto.</item>
|
||||||
|
<item quantity="other">%d inviti al gruppo aperti.</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="groups_invitations_response_accepted_sent">Hai accettato l\'invito al gruppo da %s.</string>
|
||||||
|
<string name="groups_invitations_response_declined_sent">Hai rifiutato l\'invito al gruppo da %s.</string>
|
||||||
|
<string name="groups_invitations_response_accepted_received">%s ha accettato l\'invito al gruppo.</string>
|
||||||
|
<string name="groups_invitations_response_declined_received">%s ha rifiutato l\'invito al gruppo.</string>
|
||||||
|
<string name="sharing_status_groups">Solo il creatore può invitare nuovi membri nel gruppo. Sotto ci sono i membri correnti del gruppo.</string>
|
||||||
<!--Private Groups Revealing Contacts-->
|
<!--Private Groups Revealing Contacts-->
|
||||||
|
<string name="groups_reveal_contacts">Rivelare contatti</string>
|
||||||
|
<string name="groups_reveal_dialog_message">Puoi scegliere se rivelare i contatti a tutti i membri correnti e futuri di questo gruppo.\n\nRivelare i contatti fa diventare la connessione al gruppo più veloce e più affidabile, perchè puoi comunicare con i contatti rivelati anche quando il creatore del gruppo è offline.</string>
|
||||||
|
<string name="groups_reveal_visible">La relazione fra i contatti è visibile al gruppo</string>
|
||||||
|
<string name="groups_reveal_visible_revealed_by_us">La relazione fra i contatti è visibile al gruppo (rivelata da te)</string>
|
||||||
|
<string name="groups_reveal_visible_revealed_by_contact">La relazione fra i contatti è visibile al gruppo (rivelata da %s)</string>
|
||||||
|
<string name="groups_reveal_invisible">La relazione fra i contatti non è visibile al gruppo</string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="create_forum_title">Nuovo Forum</string>
|
<string name="no_forums">Non hai ancora alcun forum.\n\nPerchè non ne crei uno nuovo tu premendo l\' icona + in alto?\n\nPuoi anche chiedere ai tuoi contatti di condividere forums con te.</string>
|
||||||
<string name="choose_forum_name">Scegli un nome per il tuo forum:</string>
|
|
||||||
<string name="create_forum_button">Crea Forum</string>
|
<string name="create_forum_button">Crea Forum</string>
|
||||||
<string name="forum_created_toast">Forum creato</string>
|
<string name="forum_created_toast">Forum creato</string>
|
||||||
|
<string name="no_forum_posts">Questo forum è vuoto.\n\nUsa l\' icona penna in alto per comporre il primo post.\n\nTi senti solo qui? Condividi questo forum con i tuoi contatti!</string>
|
||||||
<string name="no_posts">Nessun post.</string>
|
<string name="no_posts">Nessun post.</string>
|
||||||
<plurals name="posts">
|
<plurals name="posts">
|
||||||
<item quantity="one">%d post</item>
|
<item quantity="one">%d post</item>
|
||||||
<item quantity="other">%d post</item>
|
<item quantity="other">%d post</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="forum_new_entry_posted">Nuova inserzione sul forum</string>
|
||||||
|
<string name="forum_new_message_hint">Nuova inserzione</string>
|
||||||
<string name="forum_message_reply_hint">Nuova Risposta</string>
|
<string name="forum_message_reply_hint">Nuova Risposta</string>
|
||||||
|
<string name="btn_reply">Rispondere</string>
|
||||||
<string name="forum_leave">Lascia Forum</string>
|
<string name="forum_leave">Lascia Forum</string>
|
||||||
<string name="dialog_title_leave_forum">Conferma l\'abbandono del forum</string>
|
<string name="dialog_title_leave_forum">Conferma l\'abbandono del forum</string>
|
||||||
|
<string name="dialog_message_leave_forum">Sei sicuro di voler lasciare questo forum? I contatti che hai condiviso in questo forum potrebbero essere tagliati fuori dalla ricezione di aggiornamenti di questo forum.</string>
|
||||||
<string name="dialog_button_leave">Lascia</string>
|
<string name="dialog_button_leave">Lascia</string>
|
||||||
<string name="forum_left_toast">Forum lasciato</string>
|
<string name="forum_left_toast">Forum lasciato</string>
|
||||||
<!--Forum Sharing-->
|
<!--Forum Sharing-->
|
||||||
<string name="forum_share_button">Condividi Forum</string>
|
<string name="forum_share_button">Condividi Forum</string>
|
||||||
<string name="contacts_selected">Contatti selezionati</string>
|
<string name="contacts_selected">Contatti selezionati</string>
|
||||||
<string name="activity_share_toolbar_header">Scegli Contatti</string>
|
<string name="activity_share_toolbar_header">Scegli Contatti</string>
|
||||||
|
<string name="no_contacts_selector">Sembra che tu sia nuovo qui e non hai alcun contatto ancora.\n\nPer favore torna dopo aver aggiunto il tuo primo contatto.</string>
|
||||||
<string name="forum_shared_snackbar">Forum condiviso con i contatti scelti</string>
|
<string name="forum_shared_snackbar">Forum condiviso con i contatti scelti</string>
|
||||||
<string name="forum_share_error">C\'è stato un errore nella condivisione di questo forum.</string>
|
<string name="forum_share_error">C\'è stato un errore nella condivisione di questo forum.</string>
|
||||||
<string name="forum_invitation_received">%1$s ha condiviso il forum \"%2$s\" con te.</string>
|
<string name="forum_invitation_received">%1$s ha condiviso il forum \"%2$s\" con te.</string>
|
||||||
<string name="forum_invitation_sent">Hai condiviso il forum \"%1$s\" con %2$s.</string>
|
<string name="forum_invitation_sent">Hai condiviso il forum \"%1$s\" con %2$s.</string>
|
||||||
<string name="forum_invitations_title">Inviti Forum</string>
|
<string name="forum_invitations_title">Inviti Forum</string>
|
||||||
|
<string name="forum_invitation_exists">Hai già accettato l\' invito a questo forum. Accettare più inviti cresce e rinforza la comunicazione nel forum.</string>
|
||||||
<string name="forum_joined_toast">Unito al forum</string>
|
<string name="forum_joined_toast">Unito al forum</string>
|
||||||
<string name="forum_declined_toast">Invito al forum declinato</string>
|
<string name="forum_declined_toast">Invito al forum declinato</string>
|
||||||
<string name="shared_by_format">Condiviso da %s</string>
|
<string name="shared_by_format">Condiviso da %s</string>
|
||||||
@@ -173,22 +225,29 @@
|
|||||||
<string name="forum_invitation_response_accepted_received">%s ha accettato il tuo invito al forum.</string>
|
<string name="forum_invitation_response_accepted_received">%s ha accettato il tuo invito al forum.</string>
|
||||||
<string name="forum_invitation_response_declined_received">%s ha declinato il tuo invito al forum.</string>
|
<string name="forum_invitation_response_declined_received">%s ha declinato il tuo invito al forum.</string>
|
||||||
<string name="sharing_status">Stato Condivisione</string>
|
<string name="sharing_status">Stato Condivisione</string>
|
||||||
|
<string name="sharing_status_forum">Ogni membro del forum può condividere con esso i suoi contatti. Stai condividendo questo forum con i seguenti contatti. Ci potrebbero inoltre essere altri membri che non puoi vedere.</string>
|
||||||
|
<string name="shared_with">Condiviso con %1$d (%2$d online)</string>
|
||||||
<plurals name="forums_shared">
|
<plurals name="forums_shared">
|
||||||
<item quantity="one">%d forum condiviso dai contatti</item>
|
<item quantity="one">%d forum condiviso dai contatti</item>
|
||||||
<item quantity="other">%d forum condivisi dai contatti</item>
|
<item quantity="other">%d forum condivisi dai contatti</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="nobody">Nessuno</string>
|
<string name="nobody">Nessuno</string>
|
||||||
<!--Blogs-->
|
<!--Blogs-->
|
||||||
|
<string name="blogs_other_blog_empty_state">Questo blog è attualmente vuoto.\n\nO l\'autore non ha ancora scritto nulla, oppure la persona che ha condiviso questo blog con te deve tornare in line, in modo che i post possano sincronizzarsi.</string>
|
||||||
<string name="read_more">leggi ancora</string>
|
<string name="read_more">leggi ancora</string>
|
||||||
<string name="blogs_write_blog_post">Scrivere un post sul blog</string>
|
<string name="blogs_write_blog_post">Scrivere un post sul blog</string>
|
||||||
|
<string name="blogs_write_blog_post_body_hint">Scrivi qui il tuo post del blog</string>
|
||||||
<string name="blogs_publish_blog_post">Pubblica</string>
|
<string name="blogs_publish_blog_post">Pubblica</string>
|
||||||
<string name="blogs_blog_post_created">Post blog creato</string>
|
<string name="blogs_blog_post_created">Post blog creato</string>
|
||||||
<string name="blogs_blog_post_received">Ricevuto nuovo post del blog</string>
|
<string name="blogs_blog_post_received">Ricevuto nuovo post del blog</string>
|
||||||
|
<string name="blogs_blog_post_scroll_to">Scorri a</string>
|
||||||
|
<string name="blogs_feed_empty_state">Questo è il feed globale del blog.\n\nSembra che nessuno abbia ancora scritto nulla.\n\nSii il primo e tocca l\'icona della penna per scrivere un nuovo post sul blog.</string>
|
||||||
<string name="blogs_personal_blog">Il blog personale di %s</string>
|
<string name="blogs_personal_blog">Il blog personale di %s</string>
|
||||||
<string name="blogs_remove_blog">Rimuovi Blog</string>
|
<string name="blogs_remove_blog">Rimuovi Blog</string>
|
||||||
|
<string name="blogs_remove_blog_dialog_message">Sei sicuro di voler rimuovere questo blog e tutti i post?\nTieni presente che questo non rimuoverà il blog dai dispositivi degli altri.</string>
|
||||||
<string name="blogs_remove_blog_ok">Rimuovi Blog</string>
|
<string name="blogs_remove_blog_ok">Rimuovi Blog</string>
|
||||||
<string name="blogs_blog_removed">Blog Rimosso</string>
|
<string name="blogs_blog_removed">Blog Rimosso</string>
|
||||||
<string name="blogs_reblog_comment_hint">Aggiungi un commento facoltativo</string>
|
<string name="blogs_reblog_button">Reblog</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">Condividi Blog</string>
|
<string name="blogs_sharing_share">Condividi Blog</string>
|
||||||
<string name="blogs_sharing_error">C\'è stato un errore nella condivisione di questo blog.</string>
|
<string name="blogs_sharing_error">C\'è stato un errore nella condivisione di questo blog.</string>
|
||||||
@@ -203,8 +262,9 @@
|
|||||||
<string name="blogs_sharing_invitations_title">Inviti Blog</string>
|
<string name="blogs_sharing_invitations_title">Inviti Blog</string>
|
||||||
<string name="blogs_sharing_joined_toast">Iscritto al Blog</string>
|
<string name="blogs_sharing_joined_toast">Iscritto al Blog</string>
|
||||||
<string name="blogs_sharing_declined_toast">Invito al blog declinato</string>
|
<string name="blogs_sharing_declined_toast">Invito al blog declinato</string>
|
||||||
|
<string name="sharing_status_blog">Chiunque si iscrive ad un blog può condividerlo con i suoi contatti. Stai condividendo questo blog con i seguenti contatti. Ci potrebbero inoltre essere altri membri che non puoi vedere.</string>
|
||||||
<!--RSS Feeds-->
|
<!--RSS Feeds-->
|
||||||
<string name="blogs_rss_feeds_import">Importa RSS Fee</string>
|
<string name="blogs_rss_feeds_import">Importa RSS Feed</string>
|
||||||
<string name="blogs_rss_feeds_import_button">Importa</string>
|
<string name="blogs_rss_feeds_import_button">Importa</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Inserire l\'URL dell\'RSS feed</string>
|
<string name="blogs_rss_feeds_import_hint">Inserire l\'URL dell\'RSS feed</string>
|
||||||
<string name="blogs_rss_feeds_import_error">Ci dispiace! C\'è stato un errore nell\'importazione del tuo feed.</string>
|
<string name="blogs_rss_feeds_import_error">Ci dispiace! C\'è stato un errore nell\'importazione del tuo feed.</string>
|
||||||
@@ -212,11 +272,21 @@
|
|||||||
<string name="blogs_rss_feeds_manage_imported">Importato:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importato:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autore:</string>
|
<string name="blogs_rss_feeds_manage_author">Autore:</string>
|
||||||
<string name="blogs_rss_feeds_manage_updated">Ultimo Aggiornamento:</string>
|
<string name="blogs_rss_feeds_manage_updated">Ultimo Aggiornamento:</string>
|
||||||
|
<string name="blogs_rss_remove_feed">Rimuovi feed</string>
|
||||||
|
<string name="blogs_rss_remove_feed_dialog_message">Sei sicuro di voler rimuovere questo feed e tutti i suoi post?\nOgni post che hai condiviso non sarà rimosso dai dispositivi degli altri.</string>
|
||||||
|
<string name="blogs_rss_remove_feed_ok">Rimuovi feed</string>
|
||||||
<string name="blogs_rss_feeds_manage_delete_error">Non è stato possibile cancellare il feed!</string>
|
<string name="blogs_rss_feeds_manage_delete_error">Non è stato possibile cancellare il feed!</string>
|
||||||
|
<string name="blogs_rss_feeds_manage_empty_state">Non hai importato alcun feed RSS.\n\nPerchè non premi il più in alto per aggingere il primo?</string>
|
||||||
|
<string name="blogs_rss_feeds_manage_error">C\'è stato un problema nel caricare i tuoi feeds. Per favore riprova fra poco.</string>
|
||||||
<!--Settings Network-->
|
<!--Settings Network-->
|
||||||
<string name="network_settings_title">Network</string>
|
<string name="network_settings_title">Reti</string>
|
||||||
<string name="bluetooth_setting">Connessione attraverso Bluetooth</string>
|
<string name="bluetooth_setting">Connessione attraverso Bluetooth</string>
|
||||||
|
<string name="bluetooth_setting_enabled">Quando i contatti sono vicini</string>
|
||||||
<string name="bluetooth_setting_disabled">Solo con l\'aggiunta di contatti</string>
|
<string name="bluetooth_setting_disabled">Solo con l\'aggiunta di contatti</string>
|
||||||
|
<string name="tor_network_setting">Connetti via Tor</string>
|
||||||
|
<string name="tor_network_setting_never">Mai</string>
|
||||||
|
<string name="tor_network_setting_wifi">Solo se usando Wi-Fi</string>
|
||||||
|
<string name="tor_network_setting_always">Nel caso di uso Wi-Fi o dati mobile</string>
|
||||||
<!--Settings Security and Panic-->
|
<!--Settings Security and Panic-->
|
||||||
<string name="security_settings_title">Sicurezza</string>
|
<string name="security_settings_title">Sicurezza</string>
|
||||||
<string name="change_password">Cambia password</string>
|
<string name="change_password">Cambia password</string>
|
||||||
@@ -224,37 +294,53 @@
|
|||||||
<string name="choose_new_password">Scegli la tua password:</string>
|
<string name="choose_new_password">Scegli la tua password:</string>
|
||||||
<string name="confirm_new_password">Conferma la tua nuova password:</string>
|
<string name="confirm_new_password">Conferma la tua nuova password:</string>
|
||||||
<string name="password_changed">La password è stata cambiata.</string>
|
<string name="password_changed">La password è stata cambiata.</string>
|
||||||
|
<string name="panic_setting">Impostazione pulsante panico</string>
|
||||||
<string name="panic_setting_title">Pulsante panico</string>
|
<string name="panic_setting_title">Pulsante panico</string>
|
||||||
|
<string name="panic_setting_hint">Configura come Briar reagirà quando userai un\'app pulsante panico</string>
|
||||||
|
<string name="panic_app_setting_title">App Pulsante Panico</string>
|
||||||
<string name="unknown_app">un\'app sconosciuta</string>
|
<string name="unknown_app">un\'app sconosciuta</string>
|
||||||
<string name="panic_app_setting_summary">Nessun app è stata impostata</string>
|
<string name="panic_app_setting_summary">Nessun app è stata impostata</string>
|
||||||
<string name="panic_app_setting_none">Nessuno</string>
|
<string name="panic_app_setting_none">Nessuno</string>
|
||||||
|
<string name="dialog_title_connect_panic_app">Conferma App Panico</string>
|
||||||
|
<string name="dialog_message_connect_panic_app">Sei sicuro di voler consentire %1$s di attivare le azioni distruttive del pulsante panico?</string>
|
||||||
<string name="lock_setting_title">Esci</string>
|
<string name="lock_setting_title">Esci</string>
|
||||||
|
<string name="lock_setting_summary">Uscire da Briar se viene premuto un pulsante di panico</string>
|
||||||
<string name="purge_setting_title">Elimina Account</string>
|
<string name="purge_setting_title">Elimina Account</string>
|
||||||
|
<string name="purge_setting_summary">Cancella il tuo account Briar se un panic button è premuto. Attenzione: ciò cancellerà permanentemente le tue identità, contatti e messaggi</string>
|
||||||
<string name="uninstall_setting_title">Disinstalla Briar</string>
|
<string name="uninstall_setting_title">Disinstalla Briar</string>
|
||||||
|
<string name="uninstall_setting_summary">Questo richiede una conferma manuale in un evento panico</string>
|
||||||
<!--Settings Notifications-->
|
<!--Settings Notifications-->
|
||||||
<string name="notification_settings_title">Notifiche</string>
|
<string name="notification_settings_title">Notifiche</string>
|
||||||
<string name="notify_private_messages_setting">Mostra avvertenze per i messaggi privati</string>
|
|
||||||
<string name="notify_forum_posts_setting">Mostra avvertenze per post di forum</string>
|
|
||||||
<string name="notify_blog_posts_setting">Mostra avvertenze per post di blog</string>
|
|
||||||
<string name="notify_vibration_setting">Vibrazione</string>
|
<string name="notify_vibration_setting">Vibrazione</string>
|
||||||
<string name="notify_sound_setting">Suono</string>
|
<string name="notify_sound_setting">Suono</string>
|
||||||
<string name="notify_sound_setting_default">Suoneria di default</string>
|
<string name="notify_sound_setting_default">Suoneria di default</string>
|
||||||
<string name="notify_sound_setting_disabled">Nessuno</string>
|
<string name="notify_sound_setting_disabled">Nessuno</string>
|
||||||
<string name="choose_ringtone_title">Scegli suoneria</string>
|
<string name="choose_ringtone_title">Scegli suoneria</string>
|
||||||
<!--Settings Feedback-->
|
<!--Settings Feedback-->
|
||||||
|
<string name="feedback_settings_title">Feedback</string>
|
||||||
|
<string name="send_feedback">Invia feedback</string>
|
||||||
<!--Link Warning-->
|
<!--Link Warning-->
|
||||||
<string name="link_warning_title">Attenzione Link</string>
|
<string name="link_warning_title">Attenzione Link</string>
|
||||||
|
<string name="link_warning_intro">Stai per aprire il seguente link con un\' app esterna</string>
|
||||||
|
<string name="link_warning_text">Ciò può essere usato per identificarti. Pensa se ti fidi della persona che ti ha inviato questo link e considera se aprirlo con Orfox.</string>
|
||||||
<string name="link_warning_open_link">Apri Link</string>
|
<string name="link_warning_open_link">Apri Link</string>
|
||||||
<!--Crash Reporter-->
|
<!--Crash Reporter-->
|
||||||
|
<string name="crash_report_title">Rapporto Crash Briar</string>
|
||||||
<string name="briar_crashed">Spiacenti, Briar è crashato</string>
|
<string name="briar_crashed">Spiacenti, Briar è crashato</string>
|
||||||
<string name="not_your_fault">Questo non è colpa tua.</string>
|
<string name="not_your_fault">Questo non è colpa tua.</string>
|
||||||
|
<string name="please_send_report">Per favore aiutaci a migliorare Briar mandandoci un report del crash.</string>
|
||||||
|
<string name="report_is_encrypted">Vi promettiamo che il rapporto è cifrato e inviato in modo sicuro.</string>
|
||||||
|
<string name="feedback_title">Feedback</string>
|
||||||
<string name="describe_crash">Descrivi cosa è successo (facoltativo)</string>
|
<string name="describe_crash">Descrivi cosa è successo (facoltativo)</string>
|
||||||
|
<string name="enter_feedback">Immetti il tuo feedback</string>
|
||||||
<string name="optional_contact_email">Il tuo indirizzo email (facoltativo)</string>
|
<string name="optional_contact_email">Il tuo indirizzo email (facoltativo)</string>
|
||||||
<string name="include_debug_report_crash">Includere dati anonimi riguardo al crash</string>
|
<string name="include_debug_report_crash">Includere dati anonimi riguardo al crash</string>
|
||||||
<string name="include_debug_report_feedback">Includere dati anonimi riguardo al tuo dispositivo</string>
|
<string name="include_debug_report_feedback">Includere dati anonimi riguardo al tuo dispositivo</string>
|
||||||
<string name="could_not_load_report_data">Non è stato possibile caricare i dati del report.</string>
|
<string name="could_not_load_report_data">Non è stato possibile caricare i dati del report.</string>
|
||||||
<string name="send_report">Invia report</string>
|
<string name="send_report">Invia report</string>
|
||||||
<string name="close">Chiudi</string>
|
<string name="close">Chiudi</string>
|
||||||
|
<string name="dev_report_saved">Report salvato. Verrà spedito la prossima volta che loggherai in Briar.</string>
|
||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
|
<string name="progress_title_logout">Uscire da Briar ...</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<string name="enter_password">Masukkan kata laluan anda:</string>
|
<string name="enter_password">Masukkan kata laluan anda:</string>
|
||||||
<string name="startup_failed_notification_title">Briar gagal dimulakan</string>
|
<string name="startup_failed_notification_title">Briar gagal dimulakan</string>
|
||||||
<string name="startup_failed_notification_text">Anda perlu pasang ulang Briar.</string>
|
<string name="startup_failed_notification_text">Anda perlu pasang ulang Briar.</string>
|
||||||
<string name="expiry_warning">Aplikasi ini telah tamat tempoh.\nSila pasang ulang versi baru.</string>
|
<string name="expiry_date_reached">Aplikasi ini telah tamat tempoh.\nSila pasang ulang versi baru.</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
<string name="contact_list_button">Kenalan</string>
|
<string name="contact_list_button">Kenalan</string>
|
||||||
<string name="forums_button">Forum</string>
|
<string name="forums_button">Forum</string>
|
||||||
|
|||||||
@@ -117,8 +117,6 @@
|
|||||||
<string name="introduction_onboarding_text">Você pode apresentar seus contatos entre si, assim eles não precisam se encontrar pessoalmente para se comunicar no Briar.</string>
|
<string name="introduction_onboarding_text">Você pode apresentar seus contatos entre si, assim eles não precisam se encontrar pessoalmente para se comunicar no Briar.</string>
|
||||||
<string name="introduction_activity_title">Selecionar contato</string>
|
<string name="introduction_activity_title">Selecionar contato</string>
|
||||||
<string name="introduction_message_title">Apresentar contatos</string>
|
<string name="introduction_message_title">Apresentar contatos</string>
|
||||||
<string name="introduction_message_text">Você pode escrever uma mensagem que será enviada para %1$s e %2$s junto com sua apresentação:</string>
|
|
||||||
<string name="introduction_message_hint">Digitar mensagem (opcional)</string>
|
|
||||||
<string name="introduction_button">Fazer apresentação</string>
|
<string name="introduction_button">Fazer apresentação</string>
|
||||||
<string name="introduction_sent">Sua Introdução foi enviada.</string>
|
<string name="introduction_sent">Sua Introdução foi enviada.</string>
|
||||||
<string name="introduction_error">Houve um erro ao fazer a apresentação</string>
|
<string name="introduction_error">Houve um erro ao fazer a apresentação</string>
|
||||||
@@ -149,7 +147,6 @@
|
|||||||
<string name="groups_create_group_title">Criar Grupo Privado</string>
|
<string name="groups_create_group_title">Criar Grupo Privado</string>
|
||||||
<string name="groups_create_group_button">Criar Grupo</string>
|
<string name="groups_create_group_button">Criar Grupo</string>
|
||||||
<string name="groups_create_group_invitation_button">Enviar Convite</string>
|
<string name="groups_create_group_invitation_button">Enviar Convite</string>
|
||||||
<string name="groups_create_group_hint">Adicionar um nome para seu grupo privado</string>
|
|
||||||
<string name="groups_invitation_sent">Convite do Grupo enviado </string>
|
<string name="groups_invitation_sent">Convite do Grupo enviado </string>
|
||||||
<string name="groups_message_sent">Mensagem enviada</string>
|
<string name="groups_message_sent">Mensagem enviada</string>
|
||||||
<string name="groups_member_list">Lista de membros</string>
|
<string name="groups_member_list">Lista de membros</string>
|
||||||
@@ -190,8 +187,6 @@
|
|||||||
<string name="groups_reveal_invisible">Relação de contatos não visível para o Grupo </string>
|
<string name="groups_reveal_invisible">Relação de contatos não visível para o Grupo </string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="no_forums">Você não tem nenhum fórum.\nPor que não cria um novo você mesmo, Clicando o ícone + no topo?\nVocê também pode pedir que seus contatos compartilhem fóruns com você.</string>
|
<string name="no_forums">Você não tem nenhum fórum.\nPor que não cria um novo você mesmo, Clicando o ícone + no topo?\nVocê também pode pedir que seus contatos compartilhem fóruns com você.</string>
|
||||||
<string name="create_forum_title">Novo fórum</string>
|
|
||||||
<string name="choose_forum_name">Escolha um nome para o seu fórum:</string>
|
|
||||||
<string name="create_forum_button">Criar fórum</string>
|
<string name="create_forum_button">Criar fórum</string>
|
||||||
<string name="forum_created_toast">Fórum criado</string>
|
<string name="forum_created_toast">Fórum criado</string>
|
||||||
<string name="no_forum_posts">Esse fórum está vazio.\nUse o ícone da caneta no topo para escrever o primeiro Post.\nSe sentido sozinho aqui? Compartilhe esse fórum com seus contatos!</string>
|
<string name="no_forum_posts">Esse fórum está vazio.\nUse o ícone da caneta no topo para escrever o primeiro Post.\nSe sentido sozinho aqui? Compartilhe esse fórum com seus contatos!</string>
|
||||||
@@ -215,7 +210,6 @@
|
|||||||
<string name="activity_share_toolbar_header">Escolher contatos</string>
|
<string name="activity_share_toolbar_header">Escolher contatos</string>
|
||||||
<string name="no_contacts_selector">Parece que você é novo aqui e não tem nenhum contato ainda.\nPor favor volte aqui depois de adicionar um contato.</string>
|
<string name="no_contacts_selector">Parece que você é novo aqui e não tem nenhum contato ainda.\nPor favor volte aqui depois de adicionar um contato.</string>
|
||||||
<string name="forum_shared_snackbar">Fòrum compartilhado com os contatos escolhidos</string>
|
<string name="forum_shared_snackbar">Fòrum compartilhado com os contatos escolhidos</string>
|
||||||
<string name="forum_share_message">Você pode escrever um convite que será enviado aos contatos selecionados.</string>
|
|
||||||
<string name="forum_share_error">Houve um erro em compartilhar esse fórum.</string>
|
<string name="forum_share_error">Houve um erro em compartilhar esse fórum.</string>
|
||||||
<string name="forum_invitation_received">%1$s compartilhou o fórum \"%2$s\" com você.</string>
|
<string name="forum_invitation_received">%1$s compartilhou o fórum \"%2$s\" com você.</string>
|
||||||
<string name="forum_invitation_sent">Você compartilhou o fórum \"%1$s\" com %2$s.</string>
|
<string name="forum_invitation_sent">Você compartilhou o fórum \"%1$s\" com %2$s.</string>
|
||||||
@@ -251,7 +245,6 @@
|
|||||||
<string name="blogs_remove_blog_dialog_message">Você ter certeza que quer remover esse Blog e todos seus Posts?\nNote que isso não irá remover o Blog dos dispositivos de outras pessoas. </string>
|
<string name="blogs_remove_blog_dialog_message">Você ter certeza que quer remover esse Blog e todos seus Posts?\nNote que isso não irá remover o Blog dos dispositivos de outras pessoas. </string>
|
||||||
<string name="blogs_remove_blog_ok">Remover Blog</string>
|
<string name="blogs_remove_blog_ok">Remover Blog</string>
|
||||||
<string name="blogs_blog_removed">Blog Deletado</string>
|
<string name="blogs_blog_removed">Blog Deletado</string>
|
||||||
<string name="blogs_reblog_comment_hint">Adicione um comentario (opcional)</string>
|
|
||||||
<string name="blogs_reblog_button">Reblog</string>
|
<string name="blogs_reblog_button">Reblog</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">Compartilhar Blog</string>
|
<string name="blogs_sharing_share">Compartilhar Blog</string>
|
||||||
@@ -308,10 +301,6 @@
|
|||||||
<string name="uninstall_setting_summary">Isso requer configuração manual em um evento de pânico</string>
|
<string name="uninstall_setting_summary">Isso requer configuração manual em um evento de pânico</string>
|
||||||
<!--Settings Notifications-->
|
<!--Settings Notifications-->
|
||||||
<string name="notification_settings_title">Notificações</string>
|
<string name="notification_settings_title">Notificações</string>
|
||||||
<string name="notify_private_messages_setting">Mostrar alertas para mensagens privadas</string>
|
|
||||||
<string name="notify_group_messages_setting">Mostrar alertas para mensagens nos Grupos </string>
|
|
||||||
<string name="notify_forum_posts_setting">Mostrar alertas para postagens nos fórums</string>
|
|
||||||
<string name="notify_blog_posts_setting">Mostrar alertas para postagens nos blogs</string>
|
|
||||||
<string name="notify_vibration_setting">Vibrar</string>
|
<string name="notify_vibration_setting">Vibrar</string>
|
||||||
<string name="notify_sound_setting">Som</string>
|
<string name="notify_sound_setting">Som</string>
|
||||||
<string name="notify_sound_setting_default">Toque padrão</string>
|
<string name="notify_sound_setting_default">Toque padrão</string>
|
||||||
|
|||||||
@@ -117,8 +117,6 @@
|
|||||||
<string name="introduction_onboarding_text">Kontaktet tuaja mund t’ia prezantoni njëri-tjetrit, që kështu të mos u duhet të takohen realisht për të mundur të lidhen në Briar.</string>
|
<string name="introduction_onboarding_text">Kontaktet tuaja mund t’ia prezantoni njëri-tjetrit, që kështu të mos u duhet të takohen realisht për të mundur të lidhen në Briar.</string>
|
||||||
<string name="introduction_activity_title">Përzgjidhni Kontakt</string>
|
<string name="introduction_activity_title">Përzgjidhni Kontakt</string>
|
||||||
<string name="introduction_message_title">Prezantoni Kontakte</string>
|
<string name="introduction_message_title">Prezantoni Kontakte</string>
|
||||||
<string name="introduction_message_text">Mund të hartoni një mesazh për t’u dërguar te %1$s dhe %2$s tok me prezantimin tuaj:</string>
|
|
||||||
<string name="introduction_message_hint">Shtypni mesazh (në daçi)</string>
|
|
||||||
<string name="introduction_button">Bëje prezantimin</string>
|
<string name="introduction_button">Bëje prezantimin</string>
|
||||||
<string name="introduction_sent">Prezantimi juaj u dërgua.</string>
|
<string name="introduction_sent">Prezantimi juaj u dërgua.</string>
|
||||||
<string name="introduction_error">Pati një gabim me bërjen e prezantimit.</string>
|
<string name="introduction_error">Pati një gabim me bërjen e prezantimit.</string>
|
||||||
@@ -149,7 +147,6 @@
|
|||||||
<string name="groups_create_group_title">Krijoni Grup Privat</string>
|
<string name="groups_create_group_title">Krijoni Grup Privat</string>
|
||||||
<string name="groups_create_group_button">Krijoje Grupin</string>
|
<string name="groups_create_group_button">Krijoje Grupin</string>
|
||||||
<string name="groups_create_group_invitation_button">Dërgoje Ftesën</string>
|
<string name="groups_create_group_invitation_button">Dërgoje Ftesën</string>
|
||||||
<string name="groups_create_group_hint">Shtoni një emër për grupin tuaj privat</string>
|
|
||||||
<string name="groups_invitation_sent">Ftesa e grupit u dërgua</string>
|
<string name="groups_invitation_sent">Ftesa e grupit u dërgua</string>
|
||||||
<string name="groups_message_sent">Mesazhi u dërgua</string>
|
<string name="groups_message_sent">Mesazhi u dërgua</string>
|
||||||
<string name="groups_member_list">Listë Anëtarësh</string>
|
<string name="groups_member_list">Listë Anëtarësh</string>
|
||||||
@@ -191,8 +188,6 @@
|
|||||||
<string name="groups_reveal_invisible">Marrëdhënia e kontaktit s’është e dukshme për grupin</string>
|
<string name="groups_reveal_invisible">Marrëdhënia e kontaktit s’është e dukshme për grupin</string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="no_forums">Ende s’keni forume.\n\nPse nuk krijoni vetë një të tillë duke prekur ikonën + në krye?\n\nMund edhe t’u kërkoni kontakteve tuaj të ndajnë me ju forume.</string>
|
<string name="no_forums">Ende s’keni forume.\n\nPse nuk krijoni vetë një të tillë duke prekur ikonën + në krye?\n\nMund edhe t’u kërkoni kontakteve tuaj të ndajnë me ju forume.</string>
|
||||||
<string name="create_forum_title">Forum i Ri</string>
|
|
||||||
<string name="choose_forum_name">Zgjidhni një emër për forumin tuaj:</string>
|
|
||||||
<string name="create_forum_button">Krijoje Forumin</string>
|
<string name="create_forum_button">Krijoje Forumin</string>
|
||||||
<string name="forum_created_toast">Forumi u krijua</string>
|
<string name="forum_created_toast">Forumi u krijua</string>
|
||||||
<string name="no_forum_posts">Ky forum është i zbrazët.\n\nPërdorni ikonën penë që të hartoni postimin tuaj të parë.\n\nNdiheni vetëm? Ndajeni këtë forum me kontaktet tuaj!</string>
|
<string name="no_forum_posts">Ky forum është i zbrazët.\n\nPërdorni ikonën penë që të hartoni postimin tuaj të parë.\n\nNdiheni vetëm? Ndajeni këtë forum me kontaktet tuaj!</string>
|
||||||
@@ -216,7 +211,6 @@
|
|||||||
<string name="activity_share_toolbar_header">Zgjidhni Kontakte</string>
|
<string name="activity_share_toolbar_header">Zgjidhni Kontakte</string>
|
||||||
<string name="no_contacts_selector">Duket se jeni i ri këtu dhe s’keni ende kontakte.\n\nJu lutemi, rikthehuni këtu pasi të keni shtuar kontaktin tuaj të parë.</string>
|
<string name="no_contacts_selector">Duket se jeni i ri këtu dhe s’keni ende kontakte.\n\nJu lutemi, rikthehuni këtu pasi të keni shtuar kontaktin tuaj të parë.</string>
|
||||||
<string name="forum_shared_snackbar">Forumi u nda me kontaktet e zgjedhur</string>
|
<string name="forum_shared_snackbar">Forumi u nda me kontaktet e zgjedhur</string>
|
||||||
<string name="forum_share_message">Mundeni të hartoni një mesazh ftese (në daçi) që do t’u dërgohet kontakteve të përzgjedhur.</string>
|
|
||||||
<string name="forum_share_error">Pati një gabim në ndarjen e këtij forumi me të tjerët.</string>
|
<string name="forum_share_error">Pati një gabim në ndarjen e këtij forumi me të tjerët.</string>
|
||||||
<string name="forum_invitation_received">%1$s ndau me ju forumin \"%2$s\".</string>
|
<string name="forum_invitation_received">%1$s ndau me ju forumin \"%2$s\".</string>
|
||||||
<string name="forum_invitation_sent">Ndatë me \"%2$s\" forumin %1$s.</string>
|
<string name="forum_invitation_sent">Ndatë me \"%2$s\" forumin %1$s.</string>
|
||||||
@@ -253,7 +247,6 @@
|
|||||||
<string name="blogs_remove_blog_dialog_message">Jeni i sigurt se doni të hiqet ky blog dhe krejt postimet?\nMbani parasysh që kjo nuk do ta heqë blogun nga pajisjet e personave të tjerë.</string>
|
<string name="blogs_remove_blog_dialog_message">Jeni i sigurt se doni të hiqet ky blog dhe krejt postimet?\nMbani parasysh që kjo nuk do ta heqë blogun nga pajisjet e personave të tjerë.</string>
|
||||||
<string name="blogs_remove_blog_ok">Hiqe Blogun</string>
|
<string name="blogs_remove_blog_ok">Hiqe Blogun</string>
|
||||||
<string name="blogs_blog_removed">Blogu u Hoq</string>
|
<string name="blogs_blog_removed">Blogu u Hoq</string>
|
||||||
<string name="blogs_reblog_comment_hint">Shtoni një koment opsional</string>
|
|
||||||
<string name="blogs_reblog_button">Riblogojeni</string>
|
<string name="blogs_reblog_button">Riblogojeni</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">Ndajeni Blogun Me të Tjerë</string>
|
<string name="blogs_sharing_share">Ndajeni Blogun Me të Tjerë</string>
|
||||||
@@ -318,10 +311,6 @@
|
|||||||
<string name="uninstall_setting_summary">Kjo lyp ripohim dorazi, në rast akti paniku</string>
|
<string name="uninstall_setting_summary">Kjo lyp ripohim dorazi, në rast akti paniku</string>
|
||||||
<!--Settings Notifications-->
|
<!--Settings Notifications-->
|
||||||
<string name="notification_settings_title">Njoftime</string>
|
<string name="notification_settings_title">Njoftime</string>
|
||||||
<string name="notify_private_messages_setting">Shfaq sinjalizime për mesazhe private</string>
|
|
||||||
<string name="notify_group_messages_setting">Shfaq sinjalizime për mesazhe grupi</string>
|
|
||||||
<string name="notify_forum_posts_setting">Shfaq sinjalizime për postime forumi</string>
|
|
||||||
<string name="notify_blog_posts_setting">Shfaq sinjalizime për postime blogu</string>
|
|
||||||
<string name="notify_vibration_setting">Dridhu</string>
|
<string name="notify_vibration_setting">Dridhu</string>
|
||||||
<string name="notify_sound_setting">Tingull</string>
|
<string name="notify_sound_setting">Tingull</string>
|
||||||
<string name="notify_sound_setting_default">Zilja parazgjedhje</string>
|
<string name="notify_sound_setting_default">Zilja parazgjedhje</string>
|
||||||
@@ -354,8 +343,4 @@
|
|||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
<string name="progress_title_logout">Po dilet nga Briar-i…</string>
|
<string name="progress_title_logout">Po dilet nga Briar-i…</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
<string name="screen_filter_title">U pikas filtër ekrani</string>
|
|
||||||
<string name="screen_filter_body">Aplikacionet vijuese kanë leje të vizatojnë përmbi aplikacione të tjera:\n\n%1$s \n\nBriar-i nuk do të reagojë ndaj prekjesh, kur mbi të po vizaton një tjetër aplikacion.
|
|
||||||
Nëse hasni probleme, provoni t’i mbyllni këto aplikacione, kur përdorni Briar-in.\n</string>
|
|
||||||
<string name="checkbox_dont_show_again">Mos më sinjalizo më për këto aplikacione</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
<color name="briar_text_tertiary_inverse">#80ffffff</color>
|
<color name="briar_text_tertiary_inverse">#80ffffff</color>
|
||||||
<color name="briar_button_positive">#06b9ff</color>
|
<color name="briar_button_positive">#06b9ff</color>
|
||||||
<color name="briar_button_negative">#ff0000</color>
|
<color name="briar_button_negative">#ff0000</color>
|
||||||
|
<color name="briar_warning_background">#ff0000</color>
|
||||||
<color name="emoji_text_color">#ff000000</color>
|
<color name="emoji_text_color">#ff000000</color>
|
||||||
|
|
||||||
<color name="emoji_pager_background">@color/window_background</color>
|
<color name="emoji_pager_background">@color/window_background</color>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string translatable="false" name="app_name">Briar</string>
|
<string translatable="false" name="app_name">Briar Beta</string>
|
||||||
|
|
||||||
<!-- Setup -->
|
<!-- Setup -->
|
||||||
<string name="setup_title">Briar Setup</string>
|
<string name="setup_title">Briar Setup</string>
|
||||||
@@ -25,7 +25,11 @@
|
|||||||
<string name="startup_failed_activity_title">Briar Startup Failure</string>
|
<string name="startup_failed_activity_title">Briar Startup Failure</string>
|
||||||
<string name="startup_failed_db_error">For some reason, your Briar database is corrupted beyond repair. Your account, your data and all your contact connections are lost. Unfortunately, you need to reinstall Briar und set up a new account.</string>
|
<string name="startup_failed_db_error">For some reason, your Briar database is corrupted beyond repair. Your account, your data and all your contact connections are lost. Unfortunately, you need to reinstall Briar und set up a new account.</string>
|
||||||
<string name="startup_failed_service_error">Briar was unable to start a required plugin. Reinstalling Briar usually solves this problem. However, please note that you will then lose your account and all data associated with it since Briar is not using central servers to store your data on.</string>
|
<string name="startup_failed_service_error">Briar was unable to start a required plugin. Reinstalling Briar usually solves this problem. However, please note that you will then lose your account and all data associated with it since Briar is not using central servers to store your data on.</string>
|
||||||
<string name="expiry_warning">This software has expired.\nPlease install a newer version.</string>
|
<plurals name="expiry_warning">
|
||||||
|
<item quantity="one">This is a beta version of Briar. Your account will expire in %d day and cannot be renewed.</item>
|
||||||
|
<item quantity="other">This is a beta version of Briar. Your account will expire in %d days and cannot be renewed.</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="expiry_date_reached">This software has expired.\nThank you for testing!</string>
|
||||||
|
|
||||||
<!-- Navigation Drawer -->
|
<!-- Navigation Drawer -->
|
||||||
<string name="nav_drawer_open_description">Open the navigation drawer</string>
|
<string name="nav_drawer_open_description">Open the navigation drawer</string>
|
||||||
@@ -127,8 +131,7 @@
|
|||||||
<string name="introduction_onboarding_text">You can introduce your contacts to each other, so they don\'t need to meet in person to connect on Briar.</string>
|
<string name="introduction_onboarding_text">You can introduce your contacts to each other, so they don\'t need to meet in person to connect on Briar.</string>
|
||||||
<string name="introduction_activity_title">Select Contact</string>
|
<string name="introduction_activity_title">Select Contact</string>
|
||||||
<string name="introduction_message_title">Introduce Contacts</string>
|
<string name="introduction_message_title">Introduce Contacts</string>
|
||||||
<string name="introduction_message_text">You can compose a message that will be sent to %1$s and %2$s along with your introduction:</string>
|
<string name="introduction_message_hint">Add a message (optional)</string>
|
||||||
<string name="introduction_message_hint">Type message (optional)</string>
|
|
||||||
<string name="introduction_button">Make Introduction</string>
|
<string name="introduction_button">Make Introduction</string>
|
||||||
<string name="introduction_sent">Your introduction has been sent.</string>
|
<string name="introduction_sent">Your introduction has been sent.</string>
|
||||||
<string name="introduction_error">There was an error making the introduction.</string>
|
<string name="introduction_error">There was an error making the introduction.</string>
|
||||||
@@ -160,7 +163,7 @@
|
|||||||
<string name="groups_create_group_title">Create Private Group</string>
|
<string name="groups_create_group_title">Create Private Group</string>
|
||||||
<string name="groups_create_group_button">Create Group</string>
|
<string name="groups_create_group_button">Create Group</string>
|
||||||
<string name="groups_create_group_invitation_button">Send Invitation</string>
|
<string name="groups_create_group_invitation_button">Send Invitation</string>
|
||||||
<string name="groups_create_group_hint">Add a name for your private group</string>
|
<string name="groups_create_group_hint">Choose a name for your private group</string>
|
||||||
<string name="groups_invitation_sent">Group invitation has been sent</string>
|
<string name="groups_invitation_sent">Group invitation has been sent</string>
|
||||||
<string name="groups_message_sent">Message sent</string>
|
<string name="groups_message_sent">Message sent</string>
|
||||||
<string name="groups_member_list">Member List</string>
|
<string name="groups_member_list">Member List</string>
|
||||||
@@ -205,8 +208,8 @@
|
|||||||
|
|
||||||
<!-- Forums -->
|
<!-- Forums -->
|
||||||
<string name="no_forums">You don\'t have any forums yet.\n\nWhy don\'t you create a new one yourself by tapping the + icon at the top?\n\nYou can also ask your contacts to share forums with you.</string>
|
<string name="no_forums">You don\'t have any forums yet.\n\nWhy don\'t you create a new one yourself by tapping the + icon at the top?\n\nYou can also ask your contacts to share forums with you.</string>
|
||||||
<string name="create_forum_title">New Forum</string>
|
<string name="create_forum_title">Create Forum</string>
|
||||||
<string name="choose_forum_name">Choose a name for your forum:</string>
|
<string name="choose_forum_hint">Choose a name for your forum</string>
|
||||||
<string name="create_forum_button">Create Forum</string>
|
<string name="create_forum_button">Create Forum</string>
|
||||||
<string name="forum_created_toast">Forum created</string>
|
<string name="forum_created_toast">Forum created</string>
|
||||||
<string name="no_forum_posts">This forum is empty.\n\nUse the pen icon at the top to compose the first post.\n\nFeeling lonely here? Share this forum with more of your contacts!</string>
|
<string name="no_forum_posts">This forum is empty.\n\nUse the pen icon at the top to compose the first post.\n\nFeeling lonely here? Share this forum with more of your contacts!</string>
|
||||||
@@ -231,7 +234,7 @@
|
|||||||
<string name="activity_share_toolbar_header">Choose Contacts</string>
|
<string name="activity_share_toolbar_header">Choose Contacts</string>
|
||||||
<string name="no_contacts_selector">It seems that you are new here and have no contacts yet.\n\nPlease come back here after you added your first contact.</string>
|
<string name="no_contacts_selector">It seems that you are new here and have no contacts yet.\n\nPlease come back here after you added your first contact.</string>
|
||||||
<string name="forum_shared_snackbar">Forum shared with chosen contacts</string>
|
<string name="forum_shared_snackbar">Forum shared with chosen contacts</string>
|
||||||
<string name="forum_share_message">You may compose an optional invitation message that will be sent to the selected contacts.</string>
|
<string name="forum_share_message">Add a message (optional)</string>
|
||||||
<string name="forum_share_error">There was an error sharing this forum.</string>
|
<string name="forum_share_error">There was an error sharing this forum.</string>
|
||||||
<string name="forum_invitation_received">%1$s has shared the forum \"%2$s\" with you.</string>
|
<string name="forum_invitation_received">%1$s has shared the forum \"%2$s\" with you.</string>
|
||||||
<string name="forum_invitation_sent">You have shared the forum \"%1$s\" with %2$s.</string>
|
<string name="forum_invitation_sent">You have shared the forum \"%1$s\" with %2$s.</string>
|
||||||
@@ -265,12 +268,11 @@
|
|||||||
<string name="blogs_blog_post_received">New Blog Post Received</string>
|
<string name="blogs_blog_post_received">New Blog Post Received</string>
|
||||||
<string name="blogs_blog_post_scroll_to">Scroll To</string>
|
<string name="blogs_blog_post_scroll_to">Scroll To</string>
|
||||||
<string name="blogs_feed_empty_state">This is the global blog feed.\n\nIt looks like nobody blogged anything, yet.\n\nBe the first and tap the pen icon to write a new blog post.</string>
|
<string name="blogs_feed_empty_state">This is the global blog feed.\n\nIt looks like nobody blogged anything, yet.\n\nBe the first and tap the pen icon to write a new blog post.</string>
|
||||||
<string name="blogs_personal_blog">%s\'s Personal Blog</string>
|
|
||||||
<string name="blogs_remove_blog">Remove Blog</string>
|
<string name="blogs_remove_blog">Remove Blog</string>
|
||||||
<string name="blogs_remove_blog_dialog_message">Are you sure that you want to remove this blog and all posts?\nNote that this will not remove the blog from other people\'s devices.</string>
|
<string name="blogs_remove_blog_dialog_message">Are you sure that you want to remove this blog and all posts?\nNote that this will not remove the blog from other people\'s devices.</string>
|
||||||
<string name="blogs_remove_blog_ok">Remove Blog</string>
|
<string name="blogs_remove_blog_ok">Remove Blog</string>
|
||||||
<string name="blogs_blog_removed">Blog Removed</string>
|
<string name="blogs_blog_removed">Blog Removed</string>
|
||||||
<string name="blogs_reblog_comment_hint">Add an optional comment</string>
|
<string name="blogs_reblog_comment_hint">Add a comment (optional)</string>
|
||||||
<string name="blogs_reblog_button">Reblog</string>
|
<string name="blogs_reblog_button">Reblog</string>
|
||||||
|
|
||||||
<!-- Blog Sharing -->
|
<!-- Blog Sharing -->
|
||||||
@@ -282,8 +284,8 @@
|
|||||||
<string name="blogs_sharing_response_declined_sent">You declined the blog invitation from %s.</string>
|
<string name="blogs_sharing_response_declined_sent">You declined the blog invitation from %s.</string>
|
||||||
<string name="blogs_sharing_response_accepted_received">%s accepted the blog invitation.</string>
|
<string name="blogs_sharing_response_accepted_received">%s accepted the blog invitation.</string>
|
||||||
<string name="blogs_sharing_response_declined_received">%s declined the blog invitation.</string>
|
<string name="blogs_sharing_response_declined_received">%s declined the blog invitation.</string>
|
||||||
<string name="blogs_sharing_invitation_received">%1$s has shared the personal blog of %2$s with you.</string>
|
<string name="blogs_sharing_invitation_received">%1$s has shared the blog \"%2$s\" with you.</string>
|
||||||
<string name="blogs_sharing_invitation_sent">You have shared the personal blog of %1$s with %2$s.</string>
|
<string name="blogs_sharing_invitation_sent">You have shared the blog \"%1$s\" with %2$s.</string>
|
||||||
<string name="blogs_sharing_invitations_title">Blog Invitations</string>
|
<string name="blogs_sharing_invitations_title">Blog Invitations</string>
|
||||||
<string name="blogs_sharing_joined_toast">Subscribed to Blog</string>
|
<string name="blogs_sharing_joined_toast">Subscribed to Blog</string>
|
||||||
<string name="blogs_sharing_declined_toast">Blog Invitation Declined</string>
|
<string name="blogs_sharing_declined_toast">Blog Invitation Declined</string>
|
||||||
@@ -340,11 +342,17 @@
|
|||||||
|
|
||||||
<!-- Settings Notifications -->
|
<!-- Settings Notifications -->
|
||||||
<string name="notification_settings_title">Notifications</string>
|
<string name="notification_settings_title">Notifications</string>
|
||||||
<string name="notify_private_messages_setting">Show alerts for private messages</string>
|
<string name="notify_private_messages_setting_title">Private messages</string>
|
||||||
<string name="notify_group_messages_setting">Show alerts for group messages</string>
|
<string name="notify_private_messages_setting_summary">Show alerts for private messages</string>
|
||||||
<string name="notify_forum_posts_setting">Show alerts for forum posts</string>
|
<string name="notify_group_messages_setting_title">Group messages</string>
|
||||||
<string name="notify_blog_posts_setting">Show alerts for blog posts</string>
|
<string name="notify_group_messages_setting_summary">Show alerts for group messages</string>
|
||||||
|
<string name="notify_forum_posts_setting_title">Forum posts</string>
|
||||||
|
<string name="notify_forum_posts_setting_summary">Show alerts for forum posts</string>
|
||||||
|
<string name="notify_blog_posts_setting_title">Blog posts</string>
|
||||||
|
<string name="notify_blog_posts_setting_summary">Show alerts for blog posts</string>
|
||||||
<string name="notify_vibration_setting">Vibrate</string>
|
<string name="notify_vibration_setting">Vibrate</string>
|
||||||
|
<string name="notify_lock_screen_setting_title">Lock Screen</string>
|
||||||
|
<string name="notify_lock_screen_setting_summary">Show notifications on the lock screen</string>
|
||||||
<string name="notify_sound_setting">Sound</string>
|
<string name="notify_sound_setting">Sound</string>
|
||||||
<string name="notify_sound_setting_default">Default ringtone</string>
|
<string name="notify_sound_setting_default">Default ringtone</string>
|
||||||
<string name="notify_sound_setting_disabled">None</string>
|
<string name="notify_sound_setting_disabled">None</string>
|
||||||
@@ -381,9 +389,7 @@
|
|||||||
<string name="progress_title_logout">Signing out of Briar…</string>
|
<string name="progress_title_logout">Signing out of Briar…</string>
|
||||||
|
|
||||||
<!-- Screen Filters & Tapjacking -->
|
<!-- Screen Filters & Tapjacking -->
|
||||||
<string name="screen_filter_title">Screen filter detected</string>
|
<string name="screen_filter_title">Screen overlay detected</string>
|
||||||
<string name="screen_filter_body">The following apps have permission to draw over other apps:\n\n%1$s \n\nBriar will not respond to touches when another app is drawing over it.
|
<string name="screen_filter_body">Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nTry turning off the following apps when using Briar:\n\n%1$s</string>
|
||||||
If you experience any problems, try turning off these apps when using Briar.\n</string>
|
|
||||||
<string name="checkbox_dont_show_again">Don\'t warn me again for these apps</string>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
<item name="android:textColorLink">@color/briar_text_link</item>
|
<item name="android:textColorLink">@color/briar_text_link</item>
|
||||||
<item name="android:windowBackground">@color/window_background</item>
|
<item name="android:windowBackground">@color/window_background</item>
|
||||||
<item name="android:windowAnimationStyle">@style/ActivityAnimation</item>
|
<item name="android:windowAnimationStyle">@style/ActivityAnimation</item>
|
||||||
<item name="android:filterTouchesWhenObscured">true</item>
|
|
||||||
|
|
||||||
<!-- These fix a long-standing UI bug in the support preference library -->
|
<!-- These fix a long-standing UI bug in the support preference library -->
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
|||||||
@@ -61,25 +61,37 @@
|
|||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="pref_key_notify_private_messages"
|
android:key="pref_key_notify_private_messages"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/notify_private_messages_setting"/>
|
android:title="@string/notify_private_messages_setting_title"
|
||||||
|
android:summary="@string/notify_private_messages_setting_summary"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="pref_key_notify_group_messages"
|
android:key="pref_key_notify_group_messages"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/notify_group_messages_setting"/>
|
android:title="@string/notify_group_messages_setting_title"
|
||||||
|
android:summary="@string/notify_group_messages_setting_summary"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="pref_key_notify_forum_posts"
|
android:key="pref_key_notify_forum_posts"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/notify_forum_posts_setting"/>
|
android:title="@string/notify_forum_posts_setting_title"
|
||||||
|
android:summary="@string/notify_forum_posts_setting_summary"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="pref_key_notify_blog_posts"
|
android:key="pref_key_notify_blog_posts"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/notify_blog_posts_setting"/>
|
android:title="@string/notify_blog_posts_setting_title"
|
||||||
|
android:summary="@string/notify_blog_posts_setting_summary"/>
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="pref_key_notify_lock_screen"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/notify_lock_screen_setting_title"
|
||||||
|
android:summary="@string/notify_lock_screen_setting_summary"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ import static org.mockito.Mockito.verify;
|
|||||||
|
|
||||||
@RunWith(RobolectricGradleTestRunner.class)
|
@RunWith(RobolectricGradleTestRunner.class)
|
||||||
@Config(constants = BuildConfig.class, sdk = 21,
|
@Config(constants = BuildConfig.class, sdk = 21,
|
||||||
application = TestBriarApplication.class)
|
application = TestBriarApplication.class,
|
||||||
|
packageName = "org.briarproject.briar")
|
||||||
public class ForumActivityTest {
|
public class ForumActivityTest {
|
||||||
|
|
||||||
private final static String AUTHOR_1 = "Author 1";
|
private final static String AUTHOR_1 = "Author 1";
|
||||||
@@ -89,7 +90,7 @@ public class ForumActivityTest {
|
|||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.putExtra("briar.GROUP_ID", TestUtils.getRandomId());
|
intent.putExtra("briar.GROUP_ID", TestUtils.getRandomId());
|
||||||
forumActivity = Robolectric.buildActivity(TestForumActivity.class)
|
forumActivity = Robolectric.buildActivity(TestForumActivity.class)
|
||||||
.withIntent(intent).create().resume().get();
|
.withIntent(intent).create().start().resume().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ThreadItemList<ForumItem> getDummyData() {
|
private ThreadItemList<ForumItem> getDummyData() {
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
@RunWith(RobolectricGradleTestRunner.class)
|
@RunWith(RobolectricGradleTestRunner.class)
|
||||||
@Config(constants = BuildConfig.class, sdk = 21,
|
@Config(constants = BuildConfig.class, sdk = 21,
|
||||||
application = TestBriarApplication.class)
|
application = TestBriarApplication.class,
|
||||||
|
packageName = "org.briarproject.briar")
|
||||||
public class ChangePasswordActivityTest {
|
public class ChangePasswordActivityTest {
|
||||||
|
|
||||||
private static final int TIMEOUT_MS = 10 * 1000;
|
private static final int TIMEOUT_MS = 10 * 1000;
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ import static org.robolectric.Shadows.shadowOf;
|
|||||||
|
|
||||||
@RunWith(RobolectricGradleTestRunner.class)
|
@RunWith(RobolectricGradleTestRunner.class)
|
||||||
@Config(constants = BuildConfig.class, sdk = 21,
|
@Config(constants = BuildConfig.class, sdk = 21,
|
||||||
application = TestBriarApplication.class)
|
application = TestBriarApplication.class,
|
||||||
|
packageName = "org.briarproject.briar")
|
||||||
public class SetupActivityTest {
|
public class SetupActivityTest {
|
||||||
|
|
||||||
private static final int TIMEOUT_MS = 10 * 1000;
|
private static final int TIMEOUT_MS = 10 * 1000;
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ public interface BlogManager {
|
|||||||
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.blog");
|
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.blog");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a blog from the given author.
|
* Adds the given {@link Blog).}
|
||||||
*/
|
*/
|
||||||
Blog addBlog(Author author) throws DbException;
|
void addBlog(Blog b) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given {@link Blog} within the given {@link Transaction}.
|
* Adds the given {@link Blog} within the given {@link Transaction}.
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id 'java'
|
||||||
id "net.ltgt.apt" version "0.9"
|
id 'net.ltgt.apt' version '0.9'
|
||||||
id "idea"
|
id 'idea'
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = 1.6
|
sourceCompatibility = 1.6
|
||||||
targetCompatibility = 1.6
|
targetCompatibility = 1.6
|
||||||
|
|
||||||
@@ -10,11 +11,10 @@ apply plugin: 'witness'
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':briar-api')
|
compile project(':briar-api')
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
compile 'com.rometools:rome:1.7.3'
|
||||||
compile 'com.rometools:rome:1.7.0'
|
|
||||||
compile 'org.jdom:jdom2:2.0.6'
|
compile 'org.jdom:jdom2:2.0.6'
|
||||||
compile 'com.squareup.okhttp3:okhttp:3.3.1'
|
compile 'com.squareup.okhttp3:okhttp:3.8.0'
|
||||||
compile 'org.jsoup:jsoup:1.9.2'
|
compile 'org.jsoup:jsoup:1.10.3'
|
||||||
|
|
||||||
testCompile project(':bramble-core')
|
testCompile project(':bramble-core')
|
||||||
testCompile project(path: ':bramble-core', configuration: 'testOutput')
|
testCompile project(path: ':bramble-core', configuration: 'testOutput')
|
||||||
@@ -24,12 +24,11 @@ dependencies {
|
|||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.rometools:rome:3096b7a36c0e54f59b8193c431d28494c6bfa85c72ef3c5f341cdf09eae815e6',
|
'com.rometools:rome:077367bf8fa01b211c9da712c2aa862724195773c5693fd4d97d61d6457e96c6',
|
||||||
'org.jdom:jdom2:1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5',
|
'org.jdom:jdom2:1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5',
|
||||||
'com.squareup.okhttp3:okhttp:a47f4efa166551cd5acc04f1071d82dafbf05638c21f9ca13068bc6633e3bff6',
|
'com.squareup.okhttp3:okhttp:19e1db51787716ff0046fa19e408fb34ed32a6274baa0c07475bf724b4eb6800',
|
||||||
'com.rometools:rome-utils:2be18a1edc601c31fe49c2000bb5484dd75182309270c2a2561d71888d81587a',
|
'org.jsoup:jsoup:a0784e793d7f518eb1defb47b428da011cd483c5da32d49c569bf491e4f1579a',
|
||||||
'com.squareup.okio:okio:5cfea5afe6c6e441a4dbf6053a07a733b1249d1009382eb44ac2255ccedd0c15',
|
'org.slf4j:slf4j-api:e56288031f5e60652c06e7bb6e9fa410a61231ab54890f7b708fc6adc4107c5b',
|
||||||
'org.jsoup:jsoup:9c1885f1b182256e06f1e30b8451caed0c0dee96299d6348f968d18b54d0a46a',
|
'com.squareup.okio:okio:734269c3ebc5090e3b23566db558f421f0b4027277c79ad5d176b8ec168bb850',
|
||||||
'org.slf4j:slf4j-api:e56288031f5e60652c06e7bb6e9fa410a61231ab54890f7b708fc6adc4107c5b'
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
|
|
||||||
import static org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
|
import static org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
|
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
|
||||||
@@ -72,7 +70,7 @@ import static org.briarproject.briar.blog.BlogPostValidator.authorToBdfDictionar
|
|||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
||||||
AddContactHook, RemoveContactHook, Client {
|
RemoveContactHook, Client {
|
||||||
|
|
||||||
private final IdentityManager identityManager;
|
private final IdentityManager identityManager;
|
||||||
private final BlogFactory blogFactory;
|
private final BlogFactory blogFactory;
|
||||||
@@ -96,27 +94,14 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
// Create our personal blog if necessary
|
// Create our personal blog if necessary
|
||||||
LocalAuthor a = identityManager.getLocalAuthor(txn);
|
LocalAuthor a = identityManager.getLocalAuthor(txn);
|
||||||
Blog b = blogFactory.createBlog(a);
|
Blog b = blogFactory.createBlog(a);
|
||||||
db.addGroup(txn, b.getGroup());
|
db.addGroup(txn, b.getGroup()); // does nothing, if group exists
|
||||||
// Ensure that we have the personal blogs of all contacts
|
|
||||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
|
||||||
// Add the personal blog of the contact and share it with the contact
|
|
||||||
Blog b = blogFactory.createBlog(c.getAuthor());
|
|
||||||
addBlog(txn, b);
|
|
||||||
db.setGroupVisibility(txn, c.getId(), b.getId(), SHARED);
|
|
||||||
// Share our personal blog with the contact
|
|
||||||
LocalAuthor a = identityManager.getLocalAuthor(txn);
|
|
||||||
Blog b2 = blogFactory.createBlog(a);
|
|
||||||
db.setGroupVisibility(txn, c.getId(), b2.getId(), SHARED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removingContact(Transaction txn, Contact c) throws DbException {
|
public void removingContact(Transaction txn, Contact c) throws DbException {
|
||||||
Blog b = blogFactory.createBlog(c.getAuthor());
|
Blog b = blogFactory.createBlog(c.getAuthor());
|
||||||
removeBlog(txn, b);
|
// TODO we might want to reconsider removing b, if otherwise shared
|
||||||
|
if (db.containsGroup(txn, b.getId())) removeBlog(txn, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -168,9 +153,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Blog addBlog(Author author) throws DbException {
|
public void addBlog(Blog b) throws DbException {
|
||||||
Blog b = blogFactory.createBlog(author);
|
|
||||||
|
|
||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.addGroup(txn, b.getGroup());
|
db.addGroup(txn, b.getGroup());
|
||||||
@@ -178,7 +161,6 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ public class BlogModule {
|
|||||||
ValidationManager validationManager) {
|
ValidationManager validationManager) {
|
||||||
|
|
||||||
lifecycleManager.registerClient(blogManager);
|
lifecycleManager.registerClient(blogManager);
|
||||||
contactManager.registerAddContactHook(blogManager);
|
|
||||||
contactManager.registerRemoveContactHook(blogManager);
|
contactManager.registerRemoveContactHook(blogManager);
|
||||||
validationManager.registerIncomingMessageHook(CLIENT_ID, blogManager);
|
validationManager.registerIncomingMessageHook(CLIENT_ID, blogManager);
|
||||||
return blogManager;
|
return blogManager;
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ class BlogMessageParserImpl extends MessageParserImpl<Blog> {
|
|||||||
throws FormatException {
|
throws FormatException {
|
||||||
String name = descriptor.getString(0);
|
String name = descriptor.getString(0);
|
||||||
byte[] publicKey = descriptor.getRaw(1);
|
byte[] publicKey = descriptor.getRaw(1);
|
||||||
|
boolean rssFeed = descriptor.getBoolean(2);
|
||||||
Author author = authorFactory.createAuthor(name, publicKey);
|
Author author = authorFactory.createAuthor(name, publicKey);
|
||||||
return blogFactory.createBlog(author);
|
if (rssFeed) return blogFactory.createFeedBlog(author);
|
||||||
|
else return blogFactory.createBlog(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,15 +51,23 @@ class BlogSharingManagerImpl extends SharingManagerImpl<Blog>
|
|||||||
return CLIENT_ID;
|
return CLIENT_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called during each startup for each existing Contact.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||||
|
// creates a group to share with the contact
|
||||||
super.addingContact(txn, c);
|
super.addingContact(txn, c);
|
||||||
|
|
||||||
|
// get our blog and that of Contact c
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
||||||
Blog ourBlog = blogManager.getPersonalBlog(localAuthor);
|
Blog ourBlog = blogManager.getPersonalBlog(localAuthor);
|
||||||
Blog theirBlog = blogManager.getPersonalBlog(c.getAuthor());
|
Blog theirBlog = blogManager.getPersonalBlog(c.getAuthor());
|
||||||
|
|
||||||
|
// pre-share both blogs, if they have not been shared already
|
||||||
try {
|
try {
|
||||||
initializeSharedSession(txn, c, ourBlog);
|
preShareShareable(txn, c, ourBlog);
|
||||||
initializeSharedSession(txn, c, theirBlog);
|
preShareShareable(txn, c, theirBlog);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user